From 5585b969c18f84bd3bb7d02a0034c19ebae79e79 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20H=C3=A4rdeman?= Date: Sat, 10 Feb 2024 03:35:04 +0100 Subject: [PATCH] router: move pref64 calculations to the config stage MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit If pref64 is misconfigured, it'll print a LOG_WARNING message every time a RA is generated, which seems a bit excessive. When fixing that, I noticed that all work is done for every RA, so I ended up moving the gist over to the config stage where it is done once. Signed-off-by: David Härdeman --- src/config.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- src/odhcpd.h | 3 ++- src/router.c | 50 +++----------------------------------------------- 3 files changed, 48 insertions(+), 51 deletions(-) diff --git a/src/config.c b/src/config.c index e816f4b..4e1493f 100644 --- a/src/config.c +++ b/src/config.c @@ -1314,10 +1314,50 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr } } - if ((c = tb[IFACE_ATTR_RA_PREF64])) + if ((c = tb[IFACE_ATTR_RA_PREF64])) { + struct in6_addr addr; + odhcpd_parse_addr6_prefix(blobmsg_get_string(c), - &iface->pref64_addr, - &iface->pref64_length); + &addr, &iface->pref64_length); + + iface->pref64_prefix[0] = addr.s6_addr32[0]; + switch (iface->pref64_length) { + case 96: + iface->pref64_plc = 0; + iface->pref64_prefix[1] = addr.s6_addr32[1]; + iface->pref64_prefix[2] = addr.s6_addr32[2]; + break; + case 64: + iface->pref64_plc = 1; + iface->pref64_prefix[1] = addr.s6_addr32[1]; + iface->pref64_prefix[2] = 0; + break; + case 56: + iface->pref64_plc = 2; + iface->pref64_prefix[1] = addr.s6_addr32[1] & htonl(0xffffff00); + iface->pref64_prefix[2] = 0; + break; + case 48: + iface->pref64_plc = 3; + iface->pref64_prefix[1] = addr.s6_addr32[1] & htonl(0xffff0000); + iface->pref64_prefix[2] = 0; + break; + case 40: + iface->pref64_plc = 4; + iface->pref64_prefix[1] = addr.s6_addr32[1] & htonl(0xff000000); + iface->pref64_prefix[2] = 0; + break; + case 32: + iface->pref64_plc = 5; + iface->pref64_prefix[1] = 0; + iface->pref64_prefix[2] = 0; + break; + default: + syslog(LOG_WARNING, "Invalid PREF64 prefix size (%d), " + "ignoring ra_pref64 option!", iface->pref64_length); + iface->pref64_length = 0; + } + } if ((c = tb[IFACE_ATTR_RA_PREFERENCE])) { const char *prio = blobmsg_get_string(c); diff --git a/src/odhcpd.h b/src/odhcpd.h index 61fb64c..779f50f 100644 --- a/src/odhcpd.h +++ b/src/odhcpd.h @@ -330,7 +330,8 @@ struct interface { bool ra_useleasetime; bool ra_dns; uint8_t pref64_length; - struct in6_addr pref64_addr; + uint8_t pref64_plc; + uint32_t pref64_prefix[3]; bool no_dynamic_dhcp; bool have_link_local; uint8_t pio_filter_length; diff --git a/src/router.c b/src/router.c index b630953..2443078 100644 --- a/src/router.c +++ b/src/router.c @@ -438,7 +438,7 @@ struct nd_opt_pref64_info { uint8_t type; uint8_t len; uint16_t lifetime_plc; - uint32_t addr[3]; + uint32_t prefix[3]; }; struct nd_opt_dnr_info { @@ -742,59 +742,15 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr if (iface->pref64_length) { /* RFC 8781 § 4.1 rounding up lifetime to multiple of 8 */ uint16_t pref64_lifetime = lifetime < (UINT16_MAX - 7) ? lifetime + 7 : UINT16_MAX; - uint8_t prefix_length_code; - uint32_t mask_a1, mask_a2; - - switch (iface->pref64_length) { - case 96: - prefix_length_code = 0; - mask_a1 = 0xffffffff; - mask_a2 = 0xffffffff; - break; - case 64: - prefix_length_code = 1; - mask_a1 = 0xffffffff; - mask_a2 = 0x00000000; - break; - case 56: - prefix_length_code = 2; - mask_a1 = 0xffffff00; - mask_a2 = 0x00000000; - break; - case 48: - prefix_length_code = 3; - mask_a1 = 0xffff0000; - mask_a2 = 0x00000000; - break; - case 40: - prefix_length_code = 4; - mask_a1 = 0xff000000; - mask_a2 = 0x00000000; - break; - case 32: - prefix_length_code = 5; - mask_a1 = 0x00000000; - mask_a2 = 0x00000000; - break; - default: - syslog(LOG_WARNING, "Invalid PREF64 prefix size (%d), " - "ignoring ra_pref64 option!", iface->pref64_length); - goto pref64_out; - break; - } pref64_sz = sizeof(*pref64); pref64 = alloca(pref64_sz); - memset(pref64, 0, pref64_sz); pref64->type = ND_OPT_PREF64; pref64->len = 2; pref64->lifetime_plc = htons((0xfff8 & pref64_lifetime) | - (0x7 & prefix_length_code)); - pref64->addr[0] = iface->pref64_addr.s6_addr32[0]; - pref64->addr[1] = iface->pref64_addr.s6_addr32[1] & htonl(mask_a1); - pref64->addr[2] = iface->pref64_addr.s6_addr32[2] & htonl(mask_a2); + (0x7 & iface->pref64_plc)); + memcpy(pref64->prefix, iface->pref64_prefix, sizeof(pref64->prefix)); } -pref64_out: iov[IOV_RA_PREF64].iov_base = (char *)pref64; iov[IOV_RA_PREF64].iov_len = pref64_sz; -- 2.30.2