1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /***
3 Copyright © 2014 Intel Corporation. All rights reserved.
4 ***/
5
6 #include <netinet/icmp6.h>
7
8 #include "sd-ndisc.h"
9
10 #include "alloc-util.h"
11 #include "dns-domain.h"
12 #include "hostname-util.h"
13 #include "memory-util.h"
14 #include "missing_network.h"
15 #include "ndisc-internal.h"
16 #include "ndisc-router.h"
17 #include "strv.h"
18
19 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_ndisc_router, sd_ndisc_router, mfree);
20
ndisc_router_new(size_t raw_size)21 sd_ndisc_router *ndisc_router_new(size_t raw_size) {
22 sd_ndisc_router *rt;
23
24 if (raw_size > SIZE_MAX - ALIGN(sizeof(sd_ndisc_router)))
25 return NULL;
26
27 rt = malloc0(ALIGN(sizeof(sd_ndisc_router)) + raw_size);
28 if (!rt)
29 return NULL;
30
31 rt->raw_size = raw_size;
32 rt->n_ref = 1;
33
34 return rt;
35 }
36
sd_ndisc_router_get_address(sd_ndisc_router * rt,struct in6_addr * ret_addr)37 int sd_ndisc_router_get_address(sd_ndisc_router *rt, struct in6_addr *ret_addr) {
38 assert_return(rt, -EINVAL);
39 assert_return(ret_addr, -EINVAL);
40
41 if (in6_addr_is_null(&rt->address))
42 return -ENODATA;
43
44 *ret_addr = rt->address;
45 return 0;
46 }
47
sd_ndisc_router_get_timestamp(sd_ndisc_router * rt,clockid_t clock,uint64_t * ret)48 int sd_ndisc_router_get_timestamp(sd_ndisc_router *rt, clockid_t clock, uint64_t *ret) {
49 assert_return(rt, -EINVAL);
50 assert_return(TRIPLE_TIMESTAMP_HAS_CLOCK(clock), -EOPNOTSUPP);
51 assert_return(clock_supported(clock), -EOPNOTSUPP);
52 assert_return(ret, -EINVAL);
53
54 if (!triple_timestamp_is_set(&rt->timestamp))
55 return -ENODATA;
56
57 *ret = triple_timestamp_by_clock(&rt->timestamp, clock);
58 return 0;
59 }
60
sd_ndisc_router_get_raw(sd_ndisc_router * rt,const void ** ret,size_t * size)61 int sd_ndisc_router_get_raw(sd_ndisc_router *rt, const void **ret, size_t *size) {
62 assert_return(rt, -EINVAL);
63 assert_return(ret, -EINVAL);
64 assert_return(size, -EINVAL);
65
66 *ret = NDISC_ROUTER_RAW(rt);
67 *size = rt->raw_size;
68
69 return 0;
70 }
71
ndisc_router_parse(sd_ndisc * nd,sd_ndisc_router * rt)72 int ndisc_router_parse(sd_ndisc *nd, sd_ndisc_router *rt) {
73 struct nd_router_advert *a;
74 const uint8_t *p;
75 bool has_mtu = false, has_flag_extension = false;
76 size_t left;
77
78 assert(rt);
79
80 if (rt->raw_size < sizeof(struct nd_router_advert))
81 return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
82 "Too small to be a router advertisement, ignoring.");
83
84 /* Router advertisement packets are neatly aligned to 64bit boundaries, hence we can access them directly */
85 a = NDISC_ROUTER_RAW(rt);
86
87 if (a->nd_ra_type != ND_ROUTER_ADVERT)
88 return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
89 "Received ND packet that is not a router advertisement, ignoring.");
90
91 if (a->nd_ra_code != 0)
92 return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
93 "Received ND packet with wrong RA code, ignoring.");
94
95 rt->hop_limit = a->nd_ra_curhoplimit;
96 rt->flags = a->nd_ra_flags_reserved; /* the first 8bit */
97 rt->lifetime = be16toh(a->nd_ra_router_lifetime);
98
99 rt->preference = (rt->flags >> 3) & 3;
100 if (!IN_SET(rt->preference, SD_NDISC_PREFERENCE_LOW, SD_NDISC_PREFERENCE_HIGH))
101 rt->preference = SD_NDISC_PREFERENCE_MEDIUM;
102
103 p = (const uint8_t*) NDISC_ROUTER_RAW(rt) + sizeof(struct nd_router_advert);
104 left = rt->raw_size - sizeof(struct nd_router_advert);
105
106 for (;;) {
107 uint8_t type;
108 size_t length;
109
110 if (left == 0)
111 break;
112
113 if (left < 2)
114 return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
115 "Option lacks header, ignoring datagram.");
116
117 type = p[0];
118 length = p[1] * 8;
119
120 if (length == 0)
121 return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
122 "Zero-length option, ignoring datagram.");
123 if (left < length)
124 return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
125 "Option truncated, ignoring datagram.");
126
127 switch (type) {
128
129 case SD_NDISC_OPTION_PREFIX_INFORMATION:
130
131 if (length != 4*8)
132 return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
133 "Prefix option of invalid size, ignoring datagram.");
134
135 if (p[2] > 128)
136 return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
137 "Bad prefix length, ignoring datagram.");
138
139 break;
140
141 case SD_NDISC_OPTION_MTU: {
142 uint32_t m;
143
144 if (has_mtu) {
145 log_ndisc(nd, "MTU option specified twice, ignoring.");
146 break;
147 }
148
149 if (length != 8)
150 return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
151 "MTU option of invalid size, ignoring datagram.");
152
153 m = be32toh(*(uint32_t*) (p + 4));
154 if (m >= IPV6_MIN_MTU) /* ignore invalidly small MTUs */
155 rt->mtu = m;
156
157 has_mtu = true;
158 break;
159 }
160
161 case SD_NDISC_OPTION_ROUTE_INFORMATION:
162 if (length < 1*8 || length > 3*8)
163 return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
164 "Route information option of invalid size, ignoring datagram.");
165
166 if (p[2] > 128)
167 return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
168 "Bad route prefix length, ignoring datagram.");
169
170 break;
171
172 case SD_NDISC_OPTION_RDNSS:
173 if (length < 3*8 || (length % (2*8)) != 1*8)
174 return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG), "RDNSS option has invalid size.");
175
176 break;
177
178 case SD_NDISC_OPTION_FLAGS_EXTENSION:
179
180 if (has_flag_extension) {
181 log_ndisc(nd, "Flags extension option specified twice, ignoring.");
182 break;
183 }
184
185 if (length < 1*8)
186 return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
187 "Flags extension option has invalid size.");
188
189 /* Add in the additional flags bits */
190 rt->flags |=
191 ((uint64_t) p[2] << 8) |
192 ((uint64_t) p[3] << 16) |
193 ((uint64_t) p[4] << 24) |
194 ((uint64_t) p[5] << 32) |
195 ((uint64_t) p[6] << 40) |
196 ((uint64_t) p[7] << 48);
197
198 has_flag_extension = true;
199 break;
200
201 case SD_NDISC_OPTION_DNSSL:
202 if (length < 2*8)
203 return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
204 "DNSSL option has invalid size.");
205
206 break;
207 }
208
209 p += length, left -= length;
210 }
211
212 rt->rindex = sizeof(struct nd_router_advert);
213 return 0;
214 }
215
sd_ndisc_router_get_hop_limit(sd_ndisc_router * rt,uint8_t * ret)216 int sd_ndisc_router_get_hop_limit(sd_ndisc_router *rt, uint8_t *ret) {
217 assert_return(rt, -EINVAL);
218 assert_return(ret, -EINVAL);
219
220 *ret = rt->hop_limit;
221 return 0;
222 }
223
sd_ndisc_router_get_flags(sd_ndisc_router * rt,uint64_t * ret_flags)224 int sd_ndisc_router_get_flags(sd_ndisc_router *rt, uint64_t *ret_flags) {
225 assert_return(rt, -EINVAL);
226 assert_return(ret_flags, -EINVAL);
227
228 *ret_flags = rt->flags;
229 return 0;
230 }
231
sd_ndisc_router_get_lifetime(sd_ndisc_router * rt,uint16_t * ret_lifetime)232 int sd_ndisc_router_get_lifetime(sd_ndisc_router *rt, uint16_t *ret_lifetime) {
233 assert_return(rt, -EINVAL);
234 assert_return(ret_lifetime, -EINVAL);
235
236 *ret_lifetime = rt->lifetime;
237 return 0;
238 }
239
sd_ndisc_router_get_preference(sd_ndisc_router * rt,unsigned * ret)240 int sd_ndisc_router_get_preference(sd_ndisc_router *rt, unsigned *ret) {
241 assert_return(rt, -EINVAL);
242 assert_return(ret, -EINVAL);
243
244 *ret = rt->preference;
245 return 0;
246 }
247
sd_ndisc_router_get_mtu(sd_ndisc_router * rt,uint32_t * ret)248 int sd_ndisc_router_get_mtu(sd_ndisc_router *rt, uint32_t *ret) {
249 assert_return(rt, -EINVAL);
250 assert_return(ret, -EINVAL);
251
252 if (rt->mtu <= 0)
253 return -ENODATA;
254
255 *ret = rt->mtu;
256 return 0;
257 }
258
sd_ndisc_router_option_rewind(sd_ndisc_router * rt)259 int sd_ndisc_router_option_rewind(sd_ndisc_router *rt) {
260 assert_return(rt, -EINVAL);
261
262 assert(rt->raw_size >= sizeof(struct nd_router_advert));
263 rt->rindex = sizeof(struct nd_router_advert);
264
265 return rt->rindex < rt->raw_size;
266 }
267
sd_ndisc_router_option_next(sd_ndisc_router * rt)268 int sd_ndisc_router_option_next(sd_ndisc_router *rt) {
269 size_t length;
270
271 assert_return(rt, -EINVAL);
272
273 if (rt->rindex == rt->raw_size) /* EOF */
274 return -ESPIPE;
275
276 if (rt->rindex + 2 > rt->raw_size) /* Truncated message */
277 return -EBADMSG;
278
279 length = NDISC_ROUTER_OPTION_LENGTH(rt);
280 if (rt->rindex + length > rt->raw_size)
281 return -EBADMSG;
282
283 rt->rindex += length;
284 return rt->rindex < rt->raw_size;
285 }
286
sd_ndisc_router_option_get_type(sd_ndisc_router * rt,uint8_t * ret)287 int sd_ndisc_router_option_get_type(sd_ndisc_router *rt, uint8_t *ret) {
288 assert_return(rt, -EINVAL);
289 assert_return(ret, -EINVAL);
290
291 if (rt->rindex == rt->raw_size) /* EOF */
292 return -ESPIPE;
293
294 if (rt->rindex + 2 > rt->raw_size) /* Truncated message */
295 return -EBADMSG;
296
297 *ret = NDISC_ROUTER_OPTION_TYPE(rt);
298 return 0;
299 }
300
sd_ndisc_router_option_is_type(sd_ndisc_router * rt,uint8_t type)301 int sd_ndisc_router_option_is_type(sd_ndisc_router *rt, uint8_t type) {
302 uint8_t k;
303 int r;
304
305 assert_return(rt, -EINVAL);
306
307 r = sd_ndisc_router_option_get_type(rt, &k);
308 if (r < 0)
309 return r;
310
311 return type == k;
312 }
313
sd_ndisc_router_option_get_raw(sd_ndisc_router * rt,const void ** ret,size_t * size)314 int sd_ndisc_router_option_get_raw(sd_ndisc_router *rt, const void **ret, size_t *size) {
315 size_t length;
316
317 assert_return(rt, -EINVAL);
318 assert_return(ret, -EINVAL);
319 assert_return(size, -EINVAL);
320
321 /* Note that this returns the full option, including the option header */
322
323 if (rt->rindex + 2 > rt->raw_size)
324 return -EBADMSG;
325
326 length = NDISC_ROUTER_OPTION_LENGTH(rt);
327 if (rt->rindex + length > rt->raw_size)
328 return -EBADMSG;
329
330 *ret = (uint8_t*) NDISC_ROUTER_RAW(rt) + rt->rindex;
331 *size = length;
332
333 return 0;
334 }
335
get_prefix_info(sd_ndisc_router * rt,struct nd_opt_prefix_info ** ret)336 static int get_prefix_info(sd_ndisc_router *rt, struct nd_opt_prefix_info **ret) {
337 struct nd_opt_prefix_info *ri;
338 size_t length;
339 int r;
340
341 assert(rt);
342 assert(ret);
343
344 r = sd_ndisc_router_option_is_type(rt, SD_NDISC_OPTION_PREFIX_INFORMATION);
345 if (r < 0)
346 return r;
347 if (r == 0)
348 return -EMEDIUMTYPE;
349
350 length = NDISC_ROUTER_OPTION_LENGTH(rt);
351 if (length != sizeof(struct nd_opt_prefix_info))
352 return -EBADMSG;
353
354 ri = (struct nd_opt_prefix_info*) ((uint8_t*) NDISC_ROUTER_RAW(rt) + rt->rindex);
355 if (ri->nd_opt_pi_prefix_len > 128)
356 return -EBADMSG;
357
358 *ret = ri;
359 return 0;
360 }
361
sd_ndisc_router_prefix_get_valid_lifetime(sd_ndisc_router * rt,uint32_t * ret)362 int sd_ndisc_router_prefix_get_valid_lifetime(sd_ndisc_router *rt, uint32_t *ret) {
363 struct nd_opt_prefix_info *ri;
364 int r;
365
366 assert_return(rt, -EINVAL);
367 assert_return(ret, -EINVAL);
368
369 r = get_prefix_info(rt, &ri);
370 if (r < 0)
371 return r;
372
373 *ret = be32toh(ri->nd_opt_pi_valid_time);
374 return 0;
375 }
376
sd_ndisc_router_prefix_get_preferred_lifetime(sd_ndisc_router * rt,uint32_t * ret)377 int sd_ndisc_router_prefix_get_preferred_lifetime(sd_ndisc_router *rt, uint32_t *ret) {
378 struct nd_opt_prefix_info *pi;
379 int r;
380
381 assert_return(rt, -EINVAL);
382 assert_return(ret, -EINVAL);
383
384 r = get_prefix_info(rt, &pi);
385 if (r < 0)
386 return r;
387
388 *ret = be32toh(pi->nd_opt_pi_preferred_time);
389 return 0;
390 }
391
sd_ndisc_router_prefix_get_flags(sd_ndisc_router * rt,uint8_t * ret)392 int sd_ndisc_router_prefix_get_flags(sd_ndisc_router *rt, uint8_t *ret) {
393 struct nd_opt_prefix_info *pi;
394 uint8_t flags;
395 int r;
396
397 assert_return(rt, -EINVAL);
398 assert_return(ret, -EINVAL);
399
400 r = get_prefix_info(rt, &pi);
401 if (r < 0)
402 return r;
403
404 flags = pi->nd_opt_pi_flags_reserved;
405
406 if ((flags & ND_OPT_PI_FLAG_AUTO) && (pi->nd_opt_pi_prefix_len != 64)) {
407 log_ndisc(NULL, "Invalid prefix length, ignoring prefix for stateless autoconfiguration.");
408 flags &= ~ND_OPT_PI_FLAG_AUTO;
409 }
410
411 *ret = flags;
412 return 0;
413 }
414
sd_ndisc_router_prefix_get_address(sd_ndisc_router * rt,struct in6_addr * ret_addr)415 int sd_ndisc_router_prefix_get_address(sd_ndisc_router *rt, struct in6_addr *ret_addr) {
416 struct nd_opt_prefix_info *pi;
417 int r;
418
419 assert_return(rt, -EINVAL);
420 assert_return(ret_addr, -EINVAL);
421
422 r = get_prefix_info(rt, &pi);
423 if (r < 0)
424 return r;
425
426 *ret_addr = pi->nd_opt_pi_prefix;
427 return 0;
428 }
429
sd_ndisc_router_prefix_get_prefixlen(sd_ndisc_router * rt,unsigned * ret)430 int sd_ndisc_router_prefix_get_prefixlen(sd_ndisc_router *rt, unsigned *ret) {
431 struct nd_opt_prefix_info *pi;
432 int r;
433
434 assert_return(rt, -EINVAL);
435 assert_return(ret, -EINVAL);
436
437 r = get_prefix_info(rt, &pi);
438 if (r < 0)
439 return r;
440
441 if (pi->nd_opt_pi_prefix_len > 128)
442 return -EBADMSG;
443
444 *ret = pi->nd_opt_pi_prefix_len;
445 return 0;
446 }
447
get_route_info(sd_ndisc_router * rt,uint8_t ** ret)448 static int get_route_info(sd_ndisc_router *rt, uint8_t **ret) {
449 uint8_t *ri;
450 size_t length;
451 int r;
452
453 assert(rt);
454 assert(ret);
455
456 r = sd_ndisc_router_option_is_type(rt, SD_NDISC_OPTION_ROUTE_INFORMATION);
457 if (r < 0)
458 return r;
459 if (r == 0)
460 return -EMEDIUMTYPE;
461
462 length = NDISC_ROUTER_OPTION_LENGTH(rt);
463 if (length < 1*8 || length > 3*8)
464 return -EBADMSG;
465
466 ri = (uint8_t*) NDISC_ROUTER_RAW(rt) + rt->rindex;
467
468 if (ri[2] > 128)
469 return -EBADMSG;
470
471 *ret = ri;
472 return 0;
473 }
474
sd_ndisc_router_route_get_lifetime(sd_ndisc_router * rt,uint32_t * ret)475 int sd_ndisc_router_route_get_lifetime(sd_ndisc_router *rt, uint32_t *ret) {
476 uint8_t *ri;
477 int r;
478
479 assert_return(rt, -EINVAL);
480 assert_return(ret, -EINVAL);
481
482 r = get_route_info(rt, &ri);
483 if (r < 0)
484 return r;
485
486 *ret = be32toh(*(uint32_t*) (ri + 4));
487 return 0;
488 }
489
sd_ndisc_router_route_get_address(sd_ndisc_router * rt,struct in6_addr * ret_addr)490 int sd_ndisc_router_route_get_address(sd_ndisc_router *rt, struct in6_addr *ret_addr) {
491 uint8_t *ri;
492 int r;
493
494 assert_return(rt, -EINVAL);
495 assert_return(ret_addr, -EINVAL);
496
497 r = get_route_info(rt, &ri);
498 if (r < 0)
499 return r;
500
501 zero(*ret_addr);
502 memcpy(ret_addr, ri + 8, NDISC_ROUTER_OPTION_LENGTH(rt) - 8);
503
504 return 0;
505 }
506
sd_ndisc_router_route_get_prefixlen(sd_ndisc_router * rt,unsigned * ret)507 int sd_ndisc_router_route_get_prefixlen(sd_ndisc_router *rt, unsigned *ret) {
508 uint8_t *ri;
509 int r;
510
511 assert_return(rt, -EINVAL);
512 assert_return(ret, -EINVAL);
513
514 r = get_route_info(rt, &ri);
515 if (r < 0)
516 return r;
517
518 *ret = ri[2];
519 return 0;
520 }
521
sd_ndisc_router_route_get_preference(sd_ndisc_router * rt,unsigned * ret)522 int sd_ndisc_router_route_get_preference(sd_ndisc_router *rt, unsigned *ret) {
523 uint8_t *ri;
524 int r;
525
526 assert_return(rt, -EINVAL);
527 assert_return(ret, -EINVAL);
528
529 r = get_route_info(rt, &ri);
530 if (r < 0)
531 return r;
532
533 *ret = (ri[3] >> 3) & 3;
534 if (!IN_SET(*ret, SD_NDISC_PREFERENCE_LOW, SD_NDISC_PREFERENCE_HIGH))
535 *ret = SD_NDISC_PREFERENCE_MEDIUM;
536
537 return 0;
538 }
539
get_rdnss_info(sd_ndisc_router * rt,uint8_t ** ret)540 static int get_rdnss_info(sd_ndisc_router *rt, uint8_t **ret) {
541 size_t length;
542 int r;
543
544 assert(rt);
545 assert(ret);
546
547 r = sd_ndisc_router_option_is_type(rt, SD_NDISC_OPTION_RDNSS);
548 if (r < 0)
549 return r;
550 if (r == 0)
551 return -EMEDIUMTYPE;
552
553 length = NDISC_ROUTER_OPTION_LENGTH(rt);
554 if (length < 3*8 || (length % (2*8)) != 1*8)
555 return -EBADMSG;
556
557 *ret = (uint8_t*) NDISC_ROUTER_RAW(rt) + rt->rindex;
558 return 0;
559 }
560
sd_ndisc_router_rdnss_get_addresses(sd_ndisc_router * rt,const struct in6_addr ** ret)561 int sd_ndisc_router_rdnss_get_addresses(sd_ndisc_router *rt, const struct in6_addr **ret) {
562 uint8_t *ri;
563 int r;
564
565 assert_return(rt, -EINVAL);
566 assert_return(ret, -EINVAL);
567
568 r = get_rdnss_info(rt, &ri);
569 if (r < 0)
570 return r;
571
572 *ret = (const struct in6_addr*) (ri + 8);
573 return (NDISC_ROUTER_OPTION_LENGTH(rt) - 8) / 16;
574 }
575
sd_ndisc_router_rdnss_get_lifetime(sd_ndisc_router * rt,uint32_t * ret)576 int sd_ndisc_router_rdnss_get_lifetime(sd_ndisc_router *rt, uint32_t *ret) {
577 uint8_t *ri;
578 int r;
579
580 assert_return(rt, -EINVAL);
581 assert_return(ret, -EINVAL);
582
583 r = get_rdnss_info(rt, &ri);
584 if (r < 0)
585 return r;
586
587 *ret = be32toh(*(uint32_t*) (ri + 4));
588 return 0;
589 }
590
get_dnssl_info(sd_ndisc_router * rt,uint8_t ** ret)591 static int get_dnssl_info(sd_ndisc_router *rt, uint8_t **ret) {
592 size_t length;
593 int r;
594
595 assert(rt);
596 assert(ret);
597
598 r = sd_ndisc_router_option_is_type(rt, SD_NDISC_OPTION_DNSSL);
599 if (r < 0)
600 return r;
601 if (r == 0)
602 return -EMEDIUMTYPE;
603
604 length = NDISC_ROUTER_OPTION_LENGTH(rt);
605 if (length < 2*8)
606 return -EBADMSG;
607
608 *ret = (uint8_t*) NDISC_ROUTER_RAW(rt) + rt->rindex;
609 return 0;
610 }
611
sd_ndisc_router_dnssl_get_domains(sd_ndisc_router * rt,char *** ret)612 int sd_ndisc_router_dnssl_get_domains(sd_ndisc_router *rt, char ***ret) {
613 _cleanup_strv_free_ char **l = NULL;
614 _cleanup_free_ char *e = NULL;
615 size_t n = 0, left;
616 uint8_t *ri, *p;
617 bool first = true;
618 int r;
619 unsigned k = 0;
620
621 assert_return(rt, -EINVAL);
622 assert_return(ret, -EINVAL);
623
624 r = get_dnssl_info(rt, &ri);
625 if (r < 0)
626 return r;
627
628 p = ri + 8;
629 left = NDISC_ROUTER_OPTION_LENGTH(rt) - 8;
630
631 for (;;) {
632 if (left == 0) {
633
634 if (n > 0) /* Not properly NUL terminated */
635 return -EBADMSG;
636
637 break;
638 }
639
640 if (*p == 0) {
641 /* Found NUL termination */
642
643 if (n > 0) {
644 _cleanup_free_ char *normalized = NULL;
645
646 e[n] = 0;
647 r = dns_name_normalize(e, 0, &normalized);
648 if (r < 0)
649 return r;
650
651 /* Ignore the root domain name or "localhost" and friends */
652 if (!is_localhost(normalized) &&
653 !dns_name_is_root(normalized)) {
654
655 if (strv_push(&l, normalized) < 0)
656 return -ENOMEM;
657
658 normalized = NULL;
659 k++;
660 }
661 }
662
663 n = 0;
664 first = true;
665 p++, left--;
666 continue;
667 }
668
669 /* Check for compression (which is not allowed) */
670 if (*p > 63)
671 return -EBADMSG;
672
673 if (1U + *p + 1U > left)
674 return -EBADMSG;
675
676 if (!GREEDY_REALLOC(e, n + !first + DNS_LABEL_ESCAPED_MAX + 1U))
677 return -ENOMEM;
678
679 if (first)
680 first = false;
681 else
682 e[n++] = '.';
683
684 r = dns_label_escape((char*) p+1, *p, e + n, DNS_LABEL_ESCAPED_MAX);
685 if (r < 0)
686 return r;
687
688 n += r;
689
690 left -= 1 + *p;
691 p += 1 + *p;
692 }
693
694 if (strv_isempty(l)) {
695 *ret = NULL;
696 return 0;
697 }
698
699 *ret = TAKE_PTR(l);
700
701 return k;
702 }
703
sd_ndisc_router_dnssl_get_lifetime(sd_ndisc_router * rt,uint32_t * ret_sec)704 int sd_ndisc_router_dnssl_get_lifetime(sd_ndisc_router *rt, uint32_t *ret_sec) {
705 uint8_t *ri;
706 int r;
707
708 assert_return(rt, -EINVAL);
709 assert_return(ret_sec, -EINVAL);
710
711 r = get_dnssl_info(rt, &ri);
712 if (r < 0)
713 return r;
714
715 *ret_sec = be32toh(*(uint32_t*) (ri + 4));
716 return 0;
717 }
718