Преглед изворни кода

Support IPv6 for parent proxy

Parent proxy can be on IPv6 network (except SOCKS4).
z3APA3A пре 11 година
родитељ
комит
8a6632f0d1
7 измењених фајлова са 58 додато и 54 уклоњено
  1. 5 4
      src/3proxy.c
  2. 28 30
      src/auth.c
  3. 7 3
      src/common.c
  4. 7 12
      src/datatypes.c
  5. 2 2
      src/socks.c
  6. 8 2
      src/structures.h
  7. 1 1
      src/udppm.c

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

+ 28 - 30
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(&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));

+ 7 - 3
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(&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)); 
 	}

+ 7 - 12
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"}
 };
 

+ 2 - 2
src/socks.c

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

+ 8 - 2
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;

+ 1 - 1
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(&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);
  }