/* 3APA3A simplest proxy server (c) 2002-2026 by Vladimir Dubrovin please read License Agreement */ #include "proxy.h" #ifndef PORTMAP #define PORTMAP #endif #ifndef UDP #define UDP #endif #define RETURN(xxx) { param->res = xxx; goto CLEANRET; } static void udpparam2hash(const struct hashtable *ht, void *index, uint8_t *hash){ struct clientparam *param = (struct clientparam *)index; uint32_t m1, m2; m1 = murmurhash3(SAADDR(¶m->srv->intsa), SAADDRLEN(¶m->srv->intsa), 0x3a3a3a3a); m1 = murmurhash3(SAPORT(¶m->sincr), 2, m1); m2 = murmurhash3(SAADDR(¶m->sincr), SAADDRLEN(¶m->sincr), m1); m2 = murmurhash3(SAPORT(¶m->srv->intsa), 2, m2); memcpy(hash, &m1, 4); memcpy(hash+4, &m2, 4); } struct hashtable udp_table = {udpparam2hash, udpparam2hash, sizeof(struct clientparam *), 8}; int socks5_udp_build_hdr(unsigned char *buf, PROXYSOCKADDRTYPE *addr); void * udppmchild(struct clientparam* param) { int authres; int i; int len = 0; if(parsehostname((char *)param->srv->target, param, ntohs(param->srv->targetport))) { RETURN(201) } #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, (struct sockaddr *)¶m->srv->extsa, SASIZE(¶m->req)); #endif *SAPORT(¶m->sinsl) = 0; param->remsock = param->srv->so._socket(param->srv->so.state, SASOCK(¶m->sinsl), SOCK_DGRAM, IPPROTO_UDP); if(param->remsock == INVALID_SOCKET) { RETURN(202); } if(param->srv->so._bind(param->srv->so.state, param->remsock, (struct sockaddr *)¶m->sinsl, SASIZE(¶m->sinsl))) { RETURN(203); } #ifdef _WIN32 { unsigned long ul2 = 1; ioctlsocket(param->remsock, FIONBIO, &ul2); } #else fcntl(param->remsock, F_SETFL, O_NONBLOCK | fcntl(param->remsock, F_GETFL)); #endif memcpy(¶m->sinsr, ¶m->req, sizeof(param->req)); param->operation = UDPASSOC; authres = (*param->srv->authfunc)(param); if(authres) { RETURN(authres); } if(!param->srv->singlepacket)hashadd(&udp_table, param, ¶m, MAX_COUNTER_TIME); if(!param->srvbuf){ if(!(param->srvbuf = malloc(UDPBUFSIZE)))RETURN(11); param->srvbufsize = UDPBUFSIZE; } if(param->udp_nhops){ for(i=1; i < param->udp_nhops; i++){ len+=socks5_udp_build_hdr(param->srvbuf+len, ¶m->udp_relay[i-1]); } len += socks5_udp_build_hdr(param->srvbuf+len, ¶m->req); } memcpy(param->srvbuf+len, param->srv->udpbuf, param->srv->udplen > UDPBUFSIZE - len?UDPBUFSIZE - len : param->srv->udplen); len += param->srv->udplen > UDPBUFSIZE - len?UDPBUFSIZE - len : param->srv->udplen; param->srv->so._sendto(param->sostate, param->remsock, (char *)param->srvbuf, len, 0, (struct sockaddr *)¶m->sinsr, SASIZE(¶m->sinsr)); _3proxy_sem_unlock(udpinit); param->statscli64 += param->srvinbuf; param->srvinbuf = 0; param->nwrites++; param->clisock = param->srv->srvsock; param->waitserver64 = 0x7fffffffffffffff; param->res = udpsockmap(param, conf.timeouts[STRING_L]); _3proxy_sem_lock(udpinit); if(!param->srv->singlepacket)hashdelete(&udp_table, param); CLEANRET: _3proxy_sem_unlock(udpinit); dolog(param, NULL); param->clisock = INVALID_SOCKET; freeparam(param); return (NULL); } #ifdef WITHMAIN struct proxydef childdef = { udppmchild, 0, 1, S_UDPPM, " -s single packet UDP service for request/reply (DNS-like) services\n" }; #include "proxymain.c" #endif