Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Apr 2006 05:20:36 +0200
From:      Max Laier <max@love2party.net>
To:        freebsd-net@freebsd.org
Cc:        andre@freebsd.org
Subject:   Re: Interface groups (from OpenBSD)
Message-ID:  <200604120520.42362.max@love2party.net>
In-Reply-To: <200603281131.28240.max@love2party.net>
References:  <200603281131.28240.max@love2party.net>

next in thread | previous in thread | raw e-mail | index | archive | help
--nextPart1349231.b1GtDd56l5
Content-Type: multipart/mixed;
  boundary="Boundary-01=_FIHPE+/4nKkInpx"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

--Boundary-01=_FIHPE+/4nKkInpx
Content-Type: text/plain;
  charset="iso-8859-6"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

On Tuesday 28 March 2006 11:31, Max Laier wrote:
> Hi,
>
> while porting OpenBSD 3.9 (soon to be released) pf I stumbled on interface
> groups.  This is a mechanism to group arbitrary interfaces into logical
> groups.  It is just naming (not functional change), but it helps to convey
> semantic information (e.g. group "LAN", "DMZ" ...) about your interface to
> supporting applications.  This way you can write a policies for interface
> group "LAN" and have it applied to all the VLAN interfaces that come and
> go. Administration is done via ifconfig.  We currently have "ifconfig nam=
e"
> which does part of the job.
>
> My question: Does that sound like something interesting for us and should=
 I
> go for importing it into FreeBSD proper, or is it not at all interesting
> and we don't want it (in which case I'd hack something up for pf).
>
> Technical reasoning:  A proper import would add an additional TAILQ link
> into struct ifnet (which is a great deal of ABI change and causes the usu=
al
> headaches).  The hack would use a single void *, but we'd have to pay for
> the additional indirection.  Also yet another config tool would be requir=
ed
> to administer the interface <-> group binding.

Okay,  here is a first version for discussion and review.  It seems fully=20
functional, but test with care.  As we allow interface names that do not en=
d=20
with a digit (e.g. stf(4) and renamed interfaces) I can't use this to=20
discriminate interfaces and groups.  So, in order to show interfaces in a=20
group I had to add a "-g" switch to ifconfig.  Printing of group membership=
s=20
is under verbose for now, but that's subject to discussion.

I'm not sure if the "egress" group makes sense for us, yet.  Andre, any pla=
ns=20
there wrt to routing?  For now it's just uncommented.

Comments and reviews appreciated.  Thanks.

=2D-=20
/"\  Best regards,                      | mlaier@freebsd.org
\ /  Max Laier                          | ICQ #67774661
 X   http://pf4freebsd.love2party.net/  | mlaier@EFnet
/ \  ASCII Ribbon Campaign              | Against HTML Mail and News

--Boundary-01=_FIHPE+/4nKkInpx
Content-Type: text/x-diff;
  charset="iso-8859-6";
  name="group.diff"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="group.diff"

Index: sbin/ifconfig/Makefile
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /usr/store/mlaier/fcvs/src/sbin/ifconfig/Makefile,v
retrieving revision 1.30
diff -u -r1.30 Makefile
=2D-- sbin/ifconfig/Makefile	20 Mar 2006 14:24:57 -0000	1.30
+++ sbin/ifconfig/Makefile	12 Apr 2006 02:46:29 -0000
@@ -26,6 +26,7 @@
 SRCS+=3D	ifieee80211.c		# SIOC[GS]IEEE80211 support
=20
 SRCS+=3D	ifcarp.c		# SIOC[GS]VH support
+SRCS+=3D	ifgroup.c		# ...
 SRCS+=3D	ifpfsync.c		# pfsync(4) support
=20
 SRCS+=3D	ifbridge.c		# bridge support
Index: sbin/ifconfig/ifconfig.8
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /usr/store/mlaier/fcvs/src/sbin/ifconfig/ifconfig.8,v
retrieving revision 1.116
diff -u -r1.116 ifconfig.8
=2D-- sbin/ifconfig/ifconfig.8	8 Apr 2006 21:38:09 -0000	1.116
+++ sbin/ifconfig/ifconfig.8	12 Apr 2006 02:39:33 -0000
@@ -28,7 +28,7 @@
 .\"     From: @(#)ifconfig.8	8.3 (Berkeley) 1/5/94
 .\" $FreeBSD: src/sbin/ifconfig/ifconfig.8,v 1.116 2006/04/08 21:38:09 sco=
