]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-neighbor.c
network: drop sections contain invalid settings in network_verify()
[thirdparty/systemd.git] / src / network / networkd-neighbor.c
CommitLineData
e4a71bf3
WKI
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include "sd-netlink.h"
4
5#include "alloc-util.h"
6#include "conf-parser.h"
7#include "ether-addr-util.h"
8#include "hashmap.h"
9#include "in-addr-util.h"
10#include "netlink-util.h"
11#include "networkd-link.h"
12#include "networkd-manager.h"
13#include "networkd-neighbor.h"
14
15void neighbor_free(Neighbor *neighbor) {
16 if (!neighbor)
17 return;
18
19 if (neighbor->network) {
20 LIST_REMOVE(neighbors, neighbor->network->neighbors, neighbor);
21 assert(neighbor->network->n_neighbors > 0);
22 neighbor->network->n_neighbors--;
23
24 if (neighbor->section) {
25 hashmap_remove(neighbor->network->neighbors_by_section, neighbor->section);
26 network_config_section_free(neighbor->section);
27 }
28 }
29
30 free(neighbor);
31}
32
33static int neighbor_new_static(Network *network, const char *filename, unsigned section_line, Neighbor **ret) {
34 _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
35 _cleanup_(neighbor_freep) Neighbor *neighbor = NULL;
36 int r;
37
38 assert(network);
39 assert(ret);
40 assert(!!filename == (section_line > 0));
41
42 if (filename) {
43 r = network_config_section_new(filename, section_line, &n);
44 if (r < 0)
45 return r;
46
47 neighbor = hashmap_get(network->neighbors_by_section, n);
48 if (neighbor) {
49 *ret = TAKE_PTR(neighbor);
50
51 return 0;
52 }
53 }
54
55 neighbor = new(Neighbor, 1);
56 if (!neighbor)
57 return -ENOMEM;
58
59 *neighbor = (Neighbor) {
60 .network = network,
61 .family = AF_UNSPEC,
62 };
63
64 LIST_APPEND(neighbors, network->neighbors, neighbor);
65 network->n_neighbors++;
66
67 if (filename) {
68 neighbor->section = TAKE_PTR(n);
69
70 r = hashmap_ensure_allocated(&network->neighbors_by_section, &network_config_hash_ops);
71 if (r < 0)
72 return r;
73
74 r = hashmap_put(network->neighbors_by_section, neighbor->section, neighbor);
75 if (r < 0)
76 return r;
77 }
78
79 *ret = TAKE_PTR(neighbor);
80
81 return 0;
82}
83
84static int neighbor_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
85 int r;
86
87 assert(link);
88 assert(link->neighbor_messages > 0);
89
90 link->neighbor_messages--;
91
92 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
93 return 1;
94
95 r = sd_netlink_message_get_errno(m);
96 if (r < 0 && r != -EEXIST)
97 log_link_warning_errno(link, r, "Could not set neighbor: %m");
98
99 if (link->neighbor_messages == 0) {
100 log_link_debug(link, "Neighbors set");
101 link->neighbors_configured = true;
102 link_check_ready(link);
103 }
104
105 return 1;
106}
107
108int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback) {
109 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
110 int r;
111
112 assert(neighbor);
113 assert(link);
114 assert(link->ifindex > 0);
115 assert(link->manager);
116 assert(link->manager->rtnl);
117
118 if (neighbor->family == AF_UNSPEC)
119 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Neighbor without Address= configured");
120 if (!neighbor->mac_configured)
121 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Neighbor without MACAddress= configured");
122
123 r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH,
124 link->ifindex, neighbor->family);
125 if (r < 0)
126 return log_error_errno(r, "Could not allocate RTM_NEWNEIGH message: %m");
127
128 r = sd_rtnl_message_neigh_set_state(req, NUD_PERMANENT);
129 if (r < 0)
130 return log_error_errno(r, "Could not set state: %m");
131
132 r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE);
133 if (r < 0)
134 return log_error_errno(r, "Could not set flags: %m");
135
136 r = sd_netlink_message_append_ether_addr(req, NDA_LLADDR, &neighbor->mac);
137 if (r < 0)
138 return log_error_errno(r, "Could not append NDA_LLADDR attribute: %m");
139
43409486
YW
140 r = netlink_message_append_in_addr_union(req, NDA_DST, neighbor->family, &neighbor->in_addr);
141 if (r < 0)
142 return log_error_errno(r, "Could not append NDA_DST attribute: %m");
e4a71bf3
WKI
143
144 r = netlink_call_async(link->manager->rtnl, NULL, req, callback ?: neighbor_handler,
145 link_netlink_destroy_callback, link);
146 if (r < 0)
147 return log_error_errno(r, "Could not send rtnetlink message: %m");
148
149 link->neighbor_messages++;
150 link_ref(link);
151
152 return 0;
153}
154
155int config_parse_neighbor_address(const char *unit,
156 const char *filename,
157 unsigned line,
158 const char *section,
159 unsigned section_line,
160 const char *lvalue,
161 int ltype,
162 const char *rvalue,
163 void *data,
164 void *userdata) {
165
166 Network *network = userdata;
fcbf4cb7 167 _cleanup_(neighbor_free_or_set_invalidp) Neighbor *n = NULL;
e4a71bf3
WKI
168 int r;
169
170 assert(filename);
171 assert(section);
172 assert(lvalue);
173 assert(rvalue);
174 assert(data);
175
176 r = neighbor_new_static(network, filename, section_line, &n);
177 if (r < 0)
178 return r;
179
180 r = in_addr_from_string_auto(rvalue, &n->family, &n->in_addr);
181 if (r < 0) {
182 log_syntax(unit, LOG_ERR, filename, line, r, "Neighbor Address is invalid, ignoring assignment: %s", rvalue);
183 return 0;
184 }
185
186 TAKE_PTR(n);
187
188 return 0;
189}
190
191int config_parse_neighbor_hwaddr(const char *unit,
192 const char *filename,
193 unsigned line,
194 const char *section,
195 unsigned section_line,
196 const char *lvalue,
197 int ltype,
198 const char *rvalue,
199 void *data,
200 void *userdata) {
201
202 Network *network = userdata;
fcbf4cb7 203 _cleanup_(neighbor_free_or_set_invalidp) Neighbor *n = NULL;
e4a71bf3
WKI
204 int r;
205
206 assert(filename);
207 assert(section);
208 assert(lvalue);
209 assert(rvalue);
210 assert(data);
211
212 r = neighbor_new_static(network, filename, section_line, &n);
213 if (r < 0)
214 return r;
215
216 r = ether_addr_from_string(rvalue, &n->mac);
217 if (r < 0) {
218 log_syntax(unit, LOG_ERR, filename, line, r, "Neighbor MACAddress is invalid, ignoring assignment: %s", rvalue);
219 return 0;
220 }
221
222 n->mac_configured = true;
223 TAKE_PTR(n);
224
225 return 0;
226}