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 "libudev-private.h"
29 #include "dhcp-lease-internal.h"
33 #include "conf-parser.h"
34 #include "condition.h"
35 #include "network-internal.h"
37 const char *net_get_name(struct udev_device *device) {
38 const char *name, *field;
42 /* fetch some persistent data unique (on this machine) to this device */
43 FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") {
44 name = udev_device_get_property_value(device, field);
52 #define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
54 int net_get_unique_predictable_data(struct udev_device *device, uint8_t result[8]) {
56 const char *name = NULL;
62 name = net_get_name(device);
67 sz = sizeof(sd_id128_t) + l;
70 /* fetch some persistent data unique to this machine */
71 r = sd_id128_get_machine((sd_id128_t*) v);
74 memcpy(v + sizeof(sd_id128_t), name, l);
76 /* Let's hash the machine ID plus the device name. We
77 * use a fixed, but originally randomly created hash
79 siphash24(result, v, sz, HASH_KEY.bytes);
84 bool net_match_config(const struct ether_addr *match_mac,
85 char * const *match_paths,
86 char * const *match_drivers,
87 char * const *match_types,
88 char * const *match_names,
89 Condition *match_host,
90 Condition *match_virt,
91 Condition *match_kernel,
92 Condition *match_arch,
93 const struct ether_addr *dev_mac,
95 const char *dev_parent_driver,
96 const char *dev_driver,
98 const char *dev_name) {
100 if (match_host && !condition_test(match_host))
103 if (match_virt && !condition_test(match_virt))
106 if (match_kernel && !condition_test(match_kernel))
109 if (match_arch && !condition_test(match_arch))
112 if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
115 if (!strv_isempty(match_paths))
116 return strv_fnmatch(dev_path, match_paths, 0);
118 if (!strv_isempty(match_drivers))
119 return strv_fnmatch(dev_driver, match_drivers, 0);
121 if (!strv_isempty(match_types))
122 return strv_fnmatch(dev_type, match_types, 0);
124 if (!strv_isempty(match_names))
125 return strv_fnmatch(dev_name, match_names, 0);
130 int config_parse_net_condition(const char *unit,
131 const char *filename,
134 unsigned section_line,
141 ConditionType cond = ltype;
142 Condition **ret = data;
145 _cleanup_free_ char *s = NULL;
152 negate = rvalue[0] == '!';
160 c = condition_new(cond, s, false, negate);
165 condition_free(*ret);
171 int config_parse_ifname(const char *unit,
172 const char *filename,
175 unsigned section_line,
183 _cleanup_free_ char *n = NULL;
194 if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
195 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
196 "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
210 int config_parse_ifnames(const char *unit,
211 const char *filename,
214 unsigned section_line,
222 const char *word, *state;
231 FOREACH_WORD(word, l, rvalue, state) {
234 n = strndup(word, l);
238 if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
239 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
240 "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
245 r = strv_consume(sv, n);
253 int config_parse_ifalias(const char *unit,
254 const char *filename,
257 unsigned section_line,
265 _cleanup_free_ char *n = NULL;
276 if (!ascii_is_valid(n) || strlen(n) >= IFALIASZ) {
277 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
278 "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
292 int config_parse_hwaddr(const char *unit,
293 const char *filename,
296 unsigned section_line,
302 struct ether_addr **hwaddr = data;
303 struct ether_addr *n;
311 n = new0(struct ether_addr, 1);
315 r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
316 &n->ether_addr_octet[0],
317 &n->ether_addr_octet[1],
318 &n->ether_addr_octet[2],
319 &n->ether_addr_octet[3],
320 &n->ether_addr_octet[4],
321 &n->ether_addr_octet[5]);
323 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
324 "Not a valid MAC address, ignoring assignment: %s", rvalue);
335 void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
342 for (i = 0; i < size; i++)
343 fprintf(f, "%s%s", inet_ntoa(addresses[i]),
344 (i < (size - 1)) ? " ": "");
347 int deserialize_in_addrs(struct in_addr **ret, const char *string) {
348 _cleanup_free_ struct in_addr *addresses = NULL;
350 const char *word, *state;
356 FOREACH_WORD(word, len, string, state) {
357 _cleanup_free_ char *addr_str = NULL;
358 struct in_addr *new_addresses;
361 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in_addr));
365 addresses = new_addresses;
367 addr_str = strndup(word, len);
371 r = inet_pton(AF_INET, addr_str, &(addresses[size]));
384 int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
385 _cleanup_free_ struct in6_addr *addresses = NULL;
387 const char *word, *state;
393 FOREACH_WORD(word, len, string, state) {
394 _cleanup_free_ char *addr_str = NULL;
395 struct in6_addr *new_addresses;
398 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in6_addr));
402 addresses = new_addresses;
404 addr_str = strndup(word, len);
408 r = inet_pton(AF_INET6, addr_str, &(addresses[size]));
421 void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size) {
429 fprintf(f, "%s=", key);
431 for (i = 0; i < size; i++) {
432 fprintf(f, "%s/%" PRIu8, inet_ntoa(routes[i].dst_addr),
433 routes[i].dst_prefixlen);
434 fprintf(f, ",%s%s", inet_ntoa(routes[i].gw_addr),
435 (i < (size - 1)) ? " ": "");
441 int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) {
442 _cleanup_free_ struct sd_dhcp_route *routes = NULL;
443 size_t size = 0, allocated = 0;
444 const char *word, *state;
449 assert(ret_allocated);
452 FOREACH_WORD(word, len, string, state) {
453 /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
454 _cleanup_free_ char* entry = NULL;
459 if (!GREEDY_REALLOC(routes, allocated, size + 1))
462 entry = strndup(word, len);
469 tok_end = strchr(tok, '/');
474 r = inet_aton(tok, &routes[size].dst_addr);
480 /* get the prefixlen */
481 tok_end = strchr(tok, ',');
487 r = safe_atou(tok, &n);
491 routes[size].dst_prefixlen = (uint8_t) n;
494 /* get the gateway */
495 r = inet_aton(tok, &routes[size].gw_addr);
503 *ret_allocated = allocated;