summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorPhilipp Buehler <pb@cvs.openbsd.org>2004-06-25 18:24:24 +0000
committerPhilipp Buehler <pb@cvs.openbsd.org>2004-06-25 18:24:24 +0000
commit1fef12e248eccc18fb9e2bc42a25274a6a608ca4 (patch)
treebd7cafab3b77f5a7f0ee17a0365cc604c676b9af /sys/net
parente7a05a23ee68d06836bb6b72fdca8a3512cae3d0 (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.
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if.c128
-rw-r--r--sys/net/if.h31
2 files changed, 157 insertions, 2 deletions
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 *);