📄 util.c
字号:
}void#ifdef STDC_HEADERSswarnx(const char *fmt, ...)#elseswarnx(fmt, va_alist) const char *fmt; va_dcl#endif /* STDC_HEADERS */{ if (fmt != NULL) { va_list ap;#ifdef STDC_HEADERS /* LINTED pointer casts may be troublesome */ va_start(ap, fmt);#else va_start(ap);#endif /* STDC_HEADERS */ vslog(LOG_ERR, fmt, ap); /* LINTED expression has null effect */ va_end(ap); }}in_addr_tsocks_addfakeip(host) const char *host;{ const char *function = "socks_addfakeip()"; char **tmpmem; struct in_addr addr; if (socks_getfakeip(host, &addr) == 1) return addr.s_addr;#if FAKEIP_END < FAKEIP_STARTerror "\"FAKEIP_END\" can't be smaller than \"FAKEIP_START\""#endif if (ipc >= FAKEIP_END - FAKEIP_START) { swarnx("%s: fakeip range (%d - %d) exhausted", function, FAKEIP_START, FAKEIP_END); return INADDR_NONE; } if ((tmpmem = (char **)realloc(ipv, sizeof(*ipv) * (ipc + 1))) == NULL || (tmpmem[ipc] = (char *)malloc(sizeof(*tmpmem) * (strlen(host) + 1))) == NULL) { swarnx("%s: %s", function, NOMEM); return INADDR_NONE; } ipv = tmpmem; strcpy(ipv[ipc], host); return htonl(ipc++ + FAKEIP_START);}const char *socks_getfakehost(addr) in_addr_t addr;{ if (ntohl(addr) - FAKEIP_START < ipc) return ipv[ntohl(addr) - FAKEIP_START]; return NULL;}intsocks_getfakeip(host, addr) const char *host; struct in_addr *addr;{ unsigned int i; for (i = 0; i < ipc; ++i) if (strcasecmp(host, ipv[i]) == 0) { addr->s_addr = htonl(i + FAKEIP_START); return 1; } return 0;}struct sockshost_t *fakesockaddr2sockshost(addr, host) const struct sockaddr *addr; struct sockshost_t *host;{ const char *function = "fakesockaddr2sockshost()";#if SOCKS_CLIENT /* may be called before normal init, log to right place. */ clientinit();#endif /* LINTED pointer casts may be troublesome */ slog(LOG_DEBUG, "%s: %s -> %s", function, sockaddr2string(addr, NULL, 0), socks_getfakehost(((const struct sockaddr_in *)addr)->sin_addr.s_addr) == NULL ? sockaddr2string(addr, NULL, 0) : socks_getfakehost(((const struct sockaddr_in *)addr)->sin_addr.s_addr)); /* LINTED pointer casts may be troublesome */ if (socks_getfakehost(((const struct sockaddr_in *)addr)->sin_addr.s_addr) != NULL) { const char *ipname /* LINTED pointer casts may be troublesome */ = socks_getfakehost(((const struct sockaddr_in *)addr)->sin_addr.s_addr); SASSERTX(ipname != NULL); host->atype = SOCKS_ADDR_DOMAIN; SASSERTX(strlen(ipname) < sizeof(host->addr.domain)); strcpy(host->addr.domain, ipname); /* LINTED pointer casts may be troublesome */ host->port = ((const struct sockaddr_in *)addr)->sin_port; } else sockaddr2sockshost(addr, host); return host;}const char *socks_packet2string(packet, type) const void *packet; int type;{ static char buf[1024]; char hstring[MAXSOCKSHOSTSTRING]; unsigned char version; const struct request_t *request = NULL; const struct response_t *response = NULL; switch (type) { case SOCKS_REQUEST: request = (const struct request_t *)packet; version = request->version; break; case SOCKS_RESPONSE: response = (const struct response_t *)packet; version = response->version; break; default: SERRX(type); } switch (version) { case SOCKS_V4: case SOCKS_V4REPLY_VERSION: switch (type) { case SOCKS_REQUEST: snprintf(buf, sizeof(buf), "(V4) VN: %d CD: %d address: %s", request->version, request->command, sockshost2string(&request->host, hstring, sizeof(hstring))); break; case SOCKS_RESPONSE: snprintf(buf, sizeof(buf), "(V4) VN: %d CD: %d address: %s", response->version, response->reply, sockshost2string(&response->host, hstring, sizeof(hstring))); break; } break; case SOCKS_V5: switch (type) { case SOCKS_REQUEST: snprintf(buf, sizeof(buf), "VER: %d CMD: %d FLAG: %d ATYP: %d address: %s", request->version, request->command, request->flag, request->host.atype, sockshost2string(&request->host, hstring, sizeof(hstring))); break; case SOCKS_RESPONSE: snprintf(buf, sizeof(buf), "VER: %d REP: %d FLAG: %d ATYP: %d address: %s", response->version, response->reply, response->flag, response->host.atype, sockshost2string(&response->host, hstring, sizeof(hstring))); break; } break; default: SERRX(version); } return buf;}intsocks_logmatch(d, log) unsigned int d; const struct logtype_t *log;{ int i; for (i = 0; i < log->fpc; ++i) if (d == (unsigned int)log->fplockv[i] || d == (unsigned int)fileno(log->fpv[i])) return 1; return 0;}intsockaddrareeq(a, b) const struct sockaddr *a; const struct sockaddr *b;{ if (a->sa_family != b->sa_family) return 0; switch (a->sa_family) { case AF_INET: { /* LINTED pointer casts may be troublesome */ const struct sockaddr_in *in_a = (const struct sockaddr_in *)a; /* LINTED pointer casts may be troublesome */ const struct sockaddr_in *in_b = (const struct sockaddr_in *)b; if (in_a->sin_addr.s_addr != in_b->sin_addr.s_addr || in_a->sin_port != in_b->sin_port) return 0; return 1; } default: SERRX(a->sa_family); } /* NOTREACHED */}intsockshostareeq(a, b) const struct sockshost_t *a; const struct sockshost_t *b;{ if (a->atype != b->atype) return 0; switch (a->atype) { case SOCKS_ADDR_IPV4: if (memcmp(&a->addr.ipv4, &b->addr.ipv4, sizeof(a->addr.ipv4)) != 0) return 0; break; case SOCKS_ADDR_IPV6: if (memcmp(a->addr.ipv6, b->addr.ipv6, sizeof(a->addr.ipv6)) != 0) return 0; break; case SOCKS_ADDR_DOMAIN: if (strcmp(a->addr.domain, b->addr.domain) != 0) return 0; break; default: SERRX(a->atype); } if (a->port != b->port) return 0; return 1;}intfdsetop(nfds, op, a, b, result) int nfds; int op; const fd_set *a; const fd_set *b; fd_set *result;{ int i, bits; FD_ZERO(result); bits = -1; switch (op) { case '&': for (i = 0; i < nfds; ++i) if (FD_ISSET(i, a) && FD_ISSET(i, b)) { FD_SET(i, result); bits = MAX(i, bits); } break; case '^': for (i = 0; i < nfds; ++i) if (FD_ISSET(i, a) != FD_ISSET(i, b)) { FD_SET(i, result); bits = MAX(i, bits); } break; default: SERRX(op); } return bits;}intmethodisset(method, methodv, methodc) int method; const int *methodv; size_t methodc;{ size_t i; for (i = 0; i < methodc; ++i) if (methodv[i] == method) return 1; return 0;}intsocketoptdup(s) int s;{ const char *function = "socketoptdup()"; unsigned int i; int flags, new_s; socklen_t len; union { int int_val; struct linger linger_val; struct timeval timeval_val; struct in_addr in_addr_val; u_char u_char_val; struct sockaddr sockaddr_val; struct ipoption ipoption; } val; int levelname[][2] = { /* socket options */#ifdef SO_BROADCAST { SOL_SOCKET, SO_BROADCAST },#endif#ifdef SO_DEBUG { SOL_SOCKET, SO_DEBUG },#endif#ifdef SO_DONTROUTE { SOL_SOCKET, SO_DONTROUTE },#endif#ifdef SO_ERROR { SOL_SOCKET, SO_ERROR },#endif#ifdef SO_KEEPALIVE { SOL_SOCKET, SO_KEEPALIVE },#endif#ifdef SO_LINGER { SOL_SOCKET, SO_LINGER },#endif#ifdef SO_OOBINLINE { SOL_SOCKET, SO_OOBINLINE },#endif#ifdef SO_RCVBUF { SOL_SOCKET, SO_RCVBUF },#endif#ifdef SO_SNDBUF { SOL_SOCKET, SO_SNDBUF },#endif#ifdef SO_RCVLOWAT { SOL_SOCKET, SO_RCVLOWAT },#endif#ifdef SO_SNDLOWAT { SOL_SOCKET, SO_SNDLOWAT },#endif#ifdef SO_RCVTIMEO { SOL_SOCKET, SO_RCVTIMEO },#endif#ifdef SO_SNDTIMEO { SOL_SOCKET, SO_SNDTIMEO },#endif#ifdef SO_REUSEADDR { SOL_SOCKET, SO_REUSEADDR },#endif#ifdef SO_REUSEPORT { SOL_SOCKET, SO_REUSEPORT },#endif#ifdef SO_USELOOPBACK { SOL_SOCKET, SO_USELOOPBACK },#endif /* IP options */#ifdef IP_HDRINCL { IPPROTO_IP, IP_HDRINCL },#endif#ifdef IP_OPTIONS { IPPROTO_IP, IP_OPTIONS },#endif#ifdef IP_RECVDSTADDR { IPPROTO_IP, IP_RECVDSTADDR },#endif#ifdef IP_RECVIF { IPPROTO_IP, IP_RECVIF },#endif#ifdef IP_TOS { IPPROTO_IP, IP_TOS },#endif#ifdef IP_TTL { IPPROTO_IP, IP_TTL },#endif#ifdef IP_MULTICAST_IF { IPPROTO_IP, IP_MULTICAST_IF },#endif#ifdef IP_MULTICAST_TTL { IPPROTO_IP, IP_MULTICAST_TTL },#endif#ifdef IP_MULTICAST_LOOP { IPPROTO_IP, IP_MULTICAST_LOOP },#endif /* TCP options */#ifdef TCP_KEEPALIVE { IPPROTO_TCP, TCP_KEEPALIVE },#endif#ifdef TCP_MAXRT { IPPROTO_TCP, TCP_MAXRT },#endif#ifdef TCP_MAXSEG { IPPROTO_TCP, TCP_MAXSEG },#endif#ifdef TCP_NODELAY { IPPROTO_TCP, TCP_NODELAY },#endif#ifdef TCP_STDURG { IPPROTO_TCP, TCP_STDURG }#endif }; len = sizeof(val); if (getsockopt(s, SOL_SOCKET, SO_TYPE, &val, &len) == -1) { swarn("%s: getsockopt(SO_TYPE)", function); return -1; } if ((new_s = socket(AF_INET, val.int_val, 0)) == -1) { swarn("%s: socket(AF_INET, %d)", function, val.int_val); return -1; } for (i = 0; i < ELEMENTS(levelname); ++i) { len = sizeof(val); if (getsockopt(s, levelname[i][0], levelname[i][1], &val, &len) == -1) { if (config.option.debug) swarn("%s: getsockopt(%d, %d)", function, levelname[i][0], levelname[i][1]); continue; } if (setsockopt(new_s, levelname[i][0], levelname[i][1], &val, len) == -1) swarn("%s: setsockopt(%d, %d)", function, levelname[i][0], levelname[i][1]); } if ((flags = fcntl(s, F_GETFL, 0)) == -1 || fcntl(new_s, F_SETFL, flags) == -1) swarn("%s: fcntl(F_GETFL/F_SETFL)", function);#if SOCKS_SERVER && HAVE_LIBWRAP if ((s = fcntl(new_s, F_GETFD, 0)) == -1 || fcntl(new_s, F_SETFD, s | FD_CLOEXEC) == -1) swarn("%s: fcntl(F_GETFD/F_SETFD)", function);#endif return new_s;}char *str2vis(string, len) const char *string; size_t len;{ const int visflag = VIS_TAB | VIS_NL | VIS_CSTYLE | VIS_OCTAL; char *visstring; /* see vis(3) for "* 4" */ if ((visstring = (char *)malloc((sizeof(*visstring) * len * 4) + sizeof(char))) != NULL) strvisx(visstring, string, len, visflag); return visstring;}intsocks_mklock(template) const char *template;{ const char *function = "socks_mklock()"; char *prefix, *newtemplate; int s; size_t len;#if SOCKS_SERVER && HAVE_LIBWRAP int flag;#endif if ((prefix = getenv("TMPDIR")) != NULL) if (*prefix == NUL) prefix = NULL; if (prefix == NULL) prefix = "/tmp"; len = strlen(prefix) + strlen("/") + strlen(template) + 1; if ((newtemplate = (char *)malloc(sizeof(*newtemplate) * len)) == NULL) return -1; snprintf(newtemplate, len, "%s/%s", prefix, template); if ((s = mkstemp(newtemplate)) == -1) { swarn("%s: mkstemp(%s)", function, newtemplate); free(newtemplate); return -1; } if (unlink(newtemplate) == -1) { swarn("%s: unlink(%s)", function, newtemplate); free(newtemplate); return -1; } free(newtemplate);#if SOCKS_SERVER && HAVE_LIBWRAP if ((flag = fcntl(s, F_GETFD, 0)) == -1 || fcntl(s, F_SETFD, flag | FD_CLOEXEC) == -1) swarn("%s: fcntl(F_GETFD/F_SETFD)", function);#endif return s;}intsocks_lock(descriptor, type, timeout) int descriptor; int type; int timeout;{/* const char *function = "socks_lock()"; */ struct flock lock; int rc; lock.l_type = (short)type; lock.l_start = 0; lock.l_whence = SEEK_SET; lock.l_len = 0; SASSERTX(timeout <= 0);#if 0 /* missing some bits here to handle racecondition. */ if (timeout > 0) { struct sigaction sigact;#if SOCKS_CLIENT if (sigaction(SIGALRM, NULL, &sigact) != 0) return -1; /* if handler already set for signal, don't override. */ if (sigact.sa_handler == SIG_DFL || sigact.sa_handler == SIG_IGN) {#else /* !SOCKS_CLIENT */ /* CONSTCOND */ if (1) {#endif /* !SOCKS_CLIENT */ sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigact.sa_handler = SIG_IGN; if (sigaction(SIGALRM, &sigact, NULL) != 0) return -1; } alarm((unsigned int)timeout); }#endif do rc = fcntl(descriptor, timeout ? F_SETLKW : F_SETLK, &lock); while (rc == -1 && timeout == -1 && errno == EINTR); if (rc == -1) switch (errno) { case EACCES: case EAGAIN: case EINTR: break; case ENOLCK: sleep(1); return socks_lock(descriptor, type, timeout); default: SERR(descriptor); }#if 0 if (timeout > 0) alarm(0);#endif if (rc != 0 && timeout == -1) abort(); return rc == -1 ? rc : 0;}voidsocks_unlock(d) int d;{ socks_lock(d, F_UNLCK, -1);}intsocks_socketisbound(s) int s;{ struct sockaddr_in addr; socklen_t len; len = sizeof(addr); /* LINTED pointer casts may be troublesome */ if (getsockname(s, (struct sockaddr *)&addr, &len) != 0) return -1; return ADDRISBOUND(addr);}intfreedescriptors(message) const char *message;{ const int errno_s = errno; int i, freed, max; /* LINTED expression has null effect */ for (freed = 0, i = 0, max = getdtablesize(); i < max; ++i) if (!fdisopen(i)) ++freed; if (message != NULL) slog(LOG_DEBUG, "freedescriptors(%s): %d/%d", message, freed, max); errno = errno_s; return freed;}intfdisopen(fd) int fd;{ if (fcntl(fd, F_GETFD, 0) == 0) return 1; return 0;}voidclosev(array, count) int *array; int count;{ for (--count; count >= 0; --count) if (array[count] >= 0) if (close(array[count]) != 0) SERR(-1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -