From nobody Sat Mar 4 09:12:41 2023 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4PTJyf1CMxz3vmqr; Sat, 4 Mar 2023 09:12:42 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4PTJyd6qg1z3xTK; Sat, 4 Mar 2023 09:12:41 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1677921161; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=LyBLWvn81mBNCYTJsLKl+NiVZQyssvbwSLBQChXtaYM=; b=ZoQeQOuTUOVLKxYsfVLYdNWSFvrqzs+1j37A4Qb3j1SwbxB3pSq56hR1Xn2Fc2JjuvBt1s UaMadGhieD0ipcDhYENxpoN/NAzpPssoYJ6B/1XPw0ix9QpWyzyPVyx8wv7yXzPA5wmHxl svjpPtym+w0+tZ4WnWVLw7sDvl83h8dfGI7Qzn/ecdxiTdMpTwqqzc1Eoz8Fbw237efJVN VavvRQrF+gv4XUWD48y00GMO32yKygrjH3bK3nwufujGNQFcFXOIEXS/Mphib2GUGZx8pr BxF7gyHSHtBDyoD/C8Cq8N+G91Iz8Z4Q4Tpc6EB5vKEmInn73/yNa5Fvei7q0w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1677921161; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=LyBLWvn81mBNCYTJsLKl+NiVZQyssvbwSLBQChXtaYM=; b=L6V6SqqCIMS9pcbgEThfVFENeXjGbJptpTgw32M+c/7GdElN8bQHKSdmqND+jWw60/z/YE YObLILOionepLMUpas/2EejNUbHMNSzWFhcGYYL9cF6RVm4WsIjcIaXr3k8LegxdLdn4KE RCGEX94wyY7L5Oq6Ad2039sk3DhX9a/X+uYKI/dpMr9hCRcmDe45OPkQWsIbEjRJCXTrzC WvMG4Bht66OB1/2zaSU6vVY48McAzNoUdm6F7W3wpPrc+K6pPGTnII8funvEgezFt5pUCu UW5sGknVHxUym+bNtAD6C4BEKf2ubzXf1pOZCpnP3NHC0utZiX+LlVW7OuiRGA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1677921161; a=rsa-sha256; cv=none; b=GvCOi+ee3WaKJKd4IqKTNt1idXUktOHAuMtei898PlDU3eE3V9MyWEab9855hQPLbba1Sa /B8VDsXORkmMf0IbIfpw4HTo0fTwZaIUmb3NvUj1MicGXcWvAb+Z4rbGnq2AZM8uZ6hTpH Q2nmzeNpbuj4yPhWXx45ZI321yYJUTJ+q/2TfpUk3A0Njluw7dCp/QFIBBFAGRdGmq+chQ JREq9cMdcvqvY0IHEgFDWHNikuQDxEovqSxnR+dyVny4vqpIzXgVhd4sfS1/O0iVghq6q6 HHutCnyNPdl+Lo1sNhnRHPL4dnmGpjW995/3147Qi6KImSMqvQR2uMFNrwUEMA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4PTJyd5wbZzYnJ; Sat, 4 Mar 2023 09:12:41 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 3249Cfus078790; Sat, 4 Mar 2023 09:12:41 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 3249Cfuh078789; Sat, 4 Mar 2023 09:12:41 GMT (envelope-from git) Date: Sat, 4 Mar 2023 09:12:41 GMT Message-Id: <202303040912.3249Cfuh078789@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Dmitry Chagin Subject: git: 6c5786fd37cb - main - linux(4): Migrate to IfAPI List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: dchagin X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 6c5786fd37cb588f577c7fa63c56fc2f59c38786 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by dchagin: URL: https://cgit.FreeBSD.org/src/commit/?id=6c5786fd37cb588f577c7fa63c56fc2f59c38786 commit 6c5786fd37cb588f577c7fa63c56fc2f59c38786 Author: Dmitry Chagin AuthorDate: 2023-03-04 09:11:38 +0000 Commit: Dmitry Chagin CommitDate: 2023-03-04 09:11:38 +0000 linux(4): Migrate to IfAPI Migrate linux and linprocfs to use the IfAPI interfaces instead of direct ifnet accesses. The code initially writed by jhibbits@, and adapted by me to 3ab3c9c2. Reviewed by: jhibbits Differential Revision: https://reviews.freebsd.org/D38735 --- sys/compat/linprocfs/linprocfs.c | 72 ++++++++++-------- sys/compat/linux/linux.c | 160 +++++++++++++++++++++++++-------------- sys/compat/linux/linux.h | 4 +- sys/compat/linux/linux_ioctl.c | 124 +++++++++++++++++------------- 4 files changed, 217 insertions(+), 143 deletions(-) diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c index d57c546eb637..a150019ae5ef 100644 --- a/sys/compat/linprocfs/linprocfs.c +++ b/sys/compat/linprocfs/linprocfs.c @@ -1478,12 +1478,49 @@ linprocfs_doprocmem(PFS_FILL_ARGS) /* * Filler function for proc/net/dev */ +static int +linprocfs_donetdev_cb(if_t ifp, void *arg) +{ + char ifname[LINUX_IFNAMSIZ]; + struct sbuf *sb = arg; + + if (ifname_bsd_to_linux_ifp(ifp, ifname, sizeof(ifname)) <= 0) + return (ENODEV); + + sbuf_printf(sb, "%6.6s: ", ifname); + sbuf_printf(sb, "%7ju %7ju %4ju %4ju %4lu %5lu %10lu %9ju ", + (uintmax_t)if_getcounter(ifp, IFCOUNTER_IBYTES), + (uintmax_t)if_getcounter(ifp, IFCOUNTER_IPACKETS), + (uintmax_t)if_getcounter(ifp, IFCOUNTER_IERRORS), + (uintmax_t)if_getcounter(ifp, IFCOUNTER_IQDROPS), + /* rx_missed_errors */ + 0UL, /* rx_fifo_errors */ + 0UL, /* rx_length_errors + + * rx_over_errors + + * rx_crc_errors + + * rx_frame_errors */ + 0UL, /* rx_compressed */ + (uintmax_t)if_getcounter(ifp, IFCOUNTER_IMCASTS)); + /* XXX-BZ rx only? */ + sbuf_printf(sb, "%8ju %7ju %4ju %4ju %4lu %5ju %7lu %10lu\n", + (uintmax_t)if_getcounter(ifp, IFCOUNTER_OBYTES), + (uintmax_t)if_getcounter(ifp, IFCOUNTER_OPACKETS), + (uintmax_t)if_getcounter(ifp, IFCOUNTER_OERRORS), + (uintmax_t)if_getcounter(ifp, IFCOUNTER_OQDROPS), + 0UL, /* tx_fifo_errors */ + (uintmax_t)if_getcounter(ifp, IFCOUNTER_COLLISIONS), + 0UL, /* tx_carrier_errors + + * tx_aborted_errors + + * tx_window_errors + + * tx_heartbeat_errors*/ + 0UL); /* tx_compressed */ + return (0); +} + static int linprocfs_donetdev(PFS_FILL_ARGS) { struct epoch_tracker et; - char ifname[16]; /* XXX LINUX_IFNAMSIZ */ - struct ifnet *ifp; sbuf_printf(sb, "%6s|%58s|%s\n" "%6s|%58s|%58s\n", @@ -1494,36 +1531,7 @@ linprocfs_donetdev(PFS_FILL_ARGS) CURVNET_SET(TD_TO_VNET(curthread)); NET_EPOCH_ENTER(et); - CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { - ifname_bsd_to_linux_ifp(ifp, ifname, sizeof(ifname)); - sbuf_printf(sb, "%6.6s: ", ifname); - sbuf_printf(sb, "%7ju %7ju %4ju %4ju %4lu %5lu %10lu %9ju ", - (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IBYTES), - (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IPACKETS), - (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IERRORS), - (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IQDROPS), - /* rx_missed_errors */ - 0UL, /* rx_fifo_errors */ - 0UL, /* rx_length_errors + - * rx_over_errors + - * rx_crc_errors + - * rx_frame_errors */ - 0UL, /* rx_compressed */ - (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IMCASTS)); - /* XXX-BZ rx only? */ - sbuf_printf(sb, "%8ju %7ju %4ju %4ju %4lu %5ju %7lu %10lu\n", - (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OBYTES), - (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OPACKETS), - (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OERRORS), - (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OQDROPS), - 0UL, /* tx_fifo_errors */ - (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_COLLISIONS), - 0UL, /* tx_carrier_errors + - * tx_aborted_errors + - * tx_window_errors + - * tx_heartbeat_errors*/ - 0UL); /* tx_compressed */ - } + if_foreach(linprocfs_donetdev_cb, sb); NET_EPOCH_EXIT(et); CURVNET_RESTORE(); diff --git a/sys/compat/linux/linux.c b/sys/compat/linux/linux.c index 2570a5fcc89c..a7844f4bbbcf 100644 --- a/sys/compat/linux/linux.c +++ b/sys/compat/linux/linux.c @@ -287,13 +287,37 @@ ifname_bsd_to_linux_idx(u_int idx, char *lxname, size_t len) /* * Translate a FreeBSD interface name to a Linux interface name, - * and return the number of bytes copied to lxname. + * and return the number of bytes copied to lxname, 0 if interface + * not found, -1 on error. */ +struct ifname_bsd_to_linux_ifp_cb_s { + struct ifnet *ifp; + int ethno; + char *lxname; + size_t len; +}; + +static int +ifname_bsd_to_linux_ifp_cb(if_t ifp, void *arg) +{ + struct ifname_bsd_to_linux_ifp_cb_s *cbs = arg; + + if (ifp == cbs->ifp) + return (snprintf(cbs->lxname, cbs->len, "eth%d", cbs->ethno)); + if (IFP_IS_ETH(ifp)) + cbs->ethno++; + return (0); +} + int ifname_bsd_to_linux_ifp(struct ifnet *ifp, char *lxname, size_t len) { - struct ifnet *ifscan; - int unit; + struct ifname_bsd_to_linux_ifp_cb_s arg = { + .ifp = ifp, + .ethno = 0, + .lxname = lxname, + .len = len, + }; NET_EPOCH_ASSERT(); @@ -306,17 +330,10 @@ ifname_bsd_to_linux_ifp(struct ifnet *ifp, char *lxname, size_t len) /* Short-circuit non ethernet interfaces. */ if (!IFP_IS_ETH(ifp) || linux_use_real_ifname(ifp)) - return (strlcpy(lxname, ifp->if_xname, len)); - - /* Determine the (relative) unit number for ethernet interfaces. */ - unit = 0; - CK_STAILQ_FOREACH(ifscan, &V_ifnet, if_link) { - if (ifscan == ifp) - return (snprintf(lxname, len, "eth%d", unit)); - if (IFP_IS_ETH(ifscan)) - unit++; - } - return (0); + return (strlcpy(lxname, if_name(ifp), len)); + + /* Determine the (relative) unit number for ethernet interfaces. */ + return (if_foreach(ifname_bsd_to_linux_ifp_cb, &arg)); } /* @@ -325,14 +342,53 @@ ifname_bsd_to_linux_ifp(struct ifnet *ifp, char *lxname, size_t len) * bsdname and lxname need to be least IFNAMSIZ bytes long, but * can point to the same buffer. */ +struct ifname_linux_to_bsd_cb_s { + bool is_lo; + bool is_eth; + int ethno; + int unit; + const char *lxname; + if_t ifp; +}; + +static int +ifname_linux_to_bsd_cb(if_t ifp, void *arg) +{ + struct ifname_linux_to_bsd_cb_s *cbs = arg; + + NET_EPOCH_ASSERT(); + + /* + * Allow Linux programs to use FreeBSD names. Don't presume + * we never have an interface named "eth", so don't make + * the test optional based on is_eth. + */ + if (strncmp(if_name(ifp), cbs->lxname, LINUX_IFNAMSIZ) == 0) + goto out; + if (cbs->is_eth && IFP_IS_ETH(ifp) && cbs->unit == cbs->ethno) + goto out; + if (cbs->is_lo && IFP_IS_LOOP(ifp)) + goto out; + if (IFP_IS_ETH(ifp)) + cbs->ethno++; + return (0); + +out: + cbs->ifp = ifp; + return (1); +} + struct ifnet * ifname_linux_to_bsd(struct thread *td, const char *lxname, char *bsdname) { - struct ifnet *ifp; - int len, unit; + struct ifname_linux_to_bsd_cb_s arg = { + .ethno = 0, + .lxname = lxname, + .ifp = NULL, + }; + struct epoch_tracker et; + int len, ret; char *ep; - int index; - bool is_eth, is_lo; for (len = 0; len < LINUX_IFNAMSIZ; ++len) if (!isalpha(lxname[len]) || lxname[len] == '\0') @@ -343,34 +399,21 @@ ifname_linux_to_bsd(struct thread *td, const char *lxname, char *bsdname) * Linux loopback interface name is lo (not lo0), * we translate lo to lo0, loX to loX. */ - is_lo = (len == 2 && strncmp(lxname, "lo", LINUX_IFNAMSIZ) == 0); - unit = (int)strtoul(lxname + len, &ep, 10); + arg.is_lo = (len == 2 && strncmp(lxname, "lo", LINUX_IFNAMSIZ) == 0); + arg.unit = (int)strtoul(lxname + len, &ep, 10); if ((ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ) && - is_lo == 0) + arg.is_lo == 0) return (NULL); - index = 0; - is_eth = (len == 3 && strncmp(lxname, "eth", len) == 0); + arg.is_eth = (len == 3 && strncmp(lxname, "eth", len) == 0); CURVNET_SET(TD_TO_VNET(td)); - IFNET_RLOCK(); - CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { - /* - * Allow Linux programs to use FreeBSD names. Don't presume - * we never have an interface named "eth", so don't make - * the test optional based on is_eth. - */ - if (strncmp(ifp->if_xname, lxname, LINUX_IFNAMSIZ) == 0) - break; - if (is_eth && IFP_IS_ETH(ifp) && unit == index++) - break; - if (is_lo && IFP_IS_LOOP(ifp)) - break; - } - IFNET_RUNLOCK(); + NET_EPOCH_ENTER(et); + ret = if_foreach(ifname_linux_to_bsd_cb, &arg); + NET_EPOCH_EXIT(et); CURVNET_RESTORE(); - if (ifp != NULL && bsdname != NULL) - strlcpy(bsdname, ifp->if_xname, IFNAMSIZ); - return (ifp); + if (ret > 0 && arg.ifp != NULL && bsdname != NULL) + strlcpy(bsdname, if_name(arg.ifp), IFNAMSIZ); + return (arg.ifp); } void @@ -378,7 +421,7 @@ linux_ifflags(struct ifnet *ifp, short *flags) { unsigned short fl; - fl = (ifp->if_flags | ifp->if_drv_flags) & 0xffff; + fl = (if_getflags(ifp) | if_getdrvflags(ifp)) & 0xffff; *flags = 0; if (fl & IFF_UP) *flags |= LINUX_IFF_UP; @@ -402,32 +445,35 @@ linux_ifflags(struct ifnet *ifp, short *flags) *flags |= LINUX_IFF_MULTICAST; } +static u_int +linux_ifhwaddr_cb(void *arg, struct ifaddr *ifa, u_int count) +{ + struct sockaddr_dl *sdl = (struct sockaddr_dl *)ifa->ifa_addr; + struct l_sockaddr *lsa = arg; + + if (count > 0) + return (0); + if (sdl->sdl_type != IFT_ETHER) + return (0); + bzero(lsa, sizeof(*lsa)); + lsa->sa_family = LINUX_ARPHRD_ETHER; + bcopy(LLADDR(sdl), lsa->sa_data, LINUX_IFHWADDRLEN); + return (1); +} + int linux_ifhwaddr(struct ifnet *ifp, struct l_sockaddr *lsa) { - struct ifaddr *ifa; - struct sockaddr_dl *sdl; if (IFP_IS_LOOP(ifp)) { bzero(lsa, sizeof(*lsa)); lsa->sa_family = LINUX_ARPHRD_LOOPBACK; return (0); } - if (!IFP_IS_ETH(ifp)) return (ENOENT); - - CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { - sdl = (struct sockaddr_dl*)ifa->ifa_addr; - if (sdl != NULL && (sdl->sdl_family == AF_LINK) && - (sdl->sdl_type == IFT_ETHER)) { - bzero(lsa, sizeof(*lsa)); - lsa->sa_family = LINUX_ARPHRD_ETHER; - bcopy(LLADDR(sdl), lsa->sa_data, LINUX_IFHWADDRLEN); - return (0); - } - } - + if (if_foreach_addr_type(ifp, AF_LINK, linux_ifhwaddr_cb, lsa) > 0) + return (0); return (ENOENT); } diff --git a/sys/compat/linux/linux.h b/sys/compat/linux/linux.h index 055d8e3b9cf6..e133c35010cf 100644 --- a/sys/compat/linux/linux.h +++ b/sys/compat/linux/linux.h @@ -287,8 +287,8 @@ struct l_statx { /* * Criteria for interface name translation */ -#define IFP_IS_ETH(ifp) ((ifp)->if_type == IFT_ETHER) -#define IFP_IS_LOOP(ifp) ((ifp)->if_type == IFT_LOOP) +#define IFP_IS_ETH(ifp) (if_gettype(ifp) == IFT_ETHER) +#define IFP_IS_LOOP(ifp) (if_gettype(ifp) == IFT_LOOP) struct ifnet; diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c index bfab28f841a0..8900102bbbc7 100644 --- a/sys/compat/linux/linux_ioctl.c +++ b/sys/compat/linux/linux_ioctl.c @@ -2108,40 +2108,91 @@ linux_ioctl_ifname(struct thread *td, struct l_ifreq *uifr) /* * Implement the SIOCGIFCONF ioctl */ +static u_int +linux_ifconf_ifaddr_cb(void *arg, struct ifaddr *ifa, u_int count) +{ +#ifdef COMPAT_LINUX32 + struct l_ifconf *ifc; +#else + struct ifconf *ifc; +#endif + + ifc = arg; + ifc->ifc_len += sizeof(struct l_ifreq); + return (1); +} + +static int +linux_ifconf_ifnet_cb(if_t ifp, void *arg) +{ + + if_foreach_addr_type(ifp, AF_INET, linux_ifconf_ifaddr_cb, arg); + return (0); +} + +struct linux_ifconfig_ifaddr_cb2_s { + struct l_ifreq ifr; + struct sbuf *sb; + size_t max_len; + size_t valid_len; +}; + +static u_int +linux_ifconf_ifaddr_cb2(void *arg, struct ifaddr *ifa, u_int len) +{ + struct linux_ifconfig_ifaddr_cb2_s *cbs = arg; + struct sockaddr *sa = ifa->ifa_addr; + + cbs->ifr.ifr_addr.sa_family = LINUX_AF_INET; + memcpy(cbs->ifr.ifr_addr.sa_data, sa->sa_data, + sizeof(cbs->ifr.ifr_addr.sa_data)); + sbuf_bcat(cbs->sb, &cbs->ifr, sizeof(cbs->ifr)); + cbs->max_len += sizeof(cbs->ifr); + + if (sbuf_error(cbs->sb) == 0) + cbs->valid_len = sbuf_len(cbs->sb); + return (1); +} + +static int +linux_ifconf_ifnet_cb2(if_t ifp, void *arg) +{ + struct linux_ifconfig_ifaddr_cb2_s *cbs = arg; + + bzero(&cbs->ifr, sizeof(cbs->ifr)); + ifname_bsd_to_linux_ifp(ifp, cbs->ifr.ifr_name, + sizeof(cbs->ifr.ifr_name)); + + /* Walk the address list */ + if_foreach_addr_type(ifp, AF_INET, linux_ifconf_ifaddr_cb2, cbs); + return (0); +} static int linux_ifconf(struct thread *td, struct ifconf *uifc) { + struct linux_ifconfig_ifaddr_cb2_s cbs; struct epoch_tracker et; #ifdef COMPAT_LINUX32 struct l_ifconf ifc; #else struct ifconf ifc; #endif - struct l_ifreq ifr; - struct ifnet *ifp; - struct ifaddr *ifa; struct sbuf *sb; - int error, full = 0, valid_len, max_len; + int error, full; error = copyin(uifc, &ifc, sizeof(ifc)); if (error != 0) return (error); - - max_len = maxphys - 1; + full = 0; + cbs.max_len = maxphys - 1; CURVNET_SET(TD_TO_VNET(td)); /* handle the 'request buffer size' case */ if ((l_uintptr_t)ifc.ifc_buf == PTROUT(NULL)) { ifc.ifc_len = 0; NET_EPOCH_ENTER(et); - CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { - CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { - struct sockaddr *sa = ifa->ifa_addr; - if (sa->sa_family == AF_INET) - ifc.ifc_len += sizeof(ifr); - } - } + if_foreach(linux_ifconf_ifnet_cb, &ifc); NET_EPOCH_EXIT(et); error = copyout(&ifc, uifc, sizeof(ifc)); CURVNET_RESTORE(); @@ -2154,56 +2205,25 @@ linux_ifconf(struct thread *td, struct ifconf *uifc) } again: - if (ifc.ifc_len <= max_len) { - max_len = ifc.ifc_len; + if (ifc.ifc_len <= cbs.max_len) { + cbs.max_len = ifc.ifc_len; full = 1; } - sb = sbuf_new(NULL, NULL, max_len + 1, SBUF_FIXEDLEN); - max_len = 0; - valid_len = 0; + cbs.sb = sb = sbuf_new(NULL, NULL, cbs.max_len + 1, SBUF_FIXEDLEN); + cbs.max_len = 0; + cbs.valid_len = 0; /* Return all AF_INET addresses of all interfaces */ NET_EPOCH_ENTER(et); - CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { - int addrs = 0; - - bzero(&ifr, sizeof(ifr)); - ifname_bsd_to_linux_ifp(ifp, ifr.ifr_name, - sizeof(ifr.ifr_name)); - - /* Walk the address list */ - CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { - struct sockaddr *sa = ifa->ifa_addr; - - 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)); - sbuf_bcat(sb, &ifr, sizeof(ifr)); - max_len += sizeof(ifr); - addrs++; - } - - if (sbuf_error(sb) == 0) - valid_len = sbuf_len(sb); - } - if (addrs == 0) { - bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); - sbuf_bcat(sb, &ifr, sizeof(ifr)); - max_len += sizeof(ifr); - - if (sbuf_error(sb) == 0) - valid_len = sbuf_len(sb); - } - } + if_foreach(linux_ifconf_ifnet_cb2, &cbs); NET_EPOCH_EXIT(et); - if (valid_len != max_len && !full) { + if (cbs.valid_len != cbs.max_len && !full) { sbuf_delete(sb); goto again; } - ifc.ifc_len = valid_len; + ifc.ifc_len = cbs.valid_len; sbuf_finish(sb); error = copyout(sbuf_data(sb), PTRIN(ifc.ifc_buf), ifc.ifc_len); if (error == 0)