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