]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-routing-policy-rule.c
network: bridgeFDB: rename FdbEntry -> BridgeFDB
[thirdparty/systemd.git] / src / network / networkd-routing-policy-rule.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <net/if.h>
4 #include <linux/fib_rules.h>
5
6 #include "af-list.h"
7 #include "alloc-util.h"
8 #include "conf-parser.h"
9 #include "fileio.h"
10 #include "format-util.h"
11 #include "hashmap.h"
12 #include "ip-protocol-list.h"
13 #include "netlink-util.h"
14 #include "networkd-manager.h"
15 #include "networkd-queue.h"
16 #include "networkd-route.h"
17 #include "networkd-routing-policy-rule.h"
18 #include "networkd-util.h"
19 #include "parse-util.h"
20 #include "socket-util.h"
21 #include "string-table.h"
22 #include "string-util.h"
23 #include "strv.h"
24 #include "user-util.h"
25
26 static const char *const fr_act_type_table[__FR_ACT_MAX] = {
27 [FR_ACT_BLACKHOLE] = "blackhole",
28 [FR_ACT_UNREACHABLE] = "unreachable",
29 [FR_ACT_PROHIBIT] = "prohibit",
30 };
31
32 assert_cc(__FR_ACT_MAX <= UINT8_MAX);
33 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(fr_act_type, int);
34
35 RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule) {
36 if (!rule)
37 return NULL;
38
39 if (rule->network) {
40 assert(rule->section);
41 hashmap_remove(rule->network->rules_by_section, rule->section);
42 }
43
44 if (rule->manager) {
45 set_remove(rule->manager->rules, rule);
46 set_remove(rule->manager->rules_foreign, rule);
47 }
48
49 network_config_section_free(rule->section);
50 free(rule->iif);
51 free(rule->oif);
52
53 return mfree(rule);
54 }
55
56 DEFINE_NETWORK_SECTION_FUNCTIONS(RoutingPolicyRule, routing_policy_rule_free);
57
58 static int routing_policy_rule_new(RoutingPolicyRule **ret) {
59 RoutingPolicyRule *rule;
60
61 rule = new(RoutingPolicyRule, 1);
62 if (!rule)
63 return -ENOMEM;
64
65 *rule = (RoutingPolicyRule) {
66 .table = RT_TABLE_MAIN,
67 .uid_range.start = UID_INVALID,
68 .uid_range.end = UID_INVALID,
69 .suppress_prefixlen = -1,
70 .protocol = RTPROT_UNSPEC,
71 .type = FR_ACT_TO_TBL,
72 };
73
74 *ret = rule;
75 return 0;
76 }
77
78 static int routing_policy_rule_new_static(Network *network, const char *filename, unsigned section_line, RoutingPolicyRule **ret) {
79 _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
80 _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
81 int r;
82
83 assert(network);
84 assert(ret);
85 assert(filename);
86 assert(section_line > 0);
87
88 r = network_config_section_new(filename, section_line, &n);
89 if (r < 0)
90 return r;
91
92 rule = hashmap_get(network->rules_by_section, n);
93 if (rule) {
94 *ret = TAKE_PTR(rule);
95 return 0;
96 }
97
98 r = routing_policy_rule_new(&rule);
99 if (r < 0)
100 return r;
101
102 rule->network = network;
103 rule->section = TAKE_PTR(n);
104 rule->protocol = RTPROT_STATIC;
105
106 r = hashmap_ensure_put(&network->rules_by_section, &network_config_hash_ops, rule->section, rule);
107 if (r < 0)
108 return r;
109
110 *ret = TAKE_PTR(rule);
111 return 0;
112 }
113
114 static int routing_policy_rule_dup(const RoutingPolicyRule *src, RoutingPolicyRule **ret) {
115 _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *dest = NULL;
116
117 assert(src);
118 assert(ret);
119
120 dest = newdup(RoutingPolicyRule, src, 1);
121 if (!dest)
122 return -ENOMEM;
123
124 /* Unset all pointers */
125 dest->manager = NULL;
126 dest->network = NULL;
127 dest->section = NULL;
128 dest->iif = dest->oif = NULL;
129
130 if (src->iif) {
131 dest->iif = strdup(src->iif);
132 if (!dest->iif)
133 return -ENOMEM;
134 }
135
136 if (src->oif) {
137 dest->oif = strdup(src->oif);
138 if (!dest->oif)
139 return -ENOMEM;
140 }
141
142 *ret = TAKE_PTR(dest);
143 return 0;
144 }
145
146 static void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct siphash *state) {
147 assert(rule);
148
149 siphash24_compress(&rule->family, sizeof(rule->family), state);
150
151 switch (rule->family) {
152 case AF_INET:
153 case AF_INET6:
154 siphash24_compress(&rule->from, FAMILY_ADDRESS_SIZE(rule->family), state);
155 siphash24_compress(&rule->from_prefixlen, sizeof(rule->from_prefixlen), state);
156
157 siphash24_compress(&rule->to, FAMILY_ADDRESS_SIZE(rule->family), state);
158 siphash24_compress(&rule->to_prefixlen, sizeof(rule->to_prefixlen), state);
159
160 siphash24_compress_boolean(rule->invert_rule, state);
161
162 siphash24_compress(&rule->tos, sizeof(rule->tos), state);
163 siphash24_compress(&rule->type, sizeof(rule->type), state);
164 siphash24_compress(&rule->fwmark, sizeof(rule->fwmark), state);
165 siphash24_compress(&rule->fwmask, sizeof(rule->fwmask), state);
166 siphash24_compress(&rule->priority, sizeof(rule->priority), state);
167 siphash24_compress(&rule->table, sizeof(rule->table), state);
168 siphash24_compress(&rule->suppress_prefixlen, sizeof(rule->suppress_prefixlen), state);
169
170 siphash24_compress(&rule->ipproto, sizeof(rule->ipproto), state);
171 siphash24_compress(&rule->protocol, sizeof(rule->protocol), state);
172 siphash24_compress(&rule->sport, sizeof(rule->sport), state);
173 siphash24_compress(&rule->dport, sizeof(rule->dport), state);
174 siphash24_compress(&rule->uid_range, sizeof(rule->uid_range), state);
175
176 siphash24_compress_string(rule->iif, state);
177 siphash24_compress_string(rule->oif, state);
178
179 break;
180 default:
181 /* treat any other address family as AF_UNSPEC */
182 break;
183 }
184 }
185
186 static int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const RoutingPolicyRule *b) {
187 int r;
188
189 r = CMP(a->family, b->family);
190 if (r != 0)
191 return r;
192
193 switch (a->family) {
194 case AF_INET:
195 case AF_INET6:
196 r = CMP(a->from_prefixlen, b->from_prefixlen);
197 if (r != 0)
198 return r;
199
200 r = memcmp(&a->from, &b->from, FAMILY_ADDRESS_SIZE(a->family));
201 if (r != 0)
202 return r;
203
204 r = CMP(a->to_prefixlen, b->to_prefixlen);
205 if (r != 0)
206 return r;
207
208 r = memcmp(&a->to, &b->to, FAMILY_ADDRESS_SIZE(a->family));
209 if (r != 0)
210 return r;
211
212 r = CMP(a->invert_rule, b->invert_rule);
213 if (r != 0)
214 return r;
215
216 r = CMP(a->tos, b->tos);
217 if (r != 0)
218 return r;
219
220 r = CMP(a->type, b->type);
221 if (r != 0)
222 return r;
223
224 r = CMP(a->fwmark, b->fwmark);
225 if (r != 0)
226 return r;
227
228 r = CMP(a->fwmask, b->fwmask);
229 if (r != 0)
230 return r;
231
232 r = CMP(a->priority, b->priority);
233 if (r != 0)
234 return r;
235
236 r = CMP(a->table, b->table);
237 if (r != 0)
238 return r;
239
240 r = CMP(a->suppress_prefixlen, b->suppress_prefixlen);
241 if (r != 0)
242 return r;
243
244 r = CMP(a->ipproto, b->ipproto);
245 if (r != 0)
246 return r;
247
248 r = CMP(a->protocol, b->protocol);
249 if (r != 0)
250 return r;
251
252 r = memcmp(&a->sport, &b->sport, sizeof(a->sport));
253 if (r != 0)
254 return r;
255
256 r = memcmp(&a->dport, &b->dport, sizeof(a->dport));
257 if (r != 0)
258 return r;
259
260 r = memcmp(&a->uid_range, &b->uid_range, sizeof(a->uid_range));
261 if (r != 0)
262 return r;
263
264 r = strcmp_ptr(a->iif, b->iif);
265 if (r != 0)
266 return r;
267
268 r = strcmp_ptr(a->oif, b->oif);
269 if (r != 0)
270 return r;
271
272 return 0;
273 default:
274 /* treat any other address family as AF_UNSPEC */
275 return 0;
276 }
277 }
278
279 static bool routing_policy_rule_equal(const RoutingPolicyRule *rule1, const RoutingPolicyRule *rule2) {
280 if (rule1 == rule2)
281 return true;
282
283 if (!rule1 || !rule2)
284 return false;
285
286 return routing_policy_rule_compare_func(rule1, rule2) == 0;
287 }
288
289 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
290 routing_policy_rule_hash_ops,
291 RoutingPolicyRule,
292 routing_policy_rule_hash_func,
293 routing_policy_rule_compare_func,
294 routing_policy_rule_free);
295
296 static int routing_policy_rule_get(Manager *m, const RoutingPolicyRule *rule, RoutingPolicyRule **ret) {
297 RoutingPolicyRule *existing;
298
299 assert(m);
300
301 existing = set_get(m->rules, rule);
302 if (existing) {
303 if (ret)
304 *ret = existing;
305 return 1;
306 }
307
308 existing = set_get(m->rules_foreign, rule);
309 if (existing) {
310 if (ret)
311 *ret = existing;
312 return 0;
313 }
314
315 return -ENOENT;
316 }
317
318 static int routing_policy_rule_add(Manager *m, const RoutingPolicyRule *in, RoutingPolicyRule **ret) {
319 _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
320 RoutingPolicyRule *existing;
321 bool is_new = false;
322 int r;
323
324 assert(m);
325 assert(in);
326 assert(IN_SET(in->family, AF_INET, AF_INET6));
327
328 r = routing_policy_rule_dup(in, &rule);
329 if (r < 0)
330 return r;
331
332 r = routing_policy_rule_get(m, rule, &existing);
333 if (r == -ENOENT) {
334 /* Rule does not exist, use a new one. */
335 r = set_ensure_put(&m->rules, &routing_policy_rule_hash_ops, rule);
336 if (r < 0)
337 return r;
338 assert(r > 0);
339
340 rule->manager = m;
341 existing = TAKE_PTR(rule);
342 is_new = true;
343 } else if (r == 0) {
344 /* Take over a foreign rule. */
345 r = set_ensure_put(&m->rules, &routing_policy_rule_hash_ops, existing);
346 if (r < 0)
347 return r;
348 assert(r > 0);
349
350 set_remove(m->rules_foreign, existing);
351 } else if (r == 1) {
352 /* Already exists, do nothing. */
353 ;
354 } else
355 return r;
356
357 if (ret)
358 *ret = existing;
359 return is_new;
360 }
361
362 static int routing_policy_rule_consume_foreign(Manager *m, RoutingPolicyRule *rule) {
363 int r;
364
365 assert(m);
366 assert(rule);
367 assert(IN_SET(rule->family, AF_INET, AF_INET6));
368
369 r = set_ensure_consume(&m->rules_foreign, &routing_policy_rule_hash_ops, rule);
370 if (r <= 0)
371 return r;
372
373 rule->manager = m;
374
375 return 1;
376 }
377
378 static void log_routing_policy_rule_debug(const RoutingPolicyRule *rule, const char *str, const Link *link, const Manager *m) {
379 _cleanup_free_ char *from = NULL, *to = NULL, *table = NULL;
380
381 assert(rule);
382 assert(IN_SET(rule->family, AF_INET, AF_INET6));
383 assert(str);
384 assert(m);
385
386 /* link may be NULL. */
387
388 if (!DEBUG_LOGGING)
389 return;
390
391 (void) in_addr_prefix_to_string(rule->family, &rule->from, rule->from_prefixlen, &from);
392 (void) in_addr_prefix_to_string(rule->family, &rule->to, rule->to_prefixlen, &to);
393 (void) manager_get_route_table_to_string(m, rule->table, &table);
394
395 log_link_debug(link,
396 "%s routing policy rule: priority: %"PRIu32", %s -> %s, iif: %s, oif: %s, table: %s",
397 str, rule->priority, strna(from), strna(to),
398 strna(rule->iif), strna(rule->oif), strna(table));
399 }
400
401 static int routing_policy_rule_set_netlink_message(const RoutingPolicyRule *rule, sd_netlink_message *m, Link *link) {
402 int r;
403
404 assert(rule);
405 assert(m);
406
407 /* link may be NULL. */
408
409 if (in_addr_is_set(rule->family, &rule->from)) {
410 r = netlink_message_append_in_addr_union(m, FRA_SRC, rule->family, &rule->from);
411 if (r < 0)
412 return log_link_error_errno(link, r, "Could not append FRA_SRC attribute: %m");
413
414 r = sd_rtnl_message_routing_policy_rule_set_fib_src_prefixlen(m, rule->from_prefixlen);
415 if (r < 0)
416 return log_link_error_errno(link, r, "Could not set source prefix length: %m");
417 }
418
419 if (in_addr_is_set(rule->family, &rule->to)) {
420 r = netlink_message_append_in_addr_union(m, FRA_DST, rule->family, &rule->to);
421 if (r < 0)
422 return log_link_error_errno(link, r, "Could not append FRA_DST attribute: %m");
423
424 r = sd_rtnl_message_routing_policy_rule_set_fib_dst_prefixlen(m, rule->to_prefixlen);
425 if (r < 0)
426 return log_link_error_errno(link, r, "Could not set destination prefix length: %m");
427 }
428
429 r = sd_netlink_message_append_u32(m, FRA_PRIORITY, rule->priority);
430 if (r < 0)
431 return log_link_error_errno(link, r, "Could not append FRA_PRIORITY attribute: %m");
432
433 if (rule->tos > 0) {
434 r = sd_rtnl_message_routing_policy_rule_set_tos(m, rule->tos);
435 if (r < 0)
436 return log_link_error_errno(link, r, "Could not set IP rule TOS: %m");
437 }
438
439 if (rule->table < 256) {
440 r = sd_rtnl_message_routing_policy_rule_set_table(m, rule->table);
441 if (r < 0)
442 return log_link_error_errno(link, r, "Could not set IP rule table: %m");
443 } else {
444 r = sd_rtnl_message_routing_policy_rule_set_table(m, RT_TABLE_UNSPEC);
445 if (r < 0)
446 return log_link_error_errno(link, r, "Could not set IP rule table: %m");
447
448 r = sd_netlink_message_append_u32(m, FRA_TABLE, rule->table);
449 if (r < 0)
450 return log_link_error_errno(link, r, "Could not append FRA_TABLE attribute: %m");
451 }
452
453 if (rule->fwmark > 0) {
454 r = sd_netlink_message_append_u32(m, FRA_FWMARK, rule->fwmark);
455 if (r < 0)
456 return log_link_error_errno(link, r, "Could not append FRA_FWMARK attribute: %m");
457
458 r = sd_netlink_message_append_u32(m, FRA_FWMASK, rule->fwmask);
459 if (r < 0)
460 return log_link_error_errno(link, r, "Could not append FRA_FWMASK attribute: %m");
461 }
462
463 if (rule->iif) {
464 r = sd_netlink_message_append_string(m, FRA_IIFNAME, rule->iif);
465 if (r < 0)
466 return log_link_error_errno(link, r, "Could not append FRA_IIFNAME attribute: %m");
467 }
468
469 if (rule->oif) {
470 r = sd_netlink_message_append_string(m, FRA_OIFNAME, rule->oif);
471 if (r < 0)
472 return log_link_error_errno(link, r, "Could not append FRA_OIFNAME attribute: %m");
473 }
474
475 r = sd_netlink_message_append_u8(m, FRA_IP_PROTO, rule->ipproto);
476 if (r < 0)
477 return log_link_error_errno(link, r, "Could not append FRA_IP_PROTO attribute: %m");
478
479 r = sd_netlink_message_append_u8(m, FRA_PROTOCOL, rule->protocol);
480 if (r < 0)
481 return log_link_error_errno(link, r, "Could not append FRA_PROTOCOL attribute: %m");
482
483 if (rule->sport.start != 0 || rule->sport.end != 0) {
484 r = sd_netlink_message_append_data(m, FRA_SPORT_RANGE, &rule->sport, sizeof(rule->sport));
485 if (r < 0)
486 return log_link_error_errno(link, r, "Could not append FRA_SPORT_RANGE attribute: %m");
487 }
488
489 if (rule->dport.start != 0 || rule->dport.end != 0) {
490 r = sd_netlink_message_append_data(m, FRA_DPORT_RANGE, &rule->dport, sizeof(rule->dport));
491 if (r < 0)
492 return log_link_error_errno(link, r, "Could not append FRA_DPORT_RANGE attribute: %m");
493 }
494
495 if (rule->uid_range.start != UID_INVALID && rule->uid_range.end != UID_INVALID) {
496 r = sd_netlink_message_append_data(m, FRA_UID_RANGE, &rule->uid_range, sizeof(rule->uid_range));
497 if (r < 0)
498 return log_link_error_errno(link, r, "Could not append FRA_UID_RANGE attribute: %m");
499 }
500
501 if (rule->invert_rule) {
502 r = sd_rtnl_message_routing_policy_rule_set_flags(m, FIB_RULE_INVERT);
503 if (r < 0)
504 return log_link_error_errno(link, r, "Could not append FIB_RULE_INVERT attribute: %m");
505 }
506
507 if (rule->suppress_prefixlen >= 0) {
508 r = sd_netlink_message_append_u32(m, FRA_SUPPRESS_PREFIXLEN, (uint32_t) rule->suppress_prefixlen);
509 if (r < 0)
510 return log_link_error_errno(link, r, "Could not append FRA_SUPPRESS_PREFIXLEN attribute: %m");
511 }
512
513 if (rule->type != FR_ACT_TO_TBL) {
514 r = sd_rtnl_message_routing_policy_rule_set_fib_type(m, rule->type);
515 if (r < 0)
516 return log_link_error_errno(link, r, "Could not append FIB rule type attribute: %m");
517 }
518
519 return 0;
520 }
521
522 static int routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Manager *manager) {
523 int r;
524
525 assert(m);
526 assert(manager);
527 assert(manager->routing_policy_rule_remove_messages > 0);
528
529 manager->routing_policy_rule_remove_messages--;
530
531 r = sd_netlink_message_get_errno(m);
532 if (r < 0)
533 log_message_warning_errno(m, r, "Could not drop routing policy rule");
534
535 return 1;
536 }
537
538 static int routing_policy_rule_remove(const RoutingPolicyRule *rule, Manager *manager) {
539 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
540 int r;
541
542 assert(rule);
543 assert(manager);
544 assert(manager->rtnl);
545 assert(IN_SET(rule->family, AF_INET, AF_INET6));
546
547 log_routing_policy_rule_debug(rule, "Removing", NULL, manager);
548
549 r = sd_rtnl_message_new_routing_policy_rule(manager->rtnl, &m, RTM_DELRULE, rule->family);
550 if (r < 0)
551 return log_error_errno(r, "Could not allocate RTM_DELRULE message: %m");
552
553 r = routing_policy_rule_set_netlink_message(rule, m, NULL);
554 if (r < 0)
555 return r;
556
557 r = netlink_call_async(manager->rtnl, NULL, m,
558 routing_policy_rule_remove_handler,
559 NULL, manager);
560 if (r < 0)
561 return log_error_errno(r, "Could not send rtnetlink message: %m");
562
563 manager->routing_policy_rule_remove_messages++;
564
565 return 0;
566 }
567
568 static int routing_policy_rule_configure(
569 const RoutingPolicyRule *rule,
570 Link *link,
571 link_netlink_message_handler_t callback,
572 RoutingPolicyRule **ret) {
573
574 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
575 int r;
576
577 assert(rule);
578 assert(IN_SET(rule->family, AF_INET, AF_INET6));
579 assert(link);
580 assert(link->ifindex > 0);
581 assert(link->manager);
582 assert(link->manager->rtnl);
583 assert(callback);
584
585 log_routing_policy_rule_debug(rule, "Configuring", link, link->manager);
586
587 r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, rule->family);
588 if (r < 0)
589 return log_link_error_errno(link, r, "Could not allocate RTM_NEWRULE message: %m");
590
591 r = routing_policy_rule_set_netlink_message(rule, m, link);
592 if (r < 0)
593 return r;
594
595 r = routing_policy_rule_add(link->manager, rule, ret);
596 if (r < 0)
597 return log_link_error_errno(link, r, "Could not add rule: %m");
598
599 r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
600 link_netlink_destroy_callback, link);
601 if (r < 0)
602 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
603
604 link_ref(link);
605
606 return r;
607 }
608
609 static int links_have_routing_policy_rule(const Manager *m, const RoutingPolicyRule *rule, const Link *except) {
610 Link *link;
611 int r;
612
613 assert(m);
614 assert(rule);
615
616 HASHMAP_FOREACH(link, m->links) {
617 RoutingPolicyRule *link_rule;
618
619 if (link == except)
620 continue;
621
622 if (!link->network)
623 continue;
624
625 HASHMAP_FOREACH(link_rule, link->network->rules_by_section)
626 if (IN_SET(link_rule->family, AF_INET, AF_INET6)) {
627 if (routing_policy_rule_equal(link_rule, rule))
628 return true;
629 } else {
630 /* The case Family=both. */
631 _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL;
632
633 r = routing_policy_rule_dup(link_rule, &tmp);
634 if (r < 0)
635 return r;
636
637 tmp->family = AF_INET;
638 if (routing_policy_rule_equal(tmp, rule))
639 return true;
640
641 tmp->family = AF_INET6;
642 if (routing_policy_rule_equal(tmp, rule))
643 return true;
644 }
645 }
646
647 return false;
648 }
649
650 int manager_drop_routing_policy_rules_internal(Manager *m, bool foreign, const Link *except) {
651 RoutingPolicyRule *rule;
652 int k, r = 0;
653 Set *rules;
654
655 assert(m);
656
657 rules = foreign ? m->rules_foreign : m->rules;
658 SET_FOREACH(rule, rules) {
659 /* Do not touch rules managed by kernel. */
660 if (rule->protocol == RTPROT_KERNEL)
661 continue;
662
663 /* The rule will be configured later, or already configured by a link. */
664 k = links_have_routing_policy_rule(m, rule, except);
665 if (k != 0) {
666 if (k < 0 && r >= 0)
667 r = k;
668 continue;
669 }
670
671 k = routing_policy_rule_remove(rule, m);
672 if (k < 0 && r >= 0)
673 r = k;
674 }
675
676 return r;
677 }
678
679 static int static_routing_policy_rule_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
680 int r;
681
682 assert(rtnl);
683 assert(m);
684 assert(link);
685 assert(link->ifname);
686 assert(link->static_routing_policy_rule_messages > 0);
687
688 link->static_routing_policy_rule_messages--;
689
690 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
691 return 1;
692
693 r = sd_netlink_message_get_errno(m);
694 if (r < 0 && r != -EEXIST) {
695 log_link_message_warning_errno(link, m, r, "Could not add routing policy rule");
696 link_enter_failed(link);
697 return 1;
698 }
699
700 if (link->static_routing_policy_rule_messages == 0) {
701 log_link_debug(link, "Routing policy rule configured");
702 link->static_routing_policy_rules_configured = true;
703 link_check_ready(link);
704 }
705
706 return 1;
707 }
708
709 static int link_request_routing_policy_rule(
710 Link *link,
711 RoutingPolicyRule *rule,
712 bool consume_object,
713 unsigned *message_counter,
714 link_netlink_message_handler_t netlink_handler,
715 Request **ret) {
716
717 assert(link);
718 assert(link->manager);
719 assert(rule);
720
721 log_routing_policy_rule_debug(rule, "Requesting", link, link->manager);
722 return link_queue_request(link, REQUEST_TYPE_ROUTING_POLICY_RULE, rule, consume_object,
723 message_counter, netlink_handler, ret);
724 }
725
726 static int link_request_static_routing_policy_rule(Link *link, RoutingPolicyRule *rule) {
727 int r;
728
729 if (IN_SET(rule->family, AF_INET, AF_INET6))
730 return link_request_routing_policy_rule(link, rule, false,
731 &link->static_routing_policy_rule_messages,
732 static_routing_policy_rule_configure_handler,
733 NULL);
734
735 if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4)) {
736 _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL;
737
738 r = routing_policy_rule_dup(rule, &tmp);
739 if (r < 0)
740 return r;
741
742 tmp->family = AF_INET;
743
744 r = link_request_routing_policy_rule(link, TAKE_PTR(tmp), true,
745 &link->static_routing_policy_rule_messages,
746 static_routing_policy_rule_configure_handler,
747 NULL);
748 if (r < 0)
749 return r;
750 }
751
752 if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6)) {
753 _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL;
754
755 r = routing_policy_rule_dup(rule, &tmp);
756 if (r < 0)
757 return r;
758
759 tmp->family = AF_INET6;
760
761 r = link_request_routing_policy_rule(link, TAKE_PTR(tmp), true,
762 &link->static_routing_policy_rule_messages,
763 static_routing_policy_rule_configure_handler,
764 NULL);
765 if (r < 0)
766 return r;
767 }
768
769 return 0;
770 }
771
772 int link_request_static_routing_policy_rules(Link *link) {
773 RoutingPolicyRule *rule;
774 int r;
775
776 assert(link);
777 assert(link->network);
778
779 link->static_routing_policy_rules_configured = false;
780
781 HASHMAP_FOREACH(rule, link->network->rules_by_section) {
782 r = link_request_static_routing_policy_rule(link, rule);
783 if (r < 0)
784 return log_link_warning_errno(link, r, "Could not request routing policy rule: %m");
785 }
786
787 if (link->static_routing_policy_rule_messages == 0) {
788 link->static_routing_policy_rules_configured = true;
789 link_check_ready(link);
790 } else {
791 log_link_debug(link, "Requesting routing policy rules");
792 link_set_state(link, LINK_STATE_CONFIGURING);
793 }
794
795 return 0;
796 }
797
798 int request_process_routing_policy_rule(Request *req) {
799 RoutingPolicyRule *ret = NULL; /* avoid false maybe-uninitialized warning */
800 int r;
801
802 assert(req);
803 assert(req->link);
804 assert(req->rule);
805 assert(req->type == REQUEST_TYPE_ROUTING_POLICY_RULE);
806
807 if (!link_is_ready_to_configure(req->link, false))
808 return 0;
809
810 if (req->link->manager->routing_policy_rule_remove_messages > 0)
811 return 0;
812
813 r = routing_policy_rule_configure(req->rule, req->link, req->netlink_handler, &ret);
814 if (r < 0)
815 return r;
816
817 /* To prevent a double decrement on failure in after_configure(). */
818 req->message_counter = NULL;
819
820 if (req->after_configure) {
821 r = req->after_configure(req, ret);
822 if (r < 0)
823 return r;
824 }
825
826 return 1;
827 }
828
829 static const RoutingPolicyRule kernel_rules[] = {
830 { .family = AF_INET, .priority = 0, .table = RT_TABLE_LOCAL, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
831 { .family = AF_INET, .priority = 32766, .table = RT_TABLE_MAIN, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
832 { .family = AF_INET, .priority = 32767, .table = RT_TABLE_DEFAULT, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
833 { .family = AF_INET6, .priority = 0, .table = RT_TABLE_LOCAL, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
834 { .family = AF_INET6, .priority = 32766, .table = RT_TABLE_MAIN, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
835 };
836
837 static bool routing_policy_rule_is_created_by_kernel(const RoutingPolicyRule *rule) {
838 assert(rule);
839
840 if (rule->l3mdev > 0)
841 /* Currently, [RoutingPolicyRule] does not explicitly set FRA_L3MDEV. So, if the flag
842 * is set, it is safe to treat the rule as created by kernel. */
843 return true;
844
845 for (size_t i = 0; i < ELEMENTSOF(kernel_rules); i++)
846 if (routing_policy_rule_equal(rule, &kernel_rules[i]))
847 return true;
848
849 return false;
850 }
851
852 int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
853 _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL;
854 RoutingPolicyRule *rule = NULL;
855 const char *iif = NULL, *oif = NULL;
856 bool adjust_protocol = false;
857 uint32_t suppress_prefixlen;
858 unsigned flags;
859 uint16_t type;
860 int r;
861
862 assert(rtnl);
863 assert(message);
864
865 if (sd_netlink_message_is_error(message)) {
866 r = sd_netlink_message_get_errno(message);
867 if (r < 0)
868 log_message_warning_errno(message, r, "rtnl: failed to receive rule message, ignoring");
869
870 return 0;
871 }
872
873 r = sd_netlink_message_get_type(message, &type);
874 if (r < 0) {
875 log_warning_errno(r, "rtnl: could not get message type, ignoring: %m");
876 return 0;
877 } else if (!IN_SET(type, RTM_NEWRULE, RTM_DELRULE)) {
878 log_warning("rtnl: received unexpected message type %u when processing rule, ignoring.", type);
879 return 0;
880 }
881
882 r = routing_policy_rule_new(&tmp);
883 if (r < 0) {
884 log_oom();
885 return 0;
886 }
887
888 r = sd_rtnl_message_get_family(message, &tmp->family);
889 if (r < 0) {
890 log_warning_errno(r, "rtnl: could not get rule family, ignoring: %m");
891 return 0;
892 } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) {
893 log_debug("rtnl: received rule message with invalid family %d, ignoring.", tmp->family);
894 return 0;
895 }
896
897 r = netlink_message_read_in_addr_union(message, FRA_SRC, tmp->family, &tmp->from);
898 if (r < 0 && r != -ENODATA) {
899 log_warning_errno(r, "rtnl: could not get FRA_SRC attribute, ignoring: %m");
900 return 0;
901 } else if (r >= 0) {
902 r = sd_rtnl_message_routing_policy_rule_get_fib_src_prefixlen(message, &tmp->from_prefixlen);
903 if (r < 0) {
904 log_warning_errno(r, "rtnl: received rule message without valid source prefix length, ignoring: %m");
905 return 0;
906 }
907 }
908
909 r = netlink_message_read_in_addr_union(message, FRA_DST, tmp->family, &tmp->to);
910 if (r < 0 && r != -ENODATA) {
911 log_warning_errno(r, "rtnl: could not get FRA_DST attribute, ignoring: %m");
912 return 0;
913 } else if (r >= 0) {
914 r = sd_rtnl_message_routing_policy_rule_get_fib_dst_prefixlen(message, &tmp->to_prefixlen);
915 if (r < 0) {
916 log_warning_errno(r, "rtnl: received rule message without valid destination prefix length, ignoring: %m");
917 return 0;
918 }
919 }
920
921 r = sd_rtnl_message_routing_policy_rule_get_flags(message, &flags);
922 if (r < 0) {
923 log_warning_errno(r, "rtnl: received rule message without valid flag, ignoring: %m");
924 return 0;
925 }
926 tmp->invert_rule = flags & FIB_RULE_INVERT;
927
928 r = sd_netlink_message_read_u32(message, FRA_FWMARK, &tmp->fwmark);
929 if (r < 0 && r != -ENODATA) {
930 log_warning_errno(r, "rtnl: could not get FRA_FWMARK attribute, ignoring: %m");
931 return 0;
932 }
933
934 r = sd_netlink_message_read_u32(message, FRA_FWMASK, &tmp->fwmask);
935 if (r < 0 && r != -ENODATA) {
936 log_warning_errno(r, "rtnl: could not get FRA_FWMASK attribute, ignoring: %m");
937 return 0;
938 }
939
940 r = sd_netlink_message_read_u32(message, FRA_PRIORITY, &tmp->priority);
941 if (r < 0 && r != -ENODATA) {
942 log_warning_errno(r, "rtnl: could not get FRA_PRIORITY attribute, ignoring: %m");
943 return 0;
944 }
945
946 r = sd_netlink_message_read_u32(message, FRA_TABLE, &tmp->table);
947 if (r < 0 && r != -ENODATA) {
948 log_warning_errno(r, "rtnl: could not get FRA_TABLE attribute, ignoring: %m");
949 return 0;
950 }
951
952 r = sd_rtnl_message_routing_policy_rule_get_tos(message, &tmp->tos);
953 if (r < 0 && r != -ENODATA) {
954 log_warning_errno(r, "rtnl: could not get FIB rule TOS, ignoring: %m");
955 return 0;
956 }
957
958 r = sd_rtnl_message_routing_policy_rule_get_fib_type(message, &tmp->type);
959 if (r < 0 && r != -ENODATA) {
960 log_warning_errno(r, "rtnl: could not get FIB rule type, ignoring: %m");
961 return 0;
962 }
963
964 r = sd_netlink_message_read_string(message, FRA_IIFNAME, &iif);
965 if (r < 0 && r != -ENODATA) {
966 log_warning_errno(r, "rtnl: could not get FRA_IIFNAME attribute, ignoring: %m");
967 return 0;
968 }
969 r = free_and_strdup(&tmp->iif, iif);
970 if (r < 0)
971 return log_oom();
972
973 r = sd_netlink_message_read_string(message, FRA_OIFNAME, &oif);
974 if (r < 0 && r != -ENODATA) {
975 log_warning_errno(r, "rtnl: could not get FRA_OIFNAME attribute, ignoring: %m");
976 return 0;
977 }
978 r = free_and_strdup(&tmp->oif, oif);
979 if (r < 0)
980 return log_oom();
981
982 r = sd_netlink_message_read_u8(message, FRA_IP_PROTO, &tmp->ipproto);
983 if (r < 0 && r != -ENODATA) {
984 log_warning_errno(r, "rtnl: could not get FRA_IP_PROTO attribute, ignoring: %m");
985 return 0;
986 }
987
988 r = sd_netlink_message_read_u8(message, FRA_PROTOCOL, &tmp->protocol);
989 if (r == -ENODATA)
990 /* If FRA_PROTOCOL is supported by kernel, then the attribute is always appended.
991 * When the received message does not have FRA_PROTOCOL, then we need to adjust the
992 * protocol of the rule later. */
993 adjust_protocol = true;
994 else if (r < 0) {
995 log_warning_errno(r, "rtnl: could not get FRA_PROTOCOL attribute, ignoring: %m");
996 return 0;
997 }
998
999 r = sd_netlink_message_read_u8(message, FRA_L3MDEV, &tmp->l3mdev);
1000 if (r < 0 && r != -ENODATA) {
1001 log_warning_errno(r, "rtnl: could not get FRA_L3MDEV attribute, ignoring: %m");
1002 return 0;
1003 }
1004
1005 r = sd_netlink_message_read(message, FRA_SPORT_RANGE, sizeof(tmp->sport), &tmp->sport);
1006 if (r < 0 && r != -ENODATA) {
1007 log_warning_errno(r, "rtnl: could not get FRA_SPORT_RANGE attribute, ignoring: %m");
1008 return 0;
1009 }
1010
1011 r = sd_netlink_message_read(message, FRA_DPORT_RANGE, sizeof(tmp->dport), &tmp->dport);
1012 if (r < 0 && r != -ENODATA) {
1013 log_warning_errno(r, "rtnl: could not get FRA_DPORT_RANGE attribute, ignoring: %m");
1014 return 0;
1015 }
1016
1017 r = sd_netlink_message_read(message, FRA_UID_RANGE, sizeof(tmp->uid_range), &tmp->uid_range);
1018 if (r < 0 && r != -ENODATA) {
1019 log_warning_errno(r, "rtnl: could not get FRA_UID_RANGE attribute, ignoring: %m");
1020 return 0;
1021 }
1022
1023 r = sd_netlink_message_read_u32(message, FRA_SUPPRESS_PREFIXLEN, &suppress_prefixlen);
1024 if (r < 0 && r != -ENODATA) {
1025 log_warning_errno(r, "rtnl: could not get FRA_SUPPRESS_PREFIXLEN attribute, ignoring: %m");
1026 return 0;
1027 }
1028 if (r >= 0)
1029 tmp->suppress_prefixlen = (int) suppress_prefixlen;
1030
1031 if (adjust_protocol)
1032 /* As .network files does not have setting to specify protocol, we can assume the
1033 * protocol of the received rule is RTPROT_KERNEL or RTPROT_STATIC. */
1034 tmp->protocol = routing_policy_rule_is_created_by_kernel(tmp) ? RTPROT_KERNEL : RTPROT_STATIC;
1035
1036 (void) routing_policy_rule_get(m, tmp, &rule);
1037
1038 switch (type) {
1039 case RTM_NEWRULE:
1040 if (rule)
1041 log_routing_policy_rule_debug(tmp, "Received remembered", NULL, m);
1042 else if (!m->manage_foreign_routes)
1043 log_routing_policy_rule_debug(tmp, "Ignoring received foreign", NULL, m);
1044 else {
1045 log_routing_policy_rule_debug(tmp, "Remembering foreign", NULL, m);
1046 r = routing_policy_rule_consume_foreign(m, TAKE_PTR(tmp));
1047 if (r < 0)
1048 log_warning_errno(r, "Could not remember foreign rule, ignoring: %m");
1049 }
1050 break;
1051 case RTM_DELRULE:
1052 if (rule) {
1053 log_routing_policy_rule_debug(tmp, "Forgetting", NULL, m);
1054 routing_policy_rule_free(rule);
1055 } else
1056 log_routing_policy_rule_debug(tmp, "Kernel removed unknown", NULL, m);
1057 break;
1058
1059 default:
1060 assert_not_reached("Received invalid RTNL message type");
1061 }
1062
1063 return 1;
1064 }
1065
1066 static int parse_fwmark_fwmask(const char *s, uint32_t *ret_fwmark, uint32_t *ret_fwmask) {
1067 _cleanup_free_ char *fwmark_str = NULL;
1068 uint32_t fwmark, fwmask = 0;
1069 const char *slash;
1070 int r;
1071
1072 assert(s);
1073 assert(ret_fwmark);
1074 assert(ret_fwmask);
1075
1076 slash = strchr(s, '/');
1077 if (slash) {
1078 fwmark_str = strndup(s, slash - s);
1079 if (!fwmark_str)
1080 return -ENOMEM;
1081 }
1082
1083 r = safe_atou32(fwmark_str ?: s, &fwmark);
1084 if (r < 0)
1085 return r;
1086
1087 if (fwmark > 0) {
1088 if (slash) {
1089 r = safe_atou32(slash + 1, &fwmask);
1090 if (r < 0)
1091 return r;
1092 } else
1093 fwmask = UINT32_MAX;
1094 }
1095
1096 *ret_fwmark = fwmark;
1097 *ret_fwmask = fwmask;
1098
1099 return 0;
1100 }
1101
1102 int config_parse_routing_policy_rule_tos(
1103 const char *unit,
1104 const char *filename,
1105 unsigned line,
1106 const char *section,
1107 unsigned section_line,
1108 const char *lvalue,
1109 int ltype,
1110 const char *rvalue,
1111 void *data,
1112 void *userdata) {
1113
1114 _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
1115 Network *network = userdata;
1116 int r;
1117
1118 assert(filename);
1119 assert(section);
1120 assert(lvalue);
1121 assert(rvalue);
1122 assert(data);
1123
1124 r = routing_policy_rule_new_static(network, filename, section_line, &n);
1125 if (r < 0)
1126 return log_oom();
1127
1128 r = safe_atou8(rvalue, &n->tos);
1129 if (r < 0) {
1130 log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse RPDB rule TOS, ignoring: %s", rvalue);
1131 return 0;
1132 }
1133
1134 TAKE_PTR(n);
1135 return 0;
1136 }
1137
1138 int config_parse_routing_policy_rule_priority(
1139 const char *unit,
1140 const char *filename,
1141 unsigned line,
1142 const char *section,
1143 unsigned section_line,
1144 const char *lvalue,
1145 int ltype,
1146 const char *rvalue,
1147 void *data,
1148 void *userdata) {
1149
1150 _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
1151 Network *network = userdata;
1152 int r;
1153
1154 assert(filename);
1155 assert(section);
1156 assert(lvalue);
1157 assert(rvalue);
1158 assert(data);
1159
1160 r = routing_policy_rule_new_static(network, filename, section_line, &n);
1161 if (r < 0)
1162 return log_oom();
1163
1164 r = safe_atou32(rvalue, &n->priority);
1165 if (r < 0) {
1166 log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse RPDB rule priority, ignoring: %s", rvalue);
1167 return 0;
1168 }
1169
1170 TAKE_PTR(n);
1171 return 0;
1172 }
1173
1174 int config_parse_routing_policy_rule_table(
1175 const char *unit,
1176 const char *filename,
1177 unsigned line,
1178 const char *section,
1179 unsigned section_line,
1180 const char *lvalue,
1181 int ltype,
1182 const char *rvalue,
1183 void *data,
1184 void *userdata) {
1185
1186 _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
1187 Network *network = userdata;
1188 int r;
1189
1190 assert(filename);
1191 assert(section);
1192 assert(lvalue);
1193 assert(rvalue);
1194 assert(data);
1195
1196 r = routing_policy_rule_new_static(network, filename, section_line, &n);
1197 if (r < 0)
1198 return log_oom();
1199
1200 r = manager_get_route_table_from_string(network->manager, rvalue, &n->table);
1201 if (r < 0) {
1202 log_syntax(unit, LOG_WARNING, filename, line, r,
1203 "Could not parse RPDB rule route table number \"%s\", ignoring assignment: %m", rvalue);
1204 return 0;
1205 }
1206
1207 TAKE_PTR(n);
1208 return 0;
1209 }
1210
1211 int config_parse_routing_policy_rule_fwmark_mask(
1212 const char *unit,
1213 const char *filename,
1214 unsigned line,
1215 const char *section,
1216 unsigned section_line,
1217 const char *lvalue,
1218 int ltype,
1219 const char *rvalue,
1220 void *data,
1221 void *userdata) {
1222
1223 _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
1224 Network *network = userdata;
1225 int r;
1226
1227 assert(filename);
1228 assert(section);
1229 assert(lvalue);
1230 assert(rvalue);
1231 assert(data);
1232
1233 r = routing_policy_rule_new_static(network, filename, section_line, &n);
1234 if (r < 0)
1235 return log_oom();
1236
1237 r = parse_fwmark_fwmask(rvalue, &n->fwmark, &n->fwmask);
1238 if (r < 0) {
1239 log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", rvalue);
1240 return 0;
1241 }
1242
1243 TAKE_PTR(n);
1244 return 0;
1245 }
1246
1247 int config_parse_routing_policy_rule_prefix(
1248 const char *unit,
1249 const char *filename,
1250 unsigned line,
1251 const char *section,
1252 unsigned section_line,
1253 const char *lvalue,
1254 int ltype,
1255 const char *rvalue,
1256 void *data,
1257 void *userdata) {
1258
1259 _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
1260 Network *network = userdata;
1261 union in_addr_union *buffer;
1262 uint8_t *prefixlen;
1263 int r;
1264
1265 assert(filename);
1266 assert(section);
1267 assert(lvalue);
1268 assert(rvalue);
1269 assert(data);
1270
1271 r = routing_policy_rule_new_static(network, filename, section_line, &n);
1272 if (r < 0)
1273 return log_oom();
1274
1275 if (streq(lvalue, "To")) {
1276 buffer = &n->to;
1277 prefixlen = &n->to_prefixlen;
1278 } else {
1279 buffer = &n->from;
1280 prefixlen = &n->from_prefixlen;
1281 }
1282
1283 if (n->family == AF_UNSPEC)
1284 r = in_addr_prefix_from_string_auto(rvalue, &n->family, buffer, prefixlen);
1285 else
1286 r = in_addr_prefix_from_string(rvalue, n->family, buffer, prefixlen);
1287 if (r < 0) {
1288 log_syntax(unit, LOG_WARNING, filename, line, r, "RPDB rule prefix is invalid, ignoring assignment: %s", rvalue);
1289 return 0;
1290 }
1291
1292 TAKE_PTR(n);
1293 return 0;
1294 }
1295
1296 int config_parse_routing_policy_rule_device(
1297 const char *unit,
1298 const char *filename,
1299 unsigned line,
1300 const char *section,
1301 unsigned section_line,
1302 const char *lvalue,
1303 int ltype,
1304 const char *rvalue,
1305 void *data,
1306 void *userdata) {
1307
1308 _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
1309 Network *network = userdata;
1310 int r;
1311
1312 assert(filename);
1313 assert(section);
1314 assert(lvalue);
1315 assert(rvalue);
1316 assert(data);
1317
1318 r = routing_policy_rule_new_static(network, filename, section_line, &n);
1319 if (r < 0)
1320 return log_oom();
1321
1322 if (!ifname_valid(rvalue)) {
1323 log_syntax(unit, LOG_WARNING, filename, line, 0,
1324 "Invalid interface name '%s' in %s=, ignoring assignment.", rvalue, lvalue);
1325 return 0;
1326 }
1327
1328 r = free_and_strdup(streq(lvalue, "IncomingInterface") ? &n->iif : &n->oif, rvalue);
1329 if (r < 0)
1330 return log_oom();
1331
1332 TAKE_PTR(n);
1333 return 0;
1334 }
1335
1336 int config_parse_routing_policy_rule_port_range(
1337 const char *unit,
1338 const char *filename,
1339 unsigned line,
1340 const char *section,
1341 unsigned section_line,
1342 const char *lvalue,
1343 int ltype,
1344 const char *rvalue,
1345 void *data,
1346 void *userdata) {
1347
1348 _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
1349 Network *network = userdata;
1350 uint16_t low, high;
1351 int r;
1352
1353 assert(filename);
1354 assert(section);
1355 assert(lvalue);
1356 assert(rvalue);
1357 assert(data);
1358
1359 r = routing_policy_rule_new_static(network, filename, section_line, &n);
1360 if (r < 0)
1361 return log_oom();
1362
1363 r = parse_ip_port_range(rvalue, &low, &high);
1364 if (r < 0) {
1365 log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse routing policy rule port range '%s'", rvalue);
1366 return 0;
1367 }
1368
1369 if (streq(lvalue, "SourcePort")) {
1370 n->sport.start = low;
1371 n->sport.end = high;
1372 } else {
1373 n->dport.start = low;
1374 n->dport.end = high;
1375 }
1376
1377 TAKE_PTR(n);
1378 return 0;
1379 }
1380
1381 int config_parse_routing_policy_rule_ip_protocol(
1382 const char *unit,
1383 const char *filename,
1384 unsigned line,
1385 const char *section,
1386 unsigned section_line,
1387 const char *lvalue,
1388 int ltype,
1389 const char *rvalue,
1390 void *data,
1391 void *userdata) {
1392
1393 _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
1394 Network *network = userdata;
1395 int r;
1396
1397 assert(filename);
1398 assert(section);
1399 assert(lvalue);
1400 assert(rvalue);
1401 assert(data);
1402
1403 r = routing_policy_rule_new_static(network, filename, section_line, &n);
1404 if (r < 0)
1405 return log_oom();
1406
1407 r = parse_ip_protocol(rvalue);
1408 if (r < 0) {
1409 log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse IP protocol '%s' for routing policy rule, ignoring: %m", rvalue);
1410 return 0;
1411 }
1412
1413 n->ipproto = r;
1414
1415 TAKE_PTR(n);
1416 return 0;
1417 }
1418
1419 int config_parse_routing_policy_rule_invert(
1420 const char *unit,
1421 const char *filename,
1422 unsigned line,
1423 const char *section,
1424 unsigned section_line,
1425 const char *lvalue,
1426 int ltype,
1427 const char *rvalue,
1428 void *data,
1429 void *userdata) {
1430
1431 _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
1432 Network *network = userdata;
1433 int r;
1434
1435 assert(filename);
1436 assert(section);
1437 assert(lvalue);
1438 assert(rvalue);
1439 assert(data);
1440
1441 r = routing_policy_rule_new_static(network, filename, section_line, &n);
1442 if (r < 0)
1443 return log_oom();
1444
1445 r = parse_boolean(rvalue);
1446 if (r < 0) {
1447 log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse RPDB rule invert, ignoring: %s", rvalue);
1448 return 0;
1449 }
1450
1451 n->invert_rule = r;
1452
1453 TAKE_PTR(n);
1454 return 0;
1455 }
1456
1457 int config_parse_routing_policy_rule_family(
1458 const char *unit,
1459 const char *filename,
1460 unsigned line,
1461 const char *section,
1462 unsigned section_line,
1463 const char *lvalue,
1464 int ltype,
1465 const char *rvalue,
1466 void *data,
1467 void *userdata) {
1468
1469 _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
1470 Network *network = userdata;
1471 AddressFamily a;
1472 int r;
1473
1474 assert(filename);
1475 assert(section);
1476 assert(lvalue);
1477 assert(rvalue);
1478 assert(data);
1479
1480 r = routing_policy_rule_new_static(network, filename, section_line, &n);
1481 if (r < 0)
1482 return log_oom();
1483
1484 a = routing_policy_rule_address_family_from_string(rvalue);
1485 if (a < 0) {
1486 log_syntax(unit, LOG_WARNING, filename, line, a,
1487 "Invalid address family '%s', ignoring.", rvalue);
1488 return 0;
1489 }
1490
1491 n->address_family = a;
1492
1493 TAKE_PTR(n);
1494 return 0;
1495 }
1496
1497 int config_parse_routing_policy_rule_uid_range(
1498 const char *unit,
1499 const char *filename,
1500 unsigned line,
1501 const char *section,
1502 unsigned section_line,
1503 const char *lvalue,
1504 int ltype,
1505 const char *rvalue,
1506 void *data,
1507 void *userdata) {
1508
1509 _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
1510 Network *network = userdata;
1511 uid_t start, end;
1512 int r;
1513
1514 assert(filename);
1515 assert(section);
1516 assert(lvalue);
1517 assert(rvalue);
1518 assert(data);
1519
1520 r = routing_policy_rule_new_static(network, filename, section_line, &n);
1521 if (r < 0)
1522 return log_oom();
1523
1524 r = get_user_creds(&rvalue, &start, NULL, NULL, NULL, 0);
1525 if (r >= 0)
1526 end = start;
1527 else {
1528 r = parse_uid_range(rvalue, &start, &end);
1529 if (r < 0) {
1530 log_syntax(unit, LOG_WARNING, filename, line, r,
1531 "Invalid uid or uid range '%s', ignoring: %m", rvalue);
1532 return 0;
1533 }
1534 }
1535
1536 n->uid_range.start = start;
1537 n->uid_range.end = end;
1538
1539 TAKE_PTR(n);
1540 return 0;
1541 }
1542
1543 int config_parse_routing_policy_rule_suppress_prefixlen(
1544 const char *unit,
1545 const char *filename,
1546 unsigned line,
1547 const char *section,
1548 unsigned section_line,
1549 const char *lvalue,
1550 int ltype,
1551 const char *rvalue,
1552 void *data,
1553 void *userdata) {
1554
1555 _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
1556 Network *network = userdata;
1557 int r;
1558
1559 assert(filename);
1560 assert(section);
1561 assert(lvalue);
1562 assert(rvalue);
1563 assert(data);
1564
1565 r = routing_policy_rule_new_static(network, filename, section_line, &n);
1566 if (r < 0)
1567 return log_oom();
1568
1569 r = parse_ip_prefix_length(rvalue, &n->suppress_prefixlen);
1570 if (r == -ERANGE) {
1571 log_syntax(unit, LOG_WARNING, filename, line, r, "Prefix length outside of valid range 0-128, ignoring: %s", rvalue);
1572 return 0;
1573 }
1574 if (r < 0) {
1575 log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse RPDB rule suppress_prefixlen, ignoring: %s", rvalue);
1576 return 0;
1577 }
1578
1579 TAKE_PTR(n);
1580 return 0;
1581 }
1582
1583 int config_parse_routing_policy_rule_type(
1584 const char *unit,
1585 const char *filename,
1586 unsigned line,
1587 const char *section,
1588 unsigned section_line,
1589 const char *lvalue,
1590 int ltype,
1591 const char *rvalue,
1592 void *data,
1593 void *userdata) {
1594
1595 _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
1596 Network *network = userdata;
1597 int r, t;
1598
1599 assert(filename);
1600 assert(section);
1601 assert(lvalue);
1602 assert(rvalue);
1603 assert(data);
1604
1605 r = routing_policy_rule_new_static(network, filename, section_line, &n);
1606 if (r < 0)
1607 return log_oom();
1608
1609 t = fr_act_type_from_string(rvalue);
1610 if (t < 0) {
1611 log_syntax(unit, LOG_WARNING, filename, line, t,
1612 "Could not parse FIB rule type \"%s\", ignoring assignment: %m", rvalue);
1613 return 0;
1614 }
1615
1616 n->type = (uint8_t) t;
1617
1618 TAKE_PTR(n);
1619 return 0;
1620 }
1621
1622 static int routing_policy_rule_section_verify(RoutingPolicyRule *rule) {
1623 if (section_is_invalid(rule->section))
1624 return -EINVAL;
1625
1626 if ((rule->family == AF_INET && FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6)) ||
1627 (rule->family == AF_INET6 && FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4)))
1628 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1629 "%s: address family specified by Family= conflicts with the address "
1630 "specified by To= or From=. Ignoring [RoutingPolicyRule] section from line %u.",
1631 rule->section->filename, rule->section->line);
1632
1633 if (rule->family == AF_UNSPEC) {
1634 if (IN_SET(rule->address_family, ADDRESS_FAMILY_IPV4, ADDRESS_FAMILY_NO))
1635 rule->family = AF_INET;
1636 else if (rule->address_family == ADDRESS_FAMILY_IPV6)
1637 rule->family = AF_INET6;
1638 /* rule->family can be AF_UNSPEC only when Family=both. */
1639 }
1640
1641 /* Currently, [RoutingPolicyRule] does not have a setting to set FRA_L3MDEV flag. Please also
1642 * update routing_policy_rule_is_created_by_kernel() when a new setting which sets the flag is
1643 * added in the future. */
1644 if (rule->l3mdev > 0)
1645 assert_not_reached("FRA_L3MDEV flag should not be configured.");
1646
1647 return 0;
1648 }
1649
1650 void network_drop_invalid_routing_policy_rules(Network *network) {
1651 RoutingPolicyRule *rule;
1652
1653 assert(network);
1654
1655 HASHMAP_FOREACH(rule, network->rules_by_section)
1656 if (routing_policy_rule_section_verify(rule) < 0)
1657 routing_policy_rule_free(rule);
1658 }