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