Bug Summary

File:build-scan/../src/network/networkd-ndisc.c
Warning:line 456, column 17
Potential leak of memory pointed to by 'x'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name networkd-ndisc.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/network/libnetworkd-core.a.p -I src/network -I ../src/network -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/network/networkd-ndisc.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2/***
3 Copyright © 2014 Intel Corporation. All rights reserved.
4***/
5
6#include <netinet/icmp6.h>
7#include <arpa/inet.h>
8
9#include "sd-ndisc.h"
10
11#include "networkd-ndisc.h"
12#include "networkd-route.h"
13
14#define NDISC_DNSSL_MAX64U 64U
15#define NDISC_RDNSS_MAX64U 64U
16#define NDISC_PREFIX_LFT_MIN7200U 7200U
17
18static int ndisc_netlink_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
19 _cleanup_(link_unrefp)__attribute__((cleanup(link_unrefp))) Link *link = userdata;
20 int r;
21
22 assert(link)do { if ((__builtin_expect(!!(!(link)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("link"), "../src/network/networkd-ndisc.c"
, 22, __PRETTY_FUNCTION__); } while (0)
;
23 assert(link->ndisc_messages > 0)do { if ((__builtin_expect(!!(!(link->ndisc_messages > 0
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("link->ndisc_messages > 0"
), "../src/network/networkd-ndisc.c", 23, __PRETTY_FUNCTION__
); } while (0)
;
24
25 link->ndisc_messages--;
26
27 r = sd_netlink_message_get_errno(m);
28 if (r < 0 && r != -EEXIST17)
29 log_link_error_errno(link, r, "Could not set NDisc route or address: %m")({ const Link *_l = (link); _l ? log_object_internal(3, r, "../src/network/networkd-ndisc.c"
, 29, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Could not set NDisc route or address: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/network/networkd-ndisc.c"
, 29, __func__, "Could not set NDisc route or address: %m"); }
)
;
30
31 if (link->ndisc_messages == 0) {
32 link->ndisc_configured = true1;
33 link_check_ready(link);
34 }
35
36 return 1;
37}
38
39static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
40 _cleanup_(route_freep)__attribute__((cleanup(route_freep))) Route *route = NULL((void*)0);
41 struct in6_addr gateway;
42 uint16_t lifetime;
43 unsigned preference;
44 uint32_t mtu;
45 usec_t time_now;
46 int r;
47 Address *address;
48 Iterator i;
49
50 assert(link)do { if ((__builtin_expect(!!(!(link)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("link"), "../src/network/networkd-ndisc.c"
, 50, __PRETTY_FUNCTION__); } while (0)
;
51 assert(rt)do { if ((__builtin_expect(!!(!(rt)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rt"), "../src/network/networkd-ndisc.c"
, 51, __PRETTY_FUNCTION__); } while (0)
;
52
53 r = sd_ndisc_router_get_lifetime(rt, &lifetime);
54 if (r < 0) {
55 log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 55, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get gateway address from RA: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 55, __func__, "Failed to get gateway address from RA: %m");
})
;
56 return;
57 }
58 if (lifetime == 0) /* not a default router */
59 return;
60
61 r = sd_ndisc_router_get_address(rt, &gateway);
62 if (r < 0) {
63 log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 63, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get gateway address from RA: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 63, __func__, "Failed to get gateway address from RA: %m");
})
;
64 return;
65 }
66
67 SET_FOREACH(address, link->addresses, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); set_iterate((link->addresses), &
(i), (void**)&(address)); )
{
68 if (!memcmp(&gateway, &address->in_addr.in6,
69 sizeof(address->in_addr.in6))) {
70 char buffer[INET6_ADDRSTRLEN46];
71
72 log_link_debug(link, "No NDisc route added, gateway %s matches local address",({ const Link *_l = (link); _l ? log_object_internal(7, 0, "../src/network/networkd-ndisc.c"
, 75, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "No NDisc route added, gateway %s matches local address"
, inet_ntop(10, &address->in_addr.in6, buffer, sizeof(
buffer))) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10
| ((7))), 0, "../src/network/networkd-ndisc.c", 75, __func__
, "No NDisc route added, gateway %s matches local address", inet_ntop
(10, &address->in_addr.in6, buffer, sizeof(buffer))); }
)
73 inet_ntop(AF_INET6,({ const Link *_l = (link); _l ? log_object_internal(7, 0, "../src/network/networkd-ndisc.c"
, 75, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "No NDisc route added, gateway %s matches local address"
, inet_ntop(10, &address->in_addr.in6, buffer, sizeof(
buffer))) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10
| ((7))), 0, "../src/network/networkd-ndisc.c", 75, __func__
, "No NDisc route added, gateway %s matches local address", inet_ntop
(10, &address->in_addr.in6, buffer, sizeof(buffer))); }
)
74 &address->in_addr.in6,({ const Link *_l = (link); _l ? log_object_internal(7, 0, "../src/network/networkd-ndisc.c"
, 75, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "No NDisc route added, gateway %s matches local address"
, inet_ntop(10, &address->in_addr.in6, buffer, sizeof(
buffer))) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10
| ((7))), 0, "../src/network/networkd-ndisc.c", 75, __func__
, "No NDisc route added, gateway %s matches local address", inet_ntop
(10, &address->in_addr.in6, buffer, sizeof(buffer))); }
)
75 buffer, sizeof(buffer)))({ const Link *_l = (link); _l ? log_object_internal(7, 0, "../src/network/networkd-ndisc.c"
, 75, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "No NDisc route added, gateway %s matches local address"
, inet_ntop(10, &address->in_addr.in6, buffer, sizeof(
buffer))) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10
| ((7))), 0, "../src/network/networkd-ndisc.c", 75, __func__
, "No NDisc route added, gateway %s matches local address", inet_ntop
(10, &address->in_addr.in6, buffer, sizeof(buffer))); }
)
;
76 return;
77 }
78 }
79
80 SET_FOREACH(address, link->addresses_foreign, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); set_iterate((link->addresses_foreign
), &(i), (void**)&(address)); )
{
81 if (!memcmp(&gateway, &address->in_addr.in6,
82 sizeof(address->in_addr.in6))) {
83 char buffer[INET6_ADDRSTRLEN46];
84
85 log_link_debug(link, "No NDisc route added, gateway %s matches local address",({ const Link *_l = (link); _l ? log_object_internal(7, 0, "../src/network/networkd-ndisc.c"
, 88, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "No NDisc route added, gateway %s matches local address"
, inet_ntop(10, &address->in_addr.in6, buffer, sizeof(
buffer))) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10
| ((7))), 0, "../src/network/networkd-ndisc.c", 88, __func__
, "No NDisc route added, gateway %s matches local address", inet_ntop
(10, &address->in_addr.in6, buffer, sizeof(buffer))); }
)
86 inet_ntop(AF_INET6,({ const Link *_l = (link); _l ? log_object_internal(7, 0, "../src/network/networkd-ndisc.c"
, 88, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "No NDisc route added, gateway %s matches local address"
, inet_ntop(10, &address->in_addr.in6, buffer, sizeof(
buffer))) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10
| ((7))), 0, "../src/network/networkd-ndisc.c", 88, __func__
, "No NDisc route added, gateway %s matches local address", inet_ntop
(10, &address->in_addr.in6, buffer, sizeof(buffer))); }
)
87 &address->in_addr.in6,({ const Link *_l = (link); _l ? log_object_internal(7, 0, "../src/network/networkd-ndisc.c"
, 88, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "No NDisc route added, gateway %s matches local address"
, inet_ntop(10, &address->in_addr.in6, buffer, sizeof(
buffer))) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10
| ((7))), 0, "../src/network/networkd-ndisc.c", 88, __func__
, "No NDisc route added, gateway %s matches local address", inet_ntop
(10, &address->in_addr.in6, buffer, sizeof(buffer))); }
)
88 buffer, sizeof(buffer)))({ const Link *_l = (link); _l ? log_object_internal(7, 0, "../src/network/networkd-ndisc.c"
, 88, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "No NDisc route added, gateway %s matches local address"
, inet_ntop(10, &address->in_addr.in6, buffer, sizeof(
buffer))) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10
| ((7))), 0, "../src/network/networkd-ndisc.c", 88, __func__
, "No NDisc route added, gateway %s matches local address", inet_ntop
(10, &address->in_addr.in6, buffer, sizeof(buffer))); }
)
;
89 return;
90 }
91 }
92
93 r = sd_ndisc_router_get_preference(rt, &preference);
94 if (r < 0) {
95 log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 95, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get default router preference from RA: %m") :
log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4)))
, r, "../src/network/networkd-ndisc.c", 95, __func__, "Failed to get default router preference from RA: %m"
); })
;
96 return;
97 }
98
99 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
100 if (r < 0) {
101 log_link_warning_errno(link, r, "Failed to get RA timestamp: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 101, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get RA timestamp: %m") : log_internal_realm(
((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 101, __func__, "Failed to get RA timestamp: %m"); })
;
102 return;
103 }
104
105 r = sd_ndisc_router_get_mtu(rt, &mtu);
106 if (r == -ENODATA61)
107 mtu = 0;
108 else if (r < 0) {
109 log_link_warning_errno(link, r, "Failed to get default router MTU from RA: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 109, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get default router MTU from RA: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 109, __func__, "Failed to get default router MTU from RA: %m"
); })
;
110 return;
111 }
112
113 r = route_new(&route);
114 if (r < 0) {
115 log_link_error_errno(link, r, "Could not allocate route: %m")({ const Link *_l = (link); _l ? log_object_internal(3, r, "../src/network/networkd-ndisc.c"
, 115, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Could not allocate route: %m") : log_internal_realm(((
LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/network/networkd-ndisc.c"
, 115, __func__, "Could not allocate route: %m"); })
;
116 return;
117 }
118
119 route->family = AF_INET610;
120 route->table = link->network->ipv6_accept_ra_route_table;
121 route->priority = link->network->dhcp_route_metric;
122 route->protocol = RTPROT_RA9;
123 route->pref = preference;
124 route->gw.in6 = gateway;
125 route->lifetime = time_now + lifetime * USEC_PER_SEC((usec_t) 1000000ULL);
126 route->mtu = mtu;
127
128 r = route_configure(route, link, ndisc_netlink_handler);
129 if (r < 0) {
130 log_link_warning_errno(link, r, "Could not set default route: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 130, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Could not set default route: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 130, __func__, "Could not set default route: %m"); })
;
131 link_enter_failed(link);
132 return;
133 }
134
135 link->ndisc_messages++;
136}
137
138static void ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) {
139 _cleanup_(address_freep)__attribute__((cleanup(address_freep))) Address *address = NULL((void*)0);
140 Address *existing_address;
141 uint32_t lifetime_valid, lifetime_preferred, lifetime_remaining;
142 usec_t time_now;
143 unsigned prefixlen;
144 int r;
145
146 assert(link)do { if ((__builtin_expect(!!(!(link)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("link"), "../src/network/networkd-ndisc.c"
, 146, __PRETTY_FUNCTION__); } while (0)
;
147 assert(rt)do { if ((__builtin_expect(!!(!(rt)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rt"), "../src/network/networkd-ndisc.c"
, 147, __PRETTY_FUNCTION__); } while (0)
;
148
149 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
150 if (r < 0) {
151 log_link_warning_errno(link, r, "Failed to get RA timestamp: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 151, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get RA timestamp: %m") : log_internal_realm(
((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 151, __func__, "Failed to get RA timestamp: %m"); })
;
152 return;
153 }
154
155 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
156 if (r < 0) {
157 log_link_error_errno(link, r, "Failed to get prefix length: %m")({ const Link *_l = (link); _l ? log_object_internal(3, r, "../src/network/networkd-ndisc.c"
, 157, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get prefix length: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/network/networkd-ndisc.c"
, 157, __func__, "Failed to get prefix length: %m"); })
;
158 return;
159 }
160
161 r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid);
162 if (r < 0) {
163 log_link_error_errno(link, r, "Failed to get prefix valid lifetime: %m")({ const Link *_l = (link); _l ? log_object_internal(3, r, "../src/network/networkd-ndisc.c"
, 163, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get prefix valid lifetime: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/network/networkd-ndisc.c"
, 163, __func__, "Failed to get prefix valid lifetime: %m"); }
)
;
164 return;
165 }
166
167 r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred);
168 if (r < 0) {
169 log_link_error_errno(link, r, "Failed to get prefix preferred lifetime: %m")({ const Link *_l = (link); _l ? log_object_internal(3, r, "../src/network/networkd-ndisc.c"
, 169, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get prefix preferred lifetime: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/network/networkd-ndisc.c"
, 169, __func__, "Failed to get prefix preferred lifetime: %m"
); })
;
170 return;
171 }
172
173 /* The preferred lifetime is never greater than the valid lifetime */
174 if (lifetime_preferred > lifetime_valid)
175 return;
176
177 r = address_new(&address);
178 if (r < 0) {
179 log_link_error_errno(link, r, "Could not allocate address: %m")({ const Link *_l = (link); _l ? log_object_internal(3, r, "../src/network/networkd-ndisc.c"
, 179, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Could not allocate address: %m") : log_internal_realm(
((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/network/networkd-ndisc.c"
, 179, __func__, "Could not allocate address: %m"); })
;
180 return;
181 }
182
183 address->family = AF_INET610;
184 r = sd_ndisc_router_prefix_get_address(rt, &address->in_addr.in6);
185 if (r < 0) {
186 log_link_error_errno(link, r, "Failed to get prefix address: %m")({ const Link *_l = (link); _l ? log_object_internal(3, r, "../src/network/networkd-ndisc.c"
, 186, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get prefix address: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/network/networkd-ndisc.c"
, 186, __func__, "Failed to get prefix address: %m"); })
;
187 return;
188 }
189
190 if (in_addr_is_null(AF_INET610, (const union in_addr_union *) &link->network->ipv6_token) == 0)
191 memcpy(((char *)&address->in_addr.in6) + 8, ((char *)&link->network->ipv6_token) + 8, 8);
192 else {
193 /* see RFC4291 section 2.5.1 */
194 address->in_addr.in6.s6_addr__in6_u.__u6_addr8[8] = link->mac.ether_addr_octet[0];
195 address->in_addr.in6.s6_addr__in6_u.__u6_addr8[8] ^= 1 << 1;
196 address->in_addr.in6.s6_addr__in6_u.__u6_addr8[9] = link->mac.ether_addr_octet[1];
197 address->in_addr.in6.s6_addr__in6_u.__u6_addr8[10] = link->mac.ether_addr_octet[2];
198 address->in_addr.in6.s6_addr__in6_u.__u6_addr8[11] = 0xff;
199 address->in_addr.in6.s6_addr__in6_u.__u6_addr8[12] = 0xfe;
200 address->in_addr.in6.s6_addr__in6_u.__u6_addr8[13] = link->mac.ether_addr_octet[3];
201 address->in_addr.in6.s6_addr__in6_u.__u6_addr8[14] = link->mac.ether_addr_octet[4];
202 address->in_addr.in6.s6_addr__in6_u.__u6_addr8[15] = link->mac.ether_addr_octet[5];
203 }
204 address->prefixlen = prefixlen;
205 address->flags = IFA_F_NOPREFIXROUTE0x200|IFA_F_MANAGETEMPADDR0x100;
206 address->cinfo.ifa_prefered = lifetime_preferred;
207
208 /* see RFC4862 section 5.5.3.e */
209 r = address_get(link, address->family, &address->in_addr, address->prefixlen, &existing_address);
210 if (r > 0) {
211 lifetime_remaining = existing_address->cinfo.tstamp / 100 + existing_address->cinfo.ifa_valid - time_now / USEC_PER_SEC((usec_t) 1000000ULL);
212 if (lifetime_valid > NDISC_PREFIX_LFT_MIN7200U || lifetime_valid > lifetime_remaining)
213 address->cinfo.ifa_valid = lifetime_valid;
214 else if (lifetime_remaining <= NDISC_PREFIX_LFT_MIN7200U)
215 address->cinfo.ifa_valid = lifetime_remaining;
216 else
217 address->cinfo.ifa_valid = NDISC_PREFIX_LFT_MIN7200U;
218 } else if (lifetime_valid > 0)
219 address->cinfo.ifa_valid = lifetime_valid;
220 else
221 return; /* see RFC4862 section 5.5.3.d */
222
223 if (address->cinfo.ifa_valid == 0)
224 return;
225
226 r = address_configure(address, link, ndisc_netlink_handler, true1);
227 if (r < 0) {
228 log_link_warning_errno(link, r, "Could not set SLAAC address: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 228, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Could not set SLAAC address: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 228, __func__, "Could not set SLAAC address: %m"); })
;
229 link_enter_failed(link);
230 return;
231 }
232
233 link->ndisc_messages++;
234}
235
236static void ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
237 _cleanup_(route_freep)__attribute__((cleanup(route_freep))) Route *route = NULL((void*)0);
238 usec_t time_now;
239 uint32_t lifetime;
240 unsigned prefixlen;
241 int r;
242
243 assert(link)do { if ((__builtin_expect(!!(!(link)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("link"), "../src/network/networkd-ndisc.c"
, 243, __PRETTY_FUNCTION__); } while (0)
;
244 assert(rt)do { if ((__builtin_expect(!!(!(rt)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rt"), "../src/network/networkd-ndisc.c"
, 244, __PRETTY_FUNCTION__); } while (0)
;
245
246 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
247 if (r < 0) {
248 log_link_warning_errno(link, r, "Failed to get RA timestamp: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 248, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get RA timestamp: %m") : log_internal_realm(
((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 248, __func__, "Failed to get RA timestamp: %m"); })
;
249 return;
250 }
251
252 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
253 if (r < 0) {
254 log_link_error_errno(link, r, "Failed to get prefix length: %m")({ const Link *_l = (link); _l ? log_object_internal(3, r, "../src/network/networkd-ndisc.c"
, 254, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get prefix length: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/network/networkd-ndisc.c"
, 254, __func__, "Failed to get prefix length: %m"); })
;
255 return;
256 }
257
258 r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime);
259 if (r < 0) {
260 log_link_error_errno(link, r, "Failed to get prefix lifetime: %m")({ const Link *_l = (link); _l ? log_object_internal(3, r, "../src/network/networkd-ndisc.c"
, 260, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get prefix lifetime: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/network/networkd-ndisc.c"
, 260, __func__, "Failed to get prefix lifetime: %m"); })
;
261 return;
262 }
263
264 r = route_new(&route);
265 if (r < 0) {
266 log_link_error_errno(link, r, "Could not allocate route: %m")({ const Link *_l = (link); _l ? log_object_internal(3, r, "../src/network/networkd-ndisc.c"
, 266, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Could not allocate route: %m") : log_internal_realm(((
LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/network/networkd-ndisc.c"
, 266, __func__, "Could not allocate route: %m"); })
;
267 return;
268 }
269
270 route->family = AF_INET610;
271 route->table = link->network->ipv6_accept_ra_route_table;
272 route->priority = link->network->dhcp_route_metric;
273 route->protocol = RTPROT_RA9;
274 route->flags = RTM_F_PREFIX0x800;
275 route->dst_prefixlen = prefixlen;
276 route->lifetime = time_now + lifetime * USEC_PER_SEC((usec_t) 1000000ULL);
277
278 r = sd_ndisc_router_prefix_get_address(rt, &route->dst.in6);
279 if (r < 0) {
280 log_link_error_errno(link, r, "Failed to get prefix address: %m")({ const Link *_l = (link); _l ? log_object_internal(3, r, "../src/network/networkd-ndisc.c"
, 280, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get prefix address: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/network/networkd-ndisc.c"
, 280, __func__, "Failed to get prefix address: %m"); })
;
281 return;
282 }
283
284 r = route_configure(route, link, ndisc_netlink_handler);
285 if (r < 0) {
286 log_link_warning_errno(link, r, "Could not set prefix route: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 286, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Could not set prefix route: %m") : log_internal_realm(
((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 286, __func__, "Could not set prefix route: %m"); })
;
287 link_enter_failed(link);
288 return;
289 }
290
291 link->ndisc_messages++;
292}
293
294static void ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
295 _cleanup_(route_freep)__attribute__((cleanup(route_freep))) Route *route = NULL((void*)0);
296 struct in6_addr gateway;
297 uint32_t lifetime;
298 unsigned preference, prefixlen;
299 usec_t time_now;
300 int r;
301
302 assert(link)do { if ((__builtin_expect(!!(!(link)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("link"), "../src/network/networkd-ndisc.c"
, 302, __PRETTY_FUNCTION__); } while (0)
;
303
304 r = sd_ndisc_router_route_get_lifetime(rt, &lifetime);
305 if (r < 0) {
306 log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 306, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get gateway address from RA: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 306, __func__, "Failed to get gateway address from RA: %m")
; })
;
307 return;
308 }
309 if (lifetime == 0)
310 return;
311
312 r = sd_ndisc_router_get_address(rt, &gateway);
313 if (r < 0) {
314 log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 314, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get gateway address from RA: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 314, __func__, "Failed to get gateway address from RA: %m")
; })
;
315 return;
316 }
317
318 r = sd_ndisc_router_route_get_prefixlen(rt, &prefixlen);
319 if (r < 0) {
320 log_link_warning_errno(link, r, "Failed to get route prefix length: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 320, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get route prefix length: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 320, __func__, "Failed to get route prefix length: %m"); })
;
321 return;
322 }
323
324 r = sd_ndisc_router_route_get_preference(rt, &preference);
325 if (r < 0) {
326 log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 326, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get default router preference from RA: %m") :
log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4)))
, r, "../src/network/networkd-ndisc.c", 326, __func__, "Failed to get default router preference from RA: %m"
); })
;
327 return;
328 }
329
330 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
331 if (r < 0) {
332 log_link_warning_errno(link, r, "Failed to get RA timestamp: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 332, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get RA timestamp: %m") : log_internal_realm(
((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 332, __func__, "Failed to get RA timestamp: %m"); })
;
333 return;
334 }
335
336 r = route_new(&route);
337 if (r < 0) {
338 log_link_error_errno(link, r, "Could not allocate route: %m")({ const Link *_l = (link); _l ? log_object_internal(3, r, "../src/network/networkd-ndisc.c"
, 338, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Could not allocate route: %m") : log_internal_realm(((
LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/network/networkd-ndisc.c"
, 338, __func__, "Could not allocate route: %m"); })
;
339 return;
340 }
341
342 route->family = AF_INET610;
343 route->table = link->network->ipv6_accept_ra_route_table;
344 route->protocol = RTPROT_RA9;
345 route->pref = preference;
346 route->gw.in6 = gateway;
347 route->dst_prefixlen = prefixlen;
348 route->lifetime = time_now + lifetime * USEC_PER_SEC((usec_t) 1000000ULL);
349
350 r = sd_ndisc_router_route_get_address(rt, &route->dst.in6);
351 if (r < 0) {
352 log_link_error_errno(link, r, "Failed to get route address: %m")({ const Link *_l = (link); _l ? log_object_internal(3, r, "../src/network/networkd-ndisc.c"
, 352, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get route address: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/network/networkd-ndisc.c"
, 352, __func__, "Failed to get route address: %m"); })
;
353 return;
354 }
355
356 r = route_configure(route, link, ndisc_netlink_handler);
357 if (r < 0) {
358 log_link_warning_errno(link, r, "Could not set additional route: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 358, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Could not set additional route: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 358, __func__, "Could not set additional route: %m"); })
;
359 link_enter_failed(link);
360 return;
361 }
362
363 link->ndisc_messages++;
364}
365
366static void ndisc_rdnss_hash_func(const void *p, struct siphash *state) {
367 const NDiscRDNSS *x = p;
368
369 siphash24_compress(&x->address, sizeof(x->address), state);
370}
371
372static int ndisc_rdnss_compare_func(const void *_a, const void *_b) {
373 const NDiscRDNSS *a = _a, *b = _b;
374
375 return memcmp(&a->address, &b->address, sizeof(a->address));
376}
377
378static const struct hash_ops ndisc_rdnss_hash_ops = {
379 .hash = ndisc_rdnss_hash_func,
380 .compare = ndisc_rdnss_compare_func
381};
382
383static void ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
384 uint32_t lifetime;
385 const struct in6_addr *a;
386 usec_t time_now;
387 int i, n, r;
388
389 assert(link)do { if ((__builtin_expect(!!(!(link)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("link"), "../src/network/networkd-ndisc.c"
, 389, __PRETTY_FUNCTION__); } while (0)
;
40
Taking false branch
41
Loop condition is false. Exiting loop
390 assert(rt)do { if ((__builtin_expect(!!(!(rt)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rt"), "../src/network/networkd-ndisc.c"
, 390, __PRETTY_FUNCTION__); } while (0)
;
42
Taking false branch
43
Loop condition is false. Exiting loop
391
392 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
393 if (r < 0) {
44
Assuming 'r' is >= 0
45
Taking false branch
394 log_link_warning_errno(link, r, "Failed to get RA timestamp: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 394, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get RA timestamp: %m") : log_internal_realm(
((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 394, __func__, "Failed to get RA timestamp: %m"); })
;
395 return;
396 }
397
398 r = sd_ndisc_router_rdnss_get_lifetime(rt, &lifetime);
399 if (r < 0) {
46
Assuming 'r' is >= 0
47
Taking false branch
400 log_link_warning_errno(link, r, "Failed to get RDNSS lifetime: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 400, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get RDNSS lifetime: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 400, __func__, "Failed to get RDNSS lifetime: %m"); })
;
401 return;
402 }
403
404 n = sd_ndisc_router_rdnss_get_addresses(rt, &a);
405 if (n < 0) {
48
Assuming 'n' is >= 0
49
Taking false branch
406 log_link_warning_errno(link, n, "Failed to get RDNSS addresses: %m")({ const Link *_l = (link); _l ? log_object_internal(4, n, "../src/network/networkd-ndisc.c"
, 406, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get RDNSS addresses: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), n, "../src/network/networkd-ndisc.c"
, 406, __func__, "Failed to get RDNSS addresses: %m"); })
;
407 return;
408 }
409
410 for (i = 0; i < n; i++) {
50
Assuming 'i' is < 'n'
51
Loop condition is true. Entering loop body
411 NDiscRDNSS d = {
412 .address = a[i]
413 }, *x;
414
415 if (lifetime == 0) {
52
Assuming 'lifetime' is not equal to 0
53
Taking false branch
416 (void) set_remove(link->ndisc_rdnss, &d);
417 link_dirty(link);
418 continue;
419 }
420
421 x = set_get(link->ndisc_rdnss, &d);
422 if (x) {
54
Assuming 'x' is null
55
Taking false branch
423 x->valid_until = time_now + lifetime * USEC_PER_SEC((usec_t) 1000000ULL);
424 continue;
425 }
426
427 ndisc_vacuum(link);
428
429 if (set_size(link->ndisc_rdnss) >= NDISC_RDNSS_MAX64U) {
56
Assuming the condition is false
57
Taking false branch
430 log_link_warning(link, "Too many RDNSS records per link, ignoring.")({ const Link *_l = (link); _l ? log_object_internal(4, 0, "../src/network/networkd-ndisc.c"
, 430, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Too many RDNSS records per link, ignoring.") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/network/networkd-ndisc.c"
, 430, __func__, "Too many RDNSS records per link, ignoring."
); })
;
431 continue;
432 }
433
434 r = set_ensure_allocated(&link->ndisc_rdnss, &ndisc_rdnss_hash_ops)internal_set_ensure_allocated(&link->ndisc_rdnss, &
ndisc_rdnss_hash_ops )
;
435 if (r < 0) {
58
Assuming 'r' is >= 0
59
Taking false branch
436 log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/networkd-ndisc.c"
, 436, __func__)
;
437 return;
438 }
439
440 x = new0(NDiscRDNSS, 1)((NDiscRDNSS*) calloc((1), sizeof(NDiscRDNSS)));
60
Memory is allocated
441 if (!x) {
61
Assuming 'x' is non-null
62
Taking false branch
442 log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/networkd-ndisc.c"
, 442, __func__)
;
443 return;
444 }
445
446 x->address = a[i];
447 x->valid_until = time_now + lifetime * USEC_PER_SEC((usec_t) 1000000ULL);
448
449 r = set_put(link->ndisc_rdnss, x);
450 if (r < 0) {
63
Assuming 'r' is >= 0
64
Taking false branch
451 free(x);
452 log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/networkd-ndisc.c"
, 452, __func__)
;
453 return;
454 }
455
456 assert(r > 0)do { if ((__builtin_expect(!!(!(r > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("r > 0"), "../src/network/networkd-ndisc.c"
, 456, __PRETTY_FUNCTION__); } while (0)
;
65
Potential leak of memory pointed to by 'x'
457 link_dirty(link);
458 }
459}
460
461static void ndisc_dnssl_hash_func(const void *p, struct siphash *state) {
462 const NDiscDNSSL *x = p;
463
464 siphash24_compress(NDISC_DNSSL_DOMAIN(x), strlen(NDISC_DNSSL_DOMAIN(x)), state);
465}
466
467static int ndisc_dnssl_compare_func(const void *_a, const void *_b) {
468 const NDiscDNSSL *a = _a, *b = _b;
469
470 return strcmp(NDISC_DNSSL_DOMAIN(a), NDISC_DNSSL_DOMAIN(b));
471}
472
473static const struct hash_ops ndisc_dnssl_hash_ops = {
474 .hash = ndisc_dnssl_hash_func,
475 .compare = ndisc_dnssl_compare_func
476};
477
478static void ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
479 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **l = NULL((void*)0);
480 uint32_t lifetime;
481 usec_t time_now;
482 char **i;
483 int r;
484
485 assert(link)do { if ((__builtin_expect(!!(!(link)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("link"), "../src/network/networkd-ndisc.c"
, 485, __PRETTY_FUNCTION__); } while (0)
;
486 assert(rt)do { if ((__builtin_expect(!!(!(rt)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rt"), "../src/network/networkd-ndisc.c"
, 486, __PRETTY_FUNCTION__); } while (0)
;
487
488 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
489 if (r < 0) {
490 log_link_warning_errno(link, r, "Failed to get RA timestamp: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 490, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get RA timestamp: %m") : log_internal_realm(
((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 490, __func__, "Failed to get RA timestamp: %m"); })
;
491 return;
492 }
493
494 r = sd_ndisc_router_dnssl_get_lifetime(rt, &lifetime);
495 if (r < 0) {
496 log_link_warning_errno(link, r, "Failed to get RDNSS lifetime: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 496, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get RDNSS lifetime: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 496, __func__, "Failed to get RDNSS lifetime: %m"); })
;
497 return;
498 }
499
500 r = sd_ndisc_router_dnssl_get_domains(rt, &l);
501 if (r < 0) {
502 log_link_warning_errno(link, r, "Failed to get RDNSS addresses: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 502, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get RDNSS addresses: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 502, __func__, "Failed to get RDNSS addresses: %m"); })
;
503 return;
504 }
505
506 STRV_FOREACH(i, l)for ((i) = (l); (i) && *(i); (i)++) {
507 _cleanup_free___attribute__((cleanup(freep))) NDiscDNSSL *s;
508 NDiscDNSSL *x;
509
510 s = malloc0(ALIGN(sizeof(NDiscDNSSL)) + strlen(*i) + 1)(calloc(1, ((((sizeof(NDiscDNSSL)) + 7) & ~7) + strlen(*i
) + 1)))
;
511 if (!s) {
512 log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/networkd-ndisc.c"
, 512, __func__)
;
513 return;
514 }
515
516 strcpy(NDISC_DNSSL_DOMAIN(s), *i);
517
518 if (lifetime == 0) {
519 (void) set_remove(link->ndisc_dnssl, s);
520 link_dirty(link);
521 continue;
522 }
523
524 x = set_get(link->ndisc_dnssl, s);
525 if (x) {
526 x->valid_until = time_now + lifetime * USEC_PER_SEC((usec_t) 1000000ULL);
527 continue;
528 }
529
530 ndisc_vacuum(link);
531
532 if (set_size(link->ndisc_dnssl) >= NDISC_DNSSL_MAX64U) {
533 log_link_warning(link, "Too many DNSSL records per link, ignoring.")({ const Link *_l = (link); _l ? log_object_internal(4, 0, "../src/network/networkd-ndisc.c"
, 533, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Too many DNSSL records per link, ignoring.") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/network/networkd-ndisc.c"
, 533, __func__, "Too many DNSSL records per link, ignoring."
); })
;
534 continue;
535 }
536
537 r = set_ensure_allocated(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops)internal_set_ensure_allocated(&link->ndisc_dnssl, &
ndisc_dnssl_hash_ops )
;
538 if (r < 0) {
539 log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/networkd-ndisc.c"
, 539, __func__)
;
540 return;
541 }
542
543 s->valid_until = time_now + lifetime * USEC_PER_SEC((usec_t) 1000000ULL);
544
545 r = set_put(link->ndisc_dnssl, s);
546 if (r < 0) {
547 log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/networkd-ndisc.c"
, 547, __func__)
;
548 return;
549 }
550
551 s = NULL((void*)0);
552 assert(r > 0)do { if ((__builtin_expect(!!(!(r > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("r > 0"), "../src/network/networkd-ndisc.c"
, 552, __PRETTY_FUNCTION__); } while (0)
;
553 link_dirty(link);
554 }
555}
556
557static void ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
558 int r;
559
560 assert(link)do { if ((__builtin_expect(!!(!(link)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("link"), "../src/network/networkd-ndisc.c"
, 560, __PRETTY_FUNCTION__); } while (0)
;
25
Taking false branch
26
Loop condition is false. Exiting loop
561 assert(rt)do { if ((__builtin_expect(!!(!(rt)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rt"), "../src/network/networkd-ndisc.c"
, 561, __PRETTY_FUNCTION__); } while (0)
;
27
Taking false branch
28
Loop condition is false. Exiting loop
562
563 r = sd_ndisc_router_option_rewind(rt);
564 for (;;) {
29
Loop condition is true. Entering loop body
565 uint8_t type;
566
567 if (r < 0) {
30
Assuming 'r' is >= 0
31
Taking false branch
568 log_link_warning_errno(link, r, "Failed to iterate through options: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 568, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to iterate through options: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 568, __func__, "Failed to iterate through options: %m"); })
;
569 return;
570 }
571 if (r == 0) /* EOF */
32
Assuming 'r' is not equal to 0
33
Taking false branch
572 break;
573
574 r = sd_ndisc_router_option_get_type(rt, &type);
575 if (r < 0) {
34
Assuming 'r' is >= 0
35
Taking false branch
576 log_link_warning_errno(link, r, "Failed to get RA option type: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 576, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get RA option type: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 576, __func__, "Failed to get RA option type: %m"); })
;
577 return;
578 }
579
580 switch (type) {
36
Control jumps to 'case SD_NDISC_OPTION_RDNSS:' at line 603
581
582 case SD_NDISC_OPTION_PREFIX_INFORMATION: {
583 uint8_t flags;
584
585 r = sd_ndisc_router_prefix_get_flags(rt, &flags);
586 if (r < 0) {
587 log_link_warning_errno(link, r, "Failed to get RA prefix flags: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 587, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get RA prefix flags: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/network/networkd-ndisc.c"
, 587, __func__, "Failed to get RA prefix flags: %m"); })
;
588 return;
589 }
590
591 if (flags & ND_OPT_PI_FLAG_ONLINK0x80)
592 ndisc_router_process_onlink_prefix(link, rt);
593 if (flags & ND_OPT_PI_FLAG_AUTO0x40)
594 ndisc_router_process_autonomous_prefix(link, rt);
595
596 break;
597 }
598
599 case SD_NDISC_OPTION_ROUTE_INFORMATION:
600 ndisc_router_process_route(link, rt);
601 break;
602
603 case SD_NDISC_OPTION_RDNSS:
604 if (link->network->ipv6_accept_ra_use_dns)
37
Assuming field 'ipv6_accept_ra_use_dns' is true
38
Taking true branch
605 ndisc_router_process_rdnss(link, rt);
39
Calling 'ndisc_router_process_rdnss'
606 break;
607
608 case SD_NDISC_OPTION_DNSSL:
609 if (link->network->ipv6_accept_ra_use_dns)
610 ndisc_router_process_dnssl(link, rt);
611 break;
612 }
613
614 r = sd_ndisc_router_option_next(rt);
615 }
616}
617
618static void ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
619 uint64_t flags;
620 int r;
621
622 assert(link)do { if ((__builtin_expect(!!(!(link)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("link"), "../src/network/networkd-ndisc.c"
, 622, __PRETTY_FUNCTION__); } while (0)
;
9
Taking false branch
10
Loop condition is false. Exiting loop
623 assert(link->network)do { if ((__builtin_expect(!!(!(link->network)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("link->network"), "../src/network/networkd-ndisc.c"
, 623, __PRETTY_FUNCTION__); } while (0)
;
11
Assuming field 'network' is non-null
12
Taking false branch
13
Loop condition is false. Exiting loop
624 assert(link->manager)do { if ((__builtin_expect(!!(!(link->manager)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("link->manager"), "../src/network/networkd-ndisc.c"
, 624, __PRETTY_FUNCTION__); } while (0)
;
14
Assuming field 'manager' is non-null
15
Taking false branch
16
Loop condition is false. Exiting loop
625 assert(rt)do { if ((__builtin_expect(!!(!(rt)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rt"), "../src/network/networkd-ndisc.c"
, 625, __PRETTY_FUNCTION__); } while (0)
;
17
Assuming 'rt' is non-null
18
Taking false branch
19
Loop condition is false. Exiting loop
626
627 r = sd_ndisc_router_get_flags(rt, &flags);
628 if (r < 0) {
20
Assuming 'r' is >= 0
21
Taking false branch
629 log_link_warning_errno(link, r, "Failed to get RA flags: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 629, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Failed to get RA flags: %m") : log_internal_realm(((LOG_REALM_SYSTEMD
) << 10 | ((4))), r, "../src/network/networkd-ndisc.c",
629, __func__, "Failed to get RA flags: %m"); })
;
630 return;
631 }
632
633 if (flags & (ND_RA_FLAG_MANAGED0x80 | ND_RA_FLAG_OTHER0x40)) {
22
Assuming the condition is false
23
Taking false branch
634 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
635 r = dhcp6_request_address(link, !(flags & ND_RA_FLAG_MANAGED0x80));
636 if (r < 0 && r != -EBUSY16)
637 log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m")({ const Link *_l = (link); _l ? log_object_internal(4, r, "../src/network/networkd-ndisc.c"
, 637, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Could not acquire DHCPv6 lease on NDisc request: %m") :
log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4)))
, r, "../src/network/networkd-ndisc.c", 637, __func__, "Could not acquire DHCPv6 lease on NDisc request: %m"
); })
;
638 else
639 log_link_debug(link, "Acquiring DHCPv6 lease on NDisc request")({ const Link *_l = (link); _l ? log_object_internal(7, 0, "../src/network/networkd-ndisc.c"
, 639, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "Acquiring DHCPv6 lease on NDisc request") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/network/networkd-ndisc.c"
, 639, __func__, "Acquiring DHCPv6 lease on NDisc request"); }
)
;
640 }
641
642 ndisc_router_process_default(link, rt);
643 ndisc_router_process_options(link, rt);
24
Calling 'ndisc_router_process_options'
644}
645
646static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata) {
647 Link *link = userdata;
648
649 assert(link)do { if ((__builtin_expect(!!(!(link)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("link"), "../src/network/networkd-ndisc.c"
, 649, __PRETTY_FUNCTION__); } while (0)
;
1
Assuming 'link' is non-null
2
Taking false branch
3
Loop condition is false. Exiting loop
650
651 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){LINK_STATE_FAILED, LINK_STATE_LINGER})/sizeof
(int)]; switch(link->state) { case LINK_STATE_FAILED: case
LINK_STATE_LINGER: _found = 1; break; default: break; } _found
; })
)
4
Control jumps to the 'default' case at line 651
5
Execution continues on line 651
6
Taking false branch
652 return;
653
654 switch (event) {
7
Control jumps to 'case SD_NDISC_EVENT_ROUTER:' at line 656
655
656 case SD_NDISC_EVENT_ROUTER:
657 ndisc_router_handler(link, rt);
8
Calling 'ndisc_router_handler'
658 break;
659
660 case SD_NDISC_EVENT_TIMEOUT:
661 link->ndisc_configured = true1;
662 link_check_ready(link);
663
664 break;
665 default:
666 log_link_warning(link, "IPv6 Neighbor Discovery unknown event: %d", event)({ const Link *_l = (link); _l ? log_object_internal(4, 0, "../src/network/networkd-ndisc.c"
, 666, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void
*)0), "IPv6 Neighbor Discovery unknown event: %d", event) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/network/networkd-ndisc.c"
, 666, __func__, "IPv6 Neighbor Discovery unknown event: %d",
event); })
;
667 }
668}
669
670int ndisc_configure(Link *link) {
671 int r;
672
673 assert(link)do { if ((__builtin_expect(!!(!(link)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("link"), "../src/network/networkd-ndisc.c"
, 673, __PRETTY_FUNCTION__); } while (0)
;
674
675 r = sd_ndisc_new(&link->ndisc);
676 if (r < 0)
677 return r;
678
679 r = sd_ndisc_attach_event(link->ndisc, NULL((void*)0), 0);
680 if (r < 0)
681 return r;
682
683 r = sd_ndisc_set_mac(link->ndisc, &link->mac);
684 if (r < 0)
685 return r;
686
687 r = sd_ndisc_set_ifindex(link->ndisc, link->ifindex);
688 if (r < 0)
689 return r;
690
691 r = sd_ndisc_set_callback(link->ndisc, ndisc_handler, link);
692 if (r < 0)
693 return r;
694
695 return 0;
696}
697
698void ndisc_vacuum(Link *link) {
699 NDiscRDNSS *r;
700 NDiscDNSSL *d;
701 Iterator i;
702 usec_t time_now;
703
704 assert(link)do { if ((__builtin_expect(!!(!(link)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("link"), "../src/network/networkd-ndisc.c"
, 704, __PRETTY_FUNCTION__); } while (0)
;
705
706 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
707
708 time_now = now(clock_boottime_or_monotonic());
709
710 SET_FOREACH(r, link->ndisc_rdnss, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); set_iterate((link->ndisc_rdnss),
&(i), (void**)&(r)); )
711 if (r->valid_until < time_now) {
712 free(set_remove(link->ndisc_rdnss, r));
713 link_dirty(link);
714 }
715
716 SET_FOREACH(d, link->ndisc_dnssl, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); set_iterate((link->ndisc_dnssl),
&(i), (void**)&(d)); )
717 if (d->valid_until < time_now) {
718 free(set_remove(link->ndisc_dnssl, d));
719 link_dirty(link);
720 }
721}
722
723void ndisc_flush(Link *link) {
724 assert(link)do { if ((__builtin_expect(!!(!(link)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("link"), "../src/network/networkd-ndisc.c"
, 724, __PRETTY_FUNCTION__); } while (0)
;
725
726 /* Removes all RDNSS and DNSSL entries, without exception */
727
728 link->ndisc_rdnss = set_free_free(link->ndisc_rdnss);
729 link->ndisc_dnssl = set_free_free(link->ndisc_dnssl);
730}