]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 2859] Improve raw DCF77 robustness deconding. Frank Kardel.
authorHarlan Stenn <stenn@ntp.org>
Sat, 27 Jun 2015 19:25:39 +0000 (19:25 +0000)
committerHarlan Stenn <stenn@ntp.org>
Sat, 27 Jun 2015 19:25:39 +0000 (19:25 +0000)
bk: 558ef8b3cYRlfs-BrLdtD7AaWgTLmw

ChangeLog
include/parse.h
libparse/clk_meinberg.c
libparse/clk_rawdcf.c
libparse/clk_schmid.c
ntpd/refclock_parse.c
parseutil/dcfd.c
parseutil/testdcf.c

index 33792dbd693e6c5d4ba8f7765d7a7a5ed6c3e3cd..9319f44e81d9d88cedacc1e3165c3d28979d5d2a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,8 @@
 ---
+
+* [Bug 1060] Buffer overruns in libparse/clk_rawdcf.c.  Helge Oldach.
+* [Bug 2859] Improve raw DCF77 robustness deconding.  Frank Kardel.
+---
 (4.2.8p3-RC3) 2015/06/27 Released by Harlan Stenn <stenn@ntp.org>
 
 * [Bug 2855] Parser fix for conditional leap smear code.  Harlan Stenn.
index ca6855d18e58579b4251909e54ac0b37f26f82c3..9b1ffb2274255192726065f760493e602f8ec19f 100644 (file)
@@ -3,7 +3,7 @@
  *
  * parse.h,v 4.12 2007/01/14 08:36:03 kardel RELEASE_20070114_A
  *
- * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org>
+ * Copyright (c) 1995-2015 by Frank Kardel <kardel <AT> ntp.org>
  * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany
  *
  * Redistribution and use in source and binary forms, with or without
@@ -141,7 +141,7 @@ extern unsigned int splclock (void);
  * feature information
  */
 #define PARSEB_S_LEAP            0x00010000 /* supports LEAP */
-#define PARSEB_S_ANTENNA         0x00020000 /* supports antenna information */
+#define PARSEB_S_CALLBIT         0x00020000 /* supports callbit information */
 #define PARSEB_S_PPS             0x00040000 /* supports PPS time stamping */
 #define PARSEB_S_POSITION        0x00080000 /* supports position information (GPS) */
 
@@ -167,7 +167,7 @@ extern unsigned int splclock (void);
 #define PARSE_LEAPSECOND(x)    (PARSE_SYNC(x) && ((x) & PARSEB_LEAP_SECOND))
 
 #define PARSE_S_LEAP(x)                ((x) & PARSEB_S_LEAP)
-#define PARSE_S_ANTENNA(x)     ((x) & PARSEB_S_ANTENNA)
+#define PARSE_S_CALLBIT(x)     ((x) & PARSEB_S_CALLBIT)
 #define PARSE_S_PPS(x)         ((x) & PARSEB_S_PPS)
 #define PARSE_S_POSITION(x)    ((x) & PARSEB_S_POSITION)
 
index 4047be5e7314fd4d268fa801405299b2de0195b7..9d2b676381c6978a44532ab35f5ad2802557536b 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Meinberg clock support
  *
- * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org>
+ * Copyright (c) 1995-2015 by Frank Kardel <kardel <AT> ntp.org>
  * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany
  *
  * Redistribution and use in source and binary forms, with or without
@@ -400,7 +400,7 @@ cvt_meinberg(
 
                if (format->flags & MBG_EXTENDED)
                {
-                       clock_time->flags |= PARSEB_S_ANTENNA;
+                       clock_time->flags |= PARSEB_S_CALLBIT;
 
                        /*
                         * DCF77 does not encode the direction -
index 2f2afdf941a2093d07c706039d9fbd5f4ccac142..ca4326336f8817771aac6b479699ce682da3f05d 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Raw DCF77 pulse clock support
  *
- * Copyright (c) 1995-2006 by Frank Kardel <kardel <AT> ntp.org>
+ * Copyright (c) 1995-2015 by Frank Kardel <kardel <AT> ntp.org>
  * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany
  *
  * Redistribution and use in source and binary forms, with or without
@@ -41,6 +41,7 @@
 #if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_RAWDCF)
 
 #include "ntp_fp.h"
+#include "timevalops.h"
 #include "ntp_unixtime.h"
 #include "ntp_calendar.h"
 
@@ -107,7 +108,9 @@ static parse_cvt_fnc_t cvt_rawdcf;
 static parse_inp_fnc_t inp_rawdcf;
 
 typedef struct last_tcode {
-       time_t tcode;   /* last converted time code */
+       time_t      tcode;      /* last converted time code */
+        timestamp_t tminute;   /* sample time for minute start */
+        timestamp_t timeout;   /* last timeout timestamp */
 } last_tcode_t;
 
 #define BUFFER_MAX     61
@@ -230,7 +233,7 @@ convert_rawdcf(
        const unsigned char *c = dcfprm->zerobits;
        int i;
 
-       parseprintf(DD_RAWDCF,("parse: convert_rawdcf: \"%s\"\n", buffer));
+       parseprintf(DD_RAWDCF,("parse: convert_rawdcf: \"%.*s\"\n", size, buffer));
 
        if (size < 57)
        {
@@ -270,7 +273,7 @@ convert_rawdcf(
                 */
                parseprintf(DD_RAWDCF,("parse: convert_rawdcf: parity check passed\n"));
 
-               clock_time->flags  = PARSEB_S_ANTENNA|PARSEB_S_LEAP;
+               clock_time->flags  = PARSEB_S_CALLBIT|PARSEB_S_LEAP;
                clock_time->utctime= 0;
                clock_time->usecond= 0;
                clock_time->second = 0;
@@ -310,7 +313,7 @@ convert_rawdcf(
                if (ext_bf(buffer, DCF_R, dcfprm->zerobits))
                    clock_time->flags |= PARSEB_CALLBIT;
 
-               parseprintf(DD_RAWDCF,("parse: convert_rawdcf: TIME CODE OK: %d:%d, %d.%d.%d, flags 0x%lx\n",
+               parseprintf(DD_RAWDCF,("parse: convert_rawdcf: TIME CODE OK: %02d:%02d, %02d.%02d.%02d, flags 0x%lx\n",
                                       (int)clock_time->hour, (int)clock_time->minute, (int)clock_time->day, (int)clock_time->month,(int) clock_time->year,
                                       (u_long)clock_time->flags));
                return CVT_OK;
@@ -321,7 +324,7 @@ convert_rawdcf(
                 * bad format - not for us
                 */
 #ifndef PARSEKERNEL
-               msyslog(LOG_ERR, "parse: convert_rawdcf: start bit / parity check FAILED for \"%s\"", buffer);
+               msyslog(LOG_ERR, "parse: convert_rawdcf: start bit / parity check FAILED for \"%.*s\"", size, buffer);
 #endif
                return CVT_FAIL|CVT_BADFMT;
        }
@@ -484,6 +487,8 @@ cvt_rawdcf(
                if (*c) c++;
        }
 
+       *s = '\0';
+
         if (rtc == CVT_NONE)
         {
               rtc = convert_rawdcf(buffer, size, &dcfparameter, clock_time);
@@ -494,14 +499,14 @@ cvt_rawdcf(
                        newtime = parse_to_unixtime(clock_time, &rtc);
                        if ((rtc == CVT_OK) && t)
                        {
-                               if ((newtime - t->tcode) == 60) /* guard against multi bit errors */
+                               if ((newtime - t->tcode) <= 600) /* require a successful telegram within last 10 minutes */
                                {
-                                       parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: minute delta check OK\n"));
+                                       parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: recent timestamp check OK\n"));
                                        clock_time->utctime = newtime;
                                }
                                else
                                {
-                                       parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: minute delta check FAIL - ignore timestamp\n"));
+                                       parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: recent timestamp check FAIL - ignore timestamp\n"));
                                        rtc = CVT_SKIP;
                                }
                                t->tcode            = newtime;
@@ -535,13 +540,63 @@ pps_rawdcf(
        return CVT_NONE;
 }
 
+static long
+calc_usecdiff(
+       timestamp_t *ref,
+       timestamp_t *base,
+       long         offset
+       )
+{
+       struct timeval delta;
+       long delta_usec = 0;
+
+#ifdef PARSEKERNEL
+       delta.tv_sec = ref->tv.tv_sec - offset - base->tv.tv_sec;
+       delta.tv_usec = ref->tv.tv_usec - base->tv.tv_usec;
+       if (delta.tv_usec < 0)
+       {
+               delta.tv_sec  -= 1;
+               delta.tv_usec += 1000000;
+       }
+#else
+       l_fp delt;
+       
+       delt = ref->fp;
+       delt.l_i -= offset;
+       L_SUB(&delt, &base->fp);
+       TSTOTV(&delt, &delta);
+#endif
+
+       delta_usec = 1000000 * (int32_t)delta.tv_sec + delta.tv_usec;
+       return delta_usec;
+}
+
 static u_long
 snt_rawdcf(
        parse_t *parseio,
        timestamp_t *ptime
        )
 {
-       if ((parseio->parse_dtime.parse_status & CVT_MASK) == CVT_OK)
+       /*
+        * only synthesize if all of following conditions are met:
+        * - CVT_OK parse_status (we have a time stamp base)
+        * - ABS(ptime - tminute - (parse_index - 1) sec) < 500ms (spaced by 1 sec +- 500ms)
+        * - minute marker is available (confirms minute raster as base)
+        */
+       last_tcode_t  *t = (last_tcode_t *)parseio->parse_pdata;
+       long delta_usec = -1;
+
+       if (t != NULL && t->tminute.tv.tv_sec != 0) {
+               delta_usec = calc_usecdiff(ptime, &t->tminute, parseio->parse_index - 1);
+               if (delta_usec < 0)
+                       delta_usec = -delta_usec;
+       }
+       
+       parseprintf(DD_RAWDCF,("parse: snt_rawdcf: synth for offset %d seconds - absolute usec error %ld\n",
+                              parseio->parse_index - 1, delta_usec));
+
+       if (((parseio->parse_dtime.parse_status & CVT_MASK) == CVT_OK) &&
+           (delta_usec < 500000 && delta_usec >= 0)) /* only if minute marker is available */
        {
                parseio->parse_dtime.parse_stime = *ptime;
 
@@ -578,10 +633,43 @@ inp_rawdcf(
 
        if (parse_timedout(parseio, tstamp, &timeout))
        {
-               parseprintf(DD_PARSE, ("inp_rawdcf: time out seen\n"));
-
+               last_tcode_t *t = (last_tcode_t *)parseio->parse_pdata;
+               long delta_usec;
+               
+               parseprintf(DD_RAWDCF, ("inp_rawdcf: time out seen\n"));
+               /* finish collection */
                (void) parse_end(parseio);
+
+               if (t != NULL)
+               {
+                       /* remember minute start sample time if timeouts occur in minute raster */
+                       if (t->timeout.tv.tv_sec != 0)
+                       {
+                               delta_usec = calc_usecdiff(tstamp, &t->timeout, 60);
+                               if (delta_usec < 0)
+                                       delta_usec = -delta_usec;
+                       }
+                       else
+                       {
+                               delta_usec = -1;
+                       }
+
+                       if (delta_usec < 500000 && delta_usec >= 0)
+                       {
+                               parseprintf(DD_RAWDCF, ("inp_rawdcf: timeout time difference %ld usec - minute marker set\n", delta_usec));
+                               /* collect minute markers only if spaced by 60 seconds */
+                               t->tminute = *tstamp;
+                       }
+                       else
+                       {
+                               parseprintf(DD_RAWDCF, ("inp_rawdcf: timeout time difference %ld usec - minute marker cleared\n", delta_usec));
+                               memset((char *)&t->tminute, 0, sizeof(t->tminute));
+                       }
+                       t->timeout = *tstamp;
+               }
                (void) parse_addchar(parseio, ch);
+
+               /* pass up to higher layers */
                return PARSE_INP_TIME;
        }
        else
index 5e303b94c29a0ef06fd44dcee7ff9a0537d4af30..c4f02b07ad13ff72f87f62b2976e0f75a2fad3dc 100644 (file)
@@ -6,7 +6,7 @@
  * Schmid clock support
  * based on information and testing from Adam W. Feigin et. al (Swisstime iis.ethz.ch)
  *
- * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org>
+ * Copyright (c) 1995-2015 by Frank Kardel <kardel <AT> ntp.org>
  * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany
  *
  * Redistribution and use in source and binary forms, with or without
@@ -184,7 +184,7 @@ cvt_schmid(
                                    }
                            }
 
-                           clock_time->flags |= PARSEB_S_LEAP|PARSEB_S_ANTENNA;
+                           clock_time->flags |= PARSEB_S_LEAP|PARSEB_S_CALLBIT;
 
                            return CVT_OK;
                    }
index 6801f6209b48d14e46917507436a65a3213a861a..147a462231dd8def5cd6dbdb58be6484a950f726 100644 (file)
@@ -15,7 +15,7 @@
  *   Currently the STREAMS module is only available for Suns running
  *   SunOS 4.x and SunOS5.x.
  *
- * Copyright (c) 1995-2009 by Frank Kardel <kardel <AT> ntp.org>
+ * Copyright (c) 1995-2015 by Frank Kardel <kardel <AT> ntp.org>
  * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany
  *
  * Redistribution and use in source and binary forms, with or without
@@ -2540,7 +2540,7 @@ parsestate(
          {
                  { PARSEB_S_LEAP,     "LEAP INDICATION" },
                  { PARSEB_S_PPS,      "PPS SIGNAL" },
-                 { PARSEB_S_ANTENNA,  "ANTENNA" },
+                 { PARSEB_S_CALLBIT,  "CALLBIT" },
                  { PARSEB_S_POSITION, "POSITION" },
                  { 0,                 NULL }
          };
@@ -2562,7 +2562,7 @@ parsestate(
                i++;
        }
 
-       if (lstate & (PARSEB_S_LEAP|PARSEB_S_ANTENNA|PARSEB_S_PPS|PARSEB_S_POSITION))
+       if (lstate & (PARSEB_S_LEAP|PARSEB_S_CALLBIT|PARSEB_S_PPS|PARSEB_S_POSITION))
        {
                if (s != t)
                        t = ap(buffer, size, t, "; ");
@@ -2998,7 +2998,7 @@ parse_start(
        if (!notice)
         {
                NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
-                       msyslog(LOG_INFO, "NTP PARSE support: Copyright (c) 1989-2009, Frank Kardel");
+                       msyslog(LOG_INFO, "NTP PARSE support: Copyright (c) 1989-2015, Frank Kardel");
                notice = 1;
        }
 
index 652b375f78d7382550b5259b89fa8153c7500670..969c1e3863c73ce74da4dc1f3b7dca792eb41d64 100644 (file)
@@ -13,7 +13,7 @@
  * Lacks:
  *  Leap second handling (at that level you should switch to NTP Version 4 - really!)
  *
- * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org>
+ * Copyright (c) 1995-2015 by Frank Kardel <kardel <AT> ntp.org>
  * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany
  *
  * Redistribution and use in source and binary forms, with or without
index 00bf05937fabbca574ec3d86b39d7d228d195f44..e876c4406dbfb116e7484875d6ca0254521b20b0 100644 (file)
@@ -5,7 +5,7 @@
  *
  * simple DCF77 100/200ms pulse test program (via 50Baud serial line)
  *
- * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org>
+ * Copyright (c) 1995-2015 by Frank Kardel <kardel <AT> ntp.org>
  * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany
  *
  * Redistribution and use in source and binary forms, with or without