git: e9e637bf243c - main - Revert "Port Linuxulator to IfAPI"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 21 Feb 2023 17:20:30 UTC
The branch main has been updated by jhibbits:
URL: https://cgit.FreeBSD.org/src/commit/?id=e9e637bf243c35180936574e761b2fa164a97144
commit e9e637bf243c35180936574e761b2fa164a97144
Author: Justin Hibbits <jhibbits@FreeBSD.org>
AuthorDate: 2023-02-21 17:18:36 +0000
Commit: Justin Hibbits <jhibbits@FreeBSD.org>
CommitDate: 2023-02-21 17:20:24 +0000
Revert "Port Linuxulator to IfAPI"
Revert pending netlink fixes, and further fixes to this.
This reverts commit 52d984831d82d97dc132d0d57fca6ee89572799b.
Requested by: dchagin
---
sys/compat/linux/linux.c | 104 ++++++++-------------
sys/compat/linux/linux.h | 4 +-
sys/compat/linux/linux_ioctl.c | 205 ++++++++++++++++-------------------------
3 files changed, 118 insertions(+), 195 deletions(-)
diff --git a/sys/compat/linux/linux.c b/sys/compat/linux/linux.c
index 16aa731b20ff..4e435081b3b6 100644
--- a/sys/compat/linux/linux.c
+++ b/sys/compat/linux/linux.c
@@ -241,36 +241,6 @@ bsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss)
}
}
-struct ifname_linux_to_bsd_cb_s {
- if_t ifp;
- const char *lxname;
- int unit;
- int index;
- bool is_lo;
- bool is_eth;
-};
-
-static int
-ifname_linux_to_bsd_cb(if_t ifp, void *arg)
-{
- struct ifname_linux_to_bsd_cb_s *cbs = arg;
-
- /*
- * 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.
- */
- cbs->ifp = ifp;
- if (strncmp(if_name(ifp), cbs->lxname, LINUX_IFNAMSIZ) == 0)
- return (-1);
- if (cbs->is_eth && IFP_IS_ETH(ifp) && cbs->unit == cbs->index++)
- return (-1);
- if (cbs->is_lo && IFP_IS_LOOP(ifp))
- return (-1);
- cbs->ifp = NULL;
-
- return (0);
-}
/*
* Translate a Linux interface name to a FreeBSD interface name,
* and return the associated ifnet structure
@@ -280,33 +250,46 @@ ifname_linux_to_bsd_cb(if_t ifp, void *arg)
struct ifnet *
ifname_linux_to_bsd(struct thread *td, const char *lxname, char *bsdname)
{
- struct ifname_linux_to_bsd_cb_s cbs = {};
- int len;
+ struct ifnet *ifp;
+ int len, unit;
char *ep;
+ int index;
+ bool is_eth, is_lo;
- cbs.lxname = lxname;
for (len = 0; len < LINUX_IFNAMSIZ; ++len)
if (!isalpha(lxname[len]) || lxname[len] == '\0')
break;
if (len == 0 || len == LINUX_IFNAMSIZ)
return (NULL);
/* Linux loopback interface name is lo (not lo0) */
- cbs.is_lo = (len == 2 && strncmp(lxname, "lo", len) == 0);
- cbs.unit = (int)strtoul(lxname + len, &ep, 10);
+ is_lo = (len == 2 && strncmp(lxname, "lo", len) == 0);
+ unit = (int)strtoul(lxname + len, &ep, 10);
if ((ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ) &&
- cbs.is_lo == 0)
+ is_lo == 0)
return (NULL);
- cbs.index = 0;
- cbs.is_eth = (len == 3 && strncmp(lxname, "eth", len) == 0);
+ index = 0;
+ is_eth = (len == 3 && strncmp(lxname, "eth", len) == 0);
CURVNET_SET(TD_TO_VNET(td));
IFNET_RLOCK();
- if_foreach(ifname_linux_to_bsd_cb, &cbs);
+ 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();
CURVNET_RESTORE();
- if (cbs.ifp != NULL && bsdname != NULL)
- strlcpy(bsdname, if_name(cbs.ifp), IFNAMSIZ);
- return (cbs.ifp);
+ if (ifp != NULL && bsdname != NULL)
+ strlcpy(bsdname, ifp->if_xname, IFNAMSIZ);
+ return (ifp);
}
void
@@ -314,7 +297,7 @@ linux_ifflags(struct ifnet *ifp, short *flags)
{
unsigned short fl;
- fl = (if_getflags(ifp) | if_getdrvflags(ifp)) & 0xffff;
+ fl = (ifp->if_flags | ifp->if_drv_flags) & 0xffff;
*flags = 0;
if (fl & IFF_UP)
*flags |= LINUX_IFF_UP;
@@ -338,28 +321,11 @@ 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));
@@ -370,8 +336,16 @@ linux_ifhwaddr(struct ifnet *ifp, struct l_sockaddr *lsa)
if (!IFP_IS_ETH(ifp))
return (ENOENT);
- if (if_foreach_addr_type(ifp, AF_LINK, linux_ifhwaddr_cb, lsa) > 0)
- return (0);
+ 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);
+ }
+ }
return (ENOENT);
}
@@ -758,5 +732,5 @@ bool
linux_use_real_ifname(const struct ifnet *ifp)
{
- return (use_real_ifnames || !IFP_IS_ETH(__DECONST(if_t, ifp)));
+ return (use_real_ifnames || !IFP_IS_ETH(ifp));
}
diff --git a/sys/compat/linux/linux.h b/sys/compat/linux/linux.h
index e133c35010cf..055d8e3b9cf6 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) (if_gettype(ifp) == IFT_ETHER)
-#define IFP_IS_LOOP(ifp) (if_gettype(ifp) == IFT_LOOP)
+#define IFP_IS_ETH(ifp) ((ifp)->if_type == IFT_ETHER)
+#define IFP_IS_LOOP(ifp) ((ifp)->if_type == IFT_LOOP)
struct ifnet;
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
index c70060b8bf5d..2cb0e9ead23f 100644
--- a/sys/compat/linux/linux_ioctl.c
+++ b/sys/compat/linux/linux_ioctl.c
@@ -2087,138 +2087,46 @@ linux_ioctl_console(struct thread *td, struct linux_ioctl_args *args)
/*
* Implement the SIOCGIFNAME ioctl
*/
-struct linux_ioctl_ifname_cb_s {
- struct l_ifreq ifr;
- int index;
- int ethno;
-};
-
-static int
-linux_ioctl_ifname_cb(if_t ifp, void *arg)
-{
- struct linux_ioctl_ifname_cb_s *cbs = arg;
-
- if (cbs->ifr.ifr_ifindex == cbs->index) {
- if (!linux_use_real_ifname(ifp))
- snprintf(cbs->ifr.ifr_name, LINUX_IFNAMSIZ,
- "eth%d", cbs->ethno);
- else
- strlcpy(cbs->ifr.ifr_name, if_name(ifp),
- LINUX_IFNAMSIZ);
- return (-1);
- }
- if (!linux_use_real_ifname(ifp))
- cbs->ethno++;
- cbs->index++;
-
- return (0);
-}
static int
linux_ioctl_ifname(struct thread *td, struct l_ifreq *uifr)
{
- struct linux_ioctl_ifname_cb_s cbs;
struct l_ifreq ifr;
- int error;
+ struct ifnet *ifp;
+ int error, ethno, index;
- error = copyin(uifr, &cbs.ifr, sizeof(cbs.ifr));
+ error = copyin(uifr, &ifr, sizeof(ifr));
if (error != 0)
return (error);
CURVNET_SET(TD_TO_VNET(curthread));
IFNET_RLOCK();
- cbs.index = 1; /* ifr.ifr_ifindex starts from 1 */
- cbs.ethno = 0;
- error = if_foreach(linux_ioctl_ifname_cb, &cbs);
-
- if (error == 0)
- error = ENODEV;
+ index = 1; /* ifr.ifr_ifindex starts from 1 */
+ ethno = 0;
+ error = ENODEV;
+ CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
+ if (ifr.ifr_ifindex == index) {
+ if (!linux_use_real_ifname(ifp))
+ snprintf(ifr.ifr_name, LINUX_IFNAMSIZ,
+ "eth%d", ethno);
+ else
+ strlcpy(ifr.ifr_name, ifp->if_xname,
+ LINUX_IFNAMSIZ);
+ error = 0;
+ break;
+ }
+ if (!linux_use_real_ifname(ifp))
+ ethno++;
+ index++;
+ }
IFNET_RUNLOCK();
- if (error == -1)
+ if (error == 0)
error = copyout(&ifr, uifr, sizeof(ifr));
CURVNET_RESTORE();
return (error);
}
-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;
- int ethno;
-};
-
-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 (len);
-}
-
-static int
-linux_ifconf_ifnet_cb2(if_t ifp, void *arg)
-{
- struct linux_ifconfig_ifaddr_cb2_s *cbs = arg;
- int addrs = 0;
-
- bzero(&cbs->ifr, sizeof(cbs->ifr));
- if (IFP_IS_ETH(ifp))
- snprintf(cbs->ifr.ifr_name, LINUX_IFNAMSIZ, "eth%d",
- cbs->ethno++);
- else
- strlcpy(cbs->ifr.ifr_name, if_name(ifp), LINUX_IFNAMSIZ);
-
- /* Walk the address list */
- addrs = if_foreach_addr_type(ifp, AF_INET,
- linux_ifconf_ifaddr_cb2, cbs);
- if (sbuf_error(cbs->sb) == 0)
- cbs->valid_len = sbuf_len(cbs->sb);
- if (addrs == 0) {
- bzero((caddr_t)&cbs->ifr.ifr_addr, sizeof(cbs->ifr.ifr_addr));
- 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 (0);
-}
-
/*
* Implement the SIOCGIFCONF ioctl
*/
@@ -2231,22 +2139,30 @@ linux_ifconf(struct thread *td, struct ifconf *uifc)
#else
struct ifconf ifc;
#endif
- struct linux_ifconfig_ifaddr_cb2_s cbs;
+ struct l_ifreq ifr;
+ struct ifnet *ifp;
+ struct ifaddr *ifa;
struct sbuf *sb;
- int error, full = 0;
+ int error, ethno, full = 0, valid_len, max_len;
error = copyin(uifc, &ifc, sizeof(ifc));
if (error != 0)
return (error);
- cbs.max_len = maxphys - 1;
+ 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;
IFNET_RLOCK();
- if_foreach(linux_ifconf_ifnet_cb, &ifc);
+ 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);
+ }
+ }
IFNET_RUNLOCK();
error = copyout(&ifc, uifc, sizeof(ifc));
CURVNET_RESTORE();
@@ -2259,28 +2175,61 @@ linux_ifconf(struct thread *td, struct ifconf *uifc)
}
again:
- cbs.ethno = 0;
/* Keep track of eth interfaces */
- if (ifc.ifc_len <= cbs.max_len) {
- cbs.max_len = ifc.ifc_len;
+ ethno = 0;
+ if (ifc.ifc_len <= max_len) {
+ max_len = ifc.ifc_len;
full = 1;
}
- sb = sbuf_new(NULL, NULL, cbs.max_len + 1, SBUF_FIXEDLEN);
- cbs.max_len = 0;
- cbs.valid_len = 0;
- cbs.sb = sb;
+ sb = sbuf_new(NULL, NULL, max_len + 1, SBUF_FIXEDLEN);
+ max_len = 0;
+ valid_len = 0;
/* Return all AF_INET addresses of all interfaces */
IFNET_RLOCK();
- if_foreach(linux_ifconf_ifnet_cb2, &cbs);
+ CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
+ int addrs = 0;
+
+ bzero(&ifr, sizeof(ifr));
+ if (IFP_IS_ETH(ifp))
+ snprintf(ifr.ifr_name, LINUX_IFNAMSIZ, "eth%d",
+ ethno++);
+ else
+ strlcpy(ifr.ifr_name, ifp->if_xname, LINUX_IFNAMSIZ);
+
+ /* 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);
+ }
+ }
IFNET_RUNLOCK();
- if (cbs.valid_len != cbs.max_len && !full) {
+ if (valid_len != max_len && !full) {
sbuf_delete(sb);
goto again;
}
- ifc.ifc_len = cbs.valid_len;
+ ifc.ifc_len = valid_len;
sbuf_finish(sb);
error = copyout(sbuf_data(sb), PTRIN(ifc.ifc_buf), ifc.ifc_len);
if (error == 0)