void * sockschild(struct clientparam* param) { int res; unsigned i=0; SOCKET s; unsigned size; SASIZETYPE sasize; unsigned char * buf=NULL; unsigned char c; unsigned char command=0; struct pollfd fds[3]; int ver=0; int havepass = 0; struct sockaddr_in sin; int len; param->req.sin_addr.s_addr = 0; param->service = S_SOCKS; if(!(buf = myalloc(BUFSIZE))) {RETURN(21);} memset(buf, 0, BUFSIZE); if ((ver = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5 && ver != 4) { RETURN(401); } /* version */ param->service = ver; if(ver == 5){ if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} /* nmethods */ for (; i; i--) { if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(442);} if (res == 2 && !param->srv->nouser) { havepass = res; } } buf[0] = 5; buf[1] = havepass; if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(402);} if (havepass) { if (((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0))) != 1) { RETURN(412); } if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(443);} if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(444);}; buf[i] = 0; if(!param->username)param->username = (unsigned char *)mystrdup((char *)buf); if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(445);} if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(446);}; buf[i] = 0; if(!param->password)param->password = (unsigned char *)mystrdup((char *)buf); buf[0] = 1; buf[1] = 0; if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(402);} } if ((c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5) { RETURN(421); } /* version */ } if( (command = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) < 1 || command > 3){command = 0; RETURN(407);} /* command */ if(ver == 5){ if (sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0) == EOF) {RETURN(447);} /* reserved */ c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0); /* atype */ } else { if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(448);} buf[0] = (unsigned char) res; if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(449);} buf[1] = (unsigned char) res; param->sins.sin_port = param->req.sin_port = *(unsigned short*)buf; c = 1; } switch(c) { case 1: for (i = 0; i<4; i++){ if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(450);} buf[i] = (unsigned char)res; } param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = *(unsigned long *)buf; if(command==1 && !param->req.sin_addr.s_addr) { RETURN(422); } myinet_ntoa(param->sins.sin_addr, (char *)buf); break; case 3: if ((size = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);} /* nmethods */ for (i=0; i<size; i++){ /* size < 256 */ if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(452);} buf[i] = (unsigned char)res; } buf[i] = 0; param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = getip(buf); if(command==1 && !param->req.sin_addr.s_addr) { RETURN(100); } break; default: RETURN(998); } if(param->hostname)myfree(param->hostname); param->hostname = (unsigned char *)mystrdup((char *)buf); if (ver == 5) { if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(453);} buf[0] = (unsigned char) res; if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(454);} buf[1] = (unsigned char) res; param->sins.sin_port = param->req.sin_port = *(unsigned short*)buf; } else { sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]); buf[127] = 0; if(!param->srv->nouser && *buf && !param->username)param->username = (unsigned char *)mystrdup((char *)buf); if(param->sins.sin_addr.s_addr && ntohl(param->sins.sin_addr.s_addr)<256){ param->service = S_SOCKS45; sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]); buf[127] = 0; if(param->hostname)myfree(param->hostname); param->hostname = (unsigned char *)mystrdup((char *)buf); param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = getip(buf); } } if(command == 1 && !param->req.sin_port) {RETURN(424);} param->sins.sin_family = AF_INET; switch(command) { case 1: param->operation = CONNECT; break; case 2: param->sins.sin_addr.s_addr = param->extip; param->sins.sin_port = param->extport?param->extport:param->req.sin_port; if ((param->remsock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN (11);} param->operation = BIND; break; case 3: param->sins.sin_port = param->extport?param->extport:param->req.sin_port; param->sins.sin_addr.s_addr = param->extip; if ((param->remsock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);} param->operation = UDPASSOC; break; default: RETURN(997); } if((res = (*param->srv->authfunc)(param))) {RETURN(res);} if(command > 1) { if(bind(param->remsock,(struct sockaddr *)¶m->sins,sizeof(param->sins))) { param->sins.sin_port = 0; if(bind(param->remsock,(struct sockaddr *)¶m->sins,sizeof(param->sins)))RETURN (12); #if SOCKSTRACE > 0 fprintf(stderr, "%s:%hu binded to communicate with server\n", inet_ntoa(param->sins.sin_addr), ntohs(param->sins.sin_port) ); fflush(stderr); #endif } sasize = sizeof(struct sockaddr_in); getsockname(param->remsock, (struct sockaddr *)¶m->sins, &sasize); if(command == 3) { param->ctrlsock = param->clisock; param->clisock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if(param->clisock == INVALID_SOCKET) {RETURN(11);} sin.sin_family = AF_INET; sin.sin_addr.s_addr = param->srv->intip; sin.sin_port = htons(0); if(bind(param->clisock,(struct sockaddr *)&sin,sizeof(struct sockaddr_in))) {RETURN (12);} #if SOCKSTRACE > 0 fprintf(stderr, "%s:%hu binded to communicate with client\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port) ); fflush(stderr); #endif } } param->res = 0; CLEANRET: if(param->clisock != INVALID_SOCKET){ sasize = sizeof(struct sockaddr_in); if(command != 3) getsockname(param->remsock, (struct sockaddr *)&sin, &sasize); else getsockname(param->clisock, (struct sockaddr *)&sin, &sasize); #if SOCKSTRACE > 0 fprintf(stderr, "Sending confirmation to client with code %d for %s with %s:%hu\n", param->res, commands[command], inet_ntoa(sin.sin_addr), ntohs(sin.sin_port) ); fflush(stderr); #endif if(ver == 5){ buf[0] = 5; buf[1] = param->res%10; buf[2] = 0; buf[3] = 1; memcpy(buf+4, &sin.sin_addr.s_addr, 4); memcpy(buf+8, &sin.sin_port, 2); socksend((command == 3)?param->ctrlsock:param->clisock, buf, 10, conf.timeouts[STRING_S]); } else{ buf[0] = 0; buf[1] = 90 + (param->res%10); memcpy(buf+2, &sin.sin_port, 2); memcpy(buf+4, &sin.sin_addr.s_addr, 4); socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]); } if (param->res == 0) { switch(command) { case 1: if(param->redirectfunc){ if(buf)myfree(buf); return (*param->redirectfunc)(param); } param->res = sockmap(param, conf.timeouts[CONNECTION_L]); break; case 2: listen (param->remsock, 1); fds[0].fd = param->remsock; fds[1].fd = param->clisock; fds[0].events = fds[1].events = POLLIN; res = poll(fds, 2, conf.timeouts[(param->req.sin_addr.s_addr)?CONNECTION_S:CONNECTION_L] * 1000); if (res < 1 || fds[1].revents) { res = 460; break; } sasize = sizeof(param->sins); s = accept(param->remsock, (struct sockaddr *)¶m->sins, &sasize); closesocket(param->remsock); param->remsock = s; if(s == INVALID_SOCKET) { param->res = 462; break; } if(param->req.sin_addr.s_addr && param->req.sin_addr.s_addr != param->sins.sin_addr.s_addr) { param->res = 470; break; } #if SOCKSTRACE > 0 fprintf(stderr, "Sending incoming connection to client with code %d for %s with %s:%hu\n", param->res, commands[command], inet_ntoa(param->sins.sin_addr), ntohs(param->sins.sin_port) ); fflush(stderr); #endif if(ver == 5){ memcpy (buf+4, ¶m->sins.sin_addr, 4); memcpy (buf+8, ¶m->sins.sin_port, 2); socksend(param->clisock, buf, 10, conf.timeouts[STRING_S]); } else { memcpy (buf+2, ¶m->sins.sin_port, 2); memcpy (buf+4, ¶m->sins.sin_addr, 4); socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]); } param->res = sockmap(param, conf.timeouts[CONNECTION_S]); break; case 3: param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr; param->sins.sin_port = param->req.sin_port; myfree(buf); if(!(buf = myalloc(LARGEBUFSIZE))) {RETURN(21);} for(;;){ fds[0].fd = param->remsock; fds[1].fd = param->clisock; fds[2].fd = param->ctrlsock; fds[2].events = fds[1].events = fds[0].events = POLLIN; res = poll(fds, 3, conf.timeouts[CONNECTION_L]*1000); if(res <= 0) { param->res = 463; break; } if (fds[2].revents) { param->res = 0; break; } if (fds[1].revents) { sasize = sizeof(struct sockaddr_in); if((len = recvfrom(param->clisock, buf, 65535, 0, (struct sockaddr *)&sin, &sasize)) <= 10) { param->res = 464; break; } if(sin.sin_addr.s_addr != param->sinc.sin_addr.s_addr){ param->res = 465; break; } if(buf[0] || buf[1] || buf[2]) { param->res = 466; break; } switch(buf[3]) { case 1: i = 8; memcpy(¶m->sins.sin_addr.s_addr, buf+4, 4); break; case 3: size = buf[4]; for (i=4; size; i++, size--){ buf[i] = buf[i+1]; } buf[i++] = 0; param->sins.sin_addr.s_addr = getip(buf+4); break; default: RETURN(996); } memcpy(¶m->sins.sin_port, buf+i, 2); i+=2; sasize = sizeof(param->sins); if(len > (int)i){ if(socksendto(param->remsock, ¶m->sins, buf+i, len - i, conf.timeouts[SINGLEBYTE_L]*1000) <= 0){ param->res = 467; break; } param->statscli+=(len - i); param->nwrites++; #if SOCKSTRACE > 1 fprintf(stderr, "UDP packet relayed from client to %s:%hu size %d, header %d\n", inet_ntoa(param->sins.sin_addr), ntohs(param->sins.sin_port), (len - i), i ); fprintf(stderr, "client address is assumed to be %s:%hu\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port) ); fflush(stderr); #endif } } if (fds[0].revents) { struct sockaddr_in tsin; sasize = sizeof(tsin); buf[0]=buf[1]=buf[2]=0; buf[3]=1; if((len = recvfrom(param->remsock, buf+10, 65535 - 10, 0, (struct sockaddr *)&tsin, &sasize)) <= 0) { param->res = 468; break; } param->statssrv+=len; param->nreads++; memcpy(buf+4, &tsin.sin_addr.s_addr, 4); memcpy(buf+8, &tsin.sin_port, 2); sasize = sizeof(param->sins); if(socksendto(param->clisock, &sin, buf, len + 10, conf.timeouts[SINGLEBYTE_L]*1000) <=0){ param->res = 469; break; } #if SOCKSTRACE > 1 fprintf(stderr, "UDP packet relayed to client from %s:%hu size %d\n", inet_ntoa(tsin.sin_addr), ntohs(tsin.sin_port), len ); fflush(stderr); #endif } } break; default: param->res = 417; break; } } } if(command > 3) command = 0; if(buf){ sprintf((char *)buf, "%s ", commands[command]); if(param->hostname){ sprintf((char *)buf + strlen((char *)buf), "%.265s", param->hostname); } else myinet_ntoa(param->req.sin_addr, (char *)buf+strlen((char *)buf)); sprintf((char *)buf+strlen((char *)buf), ":%hu", ntohs(param->req.sin_port)); (*param->srv->logfunc)(param, buf); myfree(buf); } freeparam(param); return (NULL); }
void * sockschild(struct clientparam* param) { int res; unsigned i=0; SOCKET s; unsigned size; SASIZETYPE sasize; unsigned short port = 0; unsigned char * buf=NULL; unsigned char c; unsigned char command=0; struct pollfd fds[3]; int ver=0; int havepass = 0; #ifndef NOIPV6 struct sockaddr_in6 sin = {AF_INET6}; #else struct sockaddr_in sin = {AF_INET}; #endif int len; param->service = S_SOCKS; if(!(buf = myalloc(BUFSIZE))) {RETURN(21);} memset(buf, 0, BUFSIZE); if ((ver = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5 && ver != 4) { RETURN(401); } /* version */ param->service = ver; if(ver == 5){ if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} /* nmethods */ for (; i; i--) { if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} if (res == 2 && param->srv->needuser) { havepass = res; } } buf[0] = 5; buf[1] = (param->srv->needuser > 1 && !havepass)? 255 : havepass; if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(401);} if (param->srv->needuser > 1 && !havepass) RETURN(4); if (havepass) { if (((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0))) != 1) { RETURN(412); } if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);} if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(441);}; buf[i] = 0; if(!param->username)param->username = (unsigned char *)mystrdup((char *)buf); if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(445);} if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(441);}; buf[i] = 0; if(!param->password)param->password = (unsigned char *)mystrdup((char *)buf); buf[0] = 1; buf[1] = 0; if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(481);} } if ((c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5) { RETURN(421); } /* version */ } if( (command = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) < 1 || command > 3){command = 0; RETURN(407);} /* command */ if(ver == 5){ if (sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0) == EOF) {RETURN(447);} /* reserved */ c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0); /* atype */ } else { if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} buf[0] = (unsigned char) res; if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} buf[1] = (unsigned char) res; port = *(unsigned short*)buf; c = 1; } 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; i<size; i++){ if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} buf[i] = (unsigned char)res; } #ifndef NOIPV6 if (c == 1 && param->srv->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(SAISNULL(¶m->req)) { RETURN(421); } myinet_ntop(*SAFAMILY(¶m->sinsr), SAADDR(¶m->sinsr), (char *)buf, 64); break; case 3: if ((size = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);} /* nmethods */ for (i=0; i<size; i++){ /* size < 256 */ if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);} buf[i] = (unsigned char)res; } buf[i] = 0; if(!getip46(param->srv->family, buf, (struct sockaddr *) ¶m->req)) RETURN(100); memcpy(¶m->sinsr, ¶m->req, sizeof(param->req)); break; default: RETURN(997); } if(param->hostname)myfree(param->hostname); param->hostname = (unsigned char *)mystrdup((char *)buf); if (ver == 5) { if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} buf[0] = (unsigned char) res; if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} buf[1] = (unsigned char) res; port = *(unsigned short*)buf; } else { sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]); buf[127] = 0; if(param->srv->needuser && *buf && !param->username)param->username = (unsigned char *)mystrdup((char *)buf); if(!memcmp(SAADDR(¶m->req), "\0\0\0", 3)){ param->service = S_SOCKS45; sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]); buf[127] = 0; if(param->hostname)myfree(param->hostname); param->hostname = (unsigned char *)mystrdup((char *)buf); if(!getip46(param->srv->family, buf, (struct sockaddr *) ¶m->req)) RETURN(100); memcpy(¶m->sinsr, ¶m->req, sizeof(¶m->req)); } } *SAPORT(¶m->sinsr) = *SAPORT(¶m->req) = port; if(command == 1 && !*SAPORT(¶m->sinsr)) {RETURN(421);} switch(command) { case 1: param->operation = CONNECT; break; case 2: case 3: #ifndef NOIPV6 memcpy(¶m->sinsl, *SAFAMILY(¶m->req)==AF_INET6? (struct sockaddr *)¶m->srv->extsa6:(struct sockaddr *)¶m->srv->extsa, SASIZE(¶m->req)); #else memcpy(¶m->sinsl, ¶m->srv->extsa, SASIZE(¶m->req)); #endif if ((param->remsock=so._socket(SASOCK(¶m->req), command == 2? SOCK_STREAM:SOCK_DGRAM, command == 2?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);} param->operation = command == 2?BIND:UDPASSOC; break; default: RETURN(997); } if((res = (*param->srv->authfunc)(param))) { RETURN(res); } if(command > 1) { if(so._bind(param->remsock,(struct sockaddr *)¶m->sinsl,SASIZE(¶m->sinsl))) { *SAPORT(¶m->sinsl) = 0; if(so._bind(param->remsock,(struct sockaddr *)¶m->sinsl,SASIZE(¶m->sinsl)))RETURN (12); #if SOCKSTRACE > 0 fprintf(stderr, "%hu binded to communicate with server\n", *SAPORT(¶m->sins)); fflush(stderr); #endif } sasize = SASIZE(¶m->sinsl); so._getsockname(param->remsock, (struct sockaddr *)¶m->sinsl, &sasize); if(command == 3) { param->ctrlsock = param->clisock; param->clisock = so._socket(SASOCK(¶m->sincr), SOCK_DGRAM, IPPROTO_UDP); if(param->clisock == INVALID_SOCKET) {RETURN(11);} memcpy(&sin, ¶m->sincl, sizeof(&sin)); *SAPORT(&sin) = 0; if(so._bind(param->clisock,(struct sockaddr *)&sin,sizeof(sin))) {RETURN (12);} #if SOCKSTRACE > 0 fprintf(stderr, "%hu binded to communicate with client\n", ntohs(*SAPORT(&sin)) ); fflush(stderr); #endif } } param->res = 0; CLEANRET: if(param->clisock != INVALID_SOCKET){ int repcode; sasize = sizeof(sin); if(command != 3) so._getsockname(param->remsock, (struct sockaddr *)&sin, &sasize); else so._getsockname(param->clisock, (struct sockaddr *)&sin, &sasize); #if SOCKSTRACE > 0 fprintf(stderr, "Sending confirmation to client with code %d for %s with %s:%hu\n", param->res, commands[command], inet_ntoa(sin.sin_addr), ntohs(sin.sin_port) ); fflush(stderr); #endif if(!param->res) repcode = 0; else if(param->res <= 10) repcode = 2; else if (param->res < 20) repcode = 5; else if (param->res < 30) repcode = 1; else if (param->res < 100) repcode = 4; else repcode = param->res%10; if(ver == 5){ buf[0] = 5; buf[1] = repcode; buf[2] = 0; buf[3] = (*SAFAMILY(&sin) == AF_INET)?1:4; memcpy(buf+4, SAADDR(&sin), SAADDRLEN(&sin)); memcpy(buf+4+SAADDRLEN(&sin), SAPORT(&sin), 2); socksend((command == 3)?param->ctrlsock:param->clisock, buf, 6+SAADDRLEN(&sin), conf.timeouts[STRING_S]); } else{ buf[0] = 0; buf[1] = 90 + !!(repcode); memcpy(buf+2, SAPORT(&sin), 2); memcpy(buf+4, SAADDR(&sin), 4); socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]); } if (param->res == 0) { switch(command) { case 1: if(param->redirectfunc){ if(buf)myfree(buf); return (*param->redirectfunc)(param); } param->res = sockmap(param, conf.timeouts[CONNECTION_L]); break; case 2: so._listen (param->remsock, 1); fds[0].fd = param->remsock; fds[1].fd = param->clisock; fds[0].events = fds[1].events = POLLIN; res = so._poll(fds, 2, conf.timeouts[CONNECTION_L] * 1000); if (res < 1 || fds[1].revents) { res = 460; break; } sasize = sizeof(param->sinsr); s = so._accept(param->remsock, (struct sockaddr *)¶m->sinsr, &sasize); so._closesocket(param->remsock); param->remsock = s; if(s == INVALID_SOCKET) { param->res = 462; break; } if(SAISNULL(¶m->req) && memcmp(SAADDR(¶m->req),SAADDR(¶m->sinsr),SAADDRLEN(¶m->req))) { param->res = 470; break; } #if SOCKSTRACE > 0 fprintf(stderr, "Sending incoming connection to client with code %d for %s with %hu\n", param->res, commands[command], *SAPORT(param->sins); ); fflush(stderr); #endif if(ver == 5){ buf[3] = (*SAFAMILY(¶m->sinsr) == AF_INET)?1:4; memcpy(buf+4, SAADDR(¶m->sinsr), SAADDRLEN(¶m->sinsr)); memcpy(buf+4+SAADDRLEN(¶m->sinsr), SAPORT(¶m->sinsr), 2); socksend(param->clisock, buf, 6+SAADDRLEN(¶m->sinsr), conf.timeouts[STRING_S]); } else { memcpy (buf+2, SAPORT(¶m->sinsr), 2); memcpy (buf+4, SAADDR(¶m->sinsr), 4); socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]); } param->res = sockmap(param, conf.timeouts[CONNECTION_S]); break; case 3: memcpy(¶m->sinsr, ¶m->req, sizeof(param->sinsr)); myfree(buf); if(!(buf = myalloc(LARGEBUFSIZE))) {RETURN(21);} for(;;){ fds[0].fd = param->remsock; fds[1].fd = param->clisock; fds[2].fd = param->ctrlsock; fds[2].events = fds[1].events = fds[0].events = POLLIN; res = so._poll(fds, 3, conf.timeouts[CONNECTION_L]*1000); if(res <= 0) { param->res = 463; break; } if (fds[2].revents) { param->res = 0; break; } if (fds[1].revents) { sasize = sizeof(sin); if((len = so._recvfrom(param->clisock, buf, 65535, 0, (struct sockaddr *)&sin, &sasize)) <= 10) { param->res = 464; break; } if(SAADDRLEN(&sin) != SAADDRLEN(¶m->sincr) || memcmp(SAADDR(&sin), SAADDR(¶m->sincr), SAADDRLEN(&sin))){ param->res = 465; break; } if(buf[0] || buf[1] || buf[2]) { param->res = 466; break; } size = 4; switch(buf[3]) { case 4: size = 16; case 1: i = 4+size; memcpy(SAADDR(¶m->sinsr), buf+4, size); *SAFAMILY(¶m->sinsr) = (size == 4)?AF_INET:AF_INET6; break; case 3: size = buf[4]; for (i=4; size; i++, size--){ buf[i] = buf[i+1]; } buf[i++] = 0; if(!getip46(param->srv->family, buf, (struct sockaddr *) ¶m->sinsr)) RETURN(100); break; default: RETURN(997); } memcpy(SAPORT(¶m->sinsr), buf+i, 2); i+=2; sasize = sizeof(param->sinsr); if(len > (int)i){ if(socksendto(param->remsock, (struct sockaddr *)¶m->sinsr, buf+i, len - i, conf.timeouts[SINGLEBYTE_L]*1000) <= 0){ param->res = 467; break; } param->statscli64+=(len - i); param->nwrites++; #if SOCKSTRACE > 1 fprintf(stderr, "UDP packet relayed from client to %s:%hu size %d, header %d\n", inet_ntoa(param->sins.sin_addr), ntohs(param->sins.sin_port), (len - i), i ); fprintf(stderr, "client address is assumed to be %s:%hu\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port) ); fflush(stderr); #endif } } if (fds[0].revents) { sasize = sizeof(param->sinsr); buf[0]=buf[1]=buf[2]=0; buf[3]=(*SAFAMILY(¶m->sinsl) == AF_INET)?1:4; if((len = so._recvfrom(param->remsock, buf+6+SAADDRLEN(¶m->sinsl), 65535 - 10, 0, (struct sockaddr *)¶m->sinsr, &sasize)) <= 0) { param->res = 468; break; } param->statssrv64+=len; param->nreads++; memcpy(buf+4, SAADDR(¶m->sinsr), SAADDRLEN(¶m->sinsr)); memcpy(buf+4+SAADDRLEN(¶m->sinsr), SAPORT(¶m->sinsr), 2); sasize = sizeof(sin); if(socksendto(param->clisock, (struct sockaddr *)&sin, buf, len + 6 + SAADDRLEN(¶m->sinsr), conf.timeouts[SINGLEBYTE_L]*1000) <=0){ param->res = 469; break; } #if SOCKSTRACE > 1 fprintf(stderr, "UDP packet relayed to client from %hu size %d\n", ntohs(*SAPORT(¶m->sinsr)), len ); fflush(stderr); #endif } } break; default: param->res = 417; break; } }
void * dnsprchild(void * data) { #define param ((struct clientparam*)data) unsigned long ip = 0; unsigned char *buf, *s1, *s2; char * host = NULL; unsigned char c; SASIZETYPE size; int res, i; int len; unsigned type=0; unsigned ttl; #ifdef _WIN32 unsigned long ul; #endif if(!(buf = myalloc(BUFSIZE))){ param->srvfds->events = POLLIN; RETURN (21); } size = sizeof(struct sockaddr_in); i = recvfrom(param->srvsock, buf, BUFSIZE, 0, (struct sockaddr *)¶m->sinc, &size); #ifdef _WIN32 if((param->clisock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { RETURN(818); } if(setsockopt(param->clisock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&ul, sizeof(int))) {RETURN(820);}; ioctlsocket(param->clisock, FIONBIO, &ul); size = sizeof(struct sockaddr_in); if(getsockname(param->srvsock, (struct sockaddr *)¶m->sins, &size)) {RETURN(21);}; if(bind(param->clisock,(struct sockaddr *)¶m->sins,sizeof(struct sockaddr_in))) { RETURN(822); } #else param->clisock = param->srvsock; #endif param->srvfds->events = POLLIN; if(i < 0) { RETURN(813); } buf[BUFSIZE - 1] = 0; if(i<=13 || i>1000){ RETURN (814); } param->operation = DNSRESOLVE; if((res = (*param->authfunc)(param))) {RETURN(res);} if(buf[4]!=0 || buf[5]!=1) RETURN(816); for(len = 12; len<i; len+=(c+1)){ c = buf[len]; if(!c)break; buf[len] = '.'; } if(len > (i-4)) {RETURN(817);} host = mystrdup((char *)buf+13); if(!host) {RETURN(21);} for(s2 = buf + 12; (s1 = (unsigned char *)strchr((char *)s2 + 1, '.')); s2 = s1)*s2 = (unsigned char)((s1 - s2) - 1); *s2 = (len - (s2 - buf)) - 1; type = ((unsigned)buf[len+1])*256 + (unsigned)buf[len+2]; if(type==1){ ip = udpresolve((unsigned char *)host, &ttl, param); } len+=5; if(ip){ buf[2] = 0x85; buf[3] = 0x80; buf[6] = 0; buf[7] = 1; buf[8] = buf[9] = buf[10] = buf[11] = 0; memset(buf+len, 0, 16); buf[len] = 0xc0; buf[len+1] = 0x0c; buf[len+3] = 1; buf[len+5] = 1; ttl = htonl(ttl); memcpy(buf + len + 6, &ttl, 4); buf[len+11] = 4; memcpy(buf+len+12,(void *)&ip,4); len+=16; } if(type == 0x0c) { unsigned a, b, c, d; sscanf(host, "%u.%u.%u.%u", &a, &b, &c, &d); ip = htonl((d<<24) ^ (c<<16) ^ (b<<8) ^ a); if(ip == param->intip){ buf[2] = 0x85; buf[3] = 0x80; buf[6] = 0; buf[7] = 1; buf[8] = buf[9] = buf[10] = buf[11] = 0; memset(buf+len, 0, 20); buf[len] = 0xc0; buf[len+1] = 0x0c; buf[len+3] = 0x0c; buf[len+5] = 1; ttl = htonl(3600); memcpy(buf + len + 6, &ttl, 4); buf[len+11] = 7; buf[len+12] = 6; memcpy(buf+len+13,(void *)"3proxy",6); len+=20; } else ip = 0; } if(!ip && nservers[0] && type!=1){ if((param->remsock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { RETURN(818); } #ifdef _WIN32 ioctlsocket(param->remsock, FIONBIO, &ul); #else fcntl(param->remsock,F_SETFL,O_NONBLOCK); #endif param->sins.sin_family = AF_INET; param->sins.sin_port = htons(0); param->sins.sin_addr.s_addr = htonl(0); if(bind(param->remsock,(struct sockaddr *)¶m->sins,sizeof(struct sockaddr_in))) { RETURN(819); } param->sins.sin_addr.s_addr = nservers[0]; param->sins.sin_port = htons(53); if(socksendto(param->remsock, ¶m->sins, buf, i, conf.timeouts[SINGLEBYTE_L]*1000) != i){ RETURN(820); } param->statscli += i; len = sockrecvfrom(param->remsock, ¶m->sins, buf, BUFSIZE, 15000); if(len <= 13) { RETURN(821); } param->statssrv += len; if(buf[6] || buf[7]){ if(socksendto(param->clisock, ¶m->sinc, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){ RETURN(822); } RETURN(0); } } if(!ip) { buf[2] = 0x85; buf[3] = 0x83; } usleep(SLEEPTIME); res = socksendto(param->clisock, ¶m->sinc, buf, len, conf.timeouts[SINGLEBYTE_L]*1000); if(res != len){RETURN(819);} if(!ip) {RETURN(888);} CLEANRET: if(param->res!=813){ sprintf((char *)buf, "%04x/%s(%u.%u.%u.%u) ", (unsigned)type, host, (unsigned)(ntohl(ip)&0xff000000)>>24, (unsigned)(ntohl(ip)&0x00ff0000)>>16, (unsigned)(ntohl(ip)&0x0000ff00)>>8, (unsigned)(ntohl(ip)&0x000000ff) ); (*param->logfunc)(param, buf); }
int sockmap(struct clientparam * param, int timeo){ int res=0; uint64_t sent=0, received=0; SASIZETYPE sasize; struct pollfd fds[2]; int sleeptime = 0, stop = 0; unsigned minsize; unsigned bufsize; FILTER_ACTION action; int retcode = 0; bufsize = BUFSIZE; minsize = (param->service == S_UDPPM || param->service == S_TCPPM)? bufsize - 1 : (bufsize>>2); fds[0].fd = param->clisock; fds[1].fd = param->remsock; #if DEBUGLEVEL > 2 (*param->srv->logfunc)(param, "Starting sockets mapping"); #endif if(!param->waitclient64){ if(!param->srvbuf && (!(param->srvbuf=myalloc(bufsize)) || !(param->srvbufsize = bufsize))){ return (21); } } if(!param->waitserver64){ if(!param->clibuf && (!(param->clibuf=myalloc(bufsize)) || !(param->clibufsize = bufsize))){ return (21); } } action = handlepredatflt(param); if(action == HANDLED){ return 0; } if(action != PASS) return 19; if(!param->nolongdatfilter){ if(param->cliinbuf > param->clioffset){ action = handledatfltcli(param, ¶m->clibuf, ¶m->clibufsize, param->clioffset, ¶m->cliinbuf); if(action == HANDLED){ return 0; } if(action != PASS) return 19; } if(param->srvinbuf > param->srvoffset){ action = handledatfltsrv(param, ¶m->srvbuf, ¶m->srvbufsize, param->srvoffset, ¶m->srvinbuf); if(action == HANDLED){ return 0; } if(action != PASS) return 19; } } while (!stop&&!conf.timetoexit){ sasize = sizeof(struct sockaddr_in); if((param->maxtrafin64 && param->statssrv64 >= param->maxtrafin64) || (param->maxtrafout64 && param->statscli64 >= param->maxtrafout64)){ return (10); } if((param->srv->logdumpsrv && (param->statssrv64 > param->srv->logdumpsrv)) || (param->srv->logdumpcli && (param->statscli64 > param->srv->logdumpcli))) (*param->srv->logfunc)(param, NULL); fds[0].events = fds[1].events = 0; if(param->srvinbuf > param->srvoffset && !param->waitclient64) { #if DEBUGLEVEL > 2 (*param->srv->logfunc)(param, "will send to client"); #endif fds[0].events |= POLLOUT; } if((param->srvbufsize - param->srvinbuf) > minsize && !param->waitclient64 && (!param->waitserver64 ||(received + param->srvinbuf - param->srvoffset < param->waitserver64))) { #if DEBUGLEVEL > 2 (*param->srv->logfunc)(param, "Will recv from server"); #endif fds[1].events |= POLLIN; } if(param->cliinbuf > param->clioffset && !param->waitserver64) { #if DEBUGLEVEL > 2 (*param->srv->logfunc)(param, "Will send to server"); #endif fds[1].events |= POLLOUT; } if((param->clibufsize - param->cliinbuf) > minsize && !param->waitserver64 &&(!param->srv->singlepacket || param->service != S_UDPPM) ) { #if DEBUGLEVEL > 2 (*param->srv->logfunc)(param, "Will recv from client"); #endif fds[0].events |= POLLIN; } if(!fds[0].events && !fds[1].events) return 666; res = so._poll(fds, 2, timeo*1000); if(res < 0){ if(errno != EAGAIN && errno != EINTR) return 91; if(errno == EINTR) usleep(SLEEPTIME); continue; } if(res < 1){ return 92; } if( (fds[0].revents & (POLLERR|POLLHUP|POLLNVAL)) && !(fds[0].revents & POLLIN)) { fds[0].revents = 0; stop = 1; retcode = 90; } if( (fds[1].revents & (POLLERR|POLLHUP|POLLNVAL)) && !(fds[1].revents & POLLIN)){ fds[1].revents = 0; stop = 1; retcode = 90; } if((fds[0].revents & POLLOUT)){ #if DEBUGLEVEL > 2 (*param->srv->logfunc)(param, "send to client"); #endif if(param->bandlimfunc) { sleeptime = (*param->bandlimfunc)(param, param->srvinbuf - param->srvoffset, 0); } res = so._sendto(param->clisock, param->srvbuf + param->srvoffset,(!param->waitserver64 || (param->waitserver64 - received) > (param->srvinbuf - param->srvoffset))? param->srvinbuf - param->srvoffset : (int)(param->waitserver64 - received), 0, (struct sockaddr*)¶m->sincr, sasize); if(res < 0) { if(errno != EAGAIN && errno != EINTR) return 96; if(errno == EINTR) usleep(SLEEPTIME); continue; } param->srvoffset += res; received += res; if(param->srvoffset == param->srvinbuf) param->srvoffset = param->srvinbuf = 0; if(param->waitserver64 && param->waitserver64<= received){ return (98); } if(param->service == S_UDPPM && param->srv->singlepacket) { stop = 1; } } if((fds[1].revents & POLLOUT)){ #if DEBUGLEVEL > 2 (*param->srv->logfunc)(param, "send to server"); #endif if(param->bandlimfunc) { int sl1; sl1 = (*param->bandlimfunc)(param, 0, param->cliinbuf - param->clioffset); if(sl1 > sleeptime) sleeptime = sl1; } res = so._sendto(param->remsock, param->clibuf + param->clioffset, (!param->waitclient64 || (param->waitclient64 - sent) > (param->cliinbuf - param->clioffset))? param->cliinbuf - param->clioffset : (int)(param->waitclient64 - sent), 0, (struct sockaddr*)¶m->sinsr, sasize); if(res < 0) { if(errno != EAGAIN && errno != EINTR) return 97; if(errno == EINTR) usleep(SLEEPTIME); continue; } param->clioffset += res; if(param->clioffset == param->cliinbuf) param->clioffset = param->cliinbuf = 0; sent += res; param->nwrites++; param->statscli64 += res; if(param->waitclient64 && param->waitclient64<= sent) { return (99); } } if ((fds[0].revents & POLLIN)) { #if DEBUGLEVEL > 2 (*param->srv->logfunc)(param, "recv from client"); #endif res = so._recvfrom(param->clisock, param->clibuf + param->cliinbuf, param->clibufsize - param->cliinbuf, 0, (struct sockaddr *)¶m->sincr, &sasize); if (res==0) { so._shutdown(param->clisock, SHUT_RDWR); so._closesocket(param->clisock); fds[0].fd = param->clisock = INVALID_SOCKET; stop = 1; } else { if (res < 0){ if(errno != EAGAIN && errno != EINTR) return 94; if(errno == EINTR) usleep(SLEEPTIME); continue; } param->cliinbuf += res; if(!param->nolongdatfilter){ action = handledatfltcli(param, ¶m->clibuf, ¶m->clibufsize, param->cliinbuf - res, ¶m->cliinbuf); if(action == HANDLED){ return 0; } if(action != PASS) return 19; } } } if (!stop && (fds[1].revents & POLLIN)) { struct sockaddr_in sin; #if DEBUGLEVEL > 2 (*param->srv->logfunc)(param, "recv from server"); #endif sasize = sizeof(sin); res = so._recvfrom(param->remsock, param->srvbuf + param->srvinbuf, param->srvbufsize - param->srvinbuf, 0, (struct sockaddr *)&sin, &sasize); if (res==0) { so._shutdown(param->remsock, SHUT_RDWR); so._closesocket(param->remsock); fds[1].fd = param->remsock = INVALID_SOCKET; stop = 2; } else { if (res < 0){ if(errno != EAGAIN && errno != EINTR) return 93; if(errno == EINTR) usleep(SLEEPTIME); continue; } param->srvinbuf += res; param->nreads++; param->statssrv64 += res; if(!param->nolongdatfilter){ action = handledatfltsrv(param, ¶m->srvbuf, ¶m->srvbufsize, param->srvinbuf - res, ¶m->srvinbuf); if(action == HANDLED){ return 0; } if(action != PASS) return 19; } } } if(sleeptime > 0) { if(sleeptime > (timeo * 1000)){return (95);} usleep(sleeptime * SLEEPTIME); sleeptime = 0; } } if(conf.timetoexit) return 89; #if DEBUGLEVEL > 2 (*param->srv->logfunc)(param, "finished with mapping"); #endif while(!param->waitclient64 && param->srvinbuf > param->srvoffset && param->clisock != INVALID_SOCKET){ #if DEBUGLEVEL > 2 (*param->srv->logfunc)(param, "flushing buffer to client"); #endif res = socksendto(param->clisock, (struct sockaddr *)¶m->sincr, param->srvbuf + param->srvoffset, param->srvinbuf - param->srvoffset, conf.timeouts[STRING_S] * 1000); if(res > 0){ param->srvoffset += res; param->statssrv64 += res; if(param->srvoffset == param->srvinbuf) param->srvoffset = param->srvinbuf = 0; } else break; } while(!param->waitserver64 && param->cliinbuf > param->clioffset && param->remsock != INVALID_SOCKET){ #if DEBUGLEVEL > 2 (*param->srv->logfunc)(param, "flushing buffer to server"); #endif res = socksendto(param->remsock, (struct sockaddr *)¶m->sinsr, param->clibuf + param->clioffset, param->cliinbuf - param->clioffset, conf.timeouts[STRING_S] * 1000); if(res > 0){ param->clioffset += res; param->statscli64 += res; if(param->cliinbuf == param->clioffset) param->cliinbuf = param->clioffset = 0; } else break; } return retcode; }
void * dnsprchild(struct clientparam* param) { unsigned long ip = 0; unsigned char *bbuf; unsigned char *buf, *s1, *s2; char * host = NULL; unsigned char c; SASIZETYPE size; int res, i; int len; unsigned type=0; unsigned ttl; unsigned char addr[16]; #ifdef _WIN32 unsigned long ul = 1; #endif if(!(bbuf = myalloc(BUFSIZE+2))){ param->srv->fds.events = POLLIN; RETURN (21); } buf = bbuf+2; size = sizeof(param->sincr); i = so._recvfrom(param->srv->srvsock, buf, BUFSIZE, 0, (struct sockaddr *)¶m->sincr, &size); size = sizeof(param->sinsl); getsockname(param->srv->srvsock, (struct sockaddr *)¶m->sincl, &size); #ifdef _WIN32 if((param->clisock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { RETURN(818); } ioctlsocket(param->clisock, FIONBIO, &ul); if(so._setsockopt(param->clisock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&ul, sizeof(int))) {RETURN(820);}; if(so._bind(param->clisock,(struct sockaddr *)¶m->sincl,sizeof(param->sincl))) { RETURN(822); } #else param->clisock = param->srv->srvsock; #endif param->srv->fds.events = POLLIN; if(i < 0) { RETURN(813); } buf[BUFSIZE - 1] = 0; if(i<=13 || i>1000){ RETURN (814); } param->operation = DNSRESOLVE; if((res = (*param->srv->authfunc)(param))) {RETURN(res);} if(buf[4]!=0 || buf[5]!=1) RETURN(816); for(len = 12; len<i; len+=(c+1)){ c = buf[len]; if(!c)break; buf[len] = '.'; } if(len > (i-4)) {RETURN(817);} host = mystrdup((char *)buf+13); if(!host) {RETURN(21);} for(s2 = buf + 12; (s1 = (unsigned char *)strchr((char *)s2 + 1, '.')); s2 = s1)*s2 = (unsigned char)((s1 - s2) - 1); *s2 = (len - (int)(s2 - buf)) - 1; type = ((unsigned)buf[len+1])*256 + (unsigned)buf[len+2]; if((type==0x01 || type==0x1c) && !param->srv->singlepacket){ ip = udpresolve((type==0x1c)?AF_INET6:AF_INET, (unsigned char *)host, addr, &ttl, param, 0); } len+=5; if(ip){ buf[2] = 0x85; buf[3] = 0x80; buf[6] = 0; buf[7] = 1; buf[8] = buf[9] = buf[10] = buf[11] = 0; memset(buf+len, 0, 16); buf[len] = 0xc0; buf[len+1] = 0x0c; buf[len+3] = type; buf[len+5] = 1; ttl = htonl(ttl); memcpy(buf + len + 6, &ttl, 4); buf[len+11] = type==1? 4:16; memcpy(buf+len+12,(void *)&addr,type==1? 4:16); len+=(type==1?16:28); } else if(type == 0x0c) { unsigned a, b, c, d; sscanf(host, "%u.%u.%u.%u", &a, &b, &c, &d); ip = htonl((d<<24) ^ (c<<16) ^ (b<<8) ^ a); if(*SAFAMILY(¶m->sincl) == AF_INET && ip == *(unsigned long*)SAADDR(¶m->sincl)){ buf[2] = 0x85; buf[3] = 0x80; buf[6] = 0; buf[7] = 1; buf[8] = buf[9] = buf[10] = buf[11] = 0; memset(buf+len, 0, 20); buf[len] = 0xc0; buf[len+1] = 0x0c; buf[len+3] = 0x0c; buf[len+5] = 1; ttl = htonl(3600); memcpy(buf + len + 6, &ttl, 4); buf[len+11] = 7; buf[len+12] = 6; memcpy(buf+len+13,(void *)"3proxy",6); len+=20; } else ip = 0; } if(!ip && numservers){ if((param->remsock=so._socket(SASOCK(&nservers[0].addr), nservers[0].usetcp? SOCK_STREAM:SOCK_DGRAM, nservers[0].usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) { RETURN(818); } memset(¶m->sinsl, 0, sizeof(param->sinsl)); *SAFAMILY(¶m->sinsl) = *SAFAMILY(&nservers[0].addr); if(so._bind(param->remsock,(struct sockaddr *)¶m->sinsl,sizeof(param->sinsl))) { RETURN(819); } memcpy(¶m->sinsr, &nservers[0].addr, sizeof(param->sinsr)); if(nservers[0].usetcp) { if(so._connect(param->remsock,(struct sockaddr *)¶m->sinsr,sizeof(param->sinsr))) RETURN(830); buf-=2; *(unsigned short*)buf = htons(i); i+=2; } else { #ifdef _WIN32 /* ioctlsocket(param->remsock, FIONBIO, &ul); */ #else /* fcntl(param->remsock,F_SETFL,O_NONBLOCK); */ #endif } if(socksendto(param->remsock, (struct sockaddr *)¶m->sinsr, buf, i, conf.timeouts[SINGLEBYTE_L]*1000) != i){ RETURN(820); } param->statscli64 += i; param->nwrites++; len = sockrecvfrom(param->remsock, (struct sockaddr *)¶m->sinsr, buf, BUFSIZE, 15000); if(len <= 13) { RETURN(821); } param->statssrv64 += len; param->nreads++; if(nservers[0].usetcp) { unsigned short us; us = ntohs(*(unsigned short *)buf); if(us > 4096) RETURN(833); buf += 2; len -= 2; if(len < us) len += sockgetlinebuf(param, SERVER, buf+len, us - len, 0, conf.timeouts[SINGLEBYTE_L]); if(len != us) RETURN(832); } if(buf[6] || buf[7]){ if(socksendto(param->clisock, (struct sockaddr *)¶m->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){ RETURN(822); } RETURN(0); } } if(!ip) { buf[2] = 0x85; buf[3] = 0x83; } res = socksendto(param->clisock, (struct sockaddr *)¶m->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000); if(res != len){RETURN(819);} if(!ip) {RETURN(888);} CLEANRET: if(param->res!=813){ sprintf((char *)buf, "%04x/%s/", (unsigned)type, host?host:""); if(ip && type == 0x01 || type == 0x1c){ myinet_ntop(type == 0x01? AF_INET:AF_INET6, addr, buf+strlen(buf), 64); } (*param->srv->logfunc)(param, buf); } if(bbuf)myfree(bbuf); if(host)myfree(host); #ifndef _WIN32 param->clisock = INVALID_SOCKET; #endif freeparam(param); return (NULL); }