1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright (C) 2017 Intel Corporation. All rights reserved.
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.
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.
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/>.
21 #include <netinet/icmp6.h>
22 #include <arpa/inet.h>
24 #include "networkd-address.h"
25 #include "networkd-manager.h"
26 #include "networkd-radv.h"
29 static int radv_get_ip6dns(Network
*network
, struct in6_addr
**dns
,
31 _cleanup_free_
struct in6_addr
*addresses
= NULL
;
32 size_t i
, n_addresses
= 0, n_allocated
= 0;
38 for (i
= 0; i
< network
->n_dns
; i
++) {
39 union in_addr_union
*addr
;
41 if (network
->dns
[i
].family
!= AF_INET6
)
44 addr
= &network
->dns
[i
].address
;
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
))
51 if (!GREEDY_REALLOC(addresses
, n_allocated
, n_addresses
+ 1))
54 addresses
[n_addresses
++] = addr
->in6
;
67 static int radv_set_dns(Link
*link
, Link
*uplink
) {
68 _cleanup_free_
struct in6_addr
*dns
= NULL
;
73 if (!link
->network
->router_emit_dns
)
76 if (link
->network
->router_dns
) {
77 dns
= newdup(struct in6_addr
, link
->network
->router_dns
,
78 link
->network
->n_router_dns
);
82 n_dns
= link
->network
->n_router_dns
;
83 lifetime_usec
= link
->network
->router_dns_lifetime_usec
;
88 lifetime_usec
= SD_RADV_DEFAULT_DNS_LIFETIME_USEC
;
90 r
= radv_get_ip6dns(link
->network
, &dns
, &n_dns
);
95 if (uplink
->network
== NULL
) {
96 log_link_debug(uplink
, "Cannot fetch DNS servers as uplink interface is not managed by us");
100 r
= radv_get_ip6dns(uplink
->network
, &dns
, &n_dns
);
108 return sd_radv_set_rdnss(link
->radv
,
109 DIV_ROUND_UP(lifetime_usec
, USEC_PER_SEC
),
113 static int radv_set_domains(Link
*link
, Link
*uplink
) {
114 char **search_domains
;
115 usec_t lifetime_usec
;
117 if (!link
->network
->router_emit_domains
)
120 search_domains
= link
->network
->router_search_domains
;
121 lifetime_usec
= link
->network
->router_dns_lifetime_usec
;
126 lifetime_usec
= SD_RADV_DEFAULT_DNS_LIFETIME_USEC
;
128 search_domains
= link
->network
->search_domains
;
133 if (uplink
->network
== NULL
) {
134 log_link_debug(uplink
, "Cannot fetch DNS search domains as uplink interface is not managed by us");
138 search_domains
= uplink
->network
->search_domains
;
146 return sd_radv_set_dnssl(link
->radv
,
147 DIV_ROUND_UP(lifetime_usec
, USEC_PER_SEC
),
152 int radv_emit_dns(Link
*link
) {
156 uplink
= manager_find_uplink(link
->manager
, link
);
158 r
= radv_set_dns(link
, uplink
);
160 log_link_warning_errno(link
, r
, "Could not set RA DNS: %m");
162 r
= radv_set_domains(link
, uplink
);
164 log_link_warning_errno(link
, r
, "Could not set RA Domains: %m");
169 int radv_configure(Link
*link
) {
174 assert(link
->network
);
176 r
= sd_radv_new(&link
->radv
);
180 r
= sd_radv_attach_event(link
->radv
, NULL
, 0);
184 r
= sd_radv_set_mac(link
->radv
, &link
->mac
);
188 r
= sd_radv_set_ifindex(link
->radv
, link
->ifindex
);
192 r
= sd_radv_set_managed_information(link
->radv
, link
->network
->router_managed
);
196 r
= sd_radv_set_other_information(link
->radv
, link
->network
->router_other_information
);
200 /* a value of 0xffffffff represents infinity, 0x0 means this host is
202 r
= sd_radv_set_router_lifetime(link
->radv
,
203 DIV_ROUND_UP(link
->network
->router_lifetime_usec
, USEC_PER_SEC
));
207 if (link
->network
->router_lifetime_usec
> 0) {
208 r
= sd_radv_set_preference(link
->radv
,
209 link
->network
->router_preference
);
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)
220 return radv_emit_dns(link
);