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