listen.c
来自「此dns服务器是在mydns基础上改写」· C语言 代码 · 共 724 行 · 第 1/2 页
C
724 行
/************************************************************************************************** $Id: listen.c,v 1.42 2006/01/18 20:46:47 bboy Exp $ Copyright (C) 2002-2005 Don Moore <bboy@bboy.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at Your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA**************************************************************************************************/#include "named.h"/* Make this nonzero to enable debugging for this source file */#define DEBUG_LISTEN 1#if HAVE_NET_IF_H# include <net/if.h>#endif# include <sys/ioctl.h>int *udp4_fd = (int *)NULL; /* Listening socket: UDP, IPv4 */int *tcp4_fd = (int *)NULL; /* Listening socket: TCP, IPv4 */int num_udp4_fd = 0; /* Number of items in 'udp4_fd' */int num_tcp4_fd = 0; /* Number of items in 'tcp4_fd' */#if HAVE_IPV6int *udp6_fd = (int *)NULL; /* Listening socket: UDP, IPv6 */int *tcp6_fd = (int *)NULL; /* Listening socket: TCP, IPv6 */int num_udp6_fd = 0; /* Number of items in 'udp6_fd' */int num_tcp6_fd = 0; /* Number of items in 'tcp6_fd' */#endifextern char *opt_conf;extern uint32_t answer_then_quit;static void server_greeting(void);typedef struct _addrlist{ int family; /* AF_INET or AF_INET6 */ struct in_addr addr4; /* Address if IPv4 */#if HAVE_IPV6 struct in6_addr addr6; /* Address if IPv6 */#endif int port; /* Port number */ int ok; /* OK to use this address? */ struct _addrlist *next; /* Next address */} ADDRLIST;static ADDRLIST *FirstAddr, *LastAddr; /* Current address list *//************************************************************************************************** ADDRLIST_ADD Adds the specified address to the current list, checking for duplicates, etc.**************************************************************************************************/static voidaddrlist_add(int family, void *address, int port){ ADDRLIST *A; struct in_addr addr4;#if HAVE_IPV6 struct in6_addr addr6;#endif /* Copy address into struct and make sure it's not the "catch-all" address */ if (family == AF_INET) { memcpy(&addr4, address, sizeof(struct in_addr)); if (addr4.s_addr == INADDR_ANY) return; }#if HAVE_IPV6 else if (family == AF_INET6) { memcpy(&addr6, address, sizeof(struct in6_addr)); if (!memcmp(&addr6, &in6addr_any, sizeof(struct in6_addr))) return; }#endif else return; /* Invalid family */ /* Check for duplicate */ for (A = FirstAddr; A; A = A->next) switch (family) { case AF_INET: if ((A->port == port) && !memcmp(&addr4, &A->addr4, sizeof(struct in_addr))) return; break;#if HAVE_IPV6 case AF_INET6: if ((A->port == port) && !memcmp(&addr6, &A->addr6, sizeof(struct in6_addr))) return; break;#endif } /* Not a duplicate; add new interface */ if (!(A = calloc(1, sizeof(ADDRLIST)))) Err(_("out of memory")); switch ((A->family = family)) { case AF_INET: memcpy(&A->addr4, &addr4, sizeof(struct in_addr)); break;#if HAVE_IPV6 case AF_INET6: memcpy(&A->addr6, &addr6, sizeof(struct in6_addr)); break;#endif } A->port = port; A->ok = 1; /* Add new interface to list */ if (!LastAddr) FirstAddr = LastAddr = A; else { LastAddr->next = A; LastAddr = A; }}/*--- addrlist_add() ----------------------------------------------------------------------------*/#if DEBUG_ENABLED && DEBUG_LISTEN && HAVE_IPV6/************************************************************************************************** IP6_EXTRA**************************************************************************************************/char *ip6_extra(const struct in6_addr *a){ static char buf[2048]; char *b = buf; *b = '\0'; if (IN6_IS_ADDR_UNSPECIFIED(a)) b += snprintf(b, sizeof(buf)-(b-buf), "UNSPECIFIED "); if (IN6_IS_ADDR_LOOPBACK(a)) b += snprintf(b, sizeof(buf)-(b-buf), "LOOPBACK "); if (IN6_IS_ADDR_MULTICAST(a)) b += snprintf(b, sizeof(buf)-(b-buf), "MULTICAST "); if (IN6_IS_ADDR_LINKLOCAL(a)) b += snprintf(b, sizeof(buf)-(b-buf), "LINKLOCAL "); if (IN6_IS_ADDR_SITELOCAL(a)) b += snprintf(b, sizeof(buf)-(b-buf), "SITELOCAL "); if (IN6_IS_ADDR_V4MAPPED(a)) b += snprintf(b, sizeof(buf)-(b-buf), "V4MAPPED "); if (IN6_IS_ADDR_V4COMPAT(a)) b += snprintf(b, sizeof(buf)-(b-buf), "V4COMPAT "); if (IN6_IS_ADDR_MULTICAST(a)) { if (IN6_IS_ADDR_MC_NODELOCAL(a)) b += snprintf(b, sizeof(buf)-(b-buf), "MC_NODELOCAL "); if (IN6_IS_ADDR_MC_LINKLOCAL(a)) b += snprintf(b, sizeof(buf)-(b-buf), "MC_LINKLOCAL "); if (IN6_IS_ADDR_MC_SITELOCAL(a)) b += snprintf(b, sizeof(buf)-(b-buf), "MC_SITELOCAL "); if (IN6_IS_ADDR_MC_ORGLOCAL(a)) b += snprintf(b, sizeof(buf)-(b-buf), "MC_ORGLOCAL "); if (IN6_IS_ADDR_MC_GLOBAL(a)) b += snprintf(b, sizeof(buf)-(b-buf), "MC_GLOBAL "); } return buf;}/*--- ip6_extra() -------------------------------------------------------------------------------*/#endif/************************************************************************************************** LINUX_LOAD_IP6 Linux does not return IPv6 interfaces via SIOCGIFCONF, so we load them from /proc/net/if_inet6. See http://tldp.org/HOWTO/Linux+IPv6-HOWTO/proc-net.html for file format.**************************************************************************************************/#ifdef __linux__#if HAVE_IPV6static voidlinux_load_ip6(int port){ FILE *fp; char line[512]; if ((fp = fopen("/proc/net/if_inet6", "r"))) { while (fgets(line, sizeof(line), fp)) { int n; char *l, *hex, *device_number, *prefix_length, *scope_value, *if_flags; char buf[sizeof("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX\0")]; struct in6_addr addr; l = line; if (!(hex = strsep(&l, " "))) continue; if (!(device_number = strsep(&l, " "))) continue; if (!(prefix_length = strsep(&l, " "))) continue; if (!(scope_value = strsep(&l, " "))) continue; if (!(if_flags = strsep(&l, " "))) continue; strtrim(l); /* Convert hex address into 'addr' */ for (n = 0; n < 8; n++) { memcpy(buf + (4 * n) + (n * 1), hex + (4 * n), 4); buf[(4 * n) + (n * 1) + 4] = ':'; } buf[39] = '\0';#if DEBUG_ENABLED && DEBUG_LISTEN { uint16_t dn, pl, sv, f; dn = (uint16_t)strtoul(device_number, NULL, 16); pl = (uint16_t)strtoul(prefix_length, NULL, 16); sv = (uint16_t)strtoul(scope_value, NULL, 16); f = (uint16_t)strtoul(if_flags, NULL, 16); Debug("IPv6 %s: device_number=%u prefix_length=%u scope_value=%u if_flags=%u", buf, dn, pl, sv, f); }#endif if (inet_pton(AF_INET6, buf, &addr) > 0) { /* I am not at all sure which of these scopes from RFC 2553 we should NOT try to bind to.. LINKLOCAL for sure doesn't work if you try it */ if (IN6_IS_ADDR_LINKLOCAL(&addr)) continue;#if DEBUG_ENABLED && DEBUG_LISTEN Debug(" extra: %s", ip6_extra(&addr));#endif addrlist_add(AF_INET6, &addr, port); } } fclose(fp); }}#endif#endif/*--- linux_load_ip6() --------------------------------------------------------------------------*//************************************************************************************************** ADDRLIST_LOAD Gets the IP addresses for all interfaces on the system. Returns the interface list, or NULL on error.**************************************************************************************************/static ADDRLIST *addrlist_load(int port){ struct ifconf ifc; struct ifreq *ifr; int sockfd, buflen = 8192, n; unsigned char *buf; FirstAddr = LastAddr = NULL; if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { Warn("error creating socket for interface scan"); return NULL; } for (;;) /* Allocate buffer space */ { if (!(buf = malloc(buflen))) Err(_("out of memory")); ifc.ifc_len = buflen; ifc.ifc_buf = buf; if ((n = ioctl(sockfd, SIOCGIFCONF, (char *)&ifc)) != -1) { if (ifc.ifc_len + 2 * sizeof(struct ifreq) < buflen) break; } if ((n == -1) && errno != EINVAL) { Err("error setting SIOCGIFCONF for interface scan"); return NULL; } free(buf); buflen += 4096; } for (n = 0; n < ifc.ifc_len;) /* Scan interfaces */ { struct in_addr addr4;#if HAVE_IPV6 struct in6_addr addr6;#endif ifr = (struct ifreq *)((char *)ifc.ifc_req + n);#ifdef HAVE_SOCKADDR_SA_LEN n += sizeof(ifr->ifr_name) + (ifr->ifr_addr.sa_len > sizeof(struct sockaddr) ? ifr->ifr_addr.sa_len : sizeof(struct sockaddr));#else n += sizeof(struct ifreq);#endif /* HAVE_SOCKADDR_SA_LEN */ if (ifr->ifr_flags & IFF_UP) /* Must be up */ continue; if (ioctl(sockfd, SIOCGIFADDR, ifr) < 0) /* Get address */ continue; switch (ifr->ifr_addr.sa_family) { case AF_INET: memcpy(&addr4, &((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr, sizeof(struct in_addr)); addrlist_add(AF_INET, &addr4, port); break;#if HAVE_IPV6 case AF_INET6: memcpy(&addr6, &((struct sockaddr_in6 *)&ifr->ifr_addr)->sin6_addr, sizeof(struct in6_addr)); addrlist_add(AF_INET, &addr4, port); break;#endif default: continue; } } close(sockfd); free(buf);#ifdef __linux__#if HAVE_IPV6 linux_load_ip6(port);#endif#endif return (FirstAddr);}/*--- addrlist_load() ---------------------------------------------------------------------------*//************************************************************************************************** ADDRLIST_FREE**************************************************************************************************/voidaddrlist_free(ADDRLIST *Addresses){ ADDRLIST *A, *tmp; for (A = Addresses; A; A = tmp) { tmp = A->next; free(A); }}/*--- addrlist_free() ---------------------------------------------------------------------------*//************************************************************************************************** GET_OPT_ADDRLIST Examines the provided configuration option string and returns an ADDRLIST structure containing the addresses.**************************************************************************************************/static ADDRLIST *get_opt_addrlist(ADDRLIST *Addresses, const char *opt, int default_port, char *desc){ int family; /* Protocol family (AF_INET/AF_INET6) */ struct in_addr addr4; /* IPv4 address buffer */#if HAVE_IPV6 struct in6_addr addr6; /* IPv6 address buffer */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?