diff --git a/src/common.c b/src/common.c index 55af748..ea5e472 100644 --- a/src/common.c +++ b/src/common.c @@ -9,6 +9,39 @@ #include "proxy.h" +/* returns 0 on success, 1 if atyp is not supported for family, 2 if the + address is null. The address is set in both the 0 and the 2 case. */ +int socks5_setaddr(int family, int atyp, const unsigned char *addr, PROXYSOCKADDRTYPE *sa){ + int i, len = 4; + + memset(sa, 0, sizeof(*sa)); + if(atyp == 4){ +#ifdef NOIPV6 + return 1; +#else + if(family == 4) return 1; + len = 16; + *SAFAMILY(sa) = AF_INET6; + memcpy(SAADDR(sa), addr, 16); +#endif + } +#ifndef NOIPV6 + else if(family == 6){ + unsigned char prefix[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255}; + + *SAFAMILY(sa) = AF_INET6; + memcpy(SAADDR(sa), prefix, 12); + memcpy(12 + (unsigned char *)SAADDR(sa), addr, 4); + } +#endif + else { + *SAFAMILY(sa) = AF_INET; + memcpy(SAADDR(sa), addr, 4); + } + for(i = 0; i < len && !addr[i]; i++); + return (i == len)? 2 : 0; +} + #ifdef __linux__ #include diff --git a/src/proxy.h b/src/proxy.h index 5702012..7a65f75 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -205,6 +205,7 @@ extern int timeouts[12]; int sockmap(struct clientparam * param, int timeo, int usesplice); int udpsockmap(struct clientparam * param, int timeo); int udpbind(struct clientparam * param); +int socks5_setaddr(int family, int atyp, const unsigned char *addr, PROXYSOCKADDRTYPE *sa); #ifdef __linux__ int switch_ns(struct srvparam *srv, int target_fd); #endif diff --git a/src/proxymain.c b/src/proxymain.c index b050930..a09bcaa 100644 --- a/src/proxymain.c +++ b/src/proxymain.c @@ -505,8 +505,8 @@ int MODULEMAINFUNC (int argc, char** argv){ } break; case 'N': - if(argv[i][3] == 'e') getip46(46, (unsigned char *)argv[i]+3, (struct sockaddr *)&srv.extNat); - else if(argv[i][3] == 'i') getip46(46, (unsigned char *)argv[i]+3, (struct sockaddr *)&srv.intNat); + if(argv[i][2] == 'e') getip46(46, (unsigned char *)argv[i]+3, (struct sockaddr *)&srv.extNat); + else if(argv[i][2] == 'i') getip46(46, (unsigned char *)argv[i]+3, (struct sockaddr *)&srv.intNat); else getip46(46, (unsigned char *)argv[i]+2, (struct sockaddr *)&srv.extNat); break; case 'n': diff --git a/src/socks.c b/src/socks.c index f60b0dc..76e77d3 100644 --- a/src/socks.c +++ b/src/socks.c @@ -107,38 +107,20 @@ void * sockschild(struct clientparam* param) { } size = 4; - *SAFAMILY(¶m->sinsr) = *SAFAMILY(¶m->req) = AF_INET; switch(c) { #ifndef NOIPV6 case 4: - if(param->srv->family == 4) RETURN(997); size = 16; - *SAFAMILY(¶m->sinsr) = *SAFAMILY(¶m->req) = AF_INET6; #endif case 1: for (i = 0; isrv->family==6){ - char prefix[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255}; - *SAFAMILY(¶m->sinsr) = *SAFAMILY(¶m->req) = AF_INET6; - memcpy(SAADDR(¶m->sinsr), prefix, 12); - memcpy(12 + (char *)SAADDR(¶m->sinsr), buf, 4); - memcpy(SAADDR(¶m->req), prefix, 12); - memcpy(12 + (char *)SAADDR(¶m->req), buf, 4); - } - else { -#endif - memcpy(SAADDR(¶m->sinsr), buf, size); - memcpy(SAADDR(¶m->req), buf, size); -#ifndef NOIPV6 - } -#endif - if(command == 1 && SAISNULL(¶m->req)) { - RETURN(431); - } + res = socks5_setaddr(param->srv->family, c, buf, ¶m->req); + if(res == 1) {RETURN(997);} + if(res == 2 && command == 1) {RETURN(431);} + param->sinsr = param->req; myinet_ntop(*SAFAMILY(¶m->sinsr), SAADDR(¶m->sinsr), (char *)buf, 64); break; case 3: @@ -285,7 +267,7 @@ CLEANRET: sasize = sizeof(sin); if(command != 3 && param->remsock != INVALID_SOCKET) param->srv->so._getsockname(param->sostate, param->remsock, (struct sockaddr *)&sin, &sasize); - if(!SAISNULL(¶m->srv->extNat)){ + if(command != 3 && !SAISNULL(¶m->srv->extNat)){ uint16_t port; port = *SAPORT(&sin); sin = param->srv->extNat; @@ -293,7 +275,7 @@ CLEANRET: } else { param->srv->so._getsockname(param->sostate, param->clisock, (struct sockaddr *)&sin, &sasize); - if(!SAISNULL(¶m->srv->intNat)){ + if(command == 3 && !SAISNULL(¶m->srv->intNat)){ uint16_t port; port = *SAPORT(&sin); sin = param->srv->intNat; diff --git a/src/udpsockmap.c b/src/udpsockmap.c index d3a0f45..46048f7 100644 --- a/src/udpsockmap.c +++ b/src/udpsockmap.c @@ -257,16 +257,16 @@ int udpsockmap(struct clientparam *param, int timeo) memset(&dst, 0, sizeof(dst)); switch (base[3]) { case 1: - *SAFAMILY(&dst) = AF_INET; - memcpy(SAADDR(&dst), base + 4, 4); + if (socks5_setaddr(param->srv->family, 1, base + 4, &dst)) continue; i = 8; break; +#ifndef NOIPV6 case 4: if (len < 22) return 484; - *SAFAMILY(&dst) = AF_INET6; - memcpy(SAADDR(&dst), base + 4, 16); + if (socks5_setaddr(param->srv->family, 4, base + 4, &dst)) continue; i = 20; break; +#endif case 3: { int sz = base[4]; if (len < 7 + sz) return 485; @@ -309,7 +309,8 @@ int udpsockmap(struct clientparam *param, int timeo) if (!nhops) param->sinsr = dst; if (!havedst) reconnect = 1; - else if ((param->srv->udpauth & 2) && !param->dstindep) { + else if (!nhops && *SAFAMILY(&dst) != *SAFAMILY(¶m->sinsl)) reconnect = 1; + if (havedst && (param->srv->udpauth & 2) && !param->dstindep) { param->preauth = 2; ares = (*param->srv->authfunc)(param); param->preauth = 0;