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(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
33 assert(link
->static_ipv6_proxy_ndp_messages
> 0);
35 link
->static_ipv6_proxy_ndp_messages
--;
37 r
= sd_netlink_message_get_errno(m
);
39 log_link_message_warning_errno(link
, m
, r
, "Could not add IPv6 proxy ndp address entry, ignoring");
41 if (link
->static_ipv6_proxy_ndp_messages
== 0) {
42 log_link_debug(link
, "IPv6 proxy NDP addresses set.");
43 link
->static_ipv6_proxy_ndp_configured
= true;
44 link_check_ready(link
);
50 /* send a request to the kernel to add an IPv6 Proxy entry to the neighbour table */
51 static int ipv6_proxy_ndp_address_configure(
52 const struct in6_addr
*address
,
54 link_netlink_message_handler_t callback
) {
56 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= 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
, &req
, RTM_NEWNEIGH
, link
->ifindex
, AF_INET6
);
68 return log_link_error_errno(link
, r
, "Could not create RTM_NEWNEIGH message: %m");
70 r
= sd_rtnl_message_neigh_set_flags(req
, NTF_PROXY
);
72 return log_link_error_errno(link
, r
, "Could not set neighbor flags: %m");
74 r
= sd_netlink_message_append_in6_addr(req
, NDA_DST
, address
);
76 return log_link_error_errno(link
, r
, "Could not append NDA_DST attribute: %m");
78 r
= netlink_call_async(link
->manager
->rtnl
, NULL
, req
, callback
,
79 link_netlink_destroy_callback
, link
);
81 return log_link_error_errno(link
, r
, "Could not send rtnetlink message: %m");
88 int link_request_static_ipv6_proxy_ndp_addresses(Link
*link
) {
89 struct in6_addr
*address
;
93 assert(link
->network
);
95 link
->static_ipv6_proxy_ndp_configured
= false;
97 SET_FOREACH(address
, link
->network
->ipv6_proxy_ndp_addresses
) {
98 r
= link_queue_request(link
, REQUEST_TYPE_IPV6_PROXY_NDP
, address
, false,
99 &link
->static_ipv6_proxy_ndp_messages
,
100 ipv6_proxy_ndp_address_configure_handler
, NULL
);
102 return log_link_warning_errno(link
, r
, "Failed to request IPv6 proxy NDP address: %m");
105 if (link
->static_ipv6_proxy_ndp_messages
== 0) {
106 link
->static_ipv6_proxy_ndp_configured
= true;
107 link_check_ready(link
);
109 log_link_debug(link
, "Setting IPv6 proxy NDP addresses.");
110 link_set_state(link
, LINK_STATE_CONFIGURING
);
116 int request_process_ipv6_proxy_ndp_address(Request
*req
) {
119 assert(req
->ipv6_proxy_ndp
);
120 assert(req
->type
== REQUEST_TYPE_IPV6_PROXY_NDP
);
122 if (!link_is_ready_to_configure(req
->link
, false))
125 return ipv6_proxy_ndp_address_configure(req
->ipv6_proxy_ndp
, req
->link
, req
->netlink_handler
);
128 int config_parse_ipv6_proxy_ndp_address(
130 const char *filename
,
133 unsigned section_line
,
140 _cleanup_free_
struct in6_addr
*address
= NULL
;
141 Network
*network
= userdata
;
142 union in_addr_union buffer
;
149 if (isempty(rvalue
)) {
150 network
->ipv6_proxy_ndp_addresses
= set_free_free(network
->ipv6_proxy_ndp_addresses
);
154 r
= in_addr_from_string(AF_INET6
, rvalue
, &buffer
);
156 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
157 "Failed to parse IPv6 proxy NDP address, ignoring: %s", rvalue
);
161 if (in_addr_is_null(AF_INET6
, &buffer
)) {
162 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
163 "IPv6 proxy NDP address cannot be the ANY address, ignoring: %s", rvalue
);
167 address
= newdup(struct in6_addr
, &buffer
.in6
, 1);
171 r
= set_ensure_put(&network
->ipv6_proxy_ndp_addresses
, &in6_addr_hash_ops
, address
);