ttl Exp $
 .\"
=2D.Dd February 27, 2006
+.Dd April 12, 2006
 .Dt IFCONFIG 8
 .Os
 .Sh NAME
@@ -71,6 +71,8 @@
 .Op Fl u
 .Op Fl v
 .Op Fl C
+.Nm
+.Op Fl g Ar groupname
 .Sh DESCRIPTION
 The
 .Nm
@@ -178,6 +180,8 @@
 .Dq name unit ,
 for example,
 .Dq Li ed0 .
+.It Ar groupname
+List the interfaces in the given group.
 .El
 .Pp
 The following parameters may be set with
@@ -262,6 +266,22 @@
 transmit messages through that interface.
 If possible, the interface will be reset to disable reception as well.
 This action does not automatically disable routes using the interface.
+.It Cm group Ar group-name
+Assign the interface to a
+.Dq group .
+Any interface can be in multiple groups.
+.Pp
+Cloned interfaces are members of their interface family group by default.
+For example, a PPP interface such as
+.Em ppp0
+is a member of the PPP interface family group,
+.Em ppp .
+.\" The interface(s) the default route(s) point to are members of the
+.\" .Em egress
+.\" interface group.
+.It Cm -group Ar group-name
+Remove the interface from the given
+.Dq group .
 .It Cm eui64
 (Inet6 only.)
 Fill interface index
