Loading src/or/connection.c +132 −62 Original line number Diff line number Diff line Loading @@ -56,6 +56,11 @@ #include <pwd.h> #endif #ifdef HAVE_SYS_UN_H #include <sys/socket.h> #include <sys/un.h> #endif static connection_t *connection_listener_new( const struct sockaddr *listensockaddr, socklen_t listensocklen, int type, Loading Loading @@ -1585,37 +1590,31 @@ connection_init_accepted_conn(connection_t *conn, return 0; } /** Take conn, make a nonblocking socket; try to connect to * addr:port (they arrive in *host order*). If fail, return -1 and if * applicable put your best guess about errno into *<b>socket_error</b>. * Else assign s to conn-\>s: if connected return 1, if EAGAIN return 0. * * address is used to make the logs useful. * * On success, add conn to the list of polled connections. */ int connection_connect(connection_t *conn, const char *address, const tor_addr_t *addr, uint16_t port, int *socket_error) static int connection_connect_sockaddr(connection_t *conn, const struct sockaddr *sa, socklen_t sa_len, const struct sockaddr *bindaddr, socklen_t bindaddr_len, int *socket_error) { tor_socket_t s; int inprogress = 0; struct sockaddr_storage addrbuf; struct sockaddr *dest_addr; int dest_addr_len; const or_options_t *options = get_options(); int protocol_family; tor_assert(conn); tor_assert(sa); tor_assert(socket_error); if (get_n_open_sockets() >= get_options()->ConnLimit_-1) { warn_too_many_conns(); *socket_error = SOCK_ERRNO(ENOBUFS); return -1; } if (tor_addr_family(addr) == AF_INET6) protocol_family = PF_INET6; else protocol_family = PF_INET; protocol_family = sa->sa_family; if (get_options()->DisableNetwork) { /* We should never even try to connect anyplace if DisableNetwork is set. Loading @@ -1628,7 +1627,7 @@ connection_connect(connection_t *conn, const char *address, return -1; } s = tor_open_socket_nonblocking(protocol_family,SOCK_STREAM,IPPROTO_TCP); s = tor_open_socket_nonblocking(protocol_family, SOCK_STREAM, 0); if (! SOCKET_OK(s)) { *socket_error = tor_socket_errno(-1); log_warn(LD_NET,"Error creating network socket: %s", Loading @@ -1641,59 +1640,26 @@ connection_connect(connection_t *conn, const char *address, tor_socket_strerror(errno)); } if (!tor_addr_is_loopback(addr)) { const tor_addr_t *ext_addr = NULL; if (protocol_family == AF_INET && !tor_addr_is_null(&options->OutboundBindAddressIPv4_)) ext_addr = &options->OutboundBindAddressIPv4_; else if (protocol_family == AF_INET6 && !tor_addr_is_null(&options->OutboundBindAddressIPv6_)) ext_addr = &options->OutboundBindAddressIPv6_; if (ext_addr) { struct sockaddr_storage ext_addr_sa; socklen_t ext_addr_len = 0; memset(&ext_addr_sa, 0, sizeof(ext_addr_sa)); ext_addr_len = tor_addr_to_sockaddr(ext_addr, 0, (struct sockaddr *) &ext_addr_sa, sizeof(ext_addr_sa)); if (ext_addr_len == 0) { log_warn(LD_NET, "Error converting OutboundBindAddress %s into sockaddr. " "Ignoring.", fmt_and_decorate_addr(ext_addr)); } else { if (bind(s, (struct sockaddr *) &ext_addr_sa, ext_addr_len) < 0) { if (bindaddr && bind(s, bindaddr, bindaddr_len) < 0) { *socket_error = tor_socket_errno(s); log_warn(LD_NET,"Error binding network socket to %s: %s", fmt_and_decorate_addr(ext_addr), log_warn(LD_NET,"Error binding network socket: %s", tor_socket_strerror(*socket_error)); tor_close_socket(s); return -1; } } } } tor_assert(options); if (options->ConstrainedSockets) set_constrained_socket_buffers(s, (int)options->ConstrainedSockSize); memset(&addrbuf,0,sizeof(addrbuf)); dest_addr = (struct sockaddr*) &addrbuf; dest_addr_len = tor_addr_to_sockaddr(addr, port, dest_addr, sizeof(addrbuf)); tor_assert(dest_addr_len > 0); log_debug(LD_NET, "Connecting to %s:%u.", escaped_safe_str_client(address), port); if (connect(s, dest_addr, (socklen_t)dest_addr_len) < 0) { if (connect(s, sa, sa_len) < 0) { int e = tor_socket_errno(s); if (!ERRNO_IS_CONN_EINPROGRESS(e)) { /* yuck. kill it. */ *socket_error = e; log_info(LD_NET, "connect() to %s:%u failed: %s", escaped_safe_str_client(address), port, tor_socket_strerror(e)); "connect() to socket failed: %s", tor_socket_strerror(e)); tor_close_socket(s); return -1; } else { Loading @@ -1703,9 +1669,8 @@ connection_connect(connection_t *conn, const char *address, /* it succeeded. we're connected. */ log_fn(inprogress ? LOG_DEBUG : LOG_INFO, LD_NET, "Connection to %s:%u %s (sock "TOR_SOCKET_T_FORMAT").", escaped_safe_str_client(address), port, inprogress?"in progress":"established", s); "Connection to socket %s (sock "TOR_SOCKET_T_FORMAT").", inprogress ? "in progress" : "established", s); conn->s = s; if (connection_add_connecting(conn) < 0) { /* no space, forget it */ Loading @@ -1713,7 +1678,112 @@ connection_connect(connection_t *conn, const char *address, return -1; } return inprogress ? 0 : 1; } /** Take conn, make a nonblocking socket; try to connect to * addr:port (they arrive in *host order*). If fail, return -1 and if * applicable put your best guess about errno into *<b>socket_error</b>. * Else assign s to conn-\>s: if connected return 1, if EAGAIN return 0. * * address is used to make the logs useful. * * On success, add conn to the list of polled connections. */ int connection_connect(connection_t *conn, const char *address, const tor_addr_t *addr, uint16_t port, int *socket_error) { struct sockaddr_storage addrbuf; struct sockaddr_storage bind_addr_ss; struct sockaddr *bind_addr = NULL; struct sockaddr *dest_addr; int dest_addr_len, bind_addr_len = 0; const or_options_t *options = get_options(); int protocol_family; if (tor_addr_family(addr) == AF_INET6) protocol_family = PF_INET6; else protocol_family = PF_INET; if (!tor_addr_is_loopback(addr)) { const tor_addr_t *ext_addr = NULL; if (protocol_family == AF_INET && !tor_addr_is_null(&options->OutboundBindAddressIPv4_)) ext_addr = &options->OutboundBindAddressIPv4_; else if (protocol_family == AF_INET6 && !tor_addr_is_null(&options->OutboundBindAddressIPv6_)) ext_addr = &options->OutboundBindAddressIPv6_; if (ext_addr) { socklen_t ext_addr_len = 0; memset(&bind_addr_ss, 0, sizeof(bind_addr_ss)); bind_addr_len = tor_addr_to_sockaddr(ext_addr, 0, (struct sockaddr *) &bind_addr_ss, sizeof(bind_addr_ss)); if (ext_addr_len == 0) { log_warn(LD_NET, "Error converting OutboundBindAddress %s into sockaddr. " "Ignoring.", fmt_and_decorate_addr(ext_addr)); } else { bind_addr = (struct sockaddr *)&bind_addr_ss; } } } memset(&addrbuf,0,sizeof(addrbuf)); dest_addr = (struct sockaddr*) &addrbuf; dest_addr_len = tor_addr_to_sockaddr(addr, port, dest_addr, sizeof(addrbuf)); tor_assert(dest_addr_len > 0); log_debug(LD_NET, "Connecting to %s:%u.", escaped_safe_str_client(address), port); return connection_connect_sockaddr(conn, dest_addr, dest_addr_len, bind_addr, bind_addr_len, socket_error); } #ifdef HAVE_SYS_UN_H /** Take conn, make a nonblocking socket; try to connect to * an AF_UNIX socket at socket_path. If fail, return -1 and if applicable * put your best guess about errno into *<b>socket_error</b>. Else assign s * to conn-\>s: if connected return 1, if EAGAIN return 0. * * On success, add conn to the list of polled connections. */ int connection_connect_unix(connection_t *conn, const char *socket_path, int *socket_error) { struct sockaddr_un dest_addr; tor_assert(socket_path); /* Check that we'll be able to fit it into dest_addr later */ if (strlen(socket_path) + 1 > sizeof(dest_addr.sun_path)) { log_warn(LD_NET, "Path %s is too long for an AF_UNIX socket\n", escaped_safe_str_client(socket_path)); *socket_error = SOCK_ERRNO(ENAMETOOLONG); return -1; } memset(&dest_addr, 0, sizeof(dest_addr)); dest_addr.sun_family = AF_UNIX; strlcpy(dest_addr.sun_path, socket_path, sizeof(dest_addr.sun_path)); log_debug(LD_NET, "Connecting to AF_UNIX socket at %s.", escaped_safe_str_client(socket_path)); return connection_connect_sockaddr(conn, (struct sockaddr *)&dest_addr, sizeof(dest_addr), NULL, 0, socket_error); } #endif /* defined(HAVE_SYS_UN_H) */ /** Convert state number to string representation for logging purposes. */ Loading src/or/connection.h +7 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,13 @@ int connection_connect(connection_t *conn, const char *address, const tor_addr_t *addr, uint16_t port, int *socket_error); #ifdef HAVE_SYS_UN_H int connection_connect_unix(connection_t *conn, const char *socket_path, int *socket_error); #endif /* defined(HAVE_SYS_UN_H) */ /** Maximum size of information that we can fit into SOCKS5 username or password fields. */ #define MAX_SOCKS5_AUTH_FIELD_SIZE 255 Loading src/or/connection_edge.c +29 −7 Original line number Diff line number Diff line Loading @@ -2940,7 +2940,7 @@ connection_exit_connect(edge_connection_t *edge_conn) const tor_addr_t *addr; uint16_t port; connection_t *conn = TO_CONN(edge_conn); int socket_error = 0; int socket_error = 0, result; if ( (!connection_edge_is_rendezvous_stream(edge_conn) && router_compare_to_my_exit_policy(&edge_conn->base_.addr, Loading @@ -2955,6 +2955,11 @@ connection_exit_connect(edge_connection_t *edge_conn) return; } #ifdef HAVE_SYS_UN_H if (conn->socket_family != AF_UNIX) { #else { #endif /* defined(HAVE_SYS_UN_H) */ addr = &conn->addr; port = conn->port; Loading @@ -2962,7 +2967,24 @@ connection_exit_connect(edge_connection_t *edge_conn) conn->socket_family = AF_INET6; log_debug(LD_EXIT, "about to try connecting"); switch (connection_connect(conn, conn->address, addr, port, &socket_error)) { result = connection_connect(conn, conn->address, addr, port, &socket_error); #ifdef HAVE_SYS_UN_H } else { /* * In the AF_UNIX case, we expect to have already had conn->port = 1, * tor_addr_make_unspec(conn->addr) (cf. the way we mark in the incoming * case in connection_handle_listener_read()), and conn->address should * have the socket path to connect to. */ tor_assert(conn->address && strlen(conn->address) > 0); log_debug(LD_EXIT, "about to try connecting"); result = connection_connect_unix(conn, conn->address, &socket_error); #endif /* defined(HAVE_SYS_UN_H) */ } switch (result) { case -1: { int reason = errno_to_stream_end_reason(socket_error); connection_edge_end(edge_conn, reason); Loading Loading
src/or/connection.c +132 −62 Original line number Diff line number Diff line Loading @@ -56,6 +56,11 @@ #include <pwd.h> #endif #ifdef HAVE_SYS_UN_H #include <sys/socket.h> #include <sys/un.h> #endif static connection_t *connection_listener_new( const struct sockaddr *listensockaddr, socklen_t listensocklen, int type, Loading Loading @@ -1585,37 +1590,31 @@ connection_init_accepted_conn(connection_t *conn, return 0; } /** Take conn, make a nonblocking socket; try to connect to * addr:port (they arrive in *host order*). If fail, return -1 and if * applicable put your best guess about errno into *<b>socket_error</b>. * Else assign s to conn-\>s: if connected return 1, if EAGAIN return 0. * * address is used to make the logs useful. * * On success, add conn to the list of polled connections. */ int connection_connect(connection_t *conn, const char *address, const tor_addr_t *addr, uint16_t port, int *socket_error) static int connection_connect_sockaddr(connection_t *conn, const struct sockaddr *sa, socklen_t sa_len, const struct sockaddr *bindaddr, socklen_t bindaddr_len, int *socket_error) { tor_socket_t s; int inprogress = 0; struct sockaddr_storage addrbuf; struct sockaddr *dest_addr; int dest_addr_len; const or_options_t *options = get_options(); int protocol_family; tor_assert(conn); tor_assert(sa); tor_assert(socket_error); if (get_n_open_sockets() >= get_options()->ConnLimit_-1) { warn_too_many_conns(); *socket_error = SOCK_ERRNO(ENOBUFS); return -1; } if (tor_addr_family(addr) == AF_INET6) protocol_family = PF_INET6; else protocol_family = PF_INET; protocol_family = sa->sa_family; if (get_options()->DisableNetwork) { /* We should never even try to connect anyplace if DisableNetwork is set. Loading @@ -1628,7 +1627,7 @@ connection_connect(connection_t *conn, const char *address, return -1; } s = tor_open_socket_nonblocking(protocol_family,SOCK_STREAM,IPPROTO_TCP); s = tor_open_socket_nonblocking(protocol_family, SOCK_STREAM, 0); if (! SOCKET_OK(s)) { *socket_error = tor_socket_errno(-1); log_warn(LD_NET,"Error creating network socket: %s", Loading @@ -1641,59 +1640,26 @@ connection_connect(connection_t *conn, const char *address, tor_socket_strerror(errno)); } if (!tor_addr_is_loopback(addr)) { const tor_addr_t *ext_addr = NULL; if (protocol_family == AF_INET && !tor_addr_is_null(&options->OutboundBindAddressIPv4_)) ext_addr = &options->OutboundBindAddressIPv4_; else if (protocol_family == AF_INET6 && !tor_addr_is_null(&options->OutboundBindAddressIPv6_)) ext_addr = &options->OutboundBindAddressIPv6_; if (ext_addr) { struct sockaddr_storage ext_addr_sa; socklen_t ext_addr_len = 0; memset(&ext_addr_sa, 0, sizeof(ext_addr_sa)); ext_addr_len = tor_addr_to_sockaddr(ext_addr, 0, (struct sockaddr *) &ext_addr_sa, sizeof(ext_addr_sa)); if (ext_addr_len == 0) { log_warn(LD_NET, "Error converting OutboundBindAddress %s into sockaddr. " "Ignoring.", fmt_and_decorate_addr(ext_addr)); } else { if (bind(s, (struct sockaddr *) &ext_addr_sa, ext_addr_len) < 0) { if (bindaddr && bind(s, bindaddr, bindaddr_len) < 0) { *socket_error = tor_socket_errno(s); log_warn(LD_NET,"Error binding network socket to %s: %s", fmt_and_decorate_addr(ext_addr), log_warn(LD_NET,"Error binding network socket: %s", tor_socket_strerror(*socket_error)); tor_close_socket(s); return -1; } } } } tor_assert(options); if (options->ConstrainedSockets) set_constrained_socket_buffers(s, (int)options->ConstrainedSockSize); memset(&addrbuf,0,sizeof(addrbuf)); dest_addr = (struct sockaddr*) &addrbuf; dest_addr_len = tor_addr_to_sockaddr(addr, port, dest_addr, sizeof(addrbuf)); tor_assert(dest_addr_len > 0); log_debug(LD_NET, "Connecting to %s:%u.", escaped_safe_str_client(address), port); if (connect(s, dest_addr, (socklen_t)dest_addr_len) < 0) { if (connect(s, sa, sa_len) < 0) { int e = tor_socket_errno(s); if (!ERRNO_IS_CONN_EINPROGRESS(e)) { /* yuck. kill it. */ *socket_error = e; log_info(LD_NET, "connect() to %s:%u failed: %s", escaped_safe_str_client(address), port, tor_socket_strerror(e)); "connect() to socket failed: %s", tor_socket_strerror(e)); tor_close_socket(s); return -1; } else { Loading @@ -1703,9 +1669,8 @@ connection_connect(connection_t *conn, const char *address, /* it succeeded. we're connected. */ log_fn(inprogress ? LOG_DEBUG : LOG_INFO, LD_NET, "Connection to %s:%u %s (sock "TOR_SOCKET_T_FORMAT").", escaped_safe_str_client(address), port, inprogress?"in progress":"established", s); "Connection to socket %s (sock "TOR_SOCKET_T_FORMAT").", inprogress ? "in progress" : "established", s); conn->s = s; if (connection_add_connecting(conn) < 0) { /* no space, forget it */ Loading @@ -1713,7 +1678,112 @@ connection_connect(connection_t *conn, const char *address, return -1; } return inprogress ? 0 : 1; } /** Take conn, make a nonblocking socket; try to connect to * addr:port (they arrive in *host order*). If fail, return -1 and if * applicable put your best guess about errno into *<b>socket_error</b>. * Else assign s to conn-\>s: if connected return 1, if EAGAIN return 0. * * address is used to make the logs useful. * * On success, add conn to the list of polled connections. */ int connection_connect(connection_t *conn, const char *address, const tor_addr_t *addr, uint16_t port, int *socket_error) { struct sockaddr_storage addrbuf; struct sockaddr_storage bind_addr_ss; struct sockaddr *bind_addr = NULL; struct sockaddr *dest_addr; int dest_addr_len, bind_addr_len = 0; const or_options_t *options = get_options(); int protocol_family; if (tor_addr_family(addr) == AF_INET6) protocol_family = PF_INET6; else protocol_family = PF_INET; if (!tor_addr_is_loopback(addr)) { const tor_addr_t *ext_addr = NULL; if (protocol_family == AF_INET && !tor_addr_is_null(&options->OutboundBindAddressIPv4_)) ext_addr = &options->OutboundBindAddressIPv4_; else if (protocol_family == AF_INET6 && !tor_addr_is_null(&options->OutboundBindAddressIPv6_)) ext_addr = &options->OutboundBindAddressIPv6_; if (ext_addr) { socklen_t ext_addr_len = 0; memset(&bind_addr_ss, 0, sizeof(bind_addr_ss)); bind_addr_len = tor_addr_to_sockaddr(ext_addr, 0, (struct sockaddr *) &bind_addr_ss, sizeof(bind_addr_ss)); if (ext_addr_len == 0) { log_warn(LD_NET, "Error converting OutboundBindAddress %s into sockaddr. " "Ignoring.", fmt_and_decorate_addr(ext_addr)); } else { bind_addr = (struct sockaddr *)&bind_addr_ss; } } } memset(&addrbuf,0,sizeof(addrbuf)); dest_addr = (struct sockaddr*) &addrbuf; dest_addr_len = tor_addr_to_sockaddr(addr, port, dest_addr, sizeof(addrbuf)); tor_assert(dest_addr_len > 0); log_debug(LD_NET, "Connecting to %s:%u.", escaped_safe_str_client(address), port); return connection_connect_sockaddr(conn, dest_addr, dest_addr_len, bind_addr, bind_addr_len, socket_error); } #ifdef HAVE_SYS_UN_H /** Take conn, make a nonblocking socket; try to connect to * an AF_UNIX socket at socket_path. If fail, return -1 and if applicable * put your best guess about errno into *<b>socket_error</b>. Else assign s * to conn-\>s: if connected return 1, if EAGAIN return 0. * * On success, add conn to the list of polled connections. */ int connection_connect_unix(connection_t *conn, const char *socket_path, int *socket_error) { struct sockaddr_un dest_addr; tor_assert(socket_path); /* Check that we'll be able to fit it into dest_addr later */ if (strlen(socket_path) + 1 > sizeof(dest_addr.sun_path)) { log_warn(LD_NET, "Path %s is too long for an AF_UNIX socket\n", escaped_safe_str_client(socket_path)); *socket_error = SOCK_ERRNO(ENAMETOOLONG); return -1; } memset(&dest_addr, 0, sizeof(dest_addr)); dest_addr.sun_family = AF_UNIX; strlcpy(dest_addr.sun_path, socket_path, sizeof(dest_addr.sun_path)); log_debug(LD_NET, "Connecting to AF_UNIX socket at %s.", escaped_safe_str_client(socket_path)); return connection_connect_sockaddr(conn, (struct sockaddr *)&dest_addr, sizeof(dest_addr), NULL, 0, socket_error); } #endif /* defined(HAVE_SYS_UN_H) */ /** Convert state number to string representation for logging purposes. */ Loading
src/or/connection.h +7 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,13 @@ int connection_connect(connection_t *conn, const char *address, const tor_addr_t *addr, uint16_t port, int *socket_error); #ifdef HAVE_SYS_UN_H int connection_connect_unix(connection_t *conn, const char *socket_path, int *socket_error); #endif /* defined(HAVE_SYS_UN_H) */ /** Maximum size of information that we can fit into SOCKS5 username or password fields. */ #define MAX_SOCKS5_AUTH_FIELD_SIZE 255 Loading
src/or/connection_edge.c +29 −7 Original line number Diff line number Diff line Loading @@ -2940,7 +2940,7 @@ connection_exit_connect(edge_connection_t *edge_conn) const tor_addr_t *addr; uint16_t port; connection_t *conn = TO_CONN(edge_conn); int socket_error = 0; int socket_error = 0, result; if ( (!connection_edge_is_rendezvous_stream(edge_conn) && router_compare_to_my_exit_policy(&edge_conn->base_.addr, Loading @@ -2955,6 +2955,11 @@ connection_exit_connect(edge_connection_t *edge_conn) return; } #ifdef HAVE_SYS_UN_H if (conn->socket_family != AF_UNIX) { #else { #endif /* defined(HAVE_SYS_UN_H) */ addr = &conn->addr; port = conn->port; Loading @@ -2962,7 +2967,24 @@ connection_exit_connect(edge_connection_t *edge_conn) conn->socket_family = AF_INET6; log_debug(LD_EXIT, "about to try connecting"); switch (connection_connect(conn, conn->address, addr, port, &socket_error)) { result = connection_connect(conn, conn->address, addr, port, &socket_error); #ifdef HAVE_SYS_UN_H } else { /* * In the AF_UNIX case, we expect to have already had conn->port = 1, * tor_addr_make_unspec(conn->addr) (cf. the way we mark in the incoming * case in connection_handle_listener_read()), and conn->address should * have the socket path to connect to. */ tor_assert(conn->address && strlen(conn->address) > 0); log_debug(LD_EXIT, "about to try connecting"); result = connection_connect_unix(conn, conn->address, &socket_error); #endif /* defined(HAVE_SYS_UN_H) */ } switch (result) { case -1: { int reason = errno_to_stream_end_reason(socket_error); connection_edge_end(edge_conn, reason); Loading