summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/net/if.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-08-21 09:39:55 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-09-21 10:29:40 +0200
commit2df56dbd60bb5d925d2ce0ddbdefdbe6107ea783 (patch)
treebd7bad558534db4a1f400bc38a2c9aa7ea4f411e /freebsd/sys/net/if.c
parentUpdate to FreeBSD head 2018-02-01 (diff)
downloadrtems-libbsd-2df56dbd60bb5d925d2ce0ddbdefdbe6107ea783.tar.bz2
Update to FreeBSD head 2018-04-01
Git mirror commit 8dfb1ccc26d1cea7e2529303003ff61f9f1784c4. Update #3472.
Diffstat (limited to 'freebsd/sys/net/if.c')
-rw-r--r--freebsd/sys/net/if.c148
1 files changed, 134 insertions, 14 deletions
diff --git a/freebsd/sys/net/if.c b/freebsd/sys/net/if.c
index 67252bd4..bbf2ddd0 100644
--- a/freebsd/sys/net/if.c
+++ b/freebsd/sys/net/if.c
@@ -59,6 +59,7 @@
#include <sys/sockio.h>
#include <sys/syslog.h>
#include <sys/sysctl.h>
+#include <sys/sysent.h>
#include <sys/taskqueue.h>
#include <sys/domain.h>
#include <sys/jail.h>
@@ -98,10 +99,59 @@
#include <security/mac/mac_framework.h>
+/*
+ * Consumers of struct ifreq such as tcpdump assume no pad between ifr_name
+ * and ifr_ifru when it is used in SIOCGIFCONF.
+ */
+_Static_assert(sizeof(((struct ifreq *)0)->ifr_name) ==
+ offsetof(struct ifreq, ifr_ifru), "gap between ifr_name and ifr_ifru");
+
#ifdef COMPAT_FREEBSD32
#include <sys/mount.h>
#include <compat/freebsd32/freebsd32.h>
+
+struct ifreq_buffer32 {
+ uint32_t length; /* (size_t) */
+ uint32_t buffer; /* (void *) */
+};
+
+/*
+ * Interface request structure used for socket
+ * ioctl's. All interface ioctl's must have parameter
+ * definitions which begin with ifr_name. The
+ * remainder may be interface specific.
+ */
+struct ifreq32 {
+ char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */
+ union {
+ struct sockaddr ifru_addr;
+ struct sockaddr ifru_dstaddr;
+ struct sockaddr ifru_broadaddr;
+ struct ifreq_buffer32 ifru_buffer;
+ short ifru_flags[2];
+ short ifru_index;
+ int ifru_jid;
+ int ifru_metric;
+ int ifru_mtu;
+ int ifru_phys;
+ int ifru_media;
+ uint32_t ifru_data;
+ int ifru_cap[2];
+ u_int ifru_fib;
+ u_char ifru_vlan_pcp;
+ } ifr_ifru;
+};
+CTASSERT(sizeof(struct ifreq) == sizeof(struct ifreq32));
+CTASSERT(__offsetof(struct ifreq, ifr_ifru) ==
+ __offsetof(struct ifreq32, ifr_ifru));
+#endif
+
+union ifreq_union {
+ struct ifreq ifr;
+#ifdef COMPAT_FREEBSD32
+ struct ifreq32 ifr32;
#endif
+};
SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers");
SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management");
@@ -487,6 +537,7 @@ if_alloc(u_char type)
for (int i = 0; i < IFCOUNTERS; i++)
ifp->if_counters[i] = counter_u64_alloc(M_WAITOK);
ifp->if_get_counter = if_get_counter_default;
+ ifp->if_pcp = IFNET_PCP_NONE;
ifnet_setbyindex(ifp->if_index, ifp);
return (ifp);
}
@@ -2306,6 +2357,75 @@ ifunit(const char *name)
return (ifp);
}
+static void *
+ifr_buffer_get_buffer(struct thread *td, void *data)
+{
+ union ifreq_union *ifrup;
+
+ ifrup = data;
+#ifdef COMPAT_FREEBSD32
+ if (SV_PROC_FLAG(td->td_proc, SV_ILP32))
+ return ((void *)(uintptr_t)
+ ifrup->ifr32.ifr_ifru.ifru_buffer.buffer);
+#endif
+ return (ifrup->ifr.ifr_ifru.ifru_buffer.buffer);
+}
+
+static void
+ifr_buffer_set_buffer_null(struct thread *td, void *data)
+{
+ union ifreq_union *ifrup;
+
+ ifrup = data;
+#ifdef COMPAT_FREEBSD32
+ if (SV_PROC_FLAG(td->td_proc, SV_ILP32))
+ ifrup->ifr32.ifr_ifru.ifru_buffer.buffer = 0;
+ else
+#endif
+ ifrup->ifr.ifr_ifru.ifru_buffer.buffer = NULL;
+}
+
+static size_t
+ifr_buffer_get_length(struct thread *td, void *data)
+{
+ union ifreq_union *ifrup;
+
+ ifrup = data;
+#ifdef COMPAT_FREEBSD32
+ if (SV_PROC_FLAG(td->td_proc, SV_ILP32))
+ return (ifrup->ifr32.ifr_ifru.ifru_buffer.length);
+#endif
+ return (ifrup->ifr.ifr_ifru.ifru_buffer.length);
+}
+
+static void
+ifr_buffer_set_length(struct thread *td, void *data, size_t len)
+{
+ union ifreq_union *ifrup;
+
+ ifrup = data;
+#ifdef COMPAT_FREEBSD32
+ if (SV_PROC_FLAG(td->td_proc, SV_ILP32))
+ ifrup->ifr32.ifr_ifru.ifru_buffer.length = len;
+ else
+#endif
+ ifrup->ifr.ifr_ifru.ifru_buffer.length = len;
+}
+
+void *
+ifr_data_get_ptr(void *ifrp)
+{
+ union ifreq_union *ifrup;
+
+ ifrup = ifrp;
+#ifdef COMPAT_FREEBSD32
+ if (SV_CURPROC_FLAG(SV_ILP32))
+ return ((void *)(uintptr_t)
+ ifrup->ifr32.ifr_ifru.ifru_data);
+#endif
+ return (ifrup->ifr.ifr_ifru.ifru_data);
+}
+
/*
* Hardware specific interface ioctls.
*/
@@ -2366,12 +2486,12 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
else {
/* space for terminating nul */
descrlen = strlen(ifp->if_description) + 1;
- if (ifr->ifr_buffer.length < descrlen)
- ifr->ifr_buffer.buffer = NULL;
+ if (ifr_buffer_get_length(td, ifr) < descrlen)
+ ifr_buffer_set_buffer_null(td, ifr);
else
error = copyout(ifp->if_description,
- ifr->ifr_buffer.buffer, descrlen);
- ifr->ifr_buffer.length = descrlen;
+ ifr_buffer_get_buffer(td, ifr), descrlen);
+ ifr_buffer_set_length(td, ifr, descrlen);
}
sx_sunlock(&ifdescr_sx);
break;
@@ -2387,15 +2507,15 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
* length parameter is supposed to count the
* terminating nul in.
*/
- if (ifr->ifr_buffer.length > ifdescr_maxlen)
+ if (ifr_buffer_get_length(td, ifr) > ifdescr_maxlen)
return (ENAMETOOLONG);
- else if (ifr->ifr_buffer.length == 0)
+ else if (ifr_buffer_get_length(td, ifr) == 0)
descrbuf = NULL;
else {
- descrbuf = malloc(ifr->ifr_buffer.length, M_IFDESCR,
- M_WAITOK | M_ZERO);
- error = copyin(ifr->ifr_buffer.buffer, descrbuf,
- ifr->ifr_buffer.length - 1);
+ descrbuf = malloc(ifr_buffer_get_length(td, ifr),
+ M_IFDESCR, M_WAITOK | M_ZERO);
+ error = copyin(ifr_buffer_get_buffer(td, ifr), descrbuf,
+ ifr_buffer_get_length(td, ifr) - 1);
if (error) {
free(descrbuf, M_IFDESCR);
break;
@@ -2487,7 +2607,8 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
error = priv_check(td, PRIV_NET_SETIFNAME);
if (error)
return (error);
- error = copyinstr(ifr->ifr_data, new_name, IFNAMSIZ, NULL);
+ error = copyinstr(ifr_data_get_ptr(ifr), new_name, IFNAMSIZ,
+ NULL);
if (error != 0)
return (error);
if (new_name[0] == '\0')
@@ -2814,8 +2935,8 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
error = priv_check(td, PRIV_NET_IFCREATE);
if (error == 0)
error = if_clone_create(ifr->ifr_name,
- sizeof(ifr->ifr_name),
- cmd == SIOCIFCREATE2 ? ifr->ifr_data : NULL);
+ sizeof(ifr->ifr_name), cmd == SIOCIFCREATE2 ?
+ ifr_data_get_ptr(ifr) : NULL);
CURVNET_RESTORE();
return (error);
case SIOCIFDESTROY:
@@ -3545,7 +3666,6 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len)
case IFT_ETHER:
case IFT_FDDI:
case IFT_XETHER:
- case IFT_ISO88025:
case IFT_L2VLAN:
case IFT_BRIDGE:
case IFT_ARCNET: