diff options
author | Philipp Buehler <pb@cvs.openbsd.org> | 2004-06-25 18:24:24 +0000 |
---|---|---|
committer | Philipp Buehler <pb@cvs.openbsd.org> | 2004-06-25 18:24:24 +0000 |
commit | 1fef12e248eccc18fb9e2bc42a25274a6a608ca4 (patch) | |
tree | bd7cafab3b77f5a7f0ee17a0365cc604c676b9af | |
parent | e7a05a23ee68d06836bb6b72fdca8a3512cae3d0 (diff) |
introduce "interface groups"
by "ifconfig fxp0 group foobar" "ifconfig xl0 group foobar"
these two interfaces are in one group.
Every interface has its if-family as default group.
idea/design from henning@, based on some work/disucssion from Joris Vink.
henning@, mcbride@ ok.
-rw-r--r-- | sbin/ifconfig/ifconfig.c | 80 | ||||
-rw-r--r-- | sys/net/if.c | 128 | ||||
-rw-r--r-- | sys/net/if.h | 31 | ||||
-rw-r--r-- | sys/sys/sockio.h | 6 |
4 files changed, 240 insertions, 5 deletions
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c index 8e2f7bbef3c..41e93d35ae8 100644 --- a/sbin/ifconfig/ifconfig.c +++ b/sbin/ifconfig/ifconfig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ifconfig.c,v 1.102 2004/06/24 20:44:06 henning Exp $ */ +/* $OpenBSD: ifconfig.c,v 1.103 2004/06/25 18:24:23 pb Exp $ */ /* $NetBSD: ifconfig.c,v 1.40 1997/10/01 02:19:43 enami Exp $ */ /* @@ -77,7 +77,7 @@ static const char copyright[] = #if 0 static const char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; #else -static const char rcsid[] = "$OpenBSD: ifconfig.c,v 1.102 2004/06/24 20:44:06 henning Exp $"; +static const char rcsid[] = "$OpenBSD: ifconfig.c,v 1.103 2004/06/25 18:24:23 pb Exp $"; #endif #endif /* not lint */ @@ -152,6 +152,8 @@ int Lflag = 1; void notealias(const char *, int); void notrailers(const char *, int); +void setifgroup(const char *, int); +void unsetifgroup(const char *, int); void setifaddr(const char *, int); void setifdstaddr(const char *, int); void setifflags(const char *, int); @@ -189,6 +191,7 @@ void setvlantag(const char *, int); void setvlandev(const char *, int); void unsetvlandev(const char *, int); void vlan_status(void); +void getifgroups(void); void carp_status(void); void setcarp_advbase(const char *,int); void setcarp_advskew(const char *, int); @@ -247,6 +250,8 @@ const struct cmd { { "swabips", EN_SWABIPS, 0, setifflags }, { "-swabips", -EN_SWABIPS, 0, setifflags }, #endif /* notdef */ + { "group", NEXTARG, 0, setifgroup }, + { "-group", NEXTARG, 0, unsetifgroup }, { "netmask", NEXTARG, 0, setifnetmask }, { "metric", NEXTARG, 0, setifmetric }, { "mtu", NEXTARG, 0, setifmtu }, @@ -1041,6 +1046,38 @@ setifmtu(const char *val, int d) warn("SIOCSIFMTU"); } +void +setifgroup(const char *group_name, int dummy) +{ + struct ifgroupreq ifg; + + memset(&ifg, 0, sizeof(ifg)); + + strlcpy(ifg.if_name, name, IFNAMSIZ); + + if (strlcpy(ifg.ifg_group, group_name, IFNAMSIZ) >= IFNAMSIZ) + err(1, "setifgroup: group name too long"); + + if (ioctl(s, SIOCAIFGROUP, (caddr_t)&ifg) == -1) + err(1," SIOCAIFGROUP"); +} + +void +unsetifgroup(const char *group_name, int dummy) +{ + struct ifgroupreq ifg; + + memset(&ifg, 0, sizeof(ifg)); + + strlcpy(ifg.if_name, name, IFNAMSIZ); + + if (strlcpy(ifg.ifg_group, group_name, IFNAMSIZ) >= IFNAMSIZ) + err(1, "unsetifgroup: group name too long"); + + if (ioctl(s, SIOCDIFGROUP, (caddr_t)&ifg) == -1) + err(1, "SIOCDIFGROUP"); +} + const char * get_string(const char *val, const char *sep, u_int8_t *buf, int *lenp) { @@ -1685,6 +1722,7 @@ status(int link, struct sockaddr_dl *sdl) carp_status(); pfsync_status(); ieee80211_status(); + getifgroups(); (void) memset(&ifmr, 0, sizeof(ifmr)); (void) strlcpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); @@ -2546,6 +2584,44 @@ unsetvlandev(const char *val, int d) static const char *carp_states[] = { CARP_STATES }; void +getifgroups(void) +{ + int len; + struct ifgroupreq ifg; + struct ifgroup *ifgp; + + memset(&ifg, 0, sizeof(ifg)); + strlcpy(ifg.if_name, name, IFNAMSIZ); + + if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifg) == -1) + err(1, "SIOCGIFGROUP"); + + len = ifg.ifg_len; + ifg.ifg_groups = (struct ifgroup *)calloc(len / sizeof(struct ifgroup), + sizeof(struct ifgroup)); + if (ifg.ifg_groups == NULL) + err(1, "getifgroups"); + + if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifg) == -1) + err(1, "SIOCGIFGROUP"); + + if (len -= sizeof(struct ifgroup)) { + len += sizeof(struct ifgroup); + printf("\tgroups: "); + ifgp = ifg.ifg_groups; + if (ifgp) { + len -= sizeof(struct ifgroup); + ifgp++; + } + for (; ifgp && len >= sizeof(struct ifgroup); ifgp++) { + len -= sizeof(struct ifgroup); + printf("%s ", ifgp->if_group); + } + printf("\n"); + } +} + +void carp_status() { const char *state; diff --git a/sys/net/if.c b/sys/net/if.c index 1beb9f670e0..de1e3ced9f6 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.88 2004/05/29 17:54:45 jcs Exp $ */ +/* $OpenBSD: if.c,v 1.89 2004/06/25 18:24:23 pb Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -166,7 +166,9 @@ void if_attachsetup(ifp) struct ifnet *ifp; { + struct ifgroup *ifg; struct ifaddr *ifa; + int n; int wrapped = 0; if (ifindex2ifnet == 0) @@ -237,6 +239,19 @@ if_attachsetup(ifp) ifindex2ifnet = (struct ifnet **)q; } + /* setup the group list */ + TAILQ_INIT(&ifp->if_groups); + ifg = (struct ifgroup *)malloc(sizeof(struct ifgroup), M_TEMP, + M_NOWAIT); + if (ifg != NULL) { + for (n = 0; + ifp->if_xname[n] < '0' || ifp->if_xname[n] > '9'; + n++) + continue; + strlcpy(ifg->if_group, ifp->if_xname, n + 1); + TAILQ_INSERT_HEAD(&ifp->if_groups, ifg, group_list); + } + ifindex2ifnet[if_index] = ifp; if (ifp->if_snd.ifq_maxlen == 0) @@ -447,6 +462,7 @@ if_detach(ifp) struct ifnet *ifp; { struct ifaddr *ifa; + struct ifgroup *ifg; int i, s = splimp(); struct radix_node_head *rnh; struct domain *dp; @@ -577,6 +593,13 @@ do { \ free(ifa, M_IFADDR); } + + for (ifg = TAILQ_FIRST(&ifp->if_groups); ifg; + ifg = TAILQ_FIRST(&ifp->if_groups)) { + TAILQ_REMOVE(&ifp->if_groups, ifg, group_list); + free(ifg, M_TEMP); + } + if_free_sadl(ifp); free(ifnet_addrs[ifp->if_index], M_IFADDR); @@ -1250,6 +1273,25 @@ ifioctl(so, cmd, data, p) } break; + case SIOCAIFGROUP: + if ((error = suser(p, 0)) != 0) + return (error); + if ((error = if_addgroup((struct ifgroupreq *)data, ifp))) + return (error); + break; + + case SIOCGIFGROUP: + if ((error = if_getgroup(data, ifp))) + return (error); + break; + + case SIOCDIFGROUP: + if ((error = suser(p, 0)) != 0) + return (error); + if ((error = if_delgroup((struct ifgroupreq *)data, ifp))) + return (error); + break; + default: if (so->so_proto == 0) return (EOPNOTSUPP); @@ -1456,6 +1498,90 @@ if_detached_watchdog(struct ifnet *ifp) } /* + * Add a group to an interface + */ +int +if_addgroup(struct ifgroupreq *ifg, struct ifnet *ifp) +{ + struct ifgroup *ifgnew, *ifgp; + + TAILQ_FOREACH(ifgp, &ifp->if_groups, group_list) + if (!strcmp(ifgp->if_group, ifg->ifg_group)) + return (EEXIST); + + ifgnew = (struct ifgroup *)malloc(sizeof(struct ifgroup), M_TEMP, + M_NOWAIT); + if (ifgnew == NULL) + return (ENOMEM); + strlcpy(ifgnew->if_group, ifg->ifg_group, IFNAMSIZ); + TAILQ_INSERT_TAIL(&ifp->if_groups, ifgnew, group_list); + + return (0); +} + +/* + * Remove a group from an interface + * note: the first group is the if-family - do not remove + */ +int +if_delgroup(struct ifgroupreq *ifg, struct ifnet *ifp) +{ + struct ifgroup *ifgp; + + for (ifgp = TAILQ_FIRST(&ifp->if_groups); + ifgp != TAILQ_END(&ifp->if_groups); + ifgp = TAILQ_NEXT(ifgp, group_list)) { + if (ifgp == TAILQ_FIRST(&ifp->if_groups) && + !strcmp(ifgp->if_group, ifg->ifg_group)) + return (EPERM); + if (!strcmp(ifgp->if_group, ifg->ifg_group)) { + TAILQ_REMOVE(&ifp->if_groups, ifgp, group_list); + free(ifgp, M_TEMP); + return (0); + } + } + + return (ENOENT); +} + +/* + * Stores all groups from an interface in memory pointed + * to by data + */ +int +if_getgroup(caddr_t data, struct ifnet *ifp) +{ + int len; + int error; + struct ifgroup *ifgp, *ifgp2, ifg; + struct ifgroupreq *ifgr = (struct ifgroupreq *)data; + + if (ifgr->ifg_len == 0) { + TAILQ_FOREACH(ifgp, &ifp->if_groups, group_list) + ifgr->ifg_len += sizeof(struct ifgroup); + return (0); + } + + len = ifgr->ifg_len; + ifgp = ifgr->ifg_groups; + for (ifgp2 = TAILQ_FIRST(&ifp->if_groups); ifgp2 && + len >= sizeof(struct ifgroup); + ifgp2 = TAILQ_NEXT(ifgp2, group_list)) { + memset(&ifg, 0, sizeof(struct ifgroup)); + strlcpy(ifg.if_group, ifgp2->if_group, IFNAMSIZ); + error = copyout((caddr_t)&ifg, (caddr_t)ifgp, + sizeof(struct ifgroup)); + if (error) + return (error); + ifgp++; + len -= sizeof(struct ifgroup); + } + + return (0); +} + + +/* * Set/clear promiscuous mode on interface ifp based on the truth value * of pswitch. The calls are reference counted so that only the first * "on" request actually has an effect, as does the final "off" request. diff --git a/sys/net/if.h b/sys/net/if.h index f67484436c2..ebcf9625a51 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if.h,v 1.54 2004/06/20 00:38:21 beck Exp $ */ +/* $OpenBSD: if.h,v 1.55 2004/06/25 18:24:23 pb Exp $ */ /* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */ /* @@ -174,6 +174,7 @@ struct ifnet { /* and the entries */ void *if_softc; /* lower-level data for this if */ TAILQ_ENTRY(ifnet) if_list; /* all struct ifnets are chained */ TAILQ_HEAD(, ifaddr) if_addrlist; /* linked list of addresses per if */ + TAILQ_HEAD(, ifgroup) if_groups; /* linked list of groups per if */ struct hook_desc_head *if_addrhooks; /* address change callbacks */ char if_xname[IFNAMSIZ]; /* external name (name + unit) */ int if_pcount; /* number of promiscuous listeners */ @@ -397,6 +398,31 @@ struct if_announcemsghdr { #define IFAN_DEPARTURE 1 /* interface departure */ /* + * The groups on an interface + */ +struct ifgroup { + char if_group[IFNAMSIZ]; + TAILQ_ENTRY(ifgroup) group_list; +}; + +/* + * Used to lookup groups for an interface + */ +struct ifgroupreq { + char if_name[IFNAMSIZ]; + u_int ifg_len; + + union { + char if_group[IFNAMSIZ]; + struct ifgroup *ifg; + } ifg_ifgu; + + TAILQ_ENTRY(ifgroupreq) next_if; +#define ifg_group ifg_ifgu.if_group +#define ifg_groups ifg_ifgu.ifg +}; + +/* * Interface request structure used for socket * ioctl's. All interface ioctl's must have parameter * definitions which begin with ifr_name. The @@ -619,6 +645,9 @@ int ifconf(u_long, caddr_t); void ifinit(void); int ifioctl(struct socket *, u_long, caddr_t, struct proc *); int ifpromisc(struct ifnet *, int); +int if_addgroup(struct ifgroupreq *, struct ifnet *); +int if_delgroup(struct ifgroupreq *, struct ifnet *); +int if_getgroup(caddr_t, struct ifnet *); struct ifnet *ifunit(const char *); struct ifaddr *ifa_ifwithaddr(struct sockaddr *); diff --git a/sys/sys/sockio.h b/sys/sys/sockio.h index bc16dff5daa..7402f360bf5 100644 --- a/sys/sys/sockio.h +++ b/sys/sys/sockio.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sockio.h,v 1.25 2004/05/29 17:54:45 jcs Exp $ */ +/* $OpenBSD: sockio.h,v 1.26 2004/06/25 18:24:23 pb Exp $ */ /* $NetBSD: sockio.h,v 1.5 1995/08/23 00:40:47 thorpej Exp $ */ /*- @@ -143,6 +143,10 @@ #define SIOCIFDESTROY _IOW('i', 121, struct ifreq) /* destroy clone if */ #define SIOCIFGCLONERS _IOWR('i', 120, struct if_clonereq) /* get cloners */ +#define SIOCAIFGROUP _IOW('i', 130, struct ifgroupreq) /* add an ifgroup */ +#define SIOCGIFGROUP _IOWR('i', 131, struct ifgroupreq) /* get ifgroups */ +#define SIOCDIFGROUP _IOW('i', 132, struct ifgroupreq) /* delete ifgroup */ + #define SIOCSIFDESCR _IOW('i', 128, struct ifreq) /* set ifnet descr */ #define SIOCGIFDESCR _IOWR('i', 129, struct ifreq) /* get ifnet descr */ |