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 <netlink/route/link.h>
11 #include <netlink/route/link/vlan.h>
12 
13 #include "utils/common.h"
14 #include "vlan_util.h"
15 
16 /*
17  * Add a vlan interface with name 'vlan_if_name', VLAN ID 'vid' and
18  * tagged interface 'if_name'.
19  *
20  * returns -1 on error
21  * returns 1 if the interface already exists
22  * returns 0 otherwise
23 */
24 int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
25 {
26 	int err, ret = -1;
27 	struct nl_sock *handle = NULL;
28 	struct rtnl_link *rlink = NULL;
29 	int if_idx = 0;
30 
31 	wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d, "
32 		   "vlan_if_name=%s)", if_name, vid, vlan_if_name);
33 
34 	if ((os_strlen(if_name) + 1) > IFNAMSIZ) {
35 		wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
36 			   if_name);
37 		return -1;
38 	}
39 
40 	if ((os_strlen(vlan_if_name) + 1) > IFNAMSIZ) {
41 		wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
42 			   vlan_if_name);
43 		return -1;
44 	}
45 
46 	handle = nl_socket_alloc();
47 	if (!handle) {
48 		wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket");
49 		goto vlan_add_error;
50 	}
51 
52 	err = nl_connect(handle, NETLINK_ROUTE);
53 	if (err < 0) {
54 		wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink: %s",
55 			   nl_geterror(err));
56 		goto vlan_add_error;
57 	}
58 
59 	err = rtnl_link_get_kernel(handle, 0, if_name, &rlink);
60 	if (err < 0) {
61 		/* link does not exist */
62 		wpa_printf(MSG_ERROR, "VLAN: interface %s does not exist",
63 			   if_name);
64 		goto vlan_add_error;
65 	}
66 	if_idx = rtnl_link_get_ifindex(rlink);
67 	rtnl_link_put(rlink);
68 	rlink = NULL;
69 
70 	err = rtnl_link_get_kernel(handle, 0, vlan_if_name, &rlink);
71 	if (err >= 0) {
72 		/* link does exist */
73 		rtnl_link_put(rlink);
74 		rlink = NULL;
75 		wpa_printf(MSG_ERROR, "VLAN: interface %s already exists",
76 			   vlan_if_name);
77 		ret = 1;
78 		goto vlan_add_error;
79 	}
80 
81 	rlink = rtnl_link_alloc();
82 	if (!rlink) {
83 		wpa_printf(MSG_ERROR, "VLAN: failed to allocate new link");
84 		goto vlan_add_error;
85 	}
86 
87 	err = rtnl_link_set_type(rlink, "vlan");
88 	if (err < 0) {
89 		wpa_printf(MSG_ERROR, "VLAN: failed to set link type: %s",
90 			   nl_geterror(err));
91 		goto vlan_add_error;
92 	}
93 
94 	rtnl_link_set_link(rlink, if_idx);
95 	rtnl_link_set_name(rlink, vlan_if_name);
96 
97 	err = rtnl_link_vlan_set_id(rlink, vid);
98 	if (err < 0) {
99 		wpa_printf(MSG_ERROR, "VLAN: failed to set link vlan id: %s",
100 			   nl_geterror(err));
101 		goto vlan_add_error;
102 	}
103 
104 	err = rtnl_link_add(handle, rlink, NLM_F_CREATE);
105 	if (err < 0) {
106 		wpa_printf(MSG_ERROR, "VLAN: failed to create link %s for "
107 			   "vlan %d on %s (%d): %s",
108 			   vlan_if_name, vid, if_name, if_idx,
109 			   nl_geterror(err));
110 		goto vlan_add_error;
111 	}
112 
113 	ret = 0;
114 
115 vlan_add_error:
116 	if (rlink)
117 		rtnl_link_put(rlink);
118 	if (handle)
119 		nl_socket_free(handle);
120 	return ret;
121 }
122 
123 
124 int vlan_rem(const char *if_name)
125 {
126 	int err, ret = -1;
127 	struct nl_sock *handle = NULL;
128 	struct rtnl_link *rlink = NULL;
129 
130 	wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(if_name=%s)", if_name);
131 
132 	handle = nl_socket_alloc();
133 	if (!handle) {
134 		wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket");
135 		goto vlan_rem_error;
136 	}
137 
138 	err = nl_connect(handle, NETLINK_ROUTE);
139 	if (err < 0) {
140 		wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink: %s",
141 			   nl_geterror(err));
142 		goto vlan_rem_error;
143 	}
144 
145 	err = rtnl_link_get_kernel(handle, 0, if_name, &rlink);
146 	if (err < 0) {
147 		/* link does not exist */
148 		wpa_printf(MSG_ERROR, "VLAN: interface %s does not exists",
149 			   if_name);
150 		goto vlan_rem_error;
151 	}
152 
153 	err = rtnl_link_delete(handle, rlink);
154 	if (err < 0) {
155 		wpa_printf(MSG_ERROR, "VLAN: failed to remove link %s: %s",
156 			   if_name, nl_geterror(err));
157 		goto vlan_rem_error;
158 	}
159 
160 	ret = 0;
161 
162 vlan_rem_error:
163 	if (rlink)
164 		rtnl_link_put(rlink);
165 	if (handle)
166 		nl_socket_free(handle);
167 	return ret;
168 }
169 
170 
171 int vlan_set_name_type(unsigned int name_type)
172 {
173 	return 0;
174 }
175