[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
interface groups
- To: tech@openbsd.org
- Subject: interface groups
- From: Philipp Buehler <pb@openbsd.org>
- Date: Tue, 22 Jun 2004 18:02:05 +0200
- Content-Disposition: inline
- Mail-Followup-To: Philipp Buehler <pb@openbsd.org>, tech@openbsd.org
- User-Agent: Mutt/1.5.6i
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()