"Fossies" - the Fresh Open Source Software Archive

Member "ntp-4.2.8p15/ntpd/refclock_nmea.c" (23 Jun 2020, 51818 Bytes) of package /linux/misc/ntp-4.2.8p15.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "refclock_nmea.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.2.8p14_vs_4.2.8p15.

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