Support IPv6 for parent proxy

Parent proxy can be on IPv6 network (except SOCKS4).
This commit is contained in:
z3APA3A 2014-12-13 22:38:03 +03:00
parent d2437975b7
commit 8a6632f0d1
7 changed files with 58 additions and 54 deletions

View File

@ -1147,8 +1147,8 @@ static int h_parent(int argc, unsigned char **argv){
fprintf(stderr, "Chaining error: bad chain type (%s)\n", argv[2]); fprintf(stderr, "Chaining error: bad chain type (%s)\n", argv[2]);
return(4); return(4);
} }
chains->redirip = getip(argv[3]); if(!getip46(46, argv[3], (struct sockaddr *)&chains->addr)) return 5;
chains->redirport = htons((unsigned short)atoi((char *)argv[4])); *SAPORT(&chains->addr) = htons((unsigned short)atoi((char *)argv[4]));
if(argc > 5) chains->extuser = (unsigned char *)mystrdup((char *)argv[5]); if(argc > 5) chains->extuser = (unsigned char *)mystrdup((char *)argv[5]);
if(argc > 6) chains->extpass = (unsigned char *)mystrdup((char *)argv[6]); if(argc > 6) chains->extpass = (unsigned char *)mystrdup((char *)argv[6]);
return 0; return 0;
@ -1523,13 +1523,14 @@ static int h_ace(int argc, unsigned char **argv){
switch(acl->action){ switch(acl->action){
case REDIRECT: case REDIRECT:
acl->chains = myalloc(sizeof(struct chain)); acl->chains = myalloc(sizeof(struct chain));
memset(acl->chains, 0, sizeof(struct chain));
if(!acl->chains) { if(!acl->chains) {
fprintf(stderr, "No memory for ACL entry, line %d\n", linenum); fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
return(2); return(2);
} }
acl->chains->type = R_HTTP; acl->chains->type = R_HTTP;
acl->chains->redirip = getip(argv[1]); if(!getip46(46, argv[1], (struct sockaddr *)&acl->chains->addr)) return 5;
acl->chains->redirport = htons((unsigned short)atoi((char *)argv[2])); *SAPORT(&acl->chains->addr) = htons((unsigned short)atoi((char *)argv[2]));
acl->chains->weight = 1000; acl->chains->weight = 1000;
acl->chains->extuser = NULL; acl->chains->extuser = NULL;
acl->chains->extpass = NULL; acl->chains->extpass = NULL;

View File

@ -13,16 +13,13 @@
#define RECORDSIZE 18 #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]; unsigned char buf[1024];
struct in_addr ina;
int res; int res;
int len=0; int len=0;
unsigned char * user, *pass; unsigned char * user, *pass;
ina.s_addr = ip;
user = redir->extuser; user = redir->extuser;
pass = redir->extpass; pass = redir->extpass;
if(user) { if(user) {
@ -39,15 +36,17 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, unsigned l
case R_CONNECT: case R_CONNECT:
case R_CONNECTP: case R_CONNECTP:
{ {
sprintf((char *)buf, "CONNECT "); len = sprintf((char *)buf, "CONNECT ");
if(redir->type == R_CONNECTP && param->hostname) { 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 { 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, 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){ if(user){
unsigned char username[256]; unsigned char username[256];
len += sprintf((char *)buf + len, "Proxy-authorization: basic "); 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: case R_SOCKS4B:
{ {
if(*SAFAMILY(addr) != AF_INET) return 44;
buf[0] = 4; buf[0] = 4;
buf[1] = 1; buf[1] = 1;
memcpy(buf+2, &port, 2); memcpy(buf+2, SAPORT(addr), 2);
if(redir->type == R_SOCKS4P && param->hostname) { if(redir->type == R_SOCKS4P && param->hostname) {
buf[4] = buf[5] = buf[6] = 0; buf[4] = buf[5] = buf[6] = 0;
buf[7] = 3; buf[7] = 3;
} }
else memcpy(buf+4, &ip, 4); else memcpy(buf+4, SAADDR(addr), 4);
if(!user)user = (unsigned char *)"anonymous"; if(!user)user = (unsigned char *)"anonymous";
len = (int)strlen((char *)user) + 1; len = (int)strlen((char *)user) + 1;
memcpy(buf+8, user, len); memcpy(buf+8, user, len);
@ -162,11 +162,12 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, unsigned l
len += 5; len += 5;
} }
else { else {
buf[3] = 1; len = 3;
memcpy(buf+4, &ip, 4); buf[len++] = (*SAFAMILY(addr) == AF_INET)? 1 : 4;
len = 8; memcpy(buf+len, SAADDR(addr), SAADDRLEN(addr));
len += SAADDRLEN(addr);
} }
memcpy(buf+len, &port, 2); memcpy(buf+len, SAPORT(addr), 2);
len += 2; len += 2;
if(socksend(param->remsock, buf, len, conf.timeouts[CHAIN_TO]) != len){ if(socksend(param->remsock, buf, len, conf.timeouts[CHAIN_TO]) != len){
return 51; return 51;
@ -210,7 +211,9 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
if(param->remsock != INVALID_SOCKET) { if(param->remsock != INVALID_SOCKET) {
return 0; return 0;
} }
if(!memcmp(SAADDR(&param->req),"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",SAADDRLEN(&param->req)) || !*SAPORT(&param->req)) return 100; if(SAISNULL(&param->req) || !*SAPORT(&param->req)) {
return 100;
}
r2 = (myrand(param, sizeof(struct clientparam))%1000); 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); r2 = (myrand(param, sizeof(struct clientparam))%1000);
} }
if(!connected){ if(!connected){
if(!cur->redirip && !cur->redirport){ if(SAISNULL(&cur->addr) && !*SAPORT(&cur->addr)){
if(cur->extuser){ if(cur->extuser){
if(param->extusername) if(param->extusername)
myfree(param->extusername); myfree(param->extusername);
@ -266,19 +269,14 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
} }
return 0; return 0;
} }
else if(!cur->redirport && cur->redirip) { else if(!*SAPORT(&cur->addr) && !SAISNULL(&cur->addr)) {
unsigned short port = *SAPORT(&param->sinsr); unsigned short port = *SAPORT(&param->sinsr);
memset(&param->sinsl, 0, sizeof(param->sinsr)); memcpy(&param->sinsr, &cur->addr, SASIZE(&cur->addr));
*SAFAMILY(&param->sinsr) = AF_INET;
*(unsigned long *)SAADDR(&param->sinsr) = cur->redirip;
*SAPORT(&param->sinsr) = port; *SAPORT(&param->sinsr) = port;
} }
else if(!cur->redirip && cur->redirport) *SAPORT(&param->sinsr) = cur->redirport; else if(SAISNULL(&cur->addr) && *SAPORT(&cur->addr)) *SAPORT(&param->sinsr) = *SAPORT(&cur->addr);
else if(*SAFAMILY(&param->req) == AF_INET){ else {
memset(&param->sinsr, 0, sizeof(param->sinsr)); memcpy(&param->sinsr, &cur->addr, SASIZE(&cur->addr));
*SAFAMILY(&param->sinsr) = AF_INET;
*(unsigned long *)SAADDR(&param->sinsr) = cur->redirip;
*SAPORT(&param->sinsr) = cur->redirport;
} }
if((res = alwaysauth(param))){ if((res = alwaysauth(param))){
@ -286,7 +284,7 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
} }
} }
else { else {
res = (redir && *SAFAMILY(&param->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; if(res) return res;
} }
redir = cur; redir = cur;
@ -309,7 +307,7 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
} }
if(!connected) return 9; if(!connected) return 9;
return (redir && *SAFAMILY(&param->req) == AF_INET)?clientnegotiate(redir, param, *(unsigned long *)SAADDR(&param->req), *SAPORT(&param->req)):0; return (redir)?clientnegotiate(redir, param, (struct sockaddr *)&param->req):0;
} }
int IPInentry(struct sockaddr *sa, struct iplist *ipentry){ 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(!ipentry) return 0;
} }
if((acentry->dst && memcmp(SAADDR(&param->req), "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", SAADDRLEN(&param->req))) || (acentry->dstnames && param->hostname)) { if((acentry->dst && SAISNULL(&param->req)) || (acentry->dstnames && param->hostname)) {
for(ipentry = acentry->dst; ipentry; ipentry = ipentry->next) for(ipentry = acentry->dst; ipentry; ipentry = ipentry->next)
if(IPInentry((struct sockaddr *)&param->req, ipentry)) { if(IPInentry((struct sockaddr *)&param->req, ipentry)) {
break; break;
@ -596,7 +594,7 @@ int checkACL(struct clientparam * param){
if(param->operation < 256 && !(param->operation & CONNECT)){ if(param->operation < 256 && !(param->operation & CONNECT)){
continue; 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; continue;
} }
memcpy(&dup, acentry, sizeof(struct ace)); memcpy(&dup, acentry, sizeof(struct ace));

View File

@ -36,7 +36,7 @@ int myinet_ntop(int af, void *src, char *dst, socklen_t size){
} }
*dst = 0; *dst = 0;
inet_ntop(af, src, dst, size); inet_ntop(af, src, dst, size);
return strlen(dst); return (int)strlen(dst);
#endif #endif
} }
@ -90,6 +90,8 @@ struct extparam conf = {
int numservers=0; 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 myrand(void * entropy, int len){
int i; int i;
unsigned short init; unsigned short init;
@ -613,8 +615,10 @@ int doconnect(struct clientparam * param){
else { else {
struct linger lg; struct linger lg;
if(!memcmp(SAADDR(&param->sinsr), "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", SAADDRLEN(&param->sinsr))){ if(SAISNULL(&param->sinsr)){
if(!memcmp(SAADDR(&param->req), "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", SAADDRLEN(&param->req))) return 100; if(SAISNULL(&param->req)) {
return 100;
}
*SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req); *SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req);
memcpy(SAADDR(&param->sinsr), SAADDR(&param->req), SAADDRLEN(&param->req)); memcpy(SAADDR(&param->sinsr), SAADDR(&param->req), SAADDRLEN(&param->req));
} }

View File

@ -344,12 +344,8 @@ static void * ef_chain_type(struct node * node){
} }
} }
static void * ef_chain_ip(struct node * node){ static void * ef_chain_addr(struct node * node){
return &((struct chain *)node->value) -> redirip; return &((struct chain *)node->value) -> addr;
}
static void * ef_chain_port(struct node * node){
return &((struct chain *)node->value) -> redirport;
} }
static void * ef_chain_weight(struct node * node){ static void * ef_chain_weight(struct node * node){
@ -690,12 +686,11 @@ static struct property prop_pwlist[] = {
}; };
static struct property prop_chain[] = { static struct property prop_chain[] = {
{prop_chain + 1, "ip", ef_chain_ip, TYPE_IP, "parent ip address"}, {prop_chain + 1, "addr", ef_chain_addr, TYPE_SA, "parent address"},
{prop_chain + 2, "port", ef_chain_port, TYPE_PORT, "parent port"}, {prop_chain + 2, "type", ef_chain_type, TYPE_STRING, "parent type"},
{prop_chain + 3, "type", ef_chain_type, TYPE_STRING, "parent type"}, {prop_chain + 3, "weight", ef_chain_weight, TYPE_SHORT, "parent weight 0-1000"},
{prop_chain + 4, "weight", ef_chain_weight, TYPE_SHORT, "parent weight 0-1000"}, {prop_chain + 4, "user", ef_chain_user, TYPE_STRING, "parent login"},
{prop_chain + 5, "user", ef_chain_user, TYPE_STRING, "parent login"}, {prop_chain + 5, "password", ef_chain_password, TYPE_STRING, "parent password"},
{prop_chain + 6, "password", ef_chain_password, TYPE_STRING, "parent password"},
{NULL, "next", ef_chain_next, TYPE_CHAIN, "next"} {NULL, "next", ef_chain_next, TYPE_CHAIN, "next"}
}; };

View File

@ -102,7 +102,7 @@ void * sockschild(struct clientparam* param) {
*SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req) = (c == 1)? AF_INET:AF_INET6; *SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req) = (c == 1)? AF_INET:AF_INET6;
memcpy(SAADDR(&param->sinsr), buf, size); memcpy(SAADDR(&param->sinsr), buf, size);
memcpy(SAADDR(&param->req), buf, size); memcpy(SAADDR(&param->req), buf, size);
if(command==1 && !memcmp(SAADDR(&param->req), "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", size)) { if(command==1 && SAISNULL(&param->req)) {
RETURN(421); RETURN(421);
} }
myinet_ntop(*SAFAMILY(&param->sinsr), SAADDR(&param->sinsr), (char *)buf, 64); myinet_ntop(*SAFAMILY(&param->sinsr), SAADDR(&param->sinsr), (char *)buf, 64);
@ -269,7 +269,7 @@ fflush(stderr);
param->res = 462; param->res = 462;
break; break;
} }
if(!memcmp(SAADDR(&param->req),"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",SAADDRLEN(&param->req)) && if(SAISNULL(&param->req) &&
memcmp(SAADDR(&param->req),SAADDR(&param->sinsr),SAADDRLEN(&param->req))) { memcmp(SAADDR(&param->req),SAADDR(&param->sinsr),SAADDRLEN(&param->req))) {
param->res = 470; param->res = 470;
break; break;

View File

@ -108,14 +108,17 @@ int
#define SAADDRLEN(sa) (((struct sockaddr_in *)sa)->sin_family == AF_INET6? 16:4) #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 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 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 #else
#define SAPORT(sa) (&((struct sockaddr_in *)sa)->sin_port) #define SAPORT(sa) (&((struct sockaddr_in *)sa)->sin_port)
#define SAADDR(sa) ((unsigned char *)&((struct sockaddr_in *)sa)->sin_addr.s_addr) #define SAADDR(sa) ((unsigned char *)&((struct sockaddr_in *)sa)->sin_addr.s_addr)
#define SAADDRLEN(sa) (4) #define SAADDRLEN(sa) (4)
#define SASOCK(sa) (PF_INET) #define SASOCK(sa) (PF_INET)
#define SASIZE(sa) (sizeof(struct sockaddr_in)) #define SASIZE(sa) (sizeof(struct sockaddr_in))
#define SAISNULL(sa) (((struct sockaddr_in *)sa)->sin_addr.s_addr == 0)
#endif #endif
extern char* NULLADDR;
typedef enum { typedef enum {
CLIENT, CLIENT,
SERVER SERVER
@ -228,8 +231,11 @@ typedef enum {
struct chain { struct chain {
struct chain * next; struct chain * next;
int type; int type;
unsigned long redirip; #ifndef NOIPV6
unsigned short redirport; struct sockaddr_in6 addr;
#else
struct sockaddr_in addr;
#endif
unsigned short weight; unsigned short weight;
unsigned char * extuser; unsigned char * extuser;
unsigned char * extpass; unsigned char * extpass;

View File

@ -40,7 +40,7 @@ void * udppmchild(struct clientparam* param) {
if(!param->hostname)parsehostname((char *)param->srv->target, param, ntohs(param->srv->targetport)); if(!param->hostname)parsehostname((char *)param->srv->target, param, ntohs(param->srv->targetport));
if (!memcmp(SAADDR(&param->req), "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", SAADDRLEN(&param->req))) { if (SAISNULL(&param->req)) {
param->srv->fds.events = POLLIN; param->srv->fds.events = POLLIN;
RETURN (100); RETURN (100);
} }