Branch data Line data Source code
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 : 0 : int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
33 : : {
34 : 0 : int ret = -1;
35 : 0 : struct nl_sock *handle = NULL;
36 : 0 : struct nl_cache *cache = NULL;
37 : 0 : struct rtnl_link *rlink = NULL;
38 : 0 : int if_idx = 0;
39 : :
40 : 0 : 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 [ # # ]: 0 : if ((os_strlen(if_name) + 1) > IFNAMSIZ) {
44 : 0 : wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
45 : : if_name);
46 : 0 : return -1;
47 : : }
48 : :
49 [ # # ]: 0 : if ((os_strlen(vlan_if_name) + 1) > IFNAMSIZ) {
50 : 0 : wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
51 : : vlan_if_name);
52 : 0 : return -1;
53 : : }
54 : :
55 : 0 : handle = nl_socket_alloc();
56 [ # # ]: 0 : if (!handle) {
57 : 0 : wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket");
58 : 0 : goto vlan_add_error;
59 : : }
60 : :
61 [ # # ]: 0 : if (nl_connect(handle, NETLINK_ROUTE) < 0) {
62 : 0 : wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink");
63 : 0 : goto vlan_add_error;
64 : : }
65 : :
66 [ # # ]: 0 : if (rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache) < 0) {
67 : 0 : cache = NULL;
68 : 0 : wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache");
69 : 0 : goto vlan_add_error;
70 : : }
71 : :
72 [ # # ]: 0 : if (!(if_idx = rtnl_link_name2i(cache, if_name))) {
73 : : /* link does not exist */
74 : 0 : wpa_printf(MSG_ERROR, "VLAN: interface %s does not exist",
75 : : if_name);
76 : 0 : goto vlan_add_error;
77 : : }
78 : :
79 [ # # ]: 0 : if ((rlink = rtnl_link_get_by_name(cache, vlan_if_name))) {
80 : : /* link does exist */
81 : 0 : rtnl_link_put(rlink);
82 : 0 : rlink = NULL;
83 : 0 : wpa_printf(MSG_ERROR, "VLAN: interface %s already exists",
84 : : vlan_if_name);
85 : 0 : ret = 1;
86 : 0 : goto vlan_add_error;
87 : : }
88 : :
89 : 0 : rlink = rtnl_link_alloc();
90 [ # # ]: 0 : if (!rlink) {
91 : 0 : wpa_printf(MSG_ERROR, "VLAN: failed to allocate new link");
92 : 0 : goto vlan_add_error;
93 : : }
94 : :
95 [ # # ]: 0 : if (rtnl_link_set_type(rlink, "vlan") < 0) {
96 : 0 : wpa_printf(MSG_ERROR, "VLAN: failed to set link type");
97 : 0 : goto vlan_add_error;
98 : : }
99 : :
100 : 0 : rtnl_link_set_link(rlink, if_idx);
101 : 0 : rtnl_link_set_name(rlink, vlan_if_name);
102 : :
103 [ # # ]: 0 : if (rtnl_link_vlan_set_id(rlink, vid) < 0) {
104 : 0 : wpa_printf(MSG_ERROR, "VLAN: failed to set link vlan id");
105 : 0 : goto vlan_add_error;
106 : : }
107 : :
108 [ # # ]: 0 : if (rtnl_link_add(handle, rlink, NLM_F_CREATE) < 0) {
109 : 0 : 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 : 0 : goto vlan_add_error;
113 : : }
114 : :
115 : 0 : ret = 0;
116 : :
117 : : vlan_add_error:
118 [ # # ]: 0 : if (rlink)
119 : 0 : rtnl_link_put(rlink);
120 [ # # ]: 0 : if (cache)
121 : 0 : nl_cache_free(cache);
122 [ # # ]: 0 : if (handle)
123 : 0 : nl_socket_free(handle);
124 : 0 : return ret;
125 : : }
126 : :
127 : :
128 : 0 : int vlan_rem(const char *if_name)
129 : : {
130 : 0 : int ret = -1;
131 : 0 : struct nl_sock *handle = NULL;
132 : 0 : struct nl_cache *cache = NULL;
133 : 0 : struct rtnl_link *rlink = NULL;
134 : :
135 : 0 : wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(if_name=%s)", if_name);
136 : :
137 : 0 : handle = nl_socket_alloc();
138 [ # # ]: 0 : if (!handle) {
139 : 0 : wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket");
140 : 0 : goto vlan_rem_error;
141 : : }
142 : :
143 [ # # ]: 0 : if (nl_connect(handle, NETLINK_ROUTE) < 0) {
144 : 0 : wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink");
145 : 0 : goto vlan_rem_error;
146 : : }
147 : :
148 [ # # ]: 0 : if (rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache) < 0) {
149 : 0 : cache = NULL;
150 : 0 : wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache");
151 : 0 : goto vlan_rem_error;
152 : : }
153 : :
154 [ # # ]: 0 : if (!(rlink = rtnl_link_get_by_name(cache, if_name))) {
155 : : /* link does not exist */
156 : 0 : wpa_printf(MSG_ERROR, "VLAN: interface %s does not exists",
157 : : if_name);
158 : 0 : goto vlan_rem_error;
159 : : }
160 : :
161 [ # # ]: 0 : if (rtnl_link_delete(handle, rlink) < 0) {
162 : 0 : wpa_printf(MSG_ERROR, "VLAN: failed to remove link %s",
163 : : if_name);
164 : 0 : goto vlan_rem_error;
165 : : }
166 : :
167 : 0 : ret = 0;
168 : :
169 : : vlan_rem_error:
170 [ # # ]: 0 : if (rlink)
171 : 0 : rtnl_link_put(rlink);
172 [ # # ]: 0 : if (cache)
173 : 0 : nl_cache_free(cache);
174 [ # # ]: 0 : if (handle)
175 : 0 : nl_socket_free(handle);
176 : 0 : return ret;
177 : : }
|