#include <arpa/inet.h>
#include <netinet/icmp6.h>
#include <linux/if.h>
+#include <linux/if_arp.h>
#include "sd-ndisc.h"
if (link->flags & IFF_LOOPBACK)
return false;
+ if (link->iftype == ARPHRD_CAN)
+ return false;
+
+ if (link->hw_addr.length != ETH_ALEN && !streq_ptr(link->kind, "wwan"))
+ /* Currently, only interfaces whose MAC address length is ETH_ALEN are supported.
+ * Note, wwan interfaces may be assigned MAC address slightly later.
+ * Hence, let's wait for a while.*/
+ return false;
+
if (!link->network)
return false;
return 0;
}
-static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
int r;
assert(link);
- assert(link->ndisc_messages > 0);
-
- link->ndisc_messages--;
r = route_configure_handler_internal(rtnl, m, link, "Could not set NDisc route");
if (r <= 0)
ndisc_route_handler, NULL);
}
-static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
int r;
assert(link);
- assert(link->ndisc_messages > 0);
-
- link->ndisc_messages--;
r = address_configure_handler_internal(rtnl, m, link, "Could not set NDisc address");
if (r <= 0)
if (lifetime_sec == 0) /* not a default router */
return 0;
- r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec);
+ r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, ×tamp_usec);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
if (r < 0)
return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m");
- if (link_get_ipv6_address(link, &gateway, NULL) >= 0) {
+ if (link_get_ipv6_address(link, &gateway, 0, NULL) >= 0) {
if (DEBUG_LOGGING) {
_cleanup_free_ char *buffer = NULL;
if (!link->network->ipv6_accept_ra_use_autonomous_prefix)
return 0;
- r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec);
+ r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, ×tamp_usec);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
if (lifetime_sec == 0)
return 0;
- r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec);
+ r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, ×tamp_usec);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
if (r < 0)
return log_link_error_errno(link, r, "Failed to get route prefix length: %m");
+ if (in6_addr_is_null(&dst) && prefixlen == 0) {
+ log_link_debug(link, "Route prefix is ::/0, ignoring");
+ return 0;
+ }
+
if (in6_prefix_is_filtered(&dst, prefixlen, link->network->ndisc_allow_listed_route_prefix, link->network->ndisc_deny_listed_route_prefix)) {
if (DEBUG_LOGGING) {
_cleanup_free_ char *buf = NULL;
if (r < 0)
return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m");
- if (link_get_ipv6_address(link, &gateway, NULL) >= 0) {
+ if (link_get_ipv6_address(link, &gateway, 0, NULL) >= 0) {
if (DEBUG_LOGGING) {
_cleanup_free_ char *buf = NULL;
if (r < 0)
return log_link_error_errno(link, r, "Failed to get default router preference from RA: %m");
- r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec);
+ r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, ×tamp_usec);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
if (r < 0)
return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
- r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec);
+ r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, ×tamp_usec);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
struct in6_addr router;
uint32_t lifetime_sec;
bool updated = false;
- char **j;
int r;
assert(link);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
- r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), ×tamp_usec);
+ r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, ×tamp_usec);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
}
}
-int ndisc_configure(Link *link) {
+static int ndisc_configure(Link *link) {
int r;
assert(link);
}
int ndisc_start(Link *link) {
+ int r;
+
assert(link);
if (!link->ndisc || !link->dhcp6_client)
log_link_debug(link, "Discovering IPv6 routers");
- return sd_ndisc_start(link->ndisc);
+ r = sd_ndisc_start(link->ndisc);
+ if (r < 0)
+ return r;
+
+ return 1;
+}
+
+static int ndisc_process_request(Request *req, Link *link, void *userdata) {
+ int r;
+
+ assert(link);
+
+ if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
+ return 0;
+
+ if (link->hw_addr.length != ETH_ALEN || hw_addr_is_null(&link->hw_addr))
+ /* No MAC address is assigned to the hardware, or non-supported MAC address length. */
+ return 0;
+
+ r = ndisc_configure(link);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Failed to configure IPv6 Router Discovery: %m");
+
+ r = ndisc_start(link);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Failed to start IPv6 Router Discovery: %m");
+
+ log_link_debug(link, "IPv6 Router Discovery is configured%s.",
+ r > 0 ? " and started" : "");
+ return 1;
+}
+
+int link_request_ndisc(Link *link) {
+ int r;
+
+ assert(link);
+
+ if (!link_ipv6_accept_ra_enabled(link))
+ return 0;
+
+ if (link->ndisc)
+ return 0;
+
+ r = link_queue_request(link, REQUEST_TYPE_NDISC, ndisc_process_request, NULL);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Failed to request configuring of the IPv6 Router Discovery: %m");
+
+ log_link_debug(link, "Requested configuring of the IPv6 Router Discovery.");
+ return 0;
}
void ndisc_vacuum(Link *link) {
/* Removes all RDNSS and DNSSL entries whose validity time has passed */
- time_now = now(clock_boottime_or_monotonic());
+ time_now = now(CLOCK_BOOTTIME);
SET_FOREACH(r, link->ndisc_rdnss)
if (r->lifetime_usec < time_now)