summaryrefslogtreecommitdiff
path: root/src/network/networkd-dhcp-common.c
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2022-10-28 12:55:59 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2022-10-28 15:48:28 +0900
commit6f812d289946a3e0e386378263b40d09e125752e (patch)
tree0d617bec9c7a5791cae07285fa4179dbda6c4eac /src/network/networkd-dhcp-common.c
parent6fadf01cf3cdd98f78b7829f4c6c892306958394 (diff)
downloadsystemd-6f812d289946a3e0e386378263b40d09e125752e.tar.gz
network: adjust route priority based on preference
Even if different preference is specified, the kernel merges multiple routes with the same preference. This is problematic when a network has multiple routers. Fixes #25138.
Diffstat (limited to 'src/network/networkd-dhcp-common.c')
-rw-r--r--src/network/networkd-dhcp-common.c73
1 files changed, 65 insertions, 8 deletions
diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c
index 6526d3378f..2a80b1766e 100644
--- a/src/network/networkd-dhcp-common.c
+++ b/src/network/networkd-dhcp-common.c
@@ -303,7 +303,7 @@ int config_parse_dhcp(
return 0;
}
-int config_parse_dhcp_or_ra_route_metric(
+int config_parse_dhcp_route_metric(
const char* unit,
const char *filename,
unsigned line,
@@ -321,7 +321,7 @@ int config_parse_dhcp_or_ra_route_metric(
assert(filename);
assert(lvalue);
- assert(IN_SET(ltype, AF_UNSPEC, AF_INET, AF_INET6));
+ assert(IN_SET(ltype, AF_UNSPEC, AF_INET));
assert(rvalue);
assert(data);
@@ -337,16 +337,15 @@ int config_parse_dhcp_or_ra_route_metric(
network->dhcp_route_metric = metric;
network->dhcp_route_metric_set = true;
break;
- case AF_INET6:
- network->ipv6_accept_ra_route_metric = metric;
- network->ipv6_accept_ra_route_metric_set = true;
- break;
case AF_UNSPEC:
/* For backward compatibility. */
if (!network->dhcp_route_metric_set)
network->dhcp_route_metric = metric;
- if (!network->ipv6_accept_ra_route_metric_set)
- network->ipv6_accept_ra_route_metric = metric;
+ if (!network->ipv6_accept_ra_route_metric_set) {
+ network->ipv6_accept_ra_route_metric_high = metric;
+ network->ipv6_accept_ra_route_metric_medium = metric;
+ network->ipv6_accept_ra_route_metric_low = metric;
+ }
break;
default:
assert_not_reached();
@@ -355,6 +354,64 @@ int config_parse_dhcp_or_ra_route_metric(
return 0;
}
+int config_parse_ipv6_accept_ra_route_metric(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Network *network = ASSERT_PTR(userdata);
+ uint32_t metric_high, metric_medium, metric_low;
+ int r, s, t;
+
+ assert(filename);
+ assert(rvalue);
+
+ if (safe_atou32(rvalue, &metric_low) >= 0)
+ metric_high = metric_medium = metric_low;
+ else {
+ _cleanup_free_ char *high = NULL, *medium = NULL, *low = NULL;
+ const char *p = rvalue;
+
+ r = extract_many_words(&p, ":", EXTRACT_DONT_COALESCE_SEPARATORS, &high, &medium, &low, NULL);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r != 3 || !isempty(p)) {
+ log_syntax(unit, LOG_WARNING, filename, line, r < 0 ? r : 0,
+ "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue);
+ return 0;
+ }
+
+ r = safe_atou32(high, &metric_high);
+ s = safe_atou32(medium, &metric_medium);
+ t = safe_atou32(low, &metric_low);
+ if (r < 0 || s < 0 || t < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r < 0 ? r : s < 0 ? s : t,
+ "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue);
+ return 0;
+ }
+
+ if (metric_high >= metric_medium || metric_medium >= metric_low) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Invalid RouteTable=%s, ignoring assignment: %m", rvalue);
+ return 0;
+ }
+ }
+
+ network->ipv6_accept_ra_route_metric_high = metric_high;
+ network->ipv6_accept_ra_route_metric_medium = metric_medium;
+ network->ipv6_accept_ra_route_metric_low = metric_low;
+ network->ipv6_accept_ra_route_metric_set = true;
+
+ return 0;
+}
+
int config_parse_dhcp_use_dns(
const char* unit,
const char *filename,