mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-12 09:58:36 +00:00
linux(4): Consolidate a FreeBSD interface names translation code
We have some amount of interface names translation functions which are
differs by bugs implementation. Consolidates it in a one place.
Fixup loopback interface names translation and use ifnet methods and
accessors, where possible.
Reviewed by: melifaro
Differential Revision: https://reviews.freebsd.org/D38714
MFC after: 3 days
X-MFC with: 32fdc75fe7
This commit is contained in:
parent
200fe6e3a0
commit
3ab3c9c29c
@ -111,6 +111,7 @@ __FBSDID("$FreeBSD$");
|
||||
#endif /* __i386__ || __amd64__ */
|
||||
|
||||
#include <compat/linux/linux.h>
|
||||
#include <compat/linux/linux_common.h>
|
||||
#include <compat/linux/linux_emul.h>
|
||||
#include <compat/linux/linux_mib.h>
|
||||
#include <compat/linux/linux_misc.h>
|
||||
@ -1474,36 +1475,13 @@ linprocfs_doprocmem(PFS_FILL_ARGS)
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
linux_ifname(struct ifnet *ifp, char *buffer, size_t buflen)
|
||||
{
|
||||
struct ifnet *ifscan;
|
||||
int ethno;
|
||||
|
||||
IFNET_RLOCK_ASSERT();
|
||||
|
||||
/* Short-circuit non ethernet interfaces */
|
||||
if (linux_use_real_ifname(ifp))
|
||||
return (strlcpy(buffer, ifp->if_xname, buflen));
|
||||
|
||||
/* Determine the (relative) unit number for ethernet interfaces */
|
||||
ethno = 0;
|
||||
CK_STAILQ_FOREACH(ifscan, &V_ifnet, if_link) {
|
||||
if (ifscan == ifp)
|
||||
return (snprintf(buffer, buflen, "eth%d", ethno));
|
||||
if (!linux_use_real_ifname(ifscan))
|
||||
ethno++;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Filler function for proc/net/dev
|
||||
*/
|
||||
static int
|
||||
linprocfs_donetdev(PFS_FILL_ARGS)
|
||||
{
|
||||
struct epoch_tracker et;
|
||||
char ifname[16]; /* XXX LINUX_IFNAMSIZ */
|
||||
struct ifnet *ifp;
|
||||
|
||||
@ -1515,9 +1493,9 @@ linprocfs_donetdev(PFS_FILL_ARGS)
|
||||
"bytes packets errs drop fifo colls carrier compressed");
|
||||
|
||||
CURVNET_SET(TD_TO_VNET(curthread));
|
||||
IFNET_RLOCK();
|
||||
NET_EPOCH_ENTER(et);
|
||||
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
|
||||
linux_ifname(ifp, ifname, sizeof ifname);
|
||||
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),
|
||||
@ -1546,7 +1524,7 @@ linprocfs_donetdev(PFS_FILL_ARGS)
|
||||
* tx_heartbeat_errors*/
|
||||
0UL); /* tx_compressed */
|
||||
}
|
||||
IFNET_RUNLOCK();
|
||||
NET_EPOCH_EXIT(et);
|
||||
CURVNET_RESTORE();
|
||||
|
||||
return (0);
|
||||
@ -1576,7 +1554,8 @@ linux_route_print(struct rtentry *rt, void *vw)
|
||||
/* select only first route in case of multipath */
|
||||
nh = nhop_select_func(rnd.rnd_nhop, 0);
|
||||
|
||||
linux_ifname(nh->nh_ifp, ifname, sizeof(ifname));
|
||||
if (ifname_bsd_to_linux_ifp(nh->nh_ifp, ifname, sizeof(ifname)) <= 0)
|
||||
return (ENODEV);
|
||||
|
||||
gw = (nh->nh_flags & NHF_GATEWAY)
|
||||
? nh->gw4_sa.sin_addr.s_addr : 0;
|
||||
@ -1605,6 +1584,7 @@ linux_route_print(struct rtentry *rt, void *vw)
|
||||
static int
|
||||
linprocfs_donetroute(PFS_FILL_ARGS)
|
||||
{
|
||||
struct epoch_tracker et;
|
||||
struct walkarg w = {
|
||||
.sb = sb
|
||||
};
|
||||
@ -1615,9 +1595,9 @@ linprocfs_donetroute(PFS_FILL_ARGS)
|
||||
"\tWindow\tIRTT");
|
||||
|
||||
CURVNET_SET(TD_TO_VNET(curthread));
|
||||
IFNET_RLOCK();
|
||||
NET_EPOCH_ENTER(et);
|
||||
rib_walk(fibnum, AF_INET, false, linux_route_print, &w);
|
||||
IFNET_RUNLOCK();
|
||||
NET_EPOCH_EXIT(et);
|
||||
CURVNET_RESTORE();
|
||||
|
||||
return (0);
|
||||
|
@ -241,6 +241,84 @@ bsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate a FreeBSD interface name to a Linux interface name
|
||||
* by interface name, and return the number of bytes copied to lxname.
|
||||
*/
|
||||
int
|
||||
ifname_bsd_to_linux_name(const char *bsdname, char *lxname, size_t len)
|
||||
{
|
||||
struct epoch_tracker et;
|
||||
struct ifnet *ifp;
|
||||
int ret;
|
||||
|
||||
ret = 0;
|
||||
CURVNET_SET(TD_TO_VNET(curthread));
|
||||
NET_EPOCH_ENTER(et);
|
||||
ifp = ifunit(bsdname);
|
||||
if (ifp != NULL)
|
||||
ret = ifname_bsd_to_linux_ifp(ifp, lxname, len);
|
||||
NET_EPOCH_EXIT(et);
|
||||
CURVNET_RESTORE();
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate a FreeBSD interface name to a Linux interface name
|
||||
* by interface index, and return the number of bytes copied to lxname.
|
||||
*/
|
||||
int
|
||||
ifname_bsd_to_linux_idx(u_int idx, char *lxname, size_t len)
|
||||
{
|
||||
struct epoch_tracker et;
|
||||
struct ifnet *ifp;
|
||||
int ret;
|
||||
|
||||
ret = 0;
|
||||
CURVNET_SET(TD_TO_VNET(curthread));
|
||||
NET_EPOCH_ENTER(et);
|
||||
ifp = ifnet_byindex(idx);
|
||||
if (ifp != NULL)
|
||||
ret = ifname_bsd_to_linux_ifp(ifp, lxname, len);
|
||||
NET_EPOCH_EXIT(et);
|
||||
CURVNET_RESTORE();
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate a FreeBSD interface name to a Linux interface name,
|
||||
* and return the number of bytes copied to lxname.
|
||||
*/
|
||||
int
|
||||
ifname_bsd_to_linux_ifp(struct ifnet *ifp, char *lxname, size_t len)
|
||||
{
|
||||
struct ifnet *ifscan;
|
||||
int unit;
|
||||
|
||||
NET_EPOCH_ASSERT();
|
||||
|
||||
/*
|
||||
* Linux loopback interface name is lo (not lo0),
|
||||
* we translate lo to lo0, loX to loX.
|
||||
*/
|
||||
if (IFP_IS_LOOP(ifp) && strncmp(ifp->if_xname, "lo0", IFNAMSIZ) == 0)
|
||||
return (strlcpy(lxname, "lo", 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate a Linux interface name to a FreeBSD interface name,
|
||||
* and return the associated ifnet structure
|
||||
@ -261,8 +339,11 @@ ifname_linux_to_bsd(struct thread *td, const char *lxname, char *bsdname)
|
||||
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);
|
||||
/*
|
||||
* 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);
|
||||
if ((ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ) &&
|
||||
is_lo == 0)
|
||||
@ -732,5 +813,5 @@ bool
|
||||
linux_use_real_ifname(const struct ifnet *ifp)
|
||||
{
|
||||
|
||||
return (use_real_ifnames || !IFP_IS_ETH(ifp));
|
||||
return (use_real_ifnames);
|
||||
}
|
||||
|
@ -30,6 +30,10 @@
|
||||
#ifndef _LINUX_COMMON_H_
|
||||
#define _LINUX_COMMON_H_
|
||||
|
||||
int ifname_bsd_to_linux_ifp(struct ifnet *, char *, size_t);
|
||||
int ifname_bsd_to_linux_idx(u_int, char *, size_t);
|
||||
int ifname_bsd_to_linux_name(const char *, char *, size_t);
|
||||
|
||||
struct ifnet *ifname_linux_to_bsd(struct thread *td,
|
||||
const char *lxname, char *bsdname);
|
||||
void linux_ifflags(struct ifnet *ifp, short *flags);
|
||||
|
@ -2092,39 +2092,17 @@ static int
|
||||
linux_ioctl_ifname(struct thread *td, struct l_ifreq *uifr)
|
||||
{
|
||||
struct l_ifreq ifr;
|
||||
struct ifnet *ifp;
|
||||
int error, ethno, index;
|
||||
int error, ret;
|
||||
|
||||
error = copyin(uifr, &ifr, sizeof(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();
|
||||
if (error == 0)
|
||||
error = copyout(&ifr, uifr, sizeof(ifr));
|
||||
CURVNET_RESTORE();
|
||||
|
||||
return (error);
|
||||
ret = ifname_bsd_to_linux_idx(ifr.ifr_ifindex, ifr.ifr_name,
|
||||
LINUX_IFNAMSIZ);
|
||||
if (ret > 0)
|
||||
return (copyout(&ifr, uifr, sizeof(ifr)));
|
||||
else
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2134,6 +2112,7 @@ linux_ioctl_ifname(struct thread *td, struct l_ifreq *uifr)
|
||||
static int
|
||||
linux_ifconf(struct thread *td, struct ifconf *uifc)
|
||||
{
|
||||
struct epoch_tracker et;
|
||||
#ifdef COMPAT_LINUX32
|
||||
struct l_ifconf ifc;
|
||||
#else
|
||||
@ -2143,7 +2122,7 @@ linux_ifconf(struct thread *td, struct ifconf *uifc)
|
||||
struct ifnet *ifp;
|
||||
struct ifaddr *ifa;
|
||||
struct sbuf *sb;
|
||||
int error, ethno, full = 0, valid_len, max_len;
|
||||
int error, full = 0, valid_len, max_len;
|
||||
|
||||
error = copyin(uifc, &ifc, sizeof(ifc));
|
||||
if (error != 0)
|
||||
@ -2155,7 +2134,7 @@ linux_ifconf(struct thread *td, struct ifconf *uifc)
|
||||
/* handle the 'request buffer size' case */
|
||||
if ((l_uintptr_t)ifc.ifc_buf == PTROUT(NULL)) {
|
||||
ifc.ifc_len = 0;
|
||||
IFNET_RLOCK();
|
||||
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;
|
||||
@ -2163,7 +2142,7 @@ linux_ifconf(struct thread *td, struct ifconf *uifc)
|
||||
ifc.ifc_len += sizeof(ifr);
|
||||
}
|
||||
}
|
||||
IFNET_RUNLOCK();
|
||||
NET_EPOCH_EXIT(et);
|
||||
error = copyout(&ifc, uifc, sizeof(ifc));
|
||||
CURVNET_RESTORE();
|
||||
return (error);
|
||||
@ -2175,8 +2154,6 @@ linux_ifconf(struct thread *td, struct ifconf *uifc)
|
||||
}
|
||||
|
||||
again:
|
||||
/* Keep track of eth interfaces */
|
||||
ethno = 0;
|
||||
if (ifc.ifc_len <= max_len) {
|
||||
max_len = ifc.ifc_len;
|
||||
full = 1;
|
||||
@ -2186,16 +2163,13 @@ linux_ifconf(struct thread *td, struct ifconf *uifc)
|
||||
valid_len = 0;
|
||||
|
||||
/* Return all AF_INET addresses of all interfaces */
|
||||
IFNET_RLOCK();
|
||||
NET_EPOCH_ENTER(et);
|
||||
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);
|
||||
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) {
|
||||
@ -2222,7 +2196,7 @@ linux_ifconf(struct thread *td, struct ifconf *uifc)
|
||||
valid_len = sbuf_len(sb);
|
||||
}
|
||||
}
|
||||
IFNET_RUNLOCK();
|
||||
NET_EPOCH_EXIT(et);
|
||||
|
||||
if (valid_len != max_len && !full) {
|
||||
sbuf_delete(sb);
|
||||
|
Loading…
Reference in New Issue
Block a user