nserver address may be given as IPv6

This commit is contained in:
z3APA3A 2014-12-13 03:56:01 +03:00
parent a4cb2f36b5
commit 042fc2afde
7 changed files with 64 additions and 40 deletions

View File

@ -1003,18 +1003,19 @@ static int h_flushusers(int argc, unsigned char **argv){
*/ */
static int h_nserver(int argc, unsigned char **argv){ static int h_nserver(int argc, unsigned char **argv){
int res;
char *str; char *str;
for(res = 0; nservers[res].ip && res < MAXNSERVERS; res++); if(numservers < MAXNSERVERS) {
if(res < MAXNSERVERS) {
if((str = strchr((char *)argv[1], '/'))) if((str = strchr((char *)argv[1], '/')))
*str = 0; *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) { if(str) {
nservers[res].usetcp = strstr(str + 1, "tcp")? 1:0; nservers[numservers].usetcp = strstr(str + 1, "tcp")? 1:0;
*str = '/'; *str = '/';
} }
numservers++;
} }
resolvfunc = myresolver; resolvfunc = myresolver;
return 0; return 0;

View File

@ -950,61 +950,68 @@ unsigned long hashresolv(struct hashtable *ht, const unsigned char* name, unsign
return 0; 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 authnserver;
unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientparam* param, int makeauth){ unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientparam* param, int makeauth){
int i; int i,n;
unsigned long retval; unsigned long retval;
if((retval = hashresolv(&dns_table, name, retttl))) { if((retval = hashresolv(&dns_table, name, retttl))) {
return retval; return retval;
} }
n = (makeauth && authnserver)? 1 : numservers;
for(i=0; (i<(makeauth && authnserver)? 1 : MAXNSERVERS) && ((makeauth && authnserver) || nservers[i].ip); i++){ for(i=0; i<n; i++){
unsigned short nq, na; unsigned short nq, na;
unsigned char b[4098], *buf, *s1, *s2; unsigned char b[4098], *buf, *s1, *s2;
int j, k, len, flen; int j, k, len, flen;
SOCKET sock; SOCKET sock;
unsigned ttl; unsigned ttl;
time_t t; 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; int usetcp = 0;
unsigned short serial = 1; unsigned short serial = 1;
buf = b+2; buf = b+2;
sinsp = (param && !makeauth)? (struct sockaddr_in *)&param->sinsr : &sin; sinsl = (param && !makeauth)? (struct sockaddr *)&param->sinsl : (struct sockaddr *)&addr;
memset(sinsp, 0, sizeof(struct sockaddr_in)); sinsr = (param && !makeauth)? (struct sockaddr *)&param->sinsr : (struct sockaddr *)&addr;
memset(sinsl, 0, sizeof(addr));
memset(sinsr, 0, sizeof(addr));
if(makeauth && authnserver){ if(makeauth && authnserver){
if((sock=so._socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) break; if((sock=so._socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) break;
*SAFAMILY(sinsl) = AF_INET;
*SAFAMILY(sinsr) = AF_INET;
} }
else { else {
usetcp = nservers[i].usetcp; 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; if(so._bind(sock,sinsl,sizeof(addr))){
sinsp->sin_port = htons(0);
sinsp->sin_addr.s_addr = htonl(0);
if(so._bind(sock,(struct sockaddr *)sinsp,sizeof(struct sockaddr_in))){
so._shutdown(sock, SHUT_RDWR); so._shutdown(sock, SHUT_RDWR);
so._closesocket(sock); so._closesocket(sock);
break; break;
} }
if(makeauth && authnserver){ 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 { else {
sinsp->sin_addr.s_addr = nservers[i].ip; memcpy(sinsr, &nservers[i].addr, sizeof(addr));
} }
sinsp->sin_port = htons(53);
if(usetcp){ 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._shutdown(sock, SHUT_RDWR);
so._closesocket(sock); so._closesocket(sock);
break; break;
@ -1040,13 +1047,13 @@ unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientpa
len+=2; 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._shutdown(sock, SHUT_RDWR);
so._closesocket(sock); so._closesocket(sock);
continue; continue;
} }
if(param) param->statscli64 += len; 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._shutdown(sock, SHUT_RDWR);
so._closesocket(sock); so._closesocket(sock);
if(len <= 13) { if(len <= 13) {
@ -1054,8 +1061,13 @@ unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientpa
} }
if(param) param->statssrv64 += len; if(param) param->statssrv64 += len;
if(usetcp){ if(usetcp){
buf+=2; unsigned short us;
us = ntohs(*(unsigned short*)buf);
len-=2; 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(*(unsigned short *)buf != serial)continue;
if((na = buf[7] + (((unsigned short)buf[6])<<8)) < 1) { if((na = buf[7] + (((unsigned short)buf[6])<<8)) < 1) {

View File

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

View File

@ -40,13 +40,13 @@ void * dnsprchild(struct clientparam* param) {
buf = bbuf+2; buf = bbuf+2;
size = sizeof(param->sincr); size = sizeof(param->sincr);
i = so._recvfrom(param->srv->srvsock, buf, BUFSIZE, 0, (struct sockaddr *)&param->sincr, &size); 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 #ifdef _WIN32
if((param->clisock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { if((param->clisock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
RETURN(818); RETURN(818);
} }
ioctlsocket(param->clisock, FIONBIO, &ul); 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._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))) { if(so._bind(param->clisock,(struct sockaddr *)&param->sincl,sizeof(param->sincl))) {
RETURN(822); RETURN(822);
@ -109,7 +109,7 @@ void * dnsprchild(struct clientparam* param) {
unsigned a, b, c, d; unsigned a, b, c, d;
sscanf(host, "%u.%u.%u.%u", &a, &b, &c, &d); sscanf(host, "%u.%u.%u.%u", &a, &b, &c, &d);
ip = htonl((d<<24) ^ (c<<16) ^ (b<<8) ^ a); 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[2] = 0x85;
buf[3] = 0x80; buf[3] = 0x80;
buf[6] = 0; buf[6] = 0;
@ -129,19 +129,16 @@ void * dnsprchild(struct clientparam* param) {
} }
else ip = 0; else ip = 0;
} }
if(!ip && nservers[0].ip){ if(!ip && numservers){
if((param->remsock=so._socket(PF_INET, nservers[0].usetcp? SOCK_STREAM:SOCK_DGRAM, nservers[0].usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) { 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); RETURN(818);
} }
*SAFAMILY(&param->sinsl) = AF_INET; memset(&param->sinsl, 0, sizeof(param->sinsl));
*SAPORT(&param->sinsl) = htons(0); *SAFAMILY(&param->sinsl) = *SAFAMILY(&nservers[0].addr);
*(unsigned long*)SAADDR(&param->sinsl) = htonl(0);
if(so._bind(param->remsock,(struct sockaddr *)&param->sinsl,sizeof(param->sinsl))) { if(so._bind(param->remsock,(struct sockaddr *)&param->sinsl,sizeof(param->sinsl))) {
RETURN(819); RETURN(819);
} }
*SAFAMILY(&param->sinsr) = AF_INET; memcpy(&param->sinsr, &nservers[0].addr, sizeof(param->sinsr));
*(unsigned long*)SAADDR(&param->sinsr) = nservers[0].ip;
*SAPORT(&param->sinsr) = htons(53);
if(nservers[0].usetcp) { if(nservers[0].usetcp) {
if(so._connect(param->remsock,(struct sockaddr *)&param->sinsr,sizeof(param->sinsr))) RETURN(830); if(so._connect(param->remsock,(struct sockaddr *)&param->sinsr,sizeof(param->sinsr))) RETURN(830);
buf-=2; buf-=2;
@ -168,8 +165,13 @@ void * dnsprchild(struct clientparam* param) {
param->statssrv64 += len; param->statssrv64 += len;
param->nreads++; param->nreads++;
if(nservers[0].usetcp) { if(nservers[0].usetcp) {
unsigned short us;
us = ntohs(*(unsigned short *)buf);
if(us > 4096) RETURN(833);
buf += 2; buf += 2;
len -= 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(buf[6] || buf[7]){
if(socksendto(param->clisock, (struct sockaddr *)&param->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){ 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[2] = 0x85;
buf[3] = 0x83; buf[3] = 0x83;
} }
/* usleep(SLEEPTIME); */
res = socksendto(param->clisock, (struct sockaddr *)&param->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000); res = socksendto(param->clisock, (struct sockaddr *)&param->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000);
if(res != len){RETURN(819);} if(res != len){RETURN(819);}
if(!ip) {RETURN(888);} if(!ip) {RETURN(888);}

View File

@ -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_LINGER, (unsigned char *)&lg, sizeof(lg));
so._setsockopt(new_sock, SOL_SOCKET, SO_OOBINLINE, (unsigned char *)&opt, sizeof(int)); so._setsockopt(new_sock, SOL_SOCKET, SO_OOBINLINE, (unsigned char *)&opt, sizeof(int));
} }
else else {
srv.fds.events = 0; srv.fds.events = 0;
}
if(! (newparam = myalloc (sizeof(defparam)))){ if(! (newparam = myalloc (sizeof(defparam)))){
if(!isudp) so._closesocket(new_sock); if(!isudp) so._closesocket(new_sock);
defparam.res = 21; defparam.res = 21;
@ -896,6 +897,7 @@ void freeconf(struct extparam *confp){
confp->singlepacket = 0; confp->singlepacket = 0;
confp->maxchild = 100; confp->maxchild = 100;
resolvfunc = NULL; resolvfunc = NULL;
numservers = 0;
acl = confp->acl; acl = confp->acl;
confp->acl = NULL; confp->acl = NULL;
confp->logtime = confp->time = 0; confp->logtime = confp->time = 0;
@ -927,6 +929,7 @@ void freeconf(struct extparam *confp){
for(i = 0; i < archiverc; i++) myfree(archiver[i]); for(i = 0; i < archiverc; i++) myfree(archiver[i]);
myfree(archiver); myfree(archiver);
} }
} }
FILTER_ACTION handlereqfilters(struct clientparam *param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p){ FILTER_ACTION handlereqfilters(struct clientparam *param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p){

View File

@ -298,9 +298,14 @@ struct trafcount {
}; };
struct nserver { struct nserver {
unsigned long ip; #ifndef NOIPV6
struct sockaddr_in6 addr;
#else
struct sockaddr_in addr;
#endif
int usetcp; int usetcp;
}; };
extern int numservers;
typedef void * (* PROXYFUNC)(struct clientparam *); typedef void * (* PROXYFUNC)(struct clientparam *);

View File

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