]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/network-internal.c
util-lib: split string parsing related calls from util.[ch] into parse-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
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
57int net_get_unique_predictable_data(struct udev_device *device, uint8_t result[8]) {
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. */
82 siphash24(result, v, sz, HASH_KEY.bytes);
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;
228 const char *word, *state;
229 size_t l;
230 int r;
231
232 assert(filename);
233 assert(lvalue);
234 assert(rvalue);
235 assert(data);
236
237 FOREACH_WORD(word, l, rvalue, state) {
238 char *n;
239
240 n = strndup(word, l);
241 if (!n)
242 return log_oom();
243
244 if (!ascii_is_valid(n) || strlen(n) >= 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 free(n);
247 return 0;
248 }
249
250 r = strv_consume(sv, n);
251 if (r < 0)
252 return log_oom();
253 }
254
255 return 0;
256}
257
d2df0d0e
TG
258int config_parse_ifalias(const char *unit,
259 const char *filename,
260 unsigned line,
261 const char *section,
71a61510 262 unsigned section_line,
d2df0d0e
TG
263 const char *lvalue,
264 int ltype,
265 const char *rvalue,
266 void *data,
267 void *userdata) {
268
269 char **s = data;
9c39eb5c 270 _cleanup_free_ char *n = NULL;
d2df0d0e
TG
271
272 assert(filename);
273 assert(lvalue);
274 assert(rvalue);
275 assert(data);
276
277 n = strdup(rvalue);
278 if (!n)
279 return log_oom();
280
281 if (!ascii_is_valid(n) || strlen(n) >= IFALIASZ) {
12ca818f 282 log_syntax(unit, LOG_ERR, filename, line, 0, "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
d2df0d0e
TG
283 return 0;
284 }
285
286 free(*s);
9c39eb5c 287 if (*n) {
d2df0d0e 288 *s = n;
9c39eb5c
TG
289 n = NULL;
290 } else
d2df0d0e 291 *s = NULL;
d2df0d0e
TG
292
293 return 0;
294}
295
5fde13d7
TG
296int config_parse_hwaddr(const char *unit,
297 const char *filename,
298 unsigned line,
299 const char *section,
71a61510 300 unsigned section_line,
5fde13d7
TG
301 const char *lvalue,
302 int ltype,
303 const char *rvalue,
304 void *data,
305 void *userdata) {
306 struct ether_addr **hwaddr = data;
307 struct ether_addr *n;
308 int r;
309
310 assert(filename);
311 assert(lvalue);
312 assert(rvalue);
313 assert(data);
314
a12fa420 315 n = new0(struct ether_addr, 1);
5fde13d7
TG
316 if (!n)
317 return log_oom();
318
319 r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
320 &n->ether_addr_octet[0],
321 &n->ether_addr_octet[1],
322 &n->ether_addr_octet[2],
323 &n->ether_addr_octet[3],
324 &n->ether_addr_octet[4],
325 &n->ether_addr_octet[5]);
326 if (r != 6) {
12ca818f 327 log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue);
5fde13d7
TG
328 free(n);
329 return 0;
330 }
331
332 free(*hwaddr);
333 *hwaddr = n;
334
335 return 0;
336}
f5284182 337
b0e39c82 338void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
09bee74d
TG
339 unsigned i;
340
341 assert(f);
09bee74d
TG
342 assert(addresses);
343 assert(size);
344
09bee74d
TG
345 for (i = 0; i < size; i++)
346 fprintf(f, "%s%s", inet_ntoa(addresses[i]),
347 (i < (size - 1)) ? " ": "");
09bee74d
TG
348}
349
a2ba62c7 350int deserialize_in_addrs(struct in_addr **ret, const char *string) {
09bee74d 351 _cleanup_free_ struct in_addr *addresses = NULL;
a2ba62c7 352 int size = 0;
a2a5291b 353 const char *word, *state;
09bee74d
TG
354 size_t len;
355
356 assert(ret);
09bee74d
TG
357 assert(string);
358
359 FOREACH_WORD(word, len, string, state) {
360 _cleanup_free_ char *addr_str = NULL;
361 struct in_addr *new_addresses;
362 int r;
363
364 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in_addr));
365 if (!new_addresses)
366 return -ENOMEM;
367 else
368 addresses = new_addresses;
369
370 addr_str = strndup(word, len);
371 if (!addr_str)
372 return -ENOMEM;
373
374 r = inet_pton(AF_INET, addr_str, &(addresses[size]));
375 if (r <= 0)
376 continue;
377
378 size ++;
379 }
380
09bee74d
TG
381 *ret = addresses;
382 addresses = NULL;
383
a2ba62c7 384 return size;
09bee74d
TG
385}
386
b729fa14
PF
387void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses,
388 size_t size) {
389 unsigned i;
390
391 assert(f);
392 assert(addresses);
393 assert(size);
394
395 for (i = 0; i < size; i++)
4d7b83da
TG
396 fprintf(f, SD_NDISC_ADDRESS_FORMAT_STR"%s",
397 SD_NDISC_ADDRESS_FORMAT_VAL(addresses[i]),
b729fa14
PF
398 (i < (size - 1)) ? " ": "");
399}
400
a2ba62c7 401int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
09bee74d 402 _cleanup_free_ struct in6_addr *addresses = NULL;
a2ba62c7 403 int size = 0;
a2a5291b 404 const char *word, *state;
09bee74d
TG
405 size_t len;
406
407 assert(ret);
09bee74d
TG
408 assert(string);
409
410 FOREACH_WORD(word, len, string, state) {
411 _cleanup_free_ char *addr_str = NULL;
412 struct in6_addr *new_addresses;
413 int r;
414
415 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in6_addr));
416 if (!new_addresses)
417 return -ENOMEM;
418 else
419 addresses = new_addresses;
420
421 addr_str = strndup(word, len);
422 if (!addr_str)
423 return -ENOMEM;
424
425 r = inet_pton(AF_INET6, addr_str, &(addresses[size]));
426 if (r <= 0)
427 continue;
428
429 size++;
430 }
431
09bee74d
TG
432 *ret = addresses;
433 addresses = NULL;
434
a2ba62c7 435 return size;
09bee74d 436}
e1ea665e
EY
437
438void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size) {
439 unsigned i;
440
441 assert(f);
442 assert(key);
443 assert(routes);
444 assert(size);
445
446 fprintf(f, "%s=", key);
447
fbf7dcb5
DW
448 for (i = 0; i < size; i++) {
449 fprintf(f, "%s/%" PRIu8, inet_ntoa(routes[i].dst_addr),
450 routes[i].dst_prefixlen);
451 fprintf(f, ",%s%s", inet_ntoa(routes[i].gw_addr),
e1ea665e 452 (i < (size - 1)) ? " ": "");
fbf7dcb5 453 }
e1ea665e
EY
454
455 fputs("\n", f);
456}
457
458int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) {
459 _cleanup_free_ struct sd_dhcp_route *routes = NULL;
460 size_t size = 0, allocated = 0;
a2a5291b 461 const char *word, *state;
e1ea665e
EY
462 size_t len;
463
464 assert(ret);
465 assert(ret_size);
466 assert(ret_allocated);
467 assert(string);
468
469 FOREACH_WORD(word, len, string, state) {
470 /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
69f08c83 471 _cleanup_free_ char* entry = NULL;
e1ea665e
EY
472 char *tok, *tok_end;
473 unsigned n;
474 int r;
475
476 if (!GREEDY_REALLOC(routes, allocated, size + 1))
477 return -ENOMEM;
478
479 entry = strndup(word, len);
31db0120
SS
480 if(!entry)
481 return -ENOMEM;
e1ea665e
EY
482
483 tok = entry;
484
485 /* get the subnet */
486 tok_end = strchr(tok, '/');
487 if (!tok_end)
488 continue;
489 *tok_end = '\0';
490
491 r = inet_aton(tok, &routes[size].dst_addr);
492 if (r == 0)
493 continue;
494
495 tok = tok_end + 1;
496
497 /* get the prefixlen */
498 tok_end = strchr(tok, ',');
499 if (!tok_end)
500 continue;
501
502 *tok_end = '\0';
503
504 r = safe_atou(tok, &n);
505 if (r < 0 || n > 32)
506 continue;
507
508 routes[size].dst_prefixlen = (uint8_t) n;
509 tok = tok_end + 1;
510
511 /* get the gateway */
512 r = inet_aton(tok, &routes[size].gw_addr);
513 if (r == 0)
514 continue;
515
516 size++;
517 }
518
519 *ret_size = size;
520 *ret_allocated = allocated;
521 *ret = routes;
522 routes = NULL;
523
524 return 0;
525}
a073309f 526
e4735228 527int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size) {
a073309f
AC
528 _cleanup_free_ char *hex_buf = NULL;
529
530 assert(f);
531 assert(key);
532 assert(data);
533
534 hex_buf = hexmem(data, size);
535 if (hex_buf == NULL)
536 return -ENOMEM;
537
538 fprintf(f, "%s=%s\n", key, hex_buf);
539
540 return 0;
541}
542
e4735228 543int deserialize_dhcp_option(void **data, size_t *data_len, const char *string) {
a073309f
AC
544 assert(data);
545 assert(data_len);
546 assert(string);
547
548 if (strlen(string) % 2)
549 return -EINVAL;
550
551 return unhexmem(string, strlen(string), (void **)data, data_len);
552}