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. 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: 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
Responsible Changed From-To: freebsd-bugs->hrs Take.
*** Bug 198350 has been marked as a duplicate of this bug. ***
Created attachment 154041 [details] Patch for 10.1-STABLE (r279751) - NOT WORKING Since your 9.1 does not apply cleanly I made my own version for 10.1. But it is not working. My version patches it only in rt_msg2(), but SA_SIZE is also used in rt_msg1(), rt_xaddrs() I can confirm this bug is still present in my oldish -CURRENT (as of Sep 2014), although rtsock.c is in part rewritten. Easy way to test: Install www/node (version 0.12.0) and try: > os.networkInterfaces() it will return bogus values for IPv6 or crash if running 32-bit binary on amd64.
Please do not remove me from Cc list with no notification.
(In reply to Hiroki Sato from comment #4) > Please do not remove me from Cc list with no notification. Sorry that was not my intent. I took assignment. I'm working on a patch.
Working patch available at https://reviews.freebsd.org/D2131
Early testing shows no improvement, but trying full rebuild now.
(In reply to Marcin Cieślak from comment #7) (pls forget it, the patch didn't apply correctly to my 10.1 tree)
Summary: The fix is larger than expected. I am working on it. There is a lot of complexity involved with this issue. The original issue and fix were fine. However r263102 broke ABI compatibility with all consumers of NET_RT_IFLIST. Fixing this is difficult since if_data has different structure for <r263102 NET_RT_IFLIST users and >r263102. Given we have added NET_RT_IFLISTL as a better way to grab this data we will be removing NET_RT_IFLIST from all consumers in the tree and then removing NET_RT_IFLIST. We will fix ABI compatibility by having NET_RT_IFLIST return the older if_data for both 64bit and 32bit calls. My current patch works on amd64 by accident since the new if_data is "close enough" to the old if_data in terms of sizes. The counters and baudrate are different. The change was enough to fix getifaddrs(3) but is not fully correct. This change will break ABI compatibility on head only but that is generally acceptable, especially when restoring older ABI compatibility. All of these will need to be updated to use NET_RT_IFLISTL or getifaddrs(3): sbin/route/route.c: mib[4] = NET_RT_IFLIST; sbin/routed/if.c: mib[4] = NET_RT_IFLIST; sbin/ipfw/nat.c: mib[4] = NET_RT_IFLIST; sbin/natd/natd.c: mib[4] = NET_RT_IFLIST; usr.sbin/rtsold/if.c: int mib[6] = {CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0}; usr.sbin/rwhod/rwhod.c: mib[4] = NET_RT_IFLIST; usr.sbin/rwhod/rwhod.c: quit("out of sync parsing NET_RT_IFLIST"); usr.sbin/route6d/route6d.c: mib[4] = NET_RT_IFLIST; usr.sbin/route6d/route6d.c: fatal("sysctl estimate NET_RT_IFLIST"); usr.sbin/route6d/route6d.c: fatal("sysctl NET_RT_IFLIST"); usr.sbin/ppp/iface.c: mib[4] = NET_RT_IFLIST; usr.sbin/ppp/route.c: mib[4] = NET_RT_IFLIST; usr.sbin/ppp/arp.c: mib[4] = NET_RT_IFLIST; usr.sbin/wpa/ndis_events/ndis_events.c: mib[4] = NET_RT_IFLIST; usr.sbin/wpa/wpa_supplicant/Packet32.c: mib[4] = NET_RT_IFLIST; usr.sbin/rtadvd/if.c: int mib[] = { CTL_NET, PF_ROUTE, 0, AF_INET6, NET_RT_IFLIST, 0 }; usr.sbin/rtadvd/if.c: "<%s> sysctl: NET_RT_IFLIST size get failed", __func__); usr.sbin/rtadvd/if.c: "<%s> sysctl: NET_RT_IFLIST get failed", __func__); usr.sbin/rtadvd/if.c: "out of sync parsing NET_RT_IFLIST\n" lib/libc/net/getifaddrs.c:#ifdef NET_RT_IFLIST lib/libc/net/getifaddrs.c: mib[4] = NET_RT_IFLISTL;/* extra fields for extensible msghdr structs */ lib/libc/gen/sysctl.3:.It "NET_RT_IFLIST 0 or if_index" Ta None lib/libc/gen/sysctl.3:.It "NET_RT_IFLISTL 0 or if_index" Ta None lib/libc/gen/sysctl.3:.Dv NET_RT_IFLISTL lib/libc/gen/sysctl.3:.Dv NET_RT_IFLIST , lib/libc/gen/sysctl.3:.Dv NET_RT_IFLISTL
batch change: For bugs that match the following - Status Is In progress AND - Untouched since 2018-01-01. AND - Affects Base System OR Documentation DO: Reset to open status. Note: I did a quick pass but if you are getting this email it might be worthwhile to double check to see if this bug ought to be closed.
Keyword: patch or patch-ready – in lieu of summary line prefix: [patch] * bulk change for the keyword * summary lines may be edited manually (not in bulk). Keyword descriptions and search interface: <https://bugs.freebsd.org/bugzilla/describekeywords.cgi>
I think the synopsis of the bug is not correct. The 32-bit to 64-bit compatibility doesn't have a bug. It is incompatibility between old struct if_data, that had machine dependent sized fields, and a new struct if_data, that was has fixed size fields, change made in b245f96c44c5. So, the problem would manifest if you run FreeBSD 10 32-bit jail on a modern 64-bit host. The problem won't reproduce if both kernel and jail environment are FreeBSD 11 and up. I tried to reproduce on FreeBSD 14.2-RELEASE i386 jail running on FreeBSD 15-CURRENT kernel. I installed node from packages and tried os.networkInterfaces() and it produces a correct result. Note that the workaround patch from ports had already been removed in 440fbe7ad9af. To make sure I traced two things. The node indeed syscalls into freebsd32___sysctl() and the sysctl is net.routetable.0.0.5.0.