]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/network-internal.c
man: add documentation for the new --network-zone= concept of nspawn
[thirdparty/systemd.git] / src / libsystemd-network / network-internal.c
CommitLineData
5fde13d7
TG
1/***
2 This file is part of systemd.
3
4 Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
f5284182 20#include <arpa/inet.h>
07630cea
LP
21#include <linux/if.h>
22#include <netinet/ether.h>
5fde13d7 23
07630cea
LP
24#include "sd-ndisc.h"
25
b5efdb8a 26#include "alloc-util.h"
07630cea
LP
27#include "condition.h"
28#include "conf-parser.h"
e1ea665e 29#include "dhcp-lease-internal.h"
cf0fbc49 30#include "hexdecoct.h"
be32eb9b 31#include "log.h"
6bedfcbb
LP
32#include "network-internal.h"
33#include "parse-util.h"
07630cea
LP
34#include "siphash24.h"
35#include "string-util.h"
36#include "strv.h"
5fde13d7 37#include "utf8.h"
a12fa420 38#include "util.h"
5fde13d7 39
fc541430 40const char *net_get_name(struct udev_device *device) {
44e7b949 41 const char *name, *field;
fc541430
TG
42
43 assert(device);
b5db00e5
UTL
44
45 /* fetch some persistent data unique (on this machine) to this device */
44e7b949 46 FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") {
b5db00e5
UTL
47 name = udev_device_get_property_value(device, field);
48 if (name)
44e7b949 49 return name;
b5db00e5
UTL
50 }
51
44e7b949 52 return NULL;
fc541430
TG
53}
54
55#define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
56
dbe81cbd 57int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result) {
fc541430
TG
58 size_t l, sz = 0;
59 const char *name = NULL;
60 int r;
61 uint8_t *v;
62
63 assert(device);
64
65 name = net_get_name(device);
b5db00e5
UTL
66 if (!name)
67 return -ENOENT;
68
69 l = strlen(name);
70 sz = sizeof(sd_id128_t) + l;
71 v = alloca(sz);
72
73 /* fetch some persistent data unique to this machine */
74 r = sd_id128_get_machine((sd_id128_t*) v);
75 if (r < 0)
76 return r;
77 memcpy(v + sizeof(sd_id128_t), name, l);
78
79 /* Let's hash the machine ID plus the device name. We
80 * use a fixed, but originally randomly created hash
81 * key here. */
933f9cae 82 *result = htole64(siphash24(v, sz, HASH_KEY.bytes));
b5db00e5
UTL
83
84 return 0;
85}
86
be32eb9b 87bool net_match_config(const struct ether_addr *match_mac,
5256e00e
TG
88 char * const *match_paths,
89 char * const *match_drivers,
90 char * const *match_types,
91 char * const *match_names,
2cc412b5
TG
92 Condition *match_host,
93 Condition *match_virt,
94 Condition *match_kernel,
edbb03e9 95 Condition *match_arch,
505f8da7 96 const struct ether_addr *dev_mac,
b3e01314 97 const char *dev_path,
bf175aaf 98 const char *dev_parent_driver,
b3e01314
TG
99 const char *dev_driver,
100 const char *dev_type,
32bc8adc 101 const char *dev_name) {
be32eb9b 102
a4705396 103 if (match_host && !condition_test(match_host))
7eb08da4 104 return false;
2cc412b5 105
a4705396 106 if (match_virt && !condition_test(match_virt))
7eb08da4 107 return false;
2cc412b5 108
a4705396 109 if (match_kernel && !condition_test(match_kernel))
7eb08da4 110 return false;
2cc412b5 111
a4705396 112 if (match_arch && !condition_test(match_arch))
7eb08da4 113 return false;
edbb03e9 114
505f8da7 115 if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
7eb08da4 116 return false;
be32eb9b 117
d49dc812 118 if (!strv_isempty(match_paths) &&
2404701e 119 (!dev_path || !strv_fnmatch(match_paths, dev_path, 0)))
ee5de57b 120 return false;
5256e00e 121
d49dc812 122 if (!strv_isempty(match_drivers) &&
2404701e 123 (!dev_driver || !strv_fnmatch(match_drivers, dev_driver, 0)))
ee5de57b 124 return false;
5256e00e 125
d49dc812 126 if (!strv_isempty(match_types) &&
2404701e 127 (!dev_type || !strv_fnmatch_or_empty(match_types, dev_type, 0)))
ee5de57b 128 return false;
5256e00e 129
d49dc812 130 if (!strv_isempty(match_names) &&
2404701e 131 (!dev_name || !strv_fnmatch_or_empty(match_names, dev_name, 0)))
ee5de57b 132 return false;
5256e00e 133
7eb08da4 134 return true;
be32eb9b 135}
5fde13d7 136
2cc412b5
TG
137int config_parse_net_condition(const char *unit,
138 const char *filename,
139 unsigned line,
140 const char *section,
141 unsigned section_line,
142 const char *lvalue,
143 int ltype,
144 const char *rvalue,
145 void *data,
146 void *userdata) {
147
148 ConditionType cond = ltype;
149 Condition **ret = data;
150 bool negate;
151 Condition *c;
152 _cleanup_free_ char *s = NULL;
153
154 assert(filename);
155 assert(lvalue);
156 assert(rvalue);
157 assert(data);
158
159 negate = rvalue[0] == '!';
160 if (negate)
161 rvalue++;
162
163 s = strdup(rvalue);
164 if (!s)
165 return log_oom();
166
167 c = condition_new(cond, s, false, negate);
168 if (!c)
169 return log_oom();
170
171 if (*ret)
172 condition_free(*ret);
173
174 *ret = c;
175 return 0;
176}
177
5fde13d7
TG
178int config_parse_ifname(const char *unit,
179 const char *filename,
180 unsigned line,
181 const char *section,
71a61510 182 unsigned section_line,
5fde13d7
TG
183 const char *lvalue,
184 int ltype,
185 const char *rvalue,
186 void *data,
187 void *userdata) {
188
189 char **s = data;
5a3f1989 190 _cleanup_free_ char *n = NULL;
5fde13d7
TG
191
192 assert(filename);
193 assert(lvalue);
194 assert(rvalue);
195 assert(data);
196
197 n = strdup(rvalue);
198 if (!n)
199 return log_oom();
200
201 if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
12ca818f 202 log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
5fde13d7
TG
203 return 0;
204 }
205
206 free(*s);
5a3f1989 207 if (*n) {
5fde13d7 208 *s = n;
5a3f1989
TG
209 n = NULL;
210 } else
5fde13d7 211 *s = NULL;
5fde13d7
TG
212
213 return 0;
214}
215
5256e00e
TG
216int config_parse_ifnames(const char *unit,
217 const char *filename,
218 unsigned line,
219 const char *section,
220 unsigned section_line,
221 const char *lvalue,
222 int ltype,
223 const char *rvalue,
224 void *data,
225 void *userdata) {
226
227 char ***sv = data;
5256e00e
TG
228 int r;
229
230 assert(filename);
231 assert(lvalue);
232 assert(rvalue);
233 assert(data);
234
93e28226
SS
235 for (;;) {
236 _cleanup_free_ char *word = NULL;
5256e00e 237
93e28226
SS
238 r = extract_first_word(&rvalue, &word, NULL, 0);
239 if (r < 0)
240 return r;
241 if (r == 0)
242 break;
5256e00e 243
93e28226 244 if (!ascii_is_valid(word) || strlen(word) >= IFNAMSIZ) {
12ca818f 245 log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
5256e00e
TG
246 return 0;
247 }
248
93e28226 249 r = strv_push(sv, word);
5256e00e
TG
250 if (r < 0)
251 return log_oom();
93e28226
SS
252
253 word = NULL;
5256e00e
TG
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
413708d1
VK
339int config_parse_iaid(const char *unit,
340 const char *filename,
341 unsigned line,
342 const char *section,
343 unsigned section_line,
344 const char *lvalue,
345 int ltype,
346 const char *rvalue,
347 void *data,
348 void *userdata) {
349 uint32_t iaid;
350 int r;
351
352 assert(filename);
353 assert(lvalue);
354 assert(rvalue);
355 assert(data);
356
357 r = safe_atou32(rvalue, &iaid);
358 if (r < 0) {
b7f71444
VK
359 log_syntax(unit, LOG_ERR, filename, line, r,
360 "Unable to read IAID, ignoring assignment: %s", rvalue);
361 return 0;
413708d1
VK
362 }
363
364 *((uint32_t *)data) = iaid;
365
366 return 0;
367}
368
b0e39c82 369void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
09bee74d
TG
370 unsigned i;
371
372 assert(f);
09bee74d
TG
373 assert(addresses);
374 assert(size);
375
09bee74d
TG
376 for (i = 0; i < size; i++)
377 fprintf(f, "%s%s", inet_ntoa(addresses[i]),
378 (i < (size - 1)) ? " ": "");
09bee74d
TG
379}
380
a2ba62c7 381int deserialize_in_addrs(struct in_addr **ret, const char *string) {
09bee74d 382 _cleanup_free_ struct in_addr *addresses = NULL;
a2ba62c7 383 int size = 0;
09bee74d
TG
384
385 assert(ret);
09bee74d
TG
386 assert(string);
387
93e28226
SS
388 for (;;) {
389 _cleanup_free_ char *word = NULL;
09bee74d
TG
390 struct in_addr *new_addresses;
391 int r;
392
93e28226
SS
393 r = extract_first_word(&string, &word, NULL, 0);
394 if (r < 0)
395 return r;
396 if (r == 0)
397 break;
398
09bee74d
TG
399 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in_addr));
400 if (!new_addresses)
401 return -ENOMEM;
402 else
403 addresses = new_addresses;
404
93e28226 405 r = inet_pton(AF_INET, word, &(addresses[size]));
09bee74d
TG
406 if (r <= 0)
407 continue;
408
313cefa1 409 size++;
09bee74d
TG
410 }
411
09bee74d
TG
412 *ret = addresses;
413 addresses = NULL;
414
a2ba62c7 415 return size;
09bee74d
TG
416}
417
b729fa14
PF
418void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses,
419 size_t size) {
420 unsigned i;
421
422 assert(f);
423 assert(addresses);
424 assert(size);
425
426 for (i = 0; i < size; i++)
4d7b83da
TG
427 fprintf(f, SD_NDISC_ADDRESS_FORMAT_STR"%s",
428 SD_NDISC_ADDRESS_FORMAT_VAL(addresses[i]),
b729fa14
PF
429 (i < (size - 1)) ? " ": "");
430}
431
a2ba62c7 432int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
09bee74d 433 _cleanup_free_ struct in6_addr *addresses = NULL;
a2ba62c7 434 int size = 0;
09bee74d
TG
435
436 assert(ret);
09bee74d
TG
437 assert(string);
438
93e28226
SS
439 for (;;) {
440 _cleanup_free_ char *word = NULL;
09bee74d
TG
441 struct in6_addr *new_addresses;
442 int r;
443
93e28226
SS
444 r = extract_first_word(&string, &word, NULL, 0);
445 if (r < 0)
446 return r;
447 if (r == 0)
448 break;
449
09bee74d
TG
450 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in6_addr));
451 if (!new_addresses)
452 return -ENOMEM;
453 else
454 addresses = new_addresses;
455
93e28226 456 r = inet_pton(AF_INET6, word, &(addresses[size]));
09bee74d
TG
457 if (r <= 0)
458 continue;
459
460 size++;
461 }
462
09bee74d
TG
463 *ret = addresses;
464 addresses = NULL;
465
a2ba62c7 466 return size;
09bee74d 467}
e1ea665e 468
f8693fc7 469void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size) {
e1ea665e
EY
470 unsigned i;
471
472 assert(f);
473 assert(key);
474 assert(routes);
475 assert(size);
476
477 fprintf(f, "%s=", key);
478
fbf7dcb5 479 for (i = 0; i < size; i++) {
f8693fc7
BG
480 struct in_addr dest, gw;
481 uint8_t length;
482
483 assert_se(sd_dhcp_route_get_destination(routes[i], &dest) >= 0);
484 assert_se(sd_dhcp_route_get_gateway(routes[i], &gw) >= 0);
485 assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &length) >= 0);
486
487 fprintf(f, "%s/%" PRIu8, inet_ntoa(dest), length);
488 fprintf(f, ",%s%s", inet_ntoa(gw), (i < (size - 1)) ? " ": "");
fbf7dcb5 489 }
e1ea665e
EY
490
491 fputs("\n", f);
492}
493
494int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) {
495 _cleanup_free_ struct sd_dhcp_route *routes = NULL;
496 size_t size = 0, allocated = 0;
e1ea665e
EY
497
498 assert(ret);
499 assert(ret_size);
500 assert(ret_allocated);
501 assert(string);
502
93e28226
SS
503 /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
504 for (;;) {
505 _cleanup_free_ char *word = NULL;
e1ea665e
EY
506 char *tok, *tok_end;
507 unsigned n;
508 int r;
509
93e28226
SS
510 r = extract_first_word(&string, &word, NULL, 0);
511 if (r < 0)
512 return r;
513 if (r == 0)
514 break;
e1ea665e 515
93e28226 516 if (!GREEDY_REALLOC(routes, allocated, size + 1))
31db0120 517 return -ENOMEM;
e1ea665e 518
93e28226 519 tok = word;
e1ea665e
EY
520
521 /* get the subnet */
522 tok_end = strchr(tok, '/');
523 if (!tok_end)
524 continue;
525 *tok_end = '\0';
526
527 r = inet_aton(tok, &routes[size].dst_addr);
528 if (r == 0)
529 continue;
530
531 tok = tok_end + 1;
532
533 /* get the prefixlen */
534 tok_end = strchr(tok, ',');
535 if (!tok_end)
536 continue;
537
538 *tok_end = '\0';
539
540 r = safe_atou(tok, &n);
541 if (r < 0 || n > 32)
542 continue;
543
544 routes[size].dst_prefixlen = (uint8_t) n;
545 tok = tok_end + 1;
546
547 /* get the gateway */
548 r = inet_aton(tok, &routes[size].gw_addr);
549 if (r == 0)
550 continue;
551
552 size++;
553 }
554
555 *ret_size = size;
556 *ret_allocated = allocated;
557 *ret = routes;
558 routes = NULL;
559
560 return 0;
561}
a073309f 562
e4735228 563int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size) {
a073309f
AC
564 _cleanup_free_ char *hex_buf = NULL;
565
566 assert(f);
567 assert(key);
568 assert(data);
569
570 hex_buf = hexmem(data, size);
571 if (hex_buf == NULL)
572 return -ENOMEM;
573
574 fprintf(f, "%s=%s\n", key, hex_buf);
575
576 return 0;
577}
578
e4735228 579int deserialize_dhcp_option(void **data, size_t *data_len, const char *string) {
a073309f
AC
580 assert(data);
581 assert(data_len);
582 assert(string);
583
584 if (strlen(string) % 2)
585 return -EINVAL;
586
587 return unhexmem(string, strlen(string), (void **)data, data_len);
588}