197ed1257SBill Paul /* 2*2ccbbd06SMarcelo Araujo * Copyright (c) 1999 Bill Paul <wpaul@ctr.columbia.edu> 3*2ccbbd06SMarcelo Araujo * Copyright (c) 2012 ADARA Networks, Inc. 4*2ccbbd06SMarcelo Araujo * All rights reserved. 5*2ccbbd06SMarcelo Araujo * 6*2ccbbd06SMarcelo Araujo * Portions of this software were developed by Robert N. M. Watson under 7*2ccbbd06SMarcelo Araujo * contract to ADARA Networks, Inc. 897ed1257SBill Paul * 997ed1257SBill Paul * Redistribution and use in source and binary forms, with or without 1097ed1257SBill Paul * modification, are permitted provided that the following conditions 1197ed1257SBill Paul * are met: 1297ed1257SBill Paul * 1. Redistributions of source code must retain the above copyright 1397ed1257SBill Paul * notice, this list of conditions and the following disclaimer. 1497ed1257SBill Paul * 2. Redistributions in binary form must reproduce the above copyright 1597ed1257SBill Paul * notice, this list of conditions and the following disclaimer in the 1697ed1257SBill Paul * documentation and/or other materials provided with the distribution. 1797ed1257SBill Paul * 3. All advertising materials mentioning features or use of this software 1897ed1257SBill Paul * must display the following acknowledgement: 1997ed1257SBill Paul * This product includes software developed by Bill Paul. 2097ed1257SBill Paul * 4. Neither the name of the author nor the names of any co-contributors 2197ed1257SBill Paul * may be used to endorse or promote products derived from this software 2297ed1257SBill Paul * without specific prior written permission. 2397ed1257SBill Paul * 2497ed1257SBill Paul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 2597ed1257SBill Paul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2697ed1257SBill Paul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2797ed1257SBill Paul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 2897ed1257SBill Paul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2997ed1257SBill Paul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 3097ed1257SBill Paul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 3197ed1257SBill Paul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 3297ed1257SBill Paul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3397ed1257SBill Paul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 3497ed1257SBill Paul * THE POSSIBILITY OF SUCH DAMAGE. 3597ed1257SBill Paul */ 3697ed1257SBill Paul 3797ed1257SBill Paul #include <sys/param.h> 3897ed1257SBill Paul #include <sys/ioctl.h> 3997ed1257SBill Paul #include <sys/socket.h> 4097ed1257SBill Paul #include <sys/sockio.h> 4197ed1257SBill Paul 4297ed1257SBill Paul #include <stdlib.h> 4397ed1257SBill Paul #include <unistd.h> 4497ed1257SBill Paul 4597ed1257SBill Paul #include <net/ethernet.h> 4697ed1257SBill Paul #include <net/if.h> 4797ed1257SBill Paul #include <net/if_vlan_var.h> 4897ed1257SBill Paul #include <net/route.h> 4997ed1257SBill Paul 5097ed1257SBill Paul #include <ctype.h> 5197ed1257SBill Paul #include <stdio.h> 5297ed1257SBill Paul #include <string.h> 5397ed1257SBill Paul #include <stdlib.h> 5497ed1257SBill Paul #include <unistd.h> 5597ed1257SBill Paul #include <err.h> 5697ed1257SBill Paul #include <errno.h> 5797ed1257SBill Paul 5897ed1257SBill Paul #include "ifconfig.h" 5997ed1257SBill Paul 6097ed1257SBill Paul #ifndef lint 6197ed1257SBill Paul static const char rcsid[] = 627f3dea24SPeter Wemm "$FreeBSD$"; 6397ed1257SBill Paul #endif 6497ed1257SBill Paul 65db82353dSSam Leffler #define NOTAG ((u_short) -1) 66db82353dSSam Leffler 67db82353dSSam Leffler static struct vlanreq params = { 68db82353dSSam Leffler .vlr_tag = NOTAG, 69db82353dSSam Leffler }; 70db82353dSSam Leffler 71db82353dSSam Leffler static int 72db82353dSSam Leffler getvlan(int s, struct ifreq *ifr, struct vlanreq *vreq) 73db82353dSSam Leffler { 74db82353dSSam Leffler bzero((char *)vreq, sizeof(*vreq)); 75db82353dSSam Leffler ifr->ifr_data = (caddr_t)vreq; 76db82353dSSam Leffler 77db82353dSSam Leffler return ioctl(s, SIOCGETVLAN, (caddr_t)ifr); 78db82353dSSam Leffler } 792fe9aa26SYaroslav Tykhiy 805faf8dcbSSam Leffler static void 8190c4b74cSSam Leffler vlan_status(int s) 8297ed1257SBill Paul { 8397ed1257SBill Paul struct vlanreq vreq; 8497ed1257SBill Paul 85*2ccbbd06SMarcelo Araujo if (getvlan(s, &ifr, &vreq) == -1) 86*2ccbbd06SMarcelo Araujo return; 87*2ccbbd06SMarcelo Araujo printf("\tvlan: %d", vreq.vlr_tag); 88*2ccbbd06SMarcelo Araujo if (ioctl(s, SIOCGVLANPCP, (caddr_t)&ifr) != -1) 89*2ccbbd06SMarcelo Araujo printf(" vlanpcp: %u", ifr.ifr_vlan_pcp); 90*2ccbbd06SMarcelo Araujo printf(" parent interface: %s", vreq.vlr_parent[0] == '\0' ? 9197ed1257SBill Paul "<none>" : vreq.vlr_parent); 92*2ccbbd06SMarcelo Araujo printf("\n"); 9397ed1257SBill Paul } 9497ed1257SBill Paul 955faf8dcbSSam Leffler static void 96db82353dSSam Leffler vlan_create(int s, struct ifreq *ifr) 9797ed1257SBill Paul { 98db82353dSSam Leffler if (params.vlr_tag != NOTAG || params.vlr_parent[0] != '\0') { 99db82353dSSam Leffler /* 100db82353dSSam Leffler * One or both parameters were specified, make sure both. 101db82353dSSam Leffler */ 102db82353dSSam Leffler if (params.vlr_tag == NOTAG) 103db82353dSSam Leffler errx(1, "must specify a tag for vlan create"); 104db82353dSSam Leffler if (params.vlr_parent[0] == '\0') 105db82353dSSam Leffler errx(1, "must specify a parent device for vlan create"); 106db82353dSSam Leffler ifr->ifr_data = (caddr_t) ¶ms; 10797ed1257SBill Paul } 108db82353dSSam Leffler if (ioctl(s, SIOCIFCREATE2, ifr) < 0) 109db82353dSSam Leffler err(1, "SIOCIFCREATE2"); 1107fc2ce8aSYaroslav Tykhiy } 11197ed1257SBill Paul 1127fc2ce8aSYaroslav Tykhiy static void 1137fc2ce8aSYaroslav Tykhiy vlan_cb(int s, void *arg) 1147fc2ce8aSYaroslav Tykhiy { 115db82353dSSam Leffler if ((params.vlr_tag != NOTAG) ^ (params.vlr_parent[0] != '\0')) 1167fc2ce8aSYaroslav Tykhiy errx(1, "both vlan and vlandev must be specified"); 1172fe9aa26SYaroslav Tykhiy } 1182fe9aa26SYaroslav Tykhiy 1192fe9aa26SYaroslav Tykhiy static void 120db82353dSSam Leffler vlan_set(int s, struct ifreq *ifr) 1212fe9aa26SYaroslav Tykhiy { 122db82353dSSam Leffler if (params.vlr_tag != NOTAG && params.vlr_parent[0] != '\0') { 123db82353dSSam Leffler ifr->ifr_data = (caddr_t) ¶ms; 124db82353dSSam Leffler if (ioctl(s, SIOCSETVLAN, (caddr_t)ifr) == -1) 1257fc2ce8aSYaroslav Tykhiy err(1, "SIOCSETVLAN"); 1267fc2ce8aSYaroslav Tykhiy } 12797ed1257SBill Paul } 1285faf8dcbSSam Leffler 12967207b69SSam Leffler static 13067207b69SSam Leffler DECL_CMD_FUNC(setvlantag, val, d) 131db82353dSSam Leffler { 13267207b69SSam Leffler struct vlanreq vreq; 133db82353dSSam Leffler u_long ul; 134db82353dSSam Leffler char *endp; 135db82353dSSam Leffler 136db82353dSSam Leffler ul = strtoul(val, &endp, 0); 137db82353dSSam Leffler if (*endp != '\0') 138db82353dSSam Leffler errx(1, "invalid value for vlan"); 139db82353dSSam Leffler params.vlr_tag = ul; 140db82353dSSam Leffler /* check if the value can be represented in vlr_tag */ 141db82353dSSam Leffler if (params.vlr_tag != ul) 142db82353dSSam Leffler errx(1, "value for vlan out of range"); 143db82353dSSam Leffler 14467207b69SSam Leffler if (getvlan(s, &ifr, &vreq) != -1) 145db82353dSSam Leffler vlan_set(s, &ifr); 146db82353dSSam Leffler } 147db82353dSSam Leffler 148db82353dSSam Leffler static 149db82353dSSam Leffler DECL_CMD_FUNC(setvlandev, val, d) 150db82353dSSam Leffler { 151db82353dSSam Leffler struct vlanreq vreq; 152db82353dSSam Leffler 153db82353dSSam Leffler strlcpy(params.vlr_parent, val, sizeof(params.vlr_parent)); 15467207b69SSam Leffler 155db82353dSSam Leffler if (getvlan(s, &ifr, &vreq) != -1) 156db82353dSSam Leffler vlan_set(s, &ifr); 157db82353dSSam Leffler } 158db82353dSSam Leffler 159db82353dSSam Leffler static 160*2ccbbd06SMarcelo Araujo DECL_CMD_FUNC(setvlanpcp, val, d) 161*2ccbbd06SMarcelo Araujo { 162*2ccbbd06SMarcelo Araujo u_long ul; 163*2ccbbd06SMarcelo Araujo char *endp; 164*2ccbbd06SMarcelo Araujo 165*2ccbbd06SMarcelo Araujo ul = strtoul(val, &endp, 0); 166*2ccbbd06SMarcelo Araujo if (*endp != '\0') 167*2ccbbd06SMarcelo Araujo errx(1, "invalid value for vlanpcp"); 168*2ccbbd06SMarcelo Araujo if (ul > 7) 169*2ccbbd06SMarcelo Araujo errx(1, "value for vlanpcp out of range"); 170*2ccbbd06SMarcelo Araujo ifr.ifr_vlan_pcp = ul; 171*2ccbbd06SMarcelo Araujo if (ioctl(s, SIOCSVLANPCP, (caddr_t)&ifr) == -1) 172*2ccbbd06SMarcelo Araujo err(1, "SIOCSVLANPCP"); 173*2ccbbd06SMarcelo Araujo } 174*2ccbbd06SMarcelo Araujo 175*2ccbbd06SMarcelo Araujo static 176db82353dSSam Leffler DECL_CMD_FUNC(unsetvlandev, val, d) 177db82353dSSam Leffler { 178db82353dSSam Leffler struct vlanreq vreq; 179db82353dSSam Leffler 180db82353dSSam Leffler bzero((char *)&vreq, sizeof(struct vlanreq)); 181db82353dSSam Leffler ifr.ifr_data = (caddr_t)&vreq; 182db82353dSSam Leffler 183db82353dSSam Leffler if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) 184db82353dSSam Leffler err(1, "SIOCGETVLAN"); 185db82353dSSam Leffler 186db82353dSSam Leffler bzero((char *)&vreq.vlr_parent, sizeof(vreq.vlr_parent)); 187db82353dSSam Leffler vreq.vlr_tag = 0; 188db82353dSSam Leffler 189db82353dSSam Leffler if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) 190db82353dSSam Leffler err(1, "SIOCSETVLAN"); 191db82353dSSam Leffler } 192db82353dSSam Leffler 1935faf8dcbSSam Leffler static struct cmd vlan_cmds[] = { 19467207b69SSam Leffler DEF_CLONE_CMD_ARG("vlan", setvlantag), 19567207b69SSam Leffler DEF_CLONE_CMD_ARG("vlandev", setvlandev), 196*2ccbbd06SMarcelo Araujo DEF_CMD_ARG("vlanpcp", setvlanpcp), 19724994b36SSam Leffler /* NB: non-clone cmds */ 19824994b36SSam Leffler DEF_CMD_ARG("vlan", setvlantag), 19924994b36SSam Leffler DEF_CMD_ARG("vlandev", setvlandev), 200b0dcc11cSYaroslav Tykhiy /* XXX For compatibility. Should become DEF_CMD() some day. */ 201b0dcc11cSYaroslav Tykhiy DEF_CMD_OPTARG("-vlandev", unsetvlandev), 2025faf8dcbSSam Leffler DEF_CMD("vlanmtu", IFCAP_VLAN_MTU, setifcap), 2035faf8dcbSSam Leffler DEF_CMD("-vlanmtu", -IFCAP_VLAN_MTU, setifcap), 2045faf8dcbSSam Leffler DEF_CMD("vlanhwtag", IFCAP_VLAN_HWTAGGING, setifcap), 2055faf8dcbSSam Leffler DEF_CMD("-vlanhwtag", -IFCAP_VLAN_HWTAGGING, setifcap), 206eafbb00dSJack F Vogel DEF_CMD("vlanhwfilter", IFCAP_VLAN_HWFILTER, setifcap), 207eafbb00dSJack F Vogel DEF_CMD("-vlanhwfilter", -IFCAP_VLAN_HWFILTER, setifcap), 2080f686c0fSPyun YongHyeon DEF_CMD("-vlanhwtso", -IFCAP_VLAN_HWTSO, setifcap), 2090f686c0fSPyun YongHyeon DEF_CMD("vlanhwtso", IFCAP_VLAN_HWTSO, setifcap), 2109b776960SBjoern A. Zeeb DEF_CMD("vlanhwcsum", IFCAP_VLAN_HWCSUM, setifcap), 2119b776960SBjoern A. Zeeb DEF_CMD("-vlanhwcsum", -IFCAP_VLAN_HWCSUM, setifcap), 2125faf8dcbSSam Leffler }; 2135faf8dcbSSam Leffler static struct afswtch af_vlan = { 2145faf8dcbSSam Leffler .af_name = "af_vlan", 2155faf8dcbSSam Leffler .af_af = AF_UNSPEC, 21690c4b74cSSam Leffler .af_other_status = vlan_status, 2175faf8dcbSSam Leffler }; 2185faf8dcbSSam Leffler 2195faf8dcbSSam Leffler static __constructor void 2205faf8dcbSSam Leffler vlan_ctor(void) 2215faf8dcbSSam Leffler { 222b59dcaeeSXin LI size_t i; 2235faf8dcbSSam Leffler 224abd71050SEnji Cooper for (i = 0; i < nitems(vlan_cmds); i++) 2255faf8dcbSSam Leffler cmd_register(&vlan_cmds[i]); 2265faf8dcbSSam Leffler af_register(&af_vlan); 2277fc2ce8aSYaroslav Tykhiy callback_register(vlan_cb, NULL); 2289c1fd0b0SRui Paulo clone_setdefcallback("vlan", vlan_create); 2295faf8dcbSSam Leffler } 230