Index: sbin/ifconfig/ifgroup.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: sbin/ifconfig/ifgroup.c
diff -N sbin/ifconfig/ifgroup.c
=2D-- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sbin/ifconfig/ifgroup.c	12 Apr 2006 02:30:45 -0000
@@ -0,0 +1,186 @@
+/*-
+ * Copyright (c) 2006 Max Laier. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURP=
OSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENT=
IAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STR=
ICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY W=
AY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static const char rcsid[] =3D
+  "$FreeBSD$";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ifconfig.h"
+
+/* ARGSUSED */
+static void
+setifgroup(const char *group_name, int d, int s, const struct afswtch *raf=
p)
+{
+	struct ifgroupreq ifgr;
+
+	memset(&ifgr, 0, sizeof(ifgr));
+	strlcpy(ifgr.ifgr_name, name, IFNAMSIZ);
+
+	if (group_name[0] && isdigit(group_name[strlen(group_name) - 1]))
+		errx(1, "setifgroup: group names may not end in a digit");
+
+	if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >=3D IFNAMSIZ)
+		errx(1, "setifgroup: group name too long");
+	if (ioctl(s, SIOCAIFGROUP, (caddr_t)&ifgr) =3D=3D -1)
+		err(1," SIOCAIFGROUP");
+}
+
+/* ARGSUSED */
+static void
+unsetifgroup(const char *group_name, int d, int s, const struct afswtch *r=
afp)
+{
+	struct ifgroupreq ifgr;
+
+	memset(&ifgr, 0, sizeof(ifgr));
+	strlcpy(ifgr.ifgr_name, name, IFNAMSIZ);
+
+	if (group_name[0] && isdigit(group_name[strlen(group_name) - 1]))
+		errx(1, "unsetifgroup: group names may not end in a digit");
+
+	if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >=3D IFNAMSIZ)
+		errx(1, "unsetifgroup: group name too long");
+	if (ioctl(s, SIOCDIFGROUP, (caddr_t)&ifgr) =3D=3D -1)
+		err(1, "SIOCDIFGROUP");
+}
+
+static void
+getifgroups(int s)
+{
+	int			 len, cnt;
+	struct ifgroupreq	 ifgr;
+	struct ifg_req		*ifg;
+
+	if (!verbose)
+		return;
+
+	memset(&ifgr, 0, sizeof(ifgr));
+	strlcpy(ifgr.ifgr_name, name, IFNAMSIZ);
+
+	if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) =3D=3D -1) {
+		if (errno =3D=3D EINVAL || errno =3D=3D ENOTTY)
+			return;
+		else
+			err(1, "SIOCGIFGROUP");
+	}
+
+	len =3D ifgr.ifgr_len;
+	ifgr.ifgr_groups =3D
+	    (struct ifg_req *)calloc(len / sizeof(struct ifg_req),
+	    sizeof(struct ifg_req));
+	if (ifgr.ifgr_groups =3D=3D NULL)
+		err(1, "getifgroups");
+	if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) =3D=3D -1)
+		err(1, "SIOCGIFGROUP");
+
+	cnt =3D 0;
+	ifg =3D ifgr.ifgr_groups;
+	for (; ifg && len >=3D sizeof(struct ifg_req); ifg++) {
+		len -=3D sizeof(struct ifg_req);
+		if (strcmp(ifg->ifgrq_group, "all")) {
+			if (cnt =3D=3D 0)
+				printf("\tgroups: ");
+			cnt++;
+			printf("%s ", ifg->ifgrq_group);
+		}
+	}
+	if (cnt)
+		printf("\n");
+}
+
+static void
+printgroup(char *groupname)
+{
+	struct ifgroupreq	 ifgr;
+	struct ifg_req		*ifg;
+	int			 len, cnt =3D 0;
+	int			 s;
+
+	s =3D socket(AF_INET, SOCK_DGRAM, 0);
+	if (s =3D=3D -1)
+		err(1, "socket(AF_INET,SOCK_DGRAM)");
+	bzero(&ifgr, sizeof(ifgr));
+	strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name));
+	if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) =3D=3D -1) {
+		if (errno =3D=3D EINVAL || errno =3D=3D ENOTTY ||
+		    errno =3D=3D ENOENT)
+			exit(0);
+		else
+			err(1, "SIOCGIFGMEMB");
+	}
+
+	len =3D ifgr.ifgr_len;
+	if ((ifgr.ifgr_groups =3D calloc(1, len)) =3D=3D NULL)
+		err(1, "printgroup");
+	if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) =3D=3D -1)
+		err(1, "SIOCGIFGMEMB");
+
+	for (ifg =3D ifgr.ifgr_groups; ifg && len >=3D sizeof(struct ifg_req);
+	    ifg++) {
+		len -=3D sizeof(struct ifg_req);
+		printf("%s\n", ifg->ifgrq_member);
+		cnt++;
+	}
+	free(ifgr.ifgr_groups);
+
+	exit(0);
+}
+
+static struct cmd group_cmds[] =3D {
+	DEF_CMD_ARG("group",	setifgroup),
+	DEF_CMD_ARG("-group",	unsetifgroup),
+};
+static struct afswtch af_group =3D {
+	.af_name	=3D "af_group",
+	.af_af		=3D AF_UNSPEC,
+	.af_other_status =3D getifgroups,
+};
+static struct option group_gopt =3D { "g:", "[-g groupname]", printgroup };
+
+static __constructor void
+group_ctor(void)
+{
+#define	N(a)	(sizeof(a) / sizeof(a[0]))
+	int i;
+
+	for (i =3D 0; i < N(group_cmds);  i++)
+		cmd_register(&group_cmds[i]);
+	af_register(&af_group);
+	opt_register(&group_gopt);
+#undef N
+}
Index: sys/net/if.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /usr/store/mlaier/fcvs/src/sys/net/if.c,v
retrieving revision 1.255
diff -u -r1.255 if.c
=2D-- sys/net/if.c	21 Mar 2006 14:31:18 -0000	1.255
+++ sys/net/if.c	12 Apr 2006 02:57:34 -0000
@@ -113,6 +113,8 @@
 static int	ifhwioctl(u_long, struct ifnet *, caddr_t, struct thread *);
 static void	if_start_deferred(void *context, int pending);
 static void	do_link_state_change(void *, int);
+static int	if_getgroup(struct ifgroupreq *, struct ifnet *);
+static int	if_getgroupmembers(struct ifgroupreq *);
 #ifdef INET6
 /*
  * XXX: declare here to avoid to include many inet6 related files..
@@ -125,6 +127,7 @@
 struct	ifindex_entry *ifindex_table =3D NULL;
 int	ifqmaxlen =3D IFQ_MAXLEN;
 struct	ifnethead ifnet;	/* depend on static init XXX */
+struct	ifgrouphead ifg_head;
 struct	mtx ifnet_lock;
 static	if_com_alloc_t *if_com_alloc[256];
 static	if_com_free_t *if_com_free[256];
@@ -282,6 +285,7 @@
=20
 	IFNET_LOCK_INIT();
 	TAILQ_INIT(&ifnet);
