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 "condition.h"
29 #include "conf-parser.h"
30 #include "dhcp-lease-internal.h"
32 #include "siphash24.h"
33 #include "string-util.h"
37 #include "network-internal.h"
39 const char *net_get_name(struct udev_device
*device
) {
40 const char *name
, *field
;
44 /* fetch some persistent data unique (on this machine) to this device */
45 FOREACH_STRING(field
, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") {
46 name
= udev_device_get_property_value(device
, field
);
54 #define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
56 int net_get_unique_predictable_data(struct udev_device
*device
, uint8_t result
[8]) {
58 const char *name
= NULL
;
64 name
= net_get_name(device
);
69 sz
= sizeof(sd_id128_t
) + l
;
72 /* fetch some persistent data unique to this machine */
73 r
= sd_id128_get_machine((sd_id128_t
*) v
);
76 memcpy(v
+ sizeof(sd_id128_t
), name
, l
);
78 /* Let's hash the machine ID plus the device name. We
79 * use a fixed, but originally randomly created hash
81 siphash24(result
, v
, sz
, HASH_KEY
.bytes
);
86 bool net_match_config(const struct ether_addr
*match_mac
,
87 char * const *match_paths
,
88 char * const *match_drivers
,
89 char * const *match_types
,
90 char * const *match_names
,
91 Condition
*match_host
,
92 Condition
*match_virt
,
93 Condition
*match_kernel
,
94 Condition
*match_arch
,
95 const struct ether_addr
*dev_mac
,
97 const char *dev_parent_driver
,
98 const char *dev_driver
,
100 const char *dev_name
) {
102 if (match_host
&& !condition_test(match_host
))
105 if (match_virt
&& !condition_test(match_virt
))
108 if (match_kernel
&& !condition_test(match_kernel
))
111 if (match_arch
&& !condition_test(match_arch
))
114 if (match_mac
&& (!dev_mac
|| memcmp(match_mac
, dev_mac
, ETH_ALEN
)))
117 if (!strv_isempty(match_paths
) &&
118 (!dev_path
|| !strv_fnmatch(match_paths
, dev_path
, 0)))
121 if (!strv_isempty(match_drivers
) &&
122 (!dev_driver
|| !strv_fnmatch(match_drivers
, dev_driver
, 0)))
125 if (!strv_isempty(match_types
) &&
126 (!dev_type
|| !strv_fnmatch_or_empty(match_types
, dev_type
, 0)))
129 if (!strv_isempty(match_names
) &&
130 (!dev_name
|| !strv_fnmatch_or_empty(match_names
, dev_name
, 0)))
136 int config_parse_net_condition(const char *unit
,
137 const char *filename
,
140 unsigned section_line
,
147 ConditionType cond
= ltype
;
148 Condition
**ret
= data
;
151 _cleanup_free_
char *s
= NULL
;
158 negate
= rvalue
[0] == '!';
166 c
= condition_new(cond
, s
, false, negate
);
171 condition_free(*ret
);
177 int config_parse_ifname(const char *unit
,
178 const char *filename
,
181 unsigned section_line
,
189 _cleanup_free_
char *n
= NULL
;
200 if (!ascii_is_valid(n
) || strlen(n
) >= IFNAMSIZ
) {
201 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue
);
215 int config_parse_ifnames(const char *unit
,
216 const char *filename
,
219 unsigned section_line
,
227 const char *word
, *state
;
236 FOREACH_WORD(word
, l
, rvalue
, state
) {
239 n
= strndup(word
, l
);
243 if (!ascii_is_valid(n
) || strlen(n
) >= IFNAMSIZ
) {
244 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue
);
249 r
= strv_consume(sv
, n
);
257 int config_parse_ifalias(const char *unit
,
258 const char *filename
,
261 unsigned section_line
,
269 _cleanup_free_
char *n
= NULL
;
280 if (!ascii_is_valid(n
) || strlen(n
) >= IFALIASZ
) {
281 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue
);
295 int config_parse_hwaddr(const char *unit
,
296 const char *filename
,
299 unsigned section_line
,
305 struct ether_addr
**hwaddr
= data
;
306 struct ether_addr
*n
;
314 n
= new0(struct ether_addr
, 1);
318 r
= sscanf(rvalue
, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
319 &n
->ether_addr_octet
[0],
320 &n
->ether_addr_octet
[1],
321 &n
->ether_addr_octet
[2],
322 &n
->ether_addr_octet
[3],
323 &n
->ether_addr_octet
[4],
324 &n
->ether_addr_octet
[5]);
326 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue
);
337 void serialize_in_addrs(FILE *f
, const struct in_addr
*addresses
, size_t size
) {
344 for (i
= 0; i
< size
; i
++)
345 fprintf(f
, "%s%s", inet_ntoa(addresses
[i
]),
346 (i
< (size
- 1)) ? " ": "");
349 int deserialize_in_addrs(struct in_addr
**ret
, const char *string
) {
350 _cleanup_free_
struct in_addr
*addresses
= NULL
;
352 const char *word
, *state
;
358 FOREACH_WORD(word
, len
, string
, state
) {
359 _cleanup_free_
char *addr_str
= NULL
;
360 struct in_addr
*new_addresses
;
363 new_addresses
= realloc(addresses
, (size
+ 1) * sizeof(struct in_addr
));
367 addresses
= new_addresses
;
369 addr_str
= strndup(word
, len
);
373 r
= inet_pton(AF_INET
, addr_str
, &(addresses
[size
]));
386 void serialize_in6_addrs(FILE *f
, const struct in6_addr
*addresses
,
394 for (i
= 0; i
< size
; i
++)
395 fprintf(f
, SD_NDISC_ADDRESS_FORMAT_STR
"%s",
396 SD_NDISC_ADDRESS_FORMAT_VAL(addresses
[i
]),
397 (i
< (size
- 1)) ? " ": "");
400 int deserialize_in6_addrs(struct in6_addr
**ret
, const char *string
) {
401 _cleanup_free_
struct in6_addr
*addresses
= NULL
;
403 const char *word
, *state
;
409 FOREACH_WORD(word
, len
, string
, state
) {
410 _cleanup_free_
char *addr_str
= NULL
;
411 struct in6_addr
*new_addresses
;
414 new_addresses
= realloc(addresses
, (size
+ 1) * sizeof(struct in6_addr
));
418 addresses
= new_addresses
;
420 addr_str
= strndup(word
, len
);
424 r
= inet_pton(AF_INET6
, addr_str
, &(addresses
[size
]));
437 void serialize_dhcp_routes(FILE *f
, const char *key
, struct sd_dhcp_route
*routes
, size_t size
) {
445 fprintf(f
, "%s=", key
);
447 for (i
= 0; i
< size
; i
++) {
448 fprintf(f
, "%s/%" PRIu8
, inet_ntoa(routes
[i
].dst_addr
),
449 routes
[i
].dst_prefixlen
);
450 fprintf(f
, ",%s%s", inet_ntoa(routes
[i
].gw_addr
),
451 (i
< (size
- 1)) ? " ": "");
457 int deserialize_dhcp_routes(struct sd_dhcp_route
**ret
, size_t *ret_size
, size_t *ret_allocated
, const char *string
) {
458 _cleanup_free_
struct sd_dhcp_route
*routes
= NULL
;
459 size_t size
= 0, allocated
= 0;
460 const char *word
, *state
;
465 assert(ret_allocated
);
468 FOREACH_WORD(word
, len
, string
, state
) {
469 /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
470 _cleanup_free_
char* entry
= NULL
;
475 if (!GREEDY_REALLOC(routes
, allocated
, size
+ 1))
478 entry
= strndup(word
, len
);
485 tok_end
= strchr(tok
, '/');
490 r
= inet_aton(tok
, &routes
[size
].dst_addr
);
496 /* get the prefixlen */
497 tok_end
= strchr(tok
, ',');
503 r
= safe_atou(tok
, &n
);
507 routes
[size
].dst_prefixlen
= (uint8_t) n
;
510 /* get the gateway */
511 r
= inet_aton(tok
, &routes
[size
].gw_addr
);
519 *ret_allocated
= allocated
;
526 int serialize_dhcp_option(FILE *f
, const char *key
, const void *data
, size_t size
) {
527 _cleanup_free_
char *hex_buf
= NULL
;
533 hex_buf
= hexmem(data
, size
);
537 fprintf(f
, "%s=%s\n", key
, hex_buf
);
542 int deserialize_dhcp_option(void **data
, size_t *data_len
, const char *string
) {
547 if (strlen(string
) % 2)
550 return unhexmem(string
, strlen(string
), (void **)data
, data_len
);