1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <netinet/in.h>
6 #include "netlink-util.h"
7 #include "networkd-ipv6-proxy-ndp.h"
8 #include "networkd-link.h"
9 #include "networkd-manager.h"
10 #include "networkd-network.h"
11 #include "networkd-queue.h"
12 #include "socket-util.h"
13 #include "string-util.h"
15 void network_adjust_ipv6_proxy_ndp(Network
*network
) {
18 if (set_isempty(network
->ipv6_proxy_ndp_addresses
))
21 if (!socket_ipv6_is_supported()) {
23 "%s: IPv6 proxy NDP addresses are set, but IPv6 is not supported by kernel, "
24 "Ignoring IPv6 proxy NDP addresses.", network
->filename
);
25 network
->ipv6_proxy_ndp_addresses
= set_free_free(network
->ipv6_proxy_ndp_addresses
);
29 static int ipv6_proxy_ndp_address_configure_handler(
31 sd_netlink_message
*m
,
34 struct in6_addr
*address
) {
41 r
= sd_netlink_message_get_errno(m
);
43 log_link_message_warning_errno(link
, m
, r
, "Could not add IPv6 proxy ndp address entry, ignoring");
45 if (link
->static_ipv6_proxy_ndp_messages
== 0) {
46 log_link_debug(link
, "IPv6 proxy NDP addresses set.");
47 link
->static_ipv6_proxy_ndp_configured
= true;
48 link_check_ready(link
);
54 /* send a request to the kernel to add an IPv6 Proxy entry to the neighbour table */
55 static int ipv6_proxy_ndp_address_configure(const struct in6_addr
*address
, Link
*link
, Request
*req
) {
56 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
61 assert(link
->manager
);
62 assert(link
->manager
->rtnl
);
65 /* create new netlink message */
66 r
= sd_rtnl_message_new_neigh(link
->manager
->rtnl
, &m
, RTM_NEWNEIGH
, link
->ifindex
, AF_INET6
);
70 r
= sd_rtnl_message_neigh_set_flags(m
, NTF_PROXY
);
74 r
= sd_netlink_message_append_in6_addr(m
, NDA_DST
, address
);
78 return request_call_netlink_async(link
->manager
->rtnl
, m
, req
);
81 static int ipv6_proxy_ndp_address_process_request(Request
*req
, Link
*link
, struct in6_addr
*address
) {
88 if (!link_is_ready_to_configure(link
, false))
91 r
= ipv6_proxy_ndp_address_configure(address
, link
, req
);
93 return log_link_warning_errno(link
, r
, "Failed to configure IPv6 proxy NDP address: %m");
98 int link_request_static_ipv6_proxy_ndp_addresses(Link
*link
) {
99 struct in6_addr
*address
;
103 assert(link
->network
);
105 link
->static_ipv6_proxy_ndp_configured
= false;
107 SET_FOREACH(address
, link
->network
->ipv6_proxy_ndp_addresses
) {
108 r
= link_queue_request_safe(link
, REQUEST_TYPE_IPV6_PROXY_NDP
,
111 in6_addr_compare_func
,
112 ipv6_proxy_ndp_address_process_request
,
113 &link
->static_ipv6_proxy_ndp_messages
,
114 ipv6_proxy_ndp_address_configure_handler
,
117 return log_link_warning_errno(link
, r
, "Failed to request IPv6 proxy NDP address: %m");
120 if (link
->static_ipv6_proxy_ndp_messages
== 0) {
121 link
->static_ipv6_proxy_ndp_configured
= true;
122 link_check_ready(link
);
124 log_link_debug(link
, "Setting IPv6 proxy NDP addresses.");
125 link_set_state(link
, LINK_STATE_CONFIGURING
);
131 int config_parse_ipv6_proxy_ndp_address(
133 const char *filename
,
136 unsigned section_line
,
143 _cleanup_free_
struct in6_addr
*address
= NULL
;
144 Network
*network
= ASSERT_PTR(userdata
);
145 union in_addr_union buffer
;
151 if (isempty(rvalue
)) {
152 network
->ipv6_proxy_ndp_addresses
= set_free_free(network
->ipv6_proxy_ndp_addresses
);
156 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
158 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
159 "Failed to parse IPv6 proxy NDP address, ignoring: %s", rvalue
);
163 if (in_addr_is_null(AF_INET6
, &buffer
)) {
164 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
165 "IPv6 proxy NDP address cannot be the ANY address, ignoring: %s", rvalue
);
169 address
= newdup(struct in6_addr
, &buffer
.in6
, 1);
173 r
= set_ensure_put(&network
->ipv6_proxy_ndp_addresses
, &in6_addr_hash_ops
, address
);