+	TAILQ_INIT(&ifg_head);
 	knlist_init(&ifklist, NULL, NULL, NULL, NULL);
 	if_grow();				/* create initial table */
 	ifdev_byindex(0) =3D make_dev(&net_cdevsw, 0,
@@ -441,6 +445,10 @@
 	TAILQ_INIT(&ifp->if_addrhead);
 	TAILQ_INIT(&ifp->if_prefixhead);
 	TAILQ_INIT(&ifp->if_multiaddrs);
+	TAILQ_INIT(&ifp->if_groups);
+
+	if_addgroup(ifp, IFG_ALL);
+
 	knlist_init(&ifp->if_klist, NULL, NULL, NULL, NULL);
 	getmicrotime(&ifp->if_lastchange);
 	ifp->if_data.ifi_epoch =3D time_uptime;
@@ -713,6 +721,213 @@
 }
=20
 /*
+ * Add a group to an interface
+ */
+int
+if_addgroup(struct ifnet *ifp, const char *groupname)
+{
+	struct ifg_list		*ifgl;
+	struct ifg_group	*ifg =3D NULL;
+	struct ifg_member	*ifgm;
+
+	if (groupname[0] && groupname[strlen(groupname) - 1] >=3D '0' &&
+	    groupname[strlen(groupname) - 1] <=3D '9')
+		return (EINVAL);
+
+	IFNET_WLOCK();
+	TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
+		if (!strcmp(ifgl->ifgl_group->ifg_group, groupname)) {
+			IFNET_WUNLOCK();
+			return (EEXIST);
+		}
+
+	if ((ifgl =3D (struct ifg_list *)malloc(sizeof(struct ifg_list), M_TEMP,
+	    M_NOWAIT)) =3D=3D NULL) {
+	    	IFNET_WUNLOCK();
+		return (ENOMEM);
+	}
+
+	if ((ifgm =3D (struct ifg_member *)malloc(sizeof(struct ifg_member),
+	    M_TEMP, M_NOWAIT)) =3D=3D NULL) {
+		free(ifgl, M_TEMP);
+		IFNET_WUNLOCK();
+		return (ENOMEM);
+	}
+
+	TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
+		if (!strcmp(ifg->ifg_group, groupname))
+			break;
+
+	if (ifg =3D=3D NULL) {
+		if ((ifg =3D (struct ifg_group *)malloc(sizeof(struct ifg_group),
+		    M_TEMP, M_NOWAIT)) =3D=3D NULL) {
+			free(ifgl, M_TEMP);
+			free(ifgm, M_TEMP);
+			IFNET_WUNLOCK();
+			return (ENOMEM);
+		}
+		strlcpy(ifg->ifg_group, groupname, sizeof(ifg->ifg_group));
+		ifg->ifg_refcnt =3D 0;
+		TAILQ_INIT(&ifg->ifg_members);
+		EVENTHANDLER_INVOKE(group_attach_event, ifg);
+		TAILQ_INSERT_TAIL(&ifg_head, ifg, ifg_next);
+	}
+
+	ifg->ifg_refcnt++;
+	ifgl->ifgl_group =3D ifg;
+	ifgm->ifgm_ifp =3D ifp;
+
+	IF_ADDR_LOCK(ifp);
+	TAILQ_INSERT_TAIL(&ifg->ifg_members, ifgm, ifgm_next);
+	TAILQ_INSERT_TAIL(&ifp->if_groups, ifgl, ifgl_next);
+	IF_ADDR_UNLOCK(ifp);
+
+	EVENTHANDLER_INVOKE(group_change_event, groupname);
+	IFNET_WUNLOCK();
+
+	return (0);
+}
+
+/*
+ * Remove a group from an interface
+ */
+int
+if_delgroup(struct ifnet *ifp, const char *groupname)
+{
+	struct ifg_list		*ifgl;
+	struct ifg_member	*ifgm;
+
+	IFNET_WLOCK();
+	TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
+		if (!strcmp(ifgl->ifgl_group->ifg_group, groupname))
+			break;
+	if (ifgl =3D=3D NULL) {
+		IFNET_WUNLOCK();
+		return (ENOENT);
+	}
+
+	IF_ADDR_LOCK(ifp);
+	TAILQ_REMOVE(&ifp->if_groups, ifgl, ifgl_next);
+	IF_ADDR_UNLOCK(ifp);
+
+	TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next)
+		if (ifgm->ifgm_ifp =3D=3D ifp)
+			break;
+
+	if (ifgm !=3D NULL) {
+		TAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifgm_next);
+		free(ifgm, M_TEMP);
+	}
+
+	if (--ifgl->ifgl_group->ifg_refcnt =3D=3D 0) {
+		TAILQ_REMOVE(&ifg_head, ifgl->ifgl_group, ifg_next);
+		EVENTHANDLER_INVOKE(group_detach_event, ifgl->ifgl_group);
+		free(ifgl->ifgl_group, M_TEMP);
+	}
+	IFNET_WUNLOCK();
+
+	free(ifgl, M_TEMP);
+
+	EVENTHANDLER_INVOKE(group_change_event, groupname);
+
+	return (0);
+}
+
+/*
+ * Stores all groups from an interface in memory pointed
+ * to by data
+ */
+static int
+if_getgroup(struct ifgroupreq *data, struct ifnet *ifp)
+{
+	int			 len, error;
+	struct ifg_list		*ifgl;
+	struct ifg_req		 ifgrq, *ifgp;
+	struct ifgroupreq	*ifgr =3D data;
+
+	if (ifgr->ifgr_len =3D=3D 0) {
+		IF_ADDR_LOCK(ifp);
+		TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
+			ifgr->ifgr_len +=3D sizeof(struct ifg_req);
+		IF_ADDR_UNLOCK(ifp);
+		return (0);
+	}
+
+	len =3D ifgr->ifgr_len;
+	ifgp =3D ifgr->ifgr_groups;
+	/* XXX: wire */
+	IF_ADDR_LOCK(ifp);
+	TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) {
+		if (len < sizeof(ifgrq)) {
+			IF_ADDR_UNLOCK(ifp);
+			return (EINVAL);
+		}
+		bzero(&ifgrq, sizeof ifgrq);
+		strlcpy(ifgrq.ifgrq_group, ifgl->ifgl_group->ifg_group,
+		    sizeof(ifgrq.ifgrq_group));
+		if ((error =3D copyout(&ifgrq, ifgp, sizeof(struct ifg_req)))) {
+		    	IF_ADDR_UNLOCK(ifp);
+			return (error);
+		}
+		len -=3D sizeof(ifgrq);
+		ifgp++;
+	}
+	IF_ADDR_UNLOCK(ifp);
+
+	return (0);
+}
+
+/*
+ * Stores all members of a group in memory pointed to by data
+ */
+static int
+if_getgroupmembers(struct ifgroupreq *data)
+{
+	struct ifgroupreq	*ifgr =3D data;
+	struct ifg_group	*ifg;
+	struct ifg_member	*ifgm;
+	struct ifg_req		 ifgrq, *ifgp;
+	int			 len, error;
+
+	IFNET_RLOCK();
+	TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
+		if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
+			break;
+	if (ifg =3D=3D NULL) {
+		IFNET_RUNLOCK();
+		return (ENOENT);
+	}
+
+	if (ifgr->ifgr_len =3D=3D 0) {
+		TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next)
+			ifgr->ifgr_len +=3D sizeof(ifgrq);
+		IFNET_RUNLOCK();
+		return (0);
+	}
+
+	len =3D ifgr->ifgr_len;
+	ifgp =3D ifgr->ifgr_groups;
+	TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) {
+		if (len < sizeof(ifgrq)) {
+			IFNET_RUNLOCK();
+			return (EINVAL);
+		}
+		bzero(&ifgrq, sizeof ifgrq);
+		strlcpy(ifgrq.ifgrq_member, ifgm->ifgm_ifp->if_xname,
+		    sizeof(ifgrq.ifgrq_member));
+		if ((error =3D copyout(&ifgrq, ifgp, sizeof(struct ifg_req)))) {
+			IFNET_RUNLOCK();
+			return (error);
+		}
+		len -=3D sizeof(ifgrq);
+		ifgp++;
+	}
+	IFNET_RUNLOCK();
+
+	return (0);
+}
+
+/*
  * Delete Routes for a Network Interface
  *
  * Called for each routing entry via the rnh->rnh_walktree() call above
@@ -1470,6 +1685,35 @@
 		    ifr->ifr_addr.sa_data, ifr->ifr_addr.sa_len);
 		break;
=20
+	case SIOCAIFGROUP:
+	{
+		struct ifgroupreq *ifgr =3D (struct ifgroupreq *)ifr;
+
+		error =3D suser(td);
+		if (error)
+			return (error);
+		if ((error =3D if_addgroup(ifp, ifgr->ifgr_group)))
+			return (error);
+		break;
+	}
+
+	case SIOCGIFGROUP:
+		if ((error =3D if_getgroup((struct ifgroupreq *)ifr, ifp)))
+			return (error);
+		break;
+
+	case SIOCDIFGROUP:
+	{
+		struct ifgroupreq *ifgr =3D (struct ifgroupreq *)ifr;
+
+		error =3D suser(td);
+		if (error)
+			return (error);
+		if ((error =3D if_delgroup(ifp, ifgr->ifgr_group)))
+			return (error);
+		break;
+	}
+
 	default:
 		error =3D ENOIOCTL;
 		break;
@@ -1509,6 +1753,8 @@
=20
 	case SIOCIFGCLONERS:
 		return (if_clone_list((struct if_clonereq *)data));
+	case SIOCGIFGMEMB:
+		return (if_getgroupmembers((struct ifgroupreq *)data));
 	}
=20
 	ifp =3D ifunit(ifr->ifr_name);
Index: sys/net/if.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /usr/store/mlaier/fcvs/src/sys/net/if.h,v
retrieving revision 1.101
diff -u -r1.101 if.h
=2D-- sys/net/if.h	2 Feb 2006 19:58:37 -0000	1.101
+++ sys/net/if.h	11 Apr 2006 03:41:57 -0000
@@ -359,6 +359,37 @@
 #endif
=20
 /*
+ * interface groups
+ */
+
+#define	IFG_ALL		"all"		/* group contains all interfaces */
+/* XXX: will we implement this? */
+#define	IFG_EGRESS	"egress"	/* if(s) default route(s) point to */
+
+struct ifg_req {
+	union {
+		char			 ifgrqu_group[IFNAMSIZ];
+		char			 ifgrqu_member[IFNAMSIZ];
+	} ifgrq_ifgrqu;
+#define	ifgrq_group	ifgrq_ifgrqu.ifgrqu_group
+#define	ifgrq_member	ifgrq_ifgrqu.ifgrqu_member
+};
+
+/*
+ * Used to lookup groups for an interface
+ */
+struct ifgroupreq {
+	char	ifgr_name[IFNAMSIZ];
+	u_int	ifgr_len;
+	union {
+		char	ifgru_group[IFNAMSIZ];
+		struct	ifg_req *ifgru_groups;
+	} ifgr_ifgru;
+#define ifgr_group	ifgr_ifgru.ifgru_group
+#define ifgr_groups	ifgr_ifgru.ifgru_groups
+};
+
+/*
  * Structure for SIOC[AGD]LIFADDR
  */
 struct if_laddrreq {
Index: sys/net/if_clone.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /usr/store/mlaier/fcvs/src/sys/net/if_clone.c,v
retrieving revision 1.9
diff -u -r1.9 if_clone.c
=2D-- sys/net/if_clone.c	24 Nov 2005 18:56:14 -0000	1.9
+++ sys/net/if_clone.c	12 Apr 2006 01:03:27 -0000
@@ -158,6 +158,8 @@
 		if (ifp =3D=3D NULL)
 			panic("%s: lookup failed for %s", __func__, name);
=20
+		if_addgroup(ifp, ifc->ifc_name);
+
 		IF_CLONE_LOCK(ifc);
 		IFC_IFLIST_INSERT(ifc, ifp);
 		IF_CLONE_UNLOCK(ifc);
@@ -210,9 +212,13 @@
 	IFC_IFLIST_REMOVE(ifc, ifp);
 	IF_CLONE_UNLOCK(ifc);
=20
+	if_delgroup(ifp, ifc->ifc_name);
+
 	err =3D  (*ifc->ifc_destroy)(ifc, ifp);
=20
 	if (err !=3D 0) {
+		if_addgroup(ifp, ifc->ifc_name);
+
 		IF_CLONE_LOCK(ifc);
 		IFC_IFLIST_INSERT(ifc, ifp);
 		IF_CLONE_UNLOCK(ifc);
Index: sys/net/if_var.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /usr/store/mlaier/fcvs/src/sys/net/if_var.h,v
retrieving revision 1.106
diff -u -r1.106 if_var.h
=2D-- sys/net/if_var.h	30 Jan 2006 13:45:15 -0000	1.106
+++ sys/net/if_var.h	12 Apr 2006 02:59:42 -0000
@@ -91,6 +91,7 @@
 TAILQ_HEAD(ifaddrhead, ifaddr);	/* instantiation is preserved in the list =
*/
 TAILQ_HEAD(ifprefixhead, ifprefix);
 TAILQ_HEAD(ifmultihead, ifmultiaddr);
+TAILQ_HEAD(ifgrouphead, ifg_group);
=20
 /*
  * Structure defining a queue for a network interface.
@@ -182,6 +183,9 @@
 	struct	task if_linktask;	/* task for link change events */
 	struct	mtx if_addr_mtx;	/* mutex to protect address lists */
 	LIST_ENTRY(ifnet) if_clones;	/* interfaces of a cloner */
+	TAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if */
+					/* protected by if_addr_mtx */
+	void	*if_pf_kif;
 };
=20
 typedef void if_init_f_t(void *);
@@ -318,6 +322,37 @@
 typedef void (*ifnet_departure_event_handler_t)(void *, struct ifnet *);
 EVENTHANDLER_DECLARE(ifnet_departure_event, ifnet_departure_event_handler_=
t);
=20
+/*
+ * interface groups
+ */
+struct ifg_group {
+	char				 ifg_group[IFNAMSIZ];
+	u_int				 ifg_refcnt;
+	void				*ifg_pf_kif;
+	TAILQ_HEAD(, ifg_member)	 ifg_members;
+	TAILQ_ENTRY(ifg_group)		 ifg_next;
+};
+
+struct ifg_member {
+	TAILQ_ENTRY(ifg_member)	 ifgm_next;
+	struct ifnet		*ifgm_ifp;
+};
+
+struct ifg_list {
+	struct ifg_group	*ifgl_group;
+	TAILQ_ENTRY(ifg_list)	 ifgl_next;
+};
+
+/* group attach event */
+typedef void (*group_attach_event_handler_t)(void *, struct ifg_group *);
+EVENTHANDLER_DECLARE(group_attach_event, group_attach_event_handler_t);
+/* group detach event */
+typedef void (*group_detach_event_handler_t)(void *, struct ifg_group *);
+EVENTHANDLER_DECLARE(group_detach_event, group_detach_event_handler_t);
+/* group change event */
+typedef void (*group_change_event_handler_t)(void *, const char *);
+EVENTHANDLER_DECLARE(group_change_event, group_change_event_handler_t);
+
 #define	IF_AFDATA_LOCK_INIT(ifp)	\
     mtx_init(&(ifp)->if_afdata_mtx, "if_afdata", NULL, MTX_DEF)
 #define	IF_AFDATA_LOCK(ifp)	mtx_lock(&(ifp)->if_afdata_mtx)
@@ -624,6 +659,8 @@
 extern	struct ifnet *loif;	/* first loopback interface */
 extern	int if_index;
=20
+int	if_addgroup(struct ifnet *, const char *);
+int	if_delgroup(struct ifnet *, const char *);
 int	if_addmulti(struct ifnet *, struct sockaddr *, struct ifmultiaddr **);
 int	if_allmulti(struct ifnet *, int);
 struct	ifnet* if_alloc(u_char);
Index: sys/sys/sockio.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /usr/store/mlaier/fcvs/src/sys/sys/sockio.h,v
retrieving revision 1.29
diff -u -r1.29 sockio.h
=2D-- sys/sys/sockio.h	2 Feb 2006 19:58:37 -0000	1.29
+++ sys/sys/sockio.h	12 Apr 2006 00:36:11 -0000
@@ -117,4 +117,9 @@
 #define	SIOCIFDESTROY	 _IOW('i', 121, struct ifreq)	/* destroy clone if */
 #define	SIOCIFGCLONERS	_IOWR('i', 120, struct if_clonereq) /* get cloners =
*/
=20
+#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_ */

--Boundary-01=_FIHPE+/4nKkInpx--

--nextPart1349231.b1GtDd56l5
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.2 (FreeBSD)

iD8DBQBEPHIKXyyEoT62BG0RAsXWAJ4pgUKyND/wsYYxxFBYDqlMawYSvQCdFKmP
utDZ9vHV+y3fZLcqiYuKMnA=
=LLdv
-----END PGP SIGNATURE-----

--nextPart1349231.b1GtDd56l5--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200604120520.42362.max>