ifvlan.c revision 256281
1275970Scy/* 2275970Scy * Copyright (c) 1999 3275970Scy * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 4275970Scy * 5275970Scy * Redistribution and use in source and binary forms, with or without 6275970Scy * modification, are permitted provided that the following conditions 7275970Scy * are met: 8275970Scy * 1. Redistributions of source code must retain the above copyright 9275970Scy * notice, this list of conditions and the following disclaimer. 10275970Scy * 2. Redistributions in binary form must reproduce the above copyright 11275970Scy * notice, this list of conditions and the following disclaimer in the 12275970Scy * documentation and/or other materials provided with the distribution. 13275970Scy * 3. All advertising materials mentioning features or use of this software 14275970Scy * must display the following acknowledgement: 15275970Scy * This product includes software developed by Bill Paul. 16275970Scy * 4. Neither the name of the author nor the names of any co-contributors 17275970Scy * may be used to endorse or promote products derived from this software 18275970Scy * without specific prior written permission. 19275970Scy * 20275970Scy * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21275970Scy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22275970Scy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23275970Scy * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 24275970Scy * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25275970Scy * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26275970Scy * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27275970Scy * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28275970Scy * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29275970Scy * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30275970Scy * THE POSSIBILITY OF SUCH DAMAGE. 31275970Scy */ 32275970Scy 33275970Scy#include <sys/param.h> 34275970Scy#include <sys/ioctl.h> 35275970Scy#include <sys/socket.h> 36275970Scy#include <sys/sockio.h> 37275970Scy 38275970Scy#include <stdlib.h> 39275970Scy#include <unistd.h> 40275970Scy 41275970Scy#include <net/ethernet.h> 42275970Scy#include <net/if.h> 43275970Scy#include <net/if_var.h> 44275970Scy#include <net/if_vlan_var.h> 45275970Scy#include <net/route.h> 46275970Scy 47275970Scy#include <ctype.h> 48275970Scy#include <stdio.h> 49275970Scy#include <string.h> 50275970Scy#include <stdlib.h> 51275970Scy#include <unistd.h> 52275970Scy#include <err.h> 53275970Scy#include <errno.h> 54275970Scy 55275970Scy#include "ifconfig.h" 56275970Scy 57275970Scy#ifndef lint 58275970Scystatic const char rcsid[] = 59275970Scy "$FreeBSD: stable/10/sbin/ifconfig/ifvlan.c 228641 2011-12-17 15:44:34Z bz $"; 60275970Scy#endif 61275970Scy 62275970Scy#define NOTAG ((u_short) -1) 63275970Scy 64275970Scystatic struct vlanreq params = { 65275970Scy .vlr_tag = NOTAG, 66275970Scy}; 67275970Scy 68275970Scystatic int 69275970Scygetvlan(int s, struct ifreq *ifr, struct vlanreq *vreq) 70275970Scy{ 71275970Scy bzero((char *)vreq, sizeof(*vreq)); 72275970Scy ifr->ifr_data = (caddr_t)vreq; 73275970Scy 74275970Scy return ioctl(s, SIOCGETVLAN, (caddr_t)ifr); 75275970Scy} 76275970Scy 77275970Scystatic void 78275970Scyvlan_status(int s) 79275970Scy{ 80275970Scy struct vlanreq vreq; 81275970Scy 82275970Scy if (getvlan(s, &ifr, &vreq) != -1) 83275970Scy printf("\tvlan: %d parent interface: %s\n", 84275970Scy vreq.vlr_tag, vreq.vlr_parent[0] == '\0' ? 85275970Scy "<none>" : vreq.vlr_parent); 86275970Scy} 87275970Scy 88275970Scystatic void 89275970Scyvlan_create(int s, struct ifreq *ifr) 90275970Scy{ 91275970Scy if (params.vlr_tag != NOTAG || params.vlr_parent[0] != '\0') { 92275970Scy /* 93275970Scy * One or both parameters were specified, make sure both. 94275970Scy */ 95275970Scy if (params.vlr_tag == NOTAG) 96275970Scy errx(1, "must specify a tag for vlan create"); 97275970Scy if (params.vlr_parent[0] == '\0') 98275970Scy errx(1, "must specify a parent device for vlan create"); 99275970Scy ifr->ifr_data = (caddr_t) ¶ms; 100275970Scy } 101275970Scy if (ioctl(s, SIOCIFCREATE2, ifr) < 0) 102275970Scy err(1, "SIOCIFCREATE2"); 103275970Scy} 104275970Scy 105275970Scystatic void 106275970Scyvlan_cb(int s, void *arg) 107275970Scy{ 108275970Scy if ((params.vlr_tag != NOTAG) ^ (params.vlr_parent[0] != '\0')) 109275970Scy errx(1, "both vlan and vlandev must be specified"); 110275970Scy} 111275970Scy 112275970Scystatic void 113275970Scyvlan_set(int s, struct ifreq *ifr) 114275970Scy{ 115275970Scy if (params.vlr_tag != NOTAG && params.vlr_parent[0] != '\0') { 116275970Scy ifr->ifr_data = (caddr_t) ¶ms; 117275970Scy if (ioctl(s, SIOCSETVLAN, (caddr_t)ifr) == -1) 118275970Scy err(1, "SIOCSETVLAN"); 119275970Scy } 120275970Scy} 121275970Scy 122275970Scystatic 123275970ScyDECL_CMD_FUNC(setvlantag, val, d) 124275970Scy{ 125275970Scy struct vlanreq vreq; 126275970Scy u_long ul; 127275970Scy char *endp; 128275970Scy 129275970Scy ul = strtoul(val, &endp, 0); 130275970Scy if (*endp != '\0') 131275970Scy errx(1, "invalid value for vlan"); 132275970Scy params.vlr_tag = ul; 133275970Scy /* check if the value can be represented in vlr_tag */ 134275970Scy if (params.vlr_tag != ul) 135275970Scy errx(1, "value for vlan out of range"); 136275970Scy 137275970Scy if (getvlan(s, &ifr, &vreq) != -1) 138275970Scy vlan_set(s, &ifr); 139275970Scy} 140275970Scy 141275970Scystatic 142275970ScyDECL_CMD_FUNC(setvlandev, val, d) 143275970Scy{ 144275970Scy struct vlanreq vreq; 145275970Scy 146275970Scy strlcpy(params.vlr_parent, val, sizeof(params.vlr_parent)); 147275970Scy 148275970Scy if (getvlan(s, &ifr, &vreq) != -1) 149275970Scy vlan_set(s, &ifr); 150275970Scy} 151275970Scy 152275970Scystatic 153275970ScyDECL_CMD_FUNC(unsetvlandev, val, d) 154275970Scy{ 155275970Scy struct vlanreq vreq; 156275970Scy 157275970Scy bzero((char *)&vreq, sizeof(struct vlanreq)); 158275970Scy ifr.ifr_data = (caddr_t)&vreq; 159275970Scy 160275970Scy if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) 161275970Scy err(1, "SIOCGETVLAN"); 162275970Scy 163275970Scy bzero((char *)&vreq.vlr_parent, sizeof(vreq.vlr_parent)); 164275970Scy vreq.vlr_tag = 0; 165275970Scy 166275970Scy if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) 167275970Scy err(1, "SIOCSETVLAN"); 168275970Scy} 169275970Scy 170275970Scystatic struct cmd vlan_cmds[] = { 171275970Scy DEF_CLONE_CMD_ARG("vlan", setvlantag), 172275970Scy DEF_CLONE_CMD_ARG("vlandev", setvlandev), 173275970Scy /* NB: non-clone cmds */ 174275970Scy DEF_CMD_ARG("vlan", setvlantag), 175275970Scy DEF_CMD_ARG("vlandev", setvlandev), 176275970Scy /* XXX For compatibility. Should become DEF_CMD() some day. */ 177275970Scy DEF_CMD_OPTARG("-vlandev", unsetvlandev), 178275970Scy DEF_CMD("vlanmtu", IFCAP_VLAN_MTU, setifcap), 179275970Scy DEF_CMD("-vlanmtu", -IFCAP_VLAN_MTU, setifcap), 180275970Scy DEF_CMD("vlanhwtag", IFCAP_VLAN_HWTAGGING, setifcap), 181275970Scy DEF_CMD("-vlanhwtag", -IFCAP_VLAN_HWTAGGING, setifcap), 182275970Scy DEF_CMD("vlanhwfilter", IFCAP_VLAN_HWFILTER, setifcap), 183275970Scy DEF_CMD("-vlanhwfilter", -IFCAP_VLAN_HWFILTER, setifcap), 184275970Scy DEF_CMD("-vlanhwtso", -IFCAP_VLAN_HWTSO, setifcap), 185275970Scy DEF_CMD("vlanhwtso", IFCAP_VLAN_HWTSO, setifcap), 186275970Scy DEF_CMD("vlanhwcsum", IFCAP_VLAN_HWCSUM, setifcap), 187275970Scy DEF_CMD("-vlanhwcsum", -IFCAP_VLAN_HWCSUM, setifcap), 188275970Scy}; 189275970Scystatic struct afswtch af_vlan = { 190275970Scy .af_name = "af_vlan", 191275970Scy .af_af = AF_UNSPEC, 192275970Scy .af_other_status = vlan_status, 193275970Scy}; 194275970Scy 195275970Scystatic __constructor void 196275970Scyvlan_ctor(void) 197275970Scy{ 198275970Scy#define N(a) (sizeof(a) / sizeof(a[0])) 199275970Scy size_t i; 200275970Scy 201275970Scy for (i = 0; i < N(vlan_cmds); i++) 202275970Scy cmd_register(&vlan_cmds[i]); 203275970Scy af_register(&af_vlan); 204275970Scy callback_register(vlan_cb, NULL); 205275970Scy clone_setdefcallback("vlan", vlan_create); 206275970Scy#undef N 207275970Scy} 208275970Scy