xref: /freebsd/sbin/ifconfig/ifvlan.c (revision 76df3c57a0abfd24652bfa33982ba136d9d0575b)
1df57947fSPedro F. Giffuni /*-
2df57947fSPedro F. Giffuni  * SPDX-License-Identifier: BSD-4-Clause
3df57947fSPedro F. Giffuni  *
42ccbbd06SMarcelo Araujo  * Copyright (c) 1999 Bill Paul <wpaul@ctr.columbia.edu>
52ccbbd06SMarcelo Araujo  * Copyright (c) 2012 ADARA Networks, Inc.
62ccbbd06SMarcelo Araujo  * All rights reserved.
72ccbbd06SMarcelo Araujo  *
82ccbbd06SMarcelo Araujo  * Portions of this software were developed by Robert N. M. Watson under
92ccbbd06SMarcelo Araujo  * contract to ADARA Networks, Inc.
1097ed1257SBill Paul  *
1197ed1257SBill Paul  * Redistribution and use in source and binary forms, with or without
1297ed1257SBill Paul  * modification, are permitted provided that the following conditions
1397ed1257SBill Paul  * are met:
1497ed1257SBill Paul  * 1. Redistributions of source code must retain the above copyright
1597ed1257SBill Paul  *    notice, this list of conditions and the following disclaimer.
1697ed1257SBill Paul  * 2. Redistributions in binary form must reproduce the above copyright
1797ed1257SBill Paul  *    notice, this list of conditions and the following disclaimer in the
1897ed1257SBill Paul  *    documentation and/or other materials provided with the distribution.
1997ed1257SBill Paul  * 3. All advertising materials mentioning features or use of this software
2097ed1257SBill Paul  *    must display the following acknowledgement:
2197ed1257SBill Paul  *	This product includes software developed by Bill Paul.
2297ed1257SBill Paul  * 4. Neither the name of the author nor the names of any co-contributors
2397ed1257SBill Paul  *    may be used to endorse or promote products derived from this software
2497ed1257SBill Paul  *    without specific prior written permission.
2597ed1257SBill Paul  *
2697ed1257SBill Paul  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
2797ed1257SBill Paul  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2897ed1257SBill Paul  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2997ed1257SBill Paul  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
3097ed1257SBill Paul  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3197ed1257SBill Paul  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3297ed1257SBill Paul  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3397ed1257SBill Paul  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3497ed1257SBill Paul  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3597ed1257SBill Paul  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
3697ed1257SBill Paul  * THE POSSIBILITY OF SUCH DAMAGE.
3797ed1257SBill Paul  */
3897ed1257SBill Paul 
3997ed1257SBill Paul #include <sys/param.h>
4097ed1257SBill Paul #include <sys/ioctl.h>
4197ed1257SBill Paul #include <sys/socket.h>
4297ed1257SBill Paul #include <sys/sockio.h>
4397ed1257SBill Paul 
4497ed1257SBill Paul #include <stdlib.h>
4597ed1257SBill Paul #include <unistd.h>
4697ed1257SBill Paul 
4797ed1257SBill Paul #include <net/ethernet.h>
4897ed1257SBill Paul #include <net/if.h>
4997ed1257SBill Paul #include <net/if_vlan_var.h>
5097ed1257SBill Paul #include <net/route.h>
5197ed1257SBill Paul 
5297ed1257SBill Paul #include <ctype.h>
5397ed1257SBill Paul #include <stdio.h>
5497ed1257SBill Paul #include <string.h>
5597ed1257SBill Paul #include <stdlib.h>
5697ed1257SBill Paul #include <unistd.h>
5797ed1257SBill Paul #include <err.h>
5897ed1257SBill Paul #include <errno.h>
5997ed1257SBill Paul 
6097ed1257SBill Paul #include "ifconfig.h"
6197ed1257SBill Paul 
62db82353dSSam Leffler #define	NOTAG	((u_short) -1)
63*76df3c57SZhenlei Huang #define	NOPROTO	((u_short) -1)
64db82353dSSam Leffler 
65c7cffd65SAlexander V. Chernikov static const char proto_8021Q[]  = "802.1q";
66c7cffd65SAlexander V. Chernikov static const char proto_8021ad[] = "802.1ad";
67b84d0aaaSAllan Jude static const char proto_qinq[] = "qinq";
68c7cffd65SAlexander V. Chernikov 
69db82353dSSam Leffler static 	struct vlanreq params = {
70db82353dSSam Leffler 	.vlr_tag	= NOTAG,
71*76df3c57SZhenlei Huang 	.vlr_proto	= NOPROTO,
72db82353dSSam Leffler };
73db82353dSSam Leffler 
745faf8dcbSSam Leffler static void
vlan_status(if_ctx * ctx)756e3a9d7fSAlexander V. Chernikov vlan_status(if_ctx *ctx)
7697ed1257SBill Paul {
777fa282e6SAlexander V. Chernikov 	struct vlanreq vreq = {};
787fa282e6SAlexander V. Chernikov 	struct ifreq ifr = { .ifr_data = (caddr_t)&vreq };
7997ed1257SBill Paul 
807fa282e6SAlexander V. Chernikov 	if (ioctl_ctx_ifr(ctx, SIOCGETVLAN, &ifr) == -1)
812ccbbd06SMarcelo Araujo 		return;
822ccbbd06SMarcelo Araujo 	printf("\tvlan: %d", vreq.vlr_tag);
83c7cffd65SAlexander V. Chernikov 	printf(" vlanproto: ");
84c7cffd65SAlexander V. Chernikov 	switch (vreq.vlr_proto) {
85c7cffd65SAlexander V. Chernikov 		case ETHERTYPE_VLAN:
86c7cffd65SAlexander V. Chernikov 			printf(proto_8021Q);
87c7cffd65SAlexander V. Chernikov 			break;
88c7cffd65SAlexander V. Chernikov 		case ETHERTYPE_QINQ:
89c7cffd65SAlexander V. Chernikov 			printf(proto_8021ad);
90c7cffd65SAlexander V. Chernikov 			break;
91c7cffd65SAlexander V. Chernikov 		default:
92c7cffd65SAlexander V. Chernikov 			printf("0x%04x", vreq.vlr_proto);
93c7cffd65SAlexander V. Chernikov 	}
947fa282e6SAlexander V. Chernikov 	if (ioctl_ctx_ifr(ctx, SIOCGVLANPCP, &ifr) != -1)
952ccbbd06SMarcelo Araujo 		printf(" vlanpcp: %u", ifr.ifr_vlan_pcp);
962ccbbd06SMarcelo Araujo 	printf(" parent interface: %s", vreq.vlr_parent[0] == '\0' ?
9797ed1257SBill Paul 	    "<none>" : vreq.vlr_parent);
982ccbbd06SMarcelo Araujo 	printf("\n");
9997ed1257SBill Paul }
10097ed1257SBill Paul 
101c7cffd65SAlexander V. Chernikov static int
vlan_match_ethervid(const char * name)102c7cffd65SAlexander V. Chernikov vlan_match_ethervid(const char *name)
103c7cffd65SAlexander V. Chernikov {
104c7cffd65SAlexander V. Chernikov 	return (strchr(name, '.') != NULL);
105c7cffd65SAlexander V. Chernikov }
106c7cffd65SAlexander V. Chernikov 
107c7cffd65SAlexander V. Chernikov static void
vlan_parse_ethervid(const char * name)108c7cffd65SAlexander V. Chernikov vlan_parse_ethervid(const char *name)
109c7cffd65SAlexander V. Chernikov {
110c7cffd65SAlexander V. Chernikov 	char ifname[IFNAMSIZ];
111c7cffd65SAlexander V. Chernikov 	char *cp;
11228b498e6SZhenlei Huang 	unsigned int vid;
113c7cffd65SAlexander V. Chernikov 
114c7cffd65SAlexander V. Chernikov 	strlcpy(ifname, name, IFNAMSIZ);
115c7cffd65SAlexander V. Chernikov 	if ((cp = strrchr(ifname, '.')) == NULL)
116c7cffd65SAlexander V. Chernikov 		return;
117c7cffd65SAlexander V. Chernikov 	/*
118c7cffd65SAlexander V. Chernikov 	 * Derive params from interface name: "parent.vid".
119c7cffd65SAlexander V. Chernikov 	 */
120c7cffd65SAlexander V. Chernikov 	*cp++ = '\0';
121c7cffd65SAlexander V. Chernikov 	if ((*cp < '1') || (*cp > '9'))
122c7cffd65SAlexander V. Chernikov 		errx(1, "invalid vlan tag");
123c7cffd65SAlexander V. Chernikov 
124c7cffd65SAlexander V. Chernikov 	vid = *cp++ - '0';
12528b498e6SZhenlei Huang 	while ((*cp >= '0') && (*cp <= '9')) {
126c7cffd65SAlexander V. Chernikov 		vid = (vid * 10) + (*cp++ - '0');
12728b498e6SZhenlei Huang 		if (vid >= 0xFFF)
12828b498e6SZhenlei Huang 			errx(1, "invalid vlan tag");
12928b498e6SZhenlei Huang 	}
13028b498e6SZhenlei Huang 	if (*cp != '\0')
131c7cffd65SAlexander V. Chernikov 		errx(1, "invalid vlan tag");
132c7cffd65SAlexander V. Chernikov 
133779fd053SAlexander V. Chernikov 	/*
134779fd053SAlexander V. Chernikov 	 * allow "devX.Y vlandev devX vlan Y" syntax
135779fd053SAlexander V. Chernikov 	 */
136779fd053SAlexander V. Chernikov 	if (params.vlr_tag == NOTAG || params.vlr_tag == vid)
137779fd053SAlexander V. Chernikov 		params.vlr_tag = vid;
138779fd053SAlexander V. Chernikov 	else
139779fd053SAlexander V. Chernikov 		errx(1, "ambiguous vlan specification");
140779fd053SAlexander V. Chernikov 
141779fd053SAlexander V. Chernikov 	/* Restrict overriding interface name */
142779fd053SAlexander V. Chernikov 	if (params.vlr_parent[0] == '\0' || !strcmp(params.vlr_parent, ifname))
143c7cffd65SAlexander V. Chernikov 		strlcpy(params.vlr_parent, ifname, IFNAMSIZ);
144779fd053SAlexander V. Chernikov 	else
145779fd053SAlexander V. Chernikov 		errx(1, "ambiguous vlan specification");
146c7cffd65SAlexander V. Chernikov }
147c7cffd65SAlexander V. Chernikov 
1485faf8dcbSSam Leffler static void
vlan_create(if_ctx * ctx,struct ifreq * ifr)14974b42611SAlexander V. Chernikov vlan_create(if_ctx *ctx, struct ifreq *ifr)
15097ed1257SBill Paul {
151c7cffd65SAlexander V. Chernikov 	vlan_parse_ethervid(ifr->ifr_name);
152c7cffd65SAlexander V. Chernikov 
153db82353dSSam Leffler 	if (params.vlr_tag != NOTAG || params.vlr_parent[0] != '\0') {
154db82353dSSam Leffler 		/*
155db82353dSSam Leffler 		 * One or both parameters were specified, make sure both.
156db82353dSSam Leffler 		 */
157db82353dSSam Leffler 		if (params.vlr_tag == NOTAG)
158db82353dSSam Leffler 			errx(1, "must specify a tag for vlan create");
159db82353dSSam Leffler 		if (params.vlr_parent[0] == '\0')
160db82353dSSam Leffler 			errx(1, "must specify a parent device for vlan create");
161*76df3c57SZhenlei Huang 		if (params.vlr_proto == NOPROTO)
162*76df3c57SZhenlei Huang 			params.vlr_proto = ETHERTYPE_VLAN;
163db82353dSSam Leffler 		ifr->ifr_data = (caddr_t) &params;
16497ed1257SBill Paul 	}
16574b42611SAlexander V. Chernikov 	ifcreate_ioctl(ctx, ifr);
1667fc2ce8aSYaroslav Tykhiy }
16797ed1257SBill Paul 
1687fc2ce8aSYaroslav Tykhiy static void
vlan_cb(if_ctx * ctx __unused,void * arg __unused)16974b42611SAlexander V. Chernikov vlan_cb(if_ctx *ctx __unused, void *arg __unused)
1707fc2ce8aSYaroslav Tykhiy {
171db82353dSSam Leffler 	if ((params.vlr_tag != NOTAG) ^ (params.vlr_parent[0] != '\0'))
1727fc2ce8aSYaroslav Tykhiy 		errx(1, "both vlan and vlandev must be specified");
1732fe9aa26SYaroslav Tykhiy }
1742fe9aa26SYaroslav Tykhiy 
1752fe9aa26SYaroslav Tykhiy static void
vlan_set(int s,struct ifreq * ifr)176db82353dSSam Leffler vlan_set(int s, struct ifreq *ifr)
1772fe9aa26SYaroslav Tykhiy {
178db82353dSSam Leffler 	if (params.vlr_tag != NOTAG && params.vlr_parent[0] != '\0') {
179*76df3c57SZhenlei Huang 		if (params.vlr_proto == NOPROTO)
180*76df3c57SZhenlei Huang 			params.vlr_proto = ETHERTYPE_VLAN;
181db82353dSSam Leffler 		ifr->ifr_data = (caddr_t) &params;
182db82353dSSam Leffler 		if (ioctl(s, SIOCSETVLAN, (caddr_t)ifr) == -1)
1837fc2ce8aSYaroslav Tykhiy 			err(1, "SIOCSETVLAN");
1847fc2ce8aSYaroslav Tykhiy 	}
18597ed1257SBill Paul }
1865faf8dcbSSam Leffler 
1876e3a9d7fSAlexander V. Chernikov static void
setvlantag(if_ctx * ctx,const char * val,int dummy __unused)1886e3a9d7fSAlexander V. Chernikov setvlantag(if_ctx *ctx, const char *val, int dummy __unused)
189db82353dSSam Leffler {
1907fa282e6SAlexander V. Chernikov 	struct vlanreq vreq = {};
1917fa282e6SAlexander V. Chernikov 	struct ifreq ifr = { .ifr_data = (caddr_t)&vreq };
192db82353dSSam Leffler 	u_long ul;
193db82353dSSam Leffler 	char *endp;
194db82353dSSam Leffler 
195db82353dSSam Leffler 	ul = strtoul(val, &endp, 0);
196db82353dSSam Leffler 	if (*endp != '\0')
197db82353dSSam Leffler 		errx(1, "invalid value for vlan");
198db82353dSSam Leffler 	params.vlr_tag = ul;
199db82353dSSam Leffler 	/* check if the value can be represented in vlr_tag */
200db82353dSSam Leffler 	if (params.vlr_tag != ul)
201db82353dSSam Leffler 		errx(1, "value for vlan out of range");
202db82353dSSam Leffler 
2037fa282e6SAlexander V. Chernikov 	if (ioctl_ctx_ifr(ctx, SIOCGETVLAN, &ifr) != -1) {
204*76df3c57SZhenlei Huang 		/*
205*76df3c57SZhenlei Huang 		 * Retrieve the current settings if the interface has already
206*76df3c57SZhenlei Huang 		 * been configured.
207*76df3c57SZhenlei Huang 		 */
208*76df3c57SZhenlei Huang 		if (vreq.vlr_parent[0] != '\0') {
209*76df3c57SZhenlei Huang 			if (params.vlr_parent[0] == '\0')
210*76df3c57SZhenlei Huang 				strlcpy(params.vlr_parent, vreq.vlr_parent, IFNAMSIZ);
211*76df3c57SZhenlei Huang 			if (params.vlr_proto == NOPROTO)
212*76df3c57SZhenlei Huang 				params.vlr_proto = vreq.vlr_proto;
213*76df3c57SZhenlei Huang 		}
2146e3a9d7fSAlexander V. Chernikov 		vlan_set(ctx->io_s, &ifr);
215db82353dSSam Leffler 	}
216b82b8055SKristof Provost }
217db82353dSSam Leffler 
2186e3a9d7fSAlexander V. Chernikov static void
setvlandev(if_ctx * ctx,const char * val,int dummy __unused)2196e3a9d7fSAlexander V. Chernikov setvlandev(if_ctx *ctx, const char *val, int dummy __unused)
220db82353dSSam Leffler {
2217fa282e6SAlexander V. Chernikov 	struct vlanreq vreq = {};
2227fa282e6SAlexander V. Chernikov 	struct ifreq ifr = { .ifr_data = (caddr_t)&vreq };
223db82353dSSam Leffler 
224db82353dSSam Leffler 	strlcpy(params.vlr_parent, val, sizeof(params.vlr_parent));
22567207b69SSam Leffler 
2267fa282e6SAlexander V. Chernikov 	if (ioctl_ctx_ifr(ctx, SIOCGETVLAN, &ifr) != -1)
2276e3a9d7fSAlexander V. Chernikov 		vlan_set(ctx->io_s, &ifr);
228db82353dSSam Leffler }
229db82353dSSam Leffler 
2306e3a9d7fSAlexander V. Chernikov static void
setvlanproto(if_ctx * ctx,const char * val,int dummy __unused)2316e3a9d7fSAlexander V. Chernikov setvlanproto(if_ctx *ctx, const char *val, int dummy __unused)
232c7cffd65SAlexander V. Chernikov {
2337fa282e6SAlexander V. Chernikov 	struct vlanreq vreq = {};
2347fa282e6SAlexander V. Chernikov 	struct ifreq ifr = { .ifr_data = (caddr_t)&vreq };
235c7cffd65SAlexander V. Chernikov 
236c7cffd65SAlexander V. Chernikov 	if (strncasecmp(proto_8021Q, val,
237c7cffd65SAlexander V. Chernikov 	    strlen(proto_8021Q)) == 0) {
238c7cffd65SAlexander V. Chernikov 		params.vlr_proto = ETHERTYPE_VLAN;
239b84d0aaaSAllan Jude 	} else if ((strncasecmp(proto_8021ad, val, strlen(proto_8021ad)) == 0)
240b84d0aaaSAllan Jude 	    || (strncasecmp(proto_qinq, val, strlen(proto_qinq)) == 0)) {
241c7cffd65SAlexander V. Chernikov 		params.vlr_proto = ETHERTYPE_QINQ;
242c7cffd65SAlexander V. Chernikov 	} else
243c7cffd65SAlexander V. Chernikov 		errx(1, "invalid value for vlanproto");
244c7cffd65SAlexander V. Chernikov 
2457fa282e6SAlexander V. Chernikov 	if (ioctl_ctx_ifr(ctx, SIOCGETVLAN, &ifr) != -1) {
246*76df3c57SZhenlei Huang 		/*
247*76df3c57SZhenlei Huang 		 * Retrieve the current settings if the interface has already
248*76df3c57SZhenlei Huang 		 * been configured.
249*76df3c57SZhenlei Huang 		 */
250*76df3c57SZhenlei Huang 		if (vreq.vlr_parent[0] != '\0') {
251*76df3c57SZhenlei Huang 			if (params.vlr_parent[0] == '\0')
252*76df3c57SZhenlei Huang 				strlcpy(params.vlr_parent, vreq.vlr_parent, IFNAMSIZ);
253*76df3c57SZhenlei Huang 			if (params.vlr_tag == NOTAG)
254*76df3c57SZhenlei Huang 				params.vlr_tag = vreq.vlr_tag;
255*76df3c57SZhenlei Huang 		}
2566e3a9d7fSAlexander V. Chernikov 		vlan_set(ctx->io_s, &ifr);
257c7cffd65SAlexander V. Chernikov 	}
258b82b8055SKristof Provost }
259c7cffd65SAlexander V. Chernikov 
2606e3a9d7fSAlexander V. Chernikov static void
setvlanpcp(if_ctx * ctx,const char * val,int dummy __unused)2616e3a9d7fSAlexander V. Chernikov setvlanpcp(if_ctx *ctx, const char *val, int dummy __unused)
2622ccbbd06SMarcelo Araujo {
2632ccbbd06SMarcelo Araujo 	u_long ul;
2642ccbbd06SMarcelo Araujo 	char *endp;
2657fa282e6SAlexander V. Chernikov 	struct ifreq ifr = {};
2662ccbbd06SMarcelo Araujo 
2672ccbbd06SMarcelo Araujo 	ul = strtoul(val, &endp, 0);
2682ccbbd06SMarcelo Araujo 	if (*endp != '\0')
2692ccbbd06SMarcelo Araujo 		errx(1, "invalid value for vlanpcp");
2702ccbbd06SMarcelo Araujo 	if (ul > 7)
2712ccbbd06SMarcelo Araujo 		errx(1, "value for vlanpcp out of range");
2722ccbbd06SMarcelo Araujo 	ifr.ifr_vlan_pcp = ul;
2737fa282e6SAlexander V. Chernikov 	if (ioctl_ctx_ifr(ctx, SIOCSVLANPCP, &ifr) == -1)
2742ccbbd06SMarcelo Araujo 		err(1, "SIOCSVLANPCP");
2752ccbbd06SMarcelo Araujo }
2762ccbbd06SMarcelo Araujo 
2776e3a9d7fSAlexander V. Chernikov static void
unsetvlandev(if_ctx * ctx,const char * val __unused,int dummy __unused)2780c2beef7SAlexander V. Chernikov unsetvlandev(if_ctx *ctx, const char *val __unused, int dummy __unused)
279db82353dSSam Leffler {
2807fa282e6SAlexander V. Chernikov 	struct vlanreq vreq = {};
2817fa282e6SAlexander V. Chernikov 	struct ifreq ifr = { .ifr_data = (caddr_t)&vreq };
282db82353dSSam Leffler 
2837fa282e6SAlexander V. Chernikov 	if (ioctl_ctx_ifr(ctx, SIOCGETVLAN, &ifr) == -1)
284db82353dSSam Leffler 		err(1, "SIOCGETVLAN");
285db82353dSSam Leffler 
286db82353dSSam Leffler 	bzero((char *)&vreq.vlr_parent, sizeof(vreq.vlr_parent));
287db82353dSSam Leffler 	vreq.vlr_tag = 0;
288db82353dSSam Leffler 
2897fa282e6SAlexander V. Chernikov 	if (ioctl_ctx(ctx, SIOCSETVLAN, (caddr_t)&ifr) == -1)
290db82353dSSam Leffler 		err(1, "SIOCSETVLAN");
291db82353dSSam Leffler }
292db82353dSSam Leffler 
2935faf8dcbSSam Leffler static struct cmd vlan_cmds[] = {
29467207b69SSam Leffler 	DEF_CLONE_CMD_ARG("vlan",			setvlantag),
29567207b69SSam Leffler 	DEF_CLONE_CMD_ARG("vlandev",			setvlandev),
296c7cffd65SAlexander V. Chernikov 	DEF_CLONE_CMD_ARG("vlanproto",			setvlanproto),
2972ccbbd06SMarcelo Araujo 	DEF_CMD_ARG("vlanpcp",				setvlanpcp),
29824994b36SSam Leffler 	/* NB: non-clone cmds */
29924994b36SSam Leffler 	DEF_CMD_ARG("vlan",				setvlantag),
30024994b36SSam Leffler 	DEF_CMD_ARG("vlandev",				setvlandev),
301c7cffd65SAlexander V. Chernikov 	DEF_CMD_ARG("vlanproto",			setvlanproto),
302b0dcc11cSYaroslav Tykhiy 	/* XXX For compatibility.  Should become DEF_CMD() some day. */
303b0dcc11cSYaroslav Tykhiy 	DEF_CMD_OPTARG("-vlandev",			unsetvlandev),
3045faf8dcbSSam Leffler 	DEF_CMD("vlanmtu",	IFCAP_VLAN_MTU,		setifcap),
30508992b20SJohn Baldwin 	DEF_CMD("-vlanmtu",	IFCAP_VLAN_MTU,		clearifcap),
3065faf8dcbSSam Leffler 	DEF_CMD("vlanhwtag",	IFCAP_VLAN_HWTAGGING,	setifcap),
30708992b20SJohn Baldwin 	DEF_CMD("-vlanhwtag",	IFCAP_VLAN_HWTAGGING,	clearifcap),
308eafbb00dSJack F Vogel 	DEF_CMD("vlanhwfilter",	IFCAP_VLAN_HWFILTER,	setifcap),
30908992b20SJohn Baldwin 	DEF_CMD("-vlanhwfilter", IFCAP_VLAN_HWFILTER,	clearifcap),
3100f686c0fSPyun YongHyeon 	DEF_CMD("vlanhwtso",	IFCAP_VLAN_HWTSO,	setifcap),
311c079bcbcSEd Maste 	DEF_CMD("-vlanhwtso",	IFCAP_VLAN_HWTSO,	clearifcap),
3129b776960SBjoern A. Zeeb 	DEF_CMD("vlanhwcsum",	IFCAP_VLAN_HWCSUM,	setifcap),
31308992b20SJohn Baldwin 	DEF_CMD("-vlanhwcsum",	IFCAP_VLAN_HWCSUM,	clearifcap),
3145faf8dcbSSam Leffler };
3155faf8dcbSSam Leffler static struct afswtch af_vlan = {
3165faf8dcbSSam Leffler 	.af_name	= "af_vlan",
3175faf8dcbSSam Leffler 	.af_af		= AF_UNSPEC,
31890c4b74cSSam Leffler 	.af_other_status = vlan_status,
3195faf8dcbSSam Leffler };
3205faf8dcbSSam Leffler 
3215faf8dcbSSam Leffler static __constructor void
vlan_ctor(void)3225faf8dcbSSam Leffler vlan_ctor(void)
3235faf8dcbSSam Leffler {
324b59dcaeeSXin LI 	size_t i;
3255faf8dcbSSam Leffler 
326abd71050SEnji Cooper 	for (i = 0; i < nitems(vlan_cmds);  i++)
3275faf8dcbSSam Leffler 		cmd_register(&vlan_cmds[i]);
3285faf8dcbSSam Leffler 	af_register(&af_vlan);
3297fc2ce8aSYaroslav Tykhiy 	callback_register(vlan_cb, NULL);
330c7cffd65SAlexander V. Chernikov 	clone_setdefcallback_prefix("vlan", vlan_create);
331c7cffd65SAlexander V. Chernikov 	clone_setdefcallback_filter(vlan_match_ethervid, vlan_create);
3325faf8dcbSSam Leffler }
333