From: Harlan Stenn Date: Sat, 27 Jun 2015 19:25:39 +0000 (+0000) Subject: [Bug 2859] Improve raw DCF77 robustness deconding. Frank Kardel. X-Git-Tag: NTP_4_3_48~2^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b6a358c34d0c2f0d2050d5ee12d2d3d2c13dc546;p=thirdparty%2Fntp.git [Bug 2859] Improve raw DCF77 robustness deconding. Frank Kardel. bk: 558ef8b3cYRlfs-BrLdtD7AaWgTLmw --- diff --git a/ChangeLog b/ChangeLog index 33792dbd6..9319f44e8 100644 --- 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 * [Bug 2855] Parser fix for conditional leap smear code. Harlan Stenn. diff --git a/include/parse.h b/include/parse.h index ca6855d18..9b1ffb227 100644 --- a/include/parse.h +++ b/include/parse.h @@ -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 ntp.org> + * Copyright (c) 1995-2015 by Frank Kardel 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) diff --git a/libparse/clk_meinberg.c b/libparse/clk_meinberg.c index 4047be5e7..9d2b67638 100644 --- a/libparse/clk_meinberg.c +++ b/libparse/clk_meinberg.c @@ -5,7 +5,7 @@ * * Meinberg clock support * - * Copyright (c) 1995-2005 by Frank Kardel ntp.org> + * Copyright (c) 1995-2015 by Frank Kardel 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 - diff --git a/libparse/clk_rawdcf.c b/libparse/clk_rawdcf.c index 2f2afdf94..ca4326336 100644 --- a/libparse/clk_rawdcf.c +++ b/libparse/clk_rawdcf.c @@ -5,7 +5,7 @@ * * Raw DCF77 pulse clock support * - * Copyright (c) 1995-2006 by Frank Kardel ntp.org> + * Copyright (c) 1995-2015 by Frank Kardel 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 diff --git a/libparse/clk_schmid.c b/libparse/clk_schmid.c index 5e303b94c..c4f02b07a 100644 --- a/libparse/clk_schmid.c +++ b/libparse/clk_schmid.c @@ -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 ntp.org> + * Copyright (c) 1995-2015 by Frank Kardel 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; } diff --git a/ntpd/refclock_parse.c b/ntpd/refclock_parse.c index 6801f6209..147a46223 100644 --- a/ntpd/refclock_parse.c +++ b/ntpd/refclock_parse.c @@ -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 ntp.org> + * Copyright (c) 1995-2015 by Frank Kardel 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; } diff --git a/parseutil/dcfd.c b/parseutil/dcfd.c index 652b375f7..969c1e386 100644 --- a/parseutil/dcfd.c +++ b/parseutil/dcfd.c @@ -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 ntp.org> + * Copyright (c) 1995-2015 by Frank Kardel 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 diff --git a/parseutil/testdcf.c b/parseutil/testdcf.c index 00bf05937..e876c4406 100644 --- a/parseutil/testdcf.c +++ b/parseutil/testdcf.c @@ -5,7 +5,7 @@ * * simple DCF77 100/200ms pulse test program (via 50Baud serial line) * - * Copyright (c) 1995-2005 by Frank Kardel ntp.org> + * Copyright (c) 1995-2015 by Frank Kardel 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