linsysfs(4): Refactor to avoid referencing an unstable interfaces
Enter the net epoch when traversing a list of interfaces. For that split the ifname_linux_to_bsd() function on two counterparts, where the ifname_linux_to_ifp() intended to use in epoch, while the ifname_linux_to_bsd() intended to be a self-contained. Until the linux_ioctl_coket() function is refactored, the ifname_linux_to_bsd() temporarily returns interface outside of the net epoch. Reviewed by: melifaro Differential Revision: https://reviews.freebsd.org/D38790
This commit is contained in:
parent
130383f2f1
commit
5d5b633dde
@ -72,18 +72,23 @@ atoi(const char *str)
|
||||
static int
|
||||
linsysfs_ifnet_addr(PFS_FILL_ARGS)
|
||||
{
|
||||
struct epoch_tracker et;
|
||||
struct l_sockaddr lsa;
|
||||
struct ifnet *ifp;
|
||||
int error;
|
||||
|
||||
ifp = ifname_linux_to_bsd(td, pn->pn_parent->pn_name, NULL);
|
||||
if (ifp == NULL)
|
||||
return (ENOENT);
|
||||
if (linux_ifhwaddr(ifp, &lsa) != 0)
|
||||
return (ENOENT);
|
||||
sbuf_printf(sb, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
|
||||
lsa.sa_data[0], lsa.sa_data[1], lsa.sa_data[2],
|
||||
lsa.sa_data[3], lsa.sa_data[4], lsa.sa_data[5]);
|
||||
return (0);
|
||||
CURVNET_SET(TD_TO_VNET(td));
|
||||
NET_EPOCH_ENTER(et);
|
||||
ifp = ifname_linux_to_ifp(td, pn->pn_parent->pn_name);
|
||||
if (ifp != NULL && (error = linux_ifhwaddr(ifp, &lsa)) == 0)
|
||||
error = sbuf_printf(sb, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
|
||||
lsa.sa_data[0], lsa.sa_data[1], lsa.sa_data[2],
|
||||
lsa.sa_data[3], lsa.sa_data[4], lsa.sa_data[5]);
|
||||
else
|
||||
error = ENOENT;
|
||||
NET_EPOCH_EXIT(et);
|
||||
CURVNET_RESTORE();
|
||||
return (error == -1 ? ERANGE : error);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -97,37 +102,58 @@ linsysfs_ifnet_addrlen(PFS_FILL_ARGS)
|
||||
static int
|
||||
linsysfs_ifnet_flags(PFS_FILL_ARGS)
|
||||
{
|
||||
struct epoch_tracker et;
|
||||
struct ifnet *ifp;
|
||||
int error;
|
||||
|
||||
ifp = ifname_linux_to_bsd(td, pn->pn_parent->pn_name, NULL);
|
||||
if (ifp == NULL)
|
||||
return (ENOENT);
|
||||
sbuf_printf(sb, "0x%x\n", linux_ifflags(ifp));
|
||||
return (0);
|
||||
CURVNET_SET(TD_TO_VNET(td));
|
||||
NET_EPOCH_ENTER(et);
|
||||
ifp = ifname_linux_to_ifp(td, pn->pn_parent->pn_name);
|
||||
if (ifp != NULL)
|
||||
error = sbuf_printf(sb, "0x%x\n", linux_ifflags(ifp));
|
||||
else
|
||||
error = ENOENT;
|
||||
NET_EPOCH_EXIT(et);
|
||||
CURVNET_RESTORE();
|
||||
return (error == -1 ? ERANGE : error);
|
||||
}
|
||||
|
||||
static int
|
||||
linsysfs_ifnet_ifindex(PFS_FILL_ARGS)
|
||||
{
|
||||
struct epoch_tracker et;
|
||||
struct ifnet *ifp;
|
||||
int error;
|
||||
|
||||
ifp = ifname_linux_to_bsd(td, pn->pn_parent->pn_name, NULL);
|
||||
if (ifp == NULL)
|
||||
return (ENOENT);
|
||||
sbuf_printf(sb, "%u\n", if_getindex(ifp));
|
||||
return (0);
|
||||
CURVNET_SET(TD_TO_VNET(td));
|
||||
NET_EPOCH_ENTER(et);
|
||||
ifp = ifname_linux_to_ifp(td, pn->pn_parent->pn_name);
|
||||
if (ifp != NULL)
|
||||
error = sbuf_printf(sb, "%u\n", if_getindex(ifp));
|
||||
else
|
||||
error = ENOENT;
|
||||
NET_EPOCH_EXIT(et);
|
||||
CURVNET_RESTORE();
|
||||
return (error == -1 ? ERANGE : error);
|
||||
}
|
||||
|
||||
static int
|
||||
linsysfs_ifnet_mtu(PFS_FILL_ARGS)
|
||||
{
|
||||
struct epoch_tracker et;
|
||||
struct ifnet *ifp;
|
||||
int error;
|
||||
|
||||
ifp = ifname_linux_to_bsd(td, pn->pn_parent->pn_name, NULL);
|
||||
if (ifp == NULL)
|
||||
return (ENOENT);
|
||||
sbuf_printf(sb, "%u\n", if_getmtu(ifp));
|
||||
return (0);
|
||||
CURVNET_SET(TD_TO_VNET(td));
|
||||
NET_EPOCH_ENTER(et);
|
||||
ifp = ifname_linux_to_ifp(td, pn->pn_parent->pn_name);
|
||||
if (ifp != NULL)
|
||||
error = sbuf_printf(sb, "%u\n", if_getmtu(ifp));
|
||||
else
|
||||
error = ENOENT;
|
||||
NET_EPOCH_EXIT(et);
|
||||
CURVNET_RESTORE();
|
||||
return (error == -1 ? ERANGE : error);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -142,16 +168,21 @@ linsysfs_ifnet_tx_queue_len(PFS_FILL_ARGS)
|
||||
static int
|
||||
linsysfs_ifnet_type(PFS_FILL_ARGS)
|
||||
{
|
||||
struct epoch_tracker et;
|
||||
struct l_sockaddr lsa;
|
||||
struct ifnet *ifp;
|
||||
int error;
|
||||
|
||||
ifp = ifname_linux_to_bsd(td, pn->pn_parent->pn_name, NULL);
|
||||
if (ifp == NULL)
|
||||
return (ENOENT);
|
||||
if (linux_ifhwaddr(ifp, &lsa) != 0)
|
||||
return (ENOENT);
|
||||
sbuf_printf(sb, "%d\n", lsa.sa_family);
|
||||
return (0);
|
||||
CURVNET_SET(TD_TO_VNET(td));
|
||||
NET_EPOCH_ENTER(et);
|
||||
ifp = ifname_linux_to_ifp(td, pn->pn_parent->pn_name);
|
||||
if (ifp != NULL && (error = linux_ifhwaddr(ifp, &lsa)) == 0)
|
||||
error = sbuf_printf(sb, "%d\n", lsa.sa_family);
|
||||
else
|
||||
error = ENOENT;
|
||||
NET_EPOCH_EXIT(et);
|
||||
CURVNET_RESTORE();
|
||||
return (error == -1 ? ERANGE : error);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -342,7 +342,7 @@ 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 {
|
||||
struct ifname_linux_to_ifp_cb_s {
|
||||
bool is_lo;
|
||||
bool is_eth;
|
||||
int ethno;
|
||||
@ -352,9 +352,9 @@ struct ifname_linux_to_bsd_cb_s {
|
||||
};
|
||||
|
||||
static int
|
||||
ifname_linux_to_bsd_cb(if_t ifp, void *arg)
|
||||
ifname_linux_to_ifp_cb(if_t ifp, void *arg)
|
||||
{
|
||||
struct ifname_linux_to_bsd_cb_s *cbs = arg;
|
||||
struct ifname_linux_to_ifp_cb_s *cbs = arg;
|
||||
|
||||
NET_EPOCH_ASSERT();
|
||||
|
||||
@ -379,17 +379,18 @@ ifname_linux_to_bsd_cb(if_t ifp, void *arg)
|
||||
}
|
||||
|
||||
struct ifnet *
|
||||
ifname_linux_to_bsd(struct thread *td, const char *lxname, char *bsdname)
|
||||
ifname_linux_to_ifp(struct thread *td, const char *lxname)
|
||||
{
|
||||
struct ifname_linux_to_bsd_cb_s arg = {
|
||||
struct ifname_linux_to_ifp_cb_s arg = {
|
||||
.ethno = 0,
|
||||
.lxname = lxname,
|
||||
.ifp = NULL,
|
||||
};
|
||||
struct epoch_tracker et;
|
||||
int len, ret;
|
||||
int len;
|
||||
char *ep;
|
||||
|
||||
NET_EPOCH_ASSERT();
|
||||
|
||||
for (len = 0; len < LINUX_IFNAMSIZ; ++len)
|
||||
if (!isalpha(lxname[len]) || lxname[len] == '\0')
|
||||
break;
|
||||
@ -406,14 +407,24 @@ ifname_linux_to_bsd(struct thread *td, const char *lxname, char *bsdname)
|
||||
return (NULL);
|
||||
arg.is_eth = (len == 3 && strncmp(lxname, "eth", len) == 0);
|
||||
|
||||
if_foreach(ifname_linux_to_ifp_cb, &arg);
|
||||
return (arg.ifp);
|
||||
}
|
||||
|
||||
struct ifnet *
|
||||
ifname_linux_to_bsd(struct thread *td, const char *lxname, char *bsdname)
|
||||
{
|
||||
struct epoch_tracker et;
|
||||
struct ifnet *ifp;
|
||||
|
||||
CURVNET_SET(TD_TO_VNET(td));
|
||||
NET_EPOCH_ENTER(et);
|
||||
ret = if_foreach(ifname_linux_to_bsd_cb, &arg);
|
||||
ifp = ifname_linux_to_ifp(td, lxname);
|
||||
if (ifp != NULL && bsdname != NULL)
|
||||
strlcpy(bsdname, if_name(ifp), IFNAMSIZ);
|
||||
NET_EPOCH_EXIT(et);
|
||||
CURVNET_RESTORE();
|
||||
if (ret > 0 && arg.ifp != NULL && bsdname != NULL)
|
||||
strlcpy(bsdname, if_name(arg.ifp), IFNAMSIZ);
|
||||
return (arg.ifp);
|
||||
return (ifp);
|
||||
}
|
||||
|
||||
unsigned short
|
||||
|
@ -33,6 +33,7 @@
|
||||
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_ifp(struct thread *, const char *);
|
||||
|
||||
struct ifnet *ifname_linux_to_bsd(struct thread *td,
|
||||
const char *lxname, char *bsdname);
|
||||
|
Loading…
Reference in New Issue
Block a user