On Sat, Jan 30, 2021 at 5:33 PM Nick Hainke <vinc...@systemli.org> wrote: > > Until now it is not possible to give absolute timestamps in odhcpd. > This means that on every new RA or request, the timestamp is renewed. > Further, the valid and preferred lifetimes are not synced between all > devices. > > There are several usecases when it is needed to have absolute timestamp > that needed to be synced across all devices, e.g. your ISP delegates > you a prefix for some certain time, or you want to change to another > prefix. > > The purpose of having this as a absolute timestamp is to make it easier > to track. An example configuration is > > option absolute_lifetime '1' > option valid_lifetime '05 Jan 2021 23:00:00' > option preferred_lifetime '05 Jan 2021 23:00:00' > > If the valid_lifetime is in the past, the preferred lifetime and valid > lifetime are set to 1 minute. I have my reservations about the patch as it requires knowledge of absolute time on devices. This is a problem as not all devices have a RTC; or the time needs to be synchronized with a wan NTP server. This is also the reason why netifd does not to support absolute lifetimes for configured prefixes
Hans > > Signed-off-by: Nick Hainke <vinc...@systemli.org> > --- > README | 8 ++++-- > src/config.c | 69 ++++++++++++++++++++++++++++++++++--------------- > src/dhcpv6-ia.c | 10 +++++++ > src/odhcpd.h | 1 + > 4 files changed, 65 insertions(+), 23 deletions(-) > > diff --git a/README b/README > index f9cbb11..0af5c75 100644 > --- a/README > +++ b/README > @@ -107,11 +107,13 @@ dns_service bool 1 > Announce the address of interface as DNS service > if the list of dns is > empty > domain list <local search domain> Search domains to > announce > > -leasetime string 12h DHCPv4 address > leasetime > +leasetime string 12h DHCPv4 address > leasetime. If absolute_lifetime is > + set the value can be > given as a date, e.g. "10 Jan 2020 00:00:00". > start integer 100 DHCPv4 pool start > limit integer 150 DHCPv4 pool size > preferred_lifetime string 12h Value for the > preferred lifetime > - for a prefix > + for a prefix. If > absolute_lifetime is set the value can > + be given as a date, > e.g. "10 Jan 2020 00:00:00". > 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 > @@ -145,6 +147,8 @@ ndproxy_slave bool 0 > NDProxy external slave > prefix_filter string ::/0 Only advertise > on-link prefixes within > [IPv6 prefix] the provided IPv6 > prefix; others are > filtered out. > +absolute_lifetime bool 0 Interpret > configured lifetime as > + absolute timestamps. > The format has to be "10 Jan 2020 00:00:00". > > > Sections of type host (static leases) > diff --git a/src/config.c b/src/config.c > index 78b5855..42f73a1 100644 > --- a/src/config.c > +++ b/src/config.c > @@ -8,6 +8,7 @@ > #include <string.h> > #include <sys/stat.h> > #include <syslog.h> > +#include <time.h> > > #include <uci.h> > #include <uci_blob.h> > @@ -83,6 +84,7 @@ enum { > IFACE_ATTR_NDPROXY_SLAVE, > IFACE_ATTR_PREFIX_FILTER, > IFACE_ATTR_PREFERRED_LIFETIME, > + IFACE_ATTR_ABSOLUTE_LIFETIME, > IFACE_ATTR_MAX > }; > > @@ -132,6 +134,7 @@ static const struct blobmsg_policy > iface_attrs[IFACE_ATTR_MAX] = { > [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_ABSOLUTE_LIFETIME] = { .name = "absolute_lifetime", .type > = BLOBMSG_TYPE_BOOL }, > }; > > static const struct uci_blob_param_info iface_attr_info[IFACE_ATTR_MAX] = { > @@ -212,6 +215,7 @@ static void set_interface_defaults(struct interface > *iface) > iface->ra_mininterval = iface->ra_maxinterval/3; > iface->ra_lifetime = -1; > iface->ra_dns = true; > + iface->absolute_lifetime = false; > } > > static void clean_interface(struct interface *iface) > @@ -321,29 +325,48 @@ static void set_config(struct uci_section *s) > } > } > > -static double parse_leasetime(struct blob_attr *c) { > +static double parse_leasetime(struct blob_attr *c, bool absolute) { > char *val = blobmsg_get_string(c), *endptr = NULL; > - double time = strcmp(val, "infinite") ? strtod(val, &endptr) : > UINT32_MAX; > - > - if (time && endptr && endptr[0]) { > - if (endptr[0] == 's') > - time *= 1; > - else if (endptr[0] == 'm') > - time *= 60; > - else if (endptr[0] == 'h') > - time *= 3600; > - else if (endptr[0] == 'd') > - time *= 24 * 3600; > - else if (endptr[0] == 'w') > - time *= 7 * 24 * 3600; > - else > + double ret_time = strcmp(val, "infinite") ? strtod(val, &endptr) : > UINT32_MAX; > + > + if (absolute) > + { > + // "10 Jan 2020 00:00:00" > + // Parse absolut time > + struct tm tm = {0}; > + char *s = strptime(val, "%d %b %Y %H:%M:%S", &tm); > + if (s == NULL) { > + syslog(LOG_ERR, "Failed to Parse Date: %s", val); > goto err; > + } > + > + time_t now = odhcpd_time(); > + time_t wall_time = time(NULL); > + time_t t = mktime(&tm); > + > + double diff = difftime(t,wall_time); > + ret_time += now + diff; > + } else { > + if (ret_time && endptr && endptr[0]) { > + if (endptr[0] == 's') > + ret_time *= 1; > + else if (endptr[0] == 'm') > + ret_time *= 60; > + else if (endptr[0] == 'h') > + ret_time *= 3600; > + else if (endptr[0] == 'd') > + ret_time *= 24 * 3600; > + else if (endptr[0] == 'w') > + ret_time *= 7 * 24 * 3600; > + else > + goto err; > + } > } > > - if (time < 60) > - time = 60; > + if (ret_time < 60) > + ret_time = 60; > > - return time; > + return ret_time; > > err: > return -1; > @@ -409,7 +432,7 @@ int set_lease_from_blobmsg(struct blob_attr *ba) > } > > if ((c = tb[LEASE_ATTR_LEASETIME])) { > - double time = parse_leasetime(c); > + double time = parse_leasetime(c, false); // do not support > absolute timestamps for now > if (time < 0) > goto err; > > @@ -520,8 +543,12 @@ int config_parse_interface(void *data, size_t len, const > char *name, bool overwr > if ((c = tb[IFACE_ATTR_DYNAMICDHCP])) > iface->no_dynamic_dhcp = !blobmsg_get_bool(c); > > + > + if ((c = tb[IFACE_ATTR_ABSOLUTE_LIFETIME])) > + iface->absolute_lifetime = blobmsg_get_bool(c); > + > if ((c = tb[IFACE_ATTR_LEASETIME])) { > - double time = parse_leasetime(c); > + double time = parse_leasetime(c, iface->absolute_lifetime); > if (time < 0) > goto err; > > @@ -529,7 +556,7 @@ int config_parse_interface(void *data, size_t len, const > char *name, bool overwr > } > > if ((c = tb[IFACE_ATTR_PREFERRED_LIFETIME])) { > - double time = parse_leasetime(c); > + double time = parse_leasetime(c, iface->absolute_lifetime); > if (time < 0) > goto err; > > diff --git a/src/dhcpv6-ia.c b/src/dhcpv6-ia.c > index a59fc20..78be8b8 100644 > --- a/src/dhcpv6-ia.c > +++ b/src/dhcpv6-ia.c > @@ -865,6 +865,16 @@ static size_t build_ia(uint8_t *buf, size_t buflen, > uint16_t status, > if (prefix_valid > leasetime) > prefix_valid = leasetime; > > + if (iface->absolute_lifetime) { > + if ((long int) iface->dhcp_leasetime > now) { > + prefix_valid = iface->dhcp_leasetime > - now; > + prefix_pref = > iface->preferred_lifetime - now; > + } else { // if we have a timestamp in the > past set pref and valid to 60s > + prefix_valid = 60; > + prefix_pref = 60; > + } > + } > + > if (a->flags & OAF_DHCPV6_PD) { > struct dhcpv6_ia_prefix o_ia_p = { > .type = htons(DHCPV6_OPT_IA_PREFIX), > diff --git a/src/odhcpd.h b/src/odhcpd.h > index 45b6784..98673a8 100644 > --- a/src/odhcpd.h > +++ b/src/odhcpd.h > @@ -288,6 +288,7 @@ struct interface { > uint32_t ra_hoplimit; > int ra_mtu; > uint32_t preferred_lifetime; > + bool absolute_lifetime; > > // DHCP > uint32_t dhcp_leasetime; > -- > 2.30.0 > > > _______________________________________________ > openwrt-devel mailing list > openwrt-devel@lists.openwrt.org > https://lists.openwrt.org/mailman/listinfo/openwrt-devel _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel