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 "network-internal.h"
33 #include "hexdecoct.h"
34 #include "parse-util.h"
35 #include "siphash24.h"
36 #include "string-util.h"
41 const char *net_get_name(struct udev_device
*device
) {
42 const char *name
, *field
;
46 /* fetch some persistent data unique (on this machine) to this device */
47 FOREACH_STRING(field
, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") {
48 name
= udev_device_get_property_value(device
, field
);
56 #define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
58 int net_get_unique_predictable_data(struct udev_device
*device
, uint8_t result
[8]) {
60 const char *name
= NULL
;
66 name
= net_get_name(device
);
71 sz
= sizeof(sd_id128_t
) + l
;
74 /* fetch some persistent data unique to this machine */
75 r
= sd_id128_get_machine((sd_id128_t
*) v
);
78 memcpy(v
+ sizeof(sd_id128_t
), name
, l
);
80 /* Let's hash the machine ID plus the device name. We
81 * use a fixed, but originally randomly created hash
83 siphash24(result
, v
, sz
, HASH_KEY
.bytes
);
88 bool net_match_config(const struct ether_addr
*match_mac
,
89 char * const *match_paths
,
90 char * const *match_drivers
,
91 char * const *match_types
,
92 char * const *match_names
,
93 Condition
*match_host
,
94 Condition
*match_virt
,
95 Condition
*match_kernel
,
96 Condition
*match_arch
,
97 const struct ether_addr
*dev_mac
,
99 const char *dev_parent_driver
,
100 const char *dev_driver
,
101 const char *dev_type
,
102 const char *dev_name
) {
104 if (match_host
&& !condition_test(match_host
))
107 if (match_virt
&& !condition_test(match_virt
))
110 if (match_kernel
&& !condition_test(match_kernel
))
113 if (match_arch
&& !condition_test(match_arch
))
116 if (match_mac
&& (!dev_mac
|| memcmp(match_mac
, dev_mac
, ETH_ALEN
)))
119 if (!strv_isempty(match_paths
) &&
120 (!dev_path
|| !strv_fnmatch(match_paths
, dev_path
, 0)))
123 if (!strv_isempty(match_drivers
) &&
124 (!dev_driver
|| !strv_fnmatch(match_drivers
, dev_driver
, 0)))
127 if (!strv_isempty(match_types
) &&
128 (!dev_type
|| !strv_fnmatch_or_empty(match_types
, dev_type
, 0)))
131 if (!strv_isempty(match_names
) &&
132 (!dev_name
|| !strv_fnmatch_or_empty(match_names
, dev_name
, 0)))
138 int config_parse_net_condition(const char *unit
,
139 const char *filename
,
142 unsigned section_line
,
149 ConditionType cond
= ltype
;
150 Condition
**ret
= data
;
153 _cleanup_free_
char *s
= NULL
;
160 negate
= rvalue
[0] == '!';
168 c
= condition_new(cond
, s
, false, negate
);
173 condition_free(*ret
);
179 int config_parse_ifname(const char *unit
,
180 const char *filename
,
183 unsigned section_line
,
191 _cleanup_free_
char *n
= NULL
;
202 if (!ascii_is_valid(n
) || strlen(n
) >= IFNAMSIZ
) {
203 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue
);
217 int config_parse_ifnames(const char *unit
,
218 const char *filename
,
221 unsigned section_line
,
229 const char *word
, *state
;
238 FOREACH_WORD(word
, l
, rvalue
, state
) {
241 n
= strndup(word
, l
);
245 if (!ascii_is_valid(n
) || strlen(n
) >= IFNAMSIZ
) {
246 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue
);
251 r
= strv_consume(sv
, n
);
259 int config_parse_ifalias(const char *unit
,
260 const char *filename
,
263 unsigned section_line
,
271 _cleanup_free_
char *n
= NULL
;
282 if (!ascii_is_valid(n
) || strlen(n
) >= IFALIASZ
) {
283 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue
);
297 int config_parse_hwaddr(const char *unit
,
298 const char *filename
,
301 unsigned section_line
,
307 struct ether_addr
**hwaddr
= data
;
308 struct ether_addr
*n
;
316 n
= new0(struct ether_addr
, 1);
320 r
= sscanf(rvalue
, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
321 &n
->ether_addr_octet
[0],
322 &n
->ether_addr_octet
[1],
323 &n
->ether_addr_octet
[2],
324 &n
->ether_addr_octet
[3],
325 &n
->ether_addr_octet
[4],
326 &n
->ether_addr_octet
[5]);
328 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue
);
339 void serialize_in_addrs(FILE *f
, const struct in_addr
*addresses
, size_t size
) {
346 for (i
= 0; i
< size
; i
++)
347 fprintf(f
, "%s%s", inet_ntoa(addresses
[i
]),
348 (i
< (size
- 1)) ? " ": "");
351 int deserialize_in_addrs(struct in_addr
**ret
, const char *string
) {
352 _cleanup_free_
struct in_addr
*addresses
= NULL
;
354 const char *word
, *state
;
360 FOREACH_WORD(word
, len
, string
, state
) {
361 _cleanup_free_
char *addr_str
= NULL
;
362 struct in_addr
*new_addresses
;
365 new_addresses
= realloc(addresses
, (size
+ 1) * sizeof(struct in_addr
));
369 addresses
= new_addresses
;
371 addr_str
= strndup(word
, len
);
375 r
= inet_pton(AF_INET
, addr_str
, &(addresses
[size
]));
388 void serialize_in6_addrs(FILE *f
, const struct in6_addr
*addresses
,
396 for (i
= 0; i
< size
; i
++)
397 fprintf(f
, SD_NDISC_ADDRESS_FORMAT_STR
"%s",
398 SD_NDISC_ADDRESS_FORMAT_VAL(addresses
[i
]),
399 (i
< (size
- 1)) ? " ": "");
402 int deserialize_in6_addrs(struct in6_addr
**ret
, const char *string
) {
403 _cleanup_free_
struct in6_addr
*addresses
= NULL
;
405 const char *word
, *state
;
411 FOREACH_WORD(word
, len
, string
, state
) {
412 _cleanup_free_
char *addr_str
= NULL
;
413 struct in6_addr
*new_addresses
;
416 new_addresses
= realloc(addresses
, (size
+ 1) * sizeof(struct in6_addr
));
420 addresses
= new_addresses
;
422 addr_str
= strndup(word
, len
);
426 r
= inet_pton(AF_INET6
, addr_str
, &(addresses
[size
]));
439 void serialize_dhcp_routes(FILE *f
, const char *key
, struct sd_dhcp_route
*routes
, size_t size
) {
447 fprintf(f
, "%s=", key
);
449 for (i
= 0; i
< size
; i
++) {
450 fprintf(f
, "%s/%" PRIu8
, inet_ntoa(routes
[i
].dst_addr
),
451 routes
[i
].dst_prefixlen
);
452 fprintf(f
, ",%s%s", inet_ntoa(routes
[i
].gw_addr
),
453 (i
< (size
- 1)) ? " ": "");
459 int deserialize_dhcp_routes(struct sd_dhcp_route
**ret
, size_t *ret_size
, size_t *ret_allocated
, const char *string
) {
460 _cleanup_free_
struct sd_dhcp_route
*routes
= NULL
;
461 size_t size
= 0, allocated
= 0;
462 const char *word
, *state
;
467 assert(ret_allocated
);
470 FOREACH_WORD(word
, len
, string
, state
) {
471 /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
472 _cleanup_free_
char* entry
= NULL
;
477 if (!GREEDY_REALLOC(routes
, allocated
, size
+ 1))
480 entry
= strndup(word
, len
);
487 tok_end
= strchr(tok
, '/');
492 r
= inet_aton(tok
, &routes
[size
].dst_addr
);
498 /* get the prefixlen */
499 tok_end
= strchr(tok
, ',');
505 r
= safe_atou(tok
, &n
);
509 routes
[size
].dst_prefixlen
= (uint8_t) n
;
512 /* get the gateway */
513 r
= inet_aton(tok
, &routes
[size
].gw_addr
);
521 *ret_allocated
= allocated
;
528 int serialize_dhcp_option(FILE *f
, const char *key
, const void *data
, size_t size
) {
529 _cleanup_free_
char *hex_buf
= NULL
;
535 hex_buf
= hexmem(data
, size
);
539 fprintf(f
, "%s=%s\n", key
, hex_buf
);
544 int deserialize_dhcp_option(void **data
, size_t *data_len
, const char *string
) {
549 if (strlen(string
) % 2)
552 return unhexmem(string
, strlen(string
), (void **)data
, data_len
);