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