summaryrefslogtreecommitdiff
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
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.
-rw-r--r--sbin/ifconfig/ifconfig.c80
-rw-r--r--sys/net/if.c128
-rw-r--r--sys/net/if.h31
-rw-r--r--sys/sys/sockio.h6
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 */