diff options
author | sam <sam@FreeBSD.org> | 2006-07-09 06:10:23 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2006-07-09 06:10:23 +0000 |
commit | 5fe5db7b92d100880e8e1049b140630a29d38514 (patch) | |
tree | 459ad9fd08735e01e8a354fad1a3b67f5cd31477 /sbin/ifconfig/ifvlan.c | |
parent | 2350e920372288f7ed8401d362497880b30dea50 (diff) | |
download | FreeBSD-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.c | 132 |
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) ¶ms; + } + 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) ¶ms; + 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[] = { |