X-Git-Url: http://git.dolda2000.com/gitweb/?a=blobdiff_plain;f=daemon%2Fnet.c;h=d98f6205ac7157367c8942afc4d9e6a25d90ea0a;hb=18c1ae1d1b26cc4170eb19204bf2109fb7befe9e;hp=f16441f0d67e0041f09828b2698fbc379309c419;hpb=d3372da97568d5e1f35fa19787c8ec8af93a0435;p=doldaconnect.git diff --git a/daemon/net.c b/daemon/net.c index f16441f..d98f620 100644 --- a/daemon/net.c +++ b/daemon/net.c @@ -51,9 +51,16 @@ static struct configvar myvars[] = { /* 0 = Direct mode, 1 = Passive mode, 2 = SOCKS proxy */ {CONF_VAR_INT, "mode", {.num = 0}}, + {CONF_VAR_BOOL, "reuseaddr", {.num = 0}}, /* Only for direct mode */ {CONF_VAR_IPV4, "visibleipv4", {.ipv4 = {0}}}, {CONF_VAR_STRING, "publicif", {.str = L""}}, + /* Diffserv should be supported on IPv4, too, but I don't know the + * API to do that. */ + {CONF_VAR_INT, "diffserv-mincost", {.num = 0}}, + {CONF_VAR_INT, "diffserv-maxrel", {.num = 0}}, + {CONF_VAR_INT, "diffserv-maxtp", {.num = 0}}, + {CONF_VAR_INT, "diffserv-mindelay", {.num = 0}}, {CONF_VAR_END} }; @@ -269,6 +276,23 @@ void putsock(struct socket *sk) } } +void sockpushdata(struct socket *sk, void *buf, size_t size) +{ + switch(sk->type) + { + case SOCK_STREAM: + sizebuf(&sk->inbuf.s.buf, &sk->inbuf.s.bufsize, sk->inbuf.s.datasize + size, 1, 1); + memmove(sk->inbuf.s.buf + size, sk->inbuf.s.buf, sk->inbuf.s.datasize); + memcpy(sk->inbuf.s.buf, buf, size); + sk->inbuf.s.datasize += size; + break; + case SOCK_DGRAM: + /* XXX */ + break; + } + return; +} + void *sockgetinbuf(struct socket *sk, size_t *size) { void *buf; @@ -521,6 +545,7 @@ size_t sockqueuesize(struct socket *sk) struct socket *netcslisten(int type, struct sockaddr *name, socklen_t namelen, void (*func)(struct socket *, struct socket *, void *), void *data) { struct socket *sk; + int intbuf; if(confgetint("net", "mode") == 1) { @@ -538,6 +563,11 @@ struct socket *netcslisten(int type, struct sockaddr *name, socklen_t namelen, v if((sk = mksock(name->sa_family, type)) == NULL) return(NULL); sk->state = SOCK_LST; + if(confgetint("net", "reuseaddr")) + { + intbuf = 1; + setsockopt(sk->fd, SOL_SOCKET, SO_REUSEADDR, &intbuf, sizeof(intbuf)); + } if(bind(sk->fd, name, namelen) < 0) { putsock(sk); @@ -567,6 +597,7 @@ struct socket *netcslisten(int type, struct sockaddr *name, socklen_t namelen, v struct socket *netcslistenlocal(int type, struct sockaddr *name, socklen_t namelen, void (*func)(struct socket *, struct socket *, void *), void *data) { struct socket *sk; + int intbuf; /* I don't know if this is actually correct (it probably isn't), * but since, at on least Linux systems, PF_* are specifically @@ -577,6 +608,11 @@ struct socket *netcslistenlocal(int type, struct sockaddr *name, socklen_t namel if((sk = mksock(name->sa_family, type)) == NULL) return(NULL); sk->state = SOCK_LST; + if(confgetint("net", "reuseaddr")) + { + intbuf = 1; + setsockopt(sk->fd, SOL_SOCKET, SO_REUSEADDR, &intbuf, sizeof(intbuf)); + } if(bind(sk->fd, name, namelen) < 0) { putsock(sk); @@ -824,16 +860,67 @@ int pollsocks(int timeout) int socksettos(struct socket *sk, int tos) { + int buf; + if(sk->family == AF_INET) { - if(setsockopt(sk->fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0) + switch(tos) + { + case SOCK_TOS_MINCOST: + buf = 0x02; + break; + case SOCK_TOS_MAXREL: + buf = 0x04; + break; + case SOCK_TOS_MAXTP: + buf = 0x08; + break; + case SOCK_TOS_MINDELAY: + buf = 0x10; + break; + default: + flog(LOG_WARNING, "attempted to set unknown TOS value %i to IPv4 sock", tos); + return(-1); + } + if(setsockopt(sk->fd, SOL_IP, IP_TOS, &buf, sizeof(buf)) < 0) { flog(LOG_WARNING, "could not set sock TOS to %i: %s", tos, strerror(errno)); return(-1); } return(0); } - /* XXX: How does the IPv6 traffic class work? */ + if(sk->family == AF_INET6) + { + switch(tos) + { + case SOCK_TOS_MINCOST: + buf = confgetint("net", "diffserv-mincost"); + break; + case SOCK_TOS_MAXREL: + buf = confgetint("net", "diffserv-maxrel"); + break; + case SOCK_TOS_MAXTP: + buf = confgetint("net", "diffserv-maxtp"); + break; + case SOCK_TOS_MINDELAY: + buf = confgetint("net", "diffserv-mindelay"); + break; + default: + flog(LOG_WARNING, "attempted to set unknown TOS value %i to IPv4 sock", tos); + return(-1); + } + /* + On Linux, the API IPv6 flow label management doesn't seem to + be entirely complete, so I guess this will have to wait. + + if(setsockopt(...) < 0) + { + flog(LOG_WARNING, "could not set sock traffic class to %i: %s", tos, strerror(errno)); + return(-1); + } + */ + return(0); + } flog(LOG_WARNING, "could not set TOS on sock of family %i", sk->family); return(1); }