diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-08-21 09:39:55 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-21 10:29:40 +0200 |
commit | 2df56dbd60bb5d925d2ce0ddbdefdbe6107ea783 (patch) | |
tree | bd7bad558534db4a1f400bc38a2c9aa7ea4f411e /freebsd/sys/net/if.c | |
parent | Update to FreeBSD head 2018-02-01 (diff) | |
download | rtems-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.c | 148 |
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: |