>Number:         178881
>Category:       kern
>Synopsis:       [patch] getifaddrs(3) does not report IPv6 addresses properly 
>in 32-bit compatibility mode
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu May 23 20:00:00 UTC 2013
>Closed-Date:
>Last-Modified:
>Originator:     Steve Zweep
>Release:        9.1-RELEASE (amd64)
>Organization:
WatchGuard Technologies
>Environment:
FreeBSD outland2.borderware.com 9.1-RELEASE FreeBSD 9.1-RELEASE #0 r243825: Tue 
Dec  4 09:23:10 UTC 2012     
[email protected]:/usr/obj/usr/src/sys/GENERIC  amd64

>Description:
This was uncovered trying to run 32-bit Postfix on a 64-bit kernel, and 
subsequently verified with a simple utility which just iterates and prints the 
IP addresses returned from getifaddrs().

In 32-bit compatibility mode IPv4 addresses are reported correctly, but IPv6 
addresses are not. The address family is reported as '0' instead of the 
expected 28 for AF_INET6. The same test utility works as expected when compiled 
as a 64-bit executable.
>How-To-Repeat:
- configure a network interface with an IPv6 address
- compile a 32-bit program which calls getifaddrs() to iterate through 
interface addresses
- examine the output
>Fix:
The problem appears to be in the 32-bit compatibility code in sys/net/rtsock.c 
which handles the NET_RT_IFLIST sysctl used by getifaddrs(). The calculated 
size of the sockaddr structure does not match that which the client code in 
getifaddrs is expecting.

I'm no expert here, but the following patch worked for me:

--- rtsock.c.orig       2013-04-15 17:01:25.000000000 -0400
+++ rtsock.c    2013-04-19 11:53:09.000000000 -0400
@@ -1157,6 +1157,13 @@
        default:
                len = sizeof(struct rt_msghdr);
        }
+
+#ifdef COMPAT_FREEBSD32
+#define SA_SIZE32(sa)  (  (!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \
+       sizeof(uint32_t) : \
+       1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(uint32_t) - 1) 
) )
+#endif
+
        cp0 = cp;
        if (cp0)
                cp += len;
@@ -1166,7 +1173,12 @@
                if ((sa = rtinfo->rti_info[i]) == NULL)
                        continue;
                rtinfo->rti_addrs |= (1 << i);
-               dlen = SA_SIZE(sa);
+#ifdef COMPAT_FREEBSD32
+               if (w != NULL && w->w_req->flags & SCTL_MASK32) 
+                       dlen = SA_SIZE32(sa);
+               else
+#endif
+                       dlen = SA_SIZE(sa);
                if (cp) {
                        bcopy((caddr_t)sa, cp, (unsigned)dlen);
                        cp += dlen;




>Release-Note:
>Audit-Trail:
>Unformatted:
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "[email protected]"

Reply via email to