xref: /minix3/sbin/ifconfig/vlan.c (revision 90b801219a391518dca4b04b17c88ad3b82b6ad9)
1*90b80121SDavid van Moolenbroek /*	$NetBSD: vlan.c,v 1.14 2014/09/15 06:46:04 ozaki-r Exp $	*/
2*90b80121SDavid van Moolenbroek 
3*90b80121SDavid van Moolenbroek /*
4*90b80121SDavid van Moolenbroek  * Copyright (c) 1983, 1993
5*90b80121SDavid van Moolenbroek  *      The Regents of the University of California.  All rights reserved.
6*90b80121SDavid van Moolenbroek  *
7*90b80121SDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
8*90b80121SDavid van Moolenbroek  * modification, are permitted provided that the following conditions
9*90b80121SDavid van Moolenbroek  * are met:
10*90b80121SDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
11*90b80121SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer.
12*90b80121SDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright
13*90b80121SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer in the
14*90b80121SDavid van Moolenbroek  *    documentation and/or other materials provided with the distribution.
15*90b80121SDavid van Moolenbroek  * 3. Neither the name of the University nor the names of its contributors
16*90b80121SDavid van Moolenbroek  *    may be used to endorse or promote products derived from this software
17*90b80121SDavid van Moolenbroek  *    without specific prior written permission.
18*90b80121SDavid van Moolenbroek  *
19*90b80121SDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20*90b80121SDavid van Moolenbroek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*90b80121SDavid van Moolenbroek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*90b80121SDavid van Moolenbroek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23*90b80121SDavid van Moolenbroek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*90b80121SDavid van Moolenbroek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*90b80121SDavid van Moolenbroek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*90b80121SDavid van Moolenbroek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*90b80121SDavid van Moolenbroek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*90b80121SDavid van Moolenbroek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*90b80121SDavid van Moolenbroek  * SUCH DAMAGE.
30*90b80121SDavid van Moolenbroek  */
31*90b80121SDavid van Moolenbroek 
32*90b80121SDavid van Moolenbroek #include <sys/cdefs.h>
33*90b80121SDavid van Moolenbroek #ifndef lint
34*90b80121SDavid van Moolenbroek __RCSID("$NetBSD: vlan.c,v 1.14 2014/09/15 06:46:04 ozaki-r Exp $");
35*90b80121SDavid van Moolenbroek #endif /* not lint */
36*90b80121SDavid van Moolenbroek 
37*90b80121SDavid van Moolenbroek #include <sys/param.h>
38*90b80121SDavid van Moolenbroek #include <sys/ioctl.h>
39*90b80121SDavid van Moolenbroek 
40*90b80121SDavid van Moolenbroek #include <net/if.h>
41*90b80121SDavid van Moolenbroek #include <net/if_ether.h>
42*90b80121SDavid van Moolenbroek #include <net/if_vlanvar.h>
43*90b80121SDavid van Moolenbroek 
44*90b80121SDavid van Moolenbroek #include <ctype.h>
45*90b80121SDavid van Moolenbroek #include <err.h>
46*90b80121SDavid van Moolenbroek #include <errno.h>
47*90b80121SDavid van Moolenbroek #include <string.h>
48*90b80121SDavid van Moolenbroek #include <stdlib.h>
49*90b80121SDavid van Moolenbroek #include <stdio.h>
50*90b80121SDavid van Moolenbroek #include <util.h>
51*90b80121SDavid van Moolenbroek 
52*90b80121SDavid van Moolenbroek #include "env.h"
53*90b80121SDavid van Moolenbroek #include "extern.h"
54*90b80121SDavid van Moolenbroek #include "util.h"
55*90b80121SDavid van Moolenbroek 
56*90b80121SDavid van Moolenbroek static status_func_t status;
57*90b80121SDavid van Moolenbroek static usage_func_t usage;
58*90b80121SDavid van Moolenbroek static cmdloop_branch_t branch;
59*90b80121SDavid van Moolenbroek 
60*90b80121SDavid van Moolenbroek static void vlan_constructor(void) __attribute__((constructor));
61*90b80121SDavid van Moolenbroek static void vlan_status(prop_dictionary_t, prop_dictionary_t);
62*90b80121SDavid van Moolenbroek 
63*90b80121SDavid van Moolenbroek static int setvlan(prop_dictionary_t, prop_dictionary_t);
64*90b80121SDavid van Moolenbroek static int setvlanif(prop_dictionary_t, prop_dictionary_t);
65*90b80121SDavid van Moolenbroek 
66*90b80121SDavid van Moolenbroek struct pinteger vlantag = PINTEGER_INITIALIZER1(&vlantag, "VLAN tag",
67*90b80121SDavid van Moolenbroek     0, USHRT_MAX, 10, setvlan, "vlantag", &command_root.pb_parser);
68*90b80121SDavid van Moolenbroek 
69*90b80121SDavid van Moolenbroek struct piface vlanif = PIFACE_INITIALIZER(&vlanif, "vlanif", setvlanif,
70*90b80121SDavid van Moolenbroek     "vlanif", &command_root.pb_parser);
71*90b80121SDavid van Moolenbroek 
72*90b80121SDavid van Moolenbroek static const struct kwinst vlankw[] = {
73*90b80121SDavid van Moolenbroek 	  {.k_word = "vlan", .k_nextparser = &vlantag.pi_parser}
74*90b80121SDavid van Moolenbroek 	, {.k_word = "vlanif", .k_act = "vlantag",
75*90b80121SDavid van Moolenbroek 	   .k_nextparser = &vlanif.pif_parser}
76*90b80121SDavid van Moolenbroek 	, {.k_word = "-vlanif", .k_key = "vlanif", .k_type = KW_T_STR,
77*90b80121SDavid van Moolenbroek 	   .k_str = "", .k_exec = setvlanif}
78*90b80121SDavid van Moolenbroek };
79*90b80121SDavid van Moolenbroek 
80*90b80121SDavid van Moolenbroek struct pkw vlan = PKW_INITIALIZER(&vlan, "vlan", NULL, NULL,
81*90b80121SDavid van Moolenbroek     vlankw, __arraycount(vlankw), NULL);
82*90b80121SDavid van Moolenbroek 
83*90b80121SDavid van Moolenbroek static int
checkifname(prop_dictionary_t env)84*90b80121SDavid van Moolenbroek checkifname(prop_dictionary_t env)
85*90b80121SDavid van Moolenbroek {
86*90b80121SDavid van Moolenbroek 	const char *ifname;
87*90b80121SDavid van Moolenbroek 
88*90b80121SDavid van Moolenbroek 	if ((ifname = getifname(env)) == NULL)
89*90b80121SDavid van Moolenbroek 		return 1;
90*90b80121SDavid van Moolenbroek 
91*90b80121SDavid van Moolenbroek 	return strncmp(ifname, "vlan", 4) != 0 ||
92*90b80121SDavid van Moolenbroek 	    !isdigit((unsigned char)ifname[4]);
93*90b80121SDavid van Moolenbroek }
94*90b80121SDavid van Moolenbroek 
95*90b80121SDavid van Moolenbroek static int
getvlan(prop_dictionary_t env,struct vlanreq * vlr,bool quiet)96*90b80121SDavid van Moolenbroek getvlan(prop_dictionary_t env, struct vlanreq *vlr, bool quiet)
97*90b80121SDavid van Moolenbroek {
98*90b80121SDavid van Moolenbroek 	memset(vlr, 0, sizeof(*vlr));
99*90b80121SDavid van Moolenbroek 
100*90b80121SDavid van Moolenbroek 	if (checkifname(env)) {
101*90b80121SDavid van Moolenbroek 		if (quiet)
102*90b80121SDavid van Moolenbroek 			return -1;
103*90b80121SDavid van Moolenbroek 		errx(EXIT_FAILURE, "valid only with vlan(4) interfaces");
104*90b80121SDavid van Moolenbroek 	}
105*90b80121SDavid van Moolenbroek 
106*90b80121SDavid van Moolenbroek 	if (indirect_ioctl(env, SIOCGETVLAN, vlr) == -1)
107*90b80121SDavid van Moolenbroek 		return -1;
108*90b80121SDavid van Moolenbroek 
109*90b80121SDavid van Moolenbroek 	return 0;
110*90b80121SDavid van Moolenbroek }
111*90b80121SDavid van Moolenbroek 
112*90b80121SDavid van Moolenbroek int
setvlan(prop_dictionary_t env,prop_dictionary_t oenv)113*90b80121SDavid van Moolenbroek setvlan(prop_dictionary_t env, prop_dictionary_t oenv)
114*90b80121SDavid van Moolenbroek {
115*90b80121SDavid van Moolenbroek 	struct vlanreq vlr;
116*90b80121SDavid van Moolenbroek 	int64_t tag;
117*90b80121SDavid van Moolenbroek 
118*90b80121SDavid van Moolenbroek 	if (getvlan(env, &vlr, false) == -1)
119*90b80121SDavid van Moolenbroek 		err(EXIT_FAILURE, "%s: getvlan", __func__);
120*90b80121SDavid van Moolenbroek 
121*90b80121SDavid van Moolenbroek 	if (!prop_dictionary_get_int64(env, "vlantag", &tag)) {
122*90b80121SDavid van Moolenbroek 		errno = ENOENT;
123*90b80121SDavid van Moolenbroek 		return -1;
124*90b80121SDavid van Moolenbroek 	}
125*90b80121SDavid van Moolenbroek 
126*90b80121SDavid van Moolenbroek 	vlr.vlr_tag = tag;
127*90b80121SDavid van Moolenbroek 
128*90b80121SDavid van Moolenbroek 	if (indirect_ioctl(env, SIOCSETVLAN, &vlr) == -1)
129*90b80121SDavid van Moolenbroek 		err(EXIT_FAILURE, "SIOCSETVLAN");
130*90b80121SDavid van Moolenbroek 	return 0;
131*90b80121SDavid van Moolenbroek }
132*90b80121SDavid van Moolenbroek 
133*90b80121SDavid van Moolenbroek int
setvlanif(prop_dictionary_t env,prop_dictionary_t oenv)134*90b80121SDavid van Moolenbroek setvlanif(prop_dictionary_t env, prop_dictionary_t oenv)
135*90b80121SDavid van Moolenbroek {
136*90b80121SDavid van Moolenbroek 	struct vlanreq vlr;
137*90b80121SDavid van Moolenbroek 	const char *parent;
138*90b80121SDavid van Moolenbroek 	int64_t tag;
139*90b80121SDavid van Moolenbroek 
140*90b80121SDavid van Moolenbroek 	if (getvlan(env, &vlr, false) == -1)
141*90b80121SDavid van Moolenbroek 		err(EXIT_FAILURE, "%s: getsock", __func__);
142*90b80121SDavid van Moolenbroek 
143*90b80121SDavid van Moolenbroek 	if (!prop_dictionary_get_cstring_nocopy(env, "vlanif", &parent)) {
144*90b80121SDavid van Moolenbroek 		errno = ENOENT;
145*90b80121SDavid van Moolenbroek 		return -1;
146*90b80121SDavid van Moolenbroek 	}
147*90b80121SDavid van Moolenbroek 	strlcpy(vlr.vlr_parent, parent, sizeof(vlr.vlr_parent));
148*90b80121SDavid van Moolenbroek 	if (strcmp(parent, "") == 0)
149*90b80121SDavid van Moolenbroek 		;
150*90b80121SDavid van Moolenbroek 	else if (!prop_dictionary_get_int64(env, "vlantag", &tag)) {
151*90b80121SDavid van Moolenbroek 		errno = ENOENT;
152*90b80121SDavid van Moolenbroek 		return -1;
153*90b80121SDavid van Moolenbroek 	} else
154*90b80121SDavid van Moolenbroek 		vlr.vlr_tag = (unsigned short)tag;
155*90b80121SDavid van Moolenbroek 
156*90b80121SDavid van Moolenbroek 	if (indirect_ioctl(env, SIOCSETVLAN, &vlr) == -1)
157*90b80121SDavid van Moolenbroek 		err(EXIT_FAILURE, "SIOCSETVLAN");
158*90b80121SDavid van Moolenbroek 	return 0;
159*90b80121SDavid van Moolenbroek }
160*90b80121SDavid van Moolenbroek 
161*90b80121SDavid van Moolenbroek static void
vlan_status(prop_dictionary_t env,prop_dictionary_t oenv)162*90b80121SDavid van Moolenbroek vlan_status(prop_dictionary_t env, prop_dictionary_t oenv)
163*90b80121SDavid van Moolenbroek {
164*90b80121SDavid van Moolenbroek 	struct vlanreq vlr;
165*90b80121SDavid van Moolenbroek 
166*90b80121SDavid van Moolenbroek 	if (getvlan(env, &vlr, true) == -1)
167*90b80121SDavid van Moolenbroek 		return;
168*90b80121SDavid van Moolenbroek 
169*90b80121SDavid van Moolenbroek 	if (vlr.vlr_tag || vlr.vlr_parent[0] != '\0')
170*90b80121SDavid van Moolenbroek 		printf("\tvlan: %d parent: %s\n",
171*90b80121SDavid van Moolenbroek 		    vlr.vlr_tag, vlr.vlr_parent[0] == '\0' ?
172*90b80121SDavid van Moolenbroek 		    "<none>" : vlr.vlr_parent);
173*90b80121SDavid van Moolenbroek }
174*90b80121SDavid van Moolenbroek 
175*90b80121SDavid van Moolenbroek static void
vlan_usage(prop_dictionary_t env)176*90b80121SDavid van Moolenbroek vlan_usage(prop_dictionary_t env)
177*90b80121SDavid van Moolenbroek {
178*90b80121SDavid van Moolenbroek 	fprintf(stderr, "\t[ vlan n vlanif i ] [ -vlanif i ]\n");
179*90b80121SDavid van Moolenbroek }
180*90b80121SDavid van Moolenbroek 
181*90b80121SDavid van Moolenbroek static void
vlan_constructor(void)182*90b80121SDavid van Moolenbroek vlan_constructor(void)
183*90b80121SDavid van Moolenbroek {
184*90b80121SDavid van Moolenbroek 	cmdloop_branch_init(&branch, &vlan.pk_parser);
185*90b80121SDavid van Moolenbroek 	register_cmdloop_branch(&branch);
186*90b80121SDavid van Moolenbroek 	status_func_init(&status, vlan_status);
187*90b80121SDavid van Moolenbroek 	usage_func_init(&usage, vlan_usage);
188*90b80121SDavid van Moolenbroek 	register_status(&status);
189*90b80121SDavid van Moolenbroek 	register_usage(&usage);
190*90b80121SDavid van Moolenbroek }
191