Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F109237777
D38735.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D38735.diff
View Options
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -1478,12 +1478,49 @@
/*
* 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 @@
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.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
@@ -287,13 +287,37 @@
/*
* 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 @@
/* 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 @@
* 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 @@
* 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 @@
{
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 @@
*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_ioctl.c b/sys/compat/linux/linux_ioctl.c
--- a/sys/compat/linux/linux_ioctl.c
+++ b/sys/compat/linux/linux_ioctl.c
@@ -2108,40 +2108,91 @@
/*
* 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 @@
}
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)
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 3, 11:14 AM (21 h, 15 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16432393
Default Alt Text
D38735.diff (13 KB)
Attached To
Mode
D38735: linux(4): Migrate to IfAPI
Attached
Detach File
Event Timeline
Log In to Comment