[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

interface groups



Hi,

this adds "interface groups".

Every interface will get an implicit group entry to
its if-family, e.g. every vlan(4) will be member of the
group 'vlan'.

Other groups can be set with 'ifconfig fxp0 group foobar'

Right now, nothing makes use of those groups - but this changes
in the near future. You all can think of possible uses for this.

Basic idea/design from henning@; based on work from joris vink.


Index: sys/sys/sockio.h
===================================================================
RCS file: /cvs/src/sys/sys/sockio.h,v
retrieving revision 1.25
diff -u -r1.25 sockio.h
--- sys/sys/sockio.h	29 May 2004 17:54:45 -0000	1.25
+++ sys/sys/sockio.h	22 Jun 2004 16:00:05 -0000
@@ -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 */
 
Index: sys/net/if.h
===================================================================
RCS file: /cvs/src/sys/net/if.h,v
retrieving revision 1.54
diff -u -r1.54 if.h
--- sys/net/if.h	20 Jun 2004 00:38:21 -0000	1.54
+++ sys/net/if.h	22 Jun 2004 16:00:06 -0000
@@ -174,6 +174,7 @@
 	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 @@
 #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 @@
 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 *);
Index: sys/net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.88
diff -u -r1.88 if.c
--- sys/net/if.c	29 May 2004 17:54:45 -0000	1.88
+++ sys/net/if.c	22 Jun 2004 16:00:07 -0000
@@ -166,7 +166,9 @@
 if_attachsetup(ifp)
 	struct ifnet *ifp;
 {
+	struct ifgroup *ifg;
 	struct ifaddr *ifa;
+	int n;
 	int wrapped = 0;
 
 	if (ifindex2ifnet == 0)
@@ -237,6 +239,19 @@
 		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 @@
 	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 @@
 
 		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 @@
 		}
 		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);
@@ -1455,6 +1497,89 @@
 	/* nothing */
 }
 
+/*
+ * 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;
+
+	TAILQ_FOREACH(ifgp, &ifp->if_groups, 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
Index: sbin/ifconfig/ifconfig.c
===================================================================
RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v
retrieving revision 1.100
diff -u -r1.100 ifconfig.c
--- sbin/ifconfig/ifconfig.c	29 May 2004 17:54:46 -0000	1.100
+++ sbin/ifconfig/ifconfig.c	22 Jun 2004 16:00:10 -0000
@@ -159,6 +159,8 @@
 
 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);
@@ -198,6 +200,7 @@
 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);
@@ -257,6 +260,8 @@
 	{ "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 },
@@ -1060,6 +1065,38 @@
 		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) < 0)
+		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) < 0)
+		err(1, "SIOCDIFGROUP");
+}
+
 const char *
 get_string(const char *val, const char *sep, u_int8_t *buf, int *lenp)
 {
@@ -1704,6 +1741,7 @@
 	carp_status();
 	pfsync_status();
 	ieee80211_status();
+	getifgroups();
 
 	(void) memset(&ifmr, 0, sizeof(ifmr));
 	(void) strlcpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
@@ -2669,6 +2707,39 @@
 
 
 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) < 0)
+		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) < 0)
+		err(1, "SIOCGIFGROUP");
+	
+	if (len -= sizeof(struct ifgroup)) {
+		len += sizeof(struct ifgroup);
+		printf("\tgroups: ");
+		for (ifgp = ifg.ifg_groups; ifgp && len != 0; ifgp++) {
+			len -= sizeof(struct ifgroup);
+			printf("%s ", ifgp->if_group);
+		}
+		printf("\n");
+	}
+}
 
 void
 carp_status()