]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-util.c
Merge pull request #18863 from keszybz/cmdline-escaping
[thirdparty/systemd.git] / src / network / networkd-util.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
fc2f9534 2
f02ba163 3#include "condition.h"
fc2f9534 4#include "conf-parser.h"
fd221544 5#include "networkd-link.h"
fc2f9534 6#include "networkd-util.h"
6bedfcbb 7#include "parse-util.h"
8b43440b 8#include "string-table.h"
07630cea
LP
9#include "string-util.h"
10#include "util.h"
fc2f9534 11
ddc026f3 12static const char* const address_family_table[_ADDRESS_FAMILY_MAX] = {
135c4aad
LP
13 [ADDRESS_FAMILY_NO] = "no",
14 [ADDRESS_FAMILY_YES] = "yes",
15 [ADDRESS_FAMILY_IPV4] = "ipv4",
16 [ADDRESS_FAMILY_IPV6] = "ipv6",
e800fd24
YW
17};
18
ddc026f3 19static const char* const routing_policy_rule_address_family_table[_ADDRESS_FAMILY_MAX] = {
135c4aad
LP
20 [ADDRESS_FAMILY_YES] = "both",
21 [ADDRESS_FAMILY_IPV4] = "ipv4",
22 [ADDRESS_FAMILY_IPV6] = "ipv6",
f6c6ff97
YW
23};
24
f1923efc 25static const char* const nexthop_address_family_table[_ADDRESS_FAMILY_MAX] = {
135c4aad
LP
26 [ADDRESS_FAMILY_IPV4] = "ipv4",
27 [ADDRESS_FAMILY_IPV6] = "ipv6",
f1923efc
YW
28};
29
ddc026f3 30static const char* const duplicate_address_detection_address_family_table[_ADDRESS_FAMILY_MAX] = {
135c4aad
LP
31 [ADDRESS_FAMILY_NO] = "none",
32 [ADDRESS_FAMILY_YES] = "both",
33 [ADDRESS_FAMILY_IPV4] = "ipv4",
34 [ADDRESS_FAMILY_IPV6] = "ipv6",
051e77ca
SS
35};
36
bde8467a 37static const char* const dhcp_deprecated_address_family_table[_ADDRESS_FAMILY_MAX] = {
135c4aad
LP
38 [ADDRESS_FAMILY_NO] = "none",
39 [ADDRESS_FAMILY_YES] = "both",
40 [ADDRESS_FAMILY_IPV4] = "v4",
41 [ADDRESS_FAMILY_IPV6] = "v6",
bde8467a
YW
42};
43
4c72d851
YW
44static const char* const ip_masquerade_address_family_table[_ADDRESS_FAMILY_MAX] = {
45 [ADDRESS_FAMILY_NO] = "no",
46 [ADDRESS_FAMILY_YES] = "both",
47 [ADDRESS_FAMILY_IPV4] = "ipv4",
48 [ADDRESS_FAMILY_IPV6] = "ipv6",
49};
50
ddb82ec2
LP
51static const char* const dhcp_lease_server_type_table[_SD_DHCP_LEASE_SERVER_TYPE_MAX] = {
52 [SD_DHCP_LEASE_DNS] = "DNS servers",
53 [SD_DHCP_LEASE_NTP] = "NTP servers",
54 [SD_DHCP_LEASE_SIP] = "SIP servers",
55 [SD_DHCP_LEASE_POP3] = "POP3 servers",
56 [SD_DHCP_LEASE_SMTP] = "SMTP servers",
57 [SD_DHCP_LEASE_LPR] = "LPR servers",
ddc026f3
ZJS
58};
59
2d792895 60DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(address_family, AddressFamily, ADDRESS_FAMILY_YES);
3ca1fab7
ZJS
61
62AddressFamily link_local_address_family_from_string(const char *s) {
63 if (streq_ptr(s, "fallback")) /* compat name */
64 return ADDRESS_FAMILY_YES;
65 if (streq_ptr(s, "fallback-ipv4")) /* compat name */
66 return ADDRESS_FAMILY_IPV4;
67 return address_family_from_string(s);
68}
69
f6c6ff97 70DEFINE_STRING_TABLE_LOOKUP(routing_policy_rule_address_family, AddressFamily);
f1923efc 71DEFINE_STRING_TABLE_LOOKUP(nexthop_address_family, AddressFamily);
051e77ca 72DEFINE_STRING_TABLE_LOOKUP(duplicate_address_detection_address_family, AddressFamily);
2d792895
YW
73DEFINE_CONFIG_PARSE_ENUM(config_parse_link_local_address_family, link_local_address_family,
74 AddressFamily, "Failed to parse option");
bde8467a 75DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_deprecated_address_family, AddressFamily);
4c72d851 76DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(ip_masquerade_address_family, AddressFamily);
2324fd3a 77DEFINE_STRING_TABLE_LOOKUP(dhcp_lease_server_type, sd_dhcp_lease_server_type_t);
fc2f9534 78
2d792895 79int config_parse_address_family_with_kernel(
fc2f9534
LP
80 const char* unit,
81 const char *filename,
82 unsigned line,
83 const char *section,
84 unsigned section_line,
85 const char *lvalue,
86 int ltype,
87 const char *rvalue,
88 void *data,
89 void *userdata) {
90
2d792895 91 AddressFamily *fwd = data, s;
fc2f9534
LP
92
93 assert(filename);
94 assert(lvalue);
95 assert(rvalue);
96 assert(data);
97
765afd5c
LP
98 /* This function is mostly obsolete now. It simply redirects
99 * "kernel" to "no". In older networkd versions we used to
5238e957 100 * distinguish IPForward=off from IPForward=kernel, where the
765afd5c
LP
101 * former would explicitly turn off forwarding while the
102 * latter would simply not touch the setting. But that logic
103 * is gone, hence silently accept the old setting, but turn it
104 * to "no". */
105
2d792895 106 s = address_family_from_string(rvalue);
fc2f9534
LP
107 if (s < 0) {
108 if (streq(rvalue, "kernel"))
765afd5c 109 s = ADDRESS_FAMILY_NO;
fc2f9534 110 else {
d96edb2c 111 log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse IPForward= option, ignoring: %s", rvalue);
fc2f9534
LP
112 return 0;
113 }
114 }
115
116 *fwd = s;
117
118 return 0;
119}
f02ba163 120
4c72d851
YW
121int config_parse_ip_masquerade(
122 const char *unit,
123 const char *filename,
124 unsigned line,
125 const char *section,
126 unsigned section_line,
127 const char *lvalue,
128 int ltype,
129 const char *rvalue,
130 void *data,
131 void *userdata) {
132
133 AddressFamily a, *ret = data;
134 int r;
135
136 if (isempty(rvalue)) {
137 *ret = ADDRESS_FAMILY_NO;
138 return 0;
139 }
140
141 r = parse_boolean(rvalue);
142 if (r >= 0) {
143 if (r)
144 log_syntax(unit, LOG_WARNING, filename, line, 0,
145 "IPMasquerade=%s is deprecated, and it is handled as \"ipv4\" instead of \"both\". "
146 "Please use \"ipv4\" or \"both\".",
147 rvalue);
148
149 *ret = r ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_NO;
150 return 0;
151 }
152
153 a = ip_masquerade_address_family_from_string(rvalue);
154 if (a < 0) {
155 log_syntax(unit, LOG_WARNING, filename, line, a,
156 "Failed to parse IPMasquerade= setting, ignoring assignment: %s", rvalue);
157 return 0;
158 }
159
160 *ret = a;
161 return 0;
162}
163
f02ba163 164/* Router lifetime can be set with netlink interface since kernel >= 4.5
5238e957 165 * so for the supported kernel we don't need to expire routes in userspace */
f02ba163
DD
166int kernel_route_expiration_supported(void) {
167 static int cached = -1;
168 int r;
169
170 if (cached < 0) {
171 Condition c = {
172 .type = CONDITION_KERNEL_VERSION,
173 .parameter = (char *) ">= 4.5"
174 };
a0b191b7 175 r = condition_test(&c, NULL);
f02ba163
DD
176 if (r < 0)
177 return r;
178
179 cached = r;
180 }
181 return cached;
182}
48315d3d
YW
183
184static void network_config_hash_func(const NetworkConfigSection *c, struct siphash *state) {
f281fc1e 185 siphash24_compress_string(c->filename, state);
48315d3d
YW
186 siphash24_compress(&c->line, sizeof(c->line), state);
187}
188
189static int network_config_compare_func(const NetworkConfigSection *x, const NetworkConfigSection *y) {
190 int r;
191
192 r = strcmp(x->filename, y->filename);
193 if (r != 0)
194 return r;
195
196 return CMP(x->line, y->line);
197}
198
199DEFINE_HASH_OPS(network_config_hash_ops, NetworkConfigSection, network_config_hash_func, network_config_compare_func);
200
201int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s) {
202 NetworkConfigSection *cs;
203
204 cs = malloc0(offsetof(NetworkConfigSection, filename) + strlen(filename) + 1);
205 if (!cs)
206 return -ENOMEM;
207
208 strcpy(cs->filename, filename);
209 cs->line = line;
210
211 *s = TAKE_PTR(cs);
212
213 return 0;
214}
215
833f3663
YW
216unsigned hashmap_find_free_section_line(Hashmap *hashmap) {
217 NetworkConfigSection *cs;
218 unsigned n = 0;
219 void *entry;
220
221 HASHMAP_FOREACH_KEY(entry, cs, hashmap)
222 if (n < cs->line)
223 n = cs->line;
224
225 return n + 1;
226}
fd221544
YW
227
228int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg) {
229 const char *err_msg = NULL;
230
231 /* link may be NULL. */
232
233 (void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg);
234 return log_link_full_errno(link, level, err,
235 "%s: %s%s%s%m",
236 msg,
237 strempty(err_msg),
238 err_msg && !endswith(err_msg, ".") ? "." : "",
239 err_msg ? " " : "");
240}