1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <arpa/inet.h>
24 #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 "hexdecoct.h"
34 #include "network-internal.h"
35 #include "parse-util.h"
36 #include "siphash24.h"
37 #include "string-util.h"
42 const char *net_get_name(struct udev_device
*device
) {
43 const char *name
, *field
;
47 /* fetch some persistent data unique (on this machine) to this device */
48 FOREACH_STRING(field
, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") {
49 name
= udev_device_get_property_value(device
, field
);
57 #define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
59 int net_get_unique_predictable_data(struct udev_device
*device
, uint64_t *result
) {
61 const char *name
= NULL
;
67 name
= net_get_name(device
);
72 sz
= sizeof(sd_id128_t
) + l
;
75 /* fetch some persistent data unique to this machine */
76 r
= sd_id128_get_machine((sd_id128_t
*) v
);
79 memcpy(v
+ sizeof(sd_id128_t
), name
, l
);
81 /* Let's hash the machine ID plus the device name. We
82 * use a fixed, but originally randomly created hash
84 *result
= htole64(siphash24(v
, sz
, HASH_KEY
.bytes
));
89 bool net_match_config(const struct ether_addr
*match_mac
,
90 char * const *match_paths
,
91 char * const *match_drivers
,
92 char * const *match_types
,
93 char * const *match_names
,
94 Condition
*match_host
,
95 Condition
*match_virt
,
96 Condition
*match_kernel
,
97 Condition
*match_arch
,
98 const struct ether_addr
*dev_mac
,
100 const char *dev_parent_driver
,
101 const char *dev_driver
,
102 const char *dev_type
,
103 const char *dev_name
) {
105 if (match_host
&& !condition_test(match_host
))
108 if (match_virt
&& !condition_test(match_virt
))
111 if (match_kernel
&& !condition_test(match_kernel
))
114 if (match_arch
&& !condition_test(match_arch
))
117 if (match_mac
&& (!dev_mac
|| memcmp(match_mac
, dev_mac
, ETH_ALEN
)))
120 if (!strv_isempty(match_paths
) &&
121 (!dev_path
|| !strv_fnmatch(match_paths
, dev_path
, 0)))
124 if (!strv_isempty(match_drivers
) &&
125 (!dev_driver
|| !strv_fnmatch(match_drivers
, dev_driver
, 0)))
128 if (!strv_isempty(match_types
) &&
129 (!dev_type
|| !strv_fnmatch_or_empty(match_types
, dev_type
, 0)))
132 if (!strv_isempty(match_names
) &&
133 (!dev_name
|| !strv_fnmatch_or_empty(match_names
, dev_name
, 0)))
139 int config_parse_net_condition(const char *unit
,
140 const char *filename
,
143 unsigned section_line
,
150 ConditionType cond
= ltype
;
151 Condition
**ret
= data
;
154 _cleanup_free_
char *s
= NULL
;
161 negate
= rvalue
[0] == '!';
169 c
= condition_new(cond
, s
, false, negate
);
174 condition_free(*ret
);
180 int config_parse_ifname(const char *unit
,
181 const char *filename
,
184 unsigned section_line
,
192 _cleanup_free_
char *n
= NULL
;
203 if (!ascii_is_valid(n
) || strlen(n
) >= IFNAMSIZ
) {
204 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue
);
218 int config_parse_ifnames(const char *unit
,
219 const char *filename
,
222 unsigned section_line
,
230 const char *word
, *state
;
239 FOREACH_WORD(word
, l
, rvalue
, state
) {
242 n
= strndup(word
, l
);
246 if (!ascii_is_valid(n
) || strlen(n
) >= IFNAMSIZ
) {
247 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue
);
252 r
= strv_consume(sv
, n
);
260 int config_parse_ifalias(const char *unit
,
261 const char *filename
,
264 unsigned section_line
,
272 _cleanup_free_
char *n
= NULL
;
283 if (!ascii_is_valid(n
) || strlen(n
) >= IFALIASZ
) {
284 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue
);
298 int config_parse_hwaddr(const char *unit
,
299 const char *filename
,
302 unsigned section_line
,
308 struct ether_addr
**hwaddr
= data
;
309 struct ether_addr
*n
;
317 n
= new0(struct ether_addr
, 1);
321 r
= sscanf(rvalue
, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
322 &n
->ether_addr_octet
[0],
323 &n
->ether_addr_octet
[1],
324 &n
->ether_addr_octet
[2],
325 &n
->ether_addr_octet
[3],
326 &n
->ether_addr_octet
[4],
327 &n
->ether_addr_octet
[5]);
329 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue
);
340 void serialize_in_addrs(FILE *f
, const struct in_addr
*addresses
, size_t size
) {
347 for (i
= 0; i
< size
; i
++)
348 fprintf(f
, "%s%s", inet_ntoa(addresses
[i
]),
349 (i
< (size
- 1)) ? " ": "");
352 int deserialize_in_addrs(struct in_addr
**ret
, const char *string
) {
353 _cleanup_free_
struct in_addr
*addresses
= NULL
;
355 const char *word
, *state
;
361 FOREACH_WORD(word
, len
, string
, state
) {
362 _cleanup_free_
char *addr_str
= NULL
;
363 struct in_addr
*new_addresses
;
366 new_addresses
= realloc(addresses
, (size
+ 1) * sizeof(struct in_addr
));
370 addresses
= new_addresses
;
372 addr_str
= strndup(word
, len
);
376 r
= inet_pton(AF_INET
, addr_str
, &(addresses
[size
]));
389 void serialize_in6_addrs(FILE *f
, const struct in6_addr
*addresses
,
397 for (i
= 0; i
< size
; i
++)
398 fprintf(f
, SD_NDISC_ADDRESS_FORMAT_STR
"%s",
399 SD_NDISC_ADDRESS_FORMAT_VAL(addresses
[i
]),
400 (i
< (size
- 1)) ? " ": "");
403 int deserialize_in6_addrs(struct in6_addr
**ret
, const char *string
) {
404 _cleanup_free_
struct in6_addr
*addresses
= NULL
;
406 const char *word
, *state
;
412 FOREACH_WORD(word
, len
, string
, state
) {
413 _cleanup_free_
char *addr_str
= NULL
;
414 struct in6_addr
*new_addresses
;
417 new_addresses
= realloc(addresses
, (size
+ 1) * sizeof(struct in6_addr
));
421 addresses
= new_addresses
;
423 addr_str
= strndup(word
, len
);
427 r
= inet_pton(AF_INET6
, addr_str
, &(addresses
[size
]));
440 void serialize_dhcp_routes(FILE *f
, const char *key
, sd_dhcp_route
**routes
, size_t size
) {
448 fprintf(f
, "%s=", key
);
450 for (i
= 0; i
< size
; i
++) {
451 struct in_addr dest
, gw
;
454 assert_se(sd_dhcp_route_get_destination(routes
[i
], &dest
) >= 0);
455 assert_se(sd_dhcp_route_get_gateway(routes
[i
], &gw
) >= 0);
456 assert_se(sd_dhcp_route_get_destination_prefix_length(routes
[i
], &length
) >= 0);
458 fprintf(f
, "%s/%" PRIu8
, inet_ntoa(dest
), length
);
459 fprintf(f
, ",%s%s", inet_ntoa(gw
), (i
< (size
- 1)) ? " ": "");
465 int deserialize_dhcp_routes(struct sd_dhcp_route
**ret
, size_t *ret_size
, size_t *ret_allocated
, const char *string
) {
466 _cleanup_free_
struct sd_dhcp_route
*routes
= NULL
;
467 size_t size
= 0, allocated
= 0;
468 const char *word
, *state
;
473 assert(ret_allocated
);
476 FOREACH_WORD(word
, len
, string
, state
) {
477 /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
478 _cleanup_free_
char* entry
= NULL
;
483 if (!GREEDY_REALLOC(routes
, allocated
, size
+ 1))
486 entry
= strndup(word
, len
);
493 tok_end
= strchr(tok
, '/');
498 r
= inet_aton(tok
, &routes
[size
].dst_addr
);
504 /* get the prefixlen */
505 tok_end
= strchr(tok
, ',');
511 r
= safe_atou(tok
, &n
);
515 routes
[size
].dst_prefixlen
= (uint8_t) n
;
518 /* get the gateway */
519 r
= inet_aton(tok
, &routes
[size
].gw_addr
);
527 *ret_allocated
= allocated
;
534 int serialize_dhcp_option(FILE *f
, const char *key
, const void *data
, size_t size
) {
535 _cleanup_free_
char *hex_buf
= NULL
;
541 hex_buf
= hexmem(data
, size
);
545 fprintf(f
, "%s=%s\n", key
, hex_buf
);
550 int deserialize_dhcp_option(void **data
, size_t *data_len
, const char *string
) {
555 if (strlen(string
) % 2)
558 return unhexmem(string
, strlen(string
), (void **)data
, data_len
);