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