diff --git a/src/3proxy.c b/src/3proxy.c index a25b882..426e027 100644 --- a/src/3proxy.c +++ b/src/3proxy.c @@ -1003,10 +1003,17 @@ 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] && res < MAXNSERVERS; res++); + for(res = 0; nservers[res].ip && res < MAXNSERVERS; res++); if(res < MAXNSERVERS) { - nservers[res] = getip(argv[1]); + if((str = strchr((char *)argv[1], '/'))) + *str = 0; + nservers[res].ip = getip(argv[1]); + if(str) { + nservers[res].usetcp = strstr(str + 1, "tcp")? 1:0; + *str = '/'; + } } resolvfunc = myresolver; return 0; diff --git a/src/auth.c b/src/auth.c index 912260c..4ad77ba 100644 --- a/src/auth.c +++ b/src/auth.c @@ -950,7 +950,8 @@ unsigned long hashresolv(struct hashtable *ht, const unsigned char* name, unsign return 0; } -unsigned long nservers[MAXNSERVERS] = {0, 0, 0, 0, 0}; +struct nserver nservers[MAXNSERVERS] = {{0,0}, {0,0}, {0,0}, {0,0}, {0,0}}; +int tcpresolve = 0; unsigned long authnserver; @@ -964,34 +965,53 @@ unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientpa return retval; } - for(i=0; (i<(makeauth && authnserver)? 1 : MAXNSERVERS) && ((makeauth && authnserver) || nservers[i]); i++){ + for(i=0; (i<(makeauth && authnserver)? 1 : MAXNSERVERS) && ((makeauth && authnserver) || nservers[i].ip); i++){ unsigned short nquery, nq, na; - unsigned char buf[4096], *s1, *s2; + unsigned char b[4098], *buf, *s1, *s2; int j, k, len, flen; SOCKET sock; unsigned ttl; time_t t; struct sockaddr_in sin, *sinsp; + int usetcp = 0; - memset(&sin, 0, sizeof(sin)); - sinsp = (param && !makeauth && *SAFAMILY(¶m->sinsr) == AF_INET)? (struct sockaddr_in *)¶m->sinsr : &sin; + buf = b+2; + + sinsp = (param && !makeauth)? (struct sockaddr_in *)¶m->sinsr : &sin; + memset(sinsp, 0, sizeof(struct sockaddr_in)); - if((sock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) break; + if(makeauth && authnserver){ + if((sock=so._socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) break; + } + else { + usetcp = nservers[i].usetcp; + if((sock=so._socket(PF_INET, usetcp?SOCK_STREAM:SOCK_DGRAM, usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) break; + } 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,(struct sockaddr *)sinsp,sizeof(struct sockaddr_in))){ so._shutdown(sock, SHUT_RDWR); so._closesocket(sock); break; } - sinsp->sin_addr.s_addr = (makeauth && authnserver)?authnserver : nservers[i]; + if(makeauth && authnserver){ + sinsp->sin_addr.s_addr = authnserver; + } + else { + sinsp->sin_addr.s_addr = nservers[i].ip; + } sinsp->sin_port = htons(53); - + if(usetcp){ + if(so._connect(sock,(struct sockaddr *)sinsp,sizeof(struct sockaddr_in))) { + so._shutdown(sock, SHUT_RDWR); + so._closesocket(sock); + break; + } + } len = (int)strlen((char *)name); - nquery = myrand(name, len); - *(unsigned short*)buf = nquery; /* query id */ + *(unsigned short*)buf = htons(i+1); /* query id */ buf[2] = 1; /* recursive */ buf[3] = 0; buf[4] = 0; @@ -1012,6 +1032,12 @@ unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientpa buf[len++] = (makeauth == 1)? 0x0c : 0x01; /* PTR:host address */ buf[len++] = 0; buf[len++] = 1; /* INET */ + if(usetcp){ + buf-=2; + *(unsigned short*)buf = htons(len); + len+=2; + } + if(socksendto(sock, (struct sockaddr *)sinsp, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){ so._shutdown(sock, SHUT_RDWR); so._closesocket(sock); @@ -1021,9 +1047,15 @@ unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientpa len = sockrecvfrom(sock, (struct sockaddr *) sinsp, buf, 4096, 15000); so._shutdown(sock, SHUT_RDWR); so._closesocket(sock); - if(len <= 13) continue; + if(len <= 13) { + continue; + } if(param) param->statssrv64 += len; - if(*(unsigned short *)buf != nquery)continue; + if(usetcp){ + buf+=2; + len-=2; + } + if(*(unsigned short *)buf != htons(i+1))continue; if((na = buf[7] + (((unsigned short)buf[6])<<8)) < 1) { return 0; } diff --git a/src/common.c b/src/common.c index 8052203..753119f 100644 --- a/src/common.c +++ b/src/common.c @@ -617,7 +617,7 @@ int doconnect(struct clientparam * param){ memcpy(SAADDR(¶m->sinsr), SAADDR(¶m->req), SAADDRLEN(¶m->req)); } if(!*SAPORT(¶m->sinsr))*SAPORT(¶m->sinsr) = *SAPORT(¶m->req); - if ((param->remsock=so._socket(*SAFAMILY(¶m->sinsr), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {return (11);} + if ((param->remsock=so._socket(SASOCK(¶m->sinsr), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {return (11);} so._setsockopt(param->remsock, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg)); #ifndef NOIPV6 if(*SAFAMILY(¶m->sinsr) == AF_INET6) memcpy(¶m->sinsl, ¶m->srv->extsa6, sizeof(param->srv->extsa6)); diff --git a/src/dnspr.c b/src/dnspr.c index 56e9d5b..55d1eee 100644 --- a/src/dnspr.c +++ b/src/dnspr.c @@ -14,11 +14,12 @@ #endif #define RETURN(xxx) { param->res = xxx; goto CLEANRET; } -#define BUFSIZE 4096 +#define BUFSIZE 16384 void * dnsprchild(struct clientparam* param) { unsigned long ip = 0; + unsigned char *bbuf; unsigned char *buf, *s1, *s2; char * host = NULL; unsigned char c; @@ -32,10 +33,11 @@ void * dnsprchild(struct clientparam* param) { #endif - if(!(buf = myalloc(BUFSIZE))){ + if(!(bbuf = myalloc(BUFSIZE+2))){ param->srv->fds.events = POLLIN; RETURN (21); } + buf = bbuf+2; size = sizeof(param->sincr); i = so._recvfrom(param->srv->srvsock, buf, BUFSIZE, 0, (struct sockaddr *)¶m->sincr, &size); #ifdef _WIN32 @@ -44,9 +46,9 @@ void * dnsprchild(struct clientparam* param) { } ioctlsocket(param->clisock, FIONBIO, &ul); size = sizeof(param->sinsl); - if(so._getsockname(param->srv->srvsock, (struct sockaddr *)¶m->sinsl, &size)) {RETURN(21);}; + 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->sinsl,sizeof(param->sinsl))) { + if(so._bind(param->clisock,(struct sockaddr *)¶m->sincl,sizeof(param->sincl))) { RETURN(822); } @@ -103,7 +105,7 @@ void * dnsprchild(struct clientparam* param) { memcpy(buf+len+12,(void *)&ip,4); len+=16; } - if(type == 0x0c) { + else if(type == 0x0c) { unsigned a, b, c, d; sscanf(host, "%u.%u.%u.%u", &a, &b, &c, &d); ip = htonl((d<<24) ^ (c<<16) ^ (b<<8) ^ a); @@ -127,15 +129,10 @@ void * dnsprchild(struct clientparam* param) { } else ip = 0; } - if(!ip && nservers[0] && type!=1){ - if((param->remsock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { + if(!ip && nservers[0].ip && type!=1){ + if((param->remsock=so._socket(PF_INET, nservers[0].usetcp? SOCK_STREAM:SOCK_DGRAM, nservers[0].usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) { RETURN(818); } -#ifdef _WIN32 - ioctlsocket(param->remsock, FIONBIO, &ul); -#else - fcntl(param->remsock,F_SETFL,O_NONBLOCK); -#endif *SAFAMILY(¶m->sinsl) = AF_INET; *SAPORT(¶m->sinsl) = htons(0); *(unsigned long*)SAADDR(¶m->sinsl) = htonl(0); @@ -143,8 +140,22 @@ void * dnsprchild(struct clientparam* param) { RETURN(819); } *SAFAMILY(¶m->sinsr) = AF_INET; - *(unsigned long*)SAADDR(¶m->sinsr) = nservers[0]; + *(unsigned long*)SAADDR(¶m->sinsr) = nservers[0].ip; *SAPORT(¶m->sinsr) = htons(53); + if(nservers[0].usetcp) { + if(so._connect(param->remsock,(struct sockaddr *)¶m->sinsr,sizeof(param->sinsr))) RETURN(830); + buf-=2; + *(unsigned short*)buf = htons(i); + i+=2; + } + else { +#ifdef _WIN32 +/* ioctlsocket(param->remsock, FIONBIO, &ul); */ +#else +/* fcntl(param->remsock,F_SETFL,O_NONBLOCK); */ +#endif + } + if(socksendto(param->remsock, (struct sockaddr *)¶m->sinsr, buf, i, conf.timeouts[SINGLEBYTE_L]*1000) != i){ RETURN(820); } @@ -156,6 +167,10 @@ void * dnsprchild(struct clientparam* param) { } param->statssrv64 += len; param->nreads++; + if(nservers[0].usetcp) { + buf += 2; + len -= 2; + } if(buf[6] || buf[7]){ if(socksendto(param->clisock, (struct sockaddr *)¶m->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){ RETURN(822); @@ -168,7 +183,7 @@ void * dnsprchild(struct clientparam* param) { buf[2] = 0x85; buf[3] = 0x83; } - usleep(SLEEPTIME); + /* 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);} @@ -186,7 +201,7 @@ CLEANRET: ); (*param->srv->logfunc)(param, buf); } - if(buf)myfree(buf); + if(bbuf)myfree(bbuf); if(host)myfree(host); #ifndef _WIN32 param->clisock = INVALID_SOCKET; diff --git a/src/proxy.h b/src/proxy.h index 66b6c4b..b5898d1 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -184,7 +184,7 @@ unsigned bandlimitfunc(struct clientparam *param, unsigned nbytesin, unsigned nb int scanaddr(const unsigned char *s, unsigned long * ip, unsigned long * mask); int myinet_ntop(int af, void *src, char *dst, socklen_t size); -extern unsigned long nservers[MAXNSERVERS]; +extern struct nserver nservers[MAXNSERVERS]; extern unsigned long authnserver; unsigned long getip(unsigned char *name); unsigned long getip46(int family, unsigned char *name, struct sockaddr *sa); diff --git a/src/socks.c b/src/socks.c index 928f494..a813604 100644 --- a/src/socks.c +++ b/src/socks.c @@ -160,7 +160,7 @@ void * sockschild(struct clientparam* param) { memcpy(¶m->sinsl, ¶m->srv->extsa, SASIZE(¶m->req)); #endif if(!*SAPORT(¶m->sinsl))*SAPORT(¶m->sinsl) = port; - if ((param->remsock=so._socket(*SAFAMILY(¶m->req), command == 2? SOCK_STREAM:SOCK_DGRAM, command == 2?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);} + if ((param->remsock=so._socket(SASOCK(¶m->req), command == 2? SOCK_STREAM:SOCK_DGRAM, command == 2?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);} param->operation = command == 2?BIND:UDPASSOC; break; diff --git a/src/structures.h b/src/structures.h index 06e8cdd..00a5cd0 100644 --- a/src/structures.h +++ b/src/structures.h @@ -297,6 +297,11 @@ struct trafcount { time_t updated; }; +struct nserver { + unsigned long ip; + int usetcp; +}; + typedef void * (* PROXYFUNC)(struct clientparam *); typedef enum { @@ -623,7 +628,7 @@ extern struct sockfuncs so; struct pluginlink { struct symbol symbols; struct extparam *conf; - unsigned long *nservers; + struct nserver *nservers; int * linenum; struct auth *authfuncs; struct commands * commandhandlers; diff --git a/src/udppm.c b/src/udppm.c index 0d3ef9b..dc3d84f 100644 --- a/src/udppm.c +++ b/src/udppm.c @@ -57,7 +57,7 @@ void * udppmchild(struct clientparam* param) { param->cliinbuf = i; #ifdef _WIN32 - if((param->clisock=so._socket(*SAFAMILY(¶m->sincr), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { + if((param->clisock=so._socket(SASOCK(¶m->sincr), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { RETURN(818); } if(so._setsockopt(param->clisock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&ul, sizeof(int))) {RETURN(820);}; @@ -77,7 +77,7 @@ void * udppmchild(struct clientparam* param) { memcpy(¶m->sinsl, ¶m->srv->extsa, SASIZE(¶m->req)); #endif *SAPORT(¶m->sinsl) = 0; - if ((param->remsock=so._socket(*SAFAMILY(¶m->sinsl), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);} + if ((param->remsock=so._socket(SASOCK(¶m->sinsl), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);} if(so._bind(param->remsock,(struct sockaddr *)¶m->sinsl,sizeof(param->sinsl))) {RETURN (12);} #ifdef _WIN32 ioctlsocket(param->remsock, FIONBIO, &ul); diff --git a/src/version.h b/src/version.h index 9971bab..dc2257c 100644 --- a/src/version.h +++ b/src/version.h @@ -1,2 +1,2 @@ #define VERSION "3proxy-0.8b-devel" -#define BUILDDATE "141210181747" +#define BUILDDATE "141211025611"