From 19f3cc86a04ff7870dea3ac97fcbf624db3330fe Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 18 Feb 2024 15:23:09 +0900 Subject: [PATCH 1/2] sd-radv: set only basic information on stop There are many possible reasons to stop the service; tentative reboot of the service or the system, the router may be revoked, and so on. And, each situations, the availability of the previously announced options e.g. prefixes, DNSSL and so on is not clear. So, let's announce only the clear information, that is, the router lifetime is zero. which indicates that the router will be invalidated (regardless tentative or not). --- src/libsystemd-network/sd-radv.c | 26 +++++++++++++++++++++++++- src/libsystemd-network/test-ndisc-ra.c | 7 ++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c index 79210f9e2c..69ebd94fb1 100644 --- a/src/libsystemd-network/sd-radv.c +++ b/src/libsystemd-network/sd-radv.c @@ -129,6 +129,30 @@ static bool router_lifetime_is_valid(usec_t lifetime_usec) { lifetime_usec <= RADV_MAX_ROUTER_LIFETIME_USEC); } +static int radv_send_router_on_stop(sd_radv *ra) { + static const struct nd_router_advert adv = { + .nd_ra_type = ND_ROUTER_ADVERT, + }; + + _cleanup_set_free_ Set *options = NULL; + usec_t time_now; + int r; + + assert(ra); + + r = sd_event_now(ra->event, CLOCK_BOOTTIME, &time_now); + if (r < 0) + return r; + + if (!ether_addr_is_null(&ra->mac_addr)) { + r = ndisc_option_set_link_layer_address(&options, SD_NDISC_OPTION_SOURCE_LL_ADDRESS, &ra->mac_addr); + if (r < 0) + return r; + } + + return ndisc_send(ra->fd, &IN6_ADDR_ALL_NODES_MULTICAST, &adv.nd_ra_hdr, options, time_now); +} + static int radv_send_router(sd_radv *ra, const struct in6_addr *dst, usec_t lifetime_usec) { assert(ra); assert(router_lifetime_is_valid(lifetime_usec)); @@ -362,7 +386,7 @@ int sd_radv_stop(sd_radv *ra) { /* RFC 4861, Section 6.2.5: * the router SHOULD transmit one or more (but not more than MAX_FINAL_RTR_ADVERTISEMENTS) final * multicast Router Advertisements on the interface with a Router Lifetime field of zero. */ - r = radv_send_router(ra, NULL, 0); + r = radv_send_router_on_stop(ra); if (r < 0) log_radv_errno(ra, r, "Unable to send last Router Advertisement with router lifetime set to zero, ignoring: %m"); diff --git a/src/libsystemd-network/test-ndisc-ra.c b/src/libsystemd-network/test-ndisc-ra.c index c5f10cc795..76f4d7ba3f 100644 --- a/src/libsystemd-network/test-ndisc-ra.c +++ b/src/libsystemd-network/test-ndisc-ra.c @@ -294,8 +294,13 @@ static void verify_message(const uint8_t *buf, size_t len) { /* verify only up to known options, rest is not yet implemented */ for (size_t i = 0, m = MIN(len, sizeof(advertisement)); i < m; i++) { if (test_stopped) + /* on stop, many header fields are zero */ switch (i) { - case 6 ... 7: /* router lifetime must be zero on stop. */ + case 4: /* hop limit */ + case 5: /* flags */ + case 6 ... 7: /* router lifetime */ + case 8 ... 11: /* reachable time */ + case 12 ... 15: /* retrans timer */ assert_se(buf[i] == 0); continue; } From 69628e3b3b21206d68834521c45621121cc5c451 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 15 Apr 2024 11:19:57 +0900 Subject: [PATCH 2/2] sd-radv: drop unnecessary argument The argument always has the same value. --- src/libsystemd-network/sd-radv.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c index 69ebd94fb1..6a71ce14ff 100644 --- a/src/libsystemd-network/sd-radv.c +++ b/src/libsystemd-network/sd-radv.c @@ -153,9 +153,8 @@ static int radv_send_router_on_stop(sd_radv *ra) { return ndisc_send(ra->fd, &IN6_ADDR_ALL_NODES_MULTICAST, &adv.nd_ra_hdr, options, time_now); } -static int radv_send_router(sd_radv *ra, const struct in6_addr *dst, usec_t lifetime_usec) { +static int radv_send_router(sd_radv *ra, const struct in6_addr *dst) { assert(ra); - assert(router_lifetime_is_valid(lifetime_usec)); struct sockaddr_in6 dst_addr = { .sin6_family = AF_INET6, @@ -163,7 +162,7 @@ static int radv_send_router(sd_radv *ra, const struct in6_addr *dst, usec_t life }; struct nd_router_advert adv = { .nd_ra_type = ND_ROUTER_ADVERT, - .nd_ra_router_lifetime = usec_to_be16_sec(lifetime_usec), + .nd_ra_router_lifetime = usec_to_be16_sec(ra->lifetime_usec), .nd_ra_retransmit = usec_to_be32_msec(ra->retransmit_usec), }; struct { @@ -285,7 +284,7 @@ static int radv_process_packet(sd_radv *ra, ICMP6Packet *packet) { if (r < 0 && r != -ENODATA) /* null address is allowed */ return log_radv_errno(ra, r, "Failed to get sender address of RS, ignoring: %m"); - r = radv_send_router(ra, &src, ra->lifetime_usec); + r = radv_send_router(ra, &src); if (r < 0) return log_radv_errno(ra, r, "Unable to send solicited Router Advertisement to %s, ignoring: %m", IN6_ADDR_TO_STRING(&src)); @@ -323,7 +322,7 @@ static int radv_timeout(sd_event_source *s, uint64_t usec, void *userdata) { if (r < 0) goto fail; - r = radv_send_router(ra, NULL, ra->lifetime_usec); + r = radv_send_router(ra, NULL); if (r < 0) log_radv_errno(ra, r, "Unable to send Router Advertisement, ignoring: %m"); @@ -703,7 +702,7 @@ int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p) { return 0; /* If RAs have already been sent, send an RA immediately to announce the newly-added prefix */ - r = radv_send_router(ra, NULL, ra->lifetime_usec); + r = radv_send_router(ra, NULL); if (r < 0) log_radv_errno(ra, r, "Unable to send Router Advertisement for added prefix %s, ignoring: %m", addr_p); else @@ -799,7 +798,7 @@ int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p) { return 0; /* If RAs have already been sent, send an RA immediately to announce the newly-added route prefix */ - r = radv_send_router(ra, NULL, ra->lifetime_usec); + r = radv_send_router(ra, NULL); if (r < 0) log_radv_errno(ra, r, "Unable to send Router Advertisement for added route prefix %s, ignoring: %m", strna(addr_p)); @@ -871,7 +870,7 @@ int sd_radv_add_pref64_prefix(sd_radv *ra, sd_radv_pref64_prefix *p) { return 0; /* If RAs have already been sent, send an RA immediately to announce the newly-added route prefix */ - r = radv_send_router(ra, NULL, ra->lifetime_usec); + r = radv_send_router(ra, NULL); if (r < 0) log_radv_errno(ra, r, "Unable to send Router Advertisement for added PREF64 prefix %s, ignoring: %m", strna(addr_p));