r13266@catbus: nickm | 2007-06-05 16:38:08 -0400

Patch from peter palfrader: control interface via unix domain socket


svn:r10504
This commit is contained in:
Nick Mathewson 2007-06-05 20:54:49 +00:00
parent f0345d46f6
commit 210beff55a
10 changed files with 348 additions and 130 deletions

View File

@ -6,6 +6,11 @@ Changes in version 0.2.0.3-alpha - 2007-??-??
- tor-gencert creates all files as readable to the file creator only, and - tor-gencert creates all files as readable to the file creator only, and
write-protects the authority identity key. write-protects the authority identity key.
o Minor feature (controller):
- You can now use the ControlSocket option to tell Tor to listen for
controller connections on Unix domain sockets on systems that support
them. (Patch from Peter Palfrader.)
o Minor bugfixes (dns): o Minor bugfixes (dns):
- Fix a crash when DNSPort is set more than once. (Patch from Robert - Fix a crash when DNSPort is set more than once. (Patch from Robert
Hogan.) Hogan.)

View File

@ -240,7 +240,7 @@ AC_SYS_LARGEFILE
AC_CHECK_HEADERS(unistd.h string.h signal.h ctype.h sys/stat.h sys/types.h fcntl.h sys/fcntl.h sys/time.h errno.h assert.h time.h, , AC_MSG_WARN(Some headers were not found, compilation may fail. If compilation succeeds, please send your orconfig.h to the developers so we can fix this warning.)) AC_CHECK_HEADERS(unistd.h string.h signal.h ctype.h sys/stat.h sys/types.h fcntl.h sys/fcntl.h sys/time.h errno.h assert.h time.h, , AC_MSG_WARN(Some headers were not found, compilation may fail. If compilation succeeds, please send your orconfig.h to the developers so we can fix this warning.))
AC_CHECK_HEADERS(netdb.h sys/ioctl.h sys/socket.h arpa/inet.h netinet/in.h pwd.h grp.h) AC_CHECK_HEADERS(netdb.h sys/ioctl.h sys/socket.h arpa/inet.h netinet/in.h pwd.h grp.h sys/un.h)
dnl These headers are not essential dnl These headers are not essential

View File

