1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include "extract-word.h"
5 #include "ip-protocol-list.h"
7 #include "parse-helpers.h"
8 #include "parse-util.h"
12 int path_simplify_and_warn(
20 bool fatal
= flag
& PATH_CHECK_FATAL
;
22 assert(!FLAGS_SET(flag
, PATH_CHECK_ABSOLUTE
| PATH_CHECK_RELATIVE
));
24 if (!utf8_is_valid(path
))
25 return log_syntax_invalid_utf8(unit
, LOG_ERR
, filename
, line
, path
);
27 if (flag
& (PATH_CHECK_ABSOLUTE
| PATH_CHECK_RELATIVE
)) {
30 absolute
= path_is_absolute(path
);
32 if (!absolute
&& (flag
& PATH_CHECK_ABSOLUTE
))
33 return log_syntax(unit
, LOG_ERR
, filename
, line
, SYNTHETIC_ERRNO(EINVAL
),
34 "%s= path is not absolute%s: %s",
35 lvalue
, fatal
? "" : ", ignoring", path
);
37 if (absolute
&& (flag
& PATH_CHECK_RELATIVE
))
38 return log_syntax(unit
, LOG_ERR
, filename
, line
, SYNTHETIC_ERRNO(EINVAL
),
39 "%s= path is absolute%s: %s",
40 lvalue
, fatal
? "" : ", ignoring", path
);
43 path_simplify_full(path
, flag
& PATH_KEEP_TRAILING_SLASH
? PATH_SIMPLIFY_KEEP_TRAILING_SLASH
: 0);
45 if (!path_is_valid(path
))
46 return log_syntax(unit
, LOG_ERR
, filename
, line
, SYNTHETIC_ERRNO(EINVAL
),
47 "%s= path has invalid length (%zu bytes)%s.",
48 lvalue
, strlen(path
), fatal
? "" : ", ignoring");
50 if (!path_is_normalized(path
))
51 return log_syntax(unit
, LOG_ERR
, filename
, line
, SYNTHETIC_ERRNO(EINVAL
),
52 "%s= path is not normalized%s: %s",
53 lvalue
, fatal
? "" : ", ignoring", path
);
58 static int parse_af_token(
70 af
= af_from_ipv4_ipv6(token
);
78 static int parse_ip_protocol_token(
90 proto
= ip_protocol_from_tcp_udp(token
);
98 static int parse_ip_ports_token(
103 uint16_t *port_min
) {
111 if (streq(token
, "any"))
112 *nr_ports
= *port_min
= 0;
114 uint16_t mn
= 0, mx
= 0;
115 r
= parse_ip_port_range(token
, &mn
, &mx
, /* allow_zero = */ true);
119 *nr_ports
= mx
- mn
+ 1;
126 typedef int (*parse_token_f
)(
133 int parse_socket_bind_item(
138 uint16_t *port_min
) {
140 /* Order of token parsers is important. */
141 const parse_token_f parsers
[] = {
143 &parse_ip_protocol_token
,
144 &parse_ip_ports_token
,
146 parse_token_f
const *parser_ptr
= parsers
;
147 int af
= AF_UNSPEC
, proto
= 0, r
;
148 uint16_t nr
= 0, mn
= 0;
149 const char *p
= ASSERT_PTR(str
);
151 assert(address_family
);
160 _cleanup_free_
char *token
= NULL
;
162 r
= extract_first_word(&p
, &token
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
);
171 while (parser_ptr
!= parsers
+ ELEMENTSOF(parsers
)) {
172 r
= (*parser_ptr
)(token
, &af
, &proto
, &nr
, &mn
);
177 /* Continue to next token if parsing succeeded,
178 * otherwise apply next parser to the same token.
183 if (parser_ptr
== parsers
+ ELEMENTSOF(parsers
))
187 /* Failed to parse a token. */
191 /* Parsers applied successfully, but end of the string not reached. */
195 *address_family
= af
;
196 *ip_protocol
= proto
;
203 int config_parse_path_or_ignore(
205 const char *filename
,
208 unsigned section_line
,
215 _cleanup_free_
char *n
= NULL
;
217 char **s
= ASSERT_PTR(data
);
234 r
= path_simplify_and_warn(n
, PATH_CHECK_ABSOLUTE
| (fatal
? PATH_CHECK_FATAL
: 0), unit
, filename
, line
, lvalue
);
236 return fatal
? -ENOEXEC
: 0;
239 return free_and_replace(*s
, n
);