]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-util.c
Merge pull request #18007 from fw-strlen/ipv6_masq_and_dnat
[thirdparty/systemd.git] / src / network / networkd-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "condition.h"
4 #include "conf-parser.h"
5 #include "networkd-util.h"
6 #include "parse-util.h"
7 #include "string-table.h"
8 #include "string-util.h"
9 #include "util.h"
10
11 static const char* const address_family_table[_ADDRESS_FAMILY_MAX] = {
12 [ADDRESS_FAMILY_NO] = "no",
13 [ADDRESS_FAMILY_YES] = "yes",
14 [ADDRESS_FAMILY_IPV4] = "ipv4",
15 [ADDRESS_FAMILY_IPV6] = "ipv6",
16 };
17
18 static const char* const routing_policy_rule_address_family_table[_ADDRESS_FAMILY_MAX] = {
19 [ADDRESS_FAMILY_YES] = "both",
20 [ADDRESS_FAMILY_IPV4] = "ipv4",
21 [ADDRESS_FAMILY_IPV6] = "ipv6",
22 };
23
24 static const char* const duplicate_address_detection_address_family_table[_ADDRESS_FAMILY_MAX] = {
25 [ADDRESS_FAMILY_NO] = "none",
26 [ADDRESS_FAMILY_YES] = "both",
27 [ADDRESS_FAMILY_IPV4] = "ipv4",
28 [ADDRESS_FAMILY_IPV6] = "ipv6",
29 };
30
31 static const char* const dhcp_deprecated_address_family_table[_ADDRESS_FAMILY_MAX] = {
32 [ADDRESS_FAMILY_NO] = "none",
33 [ADDRESS_FAMILY_YES] = "both",
34 [ADDRESS_FAMILY_IPV4] = "v4",
35 [ADDRESS_FAMILY_IPV6] = "v6",
36 };
37
38 static const char* const dhcp_lease_server_type_table[_SD_DHCP_LEASE_SERVER_TYPE_MAX] = {
39 [SD_DHCP_LEASE_DNS] = "DNS servers",
40 [SD_DHCP_LEASE_NTP] = "NTP servers",
41 [SD_DHCP_LEASE_SIP] = "SIP servers",
42 [SD_DHCP_LEASE_POP3] = "POP3 servers",
43 [SD_DHCP_LEASE_SMTP] = "SMTP servers",
44 [SD_DHCP_LEASE_LPR] = "LPR servers",
45 };
46
47 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(address_family, AddressFamily, ADDRESS_FAMILY_YES);
48
49 AddressFamily link_local_address_family_from_string(const char *s) {
50 if (streq_ptr(s, "fallback")) /* compat name */
51 return ADDRESS_FAMILY_YES;
52 if (streq_ptr(s, "fallback-ipv4")) /* compat name */
53 return ADDRESS_FAMILY_IPV4;
54 return address_family_from_string(s);
55 }
56
57 DEFINE_STRING_TABLE_LOOKUP(routing_policy_rule_address_family, AddressFamily);
58 DEFINE_STRING_TABLE_LOOKUP(duplicate_address_detection_address_family, AddressFamily);
59 DEFINE_CONFIG_PARSE_ENUM(config_parse_link_local_address_family, link_local_address_family,
60 AddressFamily, "Failed to parse option");
61 DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_deprecated_address_family, AddressFamily);
62 DEFINE_STRING_TABLE_LOOKUP(dhcp_lease_server_type, sd_dhcp_lease_server_type);
63
64 static AddressFamily address_family_compat_from_string(const char *s) {
65 if (streq_ptr(s, "yes")) /* compat name */
66 return ADDRESS_FAMILY_IPV4;
67 if (streq_ptr(s, "both"))
68 return ADDRESS_FAMILY_YES;
69 return address_family_from_string(s);
70 }
71 DEFINE_CONFIG_PARSE_ENUM(config_parse_address_family_compat, address_family_compat,
72 AddressFamily, "Failed to parse option");
73
74 int config_parse_address_family_with_kernel(
75 const char* unit,
76 const char *filename,
77 unsigned line,
78 const char *section,
79 unsigned section_line,
80 const char *lvalue,
81 int ltype,
82 const char *rvalue,
83 void *data,
84 void *userdata) {
85
86 AddressFamily *fwd = data, s;
87
88 assert(filename);
89 assert(lvalue);
90 assert(rvalue);
91 assert(data);
92
93 /* This function is mostly obsolete now. It simply redirects
94 * "kernel" to "no". In older networkd versions we used to
95 * distinguish IPForward=off from IPForward=kernel, where the
96 * former would explicitly turn off forwarding while the
97 * latter would simply not touch the setting. But that logic
98 * is gone, hence silently accept the old setting, but turn it
99 * to "no". */
100
101 s = address_family_from_string(rvalue);
102 if (s < 0) {
103 if (streq(rvalue, "kernel"))
104 s = ADDRESS_FAMILY_NO;
105 else {
106 log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse IPForward= option, ignoring: %s", rvalue);
107 return 0;
108 }
109 }
110
111 *fwd = s;
112
113 return 0;
114 }
115
116 /* Router lifetime can be set with netlink interface since kernel >= 4.5
117 * so for the supported kernel we don't need to expire routes in userspace */
118 int kernel_route_expiration_supported(void) {
119 static int cached = -1;
120 int r;
121
122 if (cached < 0) {
123 Condition c = {
124 .type = CONDITION_KERNEL_VERSION,
125 .parameter = (char *) ">= 4.5"
126 };
127 r = condition_test(&c, NULL);
128 if (r < 0)
129 return r;
130
131 cached = r;
132 }
133 return cached;
134 }
135
136 static void network_config_hash_func(const NetworkConfigSection *c, struct siphash *state) {
137 siphash24_compress_string(c->filename, state);
138 siphash24_compress(&c->line, sizeof(c->line), state);
139 }
140
141 static int network_config_compare_func(const NetworkConfigSection *x, const NetworkConfigSection *y) {
142 int r;
143
144 r = strcmp(x->filename, y->filename);
145 if (r != 0)
146 return r;
147
148 return CMP(x->line, y->line);
149 }
150
151 DEFINE_HASH_OPS(network_config_hash_ops, NetworkConfigSection, network_config_hash_func, network_config_compare_func);
152
153 int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s) {
154 NetworkConfigSection *cs;
155
156 cs = malloc0(offsetof(NetworkConfigSection, filename) + strlen(filename) + 1);
157 if (!cs)
158 return -ENOMEM;
159
160 strcpy(cs->filename, filename);
161 cs->line = line;
162
163 *s = TAKE_PTR(cs);
164
165 return 0;
166 }
167
168 unsigned hashmap_find_free_section_line(Hashmap *hashmap) {
169 NetworkConfigSection *cs;
170 unsigned n = 0;
171 void *entry;
172
173 HASHMAP_FOREACH_KEY(entry, cs, hashmap)
174 if (n < cs->line)
175 n = cs->line;
176
177 return n + 1;
178 }