144764Swpaul/* 244764Swpaul * Copyright (c) 1999 344764Swpaul * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 444764Swpaul * 544764Swpaul * Redistribution and use in source and binary forms, with or without 644764Swpaul * modification, are permitted provided that the following conditions 744764Swpaul * are met: 844764Swpaul * 1. Redistributions of source code must retain the above copyright 944764Swpaul * notice, this list of conditions and the following disclaimer. 1044764Swpaul * 2. Redistributions in binary form must reproduce the above copyright 1144764Swpaul * notice, this list of conditions and the following disclaimer in the 1244764Swpaul * documentation and/or other materials provided with the distribution. 1344764Swpaul * 3. All advertising materials mentioning features or use of this software 1444764Swpaul * must display the following acknowledgement: 1544764Swpaul * This product includes software developed by Bill Paul. 1644764Swpaul * 4. Neither the name of the author nor the names of any co-contributors 1744764Swpaul * may be used to endorse or promote products derived from this software 1844764Swpaul * without specific prior written permission. 1944764Swpaul * 2044764Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 2144764Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2244764Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2344764Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 2444764Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2544764Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2644764Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2744764Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2844764Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2944764Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 3044764Swpaul * THE POSSIBILITY OF SUCH DAMAGE. 3144764Swpaul */ 3244764Swpaul 3344764Swpaul#include <sys/param.h> 3444764Swpaul#include <sys/ioctl.h> 3544764Swpaul#include <sys/socket.h> 3644764Swpaul#include <sys/sockio.h> 3744764Swpaul 3844764Swpaul#include <stdlib.h> 3944764Swpaul#include <unistd.h> 4044764Swpaul 4144764Swpaul#include <net/ethernet.h> 4244764Swpaul#include <net/if.h> 4344764Swpaul#include <net/if_var.h> 4444764Swpaul#include <net/if_vlan_var.h> 4544764Swpaul#include <net/route.h> 4644764Swpaul 4744764Swpaul#include <ctype.h> 4844764Swpaul#include <stdio.h> 4944764Swpaul#include <string.h> 5044764Swpaul#include <stdlib.h> 5144764Swpaul#include <unistd.h> 5244764Swpaul#include <err.h> 5344764Swpaul#include <errno.h> 5444764Swpaul 5544764Swpaul#include "ifconfig.h" 5644764Swpaul 5744764Swpaul#ifndef lint 5844764Swpaulstatic const char rcsid[] = 5950476Speter "$FreeBSD$"; 6044764Swpaul#endif 6144764Swpaul 62160196Ssam#define NOTAG ((u_short) -1) 63156498Syar 64160196Ssamstatic struct vlanreq params = { 65160196Ssam .vlr_tag = NOTAG, 66160196Ssam}; 67160196Ssam 68160196Ssamstatic int 69160196Ssamgetvlan(int s, struct ifreq *ifr, struct vlanreq *vreq) 70160196Ssam{ 71160196Ssam bzero((char *)vreq, sizeof(*vreq)); 72160196Ssam ifr->ifr_data = (caddr_t)vreq; 73160196Ssam 74160196Ssam return ioctl(s, SIOCGETVLAN, (caddr_t)ifr); 75160196Ssam} 76160196Ssam 77138593Ssamstatic void 78139494Ssamvlan_status(int s) 7944764Swpaul{ 8044764Swpaul struct vlanreq vreq; 8144764Swpaul 82160196Ssam if (getvlan(s, &ifr, &vreq) != -1) 83160196Ssam printf("\tvlan: %d parent interface: %s\n", 84160196Ssam vreq.vlr_tag, vreq.vlr_parent[0] == '\0' ? 85160196Ssam "<none>" : vreq.vlr_parent); 86160196Ssam} 8744764Swpaul 88160196Ssamstatic void 89160196Ssamvlan_create(int s, struct ifreq *ifr) 90160196Ssam{ 91160196Ssam if (params.vlr_tag != NOTAG || params.vlr_parent[0] != '\0') { 92160196Ssam /* 93160196Ssam * One or both parameters were specified, make sure both. 94160196Ssam */ 95160196Ssam if (params.vlr_tag == NOTAG) 96160196Ssam errx(1, "must specify a tag for vlan create"); 97160196Ssam if (params.vlr_parent[0] == '\0') 98160196Ssam errx(1, "must specify a parent device for vlan create"); 99160196Ssam ifr->ifr_data = (caddr_t) ¶ms; 100160196Ssam } 101160196Ssam if (ioctl(s, SIOCIFCREATE2, ifr) < 0) 102160196Ssam err(1, "SIOCIFCREATE2"); 103160196Ssam} 10444764Swpaul 105160196Ssamstatic void 106160196Ssamvlan_cb(int s, void *arg) 107160196Ssam{ 108160196Ssam if ((params.vlr_tag != NOTAG) ^ (params.vlr_parent[0] != '\0')) 109160196Ssam errx(1, "both vlan and vlandev must be specified"); 11044764Swpaul} 11144764Swpaul 112138593Ssamstatic void 113160196Ssamvlan_set(int s, struct ifreq *ifr) 11444764Swpaul{ 115160196Ssam if (params.vlr_tag != NOTAG && params.vlr_parent[0] != '\0') { 116160196Ssam ifr->ifr_data = (caddr_t) ¶ms; 117160196Ssam if (ioctl(s, SIOCSETVLAN, (caddr_t)ifr) == -1) 118160196Ssam err(1, "SIOCSETVLAN"); 119160196Ssam } 120160196Ssam} 12144764Swpaul 122186108Ssamstatic 123186108SsamDECL_CMD_FUNC(setvlantag, val, d) 124160196Ssam{ 125186108Ssam struct vlanreq vreq; 126160196Ssam u_long ul; 127160196Ssam char *endp; 128160196Ssam 129150907Syar ul = strtoul(val, &endp, 0); 130150907Syar if (*endp != '\0') 131150907Syar errx(1, "invalid value for vlan"); 132160196Ssam params.vlr_tag = ul; 133150907Syar /* check if the value can be represented in vlr_tag */ 134160196Ssam if (params.vlr_tag != ul) 135150907Syar errx(1, "value for vlan out of range"); 136160196Ssam 137186108Ssam if (getvlan(s, &ifr, &vreq) != -1) 138186108Ssam vlan_set(s, &ifr); 13944764Swpaul} 14044764Swpaul 141160196Ssamstatic 142186108SsamDECL_CMD_FUNC(setvlandev, val, d) 143186101Ssam{ 144186101Ssam struct vlanreq vreq; 145186101Ssam 146186101Ssam strlcpy(params.vlr_parent, val, sizeof(params.vlr_parent)); 147186101Ssam 148160196Ssam if (getvlan(s, &ifr, &vreq) != -1) 149186108Ssam vlan_set(s, &ifr); 15044764Swpaul} 15144764Swpaul 152160196Ssamstatic 153160196SsamDECL_CMD_FUNC(unsetvlandev, val, d) 15444764Swpaul{ 155160196Ssam struct vlanreq vreq; 15644764Swpaul 157160196Ssam bzero((char *)&vreq, sizeof(struct vlanreq)); 158160196Ssam ifr.ifr_data = (caddr_t)&vreq; 159150736Syar 16044764Swpaul if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) 16144764Swpaul err(1, "SIOCGETVLAN"); 16244764Swpaul 163160196Ssam bzero((char *)&vreq.vlr_parent, sizeof(vreq.vlr_parent)); 164160196Ssam vreq.vlr_tag = 0; 165160196Ssam 16644764Swpaul if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) 16744764Swpaul err(1, "SIOCSETVLAN"); 168150907Syar} 16944764Swpaul 170138593Ssamstatic struct cmd vlan_cmds[] = { 171186108Ssam DEF_CLONE_CMD_ARG("vlan", setvlantag), 172186108Ssam DEF_CLONE_CMD_ARG("vlandev", setvlandev), 173183554Ssam /* NB: non-clone cmds */ 174183554Ssam DEF_CMD_ARG("vlan", setvlantag), 175183554Ssam DEF_CMD_ARG("vlandev", setvlandev), 176150736Syar /* XXX For compatibility. Should become DEF_CMD() some day. */ 177150736Syar DEF_CMD_OPTARG("-vlandev", unsetvlandev), 178138593Ssam DEF_CMD("vlanmtu", IFCAP_VLAN_MTU, setifcap), 179138593Ssam DEF_CMD("-vlanmtu", -IFCAP_VLAN_MTU, setifcap), 180138593Ssam DEF_CMD("vlanhwtag", IFCAP_VLAN_HWTAGGING, setifcap), 181138593Ssam DEF_CMD("-vlanhwtag", -IFCAP_VLAN_HWTAGGING, setifcap), 182182414Sjfv DEF_CMD("vlanhwfilter", IFCAP_VLAN_HWFILTER, setifcap), 183182414Sjfv DEF_CMD("-vlanhwfilter", -IFCAP_VLAN_HWFILTER, setifcap), 184204150Syongari DEF_CMD("-vlanhwtso", -IFCAP_VLAN_HWTSO, setifcap), 185204150Syongari DEF_CMD("vlanhwtso", IFCAP_VLAN_HWTSO, setifcap), 186228641Sbz DEF_CMD("vlanhwcsum", IFCAP_VLAN_HWCSUM, setifcap), 187228641Sbz DEF_CMD("-vlanhwcsum", -IFCAP_VLAN_HWCSUM, setifcap), 188138593Ssam}; 189138593Ssamstatic struct afswtch af_vlan = { 190138593Ssam .af_name = "af_vlan", 191138593Ssam .af_af = AF_UNSPEC, 192139494Ssam .af_other_status = vlan_status, 193138593Ssam}; 194138593Ssam 195138593Ssamstatic __constructor void 196138593Ssamvlan_ctor(void) 197138593Ssam{ 198138593Ssam#define N(a) (sizeof(a) / sizeof(a[0])) 199194799Sdelphij size_t i; 200138593Ssam 201138593Ssam for (i = 0; i < N(vlan_cmds); i++) 202138593Ssam cmd_register(&vlan_cmds[i]); 203138593Ssam af_register(&af_vlan); 204150907Syar callback_register(vlan_cb, NULL); 205189096Srpaulo clone_setdefcallback("vlan", vlan_create); 206138593Ssam#undef N 207138593Ssam} 208