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 6197ed1257SBill Paul 62db82353dSSam Leffler #define NOTAG ((u_short) -1) 63db82353dSSam Leffler 64db82353dSSam Leffler static struct vlanreq params = { 65db82353dSSam Leffler .vlr_tag = NOTAG, 66db82353dSSam Leffler }; 67db82353dSSam Leffler 68db82353dSSam Leffler static int 69db82353dSSam Leffler getvlan(int s, struct ifreq *ifr, struct vlanreq *vreq) 70db82353dSSam Leffler { 71db82353dSSam Leffler bzero((char *)vreq, sizeof(*vreq)); 72db82353dSSam Leffler ifr->ifr_data = (caddr_t)vreq; 73db82353dSSam Leffler 74db82353dSSam Leffler return ioctl(s, SIOCGETVLAN, (caddr_t)ifr); 75db82353dSSam Leffler } 762fe9aa26SYaroslav Tykhiy 775faf8dcbSSam Leffler static void 7890c4b74cSSam Leffler vlan_status(int s) 7997ed1257SBill Paul { 8097ed1257SBill Paul struct vlanreq vreq; 8197ed1257SBill Paul 82db82353dSSam Leffler if (getvlan(s, &ifr, &vreq) != -1) 8397ed1257SBill Paul printf("\tvlan: %d parent interface: %s\n", 8497ed1257SBill Paul vreq.vlr_tag, vreq.vlr_parent[0] == '\0' ? 8597ed1257SBill Paul "<none>" : vreq.vlr_parent); 8697ed1257SBill Paul } 8797ed1257SBill Paul 885faf8dcbSSam Leffler static void 89db82353dSSam Leffler vlan_create(int s, struct ifreq *ifr) 9097ed1257SBill Paul { 91db82353dSSam Leffler if (params.vlr_tag != NOTAG || params.vlr_parent[0] != '\0') { 92db82353dSSam Leffler /* 93db82353dSSam Leffler * One or both parameters were specified, make sure both. 94db82353dSSam Leffler */ 95db82353dSSam Leffler if (params.vlr_tag == NOTAG) 96db82353dSSam Leffler errx(1, "must specify a tag for vlan create"); 97db82353dSSam Leffler if (params.vlr_parent[0] == '\0') 98db82353dSSam Leffler errx(1, "must specify a parent device for vlan create"); 99db82353dSSam Leffler ifr->ifr_data = (caddr_t) ¶ms; 10097ed1257SBill Paul } 101db82353dSSam Leffler if (ioctl(s, SIOCIFCREATE2, ifr) < 0) 102db82353dSSam Leffler err(1, "SIOCIFCREATE2"); 1037fc2ce8aSYaroslav Tykhiy } 10497ed1257SBill Paul 1057fc2ce8aSYaroslav Tykhiy static void 1067fc2ce8aSYaroslav Tykhiy vlan_cb(int s, void *arg) 1077fc2ce8aSYaroslav Tykhiy { 108db82353dSSam Leffler if ((params.vlr_tag != NOTAG) ^ (params.vlr_parent[0] != '\0')) 1097fc2ce8aSYaroslav Tykhiy errx(1, "both vlan and vlandev must be specified"); 1102fe9aa26SYaroslav Tykhiy } 1112fe9aa26SYaroslav Tykhiy 1122fe9aa26SYaroslav Tykhiy static void 113db82353dSSam Leffler vlan_set(int s, struct ifreq *ifr) 1142fe9aa26SYaroslav Tykhiy { 115db82353dSSam Leffler if (params.vlr_tag != NOTAG && params.vlr_parent[0] != '\0') { 116db82353dSSam Leffler ifr->ifr_data = (caddr_t) ¶ms; 117db82353dSSam Leffler if (ioctl(s, SIOCSETVLAN, (caddr_t)ifr) == -1) 1187fc2ce8aSYaroslav Tykhiy err(1, "SIOCSETVLAN"); 1197fc2ce8aSYaroslav Tykhiy } 12097ed1257SBill Paul } 1215faf8dcbSSam Leffler 122db82353dSSam Leffler static 123db82353dSSam Leffler DECL_CMD_FUNC(setvlantag, val, d) 124db82353dSSam Leffler { 125db82353dSSam Leffler struct vlanreq vreq; 126db82353dSSam Leffler u_long ul; 127db82353dSSam Leffler char *endp; 128db82353dSSam Leffler 129db82353dSSam Leffler ul = strtoul(val, &endp, 0); 130db82353dSSam Leffler if (*endp != '\0') 131db82353dSSam Leffler errx(1, "invalid value for vlan"); 132db82353dSSam Leffler params.vlr_tag = ul; 133db82353dSSam Leffler /* check if the value can be represented in vlr_tag */ 134db82353dSSam Leffler if (params.vlr_tag != ul) 135db82353dSSam Leffler errx(1, "value for vlan out of range"); 136db82353dSSam Leffler 137db82353dSSam Leffler if (getvlan(s, &ifr, &vreq) != -1) 138db82353dSSam Leffler vlan_set(s, &ifr); 139db82353dSSam Leffler else 140db82353dSSam Leffler clone_setcallback(vlan_create); 141db82353dSSam Leffler } 142db82353dSSam Leffler 143db82353dSSam Leffler static 144db82353dSSam Leffler DECL_CMD_FUNC(setvlandev, val, d) 145db82353dSSam Leffler { 146db82353dSSam Leffler struct vlanreq vreq; 147db82353dSSam Leffler 148db82353dSSam Leffler strlcpy(params.vlr_parent, val, sizeof(params.vlr_parent)); 149db82353dSSam Leffler 150db82353dSSam Leffler if (getvlan(s, &ifr, &vreq) != -1) 151db82353dSSam Leffler vlan_set(s, &ifr); 152db82353dSSam Leffler else 153db82353dSSam Leffler clone_setcallback(vlan_create); 154db82353dSSam Leffler } 155db82353dSSam Leffler 156db82353dSSam Leffler static 157db82353dSSam Leffler DECL_CMD_FUNC(unsetvlandev, val, d) 158db82353dSSam Leffler { 159db82353dSSam Leffler struct vlanreq vreq; 160db82353dSSam Leffler 161db82353dSSam Leffler bzero((char *)&vreq, sizeof(struct vlanreq)); 162db82353dSSam Leffler ifr.ifr_data = (caddr_t)&vreq; 163db82353dSSam Leffler 164db82353dSSam Leffler if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) 165db82353dSSam Leffler err(1, "SIOCGETVLAN"); 166db82353dSSam Leffler 167db82353dSSam Leffler bzero((char *)&vreq.vlr_parent, sizeof(vreq.vlr_parent)); 168db82353dSSam Leffler vreq.vlr_tag = 0; 169db82353dSSam Leffler 170db82353dSSam Leffler if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) 171db82353dSSam Leffler err(1, "SIOCSETVLAN"); 172db82353dSSam Leffler } 173db82353dSSam Leffler 1745faf8dcbSSam Leffler static struct cmd vlan_cmds[] = { 1752fa02c5fSSam Leffler DEF_CLONE_CMD_ARG("vlan", setvlantag), 1762fa02c5fSSam Leffler DEF_CLONE_CMD_ARG("vlandev", setvlandev), 177b0dcc11cSYaroslav Tykhiy /* XXX For compatibility. Should become DEF_CMD() some day. */ 178b0dcc11cSYaroslav Tykhiy DEF_CMD_OPTARG("-vlandev", unsetvlandev), 1795faf8dcbSSam Leffler DEF_CMD("vlanmtu", IFCAP_VLAN_MTU, setifcap), 1805faf8dcbSSam Leffler DEF_CMD("-vlanmtu", -IFCAP_VLAN_MTU, setifcap), 1815faf8dcbSSam Leffler DEF_CMD("vlanhwtag", IFCAP_VLAN_HWTAGGING, setifcap), 1825faf8dcbSSam Leffler DEF_CMD("-vlanhwtag", -IFCAP_VLAN_HWTAGGING, setifcap), 183eafbb00dSJack F Vogel DEF_CMD("vlanhwfilter", IFCAP_VLAN_HWFILTER, setifcap), 184eafbb00dSJack F Vogel DEF_CMD("-vlanhwfilter", -IFCAP_VLAN_HWFILTER, setifcap), 1855faf8dcbSSam Leffler }; 1865faf8dcbSSam Leffler static struct afswtch af_vlan = { 1875faf8dcbSSam Leffler .af_name = "af_vlan", 1885faf8dcbSSam Leffler .af_af = AF_UNSPEC, 18990c4b74cSSam Leffler .af_other_status = vlan_status, 1905faf8dcbSSam Leffler }; 1915faf8dcbSSam Leffler 1925faf8dcbSSam Leffler static __constructor void 1935faf8dcbSSam Leffler vlan_ctor(void) 1945faf8dcbSSam Leffler { 1955faf8dcbSSam Leffler #define N(a) (sizeof(a) / sizeof(a[0])) 1965faf8dcbSSam Leffler int i; 1975faf8dcbSSam Leffler 1985faf8dcbSSam Leffler for (i = 0; i < N(vlan_cmds); i++) 1995faf8dcbSSam Leffler cmd_register(&vlan_cmds[i]); 2005faf8dcbSSam Leffler af_register(&af_vlan); 2017fc2ce8aSYaroslav Tykhiy callback_register(vlan_cb, NULL); 2025faf8dcbSSam Leffler #undef N 2035faf8dcbSSam Leffler } 204