xref: /freebsd/contrib/wpa/src/ap/vlan_ioctl.c (revision 780fb4a2)
1*780fb4a2SCy Schubert /*
2*780fb4a2SCy Schubert  * hostapd / VLAN ioctl API
3*780fb4a2SCy Schubert  * Copyright 2003, Instant802 Networks, Inc.
4*780fb4a2SCy Schubert  * Copyright 2005-2006, Devicescape Software, Inc.
5*780fb4a2SCy Schubert  * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
6*780fb4a2SCy Schubert  *
7*780fb4a2SCy Schubert  * This software may be distributed under the terms of the BSD license.
8*780fb4a2SCy Schubert  * See README for more details.
9*780fb4a2SCy Schubert  */
10*780fb4a2SCy Schubert 
11*780fb4a2SCy Schubert #include "utils/includes.h"
12*780fb4a2SCy Schubert #include <sys/ioctl.h>
13*780fb4a2SCy Schubert 
14*780fb4a2SCy Schubert #include "utils/common.h"
15*780fb4a2SCy Schubert #include "common/linux_vlan.h"
16*780fb4a2SCy Schubert #include "vlan_util.h"
17*780fb4a2SCy Schubert 
18*780fb4a2SCy Schubert 
vlan_rem(const char * if_name)19*780fb4a2SCy Schubert int vlan_rem(const char *if_name)
20*780fb4a2SCy Schubert {
21*780fb4a2SCy Schubert 	int fd;
22*780fb4a2SCy Schubert 	struct vlan_ioctl_args if_request;
23*780fb4a2SCy Schubert 
24*780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(%s)", if_name);
25*780fb4a2SCy Schubert 	if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
26*780fb4a2SCy Schubert 		wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
27*780fb4a2SCy Schubert 			   if_name);
28*780fb4a2SCy Schubert 		return -1;
29*780fb4a2SCy Schubert 	}
30*780fb4a2SCy Schubert 
31*780fb4a2SCy Schubert 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
32*780fb4a2SCy Schubert 		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
33*780fb4a2SCy Schubert 			   "failed: %s", __func__, strerror(errno));
34*780fb4a2SCy Schubert 		return -1;
35*780fb4a2SCy Schubert 	}
36*780fb4a2SCy Schubert 
37*780fb4a2SCy Schubert 	os_memset(&if_request, 0, sizeof(if_request));
38*780fb4a2SCy Schubert 
39*780fb4a2SCy Schubert 	os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
40*780fb4a2SCy Schubert 	if_request.cmd = DEL_VLAN_CMD;
41*780fb4a2SCy Schubert 
42*780fb4a2SCy Schubert 	if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
43*780fb4a2SCy Schubert 		wpa_printf(MSG_ERROR, "VLAN: %s: DEL_VLAN_CMD failed for %s: "
44*780fb4a2SCy Schubert 			   "%s", __func__, if_name, strerror(errno));
45*780fb4a2SCy Schubert 		close(fd);
46*780fb4a2SCy Schubert 		return -1;
47*780fb4a2SCy Schubert 	}
48*780fb4a2SCy Schubert 
49*780fb4a2SCy Schubert 	close(fd);
50*780fb4a2SCy Schubert 	return 0;
51*780fb4a2SCy Schubert }
52*780fb4a2SCy Schubert 
53*780fb4a2SCy Schubert 
54*780fb4a2SCy Schubert /*
55*780fb4a2SCy Schubert 	Add a vlan interface with VLAN ID 'vid' and tagged interface
56*780fb4a2SCy Schubert 	'if_name'.
57*780fb4a2SCy Schubert 
58*780fb4a2SCy Schubert 	returns -1 on error
59*780fb4a2SCy Schubert 	returns 1 if the interface already exists
60*780fb4a2SCy Schubert 	returns 0 otherwise
61*780fb4a2SCy Schubert */
vlan_add(const char * if_name,int vid,const char * vlan_if_name)62*780fb4a2SCy Schubert int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
63*780fb4a2SCy Schubert {
64*780fb4a2SCy Schubert 	int fd;
65*780fb4a2SCy Schubert 	struct vlan_ioctl_args if_request;
66*780fb4a2SCy Schubert 
67*780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d)",
68*780fb4a2SCy Schubert 		   if_name, vid);
69*780fb4a2SCy Schubert 	ifconfig_up(if_name);
70*780fb4a2SCy Schubert 
71*780fb4a2SCy Schubert 	if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
72*780fb4a2SCy Schubert 		wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
73*780fb4a2SCy Schubert 			   if_name);
74*780fb4a2SCy Schubert 		return -1;
75*780fb4a2SCy Schubert 	}
76*780fb4a2SCy Schubert 
77*780fb4a2SCy Schubert 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
78*780fb4a2SCy Schubert 		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
79*780fb4a2SCy Schubert 			   "failed: %s", __func__, strerror(errno));
80*780fb4a2SCy Schubert 		return -1;
81*780fb4a2SCy Schubert 	}
82*780fb4a2SCy Schubert 
83*780fb4a2SCy Schubert 	os_memset(&if_request, 0, sizeof(if_request));
84*780fb4a2SCy Schubert 
85*780fb4a2SCy Schubert 	/* Determine if a suitable vlan device already exists. */
86*780fb4a2SCy Schubert 
87*780fb4a2SCy Schubert 	os_snprintf(if_request.device1, sizeof(if_request.device1), "vlan%d",
88*780fb4a2SCy Schubert 		    vid);
89*780fb4a2SCy Schubert 
90*780fb4a2SCy Schubert 	if_request.cmd = GET_VLAN_VID_CMD;
91*780fb4a2SCy Schubert 
92*780fb4a2SCy Schubert 	if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 &&
93*780fb4a2SCy Schubert 	    if_request.u.VID == vid) {
94*780fb4a2SCy Schubert 		if_request.cmd = GET_VLAN_REALDEV_NAME_CMD;
95*780fb4a2SCy Schubert 
96*780fb4a2SCy Schubert 		if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 &&
97*780fb4a2SCy Schubert 		    os_strncmp(if_request.u.device2, if_name,
98*780fb4a2SCy Schubert 			       sizeof(if_request.u.device2)) == 0) {
99*780fb4a2SCy Schubert 			close(fd);
100*780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
101*780fb4a2SCy Schubert 				   "VLAN: vlan_add: if_name %s exists already",
102*780fb4a2SCy Schubert 				   if_request.device1);
103*780fb4a2SCy Schubert 			return 1;
104*780fb4a2SCy Schubert 		}
105*780fb4a2SCy Schubert 	}
106*780fb4a2SCy Schubert 
107*780fb4a2SCy Schubert 	/* A suitable vlan device does not already exist, add one. */
108*780fb4a2SCy Schubert 
109*780fb4a2SCy Schubert 	os_memset(&if_request, 0, sizeof(if_request));
110*780fb4a2SCy Schubert 	os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
111*780fb4a2SCy Schubert 	if_request.u.VID = vid;
112*780fb4a2SCy Schubert 	if_request.cmd = ADD_VLAN_CMD;
113*780fb4a2SCy Schubert 
114*780fb4a2SCy Schubert 	if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
115*780fb4a2SCy Schubert 		wpa_printf(MSG_ERROR,
116*780fb4a2SCy Schubert 			   "VLAN: %s: ADD_VLAN_CMD failed for %s: %s",
117*780fb4a2SCy Schubert 			   __func__, if_request.device1, strerror(errno));
118*780fb4a2SCy Schubert 		close(fd);
119*780fb4a2SCy Schubert 		return -1;
120*780fb4a2SCy Schubert 	}
121*780fb4a2SCy Schubert 
122*780fb4a2SCy Schubert 	close(fd);
123*780fb4a2SCy Schubert 	return 0;
124*780fb4a2SCy Schubert }
125*780fb4a2SCy Schubert 
126*780fb4a2SCy Schubert 
vlan_set_name_type(unsigned int name_type)127*780fb4a2SCy Schubert int vlan_set_name_type(unsigned int name_type)
128*780fb4a2SCy Schubert {
129*780fb4a2SCy Schubert 	int fd;
130*780fb4a2SCy Schubert 	struct vlan_ioctl_args if_request;
131*780fb4a2SCy Schubert 
132*780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "VLAN: vlan_set_name_type(name_type=%u)",
133*780fb4a2SCy Schubert 		   name_type);
134*780fb4a2SCy Schubert 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
135*780fb4a2SCy Schubert 		wpa_printf(MSG_ERROR,
136*780fb4a2SCy Schubert 			   "VLAN: %s: socket(AF_INET,SOCK_STREAM) failed: %s",
137*780fb4a2SCy Schubert 			   __func__, strerror(errno));
138*780fb4a2SCy Schubert 		return -1;
139*780fb4a2SCy Schubert 	}
140*780fb4a2SCy Schubert 
141*780fb4a2SCy Schubert 	os_memset(&if_request, 0, sizeof(if_request));
142*780fb4a2SCy Schubert 
143*780fb4a2SCy Schubert 	if_request.u.name_type = name_type;
144*780fb4a2SCy Schubert 	if_request.cmd = SET_VLAN_NAME_TYPE_CMD;
145*780fb4a2SCy Schubert 	if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
146*780fb4a2SCy Schubert 		wpa_printf(MSG_ERROR,
147*780fb4a2SCy Schubert 			   "VLAN: %s: SET_VLAN_NAME_TYPE_CMD name_type=%u failed: %s",
148*780fb4a2SCy Schubert 			   __func__, name_type, strerror(errno));
149*780fb4a2SCy Schubert 		close(fd);
150*780fb4a2SCy Schubert 		return -1;
151*780fb4a2SCy Schubert 	}
152*780fb4a2SCy Schubert 
153*780fb4a2SCy Schubert 	close(fd);
154*780fb4a2SCy Schubert 	return 0;
155*780fb4a2SCy Schubert }
156