From 042fc2afde7f364bd395ef442609ecfcb8dc6d8e Mon Sep 17 00:00:00 2001 From: z3APA3A <3APA3A@3proxy.ru> Date: Sat, 13 Dec 2014 03:56:01 +0300 Subject: [PATCH] nserver address may be given as IPv6 --- src/3proxy.c | 11 +++++----- src/auth.c | 52 +++++++++++++++++++++++++++++------------------- src/common.c | 2 ++ src/dnspr.c | 25 ++++++++++++----------- src/proxymain.c | 5 ++++- src/structures.h | 7 ++++++- src/version.h | 2 +- 7 files changed, 64 insertions(+), 40 deletions(-) diff --git a/src/3proxy.c b/src/3proxy.c index 63a95d5..fb99fb9 100644 --- a/src/3proxy.c +++ b/src/3proxy.c @@ -1003,18 +1003,19 @@ static int h_flushusers(int argc, unsigned char **argv){ */ static int h_nserver(int argc, unsigned char **argv){ - int res; char *str; - for(res = 0; nservers[res].ip && res < MAXNSERVERS; res++); - if(res < MAXNSERVERS) { + if(numservers < MAXNSERVERS) { if((str = strchr((char *)argv[1], '/'))) *str = 0; - nservers[res].ip = getip(argv[1]); + if(!getip46(46, argv[1], (struct sockaddr *)&nservers[numservers].addr)) return 1; + *SAPORT(&nservers[numservers].addr) = htons(53); if(str) { - nservers[res].usetcp = strstr(str + 1, "tcp")? 1:0; + nservers[numservers].usetcp = strstr(str + 1, "tcp")? 1:0; *str = '/'; } + numservers++; + } resolvfunc = myresolver; return 0; diff --git a/src/auth.c b/src/auth.c index 0525f95..2204e04 100644 --- a/src/auth.c +++ b/src/auth.c @@ -950,61 +950,68 @@ unsigned long hashresolv(struct hashtable *ht, const unsigned char* name, unsign return 0; } -struct nserver nservers[MAXNSERVERS] = {{0,0}, {0,0}, {0,0}, {0,0}, {0,0}}; - +struct nserver nservers[MAXNSERVERS] = {{{0},0}, {{0},0}, {{0},0}, {{0},0}, {{0},0}}; unsigned long authnserver; unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientparam* param, int makeauth){ - int i; + int i,n; unsigned long retval; if((retval = hashresolv(&dns_table, name, retttl))) { return retval; } - - for(i=0; (i<(makeauth && authnserver)? 1 : MAXNSERVERS) && ((makeauth && authnserver) || nservers[i].ip); i++){ + n = (makeauth && authnserver)? 1 : numservers; + for(i=0; isinsr : &sin; - memset(sinsp, 0, sizeof(struct sockaddr_in)); + sinsl = (param && !makeauth)? (struct sockaddr *)¶m->sinsl : (struct sockaddr *)&addr; + sinsr = (param && !makeauth)? (struct sockaddr *)¶m->sinsr : (struct sockaddr *)&addr; + memset(sinsl, 0, sizeof(addr)); + memset(sinsr, 0, sizeof(addr)); if(makeauth && authnserver){ if((sock=so._socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) break; + *SAFAMILY(sinsl) = AF_INET; + *SAFAMILY(sinsr) = AF_INET; } else { usetcp = nservers[i].usetcp; - if((sock=so._socket(PF_INET, usetcp?SOCK_STREAM:SOCK_DGRAM, usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) break; + if((sock=so._socket(SASOCK(&nservers[i].addr), usetcp?SOCK_STREAM:SOCK_DGRAM, usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) break; + *SAFAMILY(sinsl) = *SAFAMILY(&nservers[i].addr); + } - sinsp->sin_family = AF_INET; - sinsp->sin_port = htons(0); - sinsp->sin_addr.s_addr = htonl(0); - if(so._bind(sock,(struct sockaddr *)sinsp,sizeof(struct sockaddr_in))){ + if(so._bind(sock,sinsl,sizeof(addr))){ so._shutdown(sock, SHUT_RDWR); so._closesocket(sock); break; } if(makeauth && authnserver){ - sinsp->sin_addr.s_addr = authnserver; + ((struct sockaddr_in *)sinsr)->sin_addr.s_addr = authnserver; + ((struct sockaddr_in *)sinsr)->sin_port = htons(53); } else { - sinsp->sin_addr.s_addr = nservers[i].ip; + memcpy(sinsr, &nservers[i].addr, sizeof(addr)); } - sinsp->sin_port = htons(53); if(usetcp){ - if(so._connect(sock,(struct sockaddr *)sinsp,sizeof(struct sockaddr_in))) { + if(so._connect(sock,sinsr,sizeof(addr))) { so._shutdown(sock, SHUT_RDWR); so._closesocket(sock); break; @@ -1040,13 +1047,13 @@ unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientpa len+=2; } - if(socksendto(sock, (struct sockaddr *)sinsp, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){ + if(socksendto(sock, sinsr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){ so._shutdown(sock, SHUT_RDWR); so._closesocket(sock); continue; } if(param) param->statscli64 += len; - len = sockrecvfrom(sock, (struct sockaddr *) sinsp, buf, 4096, 15000); + len = sockrecvfrom(sock, sinsr, buf, 4096, 15000); so._shutdown(sock, SHUT_RDWR); so._closesocket(sock); if(len <= 13) { @@ -1054,8 +1061,13 @@ unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientpa } if(param) param->statssrv64 += len; if(usetcp){ - buf+=2; + unsigned short us; + us = ntohs(*(unsigned short*)buf); len-=2; + buf+=2; + if(us > 4096 || us < len || (us > len && sockrecvfrom(sock, sinsr, buf+len, us-len, 15000) != us-len)) { + continue; + } } if(*(unsigned short *)buf != serial)continue; if((na = buf[7] + (((unsigned short)buf[6])<<8)) < 1) { diff --git a/src/common.c b/src/common.c index 753119f..5ae3cac 100644 --- a/src/common.c +++ b/src/common.c @@ -88,6 +88,8 @@ struct extparam conf = { '@' }; +int numservers=0; + int myrand(void * entropy, int len){ int i; unsigned short init; diff --git a/src/dnspr.c b/src/dnspr.c index f264fb7..db7e9f1 100644 --- a/src/dnspr.c +++ b/src/dnspr.c @@ -40,13 +40,13 @@ void * dnsprchild(struct clientparam* param) { buf = bbuf+2; size = sizeof(param->sincr); i = so._recvfrom(param->srv->srvsock, buf, BUFSIZE, 0, (struct sockaddr *)¶m->sincr, &size); + size = sizeof(param->sinsl); + getsockname(param->srv->srvsock, (struct sockaddr *)¶m->sincl, &size); #ifdef _WIN32 if((param->clisock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { RETURN(818); } ioctlsocket(param->clisock, FIONBIO, &ul); - size = sizeof(param->sinsl); - if(so._getsockname(param->srv->srvsock, (struct sockaddr *)¶m->sincl, &size)) {RETURN(21);}; if(so._setsockopt(param->clisock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&ul, sizeof(int))) {RETURN(820);}; if(so._bind(param->clisock,(struct sockaddr *)¶m->sincl,sizeof(param->sincl))) { RETURN(822); @@ -109,7 +109,7 @@ void * dnsprchild(struct clientparam* param) { unsigned a, b, c, d; sscanf(host, "%u.%u.%u.%u", &a, &b, &c, &d); ip = htonl((d<<24) ^ (c<<16) ^ (b<<8) ^ a); - if(*SAFAMILY(¶m->srv->intsa) == AF_INET && ip == *(unsigned long*)SAADDR(¶m->srv->intsa)){ + if(*SAFAMILY(¶m->sincl) == AF_INET && ip == *(unsigned long*)SAADDR(¶m->sincl)){ buf[2] = 0x85; buf[3] = 0x80; buf[6] = 0; @@ -129,19 +129,16 @@ void * dnsprchild(struct clientparam* param) { } else ip = 0; } - if(!ip && nservers[0].ip){ - if((param->remsock=so._socket(PF_INET, nservers[0].usetcp? SOCK_STREAM:SOCK_DGRAM, nservers[0].usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) { + if(!ip && numservers){ + if((param->remsock=so._socket(SASOCK(&nservers[0].addr), nservers[0].usetcp? SOCK_STREAM:SOCK_DGRAM, nservers[0].usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) { RETURN(818); } - *SAFAMILY(¶m->sinsl) = AF_INET; - *SAPORT(¶m->sinsl) = htons(0); - *(unsigned long*)SAADDR(¶m->sinsl) = htonl(0); + memset(¶m->sinsl, 0, sizeof(param->sinsl)); + *SAFAMILY(¶m->sinsl) = *SAFAMILY(&nservers[0].addr); if(so._bind(param->remsock,(struct sockaddr *)¶m->sinsl,sizeof(param->sinsl))) { RETURN(819); } - *SAFAMILY(¶m->sinsr) = AF_INET; - *(unsigned long*)SAADDR(¶m->sinsr) = nservers[0].ip; - *SAPORT(¶m->sinsr) = htons(53); + memcpy(¶m->sinsr, &nservers[0].addr, sizeof(param->sinsr)); if(nservers[0].usetcp) { if(so._connect(param->remsock,(struct sockaddr *)¶m->sinsr,sizeof(param->sinsr))) RETURN(830); buf-=2; @@ -168,8 +165,13 @@ void * dnsprchild(struct clientparam* param) { param->statssrv64 += len; param->nreads++; if(nservers[0].usetcp) { + unsigned short us; + us = ntohs(*(unsigned short *)buf); + if(us > 4096) RETURN(833); buf += 2; len -= 2; + if(len < us) len += sockgetlinebuf(param, SERVER, buf+len, us - len, 0, conf.timeouts[SINGLEBYTE_L]); + if(len != us) RETURN(832); } if(buf[6] || buf[7]){ if(socksendto(param->clisock, (struct sockaddr *)¶m->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){ @@ -183,7 +185,6 @@ void * dnsprchild(struct clientparam* param) { buf[2] = 0x85; buf[3] = 0x83; } - /* usleep(SLEEPTIME); */ res = socksendto(param->clisock, (struct sockaddr *)¶m->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000); if(res != len){RETURN(819);} if(!ip) {RETURN(888);} diff --git a/src/proxymain.c b/src/proxymain.c index fb87e6f..231d946 100644 --- a/src/proxymain.c +++ b/src/proxymain.c @@ -460,8 +460,9 @@ int MODULEMAINFUNC (int argc, char** argv){ so._setsockopt(new_sock, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg)); so._setsockopt(new_sock, SOL_SOCKET, SO_OOBINLINE, (unsigned char *)&opt, sizeof(int)); } - else + else { srv.fds.events = 0; + } if(! (newparam = myalloc (sizeof(defparam)))){ if(!isudp) so._closesocket(new_sock); defparam.res = 21; @@ -896,6 +897,7 @@ void freeconf(struct extparam *confp){ confp->singlepacket = 0; confp->maxchild = 100; resolvfunc = NULL; + numservers = 0; acl = confp->acl; confp->acl = NULL; confp->logtime = confp->time = 0; @@ -927,6 +929,7 @@ void freeconf(struct extparam *confp){ for(i = 0; i < archiverc; i++) myfree(archiver[i]); myfree(archiver); } + } FILTER_ACTION handlereqfilters(struct clientparam *param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p){ diff --git a/src/structures.h b/src/structures.h index 00a5cd0..b195213 100644 --- a/src/structures.h +++ b/src/structures.h @@ -298,9 +298,14 @@ struct trafcount { }; struct nserver { - unsigned long ip; +#ifndef NOIPV6 + struct sockaddr_in6 addr; +#else + struct sockaddr_in addr; +#endif int usetcp; }; +extern int numservers; typedef void * (* PROXYFUNC)(struct clientparam *); diff --git a/src/version.h b/src/version.h index c993aa2..1ae6423 100644 --- a/src/version.h +++ b/src/version.h @@ -1,2 +1,2 @@ #define VERSION "3proxy-0.8b-devel" -#define BUILDDATE "141212231810" +#define BUILDDATE "141213035229"