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 <netinet/ether.h>
24 #include <arpa/inet.h>
27 #include "siphash24.h"
28 #include "dhcp-lease-internal.h"
32 #include "conf-parser.h"
33 #include "condition.h"
34 #include "network-internal.h"
37 const char *net_get_name(struct udev_device
*device
) {
38 const char *name
, *field
;
42 /* fetch some persistent data unique (on this machine) to this device */
43 FOREACH_STRING(field
, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") {
44 name
= udev_device_get_property_value(device
, field
);
52 #define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
54 int net_get_unique_predictable_data(struct udev_device
*device
, uint8_t result
[8]) {
56 const char *name
= NULL
;
62 name
= net_get_name(device
);
67 sz
= sizeof(sd_id128_t
) + l
;
70 /* fetch some persistent data unique to this machine */
71 r
= sd_id128_get_machine((sd_id128_t
*) v
);
74 memcpy(v
+ sizeof(sd_id128_t
), name
, l
);
76 /* Let's hash the machine ID plus the device name. We
77 * use a fixed, but originally randomly created hash
79 siphash24(result
, v
, sz
, HASH_KEY
.bytes
);
84 bool net_match_config(const struct ether_addr
*match_mac
,
85 char * const *match_paths
,
86 char * const *match_drivers
,
87 char * const *match_types
,
88 char * const *match_names
,
89 Condition
*match_host
,
90 Condition
*match_virt
,
91 Condition
*match_kernel
,
92 Condition
*match_arch
,
93 const struct ether_addr
*dev_mac
,
95 const char *dev_parent_driver
,
96 const char *dev_driver
,
98 const char *dev_name
) {
100 if (match_host
&& !condition_test(match_host
))
103 if (match_virt
&& !condition_test(match_virt
))
106 if (match_kernel
&& !condition_test(match_kernel
))
109 if (match_arch
&& !condition_test(match_arch
))
112 if (match_mac
&& (!dev_mac
|| memcmp(match_mac
, dev_mac
, ETH_ALEN
)))
115 if (!strv_isempty(match_paths
) &&
116 (!dev_path
|| !strv_fnmatch(match_paths
, dev_path
, 0)))
119 if (!strv_isempty(match_drivers
) &&
120 (!dev_driver
|| !strv_fnmatch(match_drivers
, dev_driver
, 0)))
123 if (!strv_isempty(match_types
) &&
124 (!dev_type
|| !strv_fnmatch_or_empty(match_types
, dev_type
, 0)))
127 if (!strv_isempty(match_names
) &&
128 (!dev_name
|| !strv_fnmatch_or_empty(match_names
, dev_name
, 0)))
134 int config_parse_net_condition(const char *unit
,
135 const char *filename
,
138 unsigned section_line
,
145 ConditionType cond
= ltype
;
146 Condition
**ret
= data
;
149 _cleanup_free_
char *s
= NULL
;
156 negate
= rvalue
[0] == '!';
164 c
= condition_new(cond
, s
, false, negate
);
169 condition_free(*ret
);
175 int config_parse_ifname(const char *unit
,
176 const char *filename
,
179 unsigned section_line
,
187 _cleanup_free_
char *n
= NULL
;
198 if (!ascii_is_valid(n
) || strlen(n
) >= IFNAMSIZ
) {
199 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue
);
213 int config_parse_ifnames(const char *unit
,
214 const char *filename
,
217 unsigned section_line
,
225 const char *word
, *state
;
234 FOREACH_WORD(word
, l
, rvalue
, state
) {
237 n
= strndup(word
, l
);
241 if (!ascii_is_valid(n
) || strlen(n
) >= IFNAMSIZ
) {
242 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue
);
247 r
= strv_consume(sv
, n
);
255 int config_parse_ifalias(const char *unit
,
256 const char *filename
,
259 unsigned section_line
,
267 _cleanup_free_
char *n
= NULL
;
278 if (!ascii_is_valid(n
) || strlen(n
) >= IFALIASZ
) {
279 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue
);
293 int config_parse_hwaddr(const char *unit
,
294 const char *filename
,
297 unsigned section_line
,
303 struct ether_addr
**hwaddr
= data
;
304 struct ether_addr
*n
;
312 n
= new0(struct ether_addr
, 1);
316 r
= sscanf(rvalue
, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
317 &n
->ether_addr_octet
[0],
318 &n
->ether_addr_octet
[1],
319 &n
->ether_addr_octet
[2],
320 &n
->ether_addr_octet
[3],
321 &n
->ether_addr_octet
[4],
322 &n
->ether_addr_octet
[5]);
324 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue
);
335 void serialize_in_addrs(FILE *f
, const struct in_addr
*addresses
, size_t size
) {
342 for (i
= 0; i
< size
; i
++)
343 fprintf(f
, "%s%s", inet_ntoa(addresses
[i
]),
344 (i
< (size
- 1)) ? " ": "");
347 int deserialize_in_addrs(struct in_addr
**ret
, const char *string
) {
348 _cleanup_free_
struct in_addr
*addresses
= NULL
;
350 const char *word
, *state
;
356 FOREACH_WORD(word
, len
, string
, state
) {
357 _cleanup_free_
char *addr_str
= NULL
;
358 struct in_addr
*new_addresses
;
361 new_addresses
= realloc(addresses
, (size
+ 1) * sizeof(struct in_addr
));
365 addresses
= new_addresses
;
367 addr_str
= strndup(word
, len
);
371 r
= inet_pton(AF_INET
, addr_str
, &(addresses
[size
]));
384 void serialize_in6_addrs(FILE *f
, const struct in6_addr
*addresses
,
392 for (i
= 0; i
< size
; i
++)
393 fprintf(f
, SD_NDISC_ADDRESS_FORMAT_STR
"%s",
394 SD_NDISC_ADDRESS_FORMAT_VAL(addresses
[i
]),
395 (i
< (size
- 1)) ? " ": "");
398 int deserialize_in6_addrs(struct in6_addr
**ret
, const char *string
) {
399 _cleanup_free_
struct in6_addr
*addresses
= NULL
;
401 const char *word
, *state
;
407 FOREACH_WORD(word
, len
, string
, state
) {
408 _cleanup_free_
char *addr_str
= NULL
;
409 struct in6_addr
*new_addresses
;
412 new_addresses
= realloc(addresses
, (size
+ 1) * sizeof(struct in6_addr
));
416 addresses
= new_addresses
;
418 addr_str
= strndup(word
, len
);
422 r
= inet_pton(AF_INET6
, addr_str
, &(addresses
[size
]));
435 void serialize_dhcp_routes(FILE *f
, const char *key
, struct sd_dhcp_route
*routes
, size_t size
) {
443 fprintf(f
, "%s=", key
);
445 for (i
= 0; i
< size
; i
++) {
446 fprintf(f
, "%s/%" PRIu8
, inet_ntoa(routes
[i
].dst_addr
),
447 routes
[i
].dst_prefixlen
);
448 fprintf(f
, ",%s%s", inet_ntoa(routes
[i
].gw_addr
),
449 (i
< (size
- 1)) ? " ": "");
455 int deserialize_dhcp_routes(struct sd_dhcp_route
**ret
, size_t *ret_size
, size_t *ret_allocated
, const char *string
) {
456 _cleanup_free_
struct sd_dhcp_route
*routes
= NULL
;
457 size_t size
= 0, allocated
= 0;
458 const char *word
, *state
;
463 assert(ret_allocated
);
466 FOREACH_WORD(word
, len
, string
, state
) {
467 /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
468 _cleanup_free_
char* entry
= NULL
;
473 if (!GREEDY_REALLOC(routes
, allocated
, size
+ 1))
476 entry
= strndup(word
, len
);
483 tok_end
= strchr(tok
, '/');
488 r
= inet_aton(tok
, &routes
[size
].dst_addr
);
494 /* get the prefixlen */
495 tok_end
= strchr(tok
, ',');
501 r
= safe_atou(tok
, &n
);
505 routes
[size
].dst_prefixlen
= (uint8_t) n
;
508 /* get the gateway */
509 r
= inet_aton(tok
, &routes
[size
].gw_addr
);
517 *ret_allocated
= allocated
;
524 int serialize_dhcp_option(FILE *f
, const char *key
, const void *data
, size_t size
) {
525 _cleanup_free_
char *hex_buf
= NULL
;
531 hex_buf
= hexmem(data
, size
);
535 fprintf(f
, "%s=%s\n", key
, hex_buf
);
540 int deserialize_dhcp_option(void **data
, size_t *data_len
, const char *string
) {
545 if (strlen(string
) % 2)
548 return unhexmem(string
, strlen(string
), (void **)data
, data_len
);