Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F104972110
D38349.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D38349.diff
View Options
diff --git a/sys/compat/linux/linux.h b/sys/compat/linux/linux.h
--- a/sys/compat/linux/linux.h
+++ b/sys/compat/linux/linux.h
@@ -287,8 +287,8 @@
/*
* 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.c b/sys/compat/linux/linux.c
--- a/sys/compat/linux/linux.c
+++ b/sys/compat/linux/linux.c
@@ -241,6 +241,36 @@
}
}
+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
@@ -250,46 +280,33 @@
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 cbs = {};
+ int len;
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) */
- is_lo = (len == 2 && strncmp(lxname, "lo", len) == 0);
- unit = (int)strtoul(lxname + len, &ep, 10);
+ cbs.is_lo = (len == 2 && strncmp(lxname, "lo", len) == 0);
+ cbs.unit = (int)strtoul(lxname + len, &ep, 10);
if ((ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ) &&
- is_lo == 0)
+ cbs.is_lo == 0)
return (NULL);
- index = 0;
- is_eth = (len == 3 && strncmp(lxname, "eth", len) == 0);
+ cbs.index = 0;
+ cbs.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;
- }
+ if_foreach(ifname_linux_to_bsd_cb, &cbs);
IFNET_RUNLOCK();
CURVNET_RESTORE();
- if (ifp != NULL && bsdname != NULL)
- strlcpy(bsdname, ifp->if_xname, IFNAMSIZ);
- return (ifp);
+ if (cbs.ifp != NULL && bsdname != NULL)
+ strlcpy(bsdname, if_name(cbs.ifp), IFNAMSIZ);
+ return (cbs.ifp);
}
void
@@ -297,7 +314,7 @@
{
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;
@@ -321,11 +338,28 @@
*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));
@@ -336,16 +370,8 @@
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);
}
@@ -732,5 +758,5 @@
linux_use_real_ifname(const struct ifnet *ifp)
{
- return (use_real_ifnames || !IFP_IS_ETH(ifp));
+ return (use_real_ifnames || !IFP_IS_ETH(__DECONST(if_t, ifp)));
}
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
--- a/sys/compat/linux/linux_ioctl.c
+++ b/sys/compat/linux/linux_ioctl.c
@@ -2087,46 +2087,138 @@
/*
* 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;
- struct ifnet *ifp;
- int error, ethno, index;
+ int error;
- error = copyin(uifr, &ifr, sizeof(ifr));
+ error = copyin(uifr, &cbs.ifr, sizeof(cbs.ifr));
if (error != 0)
return (error);
CURVNET_SET(TD_TO_VNET(curthread));
IFNET_RLOCK();
- 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();
+ 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;
+ IFNET_RUNLOCK();
+ if (error == -1)
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
*/
@@ -2139,30 +2231,22 @@
#else
struct ifconf ifc;
#endif
- struct l_ifreq ifr;
- struct ifnet *ifp;
- struct ifaddr *ifa;
+ struct linux_ifconfig_ifaddr_cb2_s cbs;
struct sbuf *sb;
- int error, ethno, full = 0, valid_len, max_len;
+ int error, full = 0;
error = copyin(uifc, &ifc, sizeof(ifc));
if (error != 0)
return (error);
- max_len = maxphys - 1;
+ 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;
IFNET_RLOCK();
- 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);
IFNET_RUNLOCK();
error = copyout(&ifc, uifc, sizeof(ifc));
CURVNET_RESTORE();
@@ -2175,61 +2259,28 @@
}
again:
+ cbs.ethno = 0;
/* Keep track of eth interfaces */
- ethno = 0;
- 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;
+ sb = sbuf_new(NULL, NULL, cbs.max_len + 1, SBUF_FIXEDLEN);
+ cbs.max_len = 0;
+ cbs.valid_len = 0;
+ cbs.sb = sb;
/* Return all AF_INET addresses of all interfaces */
IFNET_RLOCK();
- 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);
- }
- }
+ if_foreach(linux_ifconf_ifnet_cb2, &cbs);
IFNET_RUNLOCK();
- 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)
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Dec 12, 6:21 AM (14 h, 43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15311526
Default Alt Text
D38349.diff (10 KB)
Attached To
Mode
D38349: Port Linuxulator to IfAPI
Attached
Detach File
Event Timeline
Log In to Comment