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>
27 #include "siphash24.h"
28 #include "dhcp-lease-internal.h"
32 #include "conf-parser.h"
33 #include "condition.h"
34 #include "network-internal.h"
36 const char *net_get_name(struct udev_device *device) {
37 const char *name, *field;
41 /* fetch some persistent data unique (on this machine) to this device */
42 FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") {
43 name = udev_device_get_property_value(device, field);
51 #define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
53 int net_get_unique_predictable_data(struct udev_device *device, uint8_t result[8]) {
55 const char *name = NULL;
61 name = net_get_name(device);
66 sz = sizeof(sd_id128_t) + l;
69 /* fetch some persistent data unique to this machine */
70 r = sd_id128_get_machine((sd_id128_t*) v);
73 memcpy(v + sizeof(sd_id128_t), name, l);
75 /* Let's hash the machine ID plus the device name. We
76 * use a fixed, but originally randomly created hash
78 siphash24(result, v, sz, HASH_KEY.bytes);
83 bool net_match_config(const struct ether_addr *match_mac,
84 char * const *match_paths,
85 char * const *match_drivers,
86 char * const *match_types,
87 char * const *match_names,
88 Condition *match_host,
89 Condition *match_virt,
90 Condition *match_kernel,
91 Condition *match_arch,
92 const struct ether_addr *dev_mac,
94 const char *dev_parent_driver,
95 const char *dev_driver,
97 const char *dev_name) {
99 if (match_host && !condition_test(match_host))
102 if (match_virt && !condition_test(match_virt))
105 if (match_kernel && !condition_test(match_kernel))
108 if (match_arch && !condition_test(match_arch))
111 if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
114 if (!strv_isempty(match_paths) &&
115 (!dev_path || !strv_fnmatch(match_paths, dev_path, 0)))
118 if (!strv_isempty(match_drivers) &&
119 (!dev_driver || !strv_fnmatch(match_drivers, dev_driver, 0)))
122 if (!strv_isempty(match_types) &&
123 (!dev_type || !strv_fnmatch_or_empty(match_types, dev_type, 0)))
126 if (!strv_isempty(match_names) &&
127 (!dev_name || !strv_fnmatch_or_empty(match_names, dev_name, 0)))
133 int config_parse_net_condition(const char *unit,
134 const char *filename,
137 unsigned section_line,
144 ConditionType cond = ltype;
145 Condition **ret = data;
148 _cleanup_free_ char *s = NULL;
155 negate = rvalue[0] == '!';
163 c = condition_new(cond, s, false, negate);
168 condition_free(*ret);
174 int config_parse_ifname(const char *unit,
175 const char *filename,
178 unsigned section_line,
186 _cleanup_free_ char *n = NULL;
197 if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
198 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
199 "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
213 int config_parse_ifnames(const char *unit,
214 const char *filename,
217 unsigned section_line,
225 const char *word, *state;
234 FOREACH_WORD(word, l, rvalue, state) {
237 n = strndup(word, l);
241 if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
242 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
243 "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
248 r = strv_consume(sv, n);
256 int config_parse_ifalias(const char *unit,
257 const char *filename,
260 unsigned section_line,
268 _cleanup_free_ char *n = NULL;
279 if (!ascii_is_valid(n) || strlen(n) >= IFALIASZ) {
280 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
281 "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
295 int config_parse_hwaddr(const char *unit,
296 const char *filename,
299 unsigned section_line,
305 struct ether_addr **hwaddr = data;
306 struct ether_addr *n;
314 n = new0(struct ether_addr, 1);
318 r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
319 &n->ether_addr_octet[0],
320 &n->ether_addr_octet[1],
321 &n->ether_addr_octet[2],
322 &n->ether_addr_octet[3],
323 &n->ether_addr_octet[4],
324 &n->ether_addr_octet[5]);
326 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
327 "Not a valid MAC address, ignoring assignment: %s", rvalue);
338 void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
345 for (i = 0; i < size; i++)
346 fprintf(f, "%s%s", inet_ntoa(addresses[i]),
347 (i < (size - 1)) ? " ": "");
350 int deserialize_in_addrs(struct in_addr **ret, const char *string) {
351 _cleanup_free_ struct in_addr *addresses = NULL;
353 const char *word, *state;
359 FOREACH_WORD(word, len, string, state) {
360 _cleanup_free_ char *addr_str = NULL;
361 struct in_addr *new_addresses;
364 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in_addr));
368 addresses = new_addresses;
370 addr_str = strndup(word, len);
374 r = inet_pton(AF_INET, addr_str, &(addresses[size]));
387 int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
388 _cleanup_free_ struct in6_addr *addresses = NULL;
390 const char *word, *state;
396 FOREACH_WORD(word, len, string, state) {
397 _cleanup_free_ char *addr_str = NULL;
398 struct in6_addr *new_addresses;
401 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in6_addr));
405 addresses = new_addresses;
407 addr_str = strndup(word, len);
411 r = inet_pton(AF_INET6, addr_str, &(addresses[size]));
424 void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size) {
432 fprintf(f, "%s=", key);
434 for (i = 0; i < size; i++) {
435 fprintf(f, "%s/%" PRIu8, inet_ntoa(routes[i].dst_addr),
436 routes[i].dst_prefixlen);
437 fprintf(f, ",%s%s", inet_ntoa(routes[i].gw_addr),
438 (i < (size - 1)) ? " ": "");
444 int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) {
445 _cleanup_free_ struct sd_dhcp_route *routes = NULL;
446 size_t size = 0, allocated = 0;
447 const char *word, *state;
452 assert(ret_allocated);
455 FOREACH_WORD(word, len, string, state) {
456 /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
457 _cleanup_free_ char* entry = NULL;
462 if (!GREEDY_REALLOC(routes, allocated, size + 1))
465 entry = strndup(word, len);
472 tok_end = strchr(tok, '/');
477 r = inet_aton(tok, &routes[size].dst_addr);
483 /* get the prefixlen */
484 tok_end = strchr(tok, ',');
490 r = safe_atou(tok, &n);
494 routes[size].dst_prefixlen = (uint8_t) n;
497 /* get the gateway */
498 r = inet_aton(tok, &routes[size].gw_addr);
506 *ret_allocated = allocated;