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