1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 Copyright © 2014 Intel Corporation. All rights reserved.
6 #include <netinet/icmp6.h>
10 #include "alloc-util.h"
11 #include "ndisc-internal.h"
12 #include "ndisc-router-internal.h"
14 #include "string-table.h"
15 #include "string-util.h"
17 static sd_ndisc_router
* ndisc_router_free(sd_ndisc_router
*rt
) {
21 icmp6_packet_unref(rt
->packet
);
22 set_free(rt
->options
);
26 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_ndisc_router
, sd_ndisc_router
, ndisc_router_free
);
28 sd_ndisc_router
* ndisc_router_new(ICMP6Packet
*packet
) {
33 rt
= new(sd_ndisc_router
, 1);
37 *rt
= (sd_ndisc_router
) {
39 .packet
= icmp6_packet_ref(packet
),
40 .iterator
= ITERATOR_FIRST
,
46 int sd_ndisc_router_set_sender_address(sd_ndisc_router
*rt
, const struct in6_addr
*addr
) {
47 assert_return(rt
, -EINVAL
);
49 return icmp6_packet_set_sender_address(rt
->packet
, addr
);
52 int sd_ndisc_router_get_sender_address(sd_ndisc_router
*rt
, struct in6_addr
*ret
) {
53 assert_return(rt
, -EINVAL
);
55 return icmp6_packet_get_sender_address(rt
->packet
, ret
);
58 int sd_ndisc_router_get_timestamp(sd_ndisc_router
*rt
, clockid_t clock
, uint64_t *ret
) {
59 assert_return(rt
, -EINVAL
);
60 assert_return(ret
, -EINVAL
);
62 return icmp6_packet_get_timestamp(rt
->packet
, clock
, ret
);
65 #define DEFINE_GET_TIMESTAMP(name) \
66 int sd_ndisc_router_##name##_timestamp( \
67 sd_ndisc_router *rt, \
74 assert_return(rt, -EINVAL); \
75 assert_return(ret, -EINVAL); \
77 r = sd_ndisc_router_##name(rt, &s); \
81 r = sd_ndisc_router_get_timestamp(rt, clock, &t); \
85 *ret = time_span_to_stamp(s, t); \
89 DEFINE_GET_TIMESTAMP(get_lifetime
);
90 DEFINE_GET_TIMESTAMP(prefix_get_valid_lifetime
);
91 DEFINE_GET_TIMESTAMP(prefix_get_preferred_lifetime
);
92 DEFINE_GET_TIMESTAMP(route_get_lifetime
);
93 DEFINE_GET_TIMESTAMP(rdnss_get_lifetime
);
94 DEFINE_GET_TIMESTAMP(dnssl_get_lifetime
);
95 DEFINE_GET_TIMESTAMP(prefix64_get_lifetime
);
96 DEFINE_GET_TIMESTAMP(encrypted_dns_get_lifetime
);
98 int ndisc_router_parse(sd_ndisc
*nd
, sd_ndisc_router
*rt
) {
99 const struct nd_router_advert
*a
;
105 if (rt
->packet
->raw_size
< sizeof(struct nd_router_advert
))
106 return log_ndisc_errno(nd
, SYNTHETIC_ERRNO(EBADMSG
),
107 "Too small to be a router advertisement, ignoring.");
109 a
= (const struct nd_router_advert
*) rt
->packet
->raw_packet
;
110 assert(a
->nd_ra_type
== ND_ROUTER_ADVERT
);
111 assert(a
->nd_ra_code
== 0);
113 rt
->hop_limit
= a
->nd_ra_curhoplimit
;
114 rt
->flags
= a
->nd_ra_flags_reserved
; /* the first 8 bits */
115 rt
->lifetime_usec
= be16_sec_to_usec(a
->nd_ra_router_lifetime
, /* max_as_infinity = */ false);
116 rt
->reachable_time_usec
= be32_msec_to_usec(a
->nd_ra_reachable
, /* max_as_infinity = */ false);
117 rt
->retransmission_time_usec
= be32_msec_to_usec(a
->nd_ra_retransmit
, /* max_as_infinity = */ false);
119 /* RFC 4191 section 2.2
120 * Prf (Default Router Preference)
121 * 2-bit signed integer. Indicates whether to prefer this router over other default routers. If the
122 * Router Lifetime is zero, the preference value MUST be set to (00) by the sender and MUST be
123 * ignored by the receiver. If the Reserved (10) value is received, the receiver MUST treat the value
124 * as if it were (00). */
125 rt
->preference
= (rt
->flags
>> 3) & 3;
126 if (rt
->preference
== SD_NDISC_PREFERENCE_RESERVED
)
127 rt
->preference
= SD_NDISC_PREFERENCE_MEDIUM
;
129 r
= ndisc_parse_options(rt
->packet
, &rt
->options
);
131 return log_ndisc_errno(nd
, r
, "Failed to parse NDisc options in router advertisement message, ignoring: %m");
136 int sd_ndisc_router_get_hop_limit(sd_ndisc_router
*rt
, uint8_t *ret
) {
137 assert_return(rt
, -EINVAL
);
138 assert_return(ret
, -EINVAL
);
140 *ret
= rt
->hop_limit
;
144 int sd_ndisc_router_get_reachable_time(sd_ndisc_router
*rt
, uint64_t *ret
) {
145 assert_return(rt
, -EINVAL
);
146 assert_return(ret
, -EINVAL
);
148 *ret
= rt
->reachable_time_usec
;
152 int sd_ndisc_router_get_retransmission_time(sd_ndisc_router
*rt
, uint64_t *ret
) {
153 assert_return(rt
, -EINVAL
);
154 assert_return(ret
, -EINVAL
);
156 *ret
= rt
->retransmission_time_usec
;
160 int sd_ndisc_router_get_flags(sd_ndisc_router
*rt
, uint64_t *ret
) {
161 assert_return(rt
, -EINVAL
);
162 assert_return(ret
, -EINVAL
);
164 sd_ndisc_option
*p
= ndisc_option_get_by_type(rt
->options
, SD_NDISC_OPTION_FLAGS_EXTENSION
);
166 *ret
= rt
->flags
| (p
? p
->extended_flags
: 0);
170 int ndisc_router_flags_to_string(uint64_t flags
, char **ret
) {
171 _cleanup_free_
char *s
= NULL
;
175 if (FLAGS_SET(flags
, ND_RA_FLAG_MANAGED
) &&
176 !strextend_with_separator(&s
, ", ", "managed"))
179 if (FLAGS_SET(flags
, ND_RA_FLAG_OTHER
) &&
180 !strextend_with_separator(&s
, ", ", "other"))
183 if (FLAGS_SET(flags
, ND_RA_FLAG_HOME_AGENT
) &&
184 !strextend_with_separator(&s
, ", ", "home-agent"))
191 int sd_ndisc_router_get_lifetime(sd_ndisc_router
*rt
, uint64_t *ret
) {
192 assert_return(rt
, -EINVAL
);
195 *ret
= rt
->lifetime_usec
;
197 return rt
->lifetime_usec
> 0; /* Indicate if the router is still valid or not. */
200 int sd_ndisc_router_get_preference(sd_ndisc_router
*rt
, uint8_t *ret
) {
201 assert_return(rt
, -EINVAL
);
202 assert_return(ret
, -EINVAL
);
204 *ret
= rt
->preference
;
208 static const char* const ndisc_router_preference_table
[] = {
209 [SD_NDISC_PREFERENCE_LOW
] = "low",
210 [SD_NDISC_PREFERENCE_MEDIUM
] = "medium",
211 [SD_NDISC_PREFERENCE_HIGH
] = "high",
212 [SD_NDISC_PREFERENCE_RESERVED
] = "reserved",
215 DEFINE_STRING_TABLE_LOOKUP_TO_STRING(ndisc_router_preference
, int);
217 int sd_ndisc_router_get_sender_mac(sd_ndisc_router
*rt
, struct ether_addr
*ret
) {
218 assert_return(rt
, -EINVAL
);
220 return ndisc_option_get_mac(rt
->options
, SD_NDISC_OPTION_SOURCE_LL_ADDRESS
, ret
);
223 int sd_ndisc_router_get_mtu(sd_ndisc_router
*rt
, uint32_t *ret
) {
224 assert_return(rt
, -EINVAL
);
225 assert_return(ret
, -EINVAL
);
227 sd_ndisc_option
*p
= ndisc_option_get_by_type(rt
->options
, SD_NDISC_OPTION_MTU
);
235 int sd_ndisc_router_get_captive_portal(sd_ndisc_router
*rt
, const char **ret
) {
236 assert_return(rt
, -EINVAL
);
237 assert_return(ret
, -EINVAL
);
239 sd_ndisc_option
*p
= ndisc_option_get_by_type(rt
->options
, SD_NDISC_OPTION_CAPTIVE_PORTAL
);
243 *ret
= p
->captive_portal
;
247 int sd_ndisc_router_option_rewind(sd_ndisc_router
*rt
) {
248 assert_return(rt
, -EINVAL
);
250 rt
->iterator
= ITERATOR_FIRST
;
251 return sd_ndisc_router_option_next(rt
);
254 int sd_ndisc_router_option_next(sd_ndisc_router
*rt
) {
255 assert_return(rt
, -EINVAL
);
257 return set_iterate(rt
->options
, &rt
->iterator
, (void**) &rt
->current_option
);
260 int sd_ndisc_router_option_get_type(sd_ndisc_router
*rt
, uint8_t *ret
) {
261 assert_return(rt
, -EINVAL
);
262 assert_return(ret
, -EINVAL
);
264 if (!rt
->current_option
)
267 *ret
= rt
->current_option
->type
;
271 int sd_ndisc_router_option_is_type(sd_ndisc_router
*rt
, uint8_t type
) {
275 assert_return(rt
, -EINVAL
);
277 r
= sd_ndisc_router_option_get_type(rt
, &t
);
284 int sd_ndisc_router_option_get_raw(sd_ndisc_router
*rt
, const uint8_t **ret
, size_t *ret_size
) {
285 assert_return(rt
, -EINVAL
);
287 if (!rt
->current_option
)
290 return ndisc_option_parse(rt
->packet
, rt
->current_option
->offset
, NULL
, ret_size
, ret
);
293 #define DEFINE_GETTER(name, type, element, element_type) \
294 int sd_ndisc_router_##name##_get_##element( \
295 sd_ndisc_router *rt, \
296 element_type *ret) { \
300 assert_return(rt, -EINVAL); \
301 assert_return(ret, -EINVAL); \
303 r = sd_ndisc_router_option_is_type(rt, type); \
307 return -EMEDIUMTYPE; \
309 *ret = rt->current_option->name.element; \
313 DEFINE_GETTER(prefix
, SD_NDISC_OPTION_PREFIX_INFORMATION
, flags
, uint8_t);
314 DEFINE_GETTER(prefix
, SD_NDISC_OPTION_PREFIX_INFORMATION
, prefixlen
, uint8_t);
315 DEFINE_GETTER(prefix
, SD_NDISC_OPTION_PREFIX_INFORMATION
, address
, struct in6_addr
);
316 DEFINE_GETTER(prefix
, SD_NDISC_OPTION_PREFIX_INFORMATION
, valid_lifetime
, uint64_t);
317 DEFINE_GETTER(prefix
, SD_NDISC_OPTION_PREFIX_INFORMATION
, preferred_lifetime
, uint64_t);
319 DEFINE_GETTER(route
, SD_NDISC_OPTION_ROUTE_INFORMATION
, preference
, uint8_t);
320 DEFINE_GETTER(route
, SD_NDISC_OPTION_ROUTE_INFORMATION
, prefixlen
, uint8_t);
321 DEFINE_GETTER(route
, SD_NDISC_OPTION_ROUTE_INFORMATION
, address
, struct in6_addr
);
322 DEFINE_GETTER(route
, SD_NDISC_OPTION_ROUTE_INFORMATION
, lifetime
, uint64_t);
324 DEFINE_GETTER(rdnss
, SD_NDISC_OPTION_RDNSS
, lifetime
, uint64_t);
326 int sd_ndisc_router_rdnss_get_addresses(sd_ndisc_router
*rt
, const struct in6_addr
**ret
) {
329 assert_return(rt
, -EINVAL
);
330 assert_return(ret
, -EINVAL
);
332 r
= sd_ndisc_router_option_is_type(rt
, SD_NDISC_OPTION_RDNSS
);
338 *ret
= rt
->current_option
->rdnss
.addresses
;
339 return (int) rt
->current_option
->rdnss
.n_addresses
;
342 DEFINE_GETTER(dnssl
, SD_NDISC_OPTION_DNSSL
, domains
, char**);
343 DEFINE_GETTER(dnssl
, SD_NDISC_OPTION_DNSSL
, lifetime
, uint64_t);
345 DEFINE_GETTER(prefix64
, SD_NDISC_OPTION_PREF64
, prefixlen
, uint8_t);
346 DEFINE_GETTER(prefix64
, SD_NDISC_OPTION_PREF64
, prefix
, struct in6_addr
);
347 DEFINE_GETTER(prefix64
, SD_NDISC_OPTION_PREF64
, lifetime
, uint64_t);
349 DEFINE_GETTER(encrypted_dns
, SD_NDISC_OPTION_ENCRYPTED_DNS
, lifetime
, uint64_t);
350 DEFINE_GETTER(encrypted_dns
, SD_NDISC_OPTION_ENCRYPTED_DNS
, resolver
, sd_dns_resolver
*);