diff --git a/src/udppm.c b/src/udppm.c index cbf7e56..270c24f 100644 --- a/src/udppm.c +++ b/src/udppm.c @@ -35,6 +35,9 @@ void * udppmchild(struct clientparam* param) { int authres; int i; int len = 0; +#if defined(_WIN32) && !defined(SHARE_UDP_SOCKET) + SOCKET copy = INVALID_SOCKET; +#endif if(parsehostname((char *)param->srv->target, param, ntohs(param->srv->targetport))) { RETURN(100) } @@ -49,6 +52,23 @@ void * udppmchild(struct clientparam* param) { authres = (*param->srv->authfunc)(param); if(authres) { RETURN(authres); } if((authres = udpbind(param))) { RETURN(authres); } +#if defined(_WIN32) && !defined(SHARE_UDP_SOCKET) + /* A build which does not share the UDP listening socket (see proxy.h) + answers the client through a socket of the session's own, bound to + the service's address, as dnspr does; the listening socket has + SO_REUSEADDR set for it in such a build. It is only written to. */ + { + PROXYSOCKADDRTYPE local; + SASIZETYPE size = sizeof(local); + unsigned long ul = 1; + + if(param->srv->so._getsockname(param->sostate, param->srv->srvsock, (struct sockaddr *)&local, &size)) { RETURN(21); } + if((copy = nssocket(param->srv, ¶m->srv->so, param->sostate, NS_IN, SASOCK(&local), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { RETURN(818); } + ioctlsocket(copy, FIONBIO, &ul); + if(param->srv->so._setsockopt(param->sostate, copy, SOL_SOCKET, SO_REUSEADDR, (char *)&ul, sizeof(int))) { RETURN(820); } + if(param->srv->so._bind(param->sostate, copy, (struct sockaddr *)&local, SASIZE(&local))) { RETURN(822); } + } +#endif if(!param->srv->s_option)hashadd(&udp_table, param, ¶m, MAX_COUNTER_TIME); if(!param->bandlimfunc || !(*param->bandlimfunc)(param, 0, param->srv->udplen)){ if(param->udp_nhops){ @@ -65,7 +85,11 @@ void * udppmchild(struct clientparam* param) { } _3proxy_sem_unlock(udpinit); param->srvinbuf = 0; +#if defined(_WIN32) && !defined(SHARE_UDP_SOCKET) + param->clisock = copy; +#else param->clisock = param->srv->srvsock; +#endif param->waitserver64 = 0x7fffffffffffffff; param->res = udpsockmap(param, param->srv->timeouts[STRING_L]); _3proxy_sem_lock(udpinit); @@ -75,6 +99,9 @@ CLEANRET: _3proxy_sem_unlock(udpinit); dolog(param, NULL); +#if defined(_WIN32) && !defined(SHARE_UDP_SOCKET) + if(copy != INVALID_SOCKET) param->srv->so._closesocket(param->sostate, copy); +#endif param->clisock = INVALID_SOCKET; return (NULL); }