Просмотр исходного кода

nserver address may be given as IPv6

z3APA3A 11 лет назад
Родитель
Сommit
042fc2afde
7 измененных файлов с 64 добавлено и 40 удалено
  1. 6 5
      src/3proxy.c
  2. 32 20
      src/auth.c
  3. 2 0
      src/common.c
  4. 13 12
      src/dnspr.c
  5. 4 1
      src/proxymain.c
  6. 6 1
      src/structures.h
  7. 1 1
      src/version.h

+ 6 - 5
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;

+ 32 - 20
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; i<n; i++){
 		unsigned short nq, na;
 		unsigned char b[4098], *buf, *s1, *s2;
 		int j, k, len, flen;
 		SOCKET sock;
 		unsigned ttl;
 		time_t t;
-		struct sockaddr_in sin, *sinsp;
+#ifndef NOIPV6
+		struct sockaddr_in6 addr;
+#else
+		struct sockaddr_in addr;
+#endif
+		struct sockaddr *sinsr, *sinsl;
 		int usetcp = 0;
 		unsigned short serial = 1;
 
 		buf = b+2;
 
-		sinsp = (param && !makeauth)? (struct sockaddr_in *)&param->sinsr : &sin;
-		memset(sinsp, 0, sizeof(struct sockaddr_in));
+		sinsl = (param && !makeauth)? (struct sockaddr *)&param->sinsl : (struct sockaddr *)&addr;
+		sinsr = (param && !makeauth)? (struct sockaddr *)&param->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) {

+ 2 - 0
src/common.c

@@ -88,6 +88,8 @@ struct extparam conf = {
 	'@'
 };
 
+int numservers=0;
+
 int myrand(void * entropy, int len){
 	int i;
 	unsigned short init;

+ 13 - 12
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 *)&param->sincr, &size); 
+ size = sizeof(param->sinsl);
+ getsockname(param->srv->srvsock, (struct sockaddr *)&param->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 *)&param->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 *)&param->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(&param->srv->intsa) == AF_INET &&  ip == *(unsigned long*)SAADDR(&param->srv->intsa)){
+	if(*SAFAMILY(&param->sincl) == AF_INET &&  ip == *(unsigned long*)SAADDR(&param->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(&param->sinsl) = AF_INET;
-	*SAPORT(&param->sinsl) = htons(0);
-	*(unsigned long*)SAADDR(&param->sinsl) = htonl(0);
+	memset(&param->sinsl, 0, sizeof(param->sinsl));
+	*SAFAMILY(&param->sinsl) = *SAFAMILY(&nservers[0].addr);
 	if(so._bind(param->remsock,(struct sockaddr *)&param->sinsl,sizeof(param->sinsl))) {
 		RETURN(819);
 	}
-	*SAFAMILY(&param->sinsr) = AF_INET;
-	*(unsigned long*)SAADDR(&param->sinsr) = nservers[0].ip;
-	*SAPORT(&param->sinsr) = htons(53);
+	memcpy(&param->sinsr, &nservers[0].addr, sizeof(param->sinsr));
 	if(nservers[0].usetcp) {
 		if(so._connect(param->remsock,(struct sockaddr *)&param->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 *)&param->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 *)&param->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000); 
  if(res != len){RETURN(819);}
  if(!ip) {RETURN(888);}

+ 4 - 1
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){

+ 6 - 1
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 *);
 

+ 1 - 1
src/version.h

@@ -1,2 +1,2 @@
 #define VERSION "3proxy-0.8b-devel"
-#define BUILDDATE "141212231810"
+#define BUILDDATE "141213035229"