197ed1257SBill Paul /* 297ed1257SBill Paul * Copyright (c) 1999 397ed1257SBill Paul * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 497ed1257SBill Paul * 597ed1257SBill Paul * Redistribution and use in source and binary forms, with or without 697ed1257SBill Paul * modification, are permitted provided that the following conditions 797ed1257SBill Paul * are met: 897ed1257SBill Paul * 1. Redistributions of source code must retain the above copyright 997ed1257SBill Paul * notice, this list of conditions and the following disclaimer. 1097ed1257SBill Paul * 2. Redistributions in binary form must reproduce the above copyright 1197ed1257SBill Paul * notice, this list of conditions and the following disclaimer in the 1297ed1257SBill Paul * documentation and/or other materials provided with the distribution. 1397ed1257SBill Paul * 3. All advertising materials mentioning features or use of this software 1497ed1257SBill Paul * must display the following acknowledgement: 1597ed1257SBill Paul * This product includes software developed by Bill Paul. 1697ed1257SBill Paul * 4. Neither the name of the author nor the names of any co-contributors 1797ed1257SBill Paul * may be used to endorse or promote products derived from this software 1897ed1257SBill Paul * without specific prior written permission. 1997ed1257SBill Paul * 2097ed1257SBill Paul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 2197ed1257SBill Paul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2297ed1257SBill Paul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2397ed1257SBill Paul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 2497ed1257SBill Paul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2597ed1257SBill Paul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2697ed1257SBill Paul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2797ed1257SBill Paul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2897ed1257SBill Paul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2997ed1257SBill Paul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 3097ed1257SBill Paul * THE POSSIBILITY OF SUCH DAMAGE. 3197ed1257SBill Paul */ 3297ed1257SBill Paul 3397ed1257SBill Paul #include <sys/param.h> 3497ed1257SBill Paul #include <sys/ioctl.h> 3597ed1257SBill Paul #include <sys/socket.h> 3697ed1257SBill Paul #include <sys/sockio.h> 3797ed1257SBill Paul 3897ed1257SBill Paul #include <stdlib.h> 3997ed1257SBill Paul #include <unistd.h> 4097ed1257SBill Paul 4197ed1257SBill Paul #include <net/ethernet.h> 4297ed1257SBill Paul #include <net/if.h> 4397ed1257SBill Paul #include <net/if_var.h> 4497ed1257SBill Paul #include <net/if_vlan_var.h> 4597ed1257SBill Paul #include <net/route.h> 4697ed1257SBill Paul 4797ed1257SBill Paul #include <ctype.h> 4897ed1257SBill Paul #include <stdio.h> 4997ed1257SBill Paul #include <string.h> 5097ed1257SBill Paul #include <stdlib.h> 5197ed1257SBill Paul #include <unistd.h> 5297ed1257SBill Paul #include <err.h> 5397ed1257SBill Paul #include <errno.h> 5497ed1257SBill Paul 5597ed1257SBill Paul #include "ifconfig.h" 5697ed1257SBill Paul 5797ed1257SBill Paul #ifndef lint 5897ed1257SBill Paul static const char rcsid[] = 597f3dea24SPeter Wemm "$FreeBSD$"; 6097ed1257SBill Paul #endif 617fc2ce8aSYaroslav Tykhiy static struct vlanreq __vreq; 627fc2ce8aSYaroslav Tykhiy static int __have_dev = 0; 6397ed1257SBill Paul static int __have_tag = 0; 6497ed1257SBill Paul 655faf8dcbSSam Leffler static void 6690c4b74cSSam Leffler vlan_status(int s) 6797ed1257SBill Paul { 6897ed1257SBill Paul struct vlanreq vreq; 6997ed1257SBill Paul 7097ed1257SBill Paul bzero((char *)&vreq, sizeof(struct vlanreq)); 7197ed1257SBill Paul ifr.ifr_data = (caddr_t)&vreq; 7297ed1257SBill Paul 7397ed1257SBill Paul if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) 7497ed1257SBill Paul return; 7597ed1257SBill Paul 7697ed1257SBill Paul printf("\tvlan: %d parent interface: %s\n", 7797ed1257SBill Paul vreq.vlr_tag, vreq.vlr_parent[0] == '\0' ? 7897ed1257SBill Paul "<none>" : vreq.vlr_parent); 7997ed1257SBill Paul 8097ed1257SBill Paul return; 8197ed1257SBill Paul } 8297ed1257SBill Paul 835faf8dcbSSam Leffler static void 84bc123897SWarner Losh setvlantag(const char *val, int d, int s, const struct afswtch *afp) 8597ed1257SBill Paul { 867fc2ce8aSYaroslav Tykhiy char *endp; 877fc2ce8aSYaroslav Tykhiy u_long ul; 8897ed1257SBill Paul 897fc2ce8aSYaroslav Tykhiy ul = strtoul(val, &endp, 0); 907fc2ce8aSYaroslav Tykhiy if (*endp != '\0') 917fc2ce8aSYaroslav Tykhiy errx(1, "invalid value for vlan"); 927fc2ce8aSYaroslav Tykhiy __vreq.vlr_tag = ul; 937fc2ce8aSYaroslav Tykhiy /* check if the value can be represented in vlr_tag */ 947fc2ce8aSYaroslav Tykhiy if (__vreq.vlr_tag != ul) 957fc2ce8aSYaroslav Tykhiy errx(1, "value for vlan out of range"); 967fc2ce8aSYaroslav Tykhiy /* the kernel will do more specific checks on vlr_tag */ 9797ed1257SBill Paul __have_tag = 1; 9897ed1257SBill Paul } 9997ed1257SBill Paul 1005faf8dcbSSam Leffler static void 101bc123897SWarner Losh setvlandev(const char *val, int d, int s, const struct afswtch *afp) 10297ed1257SBill Paul { 10397ed1257SBill Paul 1047fc2ce8aSYaroslav Tykhiy strncpy(__vreq.vlr_parent, val, sizeof(__vreq.vlr_parent)); 1057fc2ce8aSYaroslav Tykhiy __have_dev = 1; 10697ed1257SBill Paul } 10797ed1257SBill Paul 1085faf8dcbSSam Leffler static void 109bc123897SWarner Losh unsetvlandev(const char *val, int d, int s, const struct afswtch *afp) 11097ed1257SBill Paul { 11197ed1257SBill Paul struct vlanreq vreq; 11297ed1257SBill Paul 113b0dcc11cSYaroslav Tykhiy if (val != NULL) 114b0dcc11cSYaroslav Tykhiy warnx("argument to -vlandev is useless and hence deprecated"); 115b0dcc11cSYaroslav Tykhiy 11697ed1257SBill Paul bzero((char *)&vreq, sizeof(struct vlanreq)); 11797ed1257SBill Paul ifr.ifr_data = (caddr_t)&vreq; 11897ed1257SBill Paul 11997ed1257SBill Paul if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) 12097ed1257SBill Paul err(1, "SIOCGETVLAN"); 12197ed1257SBill Paul 12297ed1257SBill Paul bzero((char *)&vreq.vlr_parent, sizeof(vreq.vlr_parent)); 1237fc2ce8aSYaroslav Tykhiy vreq.vlr_tag = 0; /* XXX clear parent only (no kernel support now) */ 12497ed1257SBill Paul 12597ed1257SBill Paul if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) 12697ed1257SBill Paul err(1, "SIOCSETVLAN"); 1277fc2ce8aSYaroslav Tykhiy __have_dev = __have_tag = 0; 1287fc2ce8aSYaroslav Tykhiy } 12997ed1257SBill Paul 1307fc2ce8aSYaroslav Tykhiy static void 1317fc2ce8aSYaroslav Tykhiy vlan_cb(int s, void *arg) 1327fc2ce8aSYaroslav Tykhiy { 1337fc2ce8aSYaroslav Tykhiy 1347fc2ce8aSYaroslav Tykhiy if (__have_tag ^ __have_dev) 1357fc2ce8aSYaroslav Tykhiy errx(1, "both vlan and vlandev must be specified"); 1367fc2ce8aSYaroslav Tykhiy 1377fc2ce8aSYaroslav Tykhiy if (__have_tag && __have_dev) { 1387fc2ce8aSYaroslav Tykhiy ifr.ifr_data = (caddr_t)&__vreq; 1397fc2ce8aSYaroslav Tykhiy if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) 1407fc2ce8aSYaroslav Tykhiy err(1, "SIOCSETVLAN"); 1417fc2ce8aSYaroslav Tykhiy } 14297ed1257SBill Paul } 1435faf8dcbSSam Leffler 1445faf8dcbSSam Leffler static struct cmd vlan_cmds[] = { 1455faf8dcbSSam Leffler DEF_CMD_ARG("vlan", setvlantag), 1465faf8dcbSSam Leffler DEF_CMD_ARG("vlandev", setvlandev), 147b0dcc11cSYaroslav Tykhiy /* XXX For compatibility. Should become DEF_CMD() some day. */ 148b0dcc11cSYaroslav Tykhiy DEF_CMD_OPTARG("-vlandev", unsetvlandev), 1495faf8dcbSSam Leffler DEF_CMD("vlanmtu", IFCAP_VLAN_MTU, setifcap), 1505faf8dcbSSam Leffler DEF_CMD("-vlanmtu", -IFCAP_VLAN_MTU, setifcap), 1515faf8dcbSSam Leffler DEF_CMD("vlanhwtag", IFCAP_VLAN_HWTAGGING, setifcap), 1525faf8dcbSSam Leffler DEF_CMD("-vlanhwtag", -IFCAP_VLAN_HWTAGGING, setifcap), 1535faf8dcbSSam Leffler }; 1545faf8dcbSSam Leffler static struct afswtch af_vlan = { 1555faf8dcbSSam Leffler .af_name = "af_vlan", 1565faf8dcbSSam Leffler .af_af = AF_UNSPEC, 15790c4b74cSSam Leffler .af_other_status = vlan_status, 1585faf8dcbSSam Leffler }; 1595faf8dcbSSam Leffler 1605faf8dcbSSam Leffler static __constructor void 1615faf8dcbSSam Leffler vlan_ctor(void) 1625faf8dcbSSam Leffler { 1635faf8dcbSSam Leffler #define N(a) (sizeof(a) / sizeof(a[0])) 1645faf8dcbSSam Leffler int i; 1655faf8dcbSSam Leffler 1665faf8dcbSSam Leffler for (i = 0; i < N(vlan_cmds); i++) 1675faf8dcbSSam Leffler cmd_register(&vlan_cmds[i]); 1685faf8dcbSSam Leffler af_register(&af_vlan); 1697fc2ce8aSYaroslav Tykhiy callback_register(vlan_cb, NULL); 1705faf8dcbSSam Leffler #undef N 1715faf8dcbSSam Leffler } 172