Mailing Lists: Apple Mailing Lists
Image of Mac OS face in stamp
ipv6 disabled/linux
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

ipv6 disabled/linux



Funny, I ran into this last week too, but I thought it was a personal
problem so I didn't bother passing it on.   (Personal in the sense that
maybe I was the only one who turned of ipv6 because of the stupid
Mozilla slow resolver in the face of misconfigured ip6 name service
insanity.)    What I think is the correct fix is below...

>From: "Ademar de Souza Reis Jr." <email@hidden>
>Subject: Failure with ipv6 disabled on Linux
>To: email@hidden
>Message-ID: <email@hidden>
>Content-Type: text/plain; charset=us-ascii; format=flowed
>
>Hi.
>
>On Linux (Conectiva Linux, kernel  2.6.8), I can't run mDNS* applications
>(updated CVS) if I keep ipv6 disabled. I get the following failure:
>
>[ademar@optimus mDNSPosix]$ ./build/prod/mDNSNetMonitor
>mDNSNetMonitor: mDNSNetMonitor failed -65537
>[ademar@optimus mDNSPosix]$ ./build/prod/mDNSClientPosix
>mDNSClientPosix: Finished with status -65537, result 2
>
>Looks like the error resides in the mDNSUNP.c:get_ifi_info() function, which
>fails if socket6() returns an error on line 152.
>
>If I remove the check after the socket6() call it works fine, but I'm doing
>it blindly, I hope someone with a good understanding of the code can fix
>this issue the right way :-)
>
>Just to remember, programs should not fail if ipv6 is disabled, even if the
>platform supports it.
>
>

Below is what works for me.

struct ifi_info *get_ifi_info(int family, int doaliases)
{
    int                 junk;
    struct ifi_info     *ifi, *ifihead, **ifipnext;
    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;
    int             useip6 = 1;
#endif

    sockfd = -1;
    sockf6 = -1;
    buf = NULL;
    ifihead = NULL;

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        goto gotError;
    }

#if defined(AF_INET6) && HAVE_IPV6
    sockf6 = socket(AF_INET6, SOCK_DGRAM, 0);
    if (sockf6 < 0) {

      /* don't just error out.  ip6 might be disabled on the machine
         for other reasons.   Just don't use it.   Maybe complain?  */
      useip6 = 0;
    }
#endif

    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;

        len = GET_SA_LEN(ifr->ifr_addr);
        ptr += sizeof(ifr->ifr_name) + len; /* for next one in buffer */

//        fprintf(stderr, "intf %d 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;
        }
        *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;
        if ( 0 >= ioctl(sockfd, SIOCGIFINDEX, &ifrcopy))
            ifi->ifi_index = ifrcopy.ifr_index;
        else
            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) 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;
                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;
                    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;
                    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   useip6 = 0;
            }
            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
        if( useip6 )
                {
                struct in6_ifreq ifr6;
                bzero(&ifr6, 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) 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 */





-dB




 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Rendezvous-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden



Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2011 Apple Inc. All rights reserved.