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>
28 #include "siphash24.h"
29 #include "libudev-private.h"
30 #include "dhcp-lease-internal.h"
34 #include "conf-parser.h"
35 #include "condition.h"
36 #include "network-internal.h"
38 const char *net_get_name(struct udev_device *device) {
39 const char *name, *field;
43 /* fetch some persistent data unique (on this machine) to this device */
44 FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") {
45 name = udev_device_get_property_value(device, field);
53 #define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
55 int net_get_unique_predictable_data(struct udev_device *device, uint8_t result[8]) {
57 const char *name = NULL;
63 name = net_get_name(device);
68 sz = sizeof(sd_id128_t) + l;
71 /* fetch some persistent data unique to this machine */
72 r = sd_id128_get_machine((sd_id128_t*) v);
75 memcpy(v + sizeof(sd_id128_t), name, l);
77 /* Let's hash the machine ID plus the device name. We
78 * use a fixed, but originally randomly created hash
80 siphash24(result, v, sz, HASH_KEY.bytes);
85 bool net_match_config(const struct ether_addr *match_mac,
86 char * const *match_paths,
87 char * const *match_drivers,
88 char * const *match_types,
89 char * const *match_names,
90 Condition *match_host,
91 Condition *match_virt,
92 Condition *match_kernel,
93 Condition *match_arch,
94 const struct ether_addr *dev_mac,
96 const char *dev_parent_driver,
97 const char *dev_driver,
99 const char *dev_name) {
100 char * const *match_path;
101 char * const *match_driver;
102 char * const *match_type;
103 char * const *match_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)) {
124 STRV_FOREACH(match_path, match_paths)
125 if (fnmatch(*match_path, dev_path, 0) == 0)
131 if (!strv_isempty(match_drivers)) {
135 STRV_FOREACH(match_driver, match_drivers)
136 if (fnmatch(*match_driver, dev_driver, 0) == 0)
142 if (!strv_isempty(match_types)) {
146 STRV_FOREACH(match_type, match_types)
147 if (fnmatch(*match_type, dev_type, 0) == 0)
153 if (!strv_isempty(match_names)) {
157 STRV_FOREACH(match_name, match_names)
158 if (fnmatch(*match_name, dev_name, 0) == 0)
167 int config_parse_net_condition(const char *unit,
168 const char *filename,
171 unsigned section_line,
178 ConditionType cond = ltype;
179 Condition **ret = data;
182 _cleanup_free_ char *s = NULL;
189 negate = rvalue[0] == '!';
197 c = condition_new(cond, s, false, negate);
202 condition_free(*ret);
208 int config_parse_ifname(const char *unit,
209 const char *filename,
212 unsigned section_line,
220 _cleanup_free_ char *n = NULL;
231 if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
232 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
233 "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
247 int config_parse_ifnames(const char *unit,
248 const char *filename,
251 unsigned section_line,
259 const char *word, *state;
268 FOREACH_WORD(word, l, rvalue, state) {
271 n = strndup(word, l);
275 if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
276 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
277 "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
282 r = strv_consume(sv, n);
290 int config_parse_ifalias(const char *unit,
291 const char *filename,
294 unsigned section_line,
302 _cleanup_free_ char *n = NULL;
313 if (!ascii_is_valid(n) || strlen(n) >= IFALIASZ) {
314 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
315 "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
329 int config_parse_hwaddr(const char *unit,
330 const char *filename,
333 unsigned section_line,
339 struct ether_addr **hwaddr = data;
340 struct ether_addr *n;
348 n = new0(struct ether_addr, 1);
352 r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
353 &n->ether_addr_octet[0],
354 &n->ether_addr_octet[1],
355 &n->ether_addr_octet[2],
356 &n->ether_addr_octet[3],
357 &n->ether_addr_octet[4],
358 &n->ether_addr_octet[5]);
360 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
361 "Not a valid MAC address, ignoring assignment: %s", rvalue);
372 void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
379 for (i = 0; i < size; i++)
380 fprintf(f, "%s%s", inet_ntoa(addresses[i]),
381 (i < (size - 1)) ? " ": "");
384 int deserialize_in_addrs(struct in_addr **ret, const char *string) {
385 _cleanup_free_ struct in_addr *addresses = NULL;
387 const char *word, *state;
393 FOREACH_WORD(word, len, string, state) {
394 _cleanup_free_ char *addr_str = NULL;
395 struct in_addr *new_addresses;
398 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in_addr));
402 addresses = new_addresses;
404 addr_str = strndup(word, len);
408 r = inet_pton(AF_INET, addr_str, &(addresses[size]));
421 int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
422 _cleanup_free_ struct in6_addr *addresses = NULL;
424 const char *word, *state;
430 FOREACH_WORD(word, len, string, state) {
431 _cleanup_free_ char *addr_str = NULL;
432 struct in6_addr *new_addresses;
435 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in6_addr));
439 addresses = new_addresses;
441 addr_str = strndup(word, len);
445 r = inet_pton(AF_INET6, addr_str, &(addresses[size]));
458 void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size) {
466 fprintf(f, "%s=", key);
468 for (i = 0; i < size; i++) {
469 fprintf(f, "%s/%" PRIu8, inet_ntoa(routes[i].dst_addr),
470 routes[i].dst_prefixlen);
471 fprintf(f, ",%s%s", inet_ntoa(routes[i].gw_addr),
472 (i < (size - 1)) ? " ": "");
478 int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) {
479 _cleanup_free_ struct sd_dhcp_route *routes = NULL;
480 size_t size = 0, allocated = 0;
481 const char *word, *state;
486 assert(ret_allocated);
489 FOREACH_WORD(word, len, string, state) {
490 /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
491 _cleanup_free_ char* entry = NULL;
496 if (!GREEDY_REALLOC(routes, allocated, size + 1))
499 entry = strndup(word, len);
506 tok_end = strchr(tok, '/');
511 r = inet_aton(tok, &routes[size].dst_addr);
517 /* get the prefixlen */
518 tok_end = strchr(tok, ',');
524 r = safe_atou(tok, &n);
528 routes[size].dst_prefixlen = (uint8_t) n;
531 /* get the gateway */
532 r = inet_aton(tok, &routes[size].gw_addr);
540 *ret_allocated = allocated;