From 3bda90079ec5574ef469e2a7804808302f17769d Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Sat, 2 Jan 2021 23:27:03 +0100 Subject: [PATCH] odhcpd: add option for setting preferred lifetime "valid_lft" and "preferred_lft" are different. If the "preferred_lft" is expired the prefix should be avoided in source prefix selection. However, the interface is allowed to still receive downstream traffic. preferred_lfetime: Limit for preferred lifetime of a prefix If you want the old behavior, you have to set preferred_lifetime to the same value as leasetime. Signed-off-by: Nick Hainke Signed-off-by: Hans Dedecker --- README | 3 ++- src/config.c | 11 +++++++++++ src/dhcpv6-ia.c | 22 ++++++++++++++++------ src/odhcpd.h | 2 ++ src/router.c | 4 ++-- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/README b/README index a34a93c..f9cbb11 100644 --- a/README +++ b/README @@ -110,7 +110,8 @@ domain list Search domains to announce 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 + for a prefix ra_default integer 0 Override default route 0: default, 1: ignore no public address, 2: ignore all ra_flags list other-config List of RA flags to be diff --git a/src/config.c b/src/config.c index 015a716..78b5855 100644 --- a/src/config.c +++ b/src/config.c @@ -82,6 +82,7 @@ enum { IFACE_ATTR_NDPROXY_ROUTING, IFACE_ATTR_NDPROXY_SLAVE, IFACE_ATTR_PREFIX_FILTER, + IFACE_ATTR_PREFERRED_LIFETIME, IFACE_ATTR_MAX }; @@ -130,6 +131,7 @@ static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = { [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 }, }; static const struct uci_blob_param_info iface_attr_info[IFACE_ATTR_MAX] = { @@ -197,6 +199,7 @@ static void set_interface_defaults(struct interface *iface) iface->ndp = MODE_DISABLED; iface->learn_routes = 1; iface->dhcp_leasetime = 43200; + iface->preferred_lifetime = 43200; iface->dhcpv4_start.s_addr = htonl(START_DEFAULT); iface->dhcpv4_end.s_addr = htonl(START_DEFAULT + LIMIT_DEFAULT - 1); iface->dhcpv6_assignall = true; @@ -525,6 +528,14 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr iface->dhcp_leasetime = time; } + if ((c = tb[IFACE_ATTR_PREFERRED_LIFETIME])) { + double time = parse_leasetime(c); + if (time < 0) + goto err; + + iface->preferred_lifetime = time; + } + 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 d7848de..a59fc20 100644 --- a/src/dhcpv6-ia.c +++ b/src/dhcpv6-ia.c @@ -247,6 +247,9 @@ void dhcpv6_ia_enum_addrs(struct interface *iface, struct dhcp_assignment *c, addr.s6_addr32[2] = addr.s6_addr32[3] = 0; } + if (pref > (uint32_t)c->preferred_until) + pref = c->preferred_until; + if (pref > (uint32_t)c->valid_until) pref = c->valid_until; @@ -827,14 +830,16 @@ static size_t build_ia(uint8_t *buf, size_t buflen, uint16_t status, } if (a) { - uint32_t leasetime; + uint32_t leasetime, pref; - if (a->leasetime) + if (a->leasetime) { leasetime = a->leasetime; - else + pref = a->leasetime; + } else { leasetime = iface->dhcp_leasetime; + pref = iface->preferred_lifetime; + } - uint32_t pref = leasetime; uint32_t valid = leasetime; struct odhcpd_ipaddr *addrs = (a->managed) ? a->managed : iface->addr6; @@ -851,8 +856,8 @@ static size_t build_ia(uint8_t *buf, size_t buflen, uint16_t status, if (prefix_pref != UINT32_MAX) prefix_pref -= now; - if (prefix_pref > leasetime) - prefix_pref = leasetime; + if (prefix_pref > pref) + prefix_pref = pref; if (prefix_valid != UINT32_MAX) prefix_valid -= now; @@ -918,6 +923,10 @@ static size_t build_ia(uint8_t *buf, size_t buflen, uint16_t status, /* UINT32_MAX is considered as infinite leasetime */ a->valid_until = (valid == UINT32_MAX) ? 0 : valid + now; + if (!INFINITE_VALID(a->preferred_until)) + /* UINT32_MAX is considered as infinite leasetime */ + a->preferred_until = (pref == UINT32_MAX) ? 0 : pref + now; + o_ia.t1 = htonl((pref == UINT32_MAX) ? pref : pref * 5 / 10); o_ia.t2 = htonl((pref == UINT32_MAX) ? pref : pref * 8 / 10); @@ -1261,6 +1270,7 @@ ssize_t dhcpv6_ia_handle_IAs(uint8_t *buf, size_t buflen, struct interface *ifac a->peer = *addr; a->assigned = is_na && l ? l->hostid : reqhint; a->valid_until = now; + a->preferred_until = now; a->dhcp_free_cb = dhcpv6_ia_free_assignment; a->iface = iface; a->flags = (is_pd ? OAF_DHCPV6_PD : OAF_DHCPV6_NA); diff --git a/src/odhcpd.h b/src/odhcpd.h index 2f7dd25..45b6784 100644 --- a/src/odhcpd.h +++ b/src/odhcpd.h @@ -182,6 +182,7 @@ struct dhcp_assignment { struct sockaddr_in6 peer; time_t valid_until; + time_t preferred_until; #define fr_timer reconf_timer struct uloop_timeout reconf_timer; @@ -286,6 +287,7 @@ struct interface { uint32_t ra_retranstime; uint32_t ra_hoplimit; int ra_mtu; + uint32_t preferred_lifetime; // DHCP uint32_t dhcp_leasetime; diff --git a/src/router.c b/src/router.c index 06f3a66..d6ab4bb 100644 --- a/src/router.c +++ b/src/router.c @@ -552,8 +552,8 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr preferred = TIME_LEFT(addr->preferred, now); if (iface->ra_useleasetime && - preferred > iface->dhcp_leasetime) - preferred = iface->dhcp_leasetime; + preferred > iface->preferred_lifetime) + preferred = iface->preferred_lifetime; } valid = TIME_LEFT(addr->valid, now); -- 2.30.2