1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include "extract-word.h"
5 #include "ip-protocol-list.h"
7 #include "mountpoint-util.h"
8 #include "parse-helpers.h"
9 #include "parse-util.h"
10 #include "path-util.h"
13 int path_simplify_and_warn(
15 PathSimplifyWarnFlags flags
,
21 bool fatal
= flags
& PATH_CHECK_FATAL
;
22 int level
= fatal
? LOG_ERR
: LOG_WARNING
;
25 assert(!FLAGS_SET(flags
, PATH_CHECK_ABSOLUTE
| PATH_CHECK_RELATIVE
));
28 if (!utf8_is_valid(path
))
29 return log_syntax_invalid_utf8(unit
, LOG_ERR
, filename
, line
, path
);
31 if (flags
& (PATH_CHECK_ABSOLUTE
| PATH_CHECK_RELATIVE
)) {
34 absolute
= path_is_absolute(path
);
36 if (!absolute
&& (flags
& PATH_CHECK_ABSOLUTE
))
37 return log_syntax(unit
, level
, filename
, line
, SYNTHETIC_ERRNO(EINVAL
),
38 "%s= path is not absolute%s: %s",
39 lvalue
, fatal
? "" : ", ignoring", path
);
41 if (absolute
&& (flags
& PATH_CHECK_RELATIVE
))
42 return log_syntax(unit
, level
, filename
, line
, SYNTHETIC_ERRNO(EINVAL
),
43 "%s= path is absolute%s: %s",
44 lvalue
, fatal
? "" : ", ignoring", path
);
47 path_simplify_full(path
, flags
& PATH_KEEP_TRAILING_SLASH
? PATH_SIMPLIFY_KEEP_TRAILING_SLASH
: 0);
49 if (!path_is_valid(path
))
50 return log_syntax(unit
, level
, filename
, line
, SYNTHETIC_ERRNO(EINVAL
),
51 "%s= path has invalid length (%zu bytes)%s.",
52 lvalue
, strlen(path
), fatal
? "" : ", ignoring");
54 if (!path_is_normalized(path
))
55 return log_syntax(unit
, level
, filename
, line
, SYNTHETIC_ERRNO(EINVAL
),
56 "%s= path is not normalized%s: %s",
57 lvalue
, fatal
? "" : ", ignoring", path
);
59 if (FLAGS_SET(flags
, PATH_CHECK_NON_API_VFS
) && path_below_api_vfs(path
))
60 return log_syntax(unit
, level
, filename
, line
, SYNTHETIC_ERRNO(EINVAL
),
61 "%s= path is below API VFS%s: %s",
62 lvalue
, fatal
? ", refusing" : ", ignoring",
68 static int parse_af_token(
80 af
= af_from_ipv4_ipv6(token
);
88 static int parse_ip_protocol_token(
100 proto
= ip_protocol_from_tcp_udp(token
);
104 *ip_protocol
= proto
;
108 static int parse_ip_ports_token(
113 uint16_t *port_min
) {
121 if (streq(token
, "any"))
122 *nr_ports
= *port_min
= 0;
124 uint16_t mn
= 0, mx
= 0;
125 r
= parse_ip_port_range(token
, &mn
, &mx
, /* allow_zero = */ true);
129 *nr_ports
= mx
- mn
+ 1;
136 typedef int (*parse_token_f
)(
143 int parse_socket_bind_item(
148 uint16_t *port_min
) {
150 /* Order of token parsers is important. */
151 const parse_token_f parsers
[] = {
153 &parse_ip_protocol_token
,
154 &parse_ip_ports_token
,
156 parse_token_f
const *parser_ptr
= parsers
;
157 int af
= AF_UNSPEC
, proto
= 0, r
;
158 uint16_t nr
= 0, mn
= 0;
159 const char *p
= ASSERT_PTR(str
);
161 assert(address_family
);
170 _cleanup_free_
char *token
= NULL
;
172 r
= extract_first_word(&p
, &token
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
);
181 while (parser_ptr
!= parsers
+ ELEMENTSOF(parsers
)) {
182 r
= (*parser_ptr
)(token
, &af
, &proto
, &nr
, &mn
);
187 /* Continue to next token if parsing succeeded,
188 * otherwise apply next parser to the same token.
193 if (parser_ptr
== parsers
+ ELEMENTSOF(parsers
))
197 /* Failed to parse a token. */
201 /* Parsers applied successfully, but end of the string not reached. */
205 *address_family
= af
;
206 *ip_protocol
= proto
;
213 int config_parse_path_or_ignore(
215 const char *filename
,
218 unsigned section_line
,
225 _cleanup_free_
char *n
= NULL
;
227 char **s
= ASSERT_PTR(data
);
244 r
= path_simplify_and_warn(n
, PATH_CHECK_ABSOLUTE
| (fatal
? PATH_CHECK_FATAL
: 0), unit
, filename
, line
, lvalue
);
246 return fatal
? -ENOEXEC
: 0;
249 return free_and_replace(*s
, n
);