xref: /freebsd/contrib/wpa/src/ap/vlan_util.c (revision 780fb4a2fa9a9aee5ac48a60b790f567c0dc13e9)
1f05cddf9SRui Paulo /*
2f05cddf9SRui Paulo  * hostapd / VLAN netlink api
3f05cddf9SRui Paulo  * Copyright (c) 2012, Michael Braun <michael-dev@fami-braun.de>
4f05cddf9SRui Paulo  *
5f05cddf9SRui Paulo  * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo  * See README for more details.
7f05cddf9SRui Paulo  */
8f05cddf9SRui Paulo 
9f05cddf9SRui Paulo #include "utils/includes.h"
10f05cddf9SRui Paulo #include <netlink/route/link.h>
11f05cddf9SRui Paulo #include <netlink/route/link/vlan.h>
12f05cddf9SRui Paulo 
13f05cddf9SRui Paulo #include "utils/common.h"
14f05cddf9SRui Paulo #include "vlan_util.h"
15f05cddf9SRui Paulo 
16f05cddf9SRui Paulo /*
17f05cddf9SRui Paulo  * Add a vlan interface with name 'vlan_if_name', VLAN ID 'vid' and
18f05cddf9SRui Paulo  * tagged interface 'if_name'.
19f05cddf9SRui Paulo  *
20f05cddf9SRui Paulo  * returns -1 on error
21f05cddf9SRui Paulo  * returns 1 if the interface already exists
22f05cddf9SRui Paulo  * returns 0 otherwise
23f05cddf9SRui Paulo */
vlan_add(const char * if_name,int vid,const char * vlan_if_name)24f05cddf9SRui Paulo int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
25f05cddf9SRui Paulo {
26325151a3SRui Paulo 	int err, ret = -1;
27f05cddf9SRui Paulo 	struct nl_sock *handle = NULL;
28f05cddf9SRui Paulo 	struct rtnl_link *rlink = NULL;
29f05cddf9SRui Paulo 	int if_idx = 0;
30f05cddf9SRui Paulo 
31f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d, "
32f05cddf9SRui Paulo 		   "vlan_if_name=%s)", if_name, vid, vlan_if_name);
33f05cddf9SRui Paulo 
34f05cddf9SRui Paulo 	if ((os_strlen(if_name) + 1) > IFNAMSIZ) {
35f05cddf9SRui Paulo 		wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
36f05cddf9SRui Paulo 			   if_name);
37f05cddf9SRui Paulo 		return -1;
38f05cddf9SRui Paulo 	}
39f05cddf9SRui Paulo 
40f05cddf9SRui Paulo 	if ((os_strlen(vlan_if_name) + 1) > IFNAMSIZ) {
41f05cddf9SRui Paulo 		wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
42f05cddf9SRui Paulo 			   vlan_if_name);
43f05cddf9SRui Paulo 		return -1;
44f05cddf9SRui Paulo 	}
45f05cddf9SRui Paulo 
46f05cddf9SRui Paulo 	handle = nl_socket_alloc();
47f05cddf9SRui Paulo 	if (!handle) {
48f05cddf9SRui Paulo 		wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket");
49f05cddf9SRui Paulo 		goto vlan_add_error;
50f05cddf9SRui Paulo 	}
51f05cddf9SRui Paulo 
52325151a3SRui Paulo 	err = nl_connect(handle, NETLINK_ROUTE);
53325151a3SRui Paulo 	if (err < 0) {
54325151a3SRui Paulo 		wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink: %s",
55325151a3SRui Paulo 			   nl_geterror(err));
56f05cddf9SRui Paulo 		goto vlan_add_error;
57f05cddf9SRui Paulo 	}
58f05cddf9SRui Paulo 
59*780fb4a2SCy Schubert 	err = rtnl_link_get_kernel(handle, 0, if_name, &rlink);
60325151a3SRui Paulo 	if (err < 0) {
61f05cddf9SRui Paulo 		/* link does not exist */
62f05cddf9SRui Paulo 		wpa_printf(MSG_ERROR, "VLAN: interface %s does not exist",
63f05cddf9SRui Paulo 			   if_name);
64f05cddf9SRui Paulo 		goto vlan_add_error;
65f05cddf9SRui Paulo 	}
66*780fb4a2SCy Schubert 	if_idx = rtnl_link_get_ifindex(rlink);
67*780fb4a2SCy Schubert 	rtnl_link_put(rlink);
68*780fb4a2SCy Schubert 	rlink = NULL;
69f05cddf9SRui Paulo 
70*780fb4a2SCy Schubert 	err = rtnl_link_get_kernel(handle, 0, vlan_if_name, &rlink);
71*780fb4a2SCy Schubert 	if (err >= 0) {
72f05cddf9SRui Paulo 		/* link does exist */
73f05cddf9SRui Paulo 		rtnl_link_put(rlink);
74f05cddf9SRui Paulo 		rlink = NULL;
75f05cddf9SRui Paulo 		wpa_printf(MSG_ERROR, "VLAN: interface %s already exists",
76f05cddf9SRui Paulo 			   vlan_if_name);
77f05cddf9SRui Paulo 		ret = 1;
78f05cddf9SRui Paulo 		goto vlan_add_error;
79f05cddf9SRui Paulo 	}
80f05cddf9SRui Paulo 
81f05cddf9SRui Paulo 	rlink = rtnl_link_alloc();
82f05cddf9SRui Paulo 	if (!rlink) {
83f05cddf9SRui Paulo 		wpa_printf(MSG_ERROR, "VLAN: failed to allocate new link");
84f05cddf9SRui Paulo 		goto vlan_add_error;
85f05cddf9SRui Paulo 	}
86f05cddf9SRui Paulo 
87325151a3SRui Paulo 	err = rtnl_link_set_type(rlink, "vlan");
88325151a3SRui Paulo 	if (err < 0) {
89325151a3SRui Paulo 		wpa_printf(MSG_ERROR, "VLAN: failed to set link type: %s",
90325151a3SRui Paulo 			   nl_geterror(err));
91f05cddf9SRui Paulo 		goto vlan_add_error;
92f05cddf9SRui Paulo 	}
93f05cddf9SRui Paulo 
94f05cddf9SRui Paulo 	rtnl_link_set_link(rlink, if_idx);
95f05cddf9SRui Paulo 	rtnl_link_set_name(rlink, vlan_if_name);
96f05cddf9SRui Paulo 
97325151a3SRui Paulo 	err = rtnl_link_vlan_set_id(rlink, vid);
98325151a3SRui Paulo 	if (err < 0) {
99325151a3SRui Paulo 		wpa_printf(MSG_ERROR, "VLAN: failed to set link vlan id: %s",
100325151a3SRui Paulo 			   nl_geterror(err));
101f05cddf9SRui Paulo 		goto vlan_add_error;
102f05cddf9SRui Paulo 	}
103f05cddf9SRui Paulo 
104325151a3SRui Paulo 	err = rtnl_link_add(handle, rlink, NLM_F_CREATE);
105325151a3SRui Paulo 	if (err < 0) {
106f05cddf9SRui Paulo 		wpa_printf(MSG_ERROR, "VLAN: failed to create link %s for "
107325151a3SRui Paulo 			   "vlan %d on %s (%d): %s",
108325151a3SRui Paulo 			   vlan_if_name, vid, if_name, if_idx,
109325151a3SRui Paulo 			   nl_geterror(err));
110f05cddf9SRui Paulo 		goto vlan_add_error;
111f05cddf9SRui Paulo 	}
112f05cddf9SRui Paulo 
113f05cddf9SRui Paulo 	ret = 0;
114f05cddf9SRui Paulo 
115f05cddf9SRui Paulo vlan_add_error:
116f05cddf9SRui Paulo 	if (rlink)
117f05cddf9SRui Paulo 		rtnl_link_put(rlink);
118f05cddf9SRui Paulo 	if (handle)
119f05cddf9SRui Paulo 		nl_socket_free(handle);
120f05cddf9SRui Paulo 	return ret;
121f05cddf9SRui Paulo }
122f05cddf9SRui Paulo 
123f05cddf9SRui Paulo 
vlan_rem(const char * if_name)124f05cddf9SRui Paulo int vlan_rem(const char *if_name)
125f05cddf9SRui Paulo {
126325151a3SRui Paulo 	int err, ret = -1;
127f05cddf9SRui Paulo 	struct nl_sock *handle = NULL;
128f05cddf9SRui Paulo 	struct rtnl_link *rlink = NULL;
129f05cddf9SRui Paulo 
130f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(if_name=%s)", if_name);
131f05cddf9SRui Paulo 
132f05cddf9SRui Paulo 	handle = nl_socket_alloc();
133f05cddf9SRui Paulo 	if (!handle) {
134f05cddf9SRui Paulo 		wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket");
135f05cddf9SRui Paulo 		goto vlan_rem_error;
136f05cddf9SRui Paulo 	}
137f05cddf9SRui Paulo 
138325151a3SRui Paulo 	err = nl_connect(handle, NETLINK_ROUTE);
139325151a3SRui Paulo 	if (err < 0) {
140325151a3SRui Paulo 		wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink: %s",
141325151a3SRui Paulo 			   nl_geterror(err));
142f05cddf9SRui Paulo 		goto vlan_rem_error;
143f05cddf9SRui Paulo 	}
144f05cddf9SRui Paulo 
145*780fb4a2SCy Schubert 	err = rtnl_link_get_kernel(handle, 0, if_name, &rlink);
146325151a3SRui Paulo 	if (err < 0) {
147f05cddf9SRui Paulo 		/* link does not exist */
148f05cddf9SRui Paulo 		wpa_printf(MSG_ERROR, "VLAN: interface %s does not exists",
149f05cddf9SRui Paulo 			   if_name);
150f05cddf9SRui Paulo 		goto vlan_rem_error;
151f05cddf9SRui Paulo 	}
152f05cddf9SRui Paulo 
153325151a3SRui Paulo 	err = rtnl_link_delete(handle, rlink);
154325151a3SRui Paulo 	if (err < 0) {
155325151a3SRui Paulo 		wpa_printf(MSG_ERROR, "VLAN: failed to remove link %s: %s",
156325151a3SRui Paulo 			   if_name, nl_geterror(err));
157f05cddf9SRui Paulo 		goto vlan_rem_error;
158f05cddf9SRui Paulo 	}
159f05cddf9SRui Paulo 
160f05cddf9SRui Paulo 	ret = 0;
161f05cddf9SRui Paulo 
162f05cddf9SRui Paulo vlan_rem_error:
163f05cddf9SRui Paulo 	if (rlink)
164f05cddf9SRui Paulo 		rtnl_link_put(rlink);
165f05cddf9SRui Paulo 	if (handle)
166f05cddf9SRui Paulo 		nl_socket_free(handle);
167f05cddf9SRui Paulo 	return ret;
168f05cddf9SRui Paulo }
169*780fb4a2SCy Schubert 
170*780fb4a2SCy Schubert 
vlan_set_name_type(unsigned int name_type)171*780fb4a2SCy Schubert int vlan_set_name_type(unsigned int name_type)
172*780fb4a2SCy Schubert {
173*780fb4a2SCy Schubert 	return 0;
174*780fb4a2SCy Schubert }
175