@ -149,6 +149,7 @@ static config_var_t _option_vars[] = {
VAR("ContactInfo", STRING, ContactInfo, NULL), VAR("ContactInfo", STRING, ContactInfo, NULL),
VAR("ControlListenAddress",LINELIST, ControlListenAddress, NULL), VAR("ControlListenAddress",LINELIST, ControlListenAddress, NULL),
VAR("ControlPort", UINT, ControlPort, "0"), VAR("ControlPort", UINT, ControlPort, "0"),
VAR("ControlSocket", LINELIST, ControlSocket, NULL),
VAR("CookieAuthentication",BOOL, CookieAuthentication, "0"), VAR("CookieAuthentication",BOOL, CookieAuthentication, "0"),
VAR("DataDirectory", STRING, DataDirectory, NULL), VAR("DataDirectory", STRING, DataDirectory, NULL),
OBSOLETE("DebugLogFile"), OBSOLETE("DebugLogFile"),
@ -811,6 +812,14 @@ options_act_reversible(or_options_t *old_options, char **msg)
start_daemon(); start_daemon();
} }
#ifndef HAVE_SYS_UN_H
if (options->ControlSocket) {
*msg = tor_strdup("Unix domain sockets (ControlSocket) not supported"
" on this OS/with this build.");
goto rollback;
}
#endif
if (running_tor) { if (running_tor) {
/* We need to set the connection limit before we can open the listeners. */ /* We need to set the connection limit before we can open the listeners. */
options->_ConnLimit = options->_ConnLimit =

View File

@ -14,8 +14,9 @@ const char connection_c_id[] =
#include "or.h" #include "or.h"
static connection_t *connection_create_listener(const char *listenaddress, static connection_t *connection_create_listener(
uint16_t listenport, int type); struct sockaddr *listensockaddr, int type,
char* address);
static int connection_init_accepted_conn(connection_t *conn, static int connection_init_accepted_conn(connection_t *conn,
uint8_t listener_type); uint8_t listener_type);
static int connection_handle_listener_read(connection_t *conn, int new_type); static int connection_handle_listener_read(connection_t *conn, int new_type);
@ -156,7 +157,7 @@ conn_state_to_string(int type, int state)
* Initialize conn's timestamps to now. * Initialize conn's timestamps to now.
*/ */
connection_t * connection_t *
connection_new(int type) connection_new(int type, int sa_family)
{ {
static uint32_t n_connections_allocated = 1; static uint32_t n_connections_allocated = 1;
connection_t *conn; connection_t *conn;
@ -194,6 +195,7 @@ connection_new(int type)
conn->conn_array_index = -1; /* also default to 'not used' */ conn->conn_array_index = -1; /* also default to 'not used' */
conn->type = type; conn->type = type;
conn->sa_family = sa_family;
if (!connection_is_listener(conn)) { /* listeners never use their buf */ if (!connection_is_listener(conn)) { /* listeners never use their buf */
conn->inbuf = buf_new(); conn->inbuf = buf_new();
conn->outbuf = buf_new(); conn->outbuf = buf_new();
@ -293,6 +295,17 @@ _connection_free(connection_t *conn)
if (!connection_is_listener(conn)) { if (!connection_is_listener(conn)) {
buf_free(conn->inbuf); buf_free(conn->inbuf);
buf_free(conn->outbuf); buf_free(conn->outbuf);
} else {
if (conn->sa_family == AF_UNIX) {
/* For now only control ports can be unix domain sockets
* and listeners at the same time */
tor_assert(conn->type == CONN_TYPE_CONTROL_LISTENER);
if (unlink(conn->address) < 0 && errno != ENOENT) {
log_warn(LD_NET, "Could not unlink %s: %s", conn->address,
strerror(errno));
}
}
} }
tor_free(conn->address); tor_free(conn->address);
@ -621,43 +634,96 @@ connection_expire_held_open(void)
}); });
} }
/** Bind a new non-blocking socket listening to /** Create an AF_INET listenaddr struct.
* <b>listenaddress</b>:<b>listenport</b>, and add this new connection * <b>listenaddress</b> provides the host and optionally the port information
* (of type <b>type</b>) to the connection array. * for the new structure. If no port is provided in <b>listenaddress</b> then
* <b>listenport</b> is used.
* *
* If <b>listenaddress</b> includes a port, we bind on that port; * If not NULL <b>readable_addrress</b> will contain a copy of the host part of
* otherwise, we use listenport. * <b>listenaddress</b>.
*
* The listenaddr struct has to be freed by the caller.
*/ */
static connection_t * static struct sockaddr_in *
connection_create_listener(const char *listenaddress, uint16_t listenport, create_inet_sockaddr(const char *listenaddress, uint16_t listenport,
int type) char **readable_address) {
{ struct sockaddr_in *listenaddr = NULL;
struct sockaddr_in listenaddr; /* where to bind */
char *address = NULL;
connection_t *conn;
uint16_t usePort;
uint32_t addr; uint32_t addr;
int s; /* the socket we're going to make */ uint16_t usePort = 0;
#ifndef MS_WINDOWS
int one=1;
#endif
int is_tcp = (type != CONN_TYPE_AP_DNS_LISTENER);
memset(&listenaddr,0,sizeof(struct sockaddr_in)); if (parse_addr_port(LOG_WARN,
if (parse_addr_port(LOG_WARN, listenaddress, &address, &addr, &usePort)<0) { listenaddress, readable_address, &addr, &usePort)<0) {
log_warn(LD_CONFIG, log_warn(LD_CONFIG,
"Error parsing/resolving ListenAddress %s", listenaddress); "Error parsing/resolving ListenAddress %s", listenaddress);
return NULL; goto err;
} }
if (usePort==0) if (usePort==0)
usePort = listenport; usePort = listenport;
listenaddr.sin_addr.s_addr = htonl(addr);
listenaddr.sin_family = AF_INET;
listenaddr.sin_port = htons((uint16_t) usePort);
log_notice(LD_NET, "Opening %s on %s:%d", listenaddr = tor_malloc_zero(sizeof(struct sockaddr_in));
conn_type_to_string(type), address, usePort); listenaddr->sin_addr.s_addr = htonl(addr);
listenaddr->sin_family = AF_INET;
listenaddr->sin_port = htons((uint16_t) usePort);
return listenaddr;
err:
tor_free(listenaddr);
return NULL;
}
#ifdef HAVE_SYS_UN_H
/** Create an AF_UNIX listenaddr struct.
* <b>listenaddress</b> provides the path to the unix socket.
*
* Eventually <b>listenaddress</b> will also optionally contain user, group,
* and file permissions for the new socket. But not yet. XXX
* Also, since we do not create the socket here the information doesn't help
* here.
*
* If not NULL <b>readable_addrress</b> will contain a copy of the path part of
* <b>listenaddress</b>.
*
* The listenaddr struct has to be freed by the caller.
*/
static struct sockaddr_un *
create_unix_sockaddr(const char *listenaddress, char **readable_address)
{
struct sockaddr_un *sockaddr = NULL;
sockaddr = tor_malloc_zero(sizeof(struct sockaddr_un));
sockaddr->sun_family = AF_UNIX;
strncpy(sockaddr->sun_path, listenaddress, sizeof(sockaddr->sun_path));
if (readable_address)
*readable_address = tor_strdup(listenaddress);
return sockaddr;
}
#else
static struct sockaddr *
create_unix_sockaddr(const char *listenaddress, char **readable_address)
{
log_fn(LOG_ERR, LD_BUG,
"Unix domain sockets not supported, yet we tried to create one.");
assert(0);
};
#endif /* HAVE_SYS_UN_H */
/** Bind a new non-blocking socket listening to the socket described
* by <b>listensockaddr</b>.
*
* <b>address</b> is only used for logging purposes and to add the information
* to the conn.
*/
static connection_t *
connection_create_listener(struct sockaddr *listensockaddr, int type,
char* address)
{
connection_t *conn;
int s; /* the socket we're going to make */
uint16_t usePort = 0;
int start_reading = 0;
if (get_n_open_sockets() >= get_options()->_ConnLimit-1) { if (get_n_open_sockets() >= get_options()->_ConnLimit-1) {
int n_conns = get_n_open_sockets(); int n_conns = get_n_open_sockets();
@ -668,48 +734,105 @@ connection_create_listener(const char *listenaddress, uint16_t listenport,
return NULL; return NULL;
} }
s = tor_open_socket(PF_INET, if (listensockaddr->sa_family == AF_INET) {
is_tcp ? SOCK_STREAM : SOCK_DGRAM, int is_tcp = (type != CONN_TYPE_AP_DNS_LISTENER);
is_tcp ? IPPROTO_TCP: IPPROTO_UDP); #ifndef MS_WINDOWS
if (s < 0) { int one=1;
log_warn(LD_NET,"Socket creation failed."); #endif
goto err; if (is_tcp)
} start_reading = 1;
usePort = ntohs( (uint16_t)
((struct sockaddr_in *)listensockaddr)->sin_port);
log_notice(LD_NET, "Opening %s on %s:%d",
conn_type_to_string(type), address, usePort);
s = tor_open_socket(PF_INET,
is_tcp ? SOCK_STREAM : SOCK_DGRAM,
is_tcp ? IPPROTO_TCP: IPPROTO_UDP);
if (s < 0) {
log_warn(LD_NET,"Socket creation failed.");
goto err;
}
#ifndef MS_WINDOWS #ifndef MS_WINDOWS
/* REUSEADDR on normal places means you can rebind to the port /* REUSEADDR on normal places means you can rebind to the port
* right after somebody else has let it go. But REUSEADDR on win32 * right after somebody else has let it go. But REUSEADDR on win32
* means you can bind to the port _even when somebody else * means you can bind to the port _even when somebody else
* already has it bound_. So, don't do that on Win32. */ * already has it bound_. So, don't do that on Win32. */
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*) &one, sizeof(one)); setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*) &one, sizeof(one));
#endif #endif
if (bind(s,(struct sockaddr *)&listenaddr,sizeof(listenaddr)) < 0) { if (bind(s,listensockaddr,sizeof(struct sockaddr_in)) < 0) {
const char *helpfulhint = ""; const char *helpfulhint = "";
int e = tor_socket_errno(s); int e = tor_socket_errno(s);
if (ERRNO_IS_EADDRINUSE(e)) if (ERRNO_IS_EADDRINUSE(e))
helpfulhint = ". Is Tor already running?"; helpfulhint = ". Is Tor already running?";
log_warn(LD_NET, "Could not bind to %s:%u: %s%s", address, usePort, log_warn(LD_NET, "Could not bind to %s:%u: %s%s", address, usePort,
tor_socket_strerror(e), helpfulhint); tor_socket_strerror(e), helpfulhint);
tor_close_socket(s); tor_close_socket(s);
goto err; goto err;
} }
if (is_tcp) {
if (listen(s,SOMAXCONN) < 0) {
log_warn(LD_NET, "Could not listen on %s:%u: %s", address, usePort,
tor_socket_strerror(tor_socket_errno(s)));
tor_close_socket(s);
goto err;
}
}
#ifdef HAVE_SYS_UN_H
} else if (listensockaddr->sa_family == AF_UNIX) {
int len;
start_reading = 1;
/* For now only control ports can be unix domain sockets
* and listeners at the same time */
tor_assert(type == CONN_TYPE_CONTROL_LISTENER);
log_notice(LD_NET, "Opening %s on %s",
conn_type_to_string(type), address);
if (unlink(address) < 0 && errno != ENOENT) {
log_warn(LD_NET, "Could not unlink %s: %s", address,
strerror(errno));
goto err;
}
s = tor_open_socket(AF_UNIX, SOCK_STREAM, 0);
if (s < 0) {
log_warn(LD_NET,"Socket creation failed: %s.", strerror(errno));
goto err;
}
len = strlen(((struct sockaddr_un *)listensockaddr)->sun_path) +
sizeof(((struct sockaddr_un *)listensockaddr)->sun_family);
if (bind(s, listensockaddr, len) == -1) {
log_warn(LD_NET,"Bind to %s failed: %s.", address,
tor_socket_strerror(tor_socket_errno(s)));
goto err;
}
if (is_tcp) {
if (listen(s,SOMAXCONN) < 0) { if (listen(s,SOMAXCONN) < 0) {
log_warn(LD_NET, "Could not listen on %s:%u: %s", address, usePort, log_warn(LD_NET, "Could not listen on %s: %s", address,
tor_socket_strerror(tor_socket_errno(s))); tor_socket_strerror(tor_socket_errno(s)));
tor_close_socket(s); tor_close_socket(s);
goto err; goto err;
} }
#endif /* HAVE_SYS_UN_H */
} else {
log_err(LD_BUG,"Got unexpected address family %d.",
listensockaddr->sa_family);
tor_assert(0);
} }
set_socket_nonblocking(s); set_socket_nonblocking(s);
conn = connection_new(type); conn = connection_new(type, listensockaddr->sa_family);
conn->sa_family = listensockaddr->sa_family;
conn->s = s; conn->s = s;
conn->address = address; conn->address = tor_strdup(address);
address = NULL;
conn->port = usePort; conn->port = usePort;
if (connection_add(conn) < 0) { /* no space, forget it */ if (connection_add(conn) < 0) { /* no space, forget it */
@ -722,7 +845,7 @@ connection_create_listener(const char *listenaddress, uint16_t listenport,
conn_type_to_string(type), usePort); conn_type_to_string(type), usePort);
conn->state = LISTENER_STATE_READY; conn->state = LISTENER_STATE_READY;
if (is_tcp) { if (start_reading) {
connection_start_reading(conn); connection_start_reading(conn);
} else { } else {
tor_assert(type == CONN_TYPE_AP_DNS_LISTENER); tor_assert(type == CONN_TYPE_AP_DNS_LISTENER);
@ -732,7 +855,6 @@ connection_create_listener(const char *listenaddress, uint16_t listenport,
return conn; return conn;
err: err:
tor_free(address);
return NULL; return NULL;
} }
@ -801,55 +923,75 @@ connection_handle_listener_read(connection_t *conn, int new_type)
set_socket_nonblocking(news); set_socket_nonblocking(news);
if (check_sockaddr_in((struct sockaddr*)addrbuf, remotelen, LOG_INFO)<0) { tor_assert(((struct sockaddr*)addrbuf)->sa_family == conn->sa_family);
log_info(LD_NET,
"accept() returned a strange address; trying getsockname()."); if (conn->sa_family == AF_INET) {
remotelen=256; if (check_sockaddr_in((struct sockaddr*)addrbuf, remotelen, LOG_INFO)<0) {
memset(addrbuf, 0, sizeof(addrbuf)); log_info(LD_NET,
if (getsockname(news, (struct sockaddr*)addrbuf, &remotelen)<0) { "accept() returned a strange address; trying getsockname().");
int e = tor_socket_errno(news); remotelen=256;
log_warn(LD_NET, "getsockname() for new connection failed: %s", memset(addrbuf, 0, sizeof(addrbuf));
tor_socket_strerror(e)); if (getsockname(news, (struct sockaddr*)addrbuf, &remotelen)<0) {
} else { int e = tor_socket_errno(news);
if (check_sockaddr_in((struct sockaddr*)addrbuf, remotelen, log_warn(LD_NET, "getsockname() for new connection failed: %s",
LOG_WARN) < 0) { tor_socket_strerror(e));
log_warn(LD_NET,"Something's wrong with this conn. Closing it."); } else {
if (check_sockaddr_in((struct sockaddr*)addrbuf, remotelen,
LOG_WARN) < 0) {
log_warn(LD_NET,"Something's wrong with this conn. Closing it.");
tor_close_socket(news);
return 0;
}
}
}
memcpy(&remote, addrbuf, sizeof(struct sockaddr_in));
/* process entrance policies here, before we even create the connection */
if (new_type == CONN_TYPE_AP) {
/* check sockspolicy to see if we should accept it */
if (socks_policy_permits_address(ntohl(remote.sin_addr.s_addr)) == 0) {
tor_inet_ntoa(&remote.sin_addr, tmpbuf, sizeof(tmpbuf));
log_notice(LD_APP,
"Denying socks connection from untrusted address %s.",
tmpbuf);
tor_close_socket(news); tor_close_socket(news);
return 0; return 0;
} }
} }
} if (new_type == CONN_TYPE_DIR) {
memcpy(&remote, addrbuf, sizeof(struct sockaddr_in)); /* check dirpolicy to see if we should accept it */
if (dir_policy_permits_address(ntohl(remote.sin_addr.s_addr)) == 0) {
/* process entrance policies here, before we even create the connection */ tor_inet_ntoa(&remote.sin_addr, tmpbuf, sizeof(tmpbuf));
if (new_type == CONN_TYPE_AP) { log_notice(LD_DIRSERV,"Denying dir connection from address %s.",
/* check sockspolicy to see if we should accept it */ tmpbuf);
if (socks_policy_permits_address(ntohl(remote.sin_addr.s_addr)) == 0) { tor_close_socket(news);
tor_inet_ntoa(&remote.sin_addr, tmpbuf, sizeof(tmpbuf)); return 0;
log_notice(LD_APP,"Denying socks connection from untrusted address %s.", }
tmpbuf);
tor_close_socket(news);
return 0;
} }
}
if (new_type == CONN_TYPE_DIR) {
/* check dirpolicy to see if we should accept it */
if (dir_policy_permits_address(ntohl(remote.sin_addr.s_addr)) == 0) {
tor_inet_ntoa(&remote.sin_addr, tmpbuf, sizeof(tmpbuf));
log_notice(LD_DIRSERV,"Denying dir connection from address %s.",
tmpbuf);
tor_close_socket(news);
return 0;
}
}
newconn = connection_new(new_type); newconn = connection_new(new_type, conn->sa_family);
newconn->s = news; newconn->s = news;
/* remember the remote address */ /* remember the remote address */
newconn->addr = ntohl(remote.sin_addr.s_addr); newconn->addr = ntohl(remote.sin_addr.s_addr);
newconn->port = ntohs(remote.sin_port); newconn->port = ntohs(remote.sin_port);
newconn->address = tor_dup_addr(newconn->addr); newconn->address = tor_dup_addr(newconn->addr);
} else if (conn->sa_family == AF_UNIX) {
/* For now only control ports can be unix domain sockets
* and listeners at the same time */
tor_assert(conn->type == CONN_TYPE_CONTROL_LISTENER);
newconn = connection_new(new_type, conn->sa_family);
newconn->s = news;
/* remember the remote address -- do we have anything sane to put here? */
newconn->addr = 0;
newconn->port = 1;
newconn->address = tor_strdup(conn->address);
} else {
tor_assert(0);
};
if (connection_add(newconn) < 0) { /* no space, forget it */ if (connection_add(newconn) < 0) { /* no space, forget it */
connection_free(newconn); connection_free(newconn);
@ -1007,7 +1149,8 @@ retry_listeners(int type, config_line_t *cfg,
int port_option, const char *default_addr, int port_option, const char *default_addr,
smartlist_t *replaced_conns, smartlist_t *replaced_conns,
smartlist_t *new_conns, smartlist_t *new_conns,
int never_open_conns) int never_open_conns,
int sa_family)
{ {
smartlist_t *launch = smartlist_create(), *conns; smartlist_t *launch = smartlist_create(), *conns;
int free_launch_elts = 1; int free_launch_elts = 1;
@ -1016,6 +1159,8 @@ retry_listeners(int type, config_line_t *cfg,
connection_t *conn; connection_t *conn;
config_line_t *line; config_line_t *line;
tor_assert(sa_family == AF_INET || sa_family == AF_UNIX);
if (cfg && port_option) { if (cfg && port_option) {
for (c = cfg; c; c = c->next) { for (c = cfg; c; c = c->next) {
smartlist_add(launch, c); smartlist_add(launch, c);
@ -1036,7 +1181,9 @@ retry_listeners(int type, config_line_t *cfg,
conns = get_connection_array(); conns = get_connection_array();
SMARTLIST_FOREACH(conns, connection_t *, conn, SMARTLIST_FOREACH(conns, connection_t *, conn,
{ {
if (conn->type != type || conn->marked_for_close) if (conn->type != type ||
conn->sa_family != sa_family ||
conn->marked_for_close)
continue; continue;
/* Okay, so this is a listener. Is it configured? */ /* Okay, so this is a listener. Is it configured? */
line = NULL; line = NULL;
@ -1044,15 +1191,28 @@ retry_listeners(int type, config_line_t *cfg,
{ {
char *address=NULL; char *address=NULL;
uint16_t port; uint16_t port;
if (!parse_addr_port(LOG_WARN, wanted->value, &address, NULL, &port)) { switch (sa_family) {
int addr_matches = !strcasecmp(address, conn->address); case AF_INET:
tor_free(address); if (!parse_addr_port(LOG_WARN,
if (! port) wanted->value, &address, NULL, &port)) {
port = port_option; int addr_matches = !strcasecmp(address, conn->address);
if (port == conn->port && addr_matches) { tor_free(address);
line = wanted; if (! port)
port = port_option;
if (port == conn->port && addr_matches) {
line = wanted;
break;
}
}
break; break;
} case AF_UNIX:
if (!strcasecmp(wanted->value, conn->address)) {
line = wanted;
break;
}
break;
default:
tor_assert(0);
} }
}); });
if (! line) { if (! line) {
@ -1080,8 +1240,31 @@ retry_listeners(int type, config_line_t *cfg,
if (!never_open_conns) { if (!never_open_conns) {
SMARTLIST_FOREACH(launch, config_line_t *, cfg_line, SMARTLIST_FOREACH(launch, config_line_t *, cfg_line,
{ {
conn = connection_create_listener(cfg_line->value, char *address = NULL;
(uint16_t) port_option, type); struct sockaddr *listensockaddr;
switch (sa_family) {
case AF_INET:
listensockaddr = (struct sockaddr *)
create_inet_sockaddr(cfg_line->value,
(uint16_t) port_option,
&address);
break;
case AF_UNIX:
listensockaddr = (struct sockaddr *)
create_unix_sockaddr(cfg_line->value,
&address);
break;
default:
tor_assert(0);
}
if (listensockaddr) {
conn = connection_create_listener(listensockaddr, type, address);
tor_free(address);
} else
conn = NULL;
if (!conn) { if (!conn) {
r = -1; r = -1;
} else { } else {
@ -1115,32 +1298,45 @@ retry_all_listeners(smartlist_t *replaced_conns,
if (retry_listeners(CONN_TYPE_OR_LISTENER, options->ORListenAddress, if (retry_listeners(CONN_TYPE_OR_LISTENER, options->ORListenAddress,
options->ORPort, "0.0.0.0", options->ORPort, "0.0.0.0",
replaced_conns, new_conns, options->ClientOnly)<0) replaced_conns, new_conns, options->ClientOnly,
AF_INET)<0)
return -1; return -1;
if (retry_listeners(CONN_TYPE_DIR_LISTENER, options->DirListenAddress, if (retry_listeners(CONN_TYPE_DIR_LISTENER, options->DirListenAddress,
options->DirPort, "0.0.0.0", options->DirPort, "0.0.0.0",
replaced_conns, new_conns, 0)<0) replaced_conns, new_conns, 0,
AF_INET)<0)
return -1; return -1;
if (retry_listeners(CONN_TYPE_AP_LISTENER, options->SocksListenAddress, if (retry_listeners(CONN_TYPE_AP_LISTENER, options->SocksListenAddress,
options->SocksPort, "127.0.0.1", options->SocksPort, "127.0.0.1",
replaced_conns, new_conns, 0)<0) replaced_conns, new_conns, 0,
AF_INET)<0)
return -1; return -1;
if (retry_listeners(CONN_TYPE_AP_TRANS_LISTENER, options->TransListenAddress, if (retry_listeners(CONN_TYPE_AP_TRANS_LISTENER, options->TransListenAddress,
options->TransPort, "127.0.0.1", options->TransPort, "127.0.0.1",
replaced_conns, new_conns, 0)<0) replaced_conns, new_conns, 0,
AF_INET)<0)
return -1; return -1;
if (retry_listeners(CONN_TYPE_AP_NATD_LISTENER, options->NatdListenAddress, if (retry_listeners(CONN_TYPE_AP_NATD_LISTENER, options->NatdListenAddress,
options->NatdPort, "127.0.0.1", options->NatdPort, "127.0.0.1",
replaced_conns, new_conns, 0)<0) replaced_conns, new_conns, 0,
AF_INET)<0)
return -1; return -1;
if (retry_listeners(CONN_TYPE_AP_DNS_LISTENER, options->DNSListenAddress, if (retry_listeners(CONN_TYPE_AP_DNS_LISTENER, options->DNSListenAddress,
options->DNSPort, "127.0.0.1", options->DNSPort, "127.0.0.1",
replaced_conns, new_conns, 0)<0) replaced_conns, new_conns, 0,
AF_INET)<0)
return -1; return -1;
if (retry_listeners(CONN_TYPE_CONTROL_LISTENER, if (retry_listeners(CONN_TYPE_CONTROL_LISTENER,
options->ControlListenAddress, options->ControlListenAddress,
options->ControlPort, "127.0.0.1", options->ControlPort, "127.0.0.1",
replaced_conns, new_conns, 0)<0) replaced_conns, new_conns, 0,
AF_INET)<0)
return -1;
if (retry_listeners(CONN_TYPE_CONTROL_LISTENER,
options->ControlSocket,
options->ControlSocket ? 1 : 0, NULL,
replaced_conns, new_conns, 0,
AF_UNIX)<0)
return -1; return -1;
return 0; return 0;

View File

@ -1916,7 +1916,7 @@ connection_ap_make_bridge(char *address, uint16_t port,
log_notice(LD_APP,"Making internal anonymized tunnel to %s:%d ...", log_notice(LD_APP,"Making internal anonymized tunnel to %s:%d ...",
safe_str(address),port); /* XXXX020 Downgrade back to info. */ safe_str(address),port); /* XXXX020 Downgrade back to info. */
conn = TO_EDGE_CONN(connection_new(CONN_TYPE_AP)); conn = TO_EDGE_CONN(connection_new(CONN_TYPE_AP, AF_INET));
conn->_base.linked = 1; /* so that we can add it safely below. */ conn->_base.linked = 1; /* so that we can add it safely below. */
/* populate conn->socks_request */ /* populate conn->socks_request */
@ -2210,7 +2210,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
} }
log_debug(LD_EXIT,"Creating new exit connection."); log_debug(LD_EXIT,"Creating new exit connection.");
n_stream = TO_EDGE_CONN(connection_new(CONN_TYPE_EXIT)); n_stream = TO_EDGE_CONN(connection_new(CONN_TYPE_EXIT, AF_INET));
n_stream->_base.purpose = EXIT_PURPOSE_CONNECT; n_stream->_base.purpose = EXIT_PURPOSE_CONNECT;
n_stream->stream_id = rh.stream_id; n_stream->stream_id = rh.stream_id;
@ -2316,7 +2316,7 @@ connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ)
* resolved; but if we didn't store them in a connection like this, * resolved; but if we didn't store them in a connection like this,
* the housekeeping in dns.c would get way more complicated.) * the housekeeping in dns.c would get way more complicated.)
*/ */
dummy_conn = TO_EDGE_CONN(connection_new(CONN_TYPE_EXIT)); dummy_conn = TO_EDGE_CONN(connection_new(CONN_TYPE_EXIT, AF_INET));
dummy_conn->stream_id = rh.stream_id; dummy_conn->stream_id = rh.stream_id;
dummy_conn->_base.address = tor_strndup(cell->payload+RELAY_HEADER_SIZE, dummy_conn->_base.address = tor_strndup(cell->payload+RELAY_HEADER_SIZE,
rh.length); rh.length);
@ -2450,7 +2450,7 @@ connection_exit_connect_dir(edge_connection_t *exitconn)
exitconn->_base.state = EXIT_CONN_STATE_OPEN; exitconn->_base.state = EXIT_CONN_STATE_OPEN;
dirconn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR)); dirconn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR, AF_INET));
dirconn->_base.addr = 0x7f000001; dirconn->_base.addr = 0x7f000001;
dirconn->_base.port = 0; dirconn->_base.port = 0;

View File

@ -465,7 +465,7 @@ connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest)
return NULL; return NULL;
} }
conn = TO_OR_CONN(connection_new(CONN_TYPE_OR)); conn = TO_OR_CONN(connection_new(CONN_TYPE_OR, AF_INET));
/* set up conn so it's got all the data we need to remember */ /* set up conn so it's got all the data we need to remember */
connection_or_init_conn_from_address(conn, addr, port, id_digest, 1); connection_or_init_conn_from_address(conn, addr, port, id_digest, 1);

View File

@ -339,7 +339,7 @@ spawn_cpuworker(void)
tor_free(fdarray); tor_free(fdarray);
#endif #endif
conn = connection_new(CONN_TYPE_CPUWORKER); conn = connection_new(CONN_TYPE_CPUWORKER, AF_UNIX);
set_socket_nonblocking(fd); set_socket_nonblocking(fd);

View File

@ -490,7 +490,7 @@ directory_initiate_command(const char *address, uint32_t addr,
tor_assert(0); tor_assert(0);
} }
conn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR)); conn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR, AF_INET));
/* set up conn so it's got all the data we need to remember */ /* set up conn so it's got all the data we need to remember */
conn->_base.addr = addr; conn->_base.addr = addr;

View File

@ -110,7 +110,7 @@ evdns_server_callback(struct evdns_server_request *req, void *_data)
/* XXXX020 Send a stream event to the controller. */ /* XXXX020 Send a stream event to the controller. */
/* Make a new dummy AP connection, and attach the request to it. */ /* Make a new dummy AP connection, and attach the request to it. */
conn = TO_EDGE_CONN(connection_new(CONN_TYPE_AP)); conn = TO_EDGE_CONN(connection_new(CONN_TYPE_AP, AF_INET));
conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT; conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT;
if (q->type == EVDNS_TYPE_A) if (q->type == EVDNS_TYPE_A)
conn->socks_request->command = SOCKS_COMMAND_RESOLVE; conn->socks_request->command = SOCKS_COMMAND_RESOLVE;

View File

@ -56,6 +56,9 @@
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> #include <sys/socket.h>
#endif #endif
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
#ifdef HAVE_SYS_TIME_H #ifdef HAVE_SYS_TIME_H
#include <sys/time.h> #include <sys/time.h>
#endif #endif
@ -791,6 +794,9 @@ typedef struct connection_t {
time_t timestamp_created; /**< When was this connection_t created? */ time_t timestamp_created; /**< When was this connection_t created? */
/* XXXX020 make this ipv6-capable */ /* XXXX020 make this ipv6-capable */
int sa_family; /**< Address family of this connection's socket. Usually
* AF_INET, but it can also be AF_UNIX, or in the future
* AF_INET6 */
uint32_t addr; /**< IP of the other side of the connection; used to identify uint32_t addr; /**< IP of the other side of the connection; used to identify
* routers, along with port. */ * routers, along with port. */
uint16_t port; /**< If non-zero, port on the other end uint16_t port; /**< If non-zero, port on the other end
@ -1825,6 +1831,8 @@ typedef struct {
int TransPort; int TransPort;
int NatdPort; /**< Port to listen on for transparent natd connections. */ int NatdPort; /**< Port to listen on for transparent natd connections. */
int ControlPort; /**< Port to listen on for control connections. */ int ControlPort; /**< Port to listen on for control connections. */
config_line_t * ControlSocket; /**< Unix Domain Socket to listen on
* for control connections. */
int DirPort; /**< Port to listen on for directory connections. */ int DirPort; /**< Port to listen on for directory connections. */
int DNSPort; /**< Port to listen on for DNS requests. */ int DNSPort; /**< Port to listen on for DNS requests. */
int AssumeReachable; /**< Whether to publish our descriptor regardless. */ int AssumeReachable; /**< Whether to publish our descriptor regardless. */
@ -2347,7 +2355,7 @@ or_options_t *options_new(void);
const char *conn_type_to_string(int type); const char *conn_type_to_string(int type);
const char *conn_state_to_string(int type, int state); const char *conn_state_to_string(int type, int state);
connection_t *connection_new(int type); connection_t *connection_new(int type, int sa_family);
void connection_link_connections(connection_t *conn_a, connection_t *conn_b); void connection_link_connections(connection_t *conn_a, connection_t *conn_b);
void connection_unregister_events(connection_t *conn); void connection_unregister_events(connection_t *conn);
void connection_free(connection_t *conn); void connection_free(connection_t *conn);