X-Git-Url: http://dolda2000.com/gitweb/?a=blobdiff_plain;f=daemon%2Fnet.c;h=4147031c2048794da9a107a16d2f22c9a43ec863;hb=0ecdd176e7eba9fb46f4b3228f8b109a7cf20ab4;hp=5960a552611600c31a74e14937f08b7e1b58135c;hpb=1315d02ac996285e943de172ccd6c420633eeeec;p=doldaconnect.git diff --git a/daemon/net.c b/daemon/net.c index 5960a55..4147031 100644 --- a/daemon/net.c +++ b/daemon/net.c @@ -48,17 +48,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} }; @@ -253,12 +276,14 @@ void putsock(struct socket *sk) { sk->outbuf.d.f = buf->next; free(buf->data); + free(buf->addr); free(buf); } while((buf = sk->inbuf.d.f) != NULL) { sk->inbuf.d.f = buf->next; free(buf->data); + free(buf->addr); free(buf); } break; @@ -702,7 +727,8 @@ struct socket *netcsconn(struct sockaddr *addr, socklen_t addrlen, void (*func)( int pollsocks(int timeout) { - int i, num, ret, retlen; + int i, num, ret; + socklen_t retlen; int newfd; struct pollfd *pfds; struct socket *sk, *next, *newsk; @@ -1039,9 +1065,47 @@ int sockgetlocalname(struct socket *sk, struct sockaddr **namebuf, socklen_t *le return(0); } -int sockgetremotename(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf) +static void sethostaddr(struct sockaddr *dst, struct sockaddr *src) +{ + if(dst->sa_family != src->sa_family) + { + flog(LOG_ERR, "BUG: non-matching socket families in sethostaddr (%i -> %i)", src->sa_family, dst->sa_family); + return; + } + switch(src->sa_family) + { + case AF_INET: + ((struct sockaddr_in *)dst)->sin_addr = ((struct sockaddr_in *)src)->sin_addr; + break; + case AF_INET6: + ((struct sockaddr_in6 *)dst)->sin6_addr = ((struct sockaddr_in6 *)src)->sin6_addr; + break; + default: + flog(LOG_WARNING, "sethostaddr unimplemented for family %i", src->sa_family); + break; + } +} + +static int makepublic(struct sockaddr *addr) { int ret; + socklen_t plen; + struct sockaddr *pname; + + if((ret = getpublicaddr(addr->sa_family, &pname, &plen)) < 0) + { + flog(LOG_ERR, "could not get public address: %s", strerror(errno)); + return(-1); + } + if(ret) + return(0); + sethostaddr(addr, pname); + free(pname); + return(0); +} + +int sockgetremotename(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf) +{ socklen_t len; struct sockaddr *name; @@ -1050,22 +1114,15 @@ int sockgetremotename(struct socket *sk, struct sockaddr **namebuf, socklen_t *l case 0: *namebuf = NULL; if((sk->state == SOCK_STL) || (sk->fd < 0)) - return(-1); - if((ret = getpublicaddr(sk->family, &name, &len)) < 0) { - flog(LOG_ERR, "could not get public address: %s", strerror(errno)); + errno = EBADF; return(-1); } - if(ret == 0) - { - *namebuf = name; - *lenbuf = len; - return(0); - } if(!sockgetlocalname(sk, &name, &len)) { *namebuf = name; *lenbuf = len; + makepublic(name); return(0); } flog(LOG_ERR, "could not get remotely accessible name by any means"); @@ -1080,6 +1137,29 @@ int sockgetremotename(struct socket *sk, struct sockaddr **namebuf, socklen_t *l } } +int sockgetremotename2(struct socket *sk, struct socket *sk2, struct sockaddr **namebuf, socklen_t *lenbuf) +{ + struct sockaddr *name1, *name2; + socklen_t len1, len2; + + if(sk->family != sk2->family) + { + flog(LOG_ERR, "using sockgetremotename2 with sockets of differing family: %i %i", sk->family, sk2->family); + return(-1); + } + if(sockgetremotename(sk, &name1, &len1)) + return(-1); + if(sockgetremotename(sk2, &name2, &len2)) { + free(name1); + return(-1); + } + sethostaddr(name1, name2); + free(name2); + *namebuf = name1; + *lenbuf = len1; + return(0); +} + int addreq(struct sockaddr *x, struct sockaddr *y) { struct sockaddr_un *u1, *u2; @@ -1103,6 +1183,7 @@ int addreq(struct sockaddr *x, struct sockaddr *y) if(n1->sin_addr.s_addr != n2->sin_addr.s_addr) return(0); break; +#ifdef HAVE_IPV6 case AF_INET6: s1 = (struct sockaddr_in6 *)x; s2 = (struct sockaddr_in6 *)y; if(s1->sin6_port != s2->sin6_port) @@ -1110,6 +1191,7 @@ int addreq(struct sockaddr *x, struct sockaddr *y) if(memcmp(s1->sin6_addr.s6_addr, s2->sin6_addr.s6_addr, sizeof(s1->sin6_addr.s6_addr))) return(0); break; +#endif } return(1); }