diff options
Diffstat (limited to 'mDNSResponder/mDNSPosix/mDNSUNP.c')
-rwxr-xr-x | mDNSResponder/mDNSPosix/mDNSUNP.c | 60 |
1 files changed, 36 insertions, 24 deletions
diff --git a/mDNSResponder/mDNSPosix/mDNSUNP.c b/mDNSResponder/mDNSPosix/mDNSUNP.c index 17a37c61..e00ddd62 100755 --- a/mDNSResponder/mDNSPosix/mDNSUNP.c +++ b/mDNSResponder/mDNSPosix/mDNSUNP.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2018 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -80,40 +80,56 @@ void plen_to_mask(int plen, char *addr) { } /* Gets IPv6 interface information from the /proc filesystem in linux*/ -struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases) +struct ifi_info *get_ifi_info_linuxv6(int doaliases) { struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr; FILE *fp = NULL; - char addr[8][5]; - int flags, myflags, index, plen, scope; - char ifname[9], lastname[IFNAMSIZ]; - char addr6[32+7+1]; /* don't forget the seven ':' */ + int i, nitems, flags, index, plen, scope; struct addrinfo hints, *res0; int err; int sockfd = -1; struct ifreq ifr; + char ifnameFmt[16], addrStr[32 + 7 + 1], ifname[IFNAMSIZ], lastname[IFNAMSIZ]; res0=NULL; ifihead = NULL; ifipnext = &ifihead; - lastname[0] = 0; if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) { sockfd = socket(AF_INET6, SOCK_DGRAM, 0); if (sockfd < 0) { goto gotError; } - while (fscanf(fp, - "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %8s\n", - addr[0],addr[1],addr[2],addr[3], - addr[4],addr[5],addr[6],addr[7], - &index, &plen, &scope, &flags, ifname) != EOF) { - - myflags = 0; - if (strncmp(lastname, ifname, IFNAMSIZ) == 0) { + + // Parse /proc/net/if_inet6 according to <https://www.tldp.org/HOWTO/Linux+IPv6-HOWTO/ch11s04.html>. + + // Create a string specifier with a width of IFNAMSIZ - 1 ("%<IFNAMSIZ - 1>s") to scan the interface name. The + // reason why we don't just use the string-ified macro expansion of IFNAMSIZ for the width is because the width + // needs to be a decimal string and there's no guarantee that IFNAMSIZ will be defined as a decimal integer. For + // example, it could be defined in hexadecimal or as an arithmetic expression. + + snprintf(ifnameFmt, sizeof(ifnameFmt), "%%%ds", IFNAMSIZ - 1); + + // Write the seven IPv6 address string colons and NUL terminator, i.e., "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx". + // The remaining 32 IPv6 address characters come from /proc/net/if_inet6. + + for (i = 4; i < 39; i += 5) addrStr[i] = ':'; + addrStr[39] = '\0'; + + lastname[0] = '\0'; + for (;;) { + nitems = fscanf(fp, " %4c%4c%4c%4c%4c%4c%4c%4c %x %x %x %x", + &addrStr[0], &addrStr[5], &addrStr[10], &addrStr[15], + &addrStr[20], &addrStr[25], &addrStr[30], &addrStr[35], + &index, &plen, &scope, &flags); + if (nitems != 12) break; + + nitems = fscanf(fp, ifnameFmt, ifname); + if (nitems != 1) break; + + if (strcmp(lastname, ifname) == 0) { if (doaliases == 0) continue; /* already processed this interface */ - myflags = IFI_ALIAS; } memcpy(lastname, ifname, IFNAMSIZ); ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info)); @@ -126,15 +142,11 @@ struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases) *ifipnext = ifi; /* prev points to this new one */ ifipnext = &ifi->ifi_next; /* pointer to next one goes here */ - sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", - addr[0],addr[1],addr[2],addr[3], - addr[4],addr[5],addr[6],addr[7]); - /* Add address of the interface */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; hints.ai_flags = AI_NUMERICHOST; - err = getaddrinfo(addr6, NULL, &hints, &res0); + err = getaddrinfo(addrStr, NULL, &hints, &res0); if (err) { goto gotError; } @@ -152,9 +164,9 @@ struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases) goto gotError; } - ((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_family=family; + ((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_family=AF_INET6; ((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_scope_id=scope; - inet_pton(family, ipv6addr, &((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_addr); + inet_pton(AF_INET6, ipv6addr, &((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_addr); /* Add interface name */ memcpy(ifi->ifi_name, ifname, IFI_NAME); @@ -228,7 +240,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases) #endif #if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX - if (family == AF_INET6) return get_ifi_info_linuxv6(family, doaliases); + if (family == AF_INET6) return get_ifi_info_linuxv6(doaliases); #endif sockfd = -1; |