[PATCH] odhcpd: add option to use absolute timestamps

Hans Dedecker dedeckeh at gmail.com
Sat Feb 6 15:26:58 EST 2021


On Sat, Jan 30, 2021 at 5:33 PM Nick Hainke <vincent at 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 <vincent at 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 at lists.openwrt.org
> https://lists.openwrt.org/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list