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]);
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;

View File

@ -13,15 +13,12 @@
#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;
@ -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(&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);
@ -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(&param->sinsr);
memset(&param->sinsl, 0, sizeof(param->sinsr));
*SAFAMILY(&param->sinsr) = AF_INET;
*(unsigned long *)SAADDR(&param->sinsr) = cur->redirip;
memcpy(&param->sinsr, &cur->addr, SASIZE(&cur->addr));
*SAPORT(&param->sinsr) = port;
}
else if(!cur->redirip && cur->redirport) *SAPORT(&param->sinsr) = cur->redirport;
else if(*SAFAMILY(&param->req) == AF_INET){
memset(&param->sinsr, 0, sizeof(param->sinsr));
*SAFAMILY(&param->sinsr) = AF_INET;
*(unsigned long *)SAADDR(&param->sinsr) = cur->redirip;
*SAPORT(&param->sinsr) = cur->redirport;
else if(SAISNULL(&cur->addr) && *SAPORT(&cur->addr)) *SAPORT(&param->sinsr) = *SAPORT(&cur->addr);
else {
memcpy(&param->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(&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;
}
redir = cur;
@ -309,7 +307,7 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
}
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){
@ -347,7 +345,7 @@ int ACLmatches(struct ace* acentry, struct clientparam * param){
}
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)
if(IPInentry((struct sockaddr *)&param->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));

View File

@ -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(&param->sinsr), "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", SAADDRLEN(&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->sinsr)){
if(SAISNULL(&param->req)) {
return 100;
}
*SAFAMILY(&param->sinsr) = *SAFAMILY(&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){
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"}
};

View File

@ -102,7 +102,7 @@ void * sockschild(struct clientparam* param) {
*SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req) = (c == 1)? AF_INET:AF_INET6;
memcpy(SAADDR(&param->sinsr), 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);
}
myinet_ntop(*SAFAMILY(&param->sinsr), SAADDR(&param->sinsr), (char *)buf, 64);
@ -269,7 +269,7 @@ fflush(stderr);
param->res = 462;
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))) {
param->res = 470;
break;

View File

@ -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;

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 (!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;
RETURN (100);
}