2 This file is part of systemd.
4 Copyright (C) 2017 Intel Corporation. All rights reserved.
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include <netinet/icmp6.h>
21 #include <arpa/inet.h>
23 #include "networkd-address.h"
24 #include "networkd-manager.h"
25 #include "networkd-radv.h"
28 static int radv_get_ip6dns(Network
*network
, struct in6_addr
**dns
,
30 _cleanup_free_
struct in6_addr
*addresses
= NULL
;
31 size_t i
, n_addresses
= 0, n_allocated
= 0;
37 for (i
= 0; i
< network
->n_dns
; i
++) {
38 union in_addr_union
*addr
;
40 if (network
->dns
[i
].family
!= AF_INET6
)
43 addr
= &network
->dns
[i
].address
;
45 if (in_addr_is_null(AF_INET6
, addr
) ||
46 in_addr_is_link_local(AF_INET6
, addr
) ||
47 in_addr_is_localhost(AF_INET6
, addr
))
50 if (!GREEDY_REALLOC(addresses
, n_allocated
, n_addresses
+ 1))
53 addresses
[n_addresses
++] = addr
->in6
;
66 static int radv_set_dns(Link
*link
, Link
*uplink
) {
67 _cleanup_free_
struct in6_addr
*dns
= NULL
;
72 if (!link
->network
->router_emit_dns
)
75 if (link
->network
->router_dns
) {
76 dns
= newdup(struct in6_addr
, link
->network
->router_dns
,
77 link
->network
->n_router_dns
);
81 n_dns
= link
->network
->n_router_dns
;
82 lifetime_usec
= link
->network
->router_dns_lifetime_usec
;
87 lifetime_usec
= SD_RADV_DEFAULT_DNS_LIFETIME_USEC
;
89 r
= radv_get_ip6dns(link
->network
, &dns
, &n_dns
);
94 r
= radv_get_ip6dns(uplink
->network
, &dns
, &n_dns
);
102 return sd_radv_set_rdnss(link
->radv
,
103 DIV_ROUND_UP(lifetime_usec
, USEC_PER_SEC
),
107 static int radv_set_domains(Link
*link
, Link
*uplink
) {
108 char **search_domains
;
109 usec_t lifetime_usec
;
111 if (!link
->network
->router_emit_domains
)
114 search_domains
= link
->network
->router_search_domains
;
115 lifetime_usec
= link
->network
->router_dns_lifetime_usec
;
120 lifetime_usec
= SD_RADV_DEFAULT_DNS_LIFETIME_USEC
;
122 search_domains
= link
->network
->search_domains
;
127 search_domains
= uplink
->network
->search_domains
;
135 return sd_radv_set_dnssl(link
->radv
,
136 DIV_ROUND_UP(lifetime_usec
, USEC_PER_SEC
),
141 int radv_emit_dns(Link
*link
) {
145 uplink
= manager_find_uplink(link
->manager
, link
);
147 r
= radv_set_dns(link
, uplink
);
149 log_link_warning_errno(link
, r
, "Could not set RA DNS: %m");
151 r
= radv_set_domains(link
, uplink
);
153 log_link_warning_errno(link
, r
, "Could not set RA Domains: %m");
158 int radv_configure(Link
*link
) {
163 assert(link
->network
);
165 r
= sd_radv_new(&link
->radv
);
169 r
= sd_radv_attach_event(link
->radv
, NULL
, 0);
173 r
= sd_radv_set_mac(link
->radv
, &link
->mac
);
177 r
= sd_radv_set_ifindex(link
->radv
, link
->ifindex
);
181 r
= sd_radv_set_managed_information(link
->radv
, link
->network
->router_managed
);
185 r
= sd_radv_set_other_information(link
->radv
, link
->network
->router_other_information
);
189 /* a value of 0xffffffff represents infinity, 0x0 means this host is
191 r
= sd_radv_set_router_lifetime(link
->radv
,
192 DIV_ROUND_UP(link
->network
->router_lifetime_usec
, USEC_PER_SEC
));
196 if (link
->network
->router_lifetime_usec
> 0) {
197 r
= sd_radv_set_preference(link
->radv
,
198 link
->network
->router_preference
);
203 LIST_FOREACH(prefixes
, p
, link
->network
->static_prefixes
) {
204 r
= sd_radv_add_prefix(link
->radv
, p
->radv_prefix
);
205 if (r
!= -EEXIST
&& r
< 0)
209 return radv_emit_dns(link
);