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) ¶ms;
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) ¶ms;
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