]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/network-internal.c
util-lib: split out globbing related calls into glob-util.[ch]
[thirdparty/systemd.git] / src / libsystemd-network / network-internal.c
CommitLineData
5fde13d7
TG
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
7
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.
12
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.
17
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/>.
20***/
21
f5284182 22#include <arpa/inet.h>
07630cea
LP
23#include <linux/if.h>
24#include <netinet/ether.h>
5fde13d7 25
07630cea
LP
26#include "sd-ndisc.h"
27
28#include "condition.h"
29#include "conf-parser.h"
e1ea665e 30#include "dhcp-lease-internal.h"
be32eb9b 31#include "log.h"
6bedfcbb 32#include "network-internal.h"
e4e73a63 33#include "hexdecoct.h"
6bedfcbb 34#include "parse-util.h"
07630cea
LP
35#include "siphash24.h"
36#include "string-util.h"
37#include "strv.h"
5fde13d7 38#include "utf8.h"
a12fa420 39#include "util.h"
5fde13d7 40
fc541430 41const char *net_get_name(struct udev_device *device) {
44e7b949 42 const char *name, *field;
fc541430
TG
43
44 assert(device);
b5db00e5
UTL
45
46 /* fetch some persistent data unique (on this machine) to this device */
44e7b949 47 FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") {
b5db00e5
UTL
48 name = udev_device_get_property_value(device, field);
49 if (name)
44e7b949 50 return name;
b5db00e5
UTL
51 }
52
44e7b949 53 return NULL;
fc541430
TG
54}
55
56#define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
57
58int net_get_unique_predictable_data(struct udev_device *device, uint8_t result[8]) {
59 size_t l, sz = 0;
60 const char *name = NULL;
61 int r;
62 uint8_t *v;
63
64 assert(device);
65
66 name = net_get_name(device);
b5db00e5
UTL
67 if (!name)
68 return -ENOENT;
69
70 l = strlen(name);
71 sz = sizeof(sd_id128_t) + l;
72 v = alloca(sz);
73
74 /* fetch some persistent data unique to this machine */
75 r = sd_id128_get_machine((sd_id128_t*) v);
76 if (r < 0)
77 return r;
78 memcpy(v + sizeof(sd_id128_t), name, l);
79
80 /* Let's hash the machine ID plus the device name. We
81 * use a fixed, but originally randomly created hash
82 * key here. */
83 siphash24(result, v, sz, HASH_KEY.bytes);
84
85 return 0;
86}
87
be32eb9b 88bool net_match_config(const struct ether_addr *match_mac,
5256e00e
TG
89 char * const *match_paths,
90 char * const *match_drivers,
91 char * const *match_types,
92 char * const *match_names,
2cc412b5
TG
93 Condition *match_host,
94 Condition *match_virt,
95 Condition *match_kernel,
edbb03e9 96 Condition *match_arch,
505f8da7 97 const struct ether_addr *dev_mac,
b3e01314 98 const char *dev_path,
bf175aaf 99 const char *dev_parent_driver,
b3e01314
TG
100 const char *dev_driver,
101 const char *dev_type,
32bc8adc 102 const char *dev_name) {
be32eb9b 103
a4705396 104 if (match_host && !condition_test(match_host))
7eb08da4 105 return false;
2cc412b5 106
a4705396 107 if (match_virt && !condition_test(match_virt))
7eb08da4 108 return false;
2cc412b5 109
a4705396 110 if (match_kernel && !condition_test(match_kernel))
7eb08da4 111 return false;
2cc412b5 112
a4705396 113 if (match_arch && !condition_test(match_arch))
7eb08da4 114 return false;
edbb03e9 115
505f8da7 116 if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
7eb08da4 117 return false;
be32eb9b 118
d49dc812 119 if (!strv_isempty(match_paths) &&
2404701e 120 (!dev_path || !strv_fnmatch(match_paths, dev_path, 0)))
ee5de57b 121 return false;
5256e00e 122
d49dc812 123 if (!strv_isempty(match_drivers) &&
2404701e 124 (!dev_driver || !strv_fnmatch(match_drivers, dev_driver, 0)))
ee5de57b 125 return false;
5256e00e 126
d49dc812 127 if (!strv_isempty(match_types) &&
2404701e 128 (!dev_type || !strv_fnmatch_or_empty(match_types, dev_type, 0)))
ee5de57b 129 return false;
5256e00e 130
d49dc812 131 if (!strv_isempty(match_names) &&
2404701e 132 (!dev_name || !strv_fnmatch_or_empty(match_names, dev_name, 0)))
ee5de57b 133 return false;
5256e00e 134
7eb08da4 135 return true;
be32eb9b 136}
5fde13d7 137
2cc412b5
TG
138int config_parse_net_condition(const char *unit,
139 const char *filename,
140 unsigned line,
141 const char *section,
142 unsigned section_line,
143 const char *lvalue,
144 int ltype,
145 const char *rvalue,
146 void *data,
147 void *userdata) {
148
149 ConditionType cond = ltype;
150 Condition **ret = data;
151 bool negate;
152 Condition *c;
153 _cleanup_free_ char *s = NULL;
154
155 assert(filename);
156 assert(lvalue);
157 assert(rvalue);
158 assert(data);
159
160 negate = rvalue[0] == '!';
161 if (negate)
162 rvalue++;
163
164 s = strdup(rvalue);
165 if (!s)
166 return log_oom();
167
168 c = condition_new(cond, s, false, negate);
169 if (!c)
170 return log_oom();
171
172 if (*ret)
173 condition_free(*ret);
174
175 *ret = c;
176 return 0;
177}
178
5fde13d7
TG
179int config_parse_ifname(const char *unit,
180 const char *filename,
181 unsigned line,
182 const char *section,
71a61510 183 unsigned section_line,
5fde13d7
TG
184 const char *lvalue,
185 int ltype,
186 const char *rvalue,
187 void *data,
188 void *userdata) {
189
190 char **s = data;
5a3f1989 191 _cleanup_free_ char *n = NULL;
5fde13d7
TG
192
193 assert(filename);
194 assert(lvalue);
195 assert(rvalue);
196 assert(data);
197
198 n = strdup(rvalue);
199 if (!n)
200 return log_oom();
201
202 if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
12ca818f 203 log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
5fde13d7
TG
204 return 0;
205 }
206
207 free(*s);
5a3f1989 208 if (*n) {
5fde13d7 209 *s = n;
5a3f1989
TG
210 n = NULL;
211 } else
5fde13d7 212 *s = NULL;
5fde13d7
TG
213
214 return 0;
215}
216
5256e00e
TG
217int config_parse_ifnames(const char *unit,
218 const char *filename,
219 unsigned line,
220 const char *section,
221 unsigned section_line,
222 const char *lvalue,
223 int ltype,
224 const char *rvalue,
225 void *data,
226 void *userdata) {
227
228 char ***sv = data;
229 const char *word, *state;
230 size_t l;
231 int r;
232
233 assert(filename);
234 assert(lvalue);
235 assert(rvalue);
236 assert(data);
237
238 FOREACH_WORD(word, l, rvalue, state) {
239 char *n;
240
241 n = strndup(word, l);
242 if (!n)
243 return log_oom();
244
245 if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
12ca818f 246 log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
5256e00e
TG
247 free(n);
248 return 0;
249 }
250
251 r = strv_consume(sv, n);
252 if (r < 0)
253 return log_oom();
254 }
255
256 return 0;
257}
258
d2df0d0e
TG
259int config_parse_ifalias(const char *unit,
260 const char *filename,
261 unsigned line,
262 const char *section,
71a61510 263 unsigned section_line,
d2df0d0e
TG
264 const char *lvalue,
265 int ltype,
266 const char *rvalue,
267 void *data,
268 void *userdata) {
269
270 char **s = data;
9c39eb5c 271 _cleanup_free_ char *n = NULL;
d2df0d0e
TG
272
273 assert(filename);
274 assert(lvalue);
275 assert(rvalue);
276 assert(data);
277
278 n = strdup(rvalue);
279 if (!n)
280 return log_oom();
281
282 if (!ascii_is_valid(n) || strlen(n) >= IFALIASZ) {
12ca818f 283 log_syntax(unit, LOG_ERR, filename, line, 0, "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
d2df0d0e
TG
284 return 0;
285 }
286
287 free(*s);
9c39eb5c 288 if (*n) {
d2df0d0e 289 *s = n;
9c39eb5c
TG
290 n = NULL;
291 } else
d2df0d0e 292 *s = NULL;
d2df0d0e
TG
293
294 return 0;
295}
296
5fde13d7
TG
297int config_parse_hwaddr(const char *unit,
298 const char *filename,
299 unsigned line,
300 const char *section,
71a61510 301 unsigned section_line,
5fde13d7
TG
302 const char *lvalue,
303 int ltype,
304 const char *rvalue,
305 void *data,
306 void *userdata) {
307 struct ether_addr **hwaddr = data;
308 struct ether_addr *n;
309 int r;
310
311 assert(filename);
312 assert(lvalue);
313 assert(rvalue);
314 assert(data);
315
a12fa420 316 n = new0(struct ether_addr, 1);
5fde13d7
TG
317 if (!n)
318 return log_oom();
319
320 r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
321 &n->ether_addr_octet[0],
322 &n->ether_addr_octet[1],
323 &n->ether_addr_octet[2],
324 &n->ether_addr_octet[3],
325 &n->ether_addr_octet[4],
326 &n->ether_addr_octet[5]);
327 if (r != 6) {
12ca818f 328 log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue);
5fde13d7
TG
329 free(n);
330 return 0;
331 }
332
333 free(*hwaddr);
334 *hwaddr = n;
335
336 return 0;
337}
f5284182 338
b0e39c82 339void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
09bee74d
TG
340 unsigned i;
341
342 assert(f);
09bee74d
TG
343 assert(addresses);
344 assert(size);
345
09bee74d
TG
346 for (i = 0; i < size; i++)
347 fprintf(f, "%s%s", inet_ntoa(addresses[i]),
348 (i < (size - 1)) ? " ": "");
09bee74d
TG
349}
350
a2ba62c7 351int deserialize_in_addrs(struct in_addr **ret, const char *string) {
09bee74d 352 _cleanup_free_ struct in_addr *addresses = NULL;
a2ba62c7 353 int size = 0;
a2a5291b 354 const char *word, *state;
09bee74d
TG
355 size_t len;
356
357 assert(ret);
09bee74d
TG
358 assert(string);
359
360 FOREACH_WORD(word, len, string, state) {
361 _cleanup_free_ char *addr_str = NULL;
362 struct in_addr *new_addresses;
363 int r;
364
365 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in_addr));
366 if (!new_addresses)
367 return -ENOMEM;
368 else
369 addresses = new_addresses;
370
371 addr_str = strndup(word, len);
372 if (!addr_str)
373 return -ENOMEM;
374
375 r = inet_pton(AF_INET, addr_str, &(addresses[size]));
376 if (r <= 0)
377 continue;
378
379 size ++;
380 }
381
09bee74d
TG
382 *ret = addresses;
383 addresses = NULL;
384
a2ba62c7 385 return size;
09bee74d
TG
386}
387
b729fa14
PF
388void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses,
389 size_t size) {
390 unsigned i;
391
392 assert(f);
393 assert(addresses);
394 assert(size);
395
396 for (i = 0; i < size; i++)
4d7b83da
TG
397 fprintf(f, SD_NDISC_ADDRESS_FORMAT_STR"%s",
398 SD_NDISC_ADDRESS_FORMAT_VAL(addresses[i]),
b729fa14
PF
399 (i < (size - 1)) ? " ": "");
400}
401
a2ba62c7 402int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
09bee74d 403 _cleanup_free_ struct in6_addr *addresses = NULL;
a2ba62c7 404 int size = 0;
a2a5291b 405 const char *word, *state;
09bee74d
TG
406 size_t len;
407
408 assert(ret);
09bee74d
TG
409 assert(string);
410
411 FOREACH_WORD(word, len, string, state) {
412 _cleanup_free_ char *addr_str = NULL;
413 struct in6_addr *new_addresses;
414 int r;
415
416 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in6_addr));
417 if (!new_addresses)
418 return -ENOMEM;
419 else
420 addresses = new_addresses;
421
422 addr_str = strndup(word, len);
423 if (!addr_str)
424 return -ENOMEM;
425
426 r = inet_pton(AF_INET6, addr_str, &(addresses[size]));
427 if (r <= 0)
428 continue;
429
430 size++;
431 }
432
09bee74d
TG
433 *ret = addresses;
434 addresses = NULL;
435
a2ba62c7 436 return size;
09bee74d 437}
e1ea665e
EY
438
439void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size) {
440 unsigned i;
441
442 assert(f);
443 assert(key);
444 assert(routes);
445 assert(size);
446
447 fprintf(f, "%s=", key);
448
fbf7dcb5
DW
449 for (i = 0; i < size; i++) {
450 fprintf(f, "%s/%" PRIu8, inet_ntoa(routes[i].dst_addr),
451 routes[i].dst_prefixlen);
452 fprintf(f, ",%s%s", inet_ntoa(routes[i].gw_addr),
e1ea665e 453 (i < (size - 1)) ? " ": "");
fbf7dcb5 454 }
e1ea665e
EY
455
456 fputs("\n", f);
457}
458
459int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) {
460 _cleanup_free_ struct sd_dhcp_route *routes = NULL;
461 size_t size = 0, allocated = 0;
a2a5291b 462 const char *word, *state;
e1ea665e
EY
463 size_t len;
464
465 assert(ret);
466 assert(ret_size);
467 assert(ret_allocated);
468 assert(string);
469
470 FOREACH_WORD(word, len, string, state) {
471 /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
69f08c83 472 _cleanup_free_ char* entry = NULL;
e1ea665e
EY
473 char *tok, *tok_end;
474 unsigned n;
475 int r;
476
477 if (!GREEDY_REALLOC(routes, allocated, size + 1))
478 return -ENOMEM;
479
480 entry = strndup(word, len);
31db0120
SS
481 if(!entry)
482 return -ENOMEM;
e1ea665e
EY
483
484 tok = entry;
485
486 /* get the subnet */
487 tok_end = strchr(tok, '/');
488 if (!tok_end)
489 continue;
490 *tok_end = '\0';
491
492 r = inet_aton(tok, &routes[size].dst_addr);
493 if (r == 0)
494 continue;
495
496 tok = tok_end + 1;
497
498 /* get the prefixlen */
499 tok_end = strchr(tok, ',');
500 if (!tok_end)
501 continue;
502
503 *tok_end = '\0';
504
505 r = safe_atou(tok, &n);
506 if (r < 0 || n > 32)
507 continue;
508
509 routes[size].dst_prefixlen = (uint8_t) n;
510 tok = tok_end + 1;
511
512 /* get the gateway */
513 r = inet_aton(tok, &routes[size].gw_addr);
514 if (r == 0)
515 continue;
516
517 size++;
518 }
519
520 *ret_size = size;
521 *ret_allocated = allocated;
522 *ret = routes;
523 routes = NULL;
524
525 return 0;
526}
a073309f 527
e4735228 528int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size) {
a073309f
AC
529 _cleanup_free_ char *hex_buf = NULL;
530
531 assert(f);
532 assert(key);
533 assert(data);
534
535 hex_buf = hexmem(data, size);
536 if (hex_buf == NULL)
537 return -ENOMEM;
538
539 fprintf(f, "%s=%s\n", key, hex_buf);
540
541 return 0;
542}
543
e4735228 544int deserialize_dhcp_option(void **data, size_t *data_len, const char *string) {
a073309f
AC
545 assert(data);
546 assert(data_len);
547 assert(string);
548
549 if (strlen(string) % 2)
550 return -EINVAL;
551
552 return unhexmem(string, strlen(string), (void **)data, data_len);
553}