diff options
author | marcel <marcel@FreeBSD.org> | 2002-01-29 06:00:11 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2002-01-29 06:00:11 +0000 |
commit | 5a61ac7f11300abf6cc2bcb39c2a0aa5964177ed (patch) | |
tree | d796ca170c5bf7d635c8f426413adcf51bb11d21 /sys/compat/linux | |
parent | 358efcfdcf2fdf9bb0177364a132eaf0e094ebac (diff) | |
download | FreeBSD-src-5a61ac7f11300abf6cc2bcb39c2a0aa5964177ed.zip FreeBSD-src-5a61ac7f11300abf6cc2bcb39c2a0aa5964177ed.tar.gz |
Have SIOCGIFCONF return all (if any) AF_INET addresses for the
interfaces we encounter. In Linux, all addresses are returned for
which gifconf handlers are installed. This boils down to AF_DECnet
and AF_INET. We care mostly about AF_INET for now. Adding additional
families is simple enough.
Returning the addresses is important for RPC clients to function
properly. Andrew found in some reference code that the logic that
handles the retransmission looks for an interface that's up and has
an AF_INET address. This obviously failed as we didn't return any
addresses at all.
Note also that with this change we don't return interfaces that don't
have AF_INET addresses, whereas before we returned any interface
present in the system. This is in line with what Linux does (modulo
interfaces with only AF_DECnet addresses of course :-)
Reported by: "Andrew Atrens" <atrens@nortelnetworks.com>
MFC after: 1 week
Diffstat (limited to 'sys/compat/linux')
-rw-r--r-- | sys/compat/linux/linux_ioctl.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c index 4e72f85..ec96415 100644 --- a/sys/compat/linux/linux_ioctl.c +++ b/sys/compat/linux/linux_ioctl.c @@ -1896,6 +1896,7 @@ linux_ifconf(struct thread *td, struct ifconf *uifc) struct ifconf ifc; struct l_ifreq ifr; struct ifnet *ifp; + struct ifaddr *ifa; struct iovec iov; struct uio uio; int error, ethno; @@ -1918,10 +1919,11 @@ linux_ifconf(struct thread *td, struct ifconf *uifc) /* Keep track of eth interfaces */ ethno = 0; - /* return interface names but no addresses. */ + /* Return all AF_INET addresses of all interfaces */ TAILQ_FOREACH(ifp, &ifnet, if_link) { if (uio.uio_resid <= 0) break; + bzero(&ifr, sizeof ifr); if (IFP_IS_ETH(ifp)) snprintf(ifr.ifr_name, LINUX_IFNAMSIZ, "eth%d", @@ -1929,9 +1931,25 @@ linux_ifconf(struct thread *td, struct ifconf *uifc) else snprintf(ifr.ifr_name, LINUX_IFNAMSIZ, "%s%d", ifp->if_name, ifp->if_unit); - error = uiomove((caddr_t)&ifr, sizeof ifr, &uio); - if (error != 0) - return (error); + + /* Walk the address list */ + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + struct sockaddr *sa = ifa->ifa_addr; + + if (uio.uio_resid <= 0) + break; + + if (sa->sa_family == AF_INET) { + ifr.ifr_addr.sa_family = LINUX_AF_INET; + memcpy(ifr.ifr_addr.sa_data, sa->sa_data, + sizeof(ifr.ifr_addr.sa_data)); + + error = uiomove((caddr_t)&ifr, sizeof ifr, + &uio); + if (error != 0) + return (error); + } + } } ifc.ifc_len -= uio.uio_resid; |