📄 config.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"static const char rcsid[] ="$Id: config.c,v 1.119 1999/12/20 13:07:41 karls Exp $";__BEGIN_DECLSstatic intaddrisinlist __P((const struct in_addr *addr, const struct in_addr *mask, const struct in_addr **list));/* * Compares "addr" bitwise anded with "mask" against each element in * "list" bitwise anded with "mask". "list" is NULL terminated. * Returns: * If "list" contains a element matching "addr" and "mask": true * else: false */static intaddrareeq __P((const struct in_addr *addr, const struct in_addr *mask, const struct in_addr *against));/* * Compares "addr" bitwise anded with "mask" against "against" bitwise * anded with "mask". * Returns: * If "against" matches "addr" and "mask": true * else: false */static inthostisinlist __P((const char *host, const char **list));/* * Compares "host" against each element in "list", which is NULL * terminated. * Note that if "host" starts with a dot, it will match "list" if the * last part of "list" matches the part after the dot in "host". * Returns: * If "list" contains a element matching "host": true * else: false */static inthostareeq __P((const char *domain, const char *remotedomain));/* * Compares the rulegiven domain "domain" against "remotedomain". * Note that if "domain" starts with a dot, it will match * "remotedomain" if the last part of "remotedomain" matches * the part after the dot in "domain". * Returns: * on match: true * else: false */__END_DECLSvoidgenericinit(void){ const char *function = "genericinit()"; int i; if (!config.state.init) {#if !HAVE_SETPROCTITLE /* create a backup to avoid setproctitle replacement overwriting it. */ if ((__progname = strdup(__progname)) == NULL) serrx(EXIT_FAILURE, "%s: %s", function, NOMEM);#endif /* !HAVE_SETPROCTITLE */ } if (readconfig(config.option.configfile) != 0)#if SOCKS_SERVER exit(EXIT_FAILURE);#else return;#endif initlog();#if !HAVE_NO_RESOLVESTUFF res_init();#endif /* !HAVE_NO_RESOLVSTUFF */ switch (config.resolveprotocol) { case RESOLVEPROTOCOL_TCP:#if !HAVE_NO_RESOLVESTUFF _res.options |= RES_USEVC;#else /* HAVE_NO_RESOLVESTUFF */ SERRX(config.resolveprotocol);#endif /* HAVE_NO_RESOLVESTUFF */ break; case RESOLVEPROTOCOL_UDP: case RESOLVEPROTOCOL_FAKE: break; default: SERRX(config.resolveprotocol); } if (!config.state.init) if (config.option.lbuf) for (i = 0; i < config.log.fpc; ++i) if (setvbuf(config.log.fpv[i], NULL, _IOLBF, 0) != 0) swarn("%s: setvbuf(_IOLBF)", function); config.state.init = 1;}intaddressmatch(rule, address, protocol, alias) const struct ruleaddress_t *rule; const struct sockshost_t *address; int protocol; int alias;{ const char *function = "addressmatch()"; struct hostent *hostent; in_port_t ruleport; int matched, doresolve; /* test port first since we have all info needed for that locally. */ switch (protocol) { case SOCKS_TCP: ruleport = rule->port.tcp; break; case SOCKS_UDP: ruleport = rule->port.udp; break; default: SERRX(protocol); } switch (rule->operator) { case none: break; case eq: if (address->port == ruleport) break; return 0; case neq: if (address->port != ruleport) break; return 0; case ge: if (ntohs(address->port) >= ntohs(ruleport)) break; return 0; case le: if (ntohs(address->port) <= ntohs(ruleport)) break; return 0; case gt: if (ntohs(address->port) > ntohs(ruleport)) break; return 0; case lt: if (ntohs(address->port) < ntohs(ruleport)) break; return 0; case range: if (ntohs(address->port) >= ntohs(ruleport) && ntohs(address->port) <= ntohs(rule->portend)) break; return 0; default: SERRX(rule->operator); } /* only needed for client really... */ switch (config.resolveprotocol) { case RESOLVEPROTOCOL_TCP: case RESOLVEPROTOCOL_UDP: doresolve = 1; break; case RESOLVEPROTOCOL_FAKE: doresolve = 0; break; default: SERRX(config.resolveprotocol); } /* * The hard work begins. */ matched = 0; if (rule->atype == SOCKS_ADDR_IPV4 && address->atype == SOCKS_ADDR_DOMAIN) { /* * match(rule.ipaddress, address.hostname) * resolve address to ipaddress(es) and try to match each * resolved ipaddress against rule. * rule is in address->ipaddress(es) */ if (!doresolve) return 0; /* LINTED pointer casts may be troublesome */ if ((hostent = gethostbyname(address->addr.domain)) == NULL) { slog(LOG_DEBUG, "%s: gethostbyname(%s): %s", function, address->addr.domain, hstrerror(h_errno)); return 0; } if (addrisinlist(&rule->addr.ipv4.ip, &rule->addr.ipv4.mask, (const struct in_addr **)hostent->h_addr_list)) matched = 1; } else if (rule->atype == SOCKS_ADDR_IPV4 && address->atype == SOCKS_ADDR_IPV4) { /* * match(rule.ipaddress, address.ipaddress) * try first a simple comparison, address against rule. */ if (addrareeq(&rule->addr.ipv4.ip, &rule->addr.ipv4.mask, &address->addr.ipv4)) matched = 1; else { /* * Didn't match. If alias is set, try to resolve address * to hostname(s), the hostname back to ipaddress(es) and * then match those ipaddress(es) against rule. * rule is in address->hostname(s)->ipaddress(es) */ if (!doresolve) return 0; if (alias) { char *nexthost; int i; /* LINTED pointer casts may be troublesome */ if ((hostent = gethostbyaddr((const char *)&address->addr.ipv4, sizeof(address->addr.ipv4), AF_INET)) == NULL) { slog(LOG_DEBUG, "%s: %s: %s", function, inet_ntoa(address->addr.ipv4), hstrerror(h_errno)); return 0; } if ((hostent = hostentdup(hostent)) == NULL) { swarnx("%s: hostentdup()", function); return 0; } nexthost = hostent->h_name; i = 0; do { struct hostent *iphostent; /* iphostent = address->hostname(s)->ipaddress(es) */ if ((iphostent = gethostbyname(nexthost)) == NULL) { slog(LOG_DEBUG, "%s: gethostbyname(%s): %s", function, nexthost, hstrerror(h_errno)); continue; } /* rule is in address->hostname(s)->ipaddress(es) */ if (addrisinlist(&rule->addr.ipv4.ip, &rule->addr.ipv4.mask, (const struct in_addr **)iphostent->h_addr_list)) { matched = 1; break; } } while (hostent->h_aliases != NULL && (nexthost = hostent->h_aliases[i++]) != NULL); hostentfree(hostent); } if (!matched) return 0; } } else if (rule->atype == SOCKS_ADDR_DOMAIN && address->atype == SOCKS_ADDR_DOMAIN) { /* * match(rule.hostname, address.hostname) * Try simple match first. * * If no go and rule is a hostname rather than a domain, * resolve both rule and address to ipaddress(es) and compare * each ipaddress of resolved rule against each ipaddress of * resolved address. * rule->ipaddress(es) is in address->ipaddress(es) * */ if (hostareeq(rule->addr.domain, address->addr.domain)) matched = 1; else if (doresolve && *rule->addr.domain != '.') { struct hostent *addresshostent; struct in_addr mask; int i; if ((hostent = gethostbyname(rule->addr.domain)) == NULL) { slog(LOG_DEBUG, "%s: gethostbyname(%s): %s", function, rule->addr.domain, hstrerror(h_errno)); return 0; } if ((hostent = hostentdup(hostent)) == NULL) { swarnx("%s: hostentdup()", function); return 0; } if ((addresshostent = gethostbyname(address->addr.domain)) == NULL) { slog(LOG_DEBUG, "%s: gethostbyname(%s): %s", function, address->addr.domain, hstrerror(h_errno)); hostentfree(hostent); return 0; } /* * rule->ipaddress(es) is in address->ipaddress(es) */ for (i = 0, mask.s_addr = htonl(0xffffffff); hostent->h_addr_list != NULL && hostent->h_addr_list[i] != NULL; ++i) { /* LINTED pointer casts may be troublesome */ if (addrisinlist((const struct in_addr *)hostent->h_addr_list[i], &mask, (const struct in_addr **)addresshostent->h_addr_list)) { matched = 1; break; } } hostentfree(hostent); } if (!matched) return 0; } else if (rule->atype == SOCKS_ADDR_DOMAIN && address->atype == SOCKS_ADDR_IPV4) { /* * match(rule.hostname, address.ipaddress) * If rule is not a domain, try resolving rule to ipaddress(es) * and match against address. * address is in rule->ipaddress * * If no match, resolve address to hostname(s) and match each * against rule. * rule is in address->hostname * * If still no match and alias is set, resolve all ipaddresses * of all hostname(s) resolved from address back to hostname(s) * and match them against rule. * rule is in address->hostname->ipaddress->hostname */ if (!doresolve) return 0; if (*rule->addr.domain != '.') { /* address is in rule->ipaddress */ struct in_addr mask; if ((hostent = gethostbyname(rule->addr.domain)) == NULL) { slog(LOG_DEBUG, "%s: gethostbyname(%s): %s", function, rule->addr.domain, hstrerror(h_errno)); return 0; } mask.s_addr = htonl(0xffffffff); if (addrisinlist(&address->addr.ipv4, &mask, (const struct in_addr **)hostent->h_addr_list)) matched = 1; } if (!matched) { /* rule is in address->hostname */ /* LINTED pointer casts may be troublesome */ if ((hostent = gethostbyaddr((const char *)&address->addr.ipv4, sizeof(address->addr.ipv4), AF_INET)) == NULL) { slog(LOG_DEBUG, "%s: gethostbyaddr(%s): %s", function, inet_ntoa(address->addr.ipv4), hstrerror(h_errno)); return 0; } if (hostareeq(rule->addr.domain, hostent->h_name) || hostisinlist(rule->addr.domain, (const char **)hostent->h_aliases)) matched = 1; } if (!matched && alias) { /* * rule is in address->hostname->ipaddress->hostname. * hostent is already address->hostname due to above. */ char *nexthost; int i; if ((hostent = hostentdup(hostent)) == NULL) { swarnx("%s: hostentdup()", function); return 0; } nexthost = hostent->h_name; i = 0; do { int ii; struct hostent *host; /* host; address->hostname->ipaddress */ if ((host = gethostbyname(nexthost)) == NULL) { slog(LOG_DEBUG, "%s: gethostbyname(%s): %s", function, nexthost, hstrerror(h_errno)); continue; } if ((host = hostentdup(host)) == NULL) { swarnx("%s: hostentdup()", function); break; } /* LINTED pointer casts may be troublesome */ for (ii = 0; host->h_addr_list != NULL && host->h_addr_list[ii] != NULL; ++ii) { struct hostent *ip; /* ip; address->hostname->ipaddress->hostname */ if ((ip = gethostbyaddr(host->h_addr_list[ii], sizeof(struct in_addr), AF_INET)) == NULL) { /* LINTED pointer casts may be troublesome */ slog(LOG_DEBUG, "%s: gethostbyaddr(%s): %s", function, inet_ntoa(*(struct in_addr *)host->h_addr_list[ii]), hstrerror(h_errno)); continue; } if (hostareeq(rule->addr.domain, ip->h_name) || hostisinlist(rule->addr.domain, (const char **)ip->h_aliases)) { matched = 1; break; } } hostentfree(host); } while (!matched && hostent->h_aliases != NULL && (nexthost = hostent->h_aliases[i++]) != NULL); hostentfree(hostent); } if (!matched) return 0; } else SERRX(0); return matched;}static intaddrisinlist(addr, mask, list) const struct in_addr *addr; const struct in_addr *mask; const struct in_addr **list;{ if (list == NULL) return 0; while (*list != NULL) if (addrareeq(addr, mask, *list)) return 1; else ++list; return 0;}static intaddrareeq(addr, mask, against) const struct in_addr *addr; const struct in_addr *mask; const struct in_addr *against;{ if ((addr->s_addr & mask->s_addr) == (against->s_addr & mask->s_addr)) return 1; return 0;}static inthostisinlist(host, list) const char *host; const char **list;{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -