| 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 | } |