File: | build-scan/../src/network/networkd-ndisc.c |
Warning: | line 519, column 25 Potential leak of memory pointed to by 's' |
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 | #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 | ||||
18 | static 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 | ||||
39 | static 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 | ||||
138 | static 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 | ||||
236 | static 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 | ||||
294 | static 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 | ||||
366 | static 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 | ||||
372 | static 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 | ||||
378 | static const struct hash_ops ndisc_rdnss_hash_ops = { | |||
379 | .hash = ndisc_rdnss_hash_func, | |||
380 | .compare = ndisc_rdnss_compare_func | |||
381 | }; | |||
382 | ||||
383 | static 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); | |||
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); | |||
391 | ||||
392 | r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); | |||
393 | if (r < 0) { | |||
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) { | |||
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) { | |||
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++) { | |||
411 | NDiscRDNSS d = { | |||
412 | .address = a[i] | |||
413 | }, *x; | |||
414 | ||||
415 | if (lifetime == 0) { | |||
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) { | |||
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) { | |||
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) { | |||
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))); | |||
441 | if (!x) { | |||
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) { | |||
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); | |||
457 | link_dirty(link); | |||
458 | } | |||
459 | } | |||
460 | ||||
461 | static 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 | ||||
467 | static 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 | ||||
473 | static const struct hash_ops ndisc_dnssl_hash_ops = { | |||
474 | .hash = ndisc_dnssl_hash_func, | |||
475 | .compare = ndisc_dnssl_compare_func | |||
476 | }; | |||
477 | ||||
478 | static 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 | ||||
557 | static 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); | |||
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); | |||
562 | ||||
563 | r = sd_ndisc_router_option_rewind(rt); | |||
564 | for (;;) { | |||
565 | uint8_t type; | |||
566 | ||||
567 | if (r < 0) { | |||
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 */ | |||
572 | break; | |||
573 | ||||
574 | r = sd_ndisc_router_option_get_type(rt, &type); | |||
575 | if (r < 0) { | |||
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) { | |||
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) | |||
605 | ndisc_router_process_rdnss(link, rt); | |||
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 | ||||
618 | static 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); | |||
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); | |||
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); | |||
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); | |||
626 | ||||
627 | r = sd_ndisc_router_get_flags(rt, &flags); | |||
628 | if (r < 0) { | |||
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)) { | |||
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); | |||
644 | } | |||
645 | ||||
646 | static 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); | |||
| ||||
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 ; })) | |||
652 | return; | |||
653 | ||||
654 | switch (event) { | |||
655 | ||||
656 | case SD_NDISC_EVENT_ROUTER: | |||
657 | ndisc_router_handler(link, rt); | |||
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 | ||||
670 | int 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 | ||||
698 | void 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 | ||||
723 | void 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 | } |