]> git.saurik.com Git - apple/mdnsresponder.git/blobdiff - mDNSPosix/mDNSUNP.c
mDNSResponder-1310.80.1.tar.gz
[apple/mdnsresponder.git] / mDNSPosix / mDNSUNP.c
index e00ddd62b881a54eab294d9ad5e6d8b1a64cbea1..7ad0f301b5e05d946ebd74af9a37548d77b9f125 100755 (executable)
 #include NEED_ALIGN_MACRO
 #endif
 
-/* Solaris defined SIOCGIFCONF etc in <sys/sockio.h> but
-   other platforms don't even have that include file.  So,
-   if we haven't yet got a definition, let's try to find
-   <sys/sockio.h>.
- */
-
-#ifndef SIOCGIFCONF
-    #include <sys/sockio.h>
-#endif
-
 /* sockaddr_dl is only referenced if we're using IP_RECVIF,
    so only include the header in that case.
  */
     #include <net/if_dl.h>
 #endif
 
-#if defined(AF_INET6) && HAVE_IPV6 && !HAVE_LINUX
-#include <net/if_var.h>
-#include <netinet/in_var.h>
-// Note: netinet/in_var.h implicitly includes netinet6/in6_var.h for us
-#endif
-
-#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
-#include <netdb.h>
-#include <arpa/inet.h>
-
-/* Converts a prefix length to IPv6 network mask */
-void plen_to_mask(int plen, char *addr) {
-    int i;
-    int colons=7; /* Number of colons in IPv6 address */
-    int bits_in_block=16; /* Bits per IPv6 block */
-    for(i=0; i<=colons; i++) {
-        int block, ones=0xffff, ones_in_block;
-        if (plen>bits_in_block) ones_in_block=bits_in_block;
-        else ones_in_block=plen;
-        block = ones & (ones << (bits_in_block-ones_in_block));
-        i==0 ? sprintf(addr, "%x", block) : sprintf(addr, "%s:%x", addr, block);
-        plen -= ones_in_block;
-    }
-}
-
-/* Gets IPv6 interface information from the /proc filesystem in linux*/
-struct ifi_info *get_ifi_info_linuxv6(int doaliases)
-{
-    struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
-    FILE *fp = NULL;
-    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;
-
-    if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) {
-        sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
-        if (sockfd < 0) {
-            goto gotError;
-        }
-
-        // 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 */
-            }
-            memcpy(lastname, ifname, IFNAMSIZ);
-            ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
-            if (ifi == NULL) {
-                goto gotError;
-            }
-
-            ifipold   = *ifipnext;       /* need this later */
-            ifiptr    = ifipnext;
-            *ifipnext = ifi;            /* prev points to this new one */
-            ifipnext = &ifi->ifi_next;  /* pointer to next one goes here */
-
-            /* Add address of the interface */
-            memset(&hints, 0, sizeof(hints));
-            hints.ai_family = AF_INET6;
-            hints.ai_flags = AI_NUMERICHOST;
-            err = getaddrinfo(addrStr, NULL, &hints, &res0);
-            if (err) {
-                goto gotError;
-            }
-            ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
-            if (ifi->ifi_addr == NULL) {
-                goto gotError;
-            }
-            memcpy(ifi->ifi_addr, res0->ai_addr, sizeof(struct sockaddr_in6));
-
-            /* Add netmask of the interface */
-            char ipv6addr[INET6_ADDRSTRLEN];
-            plen_to_mask(plen, ipv6addr);
-            ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6));
-            if (ifi->ifi_netmask == NULL) {
-                goto gotError;
-            }
-
-            ((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_family=AF_INET6;
-            ((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_scope_id=scope;
-            inet_pton(AF_INET6, ipv6addr, &((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_addr);
-
-            /* Add interface name */
-            memcpy(ifi->ifi_name, ifname, IFI_NAME);
-
-            /* Add interface index */
-            ifi->ifi_index = index;
-
-            /* Add interface flags*/
-            memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
-            if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
-                if (errno == EADDRNOTAVAIL) {
-                    /*
-                     * If the main interface is configured with no IP address but
-                     * an alias interface exists with an IP address, you get
-                     * EADDRNOTAVAIL for the main interface
-                     */
-                    free(ifi->ifi_addr);
-                    free(ifi->ifi_netmask);
-                    free(ifi);
-                    ifipnext  = ifiptr;
-                    *ifipnext = ifipold;
-                    continue;
-                } else {
-                    goto gotError;
-                }
-            }
-            ifi->ifi_flags = ifr.ifr_flags;
-            freeaddrinfo(res0);
-            res0=NULL;
-        }
-    }
-    goto done;
-
-gotError:
-    if (ifihead != NULL) {
-        free_ifi_info(ifihead);
-        ifihead = NULL;
-    }
-    if (res0 != NULL) {
-        freeaddrinfo(res0);
-        res0=NULL;
-    }
-done:
-    if (sockfd != -1) {
-        int rv;
-        rv = close(sockfd);
-        assert(rv == 0);
-    }
-    if (fp != NULL) {
-        fclose(fp);
-    }
-    return(ifihead);    /* pointer to first structure in linked list */
-}
-#endif // defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
-
-struct ifi_info *get_ifi_info(int family, int doaliases)
-{
-    int junk;
-    struct ifi_info     *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
-    int sockfd, sockf6, len, lastlen, flags, myflags;
-#ifdef NOT_HAVE_IF_NAMETOINDEX
-    int index = 200;
-#endif
-    char                *ptr, *buf, lastname[IFNAMSIZ], *cptr;
-    struct ifconf ifc;
-    struct ifreq        *ifr, ifrcopy;
-    struct sockaddr_in  *sinptr;
-
-#if defined(AF_INET6) && HAVE_IPV6
-    struct sockaddr_in6 *sinptr6;
-#endif
-
-#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
-    if (family == AF_INET6) return get_ifi_info_linuxv6(doaliases);
-#endif
-
-    sockfd = -1;
-    sockf6 = -1;
-    buf = NULL;
-    ifihead = NULL;
-
-    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
-    if (sockfd < 0) {
-        goto gotError;
-    }
-
-    lastlen = 0;
-    len = 100 * sizeof(struct ifreq);   /* initial buffer size guess */
-    for ( ; ; ) {
-        buf = (char*)malloc(len);
-        if (buf == NULL) {
-            goto gotError;
-        }
-        ifc.ifc_len = len;
-        ifc.ifc_buf = buf;
-        if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
-            if (errno != EINVAL || lastlen != 0) {
-                goto gotError;
-            }
-        } else {
-            if (ifc.ifc_len == lastlen)
-                break;      /* success, len has not changed */
-            lastlen = ifc.ifc_len;
-        }
-        len += 10 * sizeof(struct ifreq);   /* increment */
-        free(buf);
-    }
-    ifihead = NULL;
-    ifipnext = &ifihead;
-    lastname[0] = 0;
-/* end get_ifi_info1 */
-
-/* include get_ifi_info2 */
-    for (ptr = buf; ptr < buf + ifc.ifc_len; ) {
-        ifr = (struct ifreq *) ptr;
-
-        /* Advance to next one in buffer */
-        if (sizeof(struct ifreq) > sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr))
-            ptr += sizeof(struct ifreq);
-        else
-            ptr += sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr);
-
-//      fprintf(stderr, "intf %p name=%s AF=%d\n", index, ifr->ifr_name, ifr->ifr_addr.sa_family);
-
-        if (ifr->ifr_addr.sa_family != family)
-            continue;   /* ignore if not desired address family */
-
-        myflags = 0;
-        if ( (cptr = strchr(ifr->ifr_name, ':')) != NULL)
-            *cptr = 0;      /* replace colon will null */
-        if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) {
-            if (doaliases == 0)
-                continue;   /* already processed this interface */
-            myflags = IFI_ALIAS;
-        }
-        memcpy(lastname, ifr->ifr_name, IFNAMSIZ);
-
-        ifrcopy = *ifr;
-        if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0) {
-            goto gotError;
-        }
-
-        flags = ifrcopy.ifr_flags;
-        if ((flags & IFF_UP) == 0)
-            continue;   /* ignore if interface not up */
-
-        ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
-        if (ifi == NULL) {
-            goto gotError;
-        }
-        ifipold   = *ifipnext;       /* need this later */
-        ifiptr    = ifipnext;
-        *ifipnext = ifi;             /* prev points to this new one */
-        ifipnext  = &ifi->ifi_next;  /* pointer to next one goes here */
-
-        ifi->ifi_flags = flags;     /* IFF_xxx values */
-        ifi->ifi_myflags = myflags; /* IFI_xxx values */
-#ifndef NOT_HAVE_IF_NAMETOINDEX
-        ifi->ifi_index = if_nametoindex(ifr->ifr_name);
-#else
-        ifrcopy = *ifr;
-#ifdef SIOCGIFINDEX
-        if ( 0 >= ioctl(sockfd, SIOCGIFINDEX, &ifrcopy))
-            ifi->ifi_index = ifrcopy.ifr_index;
-        else
-#endif
-        ifi->ifi_index = index++;       /* SIOCGIFINDEX is broken on Solaris 2.5ish, so fake it */
-#endif
-        memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME);
-        ifi->ifi_name[IFI_NAME-1] = '\0';
-/* end get_ifi_info2 */
-/* include get_ifi_info3 */
-        switch (ifr->ifr_addr.sa_family) {
-        case AF_INET:
-            sinptr = (struct sockaddr_in *) &ifr->ifr_addr;
-            if (ifi->ifi_addr == NULL) {
-                ifi->ifi_addr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
-                if (ifi->ifi_addr == NULL) {
-                    goto gotError;
-                }
-                memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));
-
-#ifdef  SIOCGIFNETMASK
-                if (ioctl(sockfd, SIOCGIFNETMASK, &ifrcopy) < 0) {
-                    if (errno == EADDRNOTAVAIL) {
-                        /*
-                         * If the main interface is configured with no IP address but
-                         * an alias interface exists with an IP address, you get
-                         * EADDRNOTAVAIL for the main interface
-                         */
-                        free(ifi->ifi_addr);
-                        free(ifi);
-                        ifipnext  = ifiptr;
-                        *ifipnext = ifipold;
-                        continue;
-                    } else {
-                        goto gotError;
-                    }
-                }
-
-                ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
-                if (ifi->ifi_netmask == NULL) goto gotError;
-                sinptr = (struct sockaddr_in *) &ifrcopy.ifr_addr;
-                /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
-#ifndef NOT_HAVE_SA_LEN
-                sinptr->sin_len    = sizeof(struct sockaddr_in);
-#endif
-                sinptr->sin_family = AF_INET;
-                memcpy(ifi->ifi_netmask, sinptr, sizeof(struct sockaddr_in));
-#endif
-
-#ifdef  SIOCGIFBRDADDR
-                if (flags & IFF_BROADCAST) {
-                    if (ioctl(sockfd, SIOCGIFBRDADDR, &ifrcopy) < 0) {
-                        goto gotError;
-                    }
-                    sinptr = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr;
-                    /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
-#ifndef NOT_HAVE_SA_LEN
-                    sinptr->sin_len    = sizeof( struct sockaddr_in );
-#endif
-                    sinptr->sin_family = AF_INET;
-                    ifi->ifi_brdaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
-                    if (ifi->ifi_brdaddr == NULL) {
-                        goto gotError;
-                    }
-                    memcpy(ifi->ifi_brdaddr, sinptr, sizeof(struct sockaddr_in));
-                }
-#endif
-
-#ifdef  SIOCGIFDSTADDR
-                if (flags & IFF_POINTOPOINT) {
-                    if (ioctl(sockfd, SIOCGIFDSTADDR, &ifrcopy) < 0) {
-                        goto gotError;
-                    }
-                    sinptr = (struct sockaddr_in *) &ifrcopy.ifr_dstaddr;
-                    /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
-#ifndef NOT_HAVE_SA_LEN
-                    sinptr->sin_len    = sizeof( struct sockaddr_in );
-#endif
-                    sinptr->sin_family = AF_INET;
-                    ifi->ifi_dstaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
-                    if (ifi->ifi_dstaddr == NULL) {
-                        goto gotError;
-                    }
-                    memcpy(ifi->ifi_dstaddr, sinptr, sizeof(struct sockaddr_in));
-                }
-#endif
-            }
-            break;
-
-#if defined(AF_INET6) && HAVE_IPV6
-        case AF_INET6:
-            sinptr6 = (struct sockaddr_in6 *) &ifr->ifr_addr;
-            if (ifi->ifi_addr == NULL) {
-                ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
-                if (ifi->ifi_addr == NULL) {
-                    goto gotError;
-                }
-
-                /* Some platforms (*BSD) inject the prefix in IPv6LL addresses */
-                /* We need to strip that out */
-                if (IN6_IS_ADDR_LINKLOCAL(&sinptr6->sin6_addr))
-                    sinptr6->sin6_addr.s6_addr[2] = sinptr6->sin6_addr.s6_addr[3] = 0;
-                memcpy(ifi->ifi_addr, sinptr6, sizeof(struct sockaddr_in6));
-
-#ifdef  SIOCGIFNETMASK_IN6
-                {
-                    struct in6_ifreq ifr6;
-                    if (sockf6 == -1)
-                        sockf6 = socket(AF_INET6, SOCK_DGRAM, 0);
-                    memset(&ifr6, 0, sizeof(ifr6));
-                    memcpy(&ifr6.ifr_name,           &ifr->ifr_name, sizeof(ifr6.ifr_name          ));
-                    memcpy(&ifr6.ifr_ifru.ifru_addr, &ifr->ifr_addr, sizeof(ifr6.ifr_ifru.ifru_addr));
-                    if (ioctl(sockf6, SIOCGIFNETMASK_IN6, &ifr6) < 0) {
-                        if (errno == EADDRNOTAVAIL) {
-                            /*
-                             * If the main interface is configured with no IP address but
-                             * an alias interface exists with an IP address, you get
-                             * EADDRNOTAVAIL for the main interface
-                             */
-                            free(ifi->ifi_addr);
-                            free(ifi);
-                            ifipnext  = ifiptr;
-                            *ifipnext = ifipold;
-                            continue;
-                        } else {
-                            goto gotError;
-                        }
-                    }
-                    ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in6));
-                    if (ifi->ifi_netmask == NULL) goto gotError;
-                    sinptr6 = (struct sockaddr_in6 *) &ifr6.ifr_ifru.ifru_addr;
-                    memcpy(ifi->ifi_netmask, sinptr6, sizeof(struct sockaddr_in6));
-                }
-#endif
-            }
-            break;
-#endif
-
-        default:
-            break;
-        }
-    }
-    goto done;
-
-gotError:
-    if (ifihead != NULL) {
-        free_ifi_info(ifihead);
-        ifihead = NULL;
-    }
-
-done:
-    if (buf != NULL) {
-        free(buf);
-    }
-    if (sockfd != -1) {
-        junk = close(sockfd);
-        assert(junk == 0);
-    }
-    if (sockf6 != -1) {
-        junk = close(sockf6);
-        assert(junk == 0);
-    }
-    return(ifihead);    /* pointer to first structure in linked list */
-}
-/* end get_ifi_info3 */
-
-/* include free_ifi_info */
-void
-free_ifi_info(struct ifi_info *ifihead)
-{
-    struct ifi_info *ifi, *ifinext;
-
-    for (ifi = ifihead; ifi != NULL; ifi = ifinext) {
-        if (ifi->ifi_addr != NULL)
-            free(ifi->ifi_addr);
-        if (ifi->ifi_netmask != NULL)
-            free(ifi->ifi_netmask);
-        if (ifi->ifi_brdaddr != NULL)
-            free(ifi->ifi_brdaddr);
-        if (ifi->ifi_dstaddr != NULL)
-            free(ifi->ifi_dstaddr);
-        ifinext = ifi->ifi_next;    /* can't fetch ifi_next after free() */
-        free(ifi);                  /* the ifi_info{} itself */
-    }
-}
-/* end free_ifi_info */
-
 ssize_t
 recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
                struct sockaddr *sa, socklen_t *salenptr, struct my_in_pktinfo *pktp, u_char *ttl)