diff --git a/package/network/services/odhcpd/patches/001-odhcpd-RFC-9096-compliance.patch b/package/network/services/odhcpd/patches/001-odhcpd-RFC-9096-compliance.patch index 9f56fb258d..e3df56b577 100644 --- a/package/network/services/odhcpd/patches/001-odhcpd-RFC-9096-compliance.patch +++ b/package/network/services/odhcpd/patches/001-odhcpd-RFC-9096-compliance.patch @@ -1,110 +1,239 @@ -From 0e41fb05fbb2896f1c6f000b0c880e837760ccce Mon Sep 17 00:00:00 2001 +From 726ca5340823e2d5f3b5e7b6ad83e52ba3be14a9 Mon Sep 17 00:00:00 2001 +From: Aviana Cruz Date: Sat, 16 Sep 2023 15:04:12 +0000 -Subject: [PATCH] odhcpd: RFC 9096 compliance +Subject: [PATCH] odhcpd: improve RFC 9096 compliance and allow configuring upper limit for preferred and valid lifetime. ---- - README | 5 +++-- - src/config.c | 32 ++++++++++++++++++++++++++++++++ - src/dhcpv6-ia.c | 8 ++++++++ - src/odhcpd.h | 6 ++++++ - src/router.c | 16 ++++++++++++---- - 5 files changed, 61 insertions(+), 6 deletions(-) -diff --git a/README b/README -index 243ae24..c13d9b8 100644 +Signed-off-by: Aviana Cruz +--- + README | 12 ++++++------ + src/config.c | 35 +++++++++++++++++++++------------- + src/dhcpv6-ia.c | 50 ++++++++++++++++++++++++++++++------------------- + src/odhcpd.h | 8 ++++++-- + src/router.c | 17 ++++++++--------- + 5 files changed, 73 insertions(+), 49 deletions(-) + --- a/README +++ b/README -@@ -131,8 +131,9 @@ ra_maxinterval integer 600 Maximum time allowed between +@@ -116,7 +116,9 @@ domain list Sear + leasetime string 12h DHCPv4 address leasetime + start integer 100 DHCPv4 pool start + limit integer 150 DHCPv4 pool size +-preferred_lifetime string 12h Value for the preferred lifetime ++max_preferred_lifetime string 45m Upper limit for the preferred lifetime ++ for a prefix ++max_valid_lifetime string 90m Upper limit for the valid lifetime + for a prefix + ra_default integer 0 Override default route + 0: default, 1: ignore no public address, 2: ignore all +@@ -131,11 +133,9 @@ ra_maxinterval integer 600 Maximum ti sending unsolicited RA ra_mininterval integer 200 Minimum time allowed between sending unsolicited RA -ra_lifetime integer 1800 Value to be placed in Router - Lifetime field of RA +-ra_useleasetime bool 0 Use configured leasetime as +- limit for the preferred and +- valid lifetime of a prefix +ra_lifetime integer 2700 Value to be placed in Router + Lifetime field of RA. Not recommended to be + more than 2700 (RFC9096). - ra_useleasetime bool 0 Use configured leasetime as - limit for the preferred and - valid lifetime of a prefix -diff --git a/src/config.c b/src/config.c -index 1cd4608..e193a94 100644 + ra_reachabletime integer 0 Reachable Time in milliseconds to be + advertised in RA messages + ra_retranstime integer 0 Retransmit Time in milliseconds to be --- a/src/config.c +++ b/src/config.c -@@ -92,6 +92,8 @@ enum { +@@ -79,7 +79,6 @@ enum { + IFACE_ATTR_RA_MININTERVAL, + IFACE_ATTR_RA_MAXINTERVAL, + IFACE_ATTR_RA_LIFETIME, +- IFACE_ATTR_RA_USELEASETIME, + IFACE_ATTR_RA_REACHABLETIME, + IFACE_ATTR_RA_RETRANSTIME, + IFACE_ATTR_RA_HOPLIMIT, +@@ -91,7 +90,8 @@ enum { + IFACE_ATTR_NDPROXY_ROUTING, IFACE_ATTR_NDPROXY_SLAVE, IFACE_ATTR_PREFIX_FILTER, - IFACE_ATTR_PREFERRED_LIFETIME, +- IFACE_ATTR_PREFERRED_LIFETIME, + IFACE_ATTR_MAX_PREFERRED_LIFETIME, + IFACE_ATTR_MAX_VALID_LIFETIME, IFACE_ATTR_NTP, IFACE_ATTR_MAX }; -@@ -145,6 +147,8 @@ static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = { +@@ -134,7 +134,6 @@ static const struct blobmsg_policy iface + [IFACE_ATTR_RA_MININTERVAL] = { .name = "ra_mininterval", .type = BLOBMSG_TYPE_INT32 }, + [IFACE_ATTR_RA_MAXINTERVAL] = { .name = "ra_maxinterval", .type = BLOBMSG_TYPE_INT32 }, + [IFACE_ATTR_RA_LIFETIME] = { .name = "ra_lifetime", .type = BLOBMSG_TYPE_INT32 }, +- [IFACE_ATTR_RA_USELEASETIME] = { .name = "ra_useleasetime", .type = BLOBMSG_TYPE_BOOL }, + [IFACE_ATTR_RA_REACHABLETIME] = { .name = "ra_reachabletime", .type = BLOBMSG_TYPE_INT32 }, + [IFACE_ATTR_RA_RETRANSTIME] = { .name = "ra_retranstime", .type = BLOBMSG_TYPE_INT32 }, + [IFACE_ATTR_RA_HOPLIMIT] = { .name = "ra_hoplimit", .type = BLOBMSG_TYPE_INT32 }, +@@ -144,7 +143,8 @@ static const struct blobmsg_policy iface + [IFACE_ATTR_NDPROXY_ROUTING] = { .name = "ndproxy_routing", .type = BLOBMSG_TYPE_BOOL }, [IFACE_ATTR_NDPROXY_SLAVE] = { .name = "ndproxy_slave", .type = BLOBMSG_TYPE_BOOL }, [IFACE_ATTR_PREFIX_FILTER] = { .name = "prefix_filter", .type = BLOBMSG_TYPE_STRING }, - [IFACE_ATTR_PREFERRED_LIFETIME] = { .name = "preferred_lifetime", .type = BLOBMSG_TYPE_STRING }, +- [IFACE_ATTR_PREFERRED_LIFETIME] = { .name = "preferred_lifetime", .type = BLOBMSG_TYPE_STRING }, + [IFACE_ATTR_MAX_PREFERRED_LIFETIME] = { .name = "max_preferred_lifetime", .type = BLOBMSG_TYPE_STRING }, + [IFACE_ATTR_MAX_VALID_LIFETIME] = { .name = "max_valid_lifetime", .type = BLOBMSG_TYPE_STRING }, [IFACE_ATTR_NTP] = { .name = "ntp", .type = BLOBMSG_TYPE_ARRAY }, }; -@@ -658,6 +662,34 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr +@@ -215,7 +215,8 @@ static void set_interface_defaults(struc + iface->ndp = MODE_DISABLED; + iface->learn_routes = 1; + iface->dhcp_leasetime = 43200; +- iface->preferred_lifetime = 43200; ++ iface->max_preferred_lifetime = ND_PREFERRED_LIMIT; ++ iface->max_valid_lifetime = ND_VALID_LIMIT; + iface->dhcpv4_start.s_addr = htonl(START_DEFAULT); + iface->dhcpv4_end.s_addr = htonl(START_DEFAULT + LIMIT_DEFAULT - 1); + iface->dhcpv6_assignall = true; +@@ -647,15 +648,26 @@ int config_parse_interface(void *data, s } +- if ((c = tb[IFACE_ATTR_PREFERRED_LIFETIME])) { + if ((c = tb[IFACE_ATTR_MAX_PREFERRED_LIFETIME])) { -+ double time = parse_leasetime(c); -+ + double time = parse_leasetime(c); + +- if (time >= 0) +- iface->preferred_lifetime = time; +- else + if (time >= 0) { + iface->max_preferred_lifetime = time; + } else { -+ iface->max_preferred_lifetime = ND_PREFERRED_LIMIT; -+ syslog(LOG_ERR, "Invalid %s value configured for interface '%s'", + syslog(LOG_ERR, "Invalid %s value configured for interface '%s'", +- iface_attrs[IFACE_ATTR_PREFERRED_LIFETIME].name, iface->name); + iface_attrs[IFACE_ATTR_MAX_PREFERRED_LIFETIME].name, iface->name); + } -+ } else { -+ iface->max_preferred_lifetime = ND_PREFERRED_LIMIT; + } -+ + + if ((c = tb[IFACE_ATTR_MAX_VALID_LIFETIME])) { + double time = parse_leasetime(c); + + if (time >= 0) { + iface->max_valid_lifetime = time; + } else { -+ iface->max_valid_lifetime = ND_VALID_LIMIT; + syslog(LOG_ERR, "Invalid %s value configured for interface '%s'", + iface_attrs[IFACE_ATTR_MAX_VALID_LIFETIME].name, iface->name); + } -+ } else { -+ iface->max_valid_lifetime = ND_VALID_LIMIT; -+ } -+ + } + if ((c = tb[IFACE_ATTR_START])) { - iface->dhcpv4_start.s_addr = htonl(blobmsg_get_u32(c)); - iface->dhcpv4_end.s_addr = htonl(ntohl(iface->dhcpv4_start.s_addr) + -diff --git a/src/dhcpv6-ia.c b/src/dhcpv6-ia.c -index 1fbed44..b4d88d7 100644 +@@ -978,9 +990,6 @@ int config_parse_interface(void *data, s + if ((c = tb[IFACE_ATTR_RA_LIFETIME])) + iface->ra_lifetime = blobmsg_get_u32(c); + +- if ((c = tb[IFACE_ATTR_RA_USELEASETIME])) +- iface->ra_useleasetime = blobmsg_get_bool(c); +- + if ((c = tb[IFACE_ATTR_RA_DNS])) + iface->ra_dns = blobmsg_get_bool(c); + --- a/src/dhcpv6-ia.c +++ b/src/dhcpv6-ia.c -@@ -1141,6 +1141,14 @@ static size_t build_ia(uint8_t *buf, size_t buflen, uint16_t status, +@@ -120,7 +120,7 @@ static inline bool valid_prefix_length(c + + static inline bool valid_addr(const struct odhcpd_ipaddr *addr, time_t now) + { +- return (addr->prefix <= 96 && addr->preferred > (uint32_t)now); ++ return (addr->prefix <= 96 && addr->valid > (uint32_t)now && addr->preferred > (uint32_t)now); + } + + static size_t get_preferred_addr(const struct odhcpd_ipaddr *addrs, const size_t addrlen) +@@ -1037,17 +1037,27 @@ static size_t build_ia(uint8_t *buf, siz + } + + if (a) { +- uint32_t leasetime, pref; ++ uint32_t leasetime; + + if (a->leasetime) { + leasetime = a->leasetime; +- pref = a->leasetime; + } else { + leasetime = iface->dhcp_leasetime; +- pref = iface->preferred_lifetime; + } + +- uint32_t valid = leasetime; ++ uint32_t floor_preferred_lifetime, floor_valid_lifetime; /* For calculating T1 / T2 */ ++ ++ if (iface->max_preferred_lifetime && iface->max_preferred_lifetime < leasetime) { ++ floor_preferred_lifetime = iface->max_preferred_lifetime; ++ } else { ++ floor_preferred_lifetime = leasetime; ++ } ++ ++ if (iface->max_valid_lifetime && iface->max_valid_lifetime < leasetime) { ++ floor_valid_lifetime = iface->max_valid_lifetime; ++ } else { ++ floor_valid_lifetime = leasetime; ++ } + + struct odhcpd_ipaddr *addrs = (a->managed) ? a->managed : iface->addr6; + size_t addrlen = (a->managed) ? (size_t)a->managed_size : iface->addr6_len; +@@ -1071,17 +1081,19 @@ static size_t build_ia(uint8_t *buf, siz + prefix_pref = addrs[i].preferred; + prefix_valid = addrs[i].valid; + +- if (prefix_pref != UINT32_MAX) ++ if (prefix_pref != UINT32_MAX) { + prefix_pref -= now; + +- if (prefix_pref > pref) +- prefix_pref = pref; ++ if (iface->max_preferred_lifetime && prefix_pref > iface->max_preferred_lifetime) ++ prefix_pref = iface->max_preferred_lifetime; ++ } + +- if (prefix_valid != UINT32_MAX) ++ if (prefix_valid != UINT32_MAX) { + prefix_valid -= now; + +- if (prefix_valid > leasetime) +- prefix_valid = leasetime; ++ if (iface->max_valid_lifetime && prefix_valid > iface->max_valid_lifetime) ++ prefix_valid = iface->max_valid_lifetime; ++ } + + if (prefix_pref > prefix_valid) + prefix_pref = prefix_valid; +@@ -1133,24 +1145,24 @@ static size_t build_ia(uint8_t *buf, siz + + /* Calculate T1 / T2 based on non-deprecated addresses */ + if (prefix_pref > 0) { +- if (prefix_pref < pref) +- pref = prefix_pref; ++ if (floor_preferred_lifetime > prefix_pref) ++ floor_preferred_lifetime = prefix_pref; + +- if (prefix_valid < valid) +- valid = prefix_valid; ++ if (floor_valid_lifetime > prefix_valid) ++ floor_valid_lifetime = prefix_valid; } } -+ if (iface->max_preferred_lifetime) { -+ pref = min(pref, iface->max_preferred_lifetime); -+ } -+ -+ if (iface->max_valid_lifetime) { -+ valid = min(valid, iface->max_valid_lifetime); -+ } -+ if (!INFINITE_VALID(a->valid_until)) /* UINT32_MAX is considered as infinite leasetime */ - a->valid_until = (valid == UINT32_MAX) ? 0 : valid + now; -diff --git a/src/odhcpd.h b/src/odhcpd.h -index 02b6ac0..e409caf 100644 +- a->valid_until = (valid == UINT32_MAX) ? 0 : valid + now; ++ a->valid_until = (floor_valid_lifetime == UINT32_MAX) ? 0 : floor_valid_lifetime + now; + + if (!INFINITE_VALID(a->preferred_until)) + /* UINT32_MAX is considered as infinite leasetime */ +- a->preferred_until = (pref == UINT32_MAX) ? 0 : pref + now; ++ a->preferred_until = (floor_preferred_lifetime == UINT32_MAX) ? 0 : floor_preferred_lifetime + now; + +- o_ia.t1 = htonl((pref == UINT32_MAX) ? pref : pref * 5 / 10); +- o_ia.t2 = htonl((pref == UINT32_MAX) ? pref : pref * 8 / 10); ++ o_ia.t1 = htonl((floor_preferred_lifetime == UINT32_MAX) ? floor_preferred_lifetime : floor_preferred_lifetime * 5 / 10); ++ o_ia.t2 = htonl((floor_preferred_lifetime == UINT32_MAX) ? floor_preferred_lifetime : floor_preferred_lifetime * 8 / 10); + + if (!o_ia.t1) + o_ia.t1 = htonl(1); --- a/src/odhcpd.h +++ b/src/odhcpd.h @@ -37,6 +37,10 @@ @@ -118,20 +247,27 @@ index 02b6ac0..e409caf 100644 #define INFINITE_VALID(x) ((x) == 0) #define _unused __attribute__((unused)) -@@ -320,6 +324,8 @@ struct interface { +@@ -302,7 +306,6 @@ struct interface { + bool ra_slaac; + bool ra_not_onlink; + bool ra_advrouter; +- bool ra_useleasetime; + bool ra_dns; + uint8_t pref64_length; + struct in6_addr pref64_addr; +@@ -319,7 +322,8 @@ struct interface { + uint32_t ra_retranstime; uint32_t ra_hoplimit; int ra_mtu; - uint32_t preferred_lifetime; +- uint32_t preferred_lifetime; + uint32_t max_preferred_lifetime; + uint32_t max_valid_lifetime; // DHCP uint32_t dhcp_leasetime; -diff --git a/src/router.c b/src/router.c -index d5ef7f8..c80358b 100644 --- a/src/router.c +++ b/src/router.c -@@ -371,7 +371,7 @@ static int calc_adv_interval(struct interface *iface, uint32_t minvalid, +@@ -371,7 +371,7 @@ static int calc_adv_interval(struct inte static uint32_t calc_ra_lifetime(struct interface *iface, uint32_t maxival) { @@ -140,22 +276,28 @@ index d5ef7f8..c80358b 100644 if (iface->ra_lifetime >= 0) { lifetime = iface->ra_lifetime; -@@ -602,6 +602,14 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr - valid = iface->dhcp_leasetime; +@@ -590,16 +590,15 @@ static int send_router_advert(struct int + if (addr->preferred > (uint32_t)now) { + preferred = TIME_LEFT(addr->preferred, now); + +- if (iface->ra_useleasetime && +- preferred > iface->preferred_lifetime) +- preferred = iface->preferred_lifetime; ++ if (iface->max_preferred_lifetime && preferred > iface->max_preferred_lifetime) ++ preferred = iface->max_preferred_lifetime; } -+ if (iface->max_preferred_lifetime) { -+ preferred = min(preferred, iface->max_preferred_lifetime); -+ } -+ -+ if (iface->max_valid_lifetime) { -+ valid = min(valid, iface->max_valid_lifetime); -+ } -+ - if (minvalid > valid) - minvalid = valid; + if (addr->valid > (uint32_t)now) { + valid = TIME_LEFT(addr->valid, now); -@@ -643,9 +651,9 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr +- if (iface->ra_useleasetime && valid > iface->dhcp_leasetime) +- valid = iface->dhcp_leasetime; ++ if (iface->max_valid_lifetime && valid > iface->max_valid_lifetime) ++ valid = iface->max_valid_lifetime; + } + + if (minvalid > valid) +@@ -643,9 +642,9 @@ static int send_router_advert(struct int if (default_route) { syslog(LOG_WARNING, "A default route is present but there is no public prefix " @@ -167,7 +309,7 @@ index d5ef7f8..c80358b 100644 } } -@@ -710,7 +718,7 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr +@@ -710,7 +709,7 @@ static int send_router_advert(struct int if (iface->pref64_length) { /* RFC 8781 ยง 4.1 rounding up lifetime to multiply of 8 */ @@ -176,6 +318,3 @@ index d5ef7f8..c80358b 100644 uint8_t prefix_length_code; uint32_t mask_a1, mask_a2; --- -2.42.1 -