📄 util.c
字号:
/* * Copyright (c) 1997, 1998, 1999 * Inferno Nettverk A/S, Norway. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. The above copyright notice, this list of conditions and the following * disclaimer must appear in all copies of the software, derivative works * or modified versions, and any portions thereof, aswell as in all * supporting documentation. * 2. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by * Inferno Nettverk A/S, Norway. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Inferno Nettverk A/S requests users of this software to return to * * Software Distribution Coordinator or sdc@inet.no * Inferno Nettverk A/S * Oslo Research Park * Gaustadal閑n 21 * N-0349 Oslo * Norway * * any improvements or extensions that they make and grant Inferno Nettverk A/S * the rights to redistribute these changes. * */#include "common.h"/* XXX */#if HAVE_STRVIS#include <vis.h>#else#include "compat.h"#endif /* HAVE_STRVIS */static const char rcsid[] ="$Id: util.c,v 1.98 1999/12/22 09:29:25 karls Exp $";/* fake "ip address", for clients without dns access. */static char **ipv;static in_addr_t ipc;const char *strcheck(string) const char *string;{ return string == NULL ? NOMEM : string;}char *sockshost2string(host, string, len) const struct sockshost_t *host; char *string; size_t len;{ if (string == NULL) { /* to ease debugging. */ static char hstring[MAXSOCKSHOSTSTRING]; string = hstring; len = sizeof(hstring); } switch (host->atype) { case SOCKS_ADDR_IPV4: snprintf(string, len, "%s.%d", inet_ntoa(host->addr.ipv4), ntohs(host->port)); break; case SOCKS_ADDR_IPV6: snprintf(string, len, "%s.%d", "<IPV6 address not supported>", ntohs(host->port)); break; case SOCKS_ADDR_DOMAIN: snprintf(string, len, "%s.%d", host->addr.domain, ntohs(host->port)); break; default: SERRX(host->atype); } return string;}const char *command2string(command) int command;{ switch (command) { case SOCKS_BIND: return SOCKS_BINDs; case SOCKS_CONNECT: return SOCKS_CONNECTs; case SOCKS_UDPASSOCIATE: return SOCKS_UDPASSOCIATEs; /* pseudo commands. */ case SOCKS_ACCEPT: return SOCKS_ACCEPTs; case SOCKS_BINDREPLY: return SOCKS_BINDREPLYs; case SOCKS_UDPREPLY: return SOCKS_UDPREPLYs; case SOCKS_DISCONNECT: return SOCKS_DISCONNECTs; default: SERRX(command); } /* NOTREACHED */}const char *method2string(method) int method;{ switch (method) { case AUTHMETHOD_NONE: return AUTHMETHOD_NONEs; case AUTHMETHOD_GSSAPI: return AUTHMETHOD_GSSAPIs; case AUTHMETHOD_UNAME: return AUTHMETHOD_UNAMEs; case AUTHMETHOD_NOACCEPT: return AUTHMETHOD_NOACCEPTs; case AUTHMETHOD_RFC931: return AUTHMETHOD_RFC931s; default: SERRX(method); } /* NOTREACHED */}intstring2method(methodname) const char *methodname;{ struct { char *methodname; int method; } method[] = { { AUTHMETHOD_NONEs, AUTHMETHOD_NONE }, { AUTHMETHOD_UNAMEs, AUTHMETHOD_UNAME }, { AUTHMETHOD_RFC931s, AUTHMETHOD_RFC931 } }; size_t i; for (i = 0; i < ELEMENTS(method); ++i) if (strcmp(method[i].methodname, methodname) == 0) return method[i].method; return -1;}intsockscode(version, code) int version; int code;{ switch (version) { case SOCKS_V4: case SOCKS_V4REPLY_VERSION: switch (code) { case SOCKS_SUCCESS: return SOCKSV4_SUCCESS; default: return SOCKSV4_FAIL; /* v4 is not very specific. */ } /* NOTREACHED */ case SOCKS_V5: switch (code) { default: return code; /* current codes are all V5. */ } /* NOTREACHED */ case MSPROXY_V2: switch (code) { case SOCKS_SUCCESS: return MSPROXY_SUCCESS; case SOCKS_FAILURE: return MSPROXY_FAILURE; default: SERRX(code); } /* NOTREACHED */ default: SERRX(version); } /* NOTREACHED */}interrno2reply(errnum, version) int errnum; int version;{ switch (errnum) { case ENETUNREACH: return sockscode(version, SOCKS_NETUNREACH); case EHOSTUNREACH: return sockscode(version, SOCKS_HOSTUNREACH); case ECONNREFUSED: return sockscode(version, SOCKS_CONNREFUSED); case ETIMEDOUT: return sockscode(version, SOCKS_TTLEXPIRED); } return sockscode(version, SOCKS_FAILURE);}struct sockaddr *sockshost2sockaddr(host, addr) const struct sockshost_t *host; struct sockaddr *addr;{ const char *function = "sockshost2sockaddr()"; bzero(addr, sizeof(*addr)); /* LINTED pointer casts may be troublesome */ ((struct sockaddr_in *)addr)->sin_family = AF_INET; switch (host->atype) { case SOCKS_ADDR_IPV4: /* LINTED pointer casts may be troublesome */ ((struct sockaddr_in *)addr)->sin_addr = host->addr.ipv4; break; case SOCKS_ADDR_DOMAIN: { struct hostent *hostent; if ((hostent = gethostbyname(host->addr.domain)) == NULL || hostent->h_addr_list == NULL) { /* LINTED pointer casts may be troublesome */ swarnx("%s: gethostbyname(%s): %s", function, host->addr.domain, hstrerror(h_errno)); /* LINTED pointer casts may be troublesome */ ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(INADDR_ANY); break; } /* LINTED pointer casts may be troublesome */ ((struct sockaddr_in *)addr)->sin_addr = *(struct in_addr *)(*hostent->h_addr_list); break; } default: SERRX(host->atype); } /* LINTED pointer casts may be troublesome */ ((struct sockaddr_in *)addr)->sin_port = host->port; /* LINTED pointer casts may be troublesome */ return addr;}struct sockaddr *fakesockshost2sockaddr(host, addr) const struct sockshost_t *host; struct sockaddr *addr;{ const char *function = "fakesockshost2sockaddr()";#if SOCKS_CLIENT /* may be called before normal init, log to right place. */ clientinit();#endif slog(LOG_DEBUG, "%s: %s", function, sockshost2string(host, NULL, 0)); bzero(addr, sizeof(*addr)); /* LINTED pointer casts may be troublesome */ ((struct sockaddr_in *)addr)->sin_family = AF_INET; switch (host->atype) { case SOCKS_ADDR_DOMAIN: /* LINTED pointer casts may be troublesome */ if (socks_getfakeip(host->addr.domain, &((struct sockaddr_in *)addr)->sin_addr)) { /* LINTED pointer casts may be troublesome */ break; } /* else; */ /* FALLTHROUGH */ default: return sockshost2sockaddr(host, addr); } /* LINTED pointer casts may be troublesome */ ((struct sockaddr_in *)addr)->sin_port = host->port; return addr;}struct sockshost_t *sockaddr2sockshost(addr, host) const struct sockaddr *addr; struct sockshost_t *host;{ switch (addr->sa_family) { case AF_INET: host->atype = SOCKS_ADDR_IPV4; /* LINTED pointer casts may be troublesome */ host->addr.ipv4 = ((const struct sockaddr_in *)addr)->sin_addr; /* LINTED pointer casts may be troublesome */ host->port = ((const struct sockaddr_in *)addr)->sin_port; break; default: SERRX(addr->sa_family); } return host;}const char *operator2string(operator) enum operator_t operator;{ switch (operator) { case none: return "none"; case eq: return "eq"; case neq: return "neq"; case ge: return "ge"; case le: return "le"; case gt: return "gt"; case lt: return "lt"; case range: return "range"; default: SERRX(operator); } /* NOTREACHED */}enum operator_tstring2operator(string) const char *string;{ if (strcmp(string, "eq") == 0 || strcmp(string, "=") == 0) return eq; if (strcmp(string, "neq") == 0 || strcmp(string, "!=") == 0) return neq; if (strcmp(string, "ge") == 0 || strcmp(string, ">=") == 0) return ge; if (strcmp(string, "le") == 0 || strcmp(string, "<=") == 0) return le; if (strcmp(string, "gt") == 0 || strcmp(string, ">") == 0) return gt; if (strcmp(string, "lt") == 0 || strcmp(string, "<") == 0) return lt; /* parser should make sure this never happens. */ SERRX(string); /* NOTREACHED */}const char *ruleaddress2string(address, string, len) const struct ruleaddress_t *address; char *string; size_t len;{ switch (address->atype) { case SOCKS_ADDR_IPV4: { char *a, *b; snprintf(string, len, "%s/%s, tcp port: %d, udp port: %d op: %s %d", strcheck(a = strdup(inet_ntoa(address->addr.ipv4.ip))), strcheck(b = strdup(inet_ntoa(address->addr.ipv4.mask))), ntohs(address->port.tcp), ntohs(address->port.udp), operator2string(address->operator), ntohs(address->portend)); free(a); free(b); break; } case SOCKS_ADDR_DOMAIN: snprintf(string, len, "%s, tcp port: %d, udp port: %d op: %s %d", address->addr.domain, ntohs(address->port.tcp), ntohs(address->port.udp), operator2string(address->operator), ntohs(address->portend)); break; default: SERRX(address->atype); } return string;}struct sockshost_t *ruleaddress2sockshost(address, host, protocol) const struct ruleaddress_t *address; struct sockshost_t *host; int protocol;{ switch (host->atype = address->atype) { case SOCKS_ADDR_IPV4: host->addr.ipv4 = address->addr.ipv4.ip; break; case SOCKS_ADDR_DOMAIN: SASSERTX(strlen(address->addr.domain) < sizeof(host->addr.domain)); strcpy(host->addr.domain, address->addr.domain); break; default: SERRX(address->atype); } switch (protocol) { case SOCKS_TCP: host->port = address->port.tcp; break; case SOCKS_UDP: host->port = address->port.udp; break; default: SERRX(protocol); } return host;}struct ruleaddress_t *sockshost2ruleaddress(host, addr) const struct sockshost_t *host; struct ruleaddress_t *addr;{ switch (addr->atype = host->atype) { case SOCKS_ADDR_IPV4: addr->addr.ipv4.ip = host->addr.ipv4; addr->addr.ipv4.mask.s_addr = htonl(0xffffffff); break; case SOCKS_ADDR_DOMAIN: SASSERTX(strlen(host->addr.domain) < sizeof(addr->addr.domain)); strcpy(addr->addr.domain, host->addr.domain); break; default: SERRX(host->atype); } addr->port.tcp = host->port; addr->port.udp = host->port; addr->portend = host->port; if (host->port == htons(0)) addr->operator = none; else addr->operator = eq; return addr;}struct ruleaddress_t *sockaddr2ruleaddress(addr, ruleaddr) const struct sockaddr *addr; struct ruleaddress_t *ruleaddr;{ struct sockshost_t host; sockaddr2sockshost(addr, &host); sockshost2ruleaddress(&host, ruleaddr); return ruleaddr;}const char *protocol2string(protocol) int protocol;{ switch (protocol) { case SOCKS_TCP: return PROTOCOL_TCPs; case SOCKS_UDP: return PROTOCOL_UDPs; default: SERRX(protocol); } /* NOTREACHED */}char *sockaddr2string(address, string, len) const struct sockaddr *address; char *string; size_t len;{ if (string == NULL) { static char addrstring[MAXSOCKADDRSTRING]; string = addrstring; len = sizeof(addrstring); } switch (address->sa_family) { case AF_UNIX: { /* LINTED pointer casts may be troublesome */ const struct sockaddr_un *addr = (const struct sockaddr_un *)address; strncpy(string, addr->sun_path, len - 1); string[len - 1] = NUL; break; } case AF_INET: { /* LINTED pointer casts may be troublesome */ const struct sockaddr_in *addr = (const struct sockaddr_in *)address; snprintf(string, len, "%s.%d", inet_ntoa(addr->sin_addr), ntohs(addr->sin_port)); break; } default: SERRX(address->sa_family); } return string;}void#ifdef STDC_HEADERSserr(int eval, const char *fmt, ...)#elseserr(eval, fmt, va_alist) int eval; const char *fmt; va_dcl#endif /* STDC_HEADERS */{ if (fmt != NULL) { va_list ap; char buf[2048]; size_t bufused;#ifdef STDC_HEADERS /* LINTED pointer casts may be troublesome */ va_start(ap, fmt);#else va_start(ap);#endif /* STDC_HEADERS */ bufused = vsnprintf(buf, sizeof(buf), fmt, ap); bufused += snprintf(&buf[bufused], sizeof(buf) - bufused, ": %s (errno = %d)", strerror(errno), errno); slog(LOG_ERR, buf); /* LINTED expression has null effect */ va_end(ap); }#if SOCKS_SERVER sockdexit(-eval);#else exit(eval);#endif}void#ifdef STDC_HEADERSserrx(int eval, const char *fmt, ...)#elseserrx(eval, fmt, va_alist) int eval; 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); }#if SOCKS_SERVER sockdexit(-eval);#else exit(eval);#endif}void#ifdef STDC_HEADERSswarn(const char *fmt, ...)#elseswarn(fmt, va_alist) const char *fmt; va_dcl#endif /* STDC_HEADERS */{ if (fmt != NULL) { va_list ap; char buf[2048]; size_t bufused;#ifdef STDC_HEADERS /* LINTED pointer casts may be troublesome */ va_start(ap, fmt);#else va_start(ap);#endif /* STDC_HEADERS */ bufused = vsnprintf(buf, sizeof(buf), fmt, ap); bufused += snprintf(&buf[bufused], sizeof(buf) - bufused, ": %s (errno = %d)", strerror(errno), errno); slog(LOG_ERR, buf); /* LINTED expression has null effect */ va_end(ap); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -