+/*
+ * Timestamp mechanism
+ *
+ * arguments: <max-skew> <max-age>
+ *
+ * encoding: prepend 4 bytes of UNIX time in network byte order
+ *
+ * <max-age> is maximum age in seconds we will accept a packet (or 0
+ * for any age); <max-skew> is maximum future age in seconds we will
+ * accept a packet (or 0 for any future age).
+ *
+ */
+
+#include <stdint.h>
+#include <netinet/in.h>
+
+#include "mech.h"
+
+struct mechdata {
+ uint32_t max_skew, max_age;
+};
+
+static void mds_timestamp(struct mechdata **md_r) {
+ struct mechdata *md;
+
+ md= xmalloc(sizeof(md));
+
+ md->max_skew= getarg_ulong();
+ md->max_age= getarg_ulong();
+ *md_r= md;
+}
+
+static void mes_timestamp(struct mechdata **md_r, int *maxprefix_io, int *maxsuffix_io) {
+ mds_timestamp(md_r);
+ *maxprefix_io += 4;
+}
+
+static void menc_timestamp(struct mechdata *md, struct buffer *buf) {
+ *(uint32_t*)buf_prepend(buf,4)= htonl(now());
+}
+
+static const char *mdec_timestamp(struct mechdata *md, struct buffer *buf) {
+ static char cbuf[40];
+
+ uint32_t *tp, timestamp, tnow;
+ long age;
+
+ BUF_UNPREPEND(tp,buf,4);
+ timestamp= ntohl(*tp);
+
+ tnow= now();
+ age= timestamp - tnow;
+ if (age > 0) {
+ if (md->max_age && age > md->max_age) {
+ sprintf(cbuf,"packet too old (%lds)",age);
+ return cbuf;
+ }
+ } else if (age < 0) {
+ if (md->max_skew && age > md->max_skew) {
+ sprintf(cbuf,"too much skew (%lds)",-age);
+ return cbuf;
+ }
+ }
+
+ return 0;
+}
+
+STANDARD_MECHANISMLIST("timestamp",timestamp);