From 8a6632f0d1e578547679a4c8b45b49ad84c03d92 Mon Sep 17 00:00:00 2001 From: z3APA3A <3APA3A@3proxy.ru> Date: Sat, 13 Dec 2014 22:38:03 +0300 Subject: [PATCH] Support IPv6 for parent proxy Parent proxy can be on IPv6 network (except SOCKS4). --- src/3proxy.c | 9 ++++---- src/auth.c | 58 +++++++++++++++++++++++------------------------- src/common.c | 10 ++++++--- src/datatypes.c | 19 ++++++---------- src/socks.c | 4 ++-- src/structures.h | 10 +++++++-- src/udppm.c | 2 +- 7 files changed, 58 insertions(+), 54 deletions(-) diff --git a/src/3proxy.c b/src/3proxy.c index 76700b1..6fb239b 100644 --- a/src/3proxy.c +++ b/src/3proxy.c @@ -1147,8 +1147,8 @@ static int h_parent(int argc, unsigned char **argv){ fprintf(stderr, "Chaining error: bad chain type (%s)\n", argv[2]); return(4); } - chains->redirip = getip(argv[3]); - chains->redirport = htons((unsigned short)atoi((char *)argv[4])); + if(!getip46(46, argv[3], (struct sockaddr *)&chains->addr)) return 5; + *SAPORT(&chains->addr) = htons((unsigned short)atoi((char *)argv[4])); if(argc > 5) chains->extuser = (unsigned char *)mystrdup((char *)argv[5]); if(argc > 6) chains->extpass = (unsigned char *)mystrdup((char *)argv[6]); return 0; @@ -1523,13 +1523,14 @@ static int h_ace(int argc, unsigned char **argv){ switch(acl->action){ case REDIRECT: acl->chains = myalloc(sizeof(struct chain)); + memset(acl->chains, 0, sizeof(struct chain)); if(!acl->chains) { fprintf(stderr, "No memory for ACL entry, line %d\n", linenum); return(2); } acl->chains->type = R_HTTP; - acl->chains->redirip = getip(argv[1]); - acl->chains->redirport = htons((unsigned short)atoi((char *)argv[2])); + if(!getip46(46, argv[1], (struct sockaddr *)&acl->chains->addr)) return 5; + *SAPORT(&acl->chains->addr) = htons((unsigned short)atoi((char *)argv[2])); acl->chains->weight = 1000; acl->chains->extuser = NULL; acl->chains->extpass = NULL; diff --git a/src/auth.c b/src/auth.c index b544e1d..ef1dbda 100644 --- a/src/auth.c +++ b/src/auth.c @@ -13,16 +13,13 @@ #define RECORDSIZE 18 -int clientnegotiate(struct chain * redir, struct clientparam * param, unsigned long ip, unsigned short port){ +int clientnegotiate(struct chain * redir, struct clientparam * param, struct sockaddr * addr){ unsigned char buf[1024]; - struct in_addr ina; int res; int len=0; unsigned char * user, *pass; - ina.s_addr = ip; - user = redir->extuser; pass = redir->extpass; if(user) { @@ -39,15 +36,17 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, unsigned l case R_CONNECT: case R_CONNECTP: { - sprintf((char *)buf, "CONNECT "); + len = sprintf((char *)buf, "CONNECT "); if(redir->type == R_CONNECTP && param->hostname) { - len = 8 + sprintf((char *)buf + 8, "%.256s", param->hostname); + len =+ sprintf((char *)buf + len, "%.256s", param->hostname); } else { - len = 8 + myinet_ntop(AF_INET, &ina, (char *)buf+8, 256); + if(*SAFAMILY(addr) == AF_INET6) buf[len++] = '['; + len += myinet_ntop(AF_INET, SAADDR(addr), (char *)buf+8, 256); + if(*SAFAMILY(addr) == AF_INET6) buf[len++] = ']'; } len += sprintf((char *)buf + len, - ":%hu HTTP/1.0\r\nProxy-Connection: keep-alive\r\n", ntohs(port)); + ":%hu HTTP/1.0\r\nProxy-Connection: keep-alive\r\n", *SAPORT(addr)); if(user){ unsigned char username[256]; len += sprintf((char *)buf + len, "Proxy-authorization: basic "); @@ -73,14 +72,15 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, unsigned l case R_SOCKS4B: { + if(*SAFAMILY(addr) != AF_INET) return 44; buf[0] = 4; buf[1] = 1; - memcpy(buf+2, &port, 2); + memcpy(buf+2, SAPORT(addr), 2); if(redir->type == R_SOCKS4P && param->hostname) { buf[4] = buf[5] = buf[6] = 0; buf[7] = 3; } - else memcpy(buf+4, &ip, 4); + else memcpy(buf+4, SAADDR(addr), 4); if(!user)user = (unsigned char *)"anonymous"; len = (int)strlen((char *)user) + 1; memcpy(buf+8, user, len); @@ -162,11 +162,12 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, unsigned l len += 5; } else { - buf[3] = 1; - memcpy(buf+4, &ip, 4); - len = 8; + len = 3; + buf[len++] = (*SAFAMILY(addr) == AF_INET)? 1 : 4; + memcpy(buf+len, SAADDR(addr), SAADDRLEN(addr)); + len += SAADDRLEN(addr); } - memcpy(buf+len, &port, 2); + memcpy(buf+len, SAPORT(addr), 2); len += 2; if(socksend(param->remsock, buf, len, conf.timeouts[CHAIN_TO]) != len){ return 51; @@ -210,7 +211,9 @@ int handleredirect(struct clientparam * param, struct ace * acentry){ if(param->remsock != INVALID_SOCKET) { return 0; } - if(!memcmp(SAADDR(¶m->req),"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",SAADDRLEN(¶m->req)) || !*SAPORT(¶m->req)) return 100; + if(SAISNULL(¶m->req) || !*SAPORT(¶m->req)) { + return 100; + } r2 = (myrand(param, sizeof(struct clientparam))%1000); @@ -231,7 +234,7 @@ int handleredirect(struct clientparam * param, struct ace * acentry){ r2 = (myrand(param, sizeof(struct clientparam))%1000); } if(!connected){ - if(!cur->redirip && !cur->redirport){ + if(SAISNULL(&cur->addr) && !*SAPORT(&cur->addr)){ if(cur->extuser){ if(param->extusername) myfree(param->extusername); @@ -266,19 +269,14 @@ int handleredirect(struct clientparam * param, struct ace * acentry){ } return 0; } - else if(!cur->redirport && cur->redirip) { + else if(!*SAPORT(&cur->addr) && !SAISNULL(&cur->addr)) { unsigned short port = *SAPORT(¶m->sinsr); - memset(¶m->sinsl, 0, sizeof(param->sinsr)); - *SAFAMILY(¶m->sinsr) = AF_INET; - *(unsigned long *)SAADDR(¶m->sinsr) = cur->redirip; + memcpy(¶m->sinsr, &cur->addr, SASIZE(&cur->addr)); *SAPORT(¶m->sinsr) = port; } - else if(!cur->redirip && cur->redirport) *SAPORT(¶m->sinsr) = cur->redirport; - else if(*SAFAMILY(¶m->req) == AF_INET){ - memset(¶m->sinsr, 0, sizeof(param->sinsr)); - *SAFAMILY(¶m->sinsr) = AF_INET; - *(unsigned long *)SAADDR(¶m->sinsr) = cur->redirip; - *SAPORT(¶m->sinsr) = cur->redirport; + else if(SAISNULL(&cur->addr) && *SAPORT(&cur->addr)) *SAPORT(¶m->sinsr) = *SAPORT(&cur->addr); + else { + memcpy(¶m->sinsr, &cur->addr, SASIZE(&cur->addr)); } if((res = alwaysauth(param))){ @@ -286,7 +284,7 @@ int handleredirect(struct clientparam * param, struct ace * acentry){ } } else { - res = (redir && *SAFAMILY(¶m->req) == AF_INET)?clientnegotiate(redir, param, cur->redirip, cur->redirport):0; + res = (redir)?clientnegotiate(redir, param, (struct sockaddr *)&cur->addr):0; if(res) return res; } redir = cur; @@ -309,7 +307,7 @@ int handleredirect(struct clientparam * param, struct ace * acentry){ } if(!connected) return 9; - return (redir && *SAFAMILY(¶m->req) == AF_INET)?clientnegotiate(redir, param, *(unsigned long *)SAADDR(¶m->req), *SAPORT(¶m->req)):0; + return (redir)?clientnegotiate(redir, param, (struct sockaddr *)¶m->req):0; } int IPInentry(struct sockaddr *sa, struct iplist *ipentry){ @@ -347,7 +345,7 @@ int ACLmatches(struct ace* acentry, struct clientparam * param){ } if(!ipentry) return 0; } - if((acentry->dst && memcmp(SAADDR(¶m->req), "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", SAADDRLEN(¶m->req))) || (acentry->dstnames && param->hostname)) { + if((acentry->dst && SAISNULL(¶m->req)) || (acentry->dstnames && param->hostname)) { for(ipentry = acentry->dst; ipentry; ipentry = ipentry->next) if(IPInentry((struct sockaddr *)¶m->req, ipentry)) { break; @@ -596,7 +594,7 @@ int checkACL(struct clientparam * param){ if(param->operation < 256 && !(param->operation & CONNECT)){ continue; } - if(param->redirected && acentry->chains && !acentry->chains->redirip && !acentry->chains->redirport) { + if(param->redirected && acentry->chains && SAISNULL(&acentry->chains->addr) && !*SAPORT(&acentry->chains->addr)) { continue; } memcpy(&dup, acentry, sizeof(struct ace)); diff --git a/src/common.c b/src/common.c index 69d1e5f..1a0006f 100644 --- a/src/common.c +++ b/src/common.c @@ -36,7 +36,7 @@ int myinet_ntop(int af, void *src, char *dst, socklen_t size){ } *dst = 0; inet_ntop(af, src, dst, size); - return strlen(dst); + return (int)strlen(dst); #endif } @@ -90,6 +90,8 @@ struct extparam conf = { int numservers=0; +char* NULLADDR="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + int myrand(void * entropy, int len){ int i; unsigned short init; @@ -613,8 +615,10 @@ int doconnect(struct clientparam * param){ else { struct linger lg; - if(!memcmp(SAADDR(¶m->sinsr), "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", SAADDRLEN(¶m->sinsr))){ - if(!memcmp(SAADDR(¶m->req), "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", SAADDRLEN(¶m->req))) return 100; + if(SAISNULL(¶m->sinsr)){ + if(SAISNULL(¶m->req)) { + return 100; + } *SAFAMILY(¶m->sinsr) = *SAFAMILY(¶m->req); memcpy(SAADDR(¶m->sinsr), SAADDR(¶m->req), SAADDRLEN(¶m->req)); } diff --git a/src/datatypes.c b/src/datatypes.c index 19364c5..4c51ed9 100644 --- a/src/datatypes.c +++ b/src/datatypes.c @@ -344,12 +344,8 @@ static void * ef_chain_type(struct node * node){ } } -static void * ef_chain_ip(struct node * node){ - return &((struct chain *)node->value) -> redirip; -} - -static void * ef_chain_port(struct node * node){ - return &((struct chain *)node->value) -> redirport; +static void * ef_chain_addr(struct node * node){ + return &((struct chain *)node->value) -> addr; } static void * ef_chain_weight(struct node * node){ @@ -690,12 +686,11 @@ static struct property prop_pwlist[] = { }; static struct property prop_chain[] = { - {prop_chain + 1, "ip", ef_chain_ip, TYPE_IP, "parent ip address"}, - {prop_chain + 2, "port", ef_chain_port, TYPE_PORT, "parent port"}, - {prop_chain + 3, "type", ef_chain_type, TYPE_STRING, "parent type"}, - {prop_chain + 4, "weight", ef_chain_weight, TYPE_SHORT, "parent weight 0-1000"}, - {prop_chain + 5, "user", ef_chain_user, TYPE_STRING, "parent login"}, - {prop_chain + 6, "password", ef_chain_password, TYPE_STRING, "parent password"}, + {prop_chain + 1, "addr", ef_chain_addr, TYPE_SA, "parent address"}, + {prop_chain + 2, "type", ef_chain_type, TYPE_STRING, "parent type"}, + {prop_chain + 3, "weight", ef_chain_weight, TYPE_SHORT, "parent weight 0-1000"}, + {prop_chain + 4, "user", ef_chain_user, TYPE_STRING, "parent login"}, + {prop_chain + 5, "password", ef_chain_password, TYPE_STRING, "parent password"}, {NULL, "next", ef_chain_next, TYPE_CHAIN, "next"} }; diff --git a/src/socks.c b/src/socks.c index a813604..6b68557 100644 --- a/src/socks.c +++ b/src/socks.c @@ -102,7 +102,7 @@ void * sockschild(struct clientparam* param) { *SAFAMILY(¶m->sinsr) = *SAFAMILY(¶m->req) = (c == 1)? AF_INET:AF_INET6; memcpy(SAADDR(¶m->sinsr), buf, size); memcpy(SAADDR(¶m->req), buf, size); - if(command==1 && !memcmp(SAADDR(¶m->req), "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", size)) { + if(command==1 && SAISNULL(¶m->req)) { RETURN(421); } myinet_ntop(*SAFAMILY(¶m->sinsr), SAADDR(¶m->sinsr), (char *)buf, 64); @@ -269,7 +269,7 @@ fflush(stderr); param->res = 462; break; } - if(!memcmp(SAADDR(¶m->req),"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",SAADDRLEN(¶m->req)) && + if(SAISNULL(¶m->req) && memcmp(SAADDR(¶m->req),SAADDR(¶m->sinsr),SAADDRLEN(¶m->req))) { param->res = 470; break; diff --git a/src/structures.h b/src/structures.h index b195213..4b7567c 100644 --- a/src/structures.h +++ b/src/structures.h @@ -108,14 +108,17 @@ int #define SAADDRLEN(sa) (((struct sockaddr_in *)sa)->sin_family == AF_INET6? 16:4) #define SASOCK(sa) (((struct sockaddr_in *)sa)->sin_family == AF_INET6? PF_INET6:PF_INET) #define SASIZE(sa) (((struct sockaddr_in *)sa)->sin_family == AF_INET6? sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in)) +#define SAISNULL(sa) (!memcmp(((struct sockaddr_in *)sa)->sin_family == AF_INET6? (unsigned char *)((struct sockaddr_in6 *)sa)->sin6_addr.u.Byte : (unsigned char *)&((struct sockaddr_in *)sa)->sin_addr.s_addr, NULLADDR, (((struct sockaddr_in *)sa)->sin_family == AF_INET6? 16:4))) #else #define SAPORT(sa) (&((struct sockaddr_in *)sa)->sin_port) #define SAADDR(sa) ((unsigned char *)&((struct sockaddr_in *)sa)->sin_addr.s_addr) #define SAADDRLEN(sa) (4) #define SASOCK(sa) (PF_INET) #define SASIZE(sa) (sizeof(struct sockaddr_in)) +#define SAISNULL(sa) (((struct sockaddr_in *)sa)->sin_addr.s_addr == 0) #endif +extern char* NULLADDR; typedef enum { CLIENT, SERVER @@ -228,8 +231,11 @@ typedef enum { struct chain { struct chain * next; int type; - unsigned long redirip; - unsigned short redirport; +#ifndef NOIPV6 + struct sockaddr_in6 addr; +#else + struct sockaddr_in addr; +#endif unsigned short weight; unsigned char * extuser; unsigned char * extpass; diff --git a/src/udppm.c b/src/udppm.c index dc3d84f..9be913a 100644 --- a/src/udppm.c +++ b/src/udppm.c @@ -40,7 +40,7 @@ void * udppmchild(struct clientparam* param) { if(!param->hostname)parsehostname((char *)param->srv->target, param, ntohs(param->srv->targetport)); - if (!memcmp(SAADDR(¶m->req), "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", SAADDRLEN(¶m->req))) { + if (SAISNULL(¶m->req)) { param->srv->fds.events = POLLIN; RETURN (100); }