decode didn't add the date offset from Jan 1 1970 --> Jan 1, 2000.
encode added 30*365*86400, which doesn't account for the fact that
years are ~365.25 days long.
case FR_TYPE_UINT32:
case FR_TYPE_UINT64:
case FR_TYPE_SIZE:
- case FR_TYPE_DATE:
case FR_TYPE_IFID:
case FR_TYPE_ETHERNET:
case FR_TYPE_IPV4_ADDR:
}
break;
+ /*
+ * A standard 32bit integer, but unlike normal UNIX timestamps
+ * starts from the 1st of January 2000.
+ *
+ * In the encoder we subtract 30 years to any values, so
+ * here we need to add that to the time here.
+ */
+ case FR_TYPE_DATE:
+ vp = fr_pair_afrom_da(ctx, parent);
+ if (!vp) return -1;
+
+ if (fr_value_box_from_network(vp, &vp->data, vp->da->type, vp->da, data, data_len, true) < 0) {
+ fr_pair_list_free(&vp);
+ goto raw;
+ }
+ vp->vp_date += ((fr_time_t) DHCPV6_DATE_OFFSET) * NSEC;
+ break;
+
case FR_TYPE_STRUCT:
rcode = fr_struct_from_network(ctx, cursor, parent, data, data_len, &tlv,
decode_value_trampoline, decoder_ctx);
FLAG_ENCODE_PARTIAL_DNS_LABEL, //!< encode as a partial DNS label
};
+/*
+ * DHCPv6 defines dates to start from Jan 1, 2000. Which is
+ * exactly this number of seconds off of the standard Unix time
+ * stamps.
+ */
+#define DHCPV6_DATE_OFFSET (946684800)
+
typedef struct {
fr_dict_attr_t const *root; //!< Root attribute of the dictionary.
} fr_dhcpv6_encode_ctx_t;
* A standard 32bit integer, but unlike normal UNIX timestamps
* starts from the 1st of January 2000.
*
- * In the decoder we add 946,080,000 seconds (30 years) to any
- * values, so here we need to subtract 946,080,000 seconds, or
- * if the value is less than 946,080,000 seconds, just encode
- * a 0x0000000000 value.
+ * In the decoder we add 30 years to any values, so here
+ * we need to subtract that time, or if the value is less
+ * than that time, just encode a 0x0000000000
+ * value.
*/
case FR_TYPE_DATE:
{
uint32_t adj_date;
- fr_time_t date = fr_time_to_sec(vp->vp_date);
+ uint64_t date = fr_time_to_sec(vp->vp_date);
CHECK_FREESPACE(outlen, fr_dhcpv6_option_len(vp));
-
- if (date < 946080000) { /* 30 years */
+ if (date < DHCPV6_DATE_OFFSET) { /* 30 years */
memset(p, 0, sizeof(uint32_t));
p += sizeof(uint32_t);
break;
}
- adj_date = htonl(date - 946080000);
+ adj_date = htonl(date - DHCPV6_DATE_OFFSET);
memcpy(p, &adj_date, sizeof(adj_date));
p += sizeof(adj_date);
}
proto-dictionary dhcpv6
#
-# Date. Like a 32bit unix timestamp but starts from 1st Jan 2000 instead of 1st Jan 1970
+# Date. Like a 32bit unix timestamp but starts from 1st Jan 2000 instead of 1st Jan 2000
#
encode-pair Failover-Expiration-Time = 0
match 00 78 00 04 00 00 00 00
decode-pair -
-match Failover-Expiration-Time = "Jan 1 1970 00:00:00 UTC"
+match Failover-Expiration-Time = "Jan 1 2000 00:00:00 UTC"
+
+#
+# Anything before Jan 1, 2000 gets mashed to "0".
+#
+encode-pair Failover-Expiration-Time = "Jan 1 1999 00:00:00 UTC"
+match 00 78 00 04 00 00 00 00
# Still less than 946080000 (30 years), so still 0 (we can't represent dates earlier than 1st Jan 2000)
encode-pair Failover-Expiration-Time = 500
match 00 78 00 04 00 00 00 00
decode-pair -
-match Failover-Expiration-Time = "Jan 1 1970 00:00:00 UTC"
+match Failover-Expiration-Time = "Jan 1 2000 00:00:00 UTC"
-encode-pair Failover-Expiration-Time = 946080000
+encode-pair Failover-Expiration-Time = 946684800
match 00 78 00 04 00 00 00 00
decode-pair -
-match Failover-Expiration-Time = "Jan 1 1970 00:00:00 UTC"
+match Failover-Expiration-Time = "Jan 1 2000 00:00:00 UTC"
# 1st second of 1st Jan 2000
-encode-pair Failover-Expiration-Time = 946080001
+encode-pair Failover-Expiration-Time = 946684801
match 00 78 00 04 00 00 00 01
decode-pair -
-match Failover-Expiration-Time = "Jan 1 1970 00:00:01 UTC"
+match Failover-Expiration-Time = "Jan 1 2000 00:00:01 UTC"
count
-match 18
+match 20