]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-fdb.c
tree-wide: minor formatting inconsistency cleanups
[thirdparty/systemd.git] / src / network / networkd-fdb.c
CommitLineData
b98b483b
AR
1/***
2 This file is part of systemd.
3
4 Copyright (C) 2014 Intel Corporation. All rights reserved.
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
b98b483b 20#include <net/ethernet.h>
cf0fbc49 21#include <net/if.h>
b98b483b 22
b5efdb8a 23#include "alloc-util.h"
b98b483b 24#include "conf-parser.h"
fc2f9534 25#include "netlink-util.h"
fc2f9534 26#include "networkd-fdb.h"
b5efdb8a
LP
27#include "networkd.h"
28#include "util.h"
b98b483b
AR
29
30/* create a new FDB entry or get an existing one. */
31int fdb_entry_new_static(Network *const network,
32 const unsigned section,
33 FdbEntry **ret) {
34 _cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL;
35 struct ether_addr *mac_addr = NULL;
36
37 assert(network);
38
39 /* search entry in hashmap first. */
9ed794a3 40 if (section) {
b98b483b
AR
41 fdb_entry = hashmap_get(network->fdb_entries_by_section, UINT_TO_PTR(section));
42 if (fdb_entry) {
43 *ret = fdb_entry;
44 fdb_entry = NULL;
45
46 return 0;
47 }
48 }
49
50 /* allocate space for MAC address. */
51 mac_addr = new0(struct ether_addr, 1);
52 if (!mac_addr)
53 return -ENOMEM;
54
55 /* allocate space for and FDB entry. */
56 fdb_entry = new0(FdbEntry, 1);
57
58 if (!fdb_entry) {
59 /* free previously allocated space for mac_addr. */
60 free(mac_addr);
61 return -ENOMEM;
62 }
63
64 /* init FDB structure. */
65 fdb_entry->network = network;
66 fdb_entry->mac_addr = mac_addr;
67
68 LIST_PREPEND(static_fdb_entries, network->static_fdb_entries, fdb_entry);
69
70 if (section) {
71 fdb_entry->section = section;
72 hashmap_put(network->fdb_entries_by_section,
73 UINT_TO_PTR(fdb_entry->section), fdb_entry);
74 }
75
76 /* return allocated FDB structure. */
77 *ret = fdb_entry;
78 fdb_entry = NULL;
79
80 return 0;
81}
82
1c4baffc 83static int set_fdb_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
ea6ec096 84 Link *link = userdata;
b98b483b
AR
85 int r;
86
ea6ec096 87 assert(link);
b98b483b 88
1c4baffc 89 r = sd_netlink_message_get_errno(m);
ea6ec096 90 if (r < 0 && r != -EEXIST)
6a7a4e4d 91 log_link_error_errno(link, r, "Could not add FDB entry: %m");
b98b483b
AR
92
93 return 1;
94}
95
96/* send a request to the kernel to add a FDB entry in its static MAC table. */
a245ced0 97int fdb_entry_configure(Link *const link, FdbEntry *const fdb_entry) {
4afd3348 98 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
1c4baffc 99 sd_netlink *rtnl;
b98b483b
AR
100 int r;
101
ea6ec096
TG
102 assert(link);
103 assert(link->manager);
b98b483b 104 assert(fdb_entry);
ea6ec096
TG
105
106 rtnl = link->manager->rtnl;
b98b483b
AR
107
108 /* create new RTM message */
ea6ec096 109 r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_NEWNEIGH, link->ifindex, PF_BRIDGE);
b98b483b
AR
110 if (r < 0)
111 return rtnl_log_create_error(r);
112
113 /* only NTF_SELF flag supported. */
114 r = sd_rtnl_message_neigh_set_flags(req, NTF_SELF);
115 if (r < 0)
116 return rtnl_log_create_error(r);
117
118 /* only NUD_PERMANENT state supported. */
119 r = sd_rtnl_message_neigh_set_state(req, NUD_NOARP | NUD_PERMANENT);
120 if (r < 0)
121 return rtnl_log_create_error(r);
122
1c4baffc 123 r = sd_netlink_message_append_ether_addr(req, NDA_LLADDR, fdb_entry->mac_addr);
b98b483b
AR
124 if (r < 0)
125 return rtnl_log_create_error(r);
126
127 /* VLAN Id is optional. We'll add VLAN Id only if it's specified. */
128 if (0 != fdb_entry->vlan_id) {
1c4baffc 129 r = sd_netlink_message_append_u16(req, NDA_VLAN, fdb_entry->vlan_id);
b98b483b
AR
130 if (r < 0)
131 return rtnl_log_create_error(r);
132 }
133
134 /* send message to the kernel to update its internal static MAC table. */
1c4baffc 135 r = sd_netlink_call_async(rtnl, req, set_fdb_handler, link, 0, NULL);
6a7a4e4d
LP
136 if (r < 0)
137 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
b98b483b
AR
138
139 return 0;
140}
141
142/* remove and FDB entry. */
143void fdb_entry_free(FdbEntry *fdb_entry) {
9ed794a3 144 if (!fdb_entry)
b98b483b
AR
145 return;
146
9ed794a3 147 if (fdb_entry->network) {
b98b483b
AR
148 LIST_REMOVE(static_fdb_entries, fdb_entry->network->static_fdb_entries,
149 fdb_entry);
150
8519d8f5
LP
151 if (fdb_entry->section)
152 hashmap_remove(fdb_entry->network->fdb_entries_by_section,
153 UINT_TO_PTR(fdb_entry->section));
b98b483b
AR
154 }
155
156 free(fdb_entry->mac_addr);
157
158 free(fdb_entry);
159}
160
161/* parse the HW address from config files. */
8519d8f5
LP
162int config_parse_fdb_hwaddr(
163 const char *unit,
164 const char *filename,
165 unsigned line,
166 const char *section,
167 unsigned section_line,
168 const char *lvalue,
169 int ltype,
170 const char *rvalue,
171 void *data,
172 void *userdata) {
173
b98b483b
AR
174 Network *network = userdata;
175 _cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL;
176 int r;
177
178 assert(filename);
179 assert(section);
180 assert(lvalue);
181 assert(rvalue);
182 assert(data);
183
184 r = fdb_entry_new_static(network, section_line, &fdb_entry);
6a7a4e4d
LP
185 if (r < 0)
186 return log_oom();
b98b483b
AR
187
188 /* read in the MAC address for the FDB table. */
189 r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
190 &fdb_entry->mac_addr->ether_addr_octet[0],
191 &fdb_entry->mac_addr->ether_addr_octet[1],
192 &fdb_entry->mac_addr->ether_addr_octet[2],
193 &fdb_entry->mac_addr->ether_addr_octet[3],
194 &fdb_entry->mac_addr->ether_addr_octet[4],
195 &fdb_entry->mac_addr->ether_addr_octet[5]);
196
8519d8f5 197 if (ETHER_ADDR_LEN != r) {
12ca818f 198 log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue);
b98b483b
AR
199 return 0;
200 }
201
202 fdb_entry = NULL;
203
204 return 0;
205}
206
207/* parse the VLAN Id from config files. */
8519d8f5
LP
208int config_parse_fdb_vlan_id(
209 const char *unit,
210 const char *filename,
211 unsigned line,
212 const char *section,
213 unsigned section_line,
214 const char *lvalue,
215 int ltype,
216 const char *rvalue,
217 void *data,
218 void *userdata) {
219
b98b483b
AR
220 Network *network = userdata;
221 _cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL;
222 int r;
223
224 assert(filename);
225 assert(section);
226 assert(lvalue);
227 assert(rvalue);
228 assert(data);
229
230 r = fdb_entry_new_static(network, section_line, &fdb_entry);
6a7a4e4d
LP
231 if (r < 0)
232 return log_oom();
b98b483b
AR
233
234 r = config_parse_unsigned(unit, filename, line, section,
235 section_line, lvalue, ltype,
236 rvalue, &fdb_entry->vlan_id, userdata);
6a7a4e4d 237 if (r < 0)
b98b483b 238 return r;
b98b483b
AR
239
240 fdb_entry = NULL;
241
242 return 0;
243}