]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-fdb.c
network: do not assign unused value
[thirdparty/systemd.git] / src / network / networkd-fdb.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
b98b483b 2/***
810adae9 3 Copyright © 2014 Intel Corporation. All rights reserved.
b98b483b
AR
4***/
5
b98b483b 6#include <net/ethernet.h>
cf0fbc49 7#include <net/if.h>
b98b483b 8
b5efdb8a 9#include "alloc-util.h"
b98b483b 10#include "conf-parser.h"
23f53b99 11#include "netdev/bridge.h"
fc2f9534 12#include "netlink-util.h"
fc2f9534 13#include "networkd-fdb.h"
23f53b99 14#include "networkd-manager.h"
b5efdb8a 15#include "util.h"
0e83e7a5 16#include "vlan-util.h"
b98b483b 17
8c34b963
LP
18#define STATIC_FDB_ENTRIES_PER_NETWORK_MAX 1024U
19
b98b483b 20/* create a new FDB entry or get an existing one. */
8c34b963
LP
21int fdb_entry_new_static(
22 Network *network,
1a75764a
YW
23 const char *filename,
24 unsigned section_line,
8c34b963
LP
25 FdbEntry **ret) {
26
1a75764a 27 _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
8e766630 28 _cleanup_(fdb_entry_freep) FdbEntry *fdb_entry = NULL;
1a75764a
YW
29 _cleanup_free_ struct ether_addr *mac_addr = NULL;
30 int r;
b98b483b
AR
31
32 assert(network);
8c34b963 33 assert(ret);
1a75764a 34 assert(!!filename == (section_line > 0));
b98b483b
AR
35
36 /* search entry in hashmap first. */
1a75764a
YW
37 if (filename) {
38 r = network_config_section_new(filename, section_line, &n);
39 if (r < 0)
40 return r;
41
42 fdb_entry = hashmap_get(network->fdb_entries_by_section, n);
b98b483b 43 if (fdb_entry) {
1cc6c93a 44 *ret = TAKE_PTR(fdb_entry);
b98b483b
AR
45
46 return 0;
47 }
48 }
49
8c34b963
LP
50 if (network->n_static_fdb_entries >= STATIC_FDB_ENTRIES_PER_NETWORK_MAX)
51 return -E2BIG;
52
b98b483b
AR
53 /* allocate space for MAC address. */
54 mac_addr = new0(struct ether_addr, 1);
55 if (!mac_addr)
56 return -ENOMEM;
57
58 /* allocate space for and FDB entry. */
1a75764a
YW
59 fdb_entry = new(FdbEntry, 1);
60 if (!fdb_entry)
b98b483b 61 return -ENOMEM;
b98b483b
AR
62
63 /* init FDB structure. */
1a75764a
YW
64 *fdb_entry = (FdbEntry) {
65 .network = network,
66 .mac_addr = TAKE_PTR(mac_addr),
67 };
b98b483b
AR
68
69 LIST_PREPEND(static_fdb_entries, network->static_fdb_entries, fdb_entry);
8c34b963 70 network->n_static_fdb_entries++;
b98b483b 71
1a75764a
YW
72 if (filename) {
73 fdb_entry->section = TAKE_PTR(n);
74
75 r = hashmap_put(network->fdb_entries_by_section, fdb_entry->section, fdb_entry);
76 if (r < 0)
77 return r;
b98b483b
AR
78 }
79
80 /* return allocated FDB structure. */
1cc6c93a 81 *ret = TAKE_PTR(fdb_entry);
b98b483b
AR
82
83 return 0;
84}
85
1c4baffc 86static int set_fdb_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
ea6ec096 87 Link *link = userdata;
b98b483b
AR
88 int r;
89
ea6ec096 90 assert(link);
b98b483b 91
1c4baffc 92 r = sd_netlink_message_get_errno(m);
ea6ec096 93 if (r < 0 && r != -EEXIST)
6a7a4e4d 94 log_link_error_errno(link, r, "Could not add FDB entry: %m");
b98b483b
AR
95
96 return 1;
97}
98
99/* send a request to the kernel to add a FDB entry in its static MAC table. */
a60a720c 100int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) {
4afd3348 101 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
1c4baffc 102 sd_netlink *rtnl;
b98b483b 103 int r;
f6bb7ac5
TJ
104 uint8_t flags;
105 Bridge *bridge;
b98b483b 106
ea6ec096 107 assert(link);
f6bb7ac5 108 assert(link->network);
ea6ec096 109 assert(link->manager);
b98b483b 110 assert(fdb_entry);
ea6ec096
TG
111
112 rtnl = link->manager->rtnl;
f6bb7ac5 113 bridge = BRIDGE(link->network->bridge);
b98b483b
AR
114
115 /* create new RTM message */
ea6ec096 116 r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_NEWNEIGH, link->ifindex, PF_BRIDGE);
b98b483b
AR
117 if (r < 0)
118 return rtnl_log_create_error(r);
119
f6bb7ac5
TJ
120 if (bridge)
121 flags = NTF_MASTER;
122 else
123 flags = NTF_SELF;
124
125 r = sd_rtnl_message_neigh_set_flags(req, flags);
b98b483b
AR
126 if (r < 0)
127 return rtnl_log_create_error(r);
128
129 /* only NUD_PERMANENT state supported. */
130 r = sd_rtnl_message_neigh_set_state(req, NUD_NOARP | NUD_PERMANENT);
131 if (r < 0)
132 return rtnl_log_create_error(r);
133
1c4baffc 134 r = sd_netlink_message_append_ether_addr(req, NDA_LLADDR, fdb_entry->mac_addr);
b98b483b
AR
135 if (r < 0)
136 return rtnl_log_create_error(r);
137
138 /* VLAN Id is optional. We'll add VLAN Id only if it's specified. */
139 if (0 != fdb_entry->vlan_id) {
1c4baffc 140 r = sd_netlink_message_append_u16(req, NDA_VLAN, fdb_entry->vlan_id);
b98b483b
AR
141 if (r < 0)
142 return rtnl_log_create_error(r);
143 }
144
145 /* send message to the kernel to update its internal static MAC table. */
ee38400b 146 r = sd_netlink_call_async(rtnl, NULL, req, set_fdb_handler,
8190a388 147 link_netlink_destroy_callback, link, 0, __func__);
6a7a4e4d
LP
148 if (r < 0)
149 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
b98b483b 150
1046bf9b
YW
151 link_ref(link);
152
b98b483b
AR
153 return 0;
154}
155
156/* remove and FDB entry. */
157void fdb_entry_free(FdbEntry *fdb_entry) {
9ed794a3 158 if (!fdb_entry)
b98b483b
AR
159 return;
160
9ed794a3 161 if (fdb_entry->network) {
8c34b963 162 LIST_REMOVE(static_fdb_entries, fdb_entry->network->static_fdb_entries, fdb_entry);
8c34b963
LP
163 assert(fdb_entry->network->n_static_fdb_entries > 0);
164 fdb_entry->network->n_static_fdb_entries--;
b98b483b 165
8519d8f5 166 if (fdb_entry->section)
1a75764a 167 hashmap_remove(fdb_entry->network->fdb_entries_by_section, fdb_entry->section);
b98b483b
AR
168 }
169
1a75764a 170 network_config_section_free(fdb_entry->section);
b98b483b 171 free(fdb_entry->mac_addr);
b98b483b
AR
172 free(fdb_entry);
173}
174
175/* parse the HW address from config files. */
8519d8f5
LP
176int config_parse_fdb_hwaddr(
177 const char *unit,
178 const char *filename,
179 unsigned line,
180 const char *section,
181 unsigned section_line,
182 const char *lvalue,
183 int ltype,
184 const char *rvalue,
185 void *data,
186 void *userdata) {
187
b98b483b 188 Network *network = userdata;
8e766630 189 _cleanup_(fdb_entry_freep) FdbEntry *fdb_entry = NULL;
b98b483b
AR
190 int r;
191
192 assert(filename);
193 assert(section);
194 assert(lvalue);
195 assert(rvalue);
196 assert(data);
197
1a75764a 198 r = fdb_entry_new_static(network, filename, section_line, &fdb_entry);
6a7a4e4d
LP
199 if (r < 0)
200 return log_oom();
b98b483b
AR
201
202 /* read in the MAC address for the FDB table. */
203 r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
204 &fdb_entry->mac_addr->ether_addr_octet[0],
205 &fdb_entry->mac_addr->ether_addr_octet[1],
206 &fdb_entry->mac_addr->ether_addr_octet[2],
207 &fdb_entry->mac_addr->ether_addr_octet[3],
208 &fdb_entry->mac_addr->ether_addr_octet[4],
209 &fdb_entry->mac_addr->ether_addr_octet[5]);
210
8627d112 211 if (r != ETHER_ADDR_LEN) {
12ca818f 212 log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue);
b98b483b
AR
213 return 0;
214 }
215
216 fdb_entry = NULL;
217
218 return 0;
219}
220
221/* parse the VLAN Id from config files. */
8519d8f5
LP
222int config_parse_fdb_vlan_id(
223 const char *unit,
224 const char *filename,
225 unsigned line,
226 const char *section,
227 unsigned section_line,
228 const char *lvalue,
229 int ltype,
230 const char *rvalue,
231 void *data,
232 void *userdata) {
233
b98b483b 234 Network *network = userdata;
8e766630 235 _cleanup_(fdb_entry_freep) FdbEntry *fdb_entry = NULL;
b98b483b
AR
236 int r;
237
238 assert(filename);
239 assert(section);
240 assert(lvalue);
241 assert(rvalue);
242 assert(data);
243
1a75764a 244 r = fdb_entry_new_static(network, filename, section_line, &fdb_entry);
6a7a4e4d
LP
245 if (r < 0)
246 return log_oom();
b98b483b 247
0e83e7a5
TJ
248 r = config_parse_vlanid(unit, filename, line, section,
249 section_line, lvalue, ltype,
250 rvalue, &fdb_entry->vlan_id, userdata);
6a7a4e4d 251 if (r < 0)
b98b483b 252 return r;
b98b483b
AR
253
254 fdb_entry = NULL;
255
256 return 0;
257}