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 const char *match_path,
87 const char *match_driver,
88 const char *match_type,
89 const char *match_name,
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,
100 bool ignore_name_match) {
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 (match_path && (!dev_path || fnmatch(match_path, dev_path, 0)))
121 if (dev_parent_driver && !streq(match_driver, dev_parent_driver))
123 else if (!streq_ptr(match_driver, dev_driver))
127 if (match_type && !streq_ptr(match_type, dev_type))
131 if (!dev_name || fnmatch(match_name, dev_name, 0))
133 else if (ignore_name_match) {
134 log_warning("ifname (%s) matched config, but is ignored as it is not the original name", dev_name);
142 int config_parse_net_condition(const char *unit,
143 const char *filename,
146 unsigned section_line,
153 ConditionType cond = ltype;
154 Condition **ret = data;
157 _cleanup_free_ char *s = NULL;
164 negate = rvalue[0] == '!';
172 c = condition_new(cond, s, false, negate);
177 condition_free(*ret);
183 int config_parse_ifname(const char *unit,
184 const char *filename,
187 unsigned section_line,
195 _cleanup_free_ char *n = NULL;
206 if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
207 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
208 "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
222 int config_parse_ifalias(const char *unit,
223 const char *filename,
226 unsigned section_line,
245 if (!ascii_is_valid(n) || strlen(n) >= IFALIASZ) {
246 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
247 "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
263 int config_parse_hwaddr(const char *unit,
264 const char *filename,
267 unsigned section_line,
273 struct ether_addr **hwaddr = data;
274 struct ether_addr *n;
282 n = new0(struct ether_addr, 1);
286 r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
287 &n->ether_addr_octet[0],
288 &n->ether_addr_octet[1],
289 &n->ether_addr_octet[2],
290 &n->ether_addr_octet[3],
291 &n->ether_addr_octet[4],
292 &n->ether_addr_octet[5]);
294 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
295 "Not a valid MAC address, ignoring assignment: %s", rvalue);
306 void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
313 for (i = 0; i < size; i++)
314 fprintf(f, "%s%s", inet_ntoa(addresses[i]),
315 (i < (size - 1)) ? " ": "");
318 int deserialize_in_addrs(struct in_addr **ret, const char *string) {
319 _cleanup_free_ struct in_addr *addresses = NULL;
321 const char *word, *state;
327 FOREACH_WORD(word, len, string, state) {
328 _cleanup_free_ char *addr_str = NULL;
329 struct in_addr *new_addresses;
332 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in_addr));
336 addresses = new_addresses;
338 addr_str = strndup(word, len);
342 r = inet_pton(AF_INET, addr_str, &(addresses[size]));
355 int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
356 _cleanup_free_ struct in6_addr *addresses = NULL;
358 const char *word, *state;
364 FOREACH_WORD(word, len, string, state) {
365 _cleanup_free_ char *addr_str = NULL;
366 struct in6_addr *new_addresses;
369 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in6_addr));
373 addresses = new_addresses;
375 addr_str = strndup(word, len);
379 r = inet_pton(AF_INET6, addr_str, &(addresses[size]));
392 void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size) {
400 fprintf(f, "%s=", key);
402 for (i = 0; i < size; i++)
403 fprintf(f, "%s/%" PRIu8 ",%s%s", inet_ntoa(routes[i].dst_addr),
404 routes[i].dst_prefixlen, inet_ntoa(routes[i].gw_addr),
405 (i < (size - 1)) ? " ": "");
410 int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) {
411 _cleanup_free_ struct sd_dhcp_route *routes = NULL;
412 size_t size = 0, allocated = 0;
413 const char *word, *state;
418 assert(ret_allocated);
421 FOREACH_WORD(word, len, string, state) {
422 /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
423 _cleanup_free_ char* entry = NULL;
428 if (!GREEDY_REALLOC(routes, allocated, size + 1))
431 entry = strndup(word, len);
438 tok_end = strchr(tok, '/');
443 r = inet_aton(tok, &routes[size].dst_addr);
449 /* get the prefixlen */
450 tok_end = strchr(tok, ',');
456 r = safe_atou(tok, &n);
460 routes[size].dst_prefixlen = (uint8_t) n;
463 /* get the gateway */
464 r = inet_aton(tok, &routes[size].gw_addr);
472 *ret_allocated = allocated;