From 233c85704a96468c162480f32a6e092b81b0cdaf Mon Sep 17 00:00:00 2001 From: Aaron LI Date: Sat, 16 Jun 2018 22:25:31 +0800 Subject: [PATCH] net: Implement interface group support The network interface group (aka ifgroup) functionality is currently only used by the PF (still needs patch to make PF use the ifgroup), allowing rules to use group names instead of the specific interface names, which makes firewall rules more generic and simpler. * The ifgroup data are stored at the following two places: - The global list of 'struct ifg_group': each entry is a group which has the name and members (a list of pointers to the interfaces). - The per-ifnet 'if_groups' list, which records the groups that the interface belongs to. * Introduce the 'ifgroup_lock' locakmgr(9) to protect the global list of 'struct ifg_group' and per-ifnet 'if_groups' list. The R/W locking operations are provided by the ifgroup_lockmgr() function. * Move the copyout() out of the locked loop in if_getgroups() and if_getgroupmembers() functions. * Fix several M_NOWAIT to be M_WAITOK. * Use M_IFNET instead of M_TEMP for allocated ifgroup memory. * Add SIOC[ADG]IFGROUP and SIOCGIFGMEMB ioctl's, bump __DragonFly_version. * Add invocations to group_{attach,change,detach}_event handlers. * Update eventhandler.9 man page. * Some style updates. Great thanks to sephe for his patient guidance and review. Credit to both FreeBSD and OpenBSD for the ifgroup functionality. NOTE: When delete the only group from an interface, which leaves an empty group that will be destroyed, make sure the group_change_event event is invoked *before* the group destroy (i.e., group_detach_event). Both FreeBSD and OpenBSD have the ordering problem with group detach event. Need to report the problem to them. --- share/man/man9/EVENTHANDLER.9 | 8 +- sys/net/if.c | 347 +++++++++++++++++++++++----------- sys/net/if.h | 4 +- sys/net/if_var.h | 38 ++-- sys/sys/param.h | 3 +- sys/sys/sockio.h | 5 +- 6 files changed, 272 insertions(+), 133 deletions(-) diff --git a/share/man/man9/EVENTHANDLER.9 b/share/man/man9/EVENTHANDLER.9 index 2af0f9fa6f..7516f87ad3 100644 --- a/share/man/man9/EVENTHANDLER.9 +++ b/share/man/man9/EVENTHANDLER.9 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD: src/share/man/man9/EVENTHANDLER.9,v 1.4 2005/10/11 16:05:35 keramida Exp $ .\" -.Dd June 21, 2018 +.Dd June 22, 2018 .Dt EVENTHANDLER 9 .Os .Sh NAME @@ -190,6 +190,12 @@ Callbacks invoked when the system is being woken up. .It Vt dev_clone Callbacks invoked when a new entry is created under .Pa /dev . +.It Vt group_attach_event +Callbacks invoked when a new interface group has been created. +.It Vt group_change_event +Callbacks invoked when the members of an interface group have changed. +.It Vt group_detach_event +Callbacks invoked when an interface group has been removed due to no members. .It Vt if_clone_event Callbacks invoked when a new interface cloner is attached. .It Vt ifaddr_event diff --git a/sys/net/if.c b/sys/net/if.c index b3c2596396..a97cd7f40c 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -78,15 +79,14 @@ #include #if defined(INET) || defined(INET6) -/*XXX*/ #include #include #include #ifdef INET6 #include #include -#endif -#endif +#endif /* INET6 */ +#endif /* INET || INET6 */ struct netmsg_ifaddr { struct netmsg_base base; @@ -130,6 +130,11 @@ static struct ifnet_array *ifnet_array_add(struct ifnet *, const struct ifnet_array *); static struct ifnet_array *ifnet_array_del(struct ifnet *, const struct ifnet_array *); +static struct ifg_group *if_creategroup(const char *); +static int if_destroygroup(struct ifg_group *); +static int if_delgroup_locked(struct ifnet *, const char *); +static int if_getgroups(struct ifgroupreq *, struct ifnet *); +static int if_getgroupmembers(struct ifgroupreq *); #ifdef INET6 /* @@ -168,6 +173,8 @@ MALLOC_DEFINE(M_IFNET, "ifnet", "interface structure"); int ifqmaxlen = IFQ_MAXLEN; struct ifnethead ifnet = TAILQ_HEAD_INITIALIZER(ifnet); +struct ifgrouphead ifg_head = TAILQ_HEAD_INITIALIZER(ifg_head); +static struct lock ifgroup_lock; static struct ifnet_array ifnet_array0; static struct ifnet_array *ifnet_array = &ifnet_array0; @@ -209,9 +216,7 @@ KTR_INFO(KTR_IF_START, if_start, contend_sched, 3, KTR_INFO(KTR_IF_START, if_start, chase_sched, 4, IF_START_KTR_STRING, IF_START_KTR_ARGS); #define logifstart(name, arg) KTR_LOG(if_start_ ## name, arg) -#endif - -TAILQ_HEAD(, ifg_group) ifg_head = TAILQ_HEAD_INITIALIZER(ifg_head); +#endif /* notyet */ /* * Network interface utility routines. @@ -223,6 +228,7 @@ TAILQ_HEAD(, ifg_group) ifg_head = TAILQ_HEAD_INITIALIZER(ifg_head); static void ifinit(void *dummy) { + lockinit(&ifgroup_lock, "ifgroup", 0, 0); callout_init_mp(&if_slowtimo_timer); netmsg_init(&if_slowtimo_netmsg, NULL, &netisr_adone_rport, @@ -528,6 +534,7 @@ if_attach(struct ifnet *ifp, lwkt_serialize_t serializer) TAILQ_INIT(&ifp->if_multiaddrs); TAILQ_INIT(&ifp->if_groups); getmicrotime(&ifp->if_lastchange); + if_addgroup(ifp, IFG_ALL); /* * create a Link Level name for this device @@ -919,6 +926,7 @@ void if_detach(struct ifnet *ifp) { struct ifnet_array *old_ifnet_array; + struct ifg_list *ifgl; struct netmsg_if_rtdel msg; struct domain *dp; int q; @@ -959,6 +967,11 @@ if_detach(struct ifnet *ifp) ifnet_unlock(); + ifgroup_lockmgr(LK_EXCLUSIVE); + while ((ifgl = TAILQ_FIRST(&ifp->if_groups)) != NULL) + if_delgroup_locked(ifp, ifgl->ifgl_group->ifg_group); + ifgroup_lockmgr(LK_RELEASE); + /* * Sync all netisrs so that the old ifnet array is no longer * accessed and we can free it safely later on. @@ -1056,197 +1069,280 @@ if_detach(struct ifnet *ifp) crit_exit(); } +int +ifgroup_lockmgr(u_int flags) +{ + return lockmgr(&ifgroup_lock, flags); +} + /* - * Create interface group without members + * Create an empty interface group. */ -struct ifg_group * +static struct ifg_group * if_creategroup(const char *groupname) { - struct ifg_group *ifg = NULL; + struct ifg_group *ifg; - if ((ifg = (struct ifg_group *)kmalloc(sizeof(struct ifg_group), - M_TEMP, M_NOWAIT)) == NULL) - return (NULL); + ifg = kmalloc(sizeof(*ifg), M_IFNET, M_WAITOK); + strlcpy(ifg->ifg_group, groupname, sizeof(ifg->ifg_group)); + ifg->ifg_refcnt = 0; + ifg->ifg_carp_demoted = 0; + TAILQ_INIT(&ifg->ifg_members); - strlcpy(ifg->ifg_group, groupname, sizeof(ifg->ifg_group)); - ifg->ifg_refcnt = 0; - ifg->ifg_carp_demoted = 0; - TAILQ_INIT(&ifg->ifg_members); -#if NPF > 0 - pfi_attach_ifgroup(ifg); -#endif - TAILQ_INSERT_TAIL(&ifg_head, ifg, ifg_next); + ifgroup_lockmgr(LK_EXCLUSIVE); + TAILQ_INSERT_TAIL(&ifg_head, ifg, ifg_next); + ifgroup_lockmgr(LK_RELEASE); + + EVENTHANDLER_INVOKE(group_attach_event, ifg); - return (ifg); + return (ifg); } /* - * Add a group to an interface + * Destroy an empty interface group. + */ +static int +if_destroygroup(struct ifg_group *ifg) +{ + KASSERT(ifg->ifg_refcnt == 0, + ("trying to delete a non-empty interface group")); + + ifgroup_lockmgr(LK_EXCLUSIVE); + TAILQ_REMOVE(&ifg_head, ifg, ifg_next); + ifgroup_lockmgr(LK_RELEASE); + + EVENTHANDLER_INVOKE(group_detach_event, ifg); + kfree(ifg, M_IFNET); + + return (0); +} + +/* + * Add the interface to a group. + * The target group will be created if it doesn't exist. */ int if_addgroup(struct ifnet *ifp, const char *groupname) { - struct ifg_list *ifgl; - struct ifg_group *ifg = NULL; - struct ifg_member *ifgm; + struct ifg_list *ifgl; + struct ifg_group *ifg; + struct ifg_member *ifgm; - if (groupname[0] && groupname[strlen(groupname) - 1] >= '0' && + if (groupname[0] && + groupname[strlen(groupname) - 1] >= '0' && groupname[strlen(groupname) - 1] <= '9') return (EINVAL); - TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) - if (!strcmp(ifgl->ifgl_group->ifg_group, groupname)) - return (EEXIST); - - if ((ifgl = kmalloc(sizeof(*ifgl), M_TEMP, M_NOWAIT)) == NULL) - return (ENOMEM); + ifgroup_lockmgr(LK_SHARED); - if ((ifgm = kmalloc(sizeof(*ifgm), M_TEMP, M_NOWAIT)) == NULL) { - kfree(ifgl, M_TEMP); - return (ENOMEM); + TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) { + if (strcmp(ifgl->ifgl_group->ifg_group, groupname) == 0) { + ifgroup_lockmgr(LK_RELEASE); + return (EEXIST); + } } - TAILQ_FOREACH(ifg, &ifg_head, ifg_next) - if (!strcmp(ifg->ifg_group, groupname)) + TAILQ_FOREACH(ifg, &ifg_head, ifg_next) { + if (strcmp(ifg->ifg_group, groupname) == 0) break; - - if (ifg == NULL && (ifg = if_creategroup(groupname)) == NULL) { - kfree(ifgl, M_TEMP); - kfree(ifgm, M_TEMP); - return (ENOMEM); } - ifg->ifg_refcnt++; + ifgroup_lockmgr(LK_RELEASE); + + if (ifg == NULL) + ifg = if_creategroup(groupname); + + ifgl = kmalloc(sizeof(*ifgl), M_IFNET, M_WAITOK); + ifgm = kmalloc(sizeof(*ifgm), M_IFNET, M_WAITOK); ifgl->ifgl_group = ifg; ifgm->ifgm_ifp = ifp; + ifg->ifg_refcnt++; + ifgroup_lockmgr(LK_EXCLUSIVE); TAILQ_INSERT_TAIL(&ifg->ifg_members, ifgm, ifgm_next); TAILQ_INSERT_TAIL(&ifp->if_groups, ifgl, ifgl_next); + ifgroup_lockmgr(LK_RELEASE); -#if NPF > 0 - pfi_group_change(groupname); -#endif + EVENTHANDLER_INVOKE(group_change_event, groupname); return (0); } /* - * Remove a group from an interface + * Remove the interface from a group. + * The group will be destroyed if it becomes empty. + * + * The 'ifgroup_lock' must be hold exclusively when calling this. */ -int -if_delgroup(struct ifnet *ifp, const char *groupname) +static int +if_delgroup_locked(struct ifnet *ifp, const char *groupname) { - struct ifg_list *ifgl; - struct ifg_member *ifgm; + struct ifg_list *ifgl; + struct ifg_member *ifgm; - TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) - if (!strcmp(ifgl->ifgl_group->ifg_group, groupname)) + KKASSERT(lockstatus(&ifgroup_lock, curthread) == LK_EXCLUSIVE); + + TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) { + if (strcmp(ifgl->ifgl_group->ifg_group, groupname) == 0) break; + } if (ifgl == NULL) return (ENOENT); TAILQ_REMOVE(&ifp->if_groups, ifgl, ifgl_next); - TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next) + TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next) { if (ifgm->ifgm_ifp == ifp) break; + } if (ifgm != NULL) { TAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifgm_next); - kfree(ifgm, M_TEMP); - } - if (--ifgl->ifgl_group->ifg_refcnt == 0) { - TAILQ_REMOVE(&ifg_head, ifgl->ifgl_group, ifg_next); -#if NPF > 0 - pfi_detach_ifgroup(ifgl->ifgl_group); -#endif - kfree(ifgl->ifgl_group, M_TEMP); + ifgroup_lockmgr(LK_RELEASE); + EVENTHANDLER_INVOKE(group_change_event, groupname); + ifgroup_lockmgr(LK_EXCLUSIVE); + + kfree(ifgm, M_IFNET); + ifgl->ifgl_group->ifg_refcnt--; } - kfree(ifgl, M_TEMP); + if (ifgl->ifgl_group->ifg_refcnt == 0) { + ifgroup_lockmgr(LK_RELEASE); + if_destroygroup(ifgl->ifgl_group); + ifgroup_lockmgr(LK_EXCLUSIVE); + } -#if NPF > 0 - pfi_group_change(groupname); -#endif + kfree(ifgl, M_IFNET); return (0); } +int +if_delgroup(struct ifnet *ifp, const char *groupname) +{ + int error; + + ifgroup_lockmgr(LK_EXCLUSIVE); + error = if_delgroup_locked(ifp, groupname); + ifgroup_lockmgr(LK_RELEASE); + + return (error); +} + /* - * Stores all groups from an interface in memory pointed - * to by data + * Store all the groups that the interface belongs to in memory + * pointed to by data. */ -int -if_getgroup(caddr_t data, struct ifnet *ifp) +static int +if_getgroups(struct ifgroupreq *ifgr, struct ifnet *ifp) { - int len, error; - struct ifg_list *ifgl; - struct ifg_req ifgrq, *ifgp; - struct ifgroupreq *ifgr = (struct ifgroupreq *)data; + struct ifg_list *ifgl; + struct ifg_req *ifgrq, *p; + int len, error; + + len = 0; + ifgroup_lockmgr(LK_SHARED); + TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) + len += sizeof(struct ifg_req); + ifgroup_lockmgr(LK_RELEASE); if (ifgr->ifgr_len == 0) { - TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) - ifgr->ifgr_len += sizeof(struct ifg_req); + /* + * Caller is asking how much memory should be allocated in + * the next request in order to hold all the groups. + */ + ifgr->ifgr_len = len; return (0); + } else if (ifgr->ifgr_len != len) { + return (EINVAL); } - len = ifgr->ifgr_len; - ifgp = ifgr->ifgr_groups; + ifgrq = kmalloc(len, M_TEMP, M_INTWAIT | M_NULLOK | M_ZERO); + if (ifgrq == NULL) + return (ENOMEM); + + ifgroup_lockmgr(LK_SHARED); + p = ifgrq; TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) { - if (len < sizeof(ifgrq)) + if (len < sizeof(struct ifg_req)) { + ifgroup_lockmgr(LK_RELEASE); return (EINVAL); - bzero(&ifgrq, sizeof ifgrq); - strlcpy(ifgrq.ifgrq_group, ifgl->ifgl_group->ifg_group, - sizeof(ifgrq.ifgrq_group)); - if ((error = copyout((caddr_t)&ifgrq, (caddr_t)ifgp, - sizeof(struct ifg_req)))) - return (error); - len -= sizeof(ifgrq); - ifgp++; + } + + strlcpy(p->ifgrq_group, ifgl->ifgl_group->ifg_group, + sizeof(ifgrq->ifgrq_group)); + len -= sizeof(struct ifg_req); + p++; } + ifgroup_lockmgr(LK_RELEASE); + + error = copyout(ifgrq, ifgr->ifgr_groups, ifgr->ifgr_len); + kfree(ifgrq, M_TEMP); + if (error) + return (error); return (0); } /* - * Stores all members of a group in memory pointed to by data + * Store all the members of a group in memory pointed to by data. */ -int -if_getgroupmembers(caddr_t data) +static int +if_getgroupmembers(struct ifgroupreq *ifgr) { - struct ifgroupreq *ifgr = (struct ifgroupreq *)data; - struct ifg_group *ifg; - struct ifg_member *ifgm; - struct ifg_req ifgrq, *ifgp; - int len, error; + struct ifg_group *ifg; + struct ifg_member *ifgm; + struct ifg_req *ifgrq, *p; + int len, error; + + ifgroup_lockmgr(LK_SHARED); - TAILQ_FOREACH(ifg, &ifg_head, ifg_next) - if (!strcmp(ifg->ifg_group, ifgr->ifgr_name)) + TAILQ_FOREACH(ifg, &ifg_head, ifg_next) { + if (strcmp(ifg->ifg_group, ifgr->ifgr_name) == 0) break; - if (ifg == NULL) + } + if (ifg == NULL) { + ifgroup_lockmgr(LK_RELEASE); return (ENOENT); + } + + len = 0; + TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) + len += sizeof(struct ifg_req); + + ifgroup_lockmgr(LK_RELEASE); if (ifgr->ifgr_len == 0) { - TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) - ifgr->ifgr_len += sizeof(ifgrq); + ifgr->ifgr_len = len; return (0); + } else if (ifgr->ifgr_len != len) { + return (EINVAL); } - len = ifgr->ifgr_len; - ifgp = ifgr->ifgr_groups; + ifgrq = kmalloc(len, M_TEMP, M_INTWAIT | M_NULLOK | M_ZERO); + if (ifgrq == NULL) + return (ENOMEM); + + ifgroup_lockmgr(LK_SHARED); + p = ifgrq; TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) { - if (len < sizeof(ifgrq)) + if (len < sizeof(struct ifg_req)) { + ifgroup_lockmgr(LK_RELEASE); return (EINVAL); - bzero(&ifgrq, sizeof ifgrq); - strlcpy(ifgrq.ifgrq_member, ifgm->ifgm_ifp->if_xname, - sizeof(ifgrq.ifgrq_member)); - if ((error = copyout((caddr_t)&ifgrq, (caddr_t)ifgp, - sizeof(struct ifg_req)))) - return (error); - len -= sizeof(ifgrq); - ifgp++; + } + + strlcpy(p->ifgrq_member, ifgm->ifgm_ifp->if_xname, + sizeof(p->ifgrq_member)); + len -= sizeof(struct ifg_req); + p++; } + ifgroup_lockmgr(LK_RELEASE); + + error = copyout(ifgrq, ifgr->ifgr_groups, ifgr->ifgr_len); + kfree(ifgrq, M_TEMP); + if (error) + return (error); return (0); } @@ -1815,6 +1911,7 @@ int ifioctl(struct socket *so, u_long cmd, caddr_t data, struct ucred *cred) { struct ifnet *ifp; + struct ifgroupreq *ifgr; struct ifreq *ifr; struct ifstat *ifs; int error, do_ifup = 0; @@ -1840,13 +1937,15 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct ucred *cred) if ((error = priv_check_cred(cred, PRIV_ROOT, 0)) != 0) return (error); return (if_clone_create(ifr->ifr_name, sizeof(ifr->ifr_name), - cmd == SIOCIFCREATE2 ? ifr->ifr_data : NULL)); + cmd == SIOCIFCREATE2 ? ifr->ifr_data : NULL)); case SIOCIFDESTROY: if ((error = priv_check_cred(cred, PRIV_ROOT, 0)) != 0) return (error); return (if_clone_destroy(ifr->ifr_name)); case SIOCIFGCLONERS: return (if_clone_list((struct if_clonereq *)data)); + case SIOCGIFGMEMB: + return (if_getgroupmembers((struct ifgroupreq *)data)); default: break; } @@ -2114,7 +2213,7 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct ucred *cred) case SIOCSIFPHYADDR_IN6: #endif case SIOCSLIFPHYADDR: - case SIOCSIFMEDIA: + case SIOCSIFMEDIA: case SIOCSIFGENERIC: error = priv_check_cred(cred, PRIV_ROOT, 0); if (error) @@ -2157,6 +2256,28 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct ucred *cred) EVENTHANDLER_INVOKE(iflladdr_event, ifp); break; + case SIOCAIFGROUP: + ifgr = (struct ifgroupreq *)ifr; + if ((error = priv_check_cred(cred, PRIV_NET_ADDIFGROUP, 0))) + return (error); + if ((error = if_addgroup(ifp, ifgr->ifgr_group))) + return (error); + break; + + case SIOCDIFGROUP: + ifgr = (struct ifgroupreq *)ifr; + if ((error = priv_check_cred(cred, PRIV_NET_DELIFGROUP, 0))) + return (error); + if ((error = if_delgroup(ifp, ifgr->ifgr_group))) + return (error); + break; + + case SIOCGIFGROUP: + ifgr = (struct ifgroupreq *)ifr; + if ((error = if_getgroups(ifgr, ifp))) + return (error); + break; + default: oif_flags = ifp->if_flags; if (so->so_proto == 0) { diff --git a/sys/net/if.h b/sys/net/if.h index 9cf4f12dab..a5fd574809 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -325,8 +325,8 @@ struct ifconf { struct ifg_req { union { - char ifgrqu_group[IFNAMSIZ]; - char ifgrqu_member[IFNAMSIZ]; + char ifgrqu_group[IFNAMSIZ]; + char ifgrqu_member[IFNAMSIZ]; } ifgrq_ifgrqu; #define ifgrq_group ifgrq_ifgrqu.ifgrqu_group #define ifgrq_member ifgrq_ifgrqu.ifgrqu_member diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 2edcd6a52a..70883c5386 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -105,9 +105,14 @@ struct ifdata_pcpu; #define IF_DUNIT_NONE -1 -TAILQ_HEAD(ifnethead, ifnet); /* we use TAILQs so that the order of */ -TAILQ_HEAD(ifaddrhead, ifaddr_container); /* instantiation is preserved in the list */ +/* + * we use TAILQs so that the order of instantiation is preserved in + * the list. + */ +TAILQ_HEAD(ifnethead, ifnet); +TAILQ_HEAD(ifaddrhead, ifaddr_container); TAILQ_HEAD(ifmultihead, ifmultiaddr); +TAILQ_HEAD(ifgrouphead, ifg_group); /* * Structure defining a mbuf queue. @@ -330,7 +335,12 @@ struct ifnet { struct if_data if_data; /* NOTE: stats are in if_data_pcpu */ struct ifmultihead if_multiaddrs; /* multicast addresses configured */ int if_amcount; /* number of all-multicast requests */ -/* procedure handles */ + TAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if; + * protected by 'ifgroup_lock' */ + + /* + * procedure handlers + */ int (*if_output) /* output routine (enqueue) */ (struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); @@ -348,7 +358,6 @@ struct ifnet { int (*if_resolvemulti) /* validate/resolve multicast */ (struct ifnet *, struct sockaddr **, struct sockaddr *); void *if_unused5; - TAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if */ int (*if_mapsubq) /* cpuid to if_snd subqueue map */ (struct ifaltq *, int); int if_unused2; @@ -723,12 +732,12 @@ struct ifnet_array { * interface groups */ struct ifg_group { - char ifg_group[IFNAMSIZ]; - u_int ifg_refcnt; - void *ifg_pf_kif; - int ifg_carp_demoted; - TAILQ_HEAD(, ifg_member) ifg_members; - TAILQ_ENTRY(ifg_group) ifg_next; + char ifg_group[IFNAMSIZ]; + u_int ifg_refcnt; + void *ifg_pf_kif; + int ifg_carp_demoted; + TAILQ_HEAD(, ifg_member) ifg_members; + TAILQ_ENTRY(ifg_group) ifg_next; }; struct ifg_member { @@ -889,6 +898,7 @@ int ifnet_array_isempty(void); extern int ifqmaxlen; extern struct ifnet *loif; +extern struct ifgrouphead ifg_head; struct ip; struct tcphdr; @@ -935,11 +945,9 @@ void if_up(struct ifnet *); int ifioctl(struct socket *, u_long, caddr_t, struct ucred *); int ifpromisc(struct ifnet *, int); -struct ifg_group *if_creategroup(const char *); -int if_addgroup(struct ifnet *, const char *); -int if_delgroup(struct ifnet *, const char *); -int if_getgroup(caddr_t, struct ifnet *); -int if_getgroupmembers(caddr_t); +int ifgroup_lockmgr(u_int flags); +int if_addgroup(struct ifnet *, const char *); +int if_delgroup(struct ifnet *, const char *); struct ifaddr *ifa_ifwithaddr(struct sockaddr *); struct ifaddr *ifa_ifwithdstaddr(struct sockaddr *); diff --git a/sys/sys/param.h b/sys/sys/param.h index 8d89e1df9d..60d94f29ca 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -186,9 +186,10 @@ * 500313 - remove vmnet support from tap(4) (VMIO_* ioctls) * 500314 - add TAPGIFNAME to tap(4) * 500315 - add TUNGIFNAME to tun(4) + * 500316 - add SIOC[ADG]IFGROUP, SIOCGIFGMEMB ioctl */ #undef __DragonFly_version -#define __DragonFly_version 500315 /* propagated to newvers */ +#define __DragonFly_version 500316 /* propagated to newvers */ #include diff --git a/sys/sys/sockio.h b/sys/sys/sockio.h index ddb31086ad..01a766fa3e 100644 --- a/sys/sys/sockio.h +++ b/sys/sys/sockio.h @@ -75,7 +75,7 @@ /* 36 SIOCGIFCONF */ /* 37 SIOCGIFNETMASK */ #define SIOCGIFDATA _IOWR('i', 38, struct ifreq) /* get if_data */ -#define SIOCSIFNAME _IOW('i', 40, struct ifreq) /* set IF name */ +#define SIOCSIFNAME _IOW('i', 40, struct ifreq) /* set IF name */ #define SIOCADDMULTI _IOW('i', 49, struct ifreq) /* add m'cast addr */ #define SIOCDELMULTI _IOW('i', 50, struct ifreq) /* del m'cast addr */ @@ -119,6 +119,9 @@ #define SIOCSIFTSOLEN _IOW('i', 127, struct ifreq) /* set max TSO len */ #define SIOCGIFTSOLEN _IOWR('i', 128, struct ifreq) /* get max TSO len */ +#define SIOCAIFGROUP _IOW('i', 135, struct ifgroupreq) /* add an ifgroup */ +#define SIOCGIFGROUP _IOWR('i', 136, struct ifgroupreq) /* get ifgroups */ +#define SIOCDIFGROUP _IOW('i', 137, struct ifgroupreq) /* delete ifgroup */ #define SIOCGIFGMEMB _IOWR('i', 138, struct ifgroupreq) /* get members */ #endif /* !_SYS_SOCKIO_H_ */ -- 2.41.0