/* 3APA3A simplest proxy server (c) 2002-2026 by Vladimir Dubrovin please read License Agreement */ #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){ if(family == 4) return 1; len = 16; *SAFAMILY(sa) = AF_INET6; memcpy(SAADDR(sa), addr, 16); } 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); } 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 /* Threads stay in the network namespace the process started in. A socket belongs to the namespace it is made in, whatever thread uses it later, so a service's other namespaces are entered for socket() alone. What a thread does without making a socket of its own, a name looked up through the system, a log line, RADIUS, happens in the main namespace. */ int mainnsfd = -1; /* set in a thread left outside the main namespace, which is not reused */ static __thread int nsfailed; int nsbroken(void){ return nsfailed; } /* Opens the main namespace, once and while /proc can still be reached: a chroot may take it away. */ int nsopen(void){ if(mainnsfd < 0) mainnsfd = open("/proc/self/ns/net", O_RDONLY | O_CLOEXEC); return mainnsfd < 0; } SOCKET nssocket(struct srvparam *srv, struct sockfuncs *sf, void *state, int side, int domain, int type, int protocol){ int nsfd = (side == NS_OUT)? srv->o_nsfd : srv->i_nsfd; SOCKET s; int err; if(nsfd < 0) return sf->_socket(state, domain, type, protocol); if(setns(nsfd, CLONE_NEWNET)) return INVALID_SOCKET; s = sf->_socket(state, domain, type, protocol); err = errno; if(setns(mainnsfd, CLONE_NEWNET)){ /* Left in the other namespace: no socket from here, and the connection fails. The thread ends with it. */ if(s != INVALID_SOCKET) sf->_closesocket(state, s); nsfailed = 1; return INVALID_SOCKET; } errno = err; return s; } #else /* no network namespaces: a socket is made where it always is */ SOCKET nssocket(struct srvparam *srv, struct sockfuncs *sf, void *state, int side, int domain, int type, int protocol){ return sf->_socket(state, domain, type, protocol); } #endif char * copyright = COPYRIGHT; #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) # define MYRAND_ARC4RANDOM 1 #elif defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 36))) # define MYRAND_ARC4RANDOM 1 #elif defined(__GLIBC__) && ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 25))) # define MYRAND_FALLBACK 1 #elif defined(__linux__) # define MYRAND_GETRANDOM 1 # include #elif defined(_WIN32) # define MYRAND_BCRYPTGENRANDOM 1 # include # pragma comment(lib, "bcrypt.lib") #else # define MYRAND_FALLBACK 1 #endif #ifndef _WIN32 pthread_attr_t pa; void daemonize(void){ pid_t pid = fork(); if(pid > 0) { usleep(SLEEPTIME); _exit(0); } if(pid < 0) { perror("fork()"); return; } setsid(); } #endif unsigned char **stringtable = NULL; #ifdef WITH_UN void make_un(const unsigned char *path, struct sockaddr_un * sun){ memset(sun, 0, sizeof(*sun)); sun->sun_family = AF_UNIX; strncpy(sun->sun_path, (char *)path, sizeof(sun->sun_path) - 1); if(*path == '@')*sun->sun_path = 0; } #endif int myinet_ntop(int af, void *src, char *dst, socklen_t size){ #ifdef WITH_UN if(af == AF_UNIX){ struct sockaddr_un *sun = (struct sockaddr_un *)src; int ephemeral = 0; char *path = sun->sun_path; char *basename; if(!path[0] && path[1]){ ephemeral = 1; *dst++ = '@'; path++; } basename = strrchr(path, '/'); if(basename) basename++; else basename = path; if(size > 0){ strncpy(dst, basename, (size > 40) ? 40 : size - (ephemeral + 1)); dst[((size > 40) ? 40 : size - (ephemeral + 1))] = 0; } return (int)strlen(dst); } #endif if(af != AF_INET6){ unsigned u = ntohl(((struct in_addr *)src)->s_addr); return sprintf(dst, "%u.%u.%u.%u", ((u&0xFF000000)>>24), ((u&0x00FF0000)>>16), ((u&0x0000FF00)>>8), ((u&0x000000FF))); } *dst = 0; inet_ntop(af, src, dst, size); return (int)strlen(dst); } char *rotations[] = { "", "/min", "/hour", "/day", "/week", "/month", "/year", "", }; /* State of the process, not configuration. */ time_t curtime; int timetoexit = 0, needreload = 0; #ifndef _WIN32 /* PTHREAD_STACK_MIN is 128K on glibc/aarch64 and glibc/powerpc and may be a sysconf() call with _GNU_SOURCE. pthread_attr_setstacksize() fails with EINVAL below it and the thread silently gets the 8M system default stack. */ size_t threadstacksize(int extra){ long size = BASESTACKSIZE + TLSSTACKSIZE + extra; if(size < (long)PTHREAD_STACK_MIN) size = (long)PTHREAD_STACK_MIN; return (size_t)size; } #endif struct threadpool tpool; /* A configuration starts as confdefaults; conf is the current one, at first confboot, which exists before main() runs. */ const struct extparam confdefaults = { #include "confinit.h" }; struct extparam confboot = { #include "confinit.h" }; /* conf is the configuration commands act on: the one being read during a reload, the one in force otherwise. runconf is the one in force, for whatever runs meanwhile without a service of its own. */ struct extparam *conf = &confboot; struct extparam *runconf = &confboot; int (*reattachfunc)(struct clientparam *param, int auth) = NULL; void (*listenertrafficfunc)(struct clientparam *param) = NULL; /* Authorizes a request on a connection which may outlive a reload, an HTTP one kept alive: as a client of the service whose rules apply now, the newest one on its listener after a reload (unless noforce). */ int clientauth(struct clientparam *param){ struct srvparam *orig; int res; if(param->version < runconf->version){ if(param->srv->noforce || !reattachfunc) param->version = runconf->version; else if((res = (*reattachfunc)(param, 0))) return res; } if(!param->newsrv) return (*param->srv->authfunc)(param); orig = param->srv; param->srv = param->newsrv; res = (*param->srv->authfunc)(param); param->srv = orig; return res; } _3proxy_mutex_t confref_mutex; char* NULLADDR="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; uint32_t myrand(void){ #if defined(MYRAND_ARC4RANDOM) return arc4random(); #elif defined(MYRAND_GETRANDOM) uint32_t r = 0; ssize_t n; do { n = getrandom(&r, sizeof(r), 0); } while(n < 0 && errno == EINTR); return r; #elif defined(MYRAND_BCRYPTGENRANDOM) uint32_t r = 0; BCryptGenRandom(NULL, (PUCHAR)&r, sizeof(r), BCRYPT_USE_SYSTEM_PREFERRED_RNG); return r; #elif defined(MYRAND_CRYPTGENRANDOM) uint32_t r = 0; HCRYPTPROV prov; if(CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT|CRYPT_SILENT)){ CryptGenRandom(prov, sizeof(r), (BYTE *)&r); CryptReleaseContext(prov, 0); } return r; #else return ((uint32_t)rand() << 16) ^ (uint32_t)rand(); #endif } /* Set while clients are served by fibers on event loops, which keep their sockets registered and remember what each was found ready for: an operation finding a socket not ready, and a socket about to be closed, are told to its loop. errno is left as it was. */ void (*fiberblockfunc)(SOCKET s, short events) = NULL; void (*fiberclosefunc)(SOCKET s) = NULL; /* set as well: whether this thread is a loop's, which is not to wait */ int (*onloopfunc)(void) = NULL; /* and what runs func(arg) on the thread's own stack, not a fiber's */ void (*onthreadstackfunc)(void (*func)(void *arg), void *arg) = NULL; #define BLOCKED(s, ev) do { if(fiberblockfunc && (errno == EAGAIN || errno == EWOULDBLOCK)) \ fiberblockfunc((s), (ev)); } while(0) #ifdef _WIN32 SOCKET WINAPI def_socket(void* state, int domain, int type, int protocol){ return socket(domain, type, protocol); } SOCKET WINAPI def_accept(void* state, SOCKET s, struct sockaddr * addr, int * addrlen){ SOCKET r = accept(s, addr, addrlen); if(r == INVALID_SOCKET) BLOCKED(s, POLLIN); return r; } int WINAPI def_bind(void* state, SOCKET s, const struct sockaddr *addr, int addrlen){ return bind(s, addr, addrlen); } int WINAPI def_listen(void* state, SOCKET s, int backlog){ return listen(s, backlog); } int WINAPI def_connect(void* state, SOCKET s, const struct sockaddr *name, int namelen){ int r = connect(s, name, namelen); if(r) BLOCKED(s, POLLOUT); return r; } int WINAPI def_getpeername(void* state, SOCKET s, struct sockaddr * name, int * namelen){ return getpeername(s, name, namelen); } int WINAPI def_getsockname(void* state, SOCKET s, struct sockaddr * name, int * namelen){ return getsockname(s, name, namelen); } int WINAPI def_getsockopt(void* state, SOCKET s, int level, int optname, char * optval, int * optlen){ return getsockopt(s, level, optname, optval, optlen); } int WINAPI def_setsockopt(void* state, SOCKET s, int level, int optname, const char *optval, int optlen){ return setsockopt(s, level, optname, optval, optlen); } int WINAPI def_prepoll(void* state, struct pollfd *fds, unsigned int nfds){ return 0; } int WINAPI def_send(void* state, SOCKET s, const char *msg, int len, int flags){ int r = send(s, msg, len, flags); if(r < 0) BLOCKED(s, POLLOUT); return r; } int WINAPI def_sendto(void* state, SOCKET s, const char *msg, int len, int flags, const struct sockaddr *to, int tolen){ int r = sendto(s, msg, len, flags, to, tolen); if(r < 0) BLOCKED(s, POLLOUT); return r; } int WINAPI def_recv(void* state, SOCKET s, char *buf, int len, int flags){ int r = recv(s, buf, len, flags); if(r < 0) BLOCKED(s, POLLIN); return r; } int WINAPI def_recvfrom(void* state, SOCKET s, char * buf, int len, int flags, struct sockaddr * from, int * fromlen){ int r = recvfrom(s, buf, len, flags, from, fromlen); if(r < 0) BLOCKED(s, POLLIN); return r; } int WINAPI def_shutdown(void* state, SOCKET s, int how){ return shutdown(s, how); } int WINAPI def_closesocket(void* state, SOCKET s){ if(fiberclosefunc) fiberclosefunc(s); return closesocket(s); } #else SOCKET def_socket(void* state, int domain, int type, int protocol){ return socket(domain, type, protocol); } SOCKET def_accept(void* state, SOCKET s, struct sockaddr * addr, socklen_t* addrlen){ SOCKET r = accept(s, addr, addrlen); if(r == INVALID_SOCKET) BLOCKED(s, POLLIN); return r; } int def_bind(void* state, SOCKET s, const struct sockaddr *addr, socklen_t addrlen){ return bind(s, addr, addrlen); } int def_getpeername(void* state, SOCKET s, struct sockaddr * name, socklen_t* namelen){ return getpeername(s, name, namelen); } int def_getsockname(void* state, SOCKET s, struct sockaddr * name, socklen_t* namelen){ return getsockname(s, name, namelen); } int def_listen(void* state, SOCKET s, int backlog){ return listen(s, backlog); } int def_connect(void* state, SOCKET s, const struct sockaddr *name, socklen_t namelen){ int r = connect(s, name, namelen); if(r && errno == EINPROGRESS && fiberblockfunc) fiberblockfunc(s, POLLOUT); return r; } int def_getsockopt(void* state, SOCKET s, int level, int optname, void * optval, socklen_t * optlen){ return getsockopt(s, level, optname, optval, optlen); } int def_setsockopt(void* state, int s, int level, int optname, const void *optval, socklen_t optlen){ return setsockopt(s, level, optname, optval, optlen); } int def_prepoll(void* state, struct pollfd *fds, nfds_t nfds){ return 0; } /* a peer gone is an error of the send, not SIGPIPE, where the system can say so for a call: SIGPIPE is ignored too, for TLS and splice() */ #ifdef MSG_NOSIGNAL #define SENDFLAGS MSG_NOSIGNAL #else #define SENDFLAGS 0 #endif ssize_t def_send(void* state, SOCKET s, const void *msg, size_t len, int flags){ ssize_t r = send(s, msg, len, flags | SENDFLAGS); if(r < 0) BLOCKED(s, POLLOUT); return r; } ssize_t def_sendto(void* state, SOCKET s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen){ ssize_t r = sendto(s, msg, len, flags | SENDFLAGS, to, tolen); if(r < 0) BLOCKED(s, POLLOUT); return r; } ssize_t def_recv(void* state, SOCKET s, void *buf, size_t len, int flags){ ssize_t r = recv(s, buf, len, flags); if(r < 0) BLOCKED(s, POLLIN); return r; } ssize_t def_recvfrom(void* state, SOCKET s, void * buf, size_t len, int flags, struct sockaddr * from, socklen_t* fromlen){ ssize_t r = recvfrom(s, buf, len, flags, from, fromlen); if(r < 0) BLOCKED(s, POLLIN); return r; } int def_shutdown(void* state, SOCKET s, int how){ return shutdown(s, how); } int def_closesocket(void* state, SOCKET s){ if(fiberclosefunc) fiberclosefunc(s); return close(s); } #endif struct sockfuncs so = { NULL, NULL, def_socket, def_accept, def_bind, def_listen, def_connect, def_getpeername, def_getsockname, def_getsockopt, def_setsockopt, def_prepoll, def_send, def_sendto, def_recv, def_recvfrom, def_shutdown, def_closesocket }; #ifndef _WIN32 /* close() of a descriptor a fiber may have waited on, a pipe of splice(): its loop forgets it first, or a socket given the same number later would be taken for it, and never registered. */ int fdclose(int fd){ if(fiberclosefunc) fiberclosefunc(fd); return close(fd); } #endif /* Whether s, found readable, is: data or its end there. A fiber's wait may answer with what a socket was reported ready for, until an operation finds it not to be: whatever takes readability for an end, rather than reading, asks first. A peek below any layer over the socket, which a TLS read would consume. */ int sockreadable(SOCKET s){ char c; if(!fiberblockfunc) return 1; if(recv(s, &c, 1, MSG_PEEK) < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)){ fiberblockfunc(s, POLLIN); return 0; } return 1; } /* Waits as poll() does for fds of sockets made with sf, once their layers know of nothing ready already. A layer may have a socket waited for other than as asked, a TLS read for it to be writable: whatever it gets is then the caller's chance to try again, revents what the caller asked for, and events are given back as they were. With no fds it only sleeps. */ #define POLLFAIL (POLLERR|POLLHUP|POLLNVAL) /* set once clients are served by fibers on event loops: the wait of a fiber, -2 for anything else */ int (*fiberpollfunc)(struct pollfd *fds, unsigned nfds, int timeout) = NULL; int sockpoll(struct sockfuncs *sf, void *state, struct pollfd *fds, unsigned nfds, int timeout){ short own[64], *events = own; unsigned i; int res; if(!nfds){ if(timeout > 0 && (!fiberpollfunc || fiberpollfunc(NULL, 0, timeout) == -2)) usleep(timeout * SLEEPTIME); return 0; } if(nfds > sizeof(own)/sizeof(own[0]) && !(events = malloc(nfds * sizeof(*events)))) return -1; for(i = 0; i < nfds; i++) events[i] = fds[i].events; if(!(res = sf->_prepoll(state, fds, nfds))){ /* a fiber waits in its loop */ if(!fiberpollfunc || (res = fiberpollfunc(fds, nfds, timeout)) == -2){ #ifdef _WIN32 res = WSAPoll(fds, nfds, timeout); #else res = poll(fds, (nfds_t)nfds, timeout); #endif } for(i = 0; res > 0 && i < nfds; i++) if(fds[i].events != events[i] && (fds[i].revents & ~POLLFAIL)) fds[i].revents = events[i] | (fds[i].revents & POLLFAIL); } for(i = 0; i < nfds; i++) fds[i].events = events[i]; if(events != own) free(events); return res; } int parsehost(int family, unsigned char *host, struct sockaddr *sa){ char *sp=NULL,*se=NULL; uint16_t port=0; int ret = 0; if(!host) return 2; if(*host == '[') se=strchr((char *)host, ']'); if ( (sp = strchr(se?se:(char *)host, ':')) && !strchr(sp+1, ':')) *sp = 0; if(se){ *se = 0; } if(sp){ port = atoi(sp+1); } ret = !getip46(family, host + (se!=0), (struct sockaddr *)sa); if(se) *se = ']'; if(sp) *sp = ':'; if(port)*SAPORT(sa) = htons(port); return ret; } int parsehostname(char *hostname, struct clientparam *param, uint16_t port){ char *sp=NULL,*se=NULL; int ret = 0; if(!hostname || !*hostname)return 2; if(*hostname == '[') se=strchr(hostname, ']'); if ((sp = strchr(se?se:hostname, ':'))) { if(strchr(sp+1, ':'))sp = NULL; else *sp = 0; } if(se){ *se = 0; } if(!*hostname){ if(sp){ port = atoi(sp+1); *sp = ':'; } *SAPORT(¶m->req) = htons(port); return 0; } if(strlen(hostname + (se!=0)) > 253){ if(se) *se = ']'; if(sp) *sp = ':'; return 1; } if(PARAMSTR(param, hostname, hostname + (se!=0))){ if(se) *se = ']'; if(sp) *sp = ':'; return 1; } if(sp){ port = atoi(sp+1); } ret = !getip46m(param->srv->resolvmode, param->srv->family, param->hostname, (struct sockaddr *)¶m->req); if(se) *se = ']'; if(sp) *sp = ':'; *SAPORT(¶m->req) = htons(port); memset(¶m->sinsr, 0, sizeof(param->sinsr)); return ret; } /* Copies a string into one of a connection's fixed fields. One too long for it is refused rather than cut short, which could name another host or another user; NULL empties it. The string may be part of the field. */ int paramstr(unsigned char *field, size_t size, const unsigned char *s){ size_t len; if(!s){ *field = 0; return 0; } len = strlen((const char *)s); if(len >= size) return 1; memmove(field, s, len + 1); return 0; } int parseusername(char *username, struct clientparam *param, int extpasswd){ char *sb = NULL, *se = NULL, *sp = NULL; if(!username || !*username) return 1; if(param->srv->needuser && (sb = strchr(username, ':')) && (se = strchr(sb + 1, ':')) && (!extpasswd || (sp = strchr(se + 1, ':')))){ *sb = 0; *se = 0; if(sp) *sp = 0; if((*(sb+1) && PARAMSTR(param, password, sb+1)) || (*username && PARAMSTR(param, username, username))){ *sb = ':'; *se = ':'; if(sp) *sp = ':'; return 1; } username = se+1; } if(extpasswd){ if(!sp) sp = strchr(username, ':'); if(sp){ *sp = 0; if(PARAMSTR(param, extpassword, sp+1)) extpasswd = -1; } } if(extpasswd < 0 || PARAMSTR(param, extusername, username)) extpasswd = -1; if(sb) *sb = ':'; if(se) *se = ':'; if(sp) *sp = ':'; return extpasswd < 0; } int parseconnusername(char *username, struct clientparam *param, int extpasswd, uint16_t port){ char *sb, *se; if(!username || !*username) return 1; if ((sb=strchr(username, param->srv->delimchar)) == NULL){ if(!*param->hostname && param->remsock == INVALID_SOCKET) return 2; if(*param->hostname)parsehostname((char *)param->hostname, param, *SAPORT(¶m->req)? ntohs(*SAPORT(¶m->req)) : port); return parseusername(username, param, extpasswd); } while ((se=strchr(sb+1, param->srv->delimchar)))sb=se; *(sb) = 0; if(parseusername(username, param, extpasswd)) return 3; *(sb) = param->srv->delimchar; if(parsehostname(sb+1, param, *SAPORT(¶m->req)? ntohs(*SAPORT(¶m->req)) : port)) return 4; return 0; } /* What waits for a socket waits in sockpoll(): a call on it never does. */ void nonblock(SOCKET sock){ #ifdef _WIN32 unsigned long ul = 1; ioctlsocket(sock, FIONBIO, &ul); #else fcntl(sock, F_SETFL, O_NONBLOCK | fcntl(sock, F_GETFL)); #endif } /* accept() with nothing to accept: another took it, or it was gone */ int acceptagain(void){ #ifdef _WIN32 int err = WSAGetLastError(); return err == WSAEWOULDBLOCK || err == WSAECONNRESET || err == WSAEINTR; #else return errno == EAGAIN || errno == EWOULDBLOCK || errno == ECONNABORTED || errno == EINTR; #endif } int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to){ struct pollfd fds[1]; #ifdef _WIN32 unsigned long ul = 1; ioctlsocket(sock, FIONBIO, &ul); #else fcntl(sock,F_SETFL, O_NONBLOCK | fcntl(sock,F_GETFL)); #endif if(param?param->srv->so._connect(param->sostate, sock,sa,size) : so._connect(so.state, sock,sa,size)) { if(errno != EAGAIN && errno != EINPROGRESS) return 13; } if(!errno) return 0; memset(fds, 0, sizeof(fds)); fds[0].fd = sock; fds[0].events = POLLOUT; if((param?sockpoll(¶m->srv->so, param->sostate, fds, 1, to*1000):sockpoll(&so, so.state, fds, 1, to*1000)) <= 0 || !(fds[0].revents & POLLOUT) || (fds[0].revents & (POLLERR|POLLHUP))) { return 13; } return 0; } /* Number of ports tried before giving up when the range has to be searched by * hand. The kernel option picks a free port itself and needs no retries. */ #define RANGETRIES 10 static int bindrange(struct clientparam *param, SOCKET sock, PROXYSOCKADDRTYPE *sa, uint32_t range, int *tries); /* -Di / -De: ties a socket to the interface asked for, for TCP and UDP alike. Where the option is set per protocol, family is the one of the address the socket will be bound to. */ int bindtodevice(struct sockfuncs *sf, void *state, SOCKET sock, const char *device, int family){ if(!device) return 0; #if defined SO_BINDTODEVICE if(sf->_setsockopt(state, sock, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1)) return 1; #elif defined IP_BOUND_IF { int idx; idx = if_nametoindex(device); if(!idx || (family == AF_INET && sf->_setsockopt(state, sock, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx)))) return 1; #ifndef IPV6_BOUND_IF #define IPV6_BOUND_IF 125 #endif if(family == AF_INET6 && sf->_setsockopt(state, sock, IPPROTO_IPV6, IPV6_BOUND_IF, &idx, sizeof(idx))) return 1; } #endif return 0; } /* the external side, a socket to be bound to sinsl */ int extbindtodevice(struct clientparam *param, SOCKET sock){ #if defined SO_BINDTODEVICE || defined IP_BOUND_IF return bindtodevice(¶m->srv->so, param->sostate, sock, param->srv->obindtodevice, *SAFAMILY(¶m->sinsl)); #else return 0; #endif } /* the internal side, a socket to be bound to sincl */ int intbindtodevice(struct clientparam *param, SOCKET sock){ #if defined SO_BINDTODEVICE || defined IP_BOUND_IF return bindtodevice(¶m->srv->so, param->sostate, sock, param->srv->ibindtodevice, *SAFAMILY(¶m->sincl)); #else return 0; #endif } int doconnect(struct clientparam * param){ SASIZETYPE size; if (*SAFAMILY(¶m->sincl) == *SAFAMILY(¶m->req) && !memcmp(SAADDR(¶m->sincl), SAADDR(¶m->req), SAADDRLEN(¶m->req)) && *SAPORT(¶m->sincl) == *SAPORT(¶m->req)) return 519; if (param->operation == ADMIN || (( param->operation == DNSRESOLVE || param->operation == BIND || param->operation == UDPASSOC) && !param->redirected)) return 0; if (param->operation == UDPASSOC && param->ctrlsocksrv != INVALID_SOCKET) return 0; if (param->remsock != INVALID_SOCKET){ if(param->operation == UDPASSOC) return 0; size = sizeof(param->sinsr); if(param->srv->so._getpeername(param->sostate, param->remsock, (struct sockaddr *)¶m->sinsr, &size)==-1) {return (14);} } else { int tries = RANGETRIES; if(SAISNULL(¶m->sinsr)){ if(SAISNULL(¶m->req)) { return 100; } *SAFAMILY(¶m->sinsr) = *SAFAMILY(¶m->req); memcpy(SAADDR(¶m->sinsr), SAADDR(¶m->req), SAADDRLEN(¶m->req)); } if(!*SAPORT(¶m->sinsr))*SAPORT(¶m->sinsr) = *SAPORT(¶m->req); for(;;){ if ((param->remsock=nssocket(param->srv, ¶m->srv->so, param->sostate, NS_OUT, SASOCK(¶m->sinsr), SOCK_STREAM, #ifdef WITH_UN *SAFAMILY(¶m->sinsr) == AF_UNIX? 0 : #endif IPPROTO_TCP )) == INVALID_SOCKET) {return (11);} if(SAISNULL(¶m->sinsl)){ #ifdef WITH_UN if(*SAFAMILY(¶m->sinsr) == AF_UNIX) param->sinsl = param->sinsr; else #endif if(*SAFAMILY(¶m->sinsr) == AF_INET6) param->sinsl = param->srv->extsa6; else param->sinsl = param->srv->extsa; } *SAPORT(¶m->sinsl) = 0; setopts(param->remsock, ¶m->srv->srvsockopts, param->srv->maxseg); if(extbindtodevice(param, param->remsock)) return 12; #ifdef IP_BIND_ADDRESS_NO_PORT /* A port the kernel chooses is chosen by connect(), for the pair with the destination: one in use towards another destination, or closing from an earlier connection, does as well. bind() would take one of its own, and with many connections find none left, or search long for it. */ if((param->operation >= 256 || (param->operation & CONNECT) || param->redirected) # ifdef WITH_UN && *SAFAMILY(¶m->sinsl) != AF_UNIX # endif ){ int one = 1; param->srv->so._setsockopt(param->sostate, param->remsock, IPPROTO_IP, IP_BIND_ADDRESS_NO_PORT, (char *)&one, sizeof(one)); } #endif #ifdef WITH_UN if(*SAFAMILY(¶m->sinsl) != AF_UNIX) #endif if(bindrange(param, param->remsock, ¶m->sinsl, param->extport, &tries)==-1) { return 12; } if(!(param->operation >= 256 || (param->operation & CONNECT) || param->redirected)) break; if(!connectwithpoll(param, param->remsock,(struct sockaddr *)¶m->sinsr,SASIZE(¶m->sinsr),param->srv->timeouts[CONNECT_TO])) break; /* The port was free to bind, but the pair it makes with the destination is still closing from an earlier connection through the same range, which Windows refuses. Another port out of the range may do. Anything else is the destination's own answer, and is not worth a second port. The ports come out of the allowance the bind is already spending, so the range is not searched any harder than one bind would search it and the attempts parentretries makes are not multiplied. Counted here as well, since the kernel option hands out a port without spending any of the allowance. */ if(!param->extport || errno != EADDRINUSE || --tries <= 0) return 13; param->srv->so._closesocket(param->sostate, param->remsock); param->remsock = INVALID_SOCKET; } size = sizeof(param->sinsl); if(param->srv->so._getsockname(param->sostate, param->remsock, (struct sockaddr *)¶m->sinsl, &size)==-1) {return (15);} } if (param->nconnectfilters){ FILTER_ACTION action; action = handleconnectflt(param); if(action != PASS) return 19; } return 0; } /* Bind sock to sa, taking the local port from the range if one is set. The * range is packed as first | last << 16. * * IP_LOCAL_PORT_RANGE leaves the choice to the kernel, which knows which ports * are free. Where the option does not exist, or the kernel refuses it, or the * address family is not one it covers, pick a port at random instead and retry * on failure, since the one picked may already be taken. * * *tries is how many ports may still be taken out of the range. A caller which * has to come back for another port, because the one it was given turned out * to be unusable for the connection it wanted, carries the same count along * and so cannot spend more attempts than one call would. */ static int bindrange(struct clientparam *param, SOCKET sock, PROXYSOCKADDRTYPE *sa, uint32_t range, int *tries) { uint16_t first, last; if(!range) return param->srv->so._bind(param->sostate, sock, (struct sockaddr *)sa, SASIZE(sa)); #ifdef IP_LOCAL_PORT_RANGE if(*SAFAMILY(sa) == AF_INET && !param->srv->so._setsockopt(param->sostate, sock, IPPROTO_IP, IP_LOCAL_PORT_RANGE, (char *)&range, sizeof(range))){ *SAPORT(sa) = 0; return param->srv->so._bind(param->sostate, sock, (struct sockaddr *)sa, SASIZE(sa)); } #endif first = (uint16_t)(range & 0xffff); last = (uint16_t)(range >> 16); while(*tries > 0){ (*tries)--; *SAPORT(sa) = htons((uint16_t)(first + (myrand() % (unsigned)(last - first + 1)))); if(!param->srv->so._bind(param->sostate, sock, (struct sockaddr *)sa, SASIZE(sa))) return 0; } /* Every port tried was taken. Fall back to an ephemeral one, which is what the kernel option above does when it cannot honour the range, so an exhausted range behaves the same way on every platform. */ *SAPORT(sa) = 0; return param->srv->so._bind(param->sostate, sock, (struct sockaddr *)sa, SASIZE(sa)); } int bindwithrange(struct clientparam *param, SOCKET sock, PROXYSOCKADDRTYPE *sa, uint32_t range) { int tries = RANGETRIES; return bindrange(param, sock, sa, range, &tries); } int scanaddr(const unsigned char *s, uint32_t * ip, uint32_t * mask) { unsigned d1, d2, d3, d4, m; int res; if ((res = sscanf((char *)s, "%u.%u.%u.%u/%u", &d1, &d2, &d3, &d4, &m)) < 4) return 0; if(mask && res == 4) *mask = 0xFFFFFFFF; else if (mask) *mask = htonl(0xFFFFFFFF << (32 - m)); *ip = htonl ((d1<<24) ^ (d2<<16) ^ (d3<<8) ^ d4); return res; } /* The default resolver: name servers, configured or the system's, or NULL for the system routines. resolvmode is the configuration's, for names resolved outside a service; each service has its own. */ /* Milliseconds on a clock which only goes forward, at the same pace as the time of day but not moved with it: a deadline does not come at once, or never, when the clock of the system is set. */ uint64_t monotime(void){ #ifdef _WIN32 LARGE_INTEGER c, f; QueryPerformanceFrequency(&f); QueryPerformanceCounter(&c); return (uint64_t)(c.QuadPart / f.QuadPart) * 1000 + (uint64_t)(c.QuadPart % f.QuadPart) * 1000 / (uint64_t)f.QuadPart; #elif defined(CLOCK_MONOTONIC) struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; #else struct timeval tv; gettimeofday(&tv, NULL); return (uint64_t)tv.tv_sec * 1000 + (uint64_t)tv.tv_usec / 1000; #endif } RESOLVFUNC resolvfunc = NULL; int resolvmode = RESOLVE_DEFAULT; uint32_t fakeresolver (int af, unsigned char *name, unsigned char * value){ if(af == AF_INET6){ memset(value, 0, 16); value[15] = 2; } else { value[0] = 127; value[1] = 0; value[2] = 0; value[3] = 2; } return 1; } /* The resolver of a mode, NULL for the system routines */ static RESOLVFUNC moderesolver(int mode){ switch(mode){ case RESOLVE_FAKE: return fakeresolver; case RESOLVE_SYSTEM: return NULL; } return resolvfunc; } int afdetect(unsigned char *name){ int ndots=0, ncols=0, nhex=0; int i; for(i=0; name[i]; i++){ if(name[i] == '.'){ if(++ndots > 3) { return -1; } } else if(name[i] == ':'){ if(++ncols > 7) { return -1; } } else if(name[i] == '%' || (name[i] >= 'a' && name[i] <= 'f') || (name[i] >= 'A' && name[i] <= 'F')){ nhex++; } else if(name[i] <'0' || name[i] >'9') { return -1; } } if(ndots == 3 && ncols == 0 && nhex == 0){ return AF_INET; } if(ncols >= 2) { return AF_INET6; } return -1; } /* A name resolved the way a mode says: a service's names with its own */ #ifndef NOSTDRESOLVE /* What the C library's resolver is asked, and its answer */ struct stdresolve { unsigned char *name; int family; struct sockaddr *sa; uint32_t res; }; /* getaddrinfo(): run on a thread's own stack, which glibc may take much of, for IPv6 most (alloca() sized by the thread's stack, not a fiber's) */ static void stdresolve46(void *arg){ struct stdresolve *r = (struct stdresolve *)arg; struct addrinfo *ai, hint; r->res = 0; memset(&hint, 0, sizeof(hint)); hint.ai_family = (r->family == 6 || r->family == 64)?AF_INET6:AF_INET; if (getaddrinfo((char *)r->name, NULL, &hint, &ai)) { if(r->family == 64 || r->family == 46){ hint.ai_family = (r->family == 64)?AF_INET:AF_INET6; if (getaddrinfo((char *)r->name, NULL, &hint, &ai)) return; } else return; } if(ai){ if(ai->ai_addr->sa_family == AF_INET || ai->ai_addr->sa_family == AF_INET6){ *SAFAMILY(r->sa)=ai->ai_addr->sa_family; memcpy(SAADDR(r->sa), SAADDR(ai->ai_addr), SAADDRLEN(ai->ai_addr)); r->res = *SAFAMILY(r->sa); } freeaddrinfo(ai); } } #endif uint32_t getip46m(int mode, int family, unsigned char *name, struct sockaddr *sa){ int detect; RESOLVFUNC tmpresolv; if(!sa) return 0; if(!family) { family = 4; } detect = afdetect(name); if(detect != -1){ if(family == 4 && detect != AF_INET) return 0; *SAFAMILY(sa) = (family == 6)? AF_INET6 : detect; return inet_pton(*SAFAMILY(sa), (char *)name, SAADDR(sa))>0? *SAFAMILY(sa) : 0; } if((tmpresolv = moderesolver(mode))){ int f = (family == 6 || family == 64)?AF_INET6:AF_INET; *SAFAMILY(sa) = f; if(tmpresolv(f, name, SAADDR(sa))) return f; if(family == 4 || family == 6) return 0; f = (family == 46)? AF_INET6 : AF_INET; *SAFAMILY(sa) = f; if(tmpresolv(f, name, SAADDR(sa))) return f; return 0; } #ifndef NOSTDRESOLVE { struct stdresolve r; r.name = name; r.family = family; r.sa = sa; /* a fiber's stack is not one to give it */ if(onthreadstackfunc) (*onthreadstackfunc)(stdresolve46, &r); else stdresolve46(&r); return r.res; } #endif return 0; } uint32_t getip46(int family, unsigned char *name, struct sockaddr *sa){ return getip46m(resolvmode, family, name, sa); } int hascap(const unsigned char *line, const char *cap){ int len = (int)strlen(cap); for(; *line; line++) if(!strncasecmp((char *)line, cap, len)) return 1; return 0; } int getmultiline(struct clientparam *param, DIRECTION which, unsigned char *buf, int bufsize, const char *cap, int *found){ int i; do { i = sockgetlinebuf(param, which, buf, bufsize, '\n', param->srv->timeouts[STRING_L]); if(i > 0 && cap && found && !*found){ buf[i] = 0; if(hascap(buf, cap)) *found = 1; } } while (i > 3 && buf[3] == '-'); return i; }