1 /*        $NetBSD: refclock_nmea.c,v 1.15 2024/08/18 20:47:18 christos Exp $    */
2 
3 /*
4  * refclock_nmea.c - clock driver for an NMEA GPS CLOCK
5  *                  Michael Petry Jun 20, 1994
6  *                   based on refclock_heathn.c
7  *
8  * Updated to add support for Accord GPS Clock
9  *                  Venu Gopal Dec 05, 2007
10  *                  neo.venu@gmail.com, venugopal_d@pgad.gov.in
11  *
12  * Updated to process 'time1' fudge factor
13  *                  Venu Gopal May 05, 2008
14  *
15  * Converted to common PPSAPI code, separate PPS fudge time1
16  * from serial timecode fudge time2.
17  *                  Dave Hart July 1, 2009
18  *                  hart@ntp.org, davehart@davehart.com
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 
25 #include "ntp_types.h"
26 
27 #if defined(REFCLOCK) && defined(CLOCK_NMEA)
28 
29 #define NMEA_WRITE_SUPPORT 0 /* no write support at the moment */
30 
31 #include <sys/stat.h>
32 #include <stdio.h>
33 #include <ctype.h>
34 #ifdef HAVE_SYS_SOCKET_H
35 #include <sys/socket.h>
36 #endif
37 
38 #include "ntpd.h"
39 #include "ntp_io.h"
40 #include "ntp_unixtime.h"
41 #include "ntp_refclock.h"
42 #include "ntp_stdlib.h"
43 #include "ntp_calgps.h"
44 #include "timespecops.h"
45 
46 #ifdef HAVE_PPSAPI
47 # include "ppsapi_timepps.h"
48 # include "refclock_atom.h"
49 #endif /* HAVE_PPSAPI */
50 
51 
52 /*
53  * This driver supports NMEA-compatible GPS receivers
54  *
55  * Prototype was refclock_trak.c, Thanks a lot.
56  *
57  * The receiver used spits out the NMEA sentences for boat navigation.
58  * And you thought it was an information superhighway.      Try a raging river
59  * filled with rapids and whirlpools that rip away your data and warp time.
60  *
61  * If HAVE_PPSAPI is defined code to use the PPSAPI will be compiled in.
62  * On startup if initialization of the PPSAPI fails, it will fall back
63  * to the "normal" timestamps.
64  *
65  * The PPSAPI part of the driver understands fudge flag2 and flag3. If
66  * flag2 is set, it will use the clear edge of the pulse. If flag3 is
67  * set, kernel hardpps is enabled.
68  *
69  * GPS sentences other than RMC (the default) may be enabled by setting
70  * the relevent bits of 'mode' in the server configuration line
71  * server 127.127.20.x mode X
72  *
73  * bit 0 - enables RMC (1)
74  * bit 1 - enables GGA (2)
75  * bit 2 - enables GLL (4)
76  * bit 3 - enables ZDA (8) - Standard Time & Date
77  * bit 3 - enables ZDG (8) - Accord GPS Clock's custom sentence with GPS time
78  *                                 very close to standard ZDA
79  *
80  * Multiple sentences may be selected except when ZDG/ZDA is selected.
81  *
82  * bit 4/5/6 - selects the baudrate for serial port :
83  *                  0 for 4800 (default)
84  *                  1 for 9600
85  *                  2 for 19200
86  *                  3 for 38400
87  *                  4 for 57600
88  *                  5 for 115200
89  */
90 #define NMEA_MESSAGE_MASK     0x0000FF0FU
91 #define NMEA_BAUDRATE_MASK    0x00000070U
92 #define NMEA_BAUDRATE_SHIFT   4
93 
94 #define NMEA_DELAYMEAS_MASK   0x00000080U
95 #define NMEA_EXTLOG_MASK      0x00010000U
96 #define NMEA_QUIETPPS_MASK    0x00020000U
97 #define NMEA_DATETRUST_MASK   0x00040000U
98 #define NMEA_IGNSTATUS_MASK   0x00080000U
99 
100 #define NMEA_PROTO_IDLEN      4         /* tag name must be at least 4 chars */
101 #define NMEA_PROTO_MINLEN     6         /* min chars in sentence, excluding CS */
102 #define NMEA_PROTO_MAXLEN     80        /* max chars in sentence, excluding CS */
103 #define NMEA_PROTO_FIELDS     32        /* not official; limit on fields per record */
104 
105 /*
106  * We check the timecode format and decode its contents.  We only care
107  * about a few of them, the most important being the $GPRMC format:
108  *
109  * $GPRMC,hhmmss,a,fddmm.xx,n,dddmmm.xx,w,zz.z,yyy.,ddmmyy,dd,v*CC
110  *
111  * mode (0,1,2,3) selects sentence ANY/ALL, RMC, GGA, GLL, ZDA
112  * $GPGLL,3513.8385,S,14900.7851,E,232420.594,A*21
113  * $GPGGA,232420.59,3513.8385,S,14900.7851,E,1,05,3.4,00519,M,,,,*3F
114  * $GPRMC,232418.19,A,3513.8386,S,14900.7853,E,00.0,000.0,121199,12.,E*77
115  *
116  * Defining GPZDA to support Standard Time & Date
117  * sentence. The sentence has the following format
118  *
119  *  $--ZDA,HHMMSS.SS,DD,MM,YYYY,TH,TM,*CS<CR><LF>
120  *
121  *  Apart from the familiar fields,
122  *  'TH'    Time zone Hours
123  *  'TM'    Time zone Minutes
124  *
125  * Defining GPZDG to support Accord GPS Clock's custom NMEA
126  * sentence. The sentence has the following format
127  *
128  *  $GPZDG,HHMMSS.S,DD,MM,YYYY,AA.BB,V*CS<CR><LF>
129  *
130  *  It contains the GPS timestamp valid for next PPS pulse.
131  *  Apart from the familiar fields,
132  *  'AA.BB' denotes the signal strength( should be < 05.00 )
133  *  'V'       denotes the GPS sync status :
134  *           '0' indicates INVALID time,
135  *           '1' indicates accuracy of +/-20 ms
136  *           '2' indicates accuracy of +/-100 ns
137  *
138  * Defining PGRMF for Garmin GPS Fix Data
139  * $PGRMF,WN,WS,DATE,TIME,LS,LAT,LAT_DIR,LON,LON_DIR,MODE,FIX,SPD,DIR,PDOP,TDOP
140  * WN  -- GPS week number (weeks since 1980-01-06, mod 1024)
141  * WS  -- GPS seconds in week
142  * LS  -- GPS leap seconds, accumulated ( UTC + LS == GPS )
143  * FIX -- Fix type: 0=nofix, 1=2D, 2=3D
144  * DATE/TIME are standard date/time strings in UTC time scale
145  *
146  * The GPS time can be used to get the full century for the truncated
147  * date spec.
148  */
149 
150 /*
151  * Definitions
152  */
153 #define   DEVICE              "/dev/gps%d"        /* GPS serial device */
154 #define   PPSDEV              "/dev/gpspps%d"     /* PPSAPI device override */
155 #define   SPEED232  B4800     /* uart speed (4800 bps) */
156 #define   PRECISION (-9)      /* precision assumed (about 2 ms) */
157 #define   PPS_PRECISION       (-20)     /* precision assumed (about 1 us) */
158 #define   DATE_HOLD 16        /* seconds to hold on provided GPS date */
159 #define   DATE_HLIM 4         /* when do we take ANY date format */
160 #define   REFID               "GPS\0"   /* reference id */
161 #define   DESCRIPTION         "NMEA GPS Clock" /* who we are */
162 #ifndef O_NOCTTY
163 #define M_NOCTTY    0
164 #else
165 #define M_NOCTTY    O_NOCTTY
166 #endif
167 #ifndef O_NONBLOCK
168 #define M_NONBLOCK  0
169 #else
170 #define M_NONBLOCK  O_NONBLOCK
171 #endif
172 #define PPSOPENMODE (O_RDWR | M_NOCTTY | M_NONBLOCK)
173 
174 /* NMEA sentence array indexes for those we use */
175 #define NMEA_GPRMC  0         /* recommended min. nav. */
176 #define NMEA_GPGGA  1         /* fix and quality */
177 #define NMEA_GPGLL  2         /* geo. lat/long */
178 #define NMEA_GPZDA  3         /* date/time */
179 /*
180  * $GPZDG is a proprietary sentence that violates the spec, by not
181  * using $P and an assigned company identifier to prefix the sentence
182  * identifier.      When used with this driver, the system needs to be
183  * isolated from other NTP networks, as it operates in GPS time, not
184  * UTC as is much more common.          GPS time is >15 seconds different from
185  * UTC due to not respecting leap seconds since 1970 or so.  Other
186  * than the different timebase, $GPZDG is similar to $GPZDA.
187  */
188 #define NMEA_GPZDG  4
189 #define NMEA_PGRMF  5
190 #define NMEA_PUBX04 6
191 #define NMEA_ARRAY_SIZE (NMEA_PUBX04 + 1)
192 
193 /*
194  * Sentence selection mode bits
195  */
196 #define USE_GPRMC             0x00000001u
197 #define USE_GPGGA             0x00000002u
198 #define USE_GPGLL             0x00000004u
199 #define USE_GPZDA             0x00000008u
200 #define USE_PGRMF             0x00000100u
201 #define USE_PUBX04            0x00000200u
202 
203 /* mapping from sentence index to controlling mode bit */
204 static const u_int32 sentence_mode[NMEA_ARRAY_SIZE] =
205 {
206           USE_GPRMC,
207           USE_GPGGA,
208           USE_GPGLL,
209           USE_GPZDA,
210           USE_GPZDA,
211           USE_PGRMF,
212           USE_PUBX04
213 };
214 
215 /* date formats we support */
216 enum date_fmt {
217           DATE_1_DDMMYY,      /* use 1 field      with 2-digit year */
218           DATE_3_DDMMYYYY     /* use 3 fields with 4-digit year */
219 };
220 
221 /* date type */
222 enum date_type {
223           DTYP_NONE,
224           DTYP_Y2D, /* 2-digit year */
225           DTYP_W10B,          /* 10-bit week in GPS epoch */
226           DTYP_Y4D, /* 4-digit (full) year */
227           DTYP_WEXT /* extended week in GPS epoch */
228 };
229 
230 /* results for 'field_init()'
231  *
232  * Note: If a checksum is present, the checksum test must pass OK or the
233  * sentence is tagged invalid.
234  */
235 #define CHECK_EMPTY  -1       /* no data                              */
236 #define CHECK_INVALID 0       /* not a valid NMEA sentence  */
237 #define CHECK_VALID   1       /* valid but without checksum */
238 #define CHECK_CSVALID 2       /* valid with checksum OK     */
239 
240 /*
241  * Unit control structure
242  */
243 struct refclock_atom;
244 typedef struct refclock_atom TAtomUnit;
245 typedef struct {
246 #   ifdef HAVE_PPSAPI
247           TAtomUnit atom;               /* PPSAPI structure */
248           int                 ppsapi_fd;          /* fd used with PPSAPI */
249           u_char              ppsapi_tried;       /* attempt PPSAPI once */
250           u_char              ppsapi_lit;         /* time_pps_create() worked */
251 #   endif /* HAVE_PPSAPI */
252           uint16_t  rcvtout;  /* one-shot for sample expiration */
253           u_char              ppsapi_gate;        /* system is on PPS */
254           u_char    gps_time; /* use GPS time, not UTC */
255           l_fp                last_reftime;       /* last processed reference stamp */
256           TNtpDatum last_gpsdate;       /* last processed split date/time */
257           u_short             hold_gpsdate;       /* validity ticker for above */
258           u_short             type_gpsdate;       /* date info type for above */
259           /* tally stats, reset each poll cycle */
260           struct
261           {
262                     u_int total;
263                     u_int accepted;
264                     u_int rejected;   /* GPS said not enough signal */
265                     u_int malformed;  /* Bad checksum, invalid date or time */
266                     u_int filtered;   /* mode bits, not GPZDG, same second */
267                     u_int pps_used;
268           }
269                     tally;
270           /* per sentence checksum seen flag */
271           u_char              cksum_type[NMEA_ARRAY_SIZE];
272 
273           /* line assembly buffer (NMEAD support) */
274           u_short   lb_len;
275           char      lb_buf[BMAX];       /* assembly buffer */
276 } nmea_unit;
277 
278 /*
279  * helper for faster field access
280  */
281 typedef struct {
282           char  *base;        /* buffer base                */
283           char  *cptr;        /* current field ptr          */
284           int    blen;        /* buffer length    */
285           int    cidx;        /* current field index        */
286 } nmea_data;
287 
288 /*
289  * Function prototypes
290  */
291 static    int       nmea_start          (int, struct peer *);
292 static    void      nmea_shutdown       (int, struct peer *);
293 static    void      nmea_receive        (struct recvbuf *);
294 static    void      nmea_poll (int, struct peer *);
295 static    void      nmea_procrec        (struct peer * const, l_fp);
296 #ifdef HAVE_PPSAPI
297 static    double    tabsdiffd (l_fp, l_fp);
298 static    void      nmea_control        (int, const struct refclockstat *,
299                                          struct refclockstat *, struct peer *);
300 #define             NMEA_CONTROL        nmea_control
301 #else
302 #define             NMEA_CONTROL        noentry
303 #endif /* HAVE_PPSAPI */
304 static    void      nmea_timer          (int, struct peer *);
305 
306 /* parsing helpers */
307 static int          field_init          (nmea_data * data, char * cp, int len);
308 static char *       field_parse         (nmea_data * data, int fn);
309 static void         field_wipe          (nmea_data * data, ...);
310 static u_char       parse_qual          (nmea_data * data, int idx,
311                                          char tag, int inv);
312 static int          parse_time          (TCivilDate * jd, l_fp * fofs,
313                                          nmea_data *, int idx);
314 static int          parse_date          (TCivilDate * jd, nmea_data *,
315                                          int idx, enum date_fmt fmt);
316 static int          parse_gpsw          (TGpsDatum *, nmea_data *,
317                                          int weekidx, int timeidx, int leapidx);
318 
319 static int          nmead_open          (const char * device);
320 
321 /*
322  * If we want the driver to output sentences, too: re-enable the send
323  * support functions by defining NMEA_WRITE_SUPPORT to non-zero...
324  */
325 #if NMEA_WRITE_SUPPORT
326 static    void gps_send(int, const char *, struct peer *);
327 #endif /* NMEA_WRITE_SUPPORT */
328 
329 /*
330  * -------------------------------------------------------------------
331  * Transfer vector
332  * -------------------------------------------------------------------
333  */
334 struct refclock refclock_nmea = {
335           nmea_start,                   /* start up driver */
336           nmea_shutdown,                /* shut down driver */
337           nmea_poll,                    /* transmit poll message */
338           NMEA_CONTROL,                 /* fudge control */
339           noentry,            /* initialize driver */
340           noentry,            /* buginfo */
341           nmea_timer                    /* called once per second */
342 };
343 
344 
345 /*
346  * -------------------------------------------------------------------
347  * nmea_start - open the GPS devices and initialize data for processing
348  *
349  * return 0 on error, 1 on success. Even on error the peer structures
350  * must be in a state that permits 'nmea_shutdown()' to clean up all
351  * resources, because it will be called immediately to do so.
352  * -------------------------------------------------------------------
353  */
354 static int
nmea_start(int unit,struct peer * peer)355 nmea_start(
356           int                 unit,
357           struct peer *       peer
358           )
359 {
360           struct refclockproc * const   pp = peer->procptr;
361           nmea_unit * const             up = emalloc_zero(sizeof(*up));
362           char                                    device[20];
363           size_t                                  devlen;
364           u_int32                                 rate;
365           int                                     baudrate;
366 
367           /* Get baudrate choice from mode byte bits 4/5/6 */
368           rate = (peer->ttl & NMEA_BAUDRATE_MASK) >> NMEA_BAUDRATE_SHIFT;
369 
370           switch (rate) {
371           default:
372           case 0:
373                     baudrate = SPEED232;
374                     break;
375           case 1:
376                     baudrate = B9600;
377                     break;
378           case 2:
379                     baudrate = B19200;
380                     break;
381           case 3:
382                     baudrate = B38400;
383                     break;
384 #   ifdef B57600
385           case 4:
386                     baudrate = B57600;
387                     break;
388 #   endif
389 #   ifdef B115200
390           case 5:
391                     baudrate = B115200;
392                     break;
393 #   endif
394           }
395 
396           /* Allocate and initialize unit structure */
397           pp->unitptr = (caddr_t)up;
398           pp->io.fd = -1;
399           pp->io.clock_recv = nmea_receive;
400           pp->io.srcclock = peer;
401           pp->io.datalen = 0;
402           /* force change detection on first valid message */
403           memset(&up->last_reftime, 0xFF, sizeof(up->last_reftime));
404           memset(&up->last_gpsdate, 0x00, sizeof(up->last_gpsdate));
405           /* force checksum on GPRMC, see below */
406           up->cksum_type[NMEA_GPRMC] = CHECK_CSVALID;
407 #   ifdef HAVE_PPSAPI
408           up->ppsapi_fd = -1;
409 #   endif /* HAVE_PPSAPI */
410           ZERO(up->tally);
411 
412           /* Initialize miscellaneous variables */
413           peer->precision = PRECISION;
414           pp->clockdesc = DESCRIPTION;
415           memcpy(&pp->refid, REFID, 4);
416 
417           /* Open serial port. Use CLK line discipline, if available. */
418           devlen = snprintf(device, sizeof(device), DEVICE, unit);
419           if (devlen >= sizeof(device)) {
420                     msyslog(LOG_ERR, "%s clock device name too long",
421                               refnumtoa(&peer->srcadr));
422                     return FALSE; /* buffer overflow */
423           }
424           pp->io.fd = refclock_open(&peer->srcadr, device, baudrate, LDISC_CLK);
425           if (0 >= pp->io.fd) {
426                     pp->io.fd = nmead_open(device);
427                     if (-1 == pp->io.fd)
428                               return FALSE;
429           }
430 
431           /* succeed if this clock can be added */
432           return io_addclock(&pp->io) != 0;
433 }
434 
435 /*
436  * -------------------------------------------------------------------
437  * nmea_shutdown - shut down a GPS clock
438  *
439  * NOTE this routine is called after nmea_start() returns failure,
440  * as well as during a normal shutdown due to ntpq :config unpeer.
441  * -------------------------------------------------------------------
442  */
443 static void
nmea_shutdown(int unit,struct peer * peer)444 nmea_shutdown(
445           int           unit,
446           struct peer * peer
447           )
448 {
449           struct refclockproc * const pp = peer->procptr;
450           nmea_unit     * const up = (nmea_unit *)pp->unitptr;
451 
452           UNUSED_ARG(unit);
453 
454           if (up != NULL) {
455 #             ifdef HAVE_PPSAPI
456                     if (up->ppsapi_lit)
457                               time_pps_destroy(up->atom.handle);
458                     ppsdev_close(pp->io.fd, up->ppsapi_fd);
459 #             endif
460                     free(up);
461           }
462           pp->unitptr = (caddr_t)NULL;
463           if (-1 != pp->io.fd)
464                     io_closeclock(&pp->io);
465           pp->io.fd = -1;
466 }
467 
468 /*
469  * -------------------------------------------------------------------
470  * nmea_control - configure fudge params
471  * -------------------------------------------------------------------
472  */
473 #ifdef HAVE_PPSAPI
474 static void
nmea_control(int unit,const struct refclockstat * in_st,struct refclockstat * out_st,struct peer * peer)475 nmea_control(
476           int                         unit,
477           const struct refclockstat * in_st,
478           struct refclockstat       * out_st,
479           struct peer               * peer
480           )
481 {
482           struct refclockproc * const pp = peer->procptr;
483           nmea_unit     * const up = (nmea_unit *)pp->unitptr;
484 
485           char   device[32];
486           size_t devlen;
487 
488           UNUSED_ARG(in_st);
489           UNUSED_ARG(out_st);
490 
491           /*
492            * PPS control
493            *
494            * If /dev/gpspps$UNIT can be opened that will be used for
495            * PPSAPI.  On Linux, a PPS device mathing the TTY will be
496            * searched for and possibly created on the fly.  Otherwise, the
497            * GPS serial device /dev/gps$UNIT already opened is used for
498            * PPSAPI as well. (This might not work, in which case the PPS
499            * API remains unavailable...)
500            */
501 
502           /* Light up the PPSAPI interface if not yet attempted. */
503           if ((CLK_FLAG1 & pp->sloppyclockflag) && !up->ppsapi_tried) {
504                     const char *ppsname = device;
505                     up->ppsapi_tried = TRUE;
506                     /* get FD for the pps device; might be the tty itself! */
507                     devlen = snprintf(device, sizeof(device), PPSDEV, unit);
508                     if (devlen >= sizeof(device)) {
509                               msyslog(LOG_ERR, "%s PPS device name too long",
510                                         refnumtoa(&peer->srcadr));
511                               ppsname = NULL;
512                     }
513                     up->ppsapi_fd = ppsdev_reopen(
514                               &peer->srcadr,
515                               pp->io.fd, up->ppsapi_fd,
516                               ppsname, PPSOPENMODE, (S_IRUSR|S_IWUSR));
517                     /* note 1: the pps fd might be the same as the tty fd
518                      * note 2: the current PPS fd remains valid until
519                      *  - the clock is shut down
520                      *  - flag1 is set again after being cleared
521                      */
522                     if (refclock_ppsapi(up->ppsapi_fd, &up->atom)) {
523                               /* use the PPS API for our own purposes now. */
524                               up->ppsapi_lit = refclock_params(
525                                         pp->sloppyclockflag, &up->atom);
526                               if (!up->ppsapi_lit) {
527                                         /* failed to configure, drop PPS unit */
528                                         time_pps_destroy(up->atom.handle);
529                                         msyslog(LOG_WARNING,
530                                                   "%s set PPSAPI params fails",
531                                                   refnumtoa(&peer->srcadr));
532                               }
533                     } else {
534                               msyslog(LOG_WARNING,
535                                         "%s flag1 1 but PPSAPI fails",
536                                         refnumtoa(&peer->srcadr));
537                     }
538           }
539 
540           /* shut down PPS API if activated */
541           if ( !(CLK_FLAG1 & pp->sloppyclockflag) && up->ppsapi_tried) {
542                     /* shutdown PPS API */
543                     if (up->ppsapi_lit)
544                               time_pps_destroy(up->atom.handle);
545                     up->atom.handle = 0;
546                     /* do !!NOT!! close/drop PPS fd here! */
547 
548                     /* clear markers and peer items */
549                     up->ppsapi_gate  = FALSE;
550                     up->ppsapi_lit   = FALSE;
551                     up->ppsapi_tried = FALSE;
552 
553                     peer->flags &= ~FLAG_PPS;
554                     peer->precision = PRECISION;
555           }
556 }
557 #endif /* HAVE_PPSAPI */
558 
559 /*
560  * -------------------------------------------------------------------
561  * nmea_timer - called once per second
562  *
563  * Usually 'nmea_receive()' can get a timestamp every second, but at
564  * least one Motorola unit needs prompting each time. Doing so in
565  * 'nmea_poll()' gives only one sample per poll cycle, which actually
566  * defeats the purpose of the median filter. Polling once per second
567  * seems a much better idea.
568  *
569  * Also takes care of sample expiration if the receiver fails to
570  * provide new input data.
571  * -------------------------------------------------------------------
572  */
573 static void
nmea_timer(int unit,struct peer * peer)574 nmea_timer(
575           int             unit,
576           struct peer * peer
577           )
578 {
579           struct refclockproc * const pp = peer->procptr;
580           nmea_unit     * const up = (nmea_unit *)pp->unitptr;
581 
582           UNUSED_ARG(unit);
583 
584 #   if NMEA_WRITE_SUPPORT
585 
586           if (-1 != pp->io.fd) /* any mode bits to evaluate here? */
587                     gps_send(pp->io.fd, "$PMOTG,RMC,0000*1D\r\n", peer);
588 
589 #   endif /* NMEA_WRITE_SUPPORT */
590 
591           /* receive timeout occurred? */
592           if (up->rcvtout) {
593                     --up->rcvtout;
594           } else if (pp->codeproc != pp->coderecv) {
595                     /* expire one (the oldest) sample, if any */
596                     refclock_samples_expire(pp, 1);
597                     /* reset message assembly buffer */
598                     up->lb_buf[0] = '\0';
599                     up->lb_len    = 0;
600           }
601 
602           if (up->hold_gpsdate && (--up->hold_gpsdate < DATE_HLIM))
603                     up->type_gpsdate = DTYP_NONE;
604 }
605 
606 /*
607  * -------------------------------------------------------------------
608  * nmea_procrec - receive data from the serial interface
609  *
610  * This is the workhorse for NMEA data evaluation:
611  *
612  * + it checks all NMEA data, and rejects sentences that are not valid
613  *   NMEA sentences
614  * + it checks whether a sentence is known and to be used
615  * + it parses the time and date data from the NMEA data string and
616  *   augments the missing bits. (century in date, whole date, ...)
617  * + it rejects data that is not from the first accepted sentence in a
618  *   burst
619  * + it eventually replaces the receive time with the PPS edge time.
620  * + it feeds the data to the internal processing stages.
621  *
622  * This function assumes a non-empty line in the unit line buffer.
623  * -------------------------------------------------------------------
624  */
625 static void
nmea_procrec(struct peer * const peer,l_fp rd_timestamp)626 nmea_procrec(
627           struct peer * const peer,
628           l_fp                          rd_timestamp
629           )
630 {
631           /* declare & init control structure pointers */
632           struct refclockproc * const pp = peer->procptr;
633           nmea_unit     * const up = (nmea_unit*)pp->unitptr;
634 
635           /* Use these variables to hold data until we decide its worth keeping */
636           nmea_data rdata;
637           l_fp        rd_reftime;
638 
639           /* working stuff */
640           TCivilDate          date;     /* to keep & convert the time stamp */
641           TGpsDatum wgps;     /* week time storage */
642           TNtpDatum dntp;
643           l_fp                tofs;     /* offset to full-second reftime */
644           /* results of sentence/date/time parsing */
645           u_char              sentence; /* sentence tag */
646           int                 checkres;
647           int                 warp;               /* warp to GPS base date */
648           char *              cp;
649           int                 rc_date, rc_time;
650           u_short             rc_dtyp;
651 #   ifdef HAVE_PPSAPI
652           int                 withpps = 0;
653 #   endif /* HAVE_PPSAPI */
654 
655           /* make sure data has defined pristine state */
656           ZERO(tofs);
657           ZERO(date);
658           ZERO(wgps);
659           ZERO(dntp);
660 
661           /*
662            * Read the timecode and timestamp, then initialize field
663            * processing. The <CR><LF> at the NMEA line end is translated
664            * to <LF><LF> by the terminal input routines on most systems,
665            * and this gives us one spurious empty read per record which we
666            * better ignore silently.
667            */
668           checkres = field_init(&rdata, up->lb_buf, up->lb_len);
669           switch (checkres) {
670 
671           case CHECK_INVALID:
672                     DPRINTF(1, ("%s invalid data: '%s'\n",
673                               refnumtoa(&peer->srcadr), up->lb_buf));
674                     refclock_report(peer, CEVNT_BADREPLY);
675                     return;
676 
677           case CHECK_EMPTY:
678                     return;
679 
680           default:
681                     DPRINTF(1, ("%s gpsread: %d '%s'\n",
682                               refnumtoa(&peer->srcadr), up->lb_len,
683                               up->lb_buf));
684                     break;
685           }
686           up->tally.total++;
687 
688           /*
689            * --> below this point we have a valid NMEA sentence <--
690            *
691            * Check sentence name. Skip first 2 chars (talker ID) in most
692            * cases, to allow for $GLGGA and $GPGGA etc. Since the name
693            * field has at least 5 chars we can simply shift the field
694            * start.
695            */
696           cp = field_parse(&rdata, 0);
697           if      (strncmp(cp + 2, "RMC,", 4) == 0)
698                     sentence = NMEA_GPRMC;
699           else if (strncmp(cp + 2, "GGA,", 4) == 0)
700                     sentence = NMEA_GPGGA;
701           else if (strncmp(cp + 2, "GLL,", 4) == 0)
702                     sentence = NMEA_GPGLL;
703           else if (strncmp(cp + 2, "ZDA,", 4) == 0)
704                     sentence = NMEA_GPZDA;
705           else if (strncmp(cp + 2, "ZDG,", 4) == 0)
706                     sentence = NMEA_GPZDG;
707           else if (strncmp(cp,   "PGRMF,", 6) == 0)
708                     sentence = NMEA_PGRMF;
709           else if (strncmp(cp,   "PUBX,04,", 8) == 0)
710                     sentence = NMEA_PUBX04;
711           else
712                     return;   /* not something we know about */
713 
714           /* Eventually output delay measurement now. */
715           if (peer->ttl & NMEA_DELAYMEAS_MASK) {
716                     mprintf_clock_stats(&peer->srcadr, "delay %0.6f %.*s",
717                                ldexp(rd_timestamp.l_uf, -32),
718                                (int)(strchr(up->lb_buf, ',') - up->lb_buf),
719                                up->lb_buf);
720           }
721 
722           /* See if I want to process this message type */
723           if ((peer->ttl & NMEA_MESSAGE_MASK) &&
724               !(peer->ttl & sentence_mode[sentence])) {
725                     up->tally.filtered++;
726                     return;
727           }
728 
729           /*
730            * make sure it came in clean
731            *
732            * Apparently, older NMEA specifications (which are expensive)
733            * did not require the checksum for all sentences.  $GPMRC is
734            * the only one so far identified which has always been required
735            * to include a checksum.
736            *
737            * Today, most NMEA GPS receivers checksum every sentence.  To
738            * preserve its error-detection capabilities with modern GPSes
739            * while allowing operation without checksums on all but $GPMRC,
740            * we keep track of whether we've ever seen a valid checksum on
741            * a given sentence, and if so, reject future instances without
742            * checksum.  ('up->cksum_type[NMEA_GPRMC]' is set in
743            * 'nmea_start()' to enforce checksums for $GPRMC right from the
744            * start.)
745            */
746           if (up->cksum_type[sentence] <= (u_char)checkres) {
747                     up->cksum_type[sentence] = (u_char)checkres;
748           } else {
749                     DPRINTF(1, ("%s checksum missing: '%s'\n",
750                               refnumtoa(&peer->srcadr), up->lb_buf));
751                     refclock_report(peer, CEVNT_BADREPLY);
752                     up->tally.malformed++;
753                     return;
754           }
755 
756           /*
757            * $GPZDG provides GPS time not UTC, and the two mix poorly.
758            * Once have processed a $GPZDG, do not process any further UTC
759            * sentences (all but $GPZDG currently).
760            */
761           if (sentence == NMEA_GPZDG) {
762                     if (!up->gps_time) {
763                               msyslog(LOG_INFO,
764                                         "%s using GPS time as if it were UTC",
765                                         refnumtoa(&peer->srcadr));
766                               up->gps_time = 1;
767                     }
768           } else {
769                     if (up->gps_time) {
770                               up->tally.filtered++;
771                               return;
772                     }
773           }
774 
775           DPRINTF(1, ("%s processing %d bytes, timecode '%s'\n",
776                     refnumtoa(&peer->srcadr), up->lb_len, up->lb_buf));
777 
778           /*
779            * Grab fields depending on clock string type and possibly wipe
780            * sensitive data from the last timecode.
781            */
782           rc_date = -1;       /* assume we have to do day-time mapping */
783           rc_dtyp = DTYP_NONE;
784           switch (sentence) {
785 
786           case NMEA_GPRMC:
787                     /* Check quality byte, fetch data & time */
788                     rc_time    = parse_time(&date, &tofs, &rdata, 1);
789                     pp->leap = parse_qual(&rdata, 2, 'A', 0);
790                     if (up->type_gpsdate <= DTYP_Y2D) {
791                               rc_date   = parse_date(&date, &rdata, 9, DATE_1_DDMMYY);
792                               rc_dtyp = DTYP_Y2D;
793                     }
794                     if (CLK_FLAG4 & pp->sloppyclockflag)
795                               field_wipe(&rdata, 3, 4, 5, 6, -1);
796                     break;
797 
798           case NMEA_GPGGA:
799                     /* Check quality byte, fetch time only */
800                     rc_time    = parse_time(&date, &tofs, &rdata, 1);
801                     pp->leap = parse_qual(&rdata, 6, '0', 1);
802                     if (CLK_FLAG4 & pp->sloppyclockflag)
803                               field_wipe(&rdata, 2, 4, -1);
804                     break;
805 
806           case NMEA_GPGLL:
807                     /* Check quality byte, fetch time only */
808                     rc_time    = parse_time(&date, &tofs, &rdata, 5);
809                     pp->leap = parse_qual(&rdata, 6, 'A', 0);
810                     if (CLK_FLAG4 & pp->sloppyclockflag)
811                               field_wipe(&rdata, 1, 3, -1);
812                     break;
813 
814           case NMEA_GPZDA:
815                     /* No quality.      Assume best, fetch time & full date */
816                     rc_time   = parse_time(&date, &tofs, &rdata, 1);
817                     if (up->type_gpsdate <= DTYP_Y4D) {
818                               rc_date   = parse_date(&date, &rdata, 2, DATE_3_DDMMYYYY);
819                               rc_dtyp = DTYP_Y4D;
820                     }
821                     break;
822 
823           case NMEA_GPZDG:
824                     /* Check quality byte, fetch time & full date */
825                     rc_time    = parse_time(&date, &tofs, &rdata, 1);
826                     pp->leap = parse_qual(&rdata, 4, '0', 1);
827                     --tofs.l_ui; /* GPZDG gives *following* second */
828                     if (up->type_gpsdate <= DTYP_Y4D) {
829                               rc_date   = parse_date(&date, &rdata, 2, DATE_3_DDMMYYYY);
830                               rc_dtyp = DTYP_Y4D;
831                     }
832                     break;
833 
834           case NMEA_PGRMF:
835                     /* get time, qualifier and GPS weektime. */
836                     rc_time = parse_time(&date, &tofs, &rdata, 4);
837                     if (up->type_gpsdate <= DTYP_W10B) {
838                               rc_date = parse_gpsw(&wgps, &rdata, 1, 2, 5);
839                               rc_dtyp = DTYP_W10B;
840                     }
841                     pp->leap = parse_qual(&rdata, 11, '0', 1);
842                     if (CLK_FLAG4 & pp->sloppyclockflag)
843                               field_wipe(&rdata, 6, 8, -1);
844                     break;
845 
846           case NMEA_PUBX04:
847                     /* PUBX,04 is peculiar. The UTC time-of-week is the *internal*
848                      * time base, which is not exactly on par with the fix time.
849                      */
850                     rc_time = parse_time(&date, &tofs, &rdata, 2);
851                     if (up->type_gpsdate <= DTYP_WEXT) {
852                               rc_date = parse_gpsw(&wgps, &rdata, 5, 4, -1);
853                               rc_dtyp = DTYP_WEXT;
854                     }
855                     break;
856 
857           default:
858                     INVARIANT(0);       /* Coverity 97123 */
859                     return;
860           }
861 
862           /* ignore receiver status? [bug 3694] */
863           if (peer->ttl & NMEA_IGNSTATUS_MASK) { /* assume always good? */
864                     pp->leap = LEAP_NOWARNING;
865           }
866 
867           /* check clock sanity; [bug 2143] */
868           if (pp->leap == LEAP_NOTINSYNC) { /* no good status? */
869                     checkres = CEVNT_PROP;
870                     up->tally.rejected++;
871           }
872           /* Check sanity of time-of-day. */
873           else if (rc_time == 0) {      /* no time or conversion error? */
874                     checkres = CEVNT_BADTIME;
875                     up->tally.malformed++;
876           }
877           /* Check sanity of date. */
878           else if (rc_date == 0) {      /* no date or conversion error? */
879                     checkres = CEVNT_BADDATE;
880                     up->tally.malformed++;
881           }
882           else {
883                     checkres = -1;
884           }
885 
886           if (checkres != -1) {
887                     refclock_save_lcode(pp, up->lb_buf, up->lb_len);
888                     refclock_report(peer, checkres);
889                     return;
890           }
891 
892           /* See if we can augment the receive time stamp. If not, apply
893            * fudge time 2 to the receive time stamp directly.
894            */
895 #   ifdef HAVE_PPSAPI
896           if (up->ppsapi_lit && pp->leap != LEAP_NOTINSYNC)
897                     withpps = refclock_ppsaugment(
898                               &up->atom, &rd_timestamp,
899                               pp->fudgetime2, pp->fudgetime1);
900           else
901 #   endif /* HAVE_PPSAPI */
902                     rd_timestamp = ntpfp_with_fudge(
903                               rd_timestamp, pp->fudgetime2);
904 
905           /* set the GPS base date, if possible */
906           warp = !(peer->ttl & NMEA_DATETRUST_MASK);
907           if (rc_dtyp != DTYP_NONE) {
908                     DPRINTF(1, ("%s saving date, type=%hu\n",
909                                   refnumtoa(&peer->srcadr), rc_dtyp));
910                     switch (rc_dtyp) {
911                     case DTYP_W10B:
912                               up->last_gpsdate = gpsntp_from_gpscal_ex(
913                                         &wgps, (warp = TRUE));
914                               break;
915                     case DTYP_WEXT:
916                               up->last_gpsdate = gpsntp_from_gpscal_ex(
917                                         &wgps, warp);
918                               break;
919                     default:
920                               up->last_gpsdate = gpsntp_from_calendar_ex(
921                                         &date, tofs, warp);
922                               break;
923                     }
924                     up->type_gpsdate = rc_dtyp;
925                     up->hold_gpsdate = DATE_HOLD;
926           }
927           /* now convert and possibly extend/expand the time stamp. */
928           if (up->hold_gpsdate) {       /* time of day, based */
929                     dntp = gpsntp_from_daytime2_ex(
930                               &date, tofs, &up->last_gpsdate, warp);
931           } else {            /* time of day, floating */
932                     dntp = gpsntp_from_daytime1_ex(
933                               &date, tofs, rd_timestamp, warp);
934           }
935 
936           if (debug) {
937                     /* debug print time stamp */
938                     gpsntp_to_calendar(&date, &dntp);
939 #             ifdef HAVE_PPSAPI
940                     DPRINTF(1, ("%s effective timecode: %s (%s PPS)\n",
941                                   refnumtoa(&peer->srcadr),
942                                   ntpcal_iso8601std(NULL, 0, &date),
943                                   (withpps ? "with" : "without")));
944 #             else /* ?HAVE_PPSAPI */
945                     DPRINTF(1, ("%s effective timecode: %s\n",
946                                   refnumtoa(&peer->srcadr),
947                                   ntpcal_iso8601std(NULL, 0, &date)));
948 #             endif /* !HAVE_PPSAPI */
949           }
950 
951           /* Get the reference time stamp from the calendar buffer.
952            * Process the new sample in the median filter and determine the
953            * timecode timestamp, but only if the PPS is not in control.
954            * Discard sentence if reference time did not change.
955            */
956           rd_reftime = ntpfp_from_ntpdatum(&dntp);
957           if (L_ISEQU(&up->last_reftime, &rd_reftime)) {
958                     /* Do not touch pp->a_lastcode on purpose! */
959                     up->tally.filtered++;
960                     return;
961           }
962           up->last_reftime = rd_reftime;
963 
964           DPRINTF(1, ("%s using '%s'\n",
965                         refnumtoa(&peer->srcadr), up->lb_buf));
966 
967           /* Data will be accepted. Update stats & log data. */
968           up->tally.accepted++;
969           refclock_save_lcode(pp, up->lb_buf, up->lb_len);
970           pp->lastrec = rd_timestamp;
971 
972           /* If we have PPS augmented receive time, we *must* have a
973            * working PPS source and we must set the flags accordingly.
974            */
975 #   ifdef HAVE_PPSAPI
976           if (withpps) {
977                     up->ppsapi_gate = TRUE;
978                     peer->precision = PPS_PRECISION;
979                     if (tabsdiffd(rd_reftime, rd_timestamp) < 0.5) {
980                               if ( ! (peer->ttl & NMEA_QUIETPPS_MASK))
981                                         peer->flags |= FLAG_PPS;
982                               DPRINTF(2, ("%s PPS_RELATE_PHASE\n",
983                                             refnumtoa(&peer->srcadr)));
984                               up->tally.pps_used++;
985                     } else {
986                               DPRINTF(2, ("%s PPS_RELATE_EDGE\n",
987                                             refnumtoa(&peer->srcadr)));
988                     }
989                     /* !Note! 'FLAG_PPS' is reset in 'nmea_poll()' */
990           }
991 #   endif /* HAVE_PPSAPI */
992           /* Whether the receive time stamp is PPS-augmented or not,
993            * the proper fudge offset is already applied. There's no
994            * residual fudge to process.
995            */
996           refclock_process_offset(pp, rd_reftime, rd_timestamp, 0.0);
997           up->rcvtout = 2;
998 }
999 
1000 /*
1001  * -------------------------------------------------------------------
1002  * nmea_receive - receive data from the serial interface
1003  *
1004  * With serial IO only, a single call to 'refclock_gtlin()' to get the
1005  * string would suffice to get the NMEA data. When using NMEAD, this
1006  * does unfortunately no longer hold, since TCP is stream oriented and
1007  * not line oriented, and there's no one to do the line-splitting work
1008  * of the TTY driver in line/cooked mode.
1009  *
1010  * So we have to do this manually here, and we have to live with the
1011  * fact that there could be more than one sentence in a receive buffer.
1012  * Likewise, there can be partial messages on either end. (Strictly
1013  * speaking, a receive buffer could also contain just a single fragment,
1014  * though that's unlikely.)
1015  *
1016  * We deal with that by scanning the input buffer, copying bytes from
1017  * the receive buffer to the assembly buffer as we go and calling the
1018  * record processor every time we hit a CR/LF, provided the resulting
1019  * line is not empty. Any leftovers are kept for the next round.
1020  *
1021  * Note: When used with a serial data stream, there's no change to the
1022  * previous line-oriented input: One line is copied to the buffer and
1023  * processed per call. Only with NMEAD the behavior changes, and the
1024  * timing is badly affected unless a PPS channel is also associated with
1025  * the clock instance. TCP leaves us nothing to improve on here.
1026  * -------------------------------------------------------------------
1027  */
1028 static void
nmea_receive(struct recvbuf * rbufp)1029 nmea_receive(
1030           struct recvbuf * rbufp
1031           )
1032 {
1033           /* declare & init control structure pointers */
1034           struct peer             * const peer = rbufp->recv_peer;
1035           struct refclockproc * const pp = peer->procptr;
1036           nmea_unit     * const up = (nmea_unit*)pp->unitptr;
1037 
1038           const char *sp, *se;
1039           char         *dp, *de;
1040 
1041           /* paranoia check: */
1042           if (up->lb_len >= sizeof(up->lb_buf))
1043                     up->lb_len = 0;
1044 
1045           /* pick up last assembly position; leave room for NUL */
1046           dp = up->lb_buf + up->lb_len;
1047           de = up->lb_buf + sizeof(up->lb_buf) - 1;
1048           /* set up input range */
1049           sp = (const char *)rbufp->recv_buffer;
1050           se = sp + rbufp->recv_length;
1051 
1052           /* walk over the input data, dropping parity bits and control
1053            * chars as we go, and calling the record processor for each
1054            * complete non-empty line.
1055            */
1056           while (sp != se) {
1057                     char ch = (*sp++ & 0x7f);
1058                     if (dp == up->lb_buf) {
1059                               if (ch == '$')
1060                                         *dp++ = ch;
1061                     } else if (dp > de) {
1062                               dp = up->lb_buf;
1063                     } else if (ch == '\n' || ch == '\r') {
1064                               *dp = '\0';
1065                               up->lb_len = (int)(dp - up->lb_buf);
1066                               dp = up->lb_buf;
1067                               nmea_procrec(peer, rbufp->recv_time);
1068                     } else if (ch >= 0x20 && ch < 0x7f) {
1069                               *dp++ = ch;
1070                     }
1071           }
1072           /* update state to keep for next round */
1073           *dp = '\0';
1074           up->lb_len = (int)(dp - up->lb_buf);
1075 }
1076 
1077 /*
1078  * -------------------------------------------------------------------
1079  * nmea_poll - called by the transmit procedure
1080  *
1081  * Does the necessary bookkeeping stuff to keep the reported state of
1082  * the clock in sync with reality.
1083  *
1084  * We go to great pains to avoid changing state here, since there may
1085  * be more than one eavesdropper receiving the same timecode.
1086  * -------------------------------------------------------------------
1087  */
1088 static void
nmea_poll(int unit,struct peer * peer)1089 nmea_poll(
1090           int           unit,
1091           struct peer * peer
1092           )
1093 {
1094           struct refclockproc * const pp = peer->procptr;
1095           nmea_unit     * const up = (nmea_unit *)pp->unitptr;
1096 
1097           /*
1098            * Process median filter samples. If none received, declare a
1099            * timeout and keep going.
1100            */
1101 #   ifdef HAVE_PPSAPI
1102           /*
1103            * If we don't have PPS pulses and time stamps, turn PPS down
1104            * for now.
1105            */
1106           if (!up->ppsapi_gate) {
1107                     peer->flags &= ~FLAG_PPS;
1108                     peer->precision = PRECISION;
1109           } else {
1110                     up->ppsapi_gate = FALSE;
1111           }
1112 #   endif /* HAVE_PPSAPI */
1113 
1114           /*
1115            * If the median filter is empty, claim a timeout. Else process
1116            * the input data and keep the stats going.
1117            */
1118           if (pp->coderecv == pp->codeproc) {
1119                     peer->flags &= ~FLAG_PPS;
1120                     if (pp->currentstatus < CEVNT_TIMEOUT)
1121                         refclock_report(peer, CEVNT_TIMEOUT);
1122                     memset(&up->last_gpsdate, 0, sizeof(up->last_gpsdate));
1123           } else {
1124                     pp->polls++;
1125                     pp->lastref = pp->lastrec;
1126                     refclock_receive(peer);
1127                     if (pp->currentstatus > CEVNT_NOMINAL)
1128                         refclock_report(peer, CEVNT_NOMINAL);
1129           }
1130 
1131           /*
1132            * If extended logging is required, write the tally stats to the
1133            * clockstats file; otherwise just do a normal clock stats
1134            * record. Clear the tally stats anyway.
1135           */
1136           if (peer->ttl & NMEA_EXTLOG_MASK) {
1137                     /* Log & reset counters with extended logging */
1138                     const char *nmea = pp->a_lastcode;
1139                     if (*nmea == '\0') nmea = "(none)";
1140                     mprintf_clock_stats(
1141                       &peer->srcadr, "%s  %u %u %u %u %u %u",
1142                       nmea,
1143                       up->tally.total, up->tally.accepted,
1144                       up->tally.rejected, up->tally.malformed,
1145                       up->tally.filtered, up->tally.pps_used);
1146           } else {
1147                     record_clock_stats(&peer->srcadr, pp->a_lastcode);
1148           }
1149           ZERO(up->tally);
1150 }
1151 
1152 #if NMEA_WRITE_SUPPORT
1153 /*
1154  * -------------------------------------------------------------------
1155  *  gps_send(fd, cmd, peer)   Sends a command to the GPS receiver.
1156  *   as in gps_send(fd, "rqts,u", peer);
1157  *
1158  * If 'cmd' starts with a '$' it is assumed that this command is in raw
1159  * format, that is, starts with '$', ends with '<cr><lf>' and that any
1160  * checksum is correctly provided; the command will be send 'as is' in
1161  * that case. Otherwise the function will create the necessary frame
1162  * (start char, chksum, final CRLF) on the fly.
1163  *
1164  * We don't currently send any data, but would like to send RTCM SC104
1165  * messages for differential positioning. It should also give us better
1166  * time. Without a PPS output, we're Just fooling ourselves because of
1167  * the serial code paths
1168  * -------------------------------------------------------------------
1169  */
1170 static void
gps_send(int fd,const char * cmd,struct peer * peer)1171 gps_send(
1172           int           fd,
1173           const char  * cmd,
1174           struct peer * peer
1175           )
1176 {
1177           /* $...*xy<CR><LF><NUL> add 7 */
1178           char            buf[NMEA_PROTO_MAXLEN + 7];
1179           int             len;
1180           u_char          dcs;
1181           const u_char *beg, *end;
1182 
1183           if (*cmd != '$') {
1184                     /* get checksum and length */
1185                     beg = end = (const u_char*)cmd;
1186                     dcs = 0;
1187                     while (*end >= ' ' && *end != '*')
1188                               dcs ^= *end++;
1189                     len = end - beg;
1190                     /* format into output buffer with overflow check */
1191                     len = snprintf(buf, sizeof(buf), "$%.*s*%02X\r\n",
1192                                      len, beg, dcs);
1193                     if ((size_t)len >= sizeof(buf)) {
1194                               DPRINTF(1, ("%s gps_send: buffer overflow for command '%s'\n",
1195                                             refnumtoa(&peer->srcadr), cmd));
1196                               return;   /* game over player 1 */
1197                     }
1198                     cmd = buf;
1199           } else {
1200                     len = strlen(cmd);
1201           }
1202 
1203           DPRINTF(1, ("%s gps_send: '%.*s'\n", refnumtoa(&peer->srcadr),
1204                     len - 2, cmd));
1205 
1206           /* send out the whole stuff */
1207           if (refclock_fdwrite(peer, fd, cmd, len) != len)
1208                     refclock_report(peer, CEVNT_FAULT);
1209 }
1210 #endif /* NMEA_WRITE_SUPPORT */
1211 
1212 /*
1213  * -------------------------------------------------------------------
1214  * helpers for faster field splitting
1215  * -------------------------------------------------------------------
1216  *
1217  * set up a field record, check syntax and verify checksum
1218  *
1219  * format is $XXXXX,1,2,3,4*ML
1220  *
1221  * 8-bit XOR of characters between $ and * noninclusive is transmitted
1222  * in last two chars M and L holding most and least significant nibbles
1223  * in hex representation such as:
1224  *
1225  *   $GPGLL,5057.970,N,00146.110,E,142451,A*27
1226  *   $GPVTG,089.0,T,,,15.2,N,,*7F
1227  *
1228  * Some other constraints:
1229  * + The field name must be at least 5 upcase characters or digits and
1230  *   must start with a character.
1231  * + The checksum (if present) must be uppercase hex digits.
1232  * + The length of a sentence is limited to 80 characters (not including
1233  *   the final CR/LF nor the checksum, but including the leading '$')
1234  *
1235  * Return values:
1236  *  + CHECK_INVALID
1237  *        The data does not form a valid NMEA sentence or a checksum error
1238  *        occurred.
1239  *  + CHECK_VALID
1240  *        The data is a valid NMEA sentence but contains no checksum.
1241  *  + CHECK_CSVALID
1242  *        The data is a valid NMEA sentence and passed the checksum test.
1243  * -------------------------------------------------------------------
1244  */
1245 static int
field_init(nmea_data * data,char * cptr,int dlen)1246 field_init(
1247           nmea_data * data,   /* context structure                           */
1248           char        * cptr, /* start of raw data                           */
1249           int           dlen  /* data len, not counting trailing NUL */
1250           )
1251 {
1252           u_char cs_l;        /* checksum local computed    */
1253           u_char cs_r;        /* checksum remote given      */
1254           char * eptr;        /* buffer end end pointer     */
1255           char   tmp;         /* char buffer                          */
1256 
1257           cs_l = 0;
1258           cs_r = 0;
1259           /* some basic input constraints */
1260           if (dlen < 0)
1261                     dlen = 0;
1262           eptr = cptr + dlen;
1263           *eptr = '\0';
1264 
1265           /* load data context */
1266           data->base = cptr;
1267           data->cptr = cptr;
1268           data->cidx = 0;
1269           data->blen = dlen;
1270 
1271           /* syntax check follows here. check allowed character
1272            * sequences, updating the local computed checksum as we go.
1273            *
1274            * regex equiv: '^\$[A-Z][A-Z0-9]{4,}[^*]*(\*[0-9A-F]{2})?$'
1275            */
1276 
1277           /* -*- start character: '^\$' */
1278           if (*cptr == '\0')
1279                     return CHECK_EMPTY;
1280           if (*cptr++ != '$')
1281                     return CHECK_INVALID;
1282 
1283           /* -*- advance context beyond start character */
1284           data->base++;
1285           data->cptr++;
1286           data->blen--;
1287 
1288           /* -*- field name: '[A-Z][A-Z0-9]{4,},' */
1289           if (*cptr < 'A' || *cptr > 'Z')
1290                     return CHECK_INVALID;
1291           cs_l ^= *cptr++;
1292           while ((*cptr >= 'A' && *cptr <= 'Z') ||
1293                  (*cptr >= '0' && *cptr <= '9')  )
1294                     cs_l ^= *cptr++;
1295           if (*cptr != ',' || (cptr - data->base) < NMEA_PROTO_IDLEN)
1296                     return CHECK_INVALID;
1297           cs_l ^= *cptr++;
1298 
1299           /* -*- data: '[^*]*' */
1300           while (*cptr && *cptr != '*')
1301                     cs_l ^= *cptr++;
1302 
1303           /* -*- checksum field: (\*[0-9A-F]{2})?$ */
1304           if (*cptr == '\0')
1305                     return CHECK_VALID;
1306           if (*cptr != '*' || cptr != eptr - 3 ||
1307               (cptr - data->base) >= NMEA_PROTO_MAXLEN)
1308                     return CHECK_INVALID;
1309 
1310           for (cptr++; (tmp = *cptr) != '\0'; cptr++) {
1311                     if (tmp >= '0' && tmp <= '9')
1312                               cs_r = (cs_r << 4) + (tmp - '0');
1313                     else if (tmp >= 'A' && tmp <= 'F')
1314                               cs_r = (cs_r << 4) + (tmp - 'A' + 10);
1315                     else
1316                               break;
1317           }
1318 
1319           /* -*- make sure we are at end of string and csum matches */
1320           if (cptr != eptr || cs_l != cs_r)
1321                     return CHECK_INVALID;
1322 
1323           return CHECK_CSVALID;
1324 }
1325 
1326 /*
1327  * -------------------------------------------------------------------
1328  * fetch a data field by index, zero being the name field. If this
1329  * function is called repeatedly with increasing indices, the total load
1330  * is O(n), n being the length of the string; if it is called with
1331  * decreasing indices, the total load is O(n^2). Try not to go backwards
1332  * too often.
1333  * -------------------------------------------------------------------
1334  */
1335 static char *
field_parse(nmea_data * data,int fn)1336 field_parse(
1337           nmea_data * data,
1338           int           fn
1339           )
1340 {
1341           char tmp;
1342 
1343           if (fn < data->cidx) {
1344                     data->cidx = 0;
1345                     data->cptr = data->base;
1346           }
1347           while ((fn > data->cidx) && (tmp = *data->cptr) != '\0') {
1348                     data->cidx += (tmp == ',');
1349                     data->cptr++;
1350           }
1351           return data->cptr;
1352 }
1353 
1354 /*
1355  * -------------------------------------------------------------------
1356  * Wipe (that is, overwrite with '_') data fields and the checksum in
1357  * the last timecode.  The list of field indices is given as integers
1358  * in a varargs list, preferably in ascending order, in any case
1359  * terminated by a negative field index.
1360  *
1361  * A maximum number of 8 fields can be overwritten at once to guard
1362  * against runaway (that is, unterminated) argument lists.
1363  *
1364  * This function affects what a remote user can see with
1365  *
1366  * ntpq -c clockvar <server>
1367  *
1368  * Note that this also removes the wiped fields from any clockstats
1369  * log.    Some NTP operators monitor their NMEA GPS using the change in
1370  * location in clockstats over time as as a proxy for the quality of
1371  * GPS reception and thereby time reported.
1372  * -------------------------------------------------------------------
1373  */
1374 static void
field_wipe(nmea_data * data,...)1375 field_wipe(
1376           nmea_data * data,
1377           ...
1378           )
1379 {
1380           va_list   va;                 /* vararg index list */
1381           int       fcnt;               /* safeguard against runaway arglist */
1382           int       fidx;               /* field to nuke, or -1 for checksum */
1383           char  * cp;                   /* overwrite destination */
1384 
1385           fcnt = 8;
1386           cp = NULL;
1387           va_start(va, data);
1388           do {
1389                     fidx = va_arg(va, int);
1390                     if (fidx >= 0 && fidx <= NMEA_PROTO_FIELDS) {
1391                               cp = field_parse(data, fidx);
1392                     } else {
1393                               cp = data->base + data->blen;
1394                               if (data->blen >= 3 && cp[-3] == '*')
1395                                         cp -= 2;
1396                     }
1397                     for ( ; '\0' != *cp && '*' != *cp && ',' != *cp; cp++)
1398                               if ('.' != *cp)
1399                                         *cp = '_';
1400           } while (fcnt-- && fidx >= 0);
1401           va_end(va);
1402 }
1403 
1404 /*
1405  * -------------------------------------------------------------------
1406  * PARSING HELPERS
1407  * -------------------------------------------------------------------
1408  */
1409 typedef unsigned char const UCC;
1410 
1411 static char const * const s_eof_chars = ",*\r\n";
1412 
1413 #ifdef DEBUG
field_length(UCC * cp,unsigned int nfields)1414 static int field_length(UCC *cp, unsigned int nfields)
1415 {
1416           char const * ep = (char const*)cp;
1417           ep = strpbrk(ep, s_eof_chars);
1418           if (ep && nfields)
1419                     while (--nfields && ep && *ep == ',')
1420                               ep = strpbrk(ep + 1, s_eof_chars);
1421           return (ep)
1422               ? (int)((UCC*)ep - cp)
1423               : (int)strlen((char const*)cp);
1424 }
1425 #endif    /* DEBUG */
1426 
1427 /* /[,*\r\n]/ --> skip */
_parse_eof(UCC * cp,UCC ** ep)1428 static int _parse_eof(UCC *cp, UCC ** ep)
1429 {
1430           int rc = (strchr(s_eof_chars, *(char const*)cp) != NULL);
1431           *ep = cp + rc;
1432           return rc;
1433 }
1434 
1435 /* /,/ --> skip */
_parse_sep(UCC * cp,UCC ** ep)1436 static int _parse_sep(UCC *cp, UCC ** ep)
1437 {
1438           int rc = (*cp == ',');
1439           *ep = cp + rc;
1440           return rc;
1441 }
1442 
1443 /* /[[:digit:]]{2}/ --> uint16_t */
_parse_num2d(UCC * cp,UCC ** ep,uint16_t * into)1444 static int _parse_num2d(UCC *cp, UCC ** ep, uint16_t *into)
1445 {
1446           int       rc = FALSE;
1447 
1448           if (isdigit(cp[0]) && isdigit(cp[1])) {
1449                     *into = (cp[0] - '0') * 10 + (cp[1] - '0');
1450                     cp += 2;
1451                     rc = TRUE;
1452           }
1453           *ep = cp;
1454           return rc;
1455 }
1456 
1457 /* /[[:digit:]]+/ --> uint16_t */
_parse_u16(UCC * cp,UCC ** ep,uint16_t * into,unsigned int ndig)1458 static int _parse_u16(UCC *cp, UCC **ep, uint16_t *into, unsigned int ndig)
1459 {
1460           uint16_t  num = 0;
1461           int                 rc  = FALSE;
1462           if (isdigit(*cp) && ndig) {
1463                     rc = TRUE;
1464                     do
1465                               num = (num * 10) + (*cp - '0');
1466                     while (isdigit(*++cp) && --ndig);
1467                     *into = num;
1468           }
1469           *ep = cp;
1470           return rc;
1471 }
1472 
1473 /* /[[:digit:]]+/ --> uint32_t */
_parse_u32(UCC * cp,UCC ** ep,uint32_t * into,unsigned int ndig)1474 static int _parse_u32(UCC *cp, UCC **ep, uint32_t *into, unsigned int ndig)
1475 {
1476           uint32_t  num = 0;
1477           int                 rc  = FALSE;
1478           if (isdigit(*cp) && ndig) {
1479                     rc = TRUE;
1480                     do
1481                               num = (num * 10) + (*cp - '0');
1482                     while (isdigit(*++cp) && --ndig);
1483                     *into = num;
1484           }
1485           *ep = cp;
1486           return rc;
1487 }
1488 
1489 /* /(\.[[:digit:]]*)?/ --> l_fp{0, f}
1490  * read fractional seconds, convert to l_fp
1491  *
1492  * Only the first 9 decimal digits are evaluated; any excess is parsed
1493  * away but silently ignored. (--> truncation to 1 nanosecond)
1494  */
_parse_frac(UCC * cp,UCC ** ep,l_fp * into)1495 static int _parse_frac(UCC *cp, UCC **ep, l_fp *into)
1496 {
1497           static const uint32_t powtab[10] = {
1498                             0,
1499                     100000000, 10000000, 1000000,
1500                        100000,    10000,    1000,
1501                           100,       10,       1
1502           };
1503 
1504           struct timespec     ts;
1505           ZERO(ts);
1506           if (*cp == '.') {
1507                     uint32_t fval = 0;
1508                     UCC *    sp   = cp + 1;
1509                     if (_parse_u32(sp, &cp, &fval, 9))
1510                               ts.tv_nsec = fval * powtab[(size_t)(cp - sp)];
1511                     while (isdigit(*cp))
1512                               ++cp;
1513           }
1514 
1515           *ep   = cp;
1516           *into = tspec_intv_to_lfp(ts);
1517           return TRUE;
1518 }
1519 
1520 /* /[[:digit:]]{6}/ --> time-of-day
1521  * parses a number string representing 'HHMMSS'
1522  */
_parse_time(UCC * cp,UCC ** ep,TCivilDate * into)1523 static int _parse_time(UCC *cp, UCC ** ep, TCivilDate *into)
1524 {
1525           uint16_t  s, m, h;
1526           int                 rc;
1527           UCC *               xp = cp;
1528 
1529           rc =   _parse_num2d(cp, &cp, &h) && (h < 24)
1530               && _parse_num2d(cp, &cp, &m) && (m < 60)
1531               && _parse_num2d(cp, &cp, &s) && (s < 61); /* leap seconds! */
1532 
1533           if (rc) {
1534                     into->hour   = (uint8_t)h;
1535                     into->minute = (uint8_t)m;
1536                     into->second = (uint8_t)s;
1537                     *ep = cp;
1538           } else {
1539                     *ep = xp;
1540                     DPRINTF(1, ("nmea: invalid time code: '%.*s'\n",
1541                                   field_length(xp, 1), xp));
1542           }
1543           return rc;
1544 }
1545 
1546 /* /[[:digit:]]{6}/ --> civil date
1547  * parses a number string representing 'ddmmyy'
1548  */
_parse_date1(UCC * cp,UCC ** ep,TCivilDate * into)1549 static int _parse_date1(UCC *cp, UCC **ep, TCivilDate *into)
1550 {
1551           unsigned short      d, m, y;
1552           int                 rc;
1553           UCC *               xp = cp;
1554 
1555           rc =   _parse_num2d(cp, &cp, &d) && (d - 1 < 31)
1556               && _parse_num2d(cp, &cp, &m) && (m - 1 < 12)
1557               && _parse_num2d(cp, &cp, &y)
1558               && _parse_eof(cp, ep);
1559           if (rc) {
1560                     into->monthday = (uint8_t )d;
1561                     into->month    = (uint8_t )m;
1562                     into->year     = (uint16_t)y;
1563                     *ep = cp;
1564           } else {
1565                     *ep = xp;
1566                     DPRINTF(1, ("nmea: invalid date code: '%.*s'\n",
1567                                   field_length(xp, 1), xp));
1568           }
1569           return rc;
1570 }
1571 
1572 /* /[[:digit:]]+,[[:digit:]]+,[[:digit:]]+/ --> civil date
1573  * parses three successive numeric fields as date: day,month,year
1574  */
_parse_date3(UCC * cp,UCC ** ep,TCivilDate * into)1575 static int _parse_date3(UCC *cp, UCC **ep, TCivilDate *into)
1576 {
1577           uint16_t  d, m, y;
1578           int                 rc;
1579           UCC *               xp = cp;
1580 
1581           rc =   _parse_u16(cp, &cp, &d, 2) && (d - 1 < 31)
1582               && _parse_sep(cp, &cp)
1583               && _parse_u16(cp, &cp, &m, 2) && (m - 1 < 12)
1584               && _parse_sep(cp, &cp)
1585               && _parse_u16(cp, &cp, &y, 4) && (y > 1980)
1586               && _parse_eof(cp, ep);
1587           if (rc) {
1588                     into->monthday = (uint8_t )d;
1589                     into->month    = (uint8_t )m;
1590                     into->year     = (uint16_t)y;
1591                     *ep = cp;
1592           } else {
1593                     *ep = xp;
1594                     DPRINTF(1, ("nmea: invalid date code: '%.*s'\n",
1595                                   field_length(xp, 3), xp));
1596           }
1597           return rc;
1598 }
1599 
1600 /*
1601  * -------------------------------------------------------------------
1602  * Check sync status
1603  *
1604  * If the character at the data field start matches the tag value,
1605  * return LEAP_NOWARNING and LEAP_NOTINSYNC otherwise. If the 'inverted'
1606  * flag is given, just the opposite value is returned. If there is no
1607  * data field (*cp points to the NUL byte) the result is LEAP_NOTINSYNC.
1608  * -------------------------------------------------------------------
1609  */
1610 static u_char
parse_qual(nmea_data * rd,int idx,char tag,int inv)1611 parse_qual(
1612           nmea_data * rd,
1613           int         idx,
1614           char        tag,
1615           int         inv
1616           )
1617 {
1618           static const u_char table[2] = {
1619                     LEAP_NOTINSYNC, LEAP_NOWARNING };
1620 
1621           char * dp = field_parse(rd, idx);
1622 
1623           return table[ *dp && ((*dp == tag) == !inv) ];
1624 }
1625 
1626 /*
1627  * -------------------------------------------------------------------
1628  * Parse a time stamp in HHMMSS[.sss] format with error checking.
1629  *
1630  * returns 1 on success, 0 on failure
1631  * -------------------------------------------------------------------
1632  */
1633 static int
parse_time(struct calendar * jd,l_fp * fofs,nmea_data * rd,int idx)1634 parse_time(
1635           struct calendar * jd,         /* result calendar pointer */
1636           l_fp                * fofs,   /* storage for nsec fraction */
1637           nmea_data       * rd,
1638           int                   idx
1639           )
1640 {
1641           UCC *     dp = (UCC*)field_parse(rd, idx);
1642 
1643           return _parse_time(dp, &dp, jd)
1644               && _parse_frac(dp, &dp, fofs)
1645               && _parse_eof (dp, &dp);
1646 }
1647 
1648 /*
1649  * -------------------------------------------------------------------
1650  * Parse a date string from an NMEA sentence. This could either be a
1651  * partial date in DDMMYY format in one field, or DD,MM,YYYY full date
1652  * spec spanning three fields. This function does some extensive error
1653  * checking to make sure the date string was consistent.
1654  *
1655  * returns 1 on success, 0 on failure
1656  * -------------------------------------------------------------------
1657  */
1658 static int
parse_date(struct calendar * jd,nmea_data * rd,int idx,enum date_fmt fmt)1659 parse_date(
1660           struct calendar * jd,         /* result pointer */
1661           nmea_data       * rd,
1662           int                   idx,
1663           enum date_fmt         fmt
1664           )
1665 {
1666           UCC  * dp = (UCC*)field_parse(rd, idx);
1667 
1668           switch (fmt) {
1669           case DATE_1_DDMMYY:
1670                     return _parse_date1(dp, &dp, jd);
1671           case DATE_3_DDMMYYYY:
1672                     return _parse_date3(dp, &dp, jd);
1673           default:
1674                     DPRINTF(1, ("nmea: invalid parse format: %d\n", fmt));
1675                     break;
1676           }
1677           return FALSE;
1678 }
1679 
1680 /*
1681  * -------------------------------------------------------------------
1682  * Parse GPS week time info from an NMEA sentence. This info contains
1683  * the GPS week number, the GPS time-of-week and the leap seconds GPS
1684  * to UTC.
1685  *
1686  * returns 1 on success, 0 on failure
1687  * -------------------------------------------------------------------
1688  */
1689 static int
parse_gpsw(TGpsDatum * wd,nmea_data * rd,int weekidx,int timeidx,int leapidx)1690 parse_gpsw(
1691           TGpsDatum *  wd,
1692           nmea_data *  rd,
1693           int          weekidx,
1694           int          timeidx,
1695           int          leapidx
1696           )
1697 {
1698           uint32_t  secs;
1699           uint16_t  week, leap = 0;
1700           l_fp                fofs;
1701           int                 rc;
1702 
1703           UCC *     dpw = (UCC*)field_parse(rd, weekidx);
1704           UCC *     dps = (UCC*)field_parse(rd, timeidx);
1705 
1706           rc =   _parse_u16 (dpw, &dpw, &week, 5)
1707               && _parse_eof (dpw, &dpw)
1708               && _parse_u32 (dps, &dps, &secs, 9)
1709               && _parse_frac(dps, &dps, &fofs)
1710               && _parse_eof (dps, &dps)
1711               && (secs < 7*SECSPERDAY);
1712           if (rc && leapidx > 0) {
1713                     UCC *     dpl = (UCC*)field_parse(rd, leapidx);
1714                     rc =   _parse_u16 (dpl, &dpl, &leap, 5)
1715                         && _parse_eof (dpl, &dpl);
1716           }
1717           if (rc) {
1718                     fofs.l_ui -= leap;
1719                     *wd = gpscal_from_gpsweek(week, secs, fofs);
1720           } else {
1721                     DPRINTF(1, ("nmea: parse_gpsw: invalid weektime spec\n"));
1722           }
1723           return rc;
1724 }
1725 
1726 
1727 #ifdef HAVE_PPSAPI
1728 static double
tabsdiffd(l_fp t1,l_fp t2)1729 tabsdiffd(
1730           l_fp      t1,
1731           l_fp      t2
1732           )
1733 {
1734           double    dd;
1735           L_SUB(&t1, &t2);
1736           LFPTOD(&t1, dd);
1737           return fabs(dd);
1738 }
1739 #endif /* HAVE_PPSAPI */
1740 
1741 /*
1742  * ===================================================================
1743  *
1744  * NMEAD support
1745  *
1746  * original nmead support added by Jon Miner (cp_n18@yahoo.com)
1747  *
1748  * See http://home.hiwaay.net/~taylorc/gps/nmea-server/
1749  * for information about nmead
1750  *
1751  * To use this, you need to create a link from /dev/gpsX to
1752  * the server:port where nmead is running.  Something like this:
1753  *
1754  * ln -s server:port /dev/gps1
1755  *
1756  * Split into separate function by Juergen Perlinger
1757  * (perlinger-at-ntp-dot-org)
1758  *
1759  * ===================================================================
1760  */
1761 static int
nmead_open(const char * device)1762 nmead_open(
1763           const char * device
1764           )
1765 {
1766           int       fd = -1;            /* result file descriptor */
1767 
1768 #   ifdef HAVE_READLINK
1769           char      host[80];           /* link target buffer         */
1770           char  * port;                           /* port name or number        */
1771           int       rc;                           /* result code (several)*/
1772           int     sh;                             /* socket handle    */
1773           struct addrinfo      ai_hint; /* resolution hint  */
1774           struct addrinfo     *ai_list; /* resolution result          */
1775           struct addrinfo *ai;                    /* result scan ptr  */
1776 
1777           fd = -1;
1778 
1779           /* try to read as link, make sure no overflow occurs */
1780           rc = readlink(device, host, sizeof(host));
1781           if ((size_t)rc >= sizeof(host))
1782                     return fd;          /* error / overflow / truncation */
1783           host[rc] = '\0';    /* readlink does not place NUL          */
1784 
1785           /* get port */
1786           port = strchr(host, ':');
1787           if (!port)
1788                     return fd; /* not 'host:port' syntax ? */
1789           *port++ = '\0';     /* put in separator */
1790 
1791           /* get address infos and try to open socket
1792            *
1793            * This getaddrinfo() is naughty in ntpd's nonblocking main
1794            * thread, but you have to go out of your wary to use this code
1795            * and typically the blocking is at startup where its impact is
1796            * reduced. The same holds for the 'connect()', as it is
1797            * blocking, too...
1798            */
1799           ZERO(ai_hint);
1800           ai_hint.ai_protocol = IPPROTO_TCP;
1801           ai_hint.ai_socktype = SOCK_STREAM;
1802           if (getaddrinfo(host, port, &ai_hint, &ai_list))
1803                     return fd;
1804 
1805           for (ai = ai_list; ai && (fd == -1); ai = ai->ai_next) {
1806                     sh = socket(ai->ai_family, ai->ai_socktype,
1807                                   ai->ai_protocol);
1808                     if (INVALID_SOCKET == sh)
1809                               continue;
1810                     rc = connect(sh, ai->ai_addr, ai->ai_addrlen);
1811                     if (-1 != rc)
1812                               fd = sh;
1813                     else
1814                               close(sh);
1815           }
1816           freeaddrinfo(ai_list);
1817           if (fd != -1)
1818                     make_socket_nonblocking(fd);
1819 #   else
1820           fd = -1;
1821 #   endif
1822 
1823           return fd;
1824 }
1825 #else
1826 NONEMPTY_TRANSLATION_UNIT
1827 #endif /* REFCLOCK && CLOCK_NMEA */
1828