1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <arpa/inet.h>
23 #include <netinet/ether.h>
28 #include "alloc-util.h"
29 #include "condition.h"
30 #include "conf-parser.h"
31 #include "dhcp-lease-internal.h"
32 #include "ether-addr-util.h"
33 #include "hexdecoct.h"
35 #include "network-internal.h"
36 #include "parse-util.h"
37 #include "siphash24.h"
38 #include "socket-util.h"
39 #include "string-util.h"
44 const char *net_get_name(struct udev_device
*device
) {
45 const char *name
, *field
;
49 /* fetch some persistent data unique (on this machine) to this device */
50 FOREACH_STRING(field
, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") {
51 name
= udev_device_get_property_value(device
, field
);
59 #define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
61 int net_get_unique_predictable_data(struct udev_device
*device
, uint64_t *result
) {
63 const char *name
= NULL
;
69 name
= net_get_name(device
);
74 sz
= sizeof(sd_id128_t
) + l
;
77 /* fetch some persistent data unique to this machine */
78 r
= sd_id128_get_machine((sd_id128_t
*) v
);
81 memcpy(v
+ sizeof(sd_id128_t
), name
, l
);
83 /* Let's hash the machine ID plus the device name. We
84 * use a fixed, but originally randomly created hash
86 *result
= htole64(siphash24(v
, sz
, HASH_KEY
.bytes
));
91 static bool net_condition_test_strv(char * const *raw_patterns
,
93 if (strv_isempty(raw_patterns
))
96 /* If the patterns begin with "!", edit it out and negate the test. */
97 if (raw_patterns
[0][0] == '!') {
101 length
= strv_length(raw_patterns
) + 1; /* Include the NULL. */
102 patterns
= newa(char*, length
);
103 patterns
[0] = raw_patterns
[0] + 1; /* Skip the "!". */
104 for (i
= 1; i
< length
; i
++)
105 patterns
[i
] = raw_patterns
[i
];
107 return !string
|| !strv_fnmatch(patterns
, string
, 0);
110 return string
&& strv_fnmatch(raw_patterns
, string
, 0);
113 bool net_match_config(const struct ether_addr
*match_mac
,
114 char * const *match_paths
,
115 char * const *match_drivers
,
116 char * const *match_types
,
117 char * const *match_names
,
118 Condition
*match_host
,
119 Condition
*match_virt
,
120 Condition
*match_kernel_cmdline
,
121 Condition
*match_kernel_version
,
122 Condition
*match_arch
,
123 const struct ether_addr
*dev_mac
,
124 const char *dev_path
,
125 const char *dev_parent_driver
,
126 const char *dev_driver
,
127 const char *dev_type
,
128 const char *dev_name
) {
130 if (match_host
&& condition_test(match_host
) <= 0)
133 if (match_virt
&& condition_test(match_virt
) <= 0)
136 if (match_kernel_cmdline
&& condition_test(match_kernel_cmdline
) <= 0)
139 if (match_kernel_version
&& condition_test(match_kernel_version
) <= 0)
142 if (match_arch
&& condition_test(match_arch
) <= 0)
145 if (match_mac
&& (!dev_mac
|| memcmp(match_mac
, dev_mac
, ETH_ALEN
)))
148 if (!net_condition_test_strv(match_paths
, dev_path
))
151 if (!net_condition_test_strv(match_drivers
, dev_driver
))
154 if (!net_condition_test_strv(match_types
, dev_type
))
157 if (!net_condition_test_strv(match_names
, dev_name
))
163 int config_parse_net_condition(const char *unit
,
164 const char *filename
,
167 unsigned section_line
,
174 ConditionType cond
= ltype
;
175 Condition
**ret
= data
;
178 _cleanup_free_
char *s
= NULL
;
185 negate
= rvalue
[0] == '!';
193 c
= condition_new(cond
, s
, false, negate
);
198 condition_free(*ret
);
204 int config_parse_ifnames(
206 const char *filename
,
209 unsigned section_line
,
225 _cleanup_free_
char *word
= NULL
;
227 r
= extract_first_word(&rvalue
, &word
, NULL
, 0);
229 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Failed to parse interface name list: %s", rvalue
);
235 if (!ifname_valid(word
)) {
236 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface name is not valid or too long, ignoring assignment: %s", rvalue
);
240 r
= strv_push(sv
, word
);
250 int config_parse_ifalias(const char *unit
,
251 const char *filename
,
254 unsigned section_line
,
262 _cleanup_free_
char *n
= NULL
;
273 if (!ascii_is_valid(n
) || strlen(n
) >= IFALIASZ
) {
274 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue
);
287 int config_parse_hwaddr(const char *unit
,
288 const char *filename
,
291 unsigned section_line
,
297 struct ether_addr
**hwaddr
= data
;
298 struct ether_addr
*n
;
308 n
= new0(struct ether_addr
, 1);
312 start
= rvalue
+ strspn(rvalue
, WHITESPACE
);
313 r
= ether_addr_from_string(start
, n
, &offset
);
315 if (r
|| (start
[offset
+ strspn(start
+ offset
, WHITESPACE
)] != '\0')) {
316 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue
);
327 int config_parse_iaid(const char *unit
,
328 const char *filename
,
331 unsigned section_line
,
345 r
= safe_atou32(rvalue
, &iaid
);
347 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
348 "Unable to read IAID, ignoring assignment: %s", rvalue
);
352 *((uint32_t *)data
) = iaid
;
357 int config_parse_bridge_port_priority(
359 const char *filename
,
362 unsigned section_line
,
377 r
= safe_atou16(rvalue
, &i
);
379 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
380 "Failed to parse bridge port priority, ignoring: %s", rvalue
);
384 if (i
> LINK_BRIDGE_PORT_PRIORITY_MAX
) {
385 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
386 "Bridge port priority is larger than maximum %u, ignoring: %s", LINK_BRIDGE_PORT_PRIORITY_MAX
, rvalue
);
390 *((uint16_t *)data
) = i
;
396 void serialize_in_addrs(FILE *f
, const struct in_addr
*addresses
, size_t size
) {
403 for (i
= 0; i
< size
; i
++)
404 fprintf(f
, "%s%s", inet_ntoa(addresses
[i
]),
405 (i
< (size
- 1)) ? " ": "");
408 int deserialize_in_addrs(struct in_addr
**ret
, const char *string
) {
409 _cleanup_free_
struct in_addr
*addresses
= NULL
;
416 _cleanup_free_
char *word
= NULL
;
417 struct in_addr
*new_addresses
;
420 r
= extract_first_word(&string
, &word
, NULL
, 0);
426 new_addresses
= reallocarray(addresses
, size
+ 1, sizeof(struct in_addr
));
430 addresses
= new_addresses
;
432 r
= inet_pton(AF_INET
, word
, &(addresses
[size
]));
439 *ret
= TAKE_PTR(addresses
);
444 void serialize_in6_addrs(FILE *f
, const struct in6_addr
*addresses
, size_t size
) {
451 for (i
= 0; i
< size
; i
++) {
452 char buffer
[INET6_ADDRSTRLEN
];
454 fputs(inet_ntop(AF_INET6
, addresses
+i
, buffer
, sizeof(buffer
)), f
);
461 int deserialize_in6_addrs(struct in6_addr
**ret
, const char *string
) {
462 _cleanup_free_
struct in6_addr
*addresses
= NULL
;
469 _cleanup_free_
char *word
= NULL
;
470 struct in6_addr
*new_addresses
;
473 r
= extract_first_word(&string
, &word
, NULL
, 0);
479 new_addresses
= reallocarray(addresses
, size
+ 1, sizeof(struct in6_addr
));
483 addresses
= new_addresses
;
485 r
= inet_pton(AF_INET6
, word
, &(addresses
[size
]));
492 *ret
= TAKE_PTR(addresses
);
497 void serialize_dhcp_routes(FILE *f
, const char *key
, sd_dhcp_route
**routes
, size_t size
) {
505 fprintf(f
, "%s=", key
);
507 for (i
= 0; i
< size
; i
++) {
508 struct in_addr dest
, gw
;
511 assert_se(sd_dhcp_route_get_destination(routes
[i
], &dest
) >= 0);
512 assert_se(sd_dhcp_route_get_gateway(routes
[i
], &gw
) >= 0);
513 assert_se(sd_dhcp_route_get_destination_prefix_length(routes
[i
], &length
) >= 0);
515 fprintf(f
, "%s/%" PRIu8
, inet_ntoa(dest
), length
);
516 fprintf(f
, ",%s%s", inet_ntoa(gw
), (i
< (size
- 1)) ? " ": "");
522 int deserialize_dhcp_routes(struct sd_dhcp_route
**ret
, size_t *ret_size
, size_t *ret_allocated
, const char *string
) {
523 _cleanup_free_
struct sd_dhcp_route
*routes
= NULL
;
524 size_t size
= 0, allocated
= 0;
528 assert(ret_allocated
);
531 /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
533 _cleanup_free_
char *word
= NULL
;
538 r
= extract_first_word(&string
, &word
, NULL
, 0);
544 if (!GREEDY_REALLOC(routes
, allocated
, size
+ 1))
550 tok_end
= strchr(tok
, '/');
555 r
= inet_aton(tok
, &routes
[size
].dst_addr
);
561 /* get the prefixlen */
562 tok_end
= strchr(tok
, ',');
568 r
= safe_atou(tok
, &n
);
572 routes
[size
].dst_prefixlen
= (uint8_t) n
;
575 /* get the gateway */
576 r
= inet_aton(tok
, &routes
[size
].gw_addr
);
584 *ret_allocated
= allocated
;
585 *ret
= TAKE_PTR(routes
);
590 int serialize_dhcp_option(FILE *f
, const char *key
, const void *data
, size_t size
) {
591 _cleanup_free_
char *hex_buf
= NULL
;
597 hex_buf
= hexmem(data
, size
);
601 fprintf(f
, "%s=%s\n", key
, hex_buf
);
606 int deserialize_dhcp_option(void **data
, size_t *data_len
, const char *string
) {
611 if (strlen(string
) % 2)
614 return unhexmem(string
, strlen(string
), (void **)data
, data_len
);