User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040906
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