blob: 313d89fe7eca6245f35fd38975386d8510e791f7 [file] [log] [blame]
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001/*
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*/
32int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
33{
Dmitry Shmidt05df46a2015-05-19 11:02:01 -070034 int err, ret = -1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070035 struct nl_sock *handle = NULL;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070036 struct rtnl_link *rlink = NULL;
37 int if_idx = 0;
38
39 wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d, "
40 "vlan_if_name=%s)", if_name, vid, vlan_if_name);
41
42 if ((os_strlen(if_name) + 1) > IFNAMSIZ) {
43 wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
44 if_name);
45 return -1;
46 }
47
48 if ((os_strlen(vlan_if_name) + 1) > IFNAMSIZ) {
49 wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
50 vlan_if_name);
51 return -1;
52 }
53
54 handle = nl_socket_alloc();
55 if (!handle) {
56 wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket");
57 goto vlan_add_error;
58 }
59
Dmitry Shmidt05df46a2015-05-19 11:02:01 -070060 err = nl_connect(handle, NETLINK_ROUTE);
61 if (err < 0) {
62 wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink: %s",
63 nl_geterror(err));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070064 goto vlan_add_error;
65 }
66
Dmitry Shmidt9c175262016-03-03 10:20:07 -080067 err = rtnl_link_get_kernel(handle, 0, if_name, &rlink);
Dmitry Shmidt05df46a2015-05-19 11:02:01 -070068 if (err < 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070069 /* link does not exist */
70 wpa_printf(MSG_ERROR, "VLAN: interface %s does not exist",
71 if_name);
72 goto vlan_add_error;
73 }
Dmitry Shmidt9c175262016-03-03 10:20:07 -080074 if_idx = rtnl_link_get_ifindex(rlink);
75 rtnl_link_put(rlink);
76 rlink = NULL;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070077
Dmitry Shmidt9c175262016-03-03 10:20:07 -080078 err = rtnl_link_get_kernel(handle, 0, vlan_if_name, &rlink);
79 if (err >= 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070080 /* 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
Dmitry Shmidt05df46a2015-05-19 11:02:01 -070095 err = rtnl_link_set_type(rlink, "vlan");
96 if (err < 0) {
97 wpa_printf(MSG_ERROR, "VLAN: failed to set link type: %s",
98 nl_geterror(err));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070099 goto vlan_add_error;
100 }
101
102 rtnl_link_set_link(rlink, if_idx);
103 rtnl_link_set_name(rlink, vlan_if_name);
104
Dmitry Shmidt05df46a2015-05-19 11:02:01 -0700105 err = rtnl_link_vlan_set_id(rlink, vid);
106 if (err < 0) {
107 wpa_printf(MSG_ERROR, "VLAN: failed to set link vlan id: %s",
108 nl_geterror(err));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700109 goto vlan_add_error;
110 }
111
Dmitry Shmidt05df46a2015-05-19 11:02:01 -0700112 err = rtnl_link_add(handle, rlink, NLM_F_CREATE);
113 if (err < 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700114 wpa_printf(MSG_ERROR, "VLAN: failed to create link %s for "
Dmitry Shmidt05df46a2015-05-19 11:02:01 -0700115 "vlan %d on %s (%d): %s",
116 vlan_if_name, vid, if_name, if_idx,
117 nl_geterror(err));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700118 goto vlan_add_error;
119 }
120
121 ret = 0;
122
123vlan_add_error:
124 if (rlink)
125 rtnl_link_put(rlink);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700126 if (handle)
127 nl_socket_free(handle);
128 return ret;
129}
130
131
132int vlan_rem(const char *if_name)
133{
Dmitry Shmidt05df46a2015-05-19 11:02:01 -0700134 int err, ret = -1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700135 struct nl_sock *handle = NULL;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700136 struct rtnl_link *rlink = NULL;
137
138 wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(if_name=%s)", if_name);
139
140 handle = nl_socket_alloc();
141 if (!handle) {
142 wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket");
143 goto vlan_rem_error;
144 }
145
Dmitry Shmidt05df46a2015-05-19 11:02:01 -0700146 err = nl_connect(handle, NETLINK_ROUTE);
147 if (err < 0) {
148 wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink: %s",
149 nl_geterror(err));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700150 goto vlan_rem_error;
151 }
152
Dmitry Shmidt9c175262016-03-03 10:20:07 -0800153 err = rtnl_link_get_kernel(handle, 0, if_name, &rlink);
Dmitry Shmidt05df46a2015-05-19 11:02:01 -0700154 if (err < 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700155 /* 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
Dmitry Shmidt05df46a2015-05-19 11:02:01 -0700161 err = rtnl_link_delete(handle, rlink);
162 if (err < 0) {
163 wpa_printf(MSG_ERROR, "VLAN: failed to remove link %s: %s",
164 if_name, nl_geterror(err));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700165 goto vlan_rem_error;
166 }
167
168 ret = 0;
169
170vlan_rem_error:
171 if (rlink)
172 rtnl_link_put(rlink);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700173 if (handle)
174 nl_socket_free(handle);
175 return ret;
176}