]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-radv.c
Merge pull request #7569 from keszybz/doc-reverse-settings
[thirdparty/systemd.git] / src / network / networkd-radv.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright (C) 2017 Intel Corporation. All rights reserved.
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <netinet/icmp6.h>
22 #include <arpa/inet.h>
23
24 #include "networkd-address.h"
25 #include "networkd-manager.h"
26 #include "networkd-radv.h"
27 #include "sd-radv.h"
28
29 static int radv_get_ip6dns(Network *network, struct in6_addr **dns,
30 size_t *n_dns) {
31 _cleanup_free_ struct in6_addr *addresses = NULL;
32 size_t i, n_addresses = 0, n_allocated = 0;
33
34 assert(network);
35 assert(dns);
36 assert(n_dns);
37
38 for (i = 0; i < network->n_dns; i++) {
39 union in_addr_union *addr;
40
41 if (network->dns[i].family != AF_INET6)
42 continue;
43
44 addr = &network->dns[i].address;
45
46 if (in_addr_is_null(AF_INET6, addr) ||
47 in_addr_is_link_local(AF_INET6, addr) ||
48 in_addr_is_localhost(AF_INET6, addr))
49 continue;
50
51 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
52 return -ENOMEM;
53
54 addresses[n_addresses++] = addr->in6;
55 }
56
57 if (addresses) {
58 *dns = addresses;
59 addresses = NULL;
60
61 *n_dns = n_addresses;
62 }
63
64 return n_addresses;
65 }
66
67 static int radv_set_dns(Link *link, Link *uplink) {
68 _cleanup_free_ struct in6_addr *dns = NULL;
69 size_t n_dns;
70 usec_t lifetime_usec;
71 int r;
72
73 if (!link->network->router_emit_dns)
74 return 0;
75
76 if (link->network->router_dns) {
77 dns = newdup(struct in6_addr, link->network->router_dns,
78 link->network->n_router_dns);
79 if (dns == NULL)
80 return -ENOMEM;
81
82 n_dns = link->network->n_router_dns;
83 lifetime_usec = link->network->router_dns_lifetime_usec;
84
85 goto set_dns;
86 }
87
88 lifetime_usec = SD_RADV_DEFAULT_DNS_LIFETIME_USEC;
89
90 r = radv_get_ip6dns(link->network, &dns, &n_dns);
91 if (r > 0)
92 goto set_dns;
93
94 if (uplink) {
95 if (uplink->network == NULL) {
96 log_link_debug(uplink, "Cannot fetch DNS servers as uplink interface is not managed by us");
97 return 0;
98 }
99
100 r = radv_get_ip6dns(uplink->network, &dns, &n_dns);
101 if (r > 0)
102 goto set_dns;
103 }
104
105 return 0;
106
107 set_dns:
108 return sd_radv_set_rdnss(link->radv,
109 DIV_ROUND_UP(lifetime_usec, USEC_PER_SEC),
110 dns, n_dns);
111 }
112
113 static int radv_set_domains(Link *link, Link *uplink) {
114 char **search_domains;
115 usec_t lifetime_usec;
116
117 if (!link->network->router_emit_domains)
118 return 0;
119
120 search_domains = link->network->router_search_domains;
121 lifetime_usec = link->network->router_dns_lifetime_usec;
122
123 if (search_domains)
124 goto set_domains;
125
126 lifetime_usec = SD_RADV_DEFAULT_DNS_LIFETIME_USEC;
127
128 search_domains = link->network->search_domains;
129 if (search_domains)
130 goto set_domains;
131
132 if (uplink) {
133 if (uplink->network == NULL) {
134 log_link_debug(uplink, "Cannot fetch DNS search domains as uplink interface is not managed by us");
135 return 0;
136 }
137
138 search_domains = uplink->network->search_domains;
139 if (search_domains)
140 goto set_domains;
141 }
142
143 return 0;
144
145 set_domains:
146 return sd_radv_set_dnssl(link->radv,
147 DIV_ROUND_UP(lifetime_usec, USEC_PER_SEC),
148 search_domains);
149
150 }
151
152 int radv_emit_dns(Link *link) {
153 Link *uplink;
154 int r;
155
156 uplink = manager_find_uplink(link->manager, link);
157
158 r = radv_set_dns(link, uplink);
159 if (r < 0)
160 log_link_warning_errno(link, r, "Could not set RA DNS: %m");
161
162 r = radv_set_domains(link, uplink);
163 if (r < 0)
164 log_link_warning_errno(link, r, "Could not set RA Domains: %m");
165
166 return 0;
167 }
168
169 int radv_configure(Link *link) {
170 int r;
171 Prefix *p;
172
173 assert(link);
174 assert(link->network);
175
176 r = sd_radv_new(&link->radv);
177 if (r < 0)
178 return r;
179
180 r = sd_radv_attach_event(link->radv, NULL, 0);
181 if (r < 0)
182 return r;
183
184 r = sd_radv_set_mac(link->radv, &link->mac);
185 if (r < 0)
186 return r;
187
188 r = sd_radv_set_ifindex(link->radv, link->ifindex);
189 if (r < 0)
190 return r;
191
192 r = sd_radv_set_managed_information(link->radv, link->network->router_managed);
193 if (r < 0)
194 return r;
195
196 r = sd_radv_set_other_information(link->radv, link->network->router_other_information);
197 if (r < 0)
198 return r;
199
200 /* a value of 0xffffffff represents infinity, 0x0 means this host is
201 not a router */
202 r = sd_radv_set_router_lifetime(link->radv,
203 DIV_ROUND_UP(link->network->router_lifetime_usec, USEC_PER_SEC));
204 if (r < 0)
205 return r;
206
207 if (link->network->router_lifetime_usec > 0) {
208 r = sd_radv_set_preference(link->radv,
209 link->network->router_preference);
210 if (r < 0)
211 return r;
212 }
213
214 LIST_FOREACH(prefixes, p, link->network->static_prefixes) {
215 r = sd_radv_add_prefix(link->radv, p->radv_prefix);
216 if (r != -EEXIST && r < 0)
217 return r;
218 }
219
220 return radv_emit_dns(link);
221 }