From 5a61ac7f11300abf6cc2bcb39c2a0aa5964177ed Mon Sep 17 00:00:00 2001 From: marcel Date: Tue, 29 Jan 2002 06:00:11 +0000 Subject: 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" MFC after: 1 week --- sys/compat/linux/linux_ioctl.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'sys/compat/linux/linux_ioctl.c') 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; -- cgit v1.1