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 "network-internal.h"
31 #include "dhcp-lease-internal.h"
35 #include "conf-parser.h"
36 #include "condition.h"
38 const char *net_get_name(struct udev_device *device) {
39 const char *name = NULL, *field = NULL;
43 /* fetch some persistent data unique (on this machine) to this device */
44 FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT",
45 "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") {
46 name = udev_device_get_property_value(device, field);
54 #define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
56 int net_get_unique_predictable_data(struct udev_device *device, uint8_t result[8]) {
58 const char *name = NULL;
64 name = net_get_name(device);
69 sz = sizeof(sd_id128_t) + l;
72 /* fetch some persistent data unique to this machine */
73 r = sd_id128_get_machine((sd_id128_t*) v);
76 memcpy(v + sizeof(sd_id128_t), name, l);
78 /* Let's hash the machine ID plus the device name. We
79 * use a fixed, but originally randomly created hash
81 siphash24(result, v, sz, HASH_KEY.bytes);
86 bool net_match_config(const struct ether_addr *match_mac,
87 const char *match_path,
88 const char *match_driver,
89 const char *match_type,
90 const char *match_name,
91 Condition *match_host,
92 Condition *match_virt,
93 Condition *match_kernel,
94 Condition *match_arch,
95 const struct ether_addr *dev_mac,
97 const char *dev_parent_driver,
98 const char *dev_driver,
100 const char *dev_name) {
102 if (match_host && !condition_test_host(match_host))
105 if (match_virt && !condition_test_virtualization(match_virt))
108 if (match_kernel && !condition_test_kernel_command_line(match_kernel))
111 if (match_arch && !condition_test_architecture(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))
130 if (match_name && (!dev_name || fnmatch(match_name, dev_name, 0)))
136 unsigned net_netmask_to_prefixlen(const struct in_addr *addr) {
139 return 32 - u32ctz(be32toh(addr->s_addr));
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);
223 int config_parse_ifalias(const char *unit,
224 const char *filename,
227 unsigned section_line,
246 if (!ascii_is_valid(n) || strlen(n) >= IFALIASZ) {
247 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
248 "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
264 int config_parse_hwaddr(const char *unit,
265 const char *filename,
268 unsigned section_line,
274 struct ether_addr **hwaddr = data;
275 struct ether_addr *n;
283 n = new0(struct ether_addr, 1);
287 r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
288 &n->ether_addr_octet[0],
289 &n->ether_addr_octet[1],
290 &n->ether_addr_octet[2],
291 &n->ether_addr_octet[3],
292 &n->ether_addr_octet[4],
293 &n->ether_addr_octet[5]);
295 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
296 "Not a valid MAC address, ignoring assignment: %s", rvalue);
307 int net_parse_inaddr(const char *address, int *family, void *dst) {
315 r = inet_pton(AF_INET, address, dst);
317 /* succsefully parsed IPv4 address */
318 if (*family == AF_UNSPEC)
320 else if (*family != AF_INET)
325 /* not an IPv4 address, so let's try IPv6 */
326 r = inet_pton(AF_INET6, address, dst);
328 /* successfully parsed IPv6 address */
329 if (*family == AF_UNSPEC)
331 else if (*family != AF_INET6)
342 void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
349 for (i = 0; i < size; i++)
350 fprintf(f, "%s%s", inet_ntoa(addresses[i]),
351 (i < (size - 1)) ? " ": "");
354 int deserialize_in_addrs(struct in_addr **ret, const char *string) {
355 _cleanup_free_ struct in_addr *addresses = NULL;
363 FOREACH_WORD(word, len, string, state) {
364 _cleanup_free_ char *addr_str = NULL;
365 struct in_addr *new_addresses;
368 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in_addr));
372 addresses = new_addresses;
374 addr_str = strndup(word, len);
378 r = inet_pton(AF_INET, addr_str, &(addresses[size]));
391 int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
392 _cleanup_free_ struct in6_addr *addresses = NULL;
400 FOREACH_WORD(word, len, string, state) {
401 _cleanup_free_ char *addr_str = NULL;
402 struct in6_addr *new_addresses;
405 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in6_addr));
409 addresses = new_addresses;
411 addr_str = strndup(word, len);
415 r = inet_pton(AF_INET6, addr_str, &(addresses[size]));
428 void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size) {
436 fprintf(f, "%s=", key);
438 for (i = 0; i < size; i++)
439 fprintf(f, "%s/%" PRIu8 ",%s%s", inet_ntoa(routes[i].dst_addr),
440 routes[i].dst_prefixlen, inet_ntoa(routes[i].gw_addr),
441 (i < (size - 1)) ? " ": "");
446 int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) {
447 _cleanup_free_ struct sd_dhcp_route *routes = NULL;
448 size_t size = 0, allocated = 0;
454 assert(ret_allocated);
457 FOREACH_WORD(word, len, string, state) {
458 /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
459 _cleanup_free_ char* entry = NULL;
464 if (!GREEDY_REALLOC(routes, allocated, size + 1))
467 entry = strndup(word, len);
474 tok_end = strchr(tok, '/');
479 r = inet_aton(tok, &routes[size].dst_addr);
485 /* get the prefixlen */
486 tok_end = strchr(tok, ',');
492 r = safe_atou(tok, &n);
496 routes[size].dst_prefixlen = (uint8_t) n;
499 /* get the gateway */
500 r = inet_aton(tok, &routes[size].gw_addr);
508 *ret_allocated = allocated;