Merge branch 'vendor/OPENSSL'
[dragonfly.git] / contrib / hostapd / src / ap / vlan_util.c
1 /*
2  * hostapd / VLAN netlink api
3  * Copyright (c) 2012, Michael Braun <michael-dev@fami-braun.de>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "utils/includes.h"
10 #include <sys/ioctl.h>
11 #include <linux/sockios.h>
12 #include <linux/if_vlan.h>
13 #include <netlink/genl/genl.h>
14 #include <netlink/genl/family.h>
15 #include <netlink/genl/ctrl.h>
16 #include <netlink/route/link.h>
17 #include <netlink/route/link/vlan.h>
18
19 #include "utils/common.h"
20 #include "utils/eloop.h"
21 #include "hostapd.h"
22 #include "vlan_util.h"
23
24 /*
25  * Add a vlan interface with name 'vlan_if_name', VLAN ID 'vid' and
26  * tagged interface 'if_name'.
27  *
28  * returns -1 on error
29  * returns 1 if the interface already exists
30  * returns 0 otherwise
31 */
32 int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
33 {
34         int ret = -1;
35         struct nl_sock *handle = NULL;
36         struct nl_cache *cache = NULL;
37         struct rtnl_link *rlink = NULL;
38         int if_idx = 0;
39
40         wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d, "
41                    "vlan_if_name=%s)", if_name, vid, vlan_if_name);
42
43         if ((os_strlen(if_name) + 1) > IFNAMSIZ) {
44                 wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
45                            if_name);
46                 return -1;
47         }
48
49         if ((os_strlen(vlan_if_name) + 1) > IFNAMSIZ) {
50                 wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
51                            vlan_if_name);
52                 return -1;
53         }
54
55         handle = nl_socket_alloc();
56         if (!handle) {
57                 wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket");
58                 goto vlan_add_error;
59         }
60
61         if (nl_connect(handle, NETLINK_ROUTE) < 0) {
62                 wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink");
63                 goto vlan_add_error;
64         }
65
66         if (rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache) < 0) {
67                 cache = NULL;
68                 wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache");
69                 goto vlan_add_error;
70         }
71
72         if (!(if_idx = rtnl_link_name2i(cache, if_name))) {
73                 /* link does not exist */
74                 wpa_printf(MSG_ERROR, "VLAN: interface %s does not exist",
75                            if_name);
76                 goto vlan_add_error;
77         }
78
79         if ((rlink = rtnl_link_get_by_name(cache, vlan_if_name))) {
80                 /* link does exist */
81                 rtnl_link_put(rlink);
82                 rlink = NULL;
83                 wpa_printf(MSG_ERROR, "VLAN: interface %s already exists",
84                            vlan_if_name);
85                 ret = 1;
86                 goto vlan_add_error;
87         }
88
89         rlink = rtnl_link_alloc();
90         if (!rlink) {
91                 wpa_printf(MSG_ERROR, "VLAN: failed to allocate new link");
92                 goto vlan_add_error;
93         }
94
95         if (rtnl_link_set_type(rlink, "vlan") < 0) {
96                 wpa_printf(MSG_ERROR, "VLAN: failed to set link type");
97                 goto vlan_add_error;
98         }
99
100         rtnl_link_set_link(rlink, if_idx);
101         rtnl_link_set_name(rlink, vlan_if_name);
102
103         if (rtnl_link_vlan_set_id(rlink, vid) < 0) {
104                 wpa_printf(MSG_ERROR, "VLAN: failed to set link vlan id");
105                 goto vlan_add_error;
106         }
107
108         if (rtnl_link_add(handle, rlink, NLM_F_CREATE) < 0) {
109                 wpa_printf(MSG_ERROR, "VLAN: failed to create link %s for "
110                            "vlan %d on %s (%d)",
111                            vlan_if_name, vid, if_name, if_idx);
112                 goto vlan_add_error;
113         }
114
115         ret = 0;
116
117 vlan_add_error:
118         if (rlink)
119                 rtnl_link_put(rlink);
120         if (cache)
121                 nl_cache_free(cache);
122         if (handle)
123                 nl_socket_free(handle);
124         return ret;
125 }
126
127
128 int vlan_rem(const char *if_name)
129 {
130         int ret = -1;
131         struct nl_sock *handle = NULL;
132         struct nl_cache *cache = NULL;
133         struct rtnl_link *rlink = NULL;
134
135         wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(if_name=%s)", if_name);
136
137         handle = nl_socket_alloc();
138         if (!handle) {
139                 wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket");
140                 goto vlan_rem_error;
141         }
142
143         if (nl_connect(handle, NETLINK_ROUTE) < 0) {
144                 wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink");
145                 goto vlan_rem_error;
146         }
147
148         if (rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache) < 0) {
149                 cache = NULL;
150                 wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache");
151                 goto vlan_rem_error;
152         }
153
154         if (!(rlink = rtnl_link_get_by_name(cache, if_name))) {
155                 /* link does not exist */
156                 wpa_printf(MSG_ERROR, "VLAN: interface %s does not exists",
157                            if_name);
158                 goto vlan_rem_error;
159         }
160
161         if (rtnl_link_delete(handle, rlink) < 0) {
162                 wpa_printf(MSG_ERROR, "VLAN: failed to remove link %s",
163                            if_name);
164                 goto vlan_rem_error;
165         }
166
167         ret = 0;
168
169 vlan_rem_error:
170         if (rlink)
171                 rtnl_link_put(rlink);
172         if (cache)
173                 nl_cache_free(cache);
174         if (handle)
175                 nl_socket_free(handle);
176         return ret;
177 }