]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-route.c
networkd: port many log messages over to newer logging API
[thirdparty/systemd.git] / src / network / networkd-route.c
CommitLineData
f579559b
TG
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
f579559b
TG
22
23#include "networkd.h"
0b1831c2 24#include "networkd-link.h"
f579559b 25
f579559b
TG
26#include "util.h"
27#include "conf-parser.h"
f579559b 28
f048a16b 29int route_new_static(Network *network, unsigned section, Route **ret) {
f579559b
TG
30 _cleanup_route_free_ Route *route = NULL;
31
6ae115c1 32 if (section) {
16aa63a0
TG
33 route = hashmap_get(network->routes_by_section,
34 UINT_TO_PTR(section));
6ae115c1
TG
35 if (route) {
36 *ret = route;
37 route = NULL;
38
39 return 0;
40 }
41 }
42
f579559b
TG
43 route = new0(Route, 1);
44 if (!route)
45 return -ENOMEM;
46
801bd9e8 47 route->family = AF_UNSPEC;
5c1d3fc9 48 route->scope = RT_SCOPE_UNIVERSE;
28cc555d 49 route->protocol = RTPROT_STATIC;
801bd9e8 50
f579559b
TG
51 route->network = network;
52
3d3d4255 53 LIST_PREPEND(routes, network->static_routes, route);
f579559b 54
6ae115c1
TG
55 if (section) {
56 route->section = section;
16aa63a0
TG
57 hashmap_put(network->routes_by_section,
58 UINT_TO_PTR(route->section), route);
6ae115c1
TG
59 }
60
f579559b
TG
61 *ret = route;
62 route = NULL;
63
64 return 0;
65}
66
28cc555d 67int route_new_dynamic(Route **ret, unsigned char rtm_protocol) {
f048a16b
TG
68 _cleanup_route_free_ Route *route = NULL;
69
70 route = new0(Route, 1);
71 if (!route)
72 return -ENOMEM;
73
801bd9e8 74 route->family = AF_UNSPEC;
5c1d3fc9 75 route->scope = RT_SCOPE_UNIVERSE;
28cc555d 76 route->protocol = rtm_protocol;
801bd9e8 77
f048a16b
TG
78 *ret = route;
79 route = NULL;
80
81 return 0;
82}
83
f579559b
TG
84void route_free(Route *route) {
85 if (!route)
86 return;
87
f048a16b 88 if (route->network) {
3d3d4255 89 LIST_REMOVE(routes, route->network->static_routes, route);
f579559b 90
f048a16b
TG
91 if (route->section)
92 hashmap_remove(route->network->routes_by_section,
16aa63a0 93 UINT_TO_PTR(route->section));
f048a16b 94 }
6ae115c1 95
f579559b
TG
96 free(route);
97}
98
5c1d3fc9 99int route_drop(Route *route, Link *link,
1c4baffc
TG
100 sd_netlink_message_handler_t callback) {
101 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
5c1d3fc9
UTL
102 int r;
103
104 assert(link);
105 assert(link->manager);
106 assert(link->manager->rtnl);
107 assert(link->ifindex > 0);
108 assert(route->family == AF_INET || route->family == AF_INET6);
109
110 r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
28cc555d
DW
111 RTM_DELROUTE, route->family,
112 route->protocol);
f647962d
MS
113 if (r < 0)
114 return log_error_errno(r, "Could not create RTM_DELROUTE message: %m");
5c1d3fc9 115
59580681
GL
116 if (!in_addr_is_null(route->family, &route->in_addr)) {
117 if (route->family == AF_INET)
1c4baffc 118 r = sd_netlink_message_append_in_addr(req, RTA_GATEWAY, &route->in_addr.in);
59580681 119 else if (route->family == AF_INET6)
1c4baffc 120 r = sd_netlink_message_append_in6_addr(req, RTA_GATEWAY, &route->in_addr.in6);
f647962d
MS
121 if (r < 0)
122 return log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m");
5c1d3fc9
UTL
123 }
124
125 if (route->dst_prefixlen) {
126 if (route->family == AF_INET)
1c4baffc 127 r = sd_netlink_message_append_in_addr(req, RTA_DST, &route->dst_addr.in);
5c1d3fc9 128 else if (route->family == AF_INET6)
1c4baffc 129 r = sd_netlink_message_append_in6_addr(req, RTA_DST, &route->dst_addr.in6);
f647962d
MS
130 if (r < 0)
131 return log_error_errno(r, "Could not append RTA_DST attribute: %m");
5c1d3fc9
UTL
132
133 r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
f647962d
MS
134 if (r < 0)
135 return log_error_errno(r, "Could not set destination prefix length: %m");
5c1d3fc9
UTL
136 }
137
9e7e4408
TG
138 if (route->src_prefixlen) {
139 if (route->family == AF_INET)
1c4baffc 140 r = sd_netlink_message_append_in_addr(req, RTA_SRC, &route->src_addr.in);
9e7e4408 141 else if (route->family == AF_INET6)
1c4baffc 142 r = sd_netlink_message_append_in6_addr(req, RTA_SRC, &route->src_addr.in6);
9e7e4408
TG
143 if (r < 0)
144 return log_error_errno(r, "Could not append RTA_DST attribute: %m");
145
146 r = sd_rtnl_message_route_set_src_prefixlen(req, route->src_prefixlen);
147 if (r < 0)
148 return log_error_errno(r, "Could not set source prefix length: %m");
149 }
150
46b0c76e
ERB
151 if (!in_addr_is_null(route->family, &route->prefsrc_addr)) {
152 if (route->family == AF_INET)
1c4baffc 153 r = sd_netlink_message_append_in_addr(req, RTA_PREFSRC, &route->prefsrc_addr.in);
46b0c76e 154 else if (route->family == AF_INET6)
1c4baffc 155 r = sd_netlink_message_append_in6_addr(req, RTA_PREFSRC, &route->prefsrc_addr.in6);
f647962d
MS
156 if (r < 0)
157 return log_error_errno(r, "Could not append RTA_PREFSRC attribute: %m");
46b0c76e
ERB
158 }
159
5c1d3fc9 160 r = sd_rtnl_message_route_set_scope(req, route->scope);
f647962d
MS
161 if (r < 0)
162 return log_error_errno(r, "Could not set scope: %m");
5c1d3fc9 163
1c4baffc 164 r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->metrics);
f647962d
MS
165 if (r < 0)
166 return log_error_errno(r, "Could not append RTA_PRIORITY attribute: %m");
5c1d3fc9 167
1c4baffc 168 r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
f647962d
MS
169 if (r < 0)
170 return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
5c1d3fc9 171
1c4baffc 172 r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
f647962d
MS
173 if (r < 0)
174 return log_error_errno(r, "Could not send rtnetlink message: %m");
5c1d3fc9 175
563c69c6
TG
176 link_ref(link);
177
5c1d3fc9
UTL
178 return 0;
179}
180
f882c247 181int route_configure(Route *route, Link *link,
1c4baffc
TG
182 sd_netlink_message_handler_t callback) {
183 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
f579559b
TG
184 int r;
185
f579559b 186 assert(link);
f882c247
TG
187 assert(link->manager);
188 assert(link->manager->rtnl);
f579559b
TG
189 assert(link->ifindex > 0);
190 assert(route->family == AF_INET || route->family == AF_INET6);
191
151b9b96 192 r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
28cc555d
DW
193 RTM_NEWROUTE, route->family,
194 route->protocol);
f647962d
MS
195 if (r < 0)
196 return log_error_errno(r, "Could not create RTM_NEWROUTE message: %m");
f579559b 197
59580681
GL
198 if (!in_addr_is_null(route->family, &route->in_addr)) {
199 if (route->family == AF_INET)
1c4baffc 200 r = sd_netlink_message_append_in_addr(req, RTA_GATEWAY, &route->in_addr.in);
59580681 201 else if (route->family == AF_INET6)
1c4baffc 202 r = sd_netlink_message_append_in6_addr(req, RTA_GATEWAY, &route->in_addr.in6);
f647962d
MS
203 if (r < 0)
204 return log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m");
f579559b
TG
205 }
206
0a0dc69b
TG
207 if (route->dst_prefixlen) {
208 if (route->family == AF_INET)
1c4baffc 209 r = sd_netlink_message_append_in_addr(req, RTA_DST, &route->dst_addr.in);
0a0dc69b 210 else if (route->family == AF_INET6)
1c4baffc 211 r = sd_netlink_message_append_in6_addr(req, RTA_DST, &route->dst_addr.in6);
f647962d
MS
212 if (r < 0)
213 return log_error_errno(r, "Could not append RTA_DST attribute: %m");
6ae115c1 214
ae4c67a7 215 r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
f647962d
MS
216 if (r < 0)
217 return log_error_errno(r, "Could not set destination prefix length: %m");
1f01fb4f
TG
218 }
219
9e7e4408
TG
220 if (route->src_prefixlen) {
221 if (route->family == AF_INET)
1c4baffc 222 r = sd_netlink_message_append_in_addr(req, RTA_SRC, &route->src_addr.in);
9e7e4408 223 else if (route->family == AF_INET6)
1c4baffc 224 r = sd_netlink_message_append_in6_addr(req, RTA_SRC, &route->src_addr.in6);
9e7e4408
TG
225 if (r < 0)
226 return log_error_errno(r, "Could not append RTA_SRC attribute: %m");
227
228 r = sd_rtnl_message_route_set_src_prefixlen(req, route->src_prefixlen);
229 if (r < 0)
230 return log_error_errno(r, "Could not set source prefix length: %m");
231 }
232
46b0c76e
ERB
233 if (!in_addr_is_null(route->family, &route->prefsrc_addr)) {
234 if (route->family == AF_INET)
1c4baffc 235 r = sd_netlink_message_append_in_addr(req, RTA_PREFSRC, &route->prefsrc_addr.in);
46b0c76e 236 else if (route->family == AF_INET6)
1c4baffc 237 r = sd_netlink_message_append_in6_addr(req, RTA_PREFSRC, &route->prefsrc_addr.in6);
f647962d
MS
238 if (r < 0)
239 return log_error_errno(r, "Could not append RTA_PREFSRC attribute: %m");
46b0c76e
ERB
240 }
241
5c1d3fc9 242 r = sd_rtnl_message_route_set_scope(req, route->scope);
f647962d
MS
243 if (r < 0)
244 return log_error_errno(r, "Could not set scope: %m");
5c1d3fc9 245
1c4baffc 246 r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->metrics);
f647962d
MS
247 if (r < 0)
248 return log_error_errno(r, "Could not append RTA_PRIORITY attribute: %m");
5c1d3fc9 249
1c4baffc 250 r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
f647962d
MS
251 if (r < 0)
252 return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
f579559b 253
1c4baffc 254 r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
f647962d
MS
255 if (r < 0)
256 return log_error_errno(r, "Could not send rtnetlink message: %m");
f579559b 257
563c69c6
TG
258 link_ref(link);
259
f579559b
TG
260 return 0;
261}
262
263int config_parse_gateway(const char *unit,
264 const char *filename,
265 unsigned line,
266 const char *section,
71a61510 267 unsigned section_line,
f579559b
TG
268 const char *lvalue,
269 int ltype,
270 const char *rvalue,
271 void *data,
272 void *userdata) {
44e7b949 273
6ae115c1 274 Network *network = userdata;
f579559b 275 _cleanup_route_free_ Route *n = NULL;
44e7b949
LP
276 union in_addr_union buffer;
277 int r, f;
f579559b
TG
278
279 assert(filename);
6ae115c1 280 assert(section);
f579559b
TG
281 assert(lvalue);
282 assert(rvalue);
283 assert(data);
284
92fe133a
TG
285 if (streq(section, "Network")) {
286 /* we are not in an Route section, so treat
287 * this as the special '0' section */
288 section_line = 0;
289 }
290
f048a16b 291 r = route_new_static(network, section_line, &n);
f579559b
TG
292 if (r < 0)
293 return r;
294
44e7b949 295 r = in_addr_from_string_auto(rvalue, &f, &buffer);
f579559b
TG
296 if (r < 0) {
297 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
44e7b949 298 "Route is invalid, ignoring assignment: %s", rvalue);
f579559b
TG
299 return 0;
300 }
301
44e7b949
LP
302 n->family = f;
303 n->in_addr = buffer;
f579559b
TG
304 n = NULL;
305
306 return 0;
307}
6ae115c1
TG
308
309int config_parse_destination(const char *unit,
310 const char *filename,
311 unsigned line,
312 const char *section,
313 unsigned section_line,
314 const char *lvalue,
315 int ltype,
316 const char *rvalue,
317 void *data,
318 void *userdata) {
44e7b949 319
6ae115c1
TG
320 Network *network = userdata;
321 _cleanup_route_free_ Route *n = NULL;
44e7b949
LP
322 const char *address, *e;
323 union in_addr_union buffer;
9e7e4408 324 unsigned char prefixlen;
44e7b949 325 int r, f;
6ae115c1
TG
326
327 assert(filename);
328 assert(section);
329 assert(lvalue);
330 assert(rvalue);
331 assert(data);
332
f048a16b 333 r = route_new_static(network, section_line, &n);
6ae115c1
TG
334 if (r < 0)
335 return r;
336
9e7e4408 337 /* Destination|Source=address/prefixlen */
6ae115c1 338
ae4c67a7 339 /* address */
6ae115c1 340 e = strchr(rvalue, '/');
44e7b949
LP
341 if (e)
342 address = strndupa(rvalue, e - rvalue);
343 else
344 address = rvalue;
6ae115c1 345
44e7b949 346 r = in_addr_from_string_auto(address, &f, &buffer);
6ae115c1
TG
347 if (r < 0) {
348 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
349 "Destination is invalid, ignoring assignment: %s", address);
350 return 0;
351 }
352
935c0d26
TG
353 if (f != AF_INET && f != AF_INET6) {
354 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
355 "Unknown address family, ignoring assignment: %s", address);
356 return 0;
357 }
358
ae4c67a7
TG
359 /* prefixlen */
360 if (e) {
9e7e4408 361 r = safe_atou8(e + 1, &prefixlen);
ae4c67a7
TG
362 if (r < 0) {
363 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
44e7b949 364 "Route destination prefix length is invalid, ignoring assignment: %s", e + 1);
ae4c67a7
TG
365 return 0;
366 }
ae4c67a7 367 } else {
935c0d26 368 switch (f) {
ae4c67a7 369 case AF_INET:
9e7e4408 370 prefixlen = 32;
ae4c67a7
TG
371 break;
372 case AF_INET6:
9e7e4408 373 prefixlen = 128;
ae4c67a7
TG
374 break;
375 }
376 }
377
44e7b949 378 n->family = f;
9e7e4408
TG
379 if (streq(lvalue, "Destination")) {
380 n->dst_addr = buffer;
381 n->dst_prefixlen = prefixlen;
382 } else if (streq(lvalue, "Source")) {
383 n->src_addr = buffer;
384 n->src_prefixlen = prefixlen;
385 } else
386 assert_not_reached(lvalue);
387
6ae115c1
TG
388 n = NULL;
389
390 return 0;
391}
5d8e593d
SS
392
393int config_parse_route_priority(const char *unit,
394 const char *filename,
395 unsigned line,
396 const char *section,
397 unsigned section_line,
398 const char *lvalue,
399 int ltype,
400 const char *rvalue,
401 void *data,
402 void *userdata) {
403 Network *network = userdata;
404 _cleanup_route_free_ Route *n = NULL;
5d8e593d
SS
405 int r;
406
407 assert(filename);
408 assert(section);
409 assert(lvalue);
410 assert(rvalue);
411 assert(data);
412
413 r = route_new_static(network, section_line, &n);
414 if (r < 0)
415 return r;
416
417 r = config_parse_unsigned(unit, filename, line, section,
418 section_line, lvalue, ltype,
419 rvalue, &n->metrics, userdata);
420 if (r < 0)
421 return r;
422
423 n = NULL;
424
425 return 0;
426}
769b56a3
TG
427
428int config_parse_route_scope(const char *unit,
429 const char *filename,
430 unsigned line,
431 const char *section,
432 unsigned section_line,
433 const char *lvalue,
434 int ltype,
435 const char *rvalue,
436 void *data,
437 void *userdata) {
438 Network *network = userdata;
439 _cleanup_route_free_ Route *n = NULL;
440 int r;
441
442 assert(filename);
443 assert(section);
444 assert(lvalue);
445 assert(rvalue);
446 assert(data);
447
448 r = route_new_static(network, section_line, &n);
449 if (r < 0)
450 return r;
451
452 if (streq(rvalue, "host"))
453 n->scope = RT_SCOPE_HOST;
454 else if (streq(rvalue, "link"))
455 n->scope = RT_SCOPE_LINK;
456 else if (streq(rvalue, "global"))
457 n->scope = RT_SCOPE_UNIVERSE;
458 else {
459 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
460 "Unknown route scope: %s", rvalue);
461 return 0;
462 }
463
464 n = NULL;
465
466 return 0;
467}