summaryrefslogtreecommitdiffstats
path: root/sbin/ifconfig/ifvlan.c
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2006-07-09 06:10:23 +0000
committersam <sam@FreeBSD.org>2006-07-09 06:10:23 +0000
commit5fe5db7b92d100880e8e1049b140630a29d38514 (patch)
tree459ad9fd08735e01e8a354fad1a3b67f5cd31477 /sbin/ifconfig/ifvlan.c
parent2350e920372288f7ed8401d362497880b30dea50 (diff)
downloadFreeBSD-src-5fe5db7b92d100880e8e1049b140630a29d38514.zip
FreeBSD-src-5fe5db7b92d100880e8e1049b140630a29d38514.tar.gz
o replace special handling of clone operations by a clone callback
mechanism o change vlan cloning to use callback and pass all vlan parameters on create using the new SIOCREATE2 ioctl o update vlan set logic to match existing practice
Diffstat (limited to 'sbin/ifconfig/ifvlan.c')
-rw-r--r--sbin/ifconfig/ifvlan.c132
1 files changed, 78 insertions, 54 deletions
diff --git a/sbin/ifconfig/ifvlan.c b/sbin/ifconfig/ifvlan.c
index f2dfba4..205ed21 100644
--- a/sbin/ifconfig/ifvlan.c
+++ b/sbin/ifconfig/ifvlan.c
@@ -58,93 +58,117 @@
static const char rcsid[] =
"$FreeBSD$";
#endif
-static struct vlanreq __vreq;
-static int __have_dev = 0;
-static int __have_tag = 0;
-static void vlan_set(int);
+#define NOTAG ((u_short) -1)
+
+static struct vlanreq params = {
+ .vlr_tag = NOTAG,
+};
+
+static int
+getvlan(int s, struct ifreq *ifr, struct vlanreq *vreq)
+{
+ bzero((char *)vreq, sizeof(*vreq));
+ ifr->ifr_data = (caddr_t)vreq;
+
+ return ioctl(s, SIOCGETVLAN, (caddr_t)ifr);
+}
static void
vlan_status(int s)
{
struct vlanreq vreq;
- bzero((char *)&vreq, sizeof(vreq));
- ifr.ifr_data = (caddr_t)&vreq;
+ if (getvlan(s, &ifr, &vreq) != -1)
+ printf("\tvlan: %d parent interface: %s\n",
+ vreq.vlr_tag, vreq.vlr_parent[0] == '\0' ?
+ "<none>" : vreq.vlr_parent);
+}
- if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1)
- return;
+static void
+vlan_create(int s, struct ifreq *ifr)
+{
+ if (params.vlr_tag != NOTAG || params.vlr_parent[0] != '\0') {
+ /*
+ * One or both parameters were specified, make sure both.
+ */
+ if (params.vlr_tag == NOTAG)
+ errx(1, "must specify a tag for vlan create");
+ if (params.vlr_parent[0] == '\0')
+ errx(1, "must specify a parent device for vlan create");
+ ifr->ifr_data = (caddr_t) &params;
+ }
+ if (ioctl(s, SIOCIFCREATE2, ifr) < 0)
+ err(1, "SIOCIFCREATE2");
+}
- printf("\tvlan: %d parent interface: %s\n",
- vreq.vlr_tag, vreq.vlr_parent[0] == '\0' ?
- "<none>" : vreq.vlr_parent);
+static void
+vlan_cb(int s, void *arg)
+{
+ if ((params.vlr_tag != NOTAG) ^ (params.vlr_parent[0] != '\0'))
+ errx(1, "both vlan and vlandev must be specified");
}
static void
-setvlantag(const char *val, int d, int s, const struct afswtch *afp)
+vlan_set(int s, struct ifreq *ifr)
+{
+ if (params.vlr_tag != NOTAG && params.vlr_parent[0] != '\0') {
+ ifr->ifr_data = (caddr_t) &params;
+ if (ioctl(s, SIOCSETVLAN, (caddr_t)ifr) == -1)
+ err(1, "SIOCSETVLAN");
+ }
+}
+
+static
+DECL_CMD_FUNC(setvlantag, val, d)
{
- char *endp;
- u_long ul;
+ struct vlanreq vreq;
+ u_long ul;
+ char *endp;
ul = strtoul(val, &endp, 0);
if (*endp != '\0')
errx(1, "invalid value for vlan");
- __vreq.vlr_tag = ul;
+ params.vlr_tag = ul;
/* check if the value can be represented in vlr_tag */
- if (__vreq.vlr_tag != ul)
+ if (params.vlr_tag != ul)
errx(1, "value for vlan out of range");
- /* the kernel will do more specific checks on vlr_tag */
- __have_tag = 1;
- vlan_set(s); /* try setting vlan params in kernel */
+
+ if (getvlan(s, &ifr, &vreq) != -1)
+ vlan_set(s, &ifr);
+ else
+ clone_setcallback(vlan_create);
}
-static void
-setvlandev(const char *val, int d, int s, const struct afswtch *afp)
+static
+DECL_CMD_FUNC(setvlandev, val, d)
{
+ struct vlanreq vreq;
+
+ strlcpy(params.vlr_parent, val, sizeof(params.vlr_parent));
- strncpy(__vreq.vlr_parent, val, sizeof(__vreq.vlr_parent));
- __have_dev = 1;
- vlan_set(s); /* try setting vlan params in kernel */
+ if (getvlan(s, &ifr, &vreq) != -1)
+ vlan_set(s, &ifr);
+ else
+ clone_setcallback(vlan_create);
}
-static void
-unsetvlandev(const char *val, int d, int s, const struct afswtch *afp)
+static
+DECL_CMD_FUNC(unsetvlandev, val, d)
{
+ struct vlanreq vreq;
- if (val != NULL)
- warnx("argument to -vlandev is useless and hence deprecated");
+ bzero((char *)&vreq, sizeof(struct vlanreq));
+ ifr.ifr_data = (caddr_t)&vreq;
- bzero((char *)&__vreq, sizeof(__vreq));
- ifr.ifr_data = (caddr_t)&__vreq;
-#if 0 /* this code will be of use when we can alter vlan or vlandev only */
if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1)
err(1, "SIOCGETVLAN");
- bzero((char *)&__vreq.vlr_parent, sizeof(__vreq.vlr_parent));
- __vreq.vlr_tag = 0; /* XXX clear parent only (no kernel support now) */
-#endif
+ bzero((char *)&vreq.vlr_parent, sizeof(vreq.vlr_parent));
+ vreq.vlr_tag = 0;
+
if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1)
err(1, "SIOCSETVLAN");
- __have_dev = __have_tag = 0;
-}
-
-static void
-vlan_cb(int s, void *arg)
-{
-
- if (__have_tag ^ __have_dev)
- errx(1, "both vlan and vlandev must be specified");
-}
-
-static void
-vlan_set(int s)
-{
-
- if (__have_tag && __have_dev) {
- ifr.ifr_data = (caddr_t)&__vreq;
- if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1)
- err(1, "SIOCSETVLAN");
- }
}
static struct cmd vlan_cmds[] = {
OpenPOWER on IntegriCloud