1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "condition.h"
4 #include "conf-parser.h"
5 #include "escape.h"
6 #include "networkd-link.h"
7 #include "networkd-util.h"
8 #include "parse-util.h"
9 #include "string-table.h"
10 #include "string-util.h"
11 #include "web-util.h"
12
13 /* This is used in log messages, and never used in parsing settings. So, upper cases are OK. */
14 static const char * const network_config_source_table[_NETWORK_CONFIG_SOURCE_MAX] = {
15 [NETWORK_CONFIG_SOURCE_FOREIGN] = "foreign",
16 [NETWORK_CONFIG_SOURCE_STATIC] = "static",
17 [NETWORK_CONFIG_SOURCE_IPV4LL] = "IPv4LL",
18 [NETWORK_CONFIG_SOURCE_DHCP4] = "DHCPv4",
19 [NETWORK_CONFIG_SOURCE_DHCP6] = "DHCPv6",
20 [NETWORK_CONFIG_SOURCE_DHCP_PD] = "DHCP-PD",
21 [NETWORK_CONFIG_SOURCE_NDISC] = "NDisc",
22 [NETWORK_CONFIG_SOURCE_RUNTIME] = "runtime",
23 };
24
25 DEFINE_STRING_TABLE_LOOKUP_TO_STRING(network_config_source, NetworkConfigSource);
26
network_config_state_to_string_alloc(NetworkConfigState s,char ** ret)27 int network_config_state_to_string_alloc(NetworkConfigState s, char **ret) {
28 static const char* states[] = {
29 [LOG2U(NETWORK_CONFIG_STATE_PROBING)] = "probing",
30 [LOG2U(NETWORK_CONFIG_STATE_REQUESTING)] = "requesting",
31 [LOG2U(NETWORK_CONFIG_STATE_CONFIGURING)] = "configuring",
32 [LOG2U(NETWORK_CONFIG_STATE_CONFIGURED)] = "configured",
33 [LOG2U(NETWORK_CONFIG_STATE_MARKED)] = "marked",
34 [LOG2U(NETWORK_CONFIG_STATE_REMOVING)] = "removing",
35 };
36 _cleanup_free_ char *buf = NULL;
37
38 assert(ret);
39
40 for (size_t i = 0; i < ELEMENTSOF(states); i++)
41 if (FLAGS_SET(s, 1 << i)) {
42 assert(states[i]);
43
44 if (!strextend_with_separator(&buf, ",", states[i]))
45 return -ENOMEM;
46 }
47
48 *ret = TAKE_PTR(buf);
49 return 0;
50 }
51
52 static const char * const address_family_table[_ADDRESS_FAMILY_MAX] = {
53 [ADDRESS_FAMILY_NO] = "no",
54 [ADDRESS_FAMILY_YES] = "yes",
55 [ADDRESS_FAMILY_IPV4] = "ipv4",
56 [ADDRESS_FAMILY_IPV6] = "ipv6",
57 };
58
59 static const char * const routing_policy_rule_address_family_table[_ADDRESS_FAMILY_MAX] = {
60 [ADDRESS_FAMILY_YES] = "both",
61 [ADDRESS_FAMILY_IPV4] = "ipv4",
62 [ADDRESS_FAMILY_IPV6] = "ipv6",
63 };
64
65 static const char * const nexthop_address_family_table[_ADDRESS_FAMILY_MAX] = {
66 [ADDRESS_FAMILY_IPV4] = "ipv4",
67 [ADDRESS_FAMILY_IPV6] = "ipv6",
68 };
69
70 static const char * const duplicate_address_detection_address_family_table[_ADDRESS_FAMILY_MAX] = {
71 [ADDRESS_FAMILY_NO] = "none",
72 [ADDRESS_FAMILY_YES] = "both",
73 [ADDRESS_FAMILY_IPV4] = "ipv4",
74 [ADDRESS_FAMILY_IPV6] = "ipv6",
75 };
76
77 static const char * const dhcp_deprecated_address_family_table[_ADDRESS_FAMILY_MAX] = {
78 [ADDRESS_FAMILY_NO] = "none",
79 [ADDRESS_FAMILY_YES] = "both",
80 [ADDRESS_FAMILY_IPV4] = "v4",
81 [ADDRESS_FAMILY_IPV6] = "v6",
82 };
83
84 static const char * const ip_masquerade_address_family_table[_ADDRESS_FAMILY_MAX] = {
85 [ADDRESS_FAMILY_NO] = "no",
86 [ADDRESS_FAMILY_YES] = "both",
87 [ADDRESS_FAMILY_IPV4] = "ipv4",
88 [ADDRESS_FAMILY_IPV6] = "ipv6",
89 };
90
91 static const char * const dhcp_lease_server_type_table[_SD_DHCP_LEASE_SERVER_TYPE_MAX] = {
92 [SD_DHCP_LEASE_DNS] = "DNS servers",
93 [SD_DHCP_LEASE_NTP] = "NTP servers",
94 [SD_DHCP_LEASE_SIP] = "SIP servers",
95 [SD_DHCP_LEASE_POP3] = "POP3 servers",
96 [SD_DHCP_LEASE_SMTP] = "SMTP servers",
97 [SD_DHCP_LEASE_LPR] = "LPR servers",
98 };
99
100 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(address_family, AddressFamily, ADDRESS_FAMILY_YES);
101
link_local_address_family_from_string(const char * s)102 AddressFamily link_local_address_family_from_string(const char *s) {
103 if (streq_ptr(s, "fallback")) /* compat name */
104 return ADDRESS_FAMILY_YES;
105 if (streq_ptr(s, "fallback-ipv4")) /* compat name */
106 return ADDRESS_FAMILY_IPV4;
107 return address_family_from_string(s);
108 }
109
110 DEFINE_STRING_TABLE_LOOKUP(routing_policy_rule_address_family, AddressFamily);
111 DEFINE_STRING_TABLE_LOOKUP(nexthop_address_family, AddressFamily);
112 DEFINE_STRING_TABLE_LOOKUP(duplicate_address_detection_address_family, AddressFamily);
113 DEFINE_CONFIG_PARSE_ENUM(config_parse_link_local_address_family, link_local_address_family,
114 AddressFamily, "Failed to parse option");
115 DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_deprecated_address_family, AddressFamily);
116 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(ip_masquerade_address_family, AddressFamily);
117 DEFINE_STRING_TABLE_LOOKUP(dhcp_lease_server_type, sd_dhcp_lease_server_type_t);
118
config_parse_address_family_with_kernel(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)119 int config_parse_address_family_with_kernel(
120 const char* unit,
121 const char *filename,
122 unsigned line,
123 const char *section,
124 unsigned section_line,
125 const char *lvalue,
126 int ltype,
127 const char *rvalue,
128 void *data,
129 void *userdata) {
130
131 AddressFamily *fwd = data, s;
132
133 assert(filename);
134 assert(lvalue);
135 assert(rvalue);
136 assert(data);
137
138 /* This function is mostly obsolete now. It simply redirects
139 * "kernel" to "no". In older networkd versions we used to
140 * distinguish IPForward=off from IPForward=kernel, where the
141 * former would explicitly turn off forwarding while the
142 * latter would simply not touch the setting. But that logic
143 * is gone, hence silently accept the old setting, but turn it
144 * to "no". */
145
146 s = address_family_from_string(rvalue);
147 if (s < 0) {
148 if (streq(rvalue, "kernel"))
149 s = ADDRESS_FAMILY_NO;
150 else {
151 log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse IPForward= option, ignoring: %s", rvalue);
152 return 0;
153 }
154 }
155
156 *fwd = s;
157
158 return 0;
159 }
160
config_parse_ip_masquerade(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)161 int config_parse_ip_masquerade(
162 const char *unit,
163 const char *filename,
164 unsigned line,
165 const char *section,
166 unsigned section_line,
167 const char *lvalue,
168 int ltype,
169 const char *rvalue,
170 void *data,
171 void *userdata) {
172
173 AddressFamily a, *ret = data;
174 int r;
175
176 if (isempty(rvalue)) {
177 *ret = ADDRESS_FAMILY_NO;
178 return 0;
179 }
180
181 r = parse_boolean(rvalue);
182 if (r >= 0) {
183 if (r)
184 log_syntax(unit, LOG_WARNING, filename, line, 0,
185 "IPMasquerade=%s is deprecated, and it is handled as \"ipv4\" instead of \"both\". "
186 "Please use \"ipv4\" or \"both\".",
187 rvalue);
188
189 *ret = r ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_NO;
190 return 0;
191 }
192
193 a = ip_masquerade_address_family_from_string(rvalue);
194 if (a < 0) {
195 log_syntax(unit, LOG_WARNING, filename, line, a,
196 "Failed to parse IPMasquerade= setting, ignoring assignment: %s", rvalue);
197 return 0;
198 }
199
200 *ret = a;
201 return 0;
202 }
203
config_parse_mud_url(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)204 int config_parse_mud_url(
205 const char *unit,
206 const char *filename,
207 unsigned line,
208 const char *section,
209 unsigned section_line,
210 const char *lvalue,
211 int ltype,
212 const char *rvalue,
213 void *data,
214 void *userdata) {
215
216 _cleanup_free_ char *unescaped = NULL;
217 char **url = data;
218 ssize_t l;
219
220 assert(filename);
221 assert(lvalue);
222 assert(rvalue);
223 assert(url);
224
225 if (isempty(rvalue)) {
226 *url = mfree(*url);
227 return 0;
228 }
229
230 l = cunescape(rvalue, 0, &unescaped);
231 if (l < 0) {
232 log_syntax(unit, LOG_WARNING, filename, line, l,
233 "Failed to unescape MUD URL, ignoring: %s", rvalue);
234 return 0;
235 }
236
237 if (l > UINT8_MAX || !http_url_is_valid(unescaped)) {
238 log_syntax(unit, LOG_WARNING, filename, line, 0,
239 "Invalid MUD URL, ignoring: %s", rvalue);
240 return 0;
241 }
242
243 return free_and_replace(*url, unescaped);
244 }
245
log_link_message_full_errno(Link * link,sd_netlink_message * m,int level,int err,const char * msg)246 int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg) {
247 const char *err_msg = NULL;
248
249 /* link may be NULL. */
250
251 (void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg);
252 return log_link_full_errno(link, level, err,
253 "%s: %s%s%s%m",
254 msg,
255 strempty(err_msg),
256 err_msg && !endswith(err_msg, ".") ? "." : "",
257 err_msg ? " " : "");
258 }
259