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,
99 const char *dev_name) {
101 if (match_host && !condition_test(match_host))
104 if (match_virt && !condition_test(match_virt))
107 if (match_kernel && !condition_test(match_kernel))
110 if (match_arch && !condition_test(match_arch))
113 if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
116 if (match_path && (!dev_path || fnmatch(match_path, dev_path, 0)))
120 if (dev_parent_driver && !streq(match_driver, dev_parent_driver))
122 else if (!streq_ptr(match_driver, dev_driver))
126 if (match_type && !streq_ptr(match_type, dev_type))
129 if (match_name && (!dev_name || fnmatch(match_name, dev_name, 0)))
135 int config_parse_net_condition(const char *unit,
136 const char *filename,
139 unsigned section_line,
146 ConditionType cond = ltype;
147 Condition **ret = data;
150 _cleanup_free_ char *s = NULL;
157 negate = rvalue[0] == '!';
165 c = condition_new(cond, s, false, negate);
170 condition_free(*ret);
176 int config_parse_ifname(const char *unit,
177 const char *filename,
180 unsigned section_line,
188 _cleanup_free_ char *n = NULL;
199 if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
200 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
201 "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
215 int config_parse_ifalias(const char *unit,
216 const char *filename,
219 unsigned section_line,
238 if (!ascii_is_valid(n) || strlen(n) >= IFALIASZ) {
239 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
240 "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
256 int config_parse_hwaddr(const char *unit,
257 const char *filename,
260 unsigned section_line,
266 struct ether_addr **hwaddr = data;
267 struct ether_addr *n;
275 n = new0(struct ether_addr, 1);
279 r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
280 &n->ether_addr_octet[0],
281 &n->ether_addr_octet[1],
282 &n->ether_addr_octet[2],
283 &n->ether_addr_octet[3],
284 &n->ether_addr_octet[4],
285 &n->ether_addr_octet[5]);
287 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
288 "Not a valid MAC address, ignoring assignment: %s", rvalue);
299 void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
306 for (i = 0; i < size; i++)
307 fprintf(f, "%s%s", inet_ntoa(addresses[i]),
308 (i < (size - 1)) ? " ": "");
311 int deserialize_in_addrs(struct in_addr **ret, const char *string) {
312 _cleanup_free_ struct in_addr *addresses = NULL;
314 const char *word, *state;
320 FOREACH_WORD(word, len, string, state) {
321 _cleanup_free_ char *addr_str = NULL;
322 struct in_addr *new_addresses;
325 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in_addr));
329 addresses = new_addresses;
331 addr_str = strndup(word, len);
335 r = inet_pton(AF_INET, addr_str, &(addresses[size]));
348 int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
349 _cleanup_free_ struct in6_addr *addresses = NULL;
351 const char *word, *state;
357 FOREACH_WORD(word, len, string, state) {
358 _cleanup_free_ char *addr_str = NULL;
359 struct in6_addr *new_addresses;
362 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in6_addr));
366 addresses = new_addresses;
368 addr_str = strndup(word, len);
372 r = inet_pton(AF_INET6, addr_str, &(addresses[size]));
385 void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size) {
393 fprintf(f, "%s=", key);
395 for (i = 0; i < size; i++)
396 fprintf(f, "%s/%" PRIu8 ",%s%s", inet_ntoa(routes[i].dst_addr),
397 routes[i].dst_prefixlen, inet_ntoa(routes[i].gw_addr),
398 (i < (size - 1)) ? " ": "");
403 int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) {
404 _cleanup_free_ struct sd_dhcp_route *routes = NULL;
405 size_t size = 0, allocated = 0;
406 const char *word, *state;
411 assert(ret_allocated);
414 FOREACH_WORD(word, len, string, state) {
415 /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
416 _cleanup_free_ char* entry = NULL;
421 if (!GREEDY_REALLOC(routes, allocated, size + 1))
424 entry = strndup(word, len);
431 tok_end = strchr(tok, '/');
436 r = inet_aton(tok, &routes[size].dst_addr);
442 /* get the prefixlen */
443 tok_end = strchr(tok, ',');
449 r = safe_atou(tok, &n);
453 routes[size].dst_prefixlen = (uint8_t) n;
456 /* get the gateway */
457 r = inet_aton(tok, &routes[size].gw_addr);
465 *ret_allocated = allocated;