X-Git-Url: http://dolda2000.com/gitweb/?a=blobdiff_plain;f=daemon%2Fnet.c;h=00bc4659c131a0ff3bb1f02f766d6abeeff94fe9;hb=eb260dc774dd251effad70e58051ee2da5784801;hp=2a8fdefe304015411ad4d5982a569e90dee59bda;hpb=cab0b442977697b876127cda082b1262ece2714b;p=doldaconnect.git diff --git a/daemon/net.c b/daemon/net.c index 2a8fdef..00bc465 100644 --- a/daemon/net.c +++ b/daemon/net.c @@ -33,6 +33,7 @@ #include #include #include +#include /* For rebindunix() */ #ifdef HAVE_LINUX_SOCKIOS_H #include #endif @@ -48,17 +49,40 @@ static struct configvar myvars[] = { - /* 0 = Direct mode, 1 = Passive mode, 2 = SOCKS proxy */ + /** The network mode to use. Currently supported values are 0 for + * active mode and 1 for passive mode. In the future, SOCKS5 proxy + * support may be added. */ {CONF_VAR_INT, "mode", {.num = 0}}, + /** Set the SO_REUSEADDR socket option on listening sockets, so + * that dead TCP connections waiting for timeout are ignored. */ {CONF_VAR_BOOL, "reuseaddr", {.num = 0}}, - /* Only for direct mode */ + /** Overrides the IPv4 address reported to other clients in active + * mode. Useful for servers behind NAT routers. If both this and + * net.publicif are unspecified the address of the hub connection + * is used. */ {CONF_VAR_IPV4, "visibleipv4", {.ipv4 = {0}}}, + /** Specifies an interface name from which to fetch the IPv4 + * address reported to other clients in active mode. If both this + * and net.visibleipv4 are unspecified the address of the hub + * connection is used. */ {CONF_VAR_STRING, "publicif", {.str = L""}}, /* Diffserv should be supported on IPv4, too, but I don't know the * API to do that. */ + /** The Diffserv value to use on IPv6 connections when the + * minimize cost TOS value is used (see the TOS VALUES + * section). */ {CONF_VAR_INT, "diffserv-mincost", {.num = 0}}, + /** The Diffserv value to use on IPv6 connections when the + * maximize reliability TOS value is used (see the TOS VALUES + * section). */ {CONF_VAR_INT, "diffserv-maxrel", {.num = 0}}, + /** The Diffserv value to use on IPv6 connections when the + * maximize throughput TOS value is used (see the TOS VALUES + * section). */ {CONF_VAR_INT, "diffserv-maxtp", {.num = 0}}, + /** The Diffserv value to use on IPv6 connections when the + * minimize delay TOS value is used (see the TOS VALUES + * section). */ {CONF_VAR_INT, "diffserv-mindelay", {.num = 0}}, {CONF_VAR_END} }; @@ -265,8 +289,7 @@ void putsock(struct socket *sk) } break; } - if(sk->fd >= 0) - close(sk->fd); + closesock(sk); if(sk->remote != NULL) free(sk->remote); free(sk); @@ -464,6 +487,16 @@ static void sockflush(struct socket *sk) void closesock(struct socket *sk) { + struct sockaddr_un *un; + + if((sk->family == AF_UNIX) && !sockgetlocalname(sk, (struct sockaddr **)&un, NULL) && (un->sun_family == PF_UNIX)) + { + if((sk->state == SOCK_LST) && strchr(un->sun_path, '/')) + { + if(unlink(un->sun_path)) + flog(LOG_WARNING, "could not unlink Unix socket %s: %s", un->sun_path, strerror(errno)); + } + } sk->state = SOCK_STL; close(sk->fd); sk->fd = -1; @@ -540,6 +573,29 @@ size_t sockqueuesize(struct socket *sk) } /* + * Seriously, I don't know if it's naughty or not to remove + * pre-existing Unix sockets. + */ +static int rebindunix(struct socket *sk, struct sockaddr *name, socklen_t namelen) +{ + struct sockaddr_un *un; + struct stat sb; + + if((sk->family != AF_UNIX) || (name->sa_family != PF_UNIX)) + return(-1); + un = (struct sockaddr_un *)name; + if(stat(un->sun_path, &sb)) + return(-1); + if(!S_ISSOCK(sb.st_mode)) + return(-1); + if(unlink(un->sun_path)) + return(-1); + if(bind(sk->fd, name, namelen) < 0) + return(-1); + return(0); +} + +/* * The difference between netcslisten() and netcslistenlocal() is that * netcslistenlocal() always listens on the local host, instead of * following proxy/passive mode directions. It is suitable for eg. the @@ -566,7 +622,7 @@ struct socket *netcslistenlocal(int type, struct sockaddr *name, socklen_t namel intbuf = 1; setsockopt(sk->fd, SOL_SOCKET, SO_REUSEADDR, &intbuf, sizeof(intbuf)); } - if(bind(sk->fd, name, namelen) < 0) + if((bind(sk->fd, name, namelen) < 0) && ((errno != EADDRINUSE) || (rebindunix(sk, name, namelen) < 0))) { putsock(sk); return(NULL); @@ -858,6 +914,8 @@ int socksettos(struct socket *sk, int tos) { int buf; + if(sk->family == AF_UNIX) + return(0); /* Unix sockets are always perfect. :) */ if(sk->family == AF_INET) { switch(tos) @@ -1038,7 +1096,8 @@ int sockgetlocalname(struct socket *sk, struct sockaddr **namebuf, socklen_t *le return(-1); } *namebuf = memcpy(smalloc(len), &name, len); - *lenbuf = len; + if(lenbuf != NULL) + *lenbuf = len; return(0); }