]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-fdb.c
netword: fdb fix coding style
[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. */
9560e5b3 21static int fdb_entry_new_static(
8c34b963 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
3e570042
YW
75 r = hashmap_ensure_allocated(&network->fdb_entries_by_section, &network_config_hash_ops);
76 if (r < 0)
77 return r;
78
1a75764a
YW
79 r = hashmap_put(network->fdb_entries_by_section, fdb_entry->section, fdb_entry);
80 if (r < 0)
81 return r;
b98b483b
AR
82 }
83
84 /* return allocated FDB structure. */
1cc6c93a 85 *ret = TAKE_PTR(fdb_entry);
b98b483b
AR
86
87 return 0;
88}
89
302a796f 90static int set_fdb_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
b98b483b
AR
91 int r;
92
ea6ec096 93 assert(link);
b98b483b 94
1c4baffc 95 r = sd_netlink_message_get_errno(m);
ea6ec096 96 if (r < 0 && r != -EEXIST)
6a7a4e4d 97 log_link_error_errno(link, r, "Could not add FDB entry: %m");
b98b483b
AR
98
99 return 1;
100}
101
102/* send a request to the kernel to add a FDB entry in its static MAC table. */
a60a720c 103int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) {
4afd3348 104 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
1c4baffc 105 sd_netlink *rtnl;
b98b483b 106 int r;
f6bb7ac5
TJ
107 uint8_t flags;
108 Bridge *bridge;
b98b483b 109
ea6ec096 110 assert(link);
f6bb7ac5 111 assert(link->network);
ea6ec096 112 assert(link->manager);
b98b483b 113 assert(fdb_entry);
ea6ec096
TG
114
115 rtnl = link->manager->rtnl;
f6bb7ac5 116 bridge = BRIDGE(link->network->bridge);
b98b483b
AR
117
118 /* create new RTM message */
ea6ec096 119 r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_NEWNEIGH, link->ifindex, PF_BRIDGE);
b98b483b
AR
120 if (r < 0)
121 return rtnl_log_create_error(r);
122
f6bb7ac5
TJ
123 if (bridge)
124 flags = NTF_MASTER;
125 else
126 flags = NTF_SELF;
127
128 r = sd_rtnl_message_neigh_set_flags(req, flags);
b98b483b
AR
129 if (r < 0)
130 return rtnl_log_create_error(r);
131
132 /* only NUD_PERMANENT state supported. */
133 r = sd_rtnl_message_neigh_set_state(req, NUD_NOARP | NUD_PERMANENT);
134 if (r < 0)
135 return rtnl_log_create_error(r);
136
1c4baffc 137 r = sd_netlink_message_append_ether_addr(req, NDA_LLADDR, fdb_entry->mac_addr);
b98b483b
AR
138 if (r < 0)
139 return rtnl_log_create_error(r);
140
141 /* VLAN Id is optional. We'll add VLAN Id only if it's specified. */
f143c650 142 if (fdb_entry->vlan_id > 0) {
1c4baffc 143 r = sd_netlink_message_append_u16(req, NDA_VLAN, fdb_entry->vlan_id);
b98b483b
AR
144 if (r < 0)
145 return rtnl_log_create_error(r);
146 }
147
148 /* send message to the kernel to update its internal static MAC table. */
302a796f
YW
149 r = netlink_call_async(rtnl, NULL, req, set_fdb_handler,
150 link_netlink_destroy_callback, link);
6a7a4e4d
LP
151 if (r < 0)
152 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
b98b483b 153
1046bf9b
YW
154 link_ref(link);
155
b98b483b
AR
156 return 0;
157}
158
159/* remove and FDB entry. */
160void fdb_entry_free(FdbEntry *fdb_entry) {
9ed794a3 161 if (!fdb_entry)
b98b483b
AR
162 return;
163
9ed794a3 164 if (fdb_entry->network) {
8c34b963 165 LIST_REMOVE(static_fdb_entries, fdb_entry->network->static_fdb_entries, fdb_entry);
8c34b963
LP
166 assert(fdb_entry->network->n_static_fdb_entries > 0);
167 fdb_entry->network->n_static_fdb_entries--;
b98b483b 168
8519d8f5 169 if (fdb_entry->section)
1a75764a 170 hashmap_remove(fdb_entry->network->fdb_entries_by_section, fdb_entry->section);
b98b483b
AR
171 }
172
1a75764a 173 network_config_section_free(fdb_entry->section);
b98b483b 174 free(fdb_entry->mac_addr);
b98b483b
AR
175 free(fdb_entry);
176}
177
178/* parse the HW address from config files. */
8519d8f5
LP
179int config_parse_fdb_hwaddr(
180 const char *unit,
181 const char *filename,
182 unsigned line,
183 const char *section,
184 unsigned section_line,
185 const char *lvalue,
186 int ltype,
187 const char *rvalue,
188 void *data,
189 void *userdata) {
190
b98b483b 191 Network *network = userdata;
fcbf4cb7 192 _cleanup_(fdb_entry_free_or_set_invalidp) FdbEntry *fdb_entry = NULL;
b98b483b
AR
193 int r;
194
195 assert(filename);
196 assert(section);
197 assert(lvalue);
198 assert(rvalue);
199 assert(data);
200
1a75764a 201 r = fdb_entry_new_static(network, filename, section_line, &fdb_entry);
6a7a4e4d
LP
202 if (r < 0)
203 return log_oom();
b98b483b
AR
204
205 /* read in the MAC address for the FDB table. */
206 r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
207 &fdb_entry->mac_addr->ether_addr_octet[0],
208 &fdb_entry->mac_addr->ether_addr_octet[1],
209 &fdb_entry->mac_addr->ether_addr_octet[2],
210 &fdb_entry->mac_addr->ether_addr_octet[3],
211 &fdb_entry->mac_addr->ether_addr_octet[4],
212 &fdb_entry->mac_addr->ether_addr_octet[5]);
213
8627d112 214 if (r != ETHER_ADDR_LEN) {
12ca818f 215 log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue);
b98b483b
AR
216 return 0;
217 }
218
219 fdb_entry = NULL;
220
221 return 0;
222}
223
224/* parse the VLAN Id from config files. */
8519d8f5
LP
225int config_parse_fdb_vlan_id(
226 const char *unit,
227 const char *filename,
228 unsigned line,
229 const char *section,
230 unsigned section_line,
231 const char *lvalue,
232 int ltype,
233 const char *rvalue,
234 void *data,
235 void *userdata) {
236
b98b483b 237 Network *network = userdata;
fcbf4cb7 238 _cleanup_(fdb_entry_free_or_set_invalidp) FdbEntry *fdb_entry = NULL;
b98b483b
AR
239 int r;
240
241 assert(filename);
242 assert(section);
243 assert(lvalue);
244 assert(rvalue);
245 assert(data);
246
1a75764a 247 r = fdb_entry_new_static(network, filename, section_line, &fdb_entry);
6a7a4e4d
LP
248 if (r < 0)
249 return log_oom();
b98b483b 250
0e83e7a5
TJ
251 r = config_parse_vlanid(unit, filename, line, section,
252 section_line, lvalue, ltype,
253 rvalue, &fdb_entry->vlan_id, userdata);
6a7a4e4d 254 if (r < 0)
b98b483b 255 return r;
b98b483b
AR
256
257 fdb_entry = NULL;
258
259 return 0;
260}