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_host(match_host))
104 if (match_virt && !condition_test_virtualization(match_virt))
107 if (match_kernel && !condition_test_kernel_command_line(match_kernel))
110 if (match_arch && !condition_test_architecture(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);
216 int config_parse_ifalias(const char *unit,
217 const char *filename,
220 unsigned section_line,
239 if (!ascii_is_valid(n) || strlen(n) >= IFALIASZ) {
240 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
241 "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
257 int config_parse_hwaddr(const char *unit,
258 const char *filename,
261 unsigned section_line,
267 struct ether_addr **hwaddr = data;
268 struct ether_addr *n;
276 n = new0(struct ether_addr, 1);
280 r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
281 &n->ether_addr_octet[0],
282 &n->ether_addr_octet[1],
283 &n->ether_addr_octet[2],
284 &n->ether_addr_octet[3],
285 &n->ether_addr_octet[4],
286 &n->ether_addr_octet[5]);
288 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
289 "Not a valid MAC address, ignoring assignment: %s", rvalue);
300 void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
307 for (i = 0; i < size; i++)
308 fprintf(f, "%s%s", inet_ntoa(addresses[i]),
309 (i < (size - 1)) ? " ": "");
312 int deserialize_in_addrs(struct in_addr **ret, const char *string) {
313 _cleanup_free_ struct in_addr *addresses = NULL;
315 const char *word, *state;
321 FOREACH_WORD(word, len, string, state) {
322 _cleanup_free_ char *addr_str = NULL;
323 struct in_addr *new_addresses;
326 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in_addr));
330 addresses = new_addresses;
332 addr_str = strndup(word, len);
336 r = inet_pton(AF_INET, addr_str, &(addresses[size]));
349 int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
350 _cleanup_free_ struct in6_addr *addresses = NULL;
352 const char *word, *state;
358 FOREACH_WORD(word, len, string, state) {
359 _cleanup_free_ char *addr_str = NULL;
360 struct in6_addr *new_addresses;
363 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in6_addr));
367 addresses = new_addresses;
369 addr_str = strndup(word, len);
373 r = inet_pton(AF_INET6, addr_str, &(addresses[size]));
386 void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size) {
394 fprintf(f, "%s=", key);
396 for (i = 0; i < size; i++)
397 fprintf(f, "%s/%" PRIu8 ",%s%s", inet_ntoa(routes[i].dst_addr),
398 routes[i].dst_prefixlen, inet_ntoa(routes[i].gw_addr),
399 (i < (size - 1)) ? " ": "");
404 int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) {
405 _cleanup_free_ struct sd_dhcp_route *routes = NULL;
406 size_t size = 0, allocated = 0;
407 const char *word, *state;
412 assert(ret_allocated);
415 FOREACH_WORD(word, len, string, state) {
416 /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
417 _cleanup_free_ char* entry = NULL;
422 if (!GREEDY_REALLOC(routes, allocated, size + 1))
425 entry = strndup(word, len);
432 tok_end = strchr(tok, '/');
437 r = inet_aton(tok, &routes[size].dst_addr);
443 /* get the prefixlen */
444 tok_end = strchr(tok, ',');
450 r = safe_atou(tok, &n);
454 routes[size].dst_prefixlen = (uint8_t) n;
457 /* get the gateway */
458 r = inet_aton(tok, &routes[size].gw_addr);
466 *ret_allocated = allocated;