]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ntp/ntpd/refclock_jupiter.c
Fix multiple vulnerabilities of ntp.
[FreeBSD/releng/10.2.git] / contrib / ntp / ntpd / refclock_jupiter.c
1 /*
2  * Copyright (c) 1997, 1998, 2003
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Lawrence Berkeley Laboratory.
17  * 4. The name of the University may not be used to endorse or promote
18  *    products derived from this software without specific prior
19  *    written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #ifdef HAVE_CONFIG_H
35 # include <config.h>
36 #endif
37
38 #if defined(REFCLOCK) && defined(CLOCK_JUPITER) && defined(HAVE_PPSAPI)
39
40 #include "ntpd.h"
41 #include "ntp_io.h"
42 #include "ntp_refclock.h"
43 #include "ntp_unixtime.h"
44 #include "ntp_stdlib.h"
45
46 #include <stdio.h>
47 #include <ctype.h>
48
49 #include "jupiter.h"
50
51 #ifdef HAVE_PPSAPI
52 # include "ppsapi_timepps.h"
53 #endif
54
55 #ifdef WORDS_BIGENDIAN
56 #define getshort(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
57 #define putshort(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
58 #else
59 #define getshort(s) ((u_short)(s))
60 #define putshort(s) ((u_short)(s))
61 #endif
62
63 /*
64  * This driver supports the Rockwell Jupiter GPS Receiver board
65  * adapted to precision timing applications.  It requires the
66  * ppsclock line discipline or streams module described in the
67  * Line Disciplines and Streams Drivers page. It also requires a
68  * gadget box and 1-PPS level converter, such as described in the
69  * Pulse-per-second (PPS) Signal Interfacing page.
70  *
71  * It may work (with minor modifications) with other Rockwell GPS
72  * receivers such as the CityTracker.
73  */
74
75 /*
76  * GPS Definitions
77  */
78 #define DEVICE          "/dev/gps%d"    /* device name and unit */
79 #define SPEED232        B9600           /* baud */
80
81 /*
82  * Radio interface parameters
83  */
84 #define PRECISION       (-18)   /* precision assumed (about 4 us) */
85 #define REFID   "GPS\0"         /* reference id */
86 #define DESCRIPTION     "Rockwell Jupiter GPS Receiver" /* who we are */
87 #define DEFFUDGETIME    0       /* default fudge time (ms) */
88
89 /* Unix timestamp for the GPS epoch: January 6, 1980 */
90 #define GPS_EPOCH 315964800
91
92 /* Rata Die Number of first day of GPS epoch. This is the number of days
93  * since 0000-12-31 to 1980-01-06 in the proleptic Gregorian Calendar.
94  */
95 #define RDN_GPS_EPOCH (4*146097 + 138431 + 1)
96
97 /* Double short to unsigned int */
98 #define DS2UI(p) ((getshort((p)[1]) << 16) | getshort((p)[0]))
99
100 /* Double short to signed int */
101 #define DS2I(p) ((getshort((p)[1]) << 16) | getshort((p)[0]))
102
103 /* One week's worth of seconds */
104 #define WEEKSECS (7 * 24 * 60 * 60)
105
106 /*
107  * Jupiter unit control structure.
108  */
109 struct instance {
110         struct peer *peer;              /* peer */
111         u_int  pollcnt;                 /* poll message counter */
112         u_int  polled;                  /* Hand in a time sample? */
113 #ifdef HAVE_PPSAPI
114         pps_params_t pps_params;        /* pps parameters */
115         pps_info_t pps_info;            /* last pps data */
116         pps_handle_t pps_handle;        /* pps handle */
117         u_int assert;                   /* pps edge to use */
118         u_int hardpps;                  /* enable kernel mode */
119         struct timespec ts;             /* last timestamp */
120 #endif
121         l_fp limit;
122         u_int gpos_gweek;               /* Current GPOS GPS week number */
123         u_int gpos_sweek;               /* Current GPOS GPS seconds into week */
124         u_int gweek;                    /* current GPS week number */
125         u_int32 lastsweek;              /* last seconds into GPS week */
126         time_t timecode;                /* current ntp timecode */
127         u_int32 stime;                  /* used to detect firmware bug */
128         int wantid;                     /* don't reconfig on channel id msg */
129         u_int  moving;                  /* mobile platform? */
130         u_char sloppyclockflag;         /* fudge flags */
131         u_short sbuf[512];              /* local input buffer */
132         int ssize;                      /* space used in sbuf */
133 };
134
135 /*
136  * Function prototypes
137  */
138 static  void    jupiter_canmsg  (struct instance *, u_int);
139 static  u_short jupiter_cksum   (u_short *, u_int);
140 static  int     jupiter_config  (struct instance *);
141 static  void    jupiter_debug   (struct peer *, const char *,
142                                  const char *, ...)
143                         __attribute__ ((format (printf, 3, 4)));
144 static  const char *    jupiter_parse_t (struct instance *, u_short *);
145 static  const char *    jupiter_parse_gpos      (struct instance *, u_short *);
146 static  void    jupiter_platform        (struct instance *, u_int);
147 static  void    jupiter_poll    (int, struct peer *);
148 static  void    jupiter_control (int, const struct refclockstat *,
149                                  struct refclockstat *, struct peer *);
150 #ifdef HAVE_PPSAPI
151 static  int     jupiter_ppsapi  (struct instance *);
152 static  int     jupiter_pps     (struct instance *);
153 #endif /* HAVE_PPSAPI */
154 static  int     jupiter_recv    (struct instance *);
155 static  void    jupiter_receive (struct recvbuf *rbufp);
156 static  void    jupiter_reqmsg  (struct instance *, u_int, u_int);
157 static  void    jupiter_reqonemsg(struct instance *, u_int);
158 static  char *  jupiter_send    (struct instance *, struct jheader *);
159 static  void    jupiter_shutdown(int, struct peer *);
160 static  int     jupiter_start   (int, struct peer *);
161
162 static  u_int   get_full_week(u_int base_week, u_int gpos_week);
163 static  u_int   get_base_week(void);
164
165
166 /*
167  * Transfer vector
168  */
169 struct  refclock refclock_jupiter = {
170         jupiter_start,          /* start up driver */
171         jupiter_shutdown,       /* shut down driver */
172         jupiter_poll,           /* transmit poll message */
173         jupiter_control,        /* (clock control) */
174         noentry,                /* (clock init) */
175         noentry,                /* (clock buginfo) */
176         NOFLAGS                 /* not used */
177 };
178
179 /*
180  * jupiter_start - open the devices and initialize data for processing
181  */
182 static int
183 jupiter_start(
184         int unit,
185         struct peer *peer
186         )
187 {
188         struct refclockproc *pp;
189         struct instance *instance;
190         int fd;
191         char gpsdev[20];
192
193         /*
194          * Open serial port
195          */
196         snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit);
197         fd = refclock_open(gpsdev, SPEED232, LDISC_RAW);
198         if (fd <= 0) {
199                 jupiter_debug(peer, "jupiter_start", "open %s: %m",
200                               gpsdev);
201                 return (0);
202         }
203
204         /* Allocate unit structure */
205         instance = emalloc_zero(sizeof(*instance));
206         instance->peer = peer;
207         pp = peer->procptr;
208         pp->io.clock_recv = jupiter_receive;
209         pp->io.srcclock = peer;
210         pp->io.datalen = 0;
211         pp->io.fd = fd;
212         if (!io_addclock(&pp->io)) {
213                 close(fd);
214                 pp->io.fd = -1;
215                 free(instance);
216                 return (0);
217         }
218         pp->unitptr = instance;
219
220         /*
221          * Initialize miscellaneous variables
222          */
223         peer->precision = PRECISION;
224         pp->clockdesc = DESCRIPTION;
225         memcpy((char *)&pp->refid, REFID, 4);
226
227 #ifdef HAVE_PPSAPI
228         instance->assert = 1;
229         instance->hardpps = 0;
230         /*
231          * Start the PPSAPI interface if it is there. Default to use
232          * the assert edge and do not enable the kernel hardpps.
233          */
234         if (time_pps_create(fd, &instance->pps_handle) < 0) {
235                 instance->pps_handle = 0;
236                 msyslog(LOG_ERR,
237                         "refclock_jupiter: time_pps_create failed: %m");
238         }
239         else if (!jupiter_ppsapi(instance))
240                 goto clean_up;
241 #endif /* HAVE_PPSAPI */
242
243         /* Ensure the receiver is properly configured */
244         if (!jupiter_config(instance))
245                 goto clean_up;
246
247         return (1);
248
249 clean_up:
250         jupiter_shutdown(unit, peer);
251         pp->unitptr = 0;
252         return (0);
253 }
254
255 /*
256  * jupiter_shutdown - shut down the clock
257  */
258 static void
259 jupiter_shutdown(int unit, struct peer *peer)
260 {
261         struct instance *instance;
262         struct refclockproc *pp;
263
264         pp = peer->procptr;
265         instance = pp->unitptr;
266         if (!instance)
267                 return;
268
269 #ifdef HAVE_PPSAPI
270         if (instance->pps_handle) {
271                 time_pps_destroy(instance->pps_handle);
272                 instance->pps_handle = 0;
273         }
274 #endif /* HAVE_PPSAPI */
275
276         if (pp->io.fd != -1)
277                 io_closeclock(&pp->io);
278         free(instance);
279 }
280
281 /*
282  * jupiter_config - Configure the receiver
283  */
284 static int
285 jupiter_config(struct instance *instance)
286 {
287         jupiter_debug(instance->peer, __func__, "init receiver");
288
289         /*
290          * Initialize the unit variables
291          */
292         instance->sloppyclockflag = instance->peer->procptr->sloppyclockflag;
293         instance->moving = !!(instance->sloppyclockflag & CLK_FLAG2);
294         if (instance->moving)
295                 jupiter_debug(instance->peer, __func__, "mobile platform");
296
297         instance->pollcnt     = 2;
298         instance->polled      = 0;
299         instance->gpos_gweek = 0;
300         instance->gpos_sweek = 0;
301         instance->gweek = 0;
302         instance->lastsweek = 2 * WEEKSECS;
303         instance->timecode = 0;
304         instance->stime = 0;
305         instance->ssize = 0;
306
307         /* Stop outputting all messages */
308         jupiter_canmsg(instance, JUPITER_ALL);
309
310         /* Request the receiver id so we can syslog the firmware version */
311         jupiter_reqonemsg(instance, JUPITER_O_ID);
312
313         /* Flag that this the id was requested (so we don't get called again) */
314         instance->wantid = 1;
315
316         /* Request perodic time mark pulse messages */
317         jupiter_reqmsg(instance, JUPITER_O_PULSE, 1);
318
319         /* Request perodic geodetic position status */
320         jupiter_reqmsg(instance, JUPITER_O_GPOS, 1);
321
322         /* Set application platform type */
323         if (instance->moving)
324                 jupiter_platform(instance, JUPITER_I_PLAT_MED);
325         else
326                 jupiter_platform(instance, JUPITER_I_PLAT_LOW);
327
328         return (1);
329 }
330
331 #ifdef HAVE_PPSAPI
332 /*
333  * Initialize PPSAPI
334  */
335 int
336 jupiter_ppsapi(
337         struct instance *instance       /* unit structure pointer */
338         )
339 {
340         int capability;
341
342         if (time_pps_getcap(instance->pps_handle, &capability) < 0) {
343                 msyslog(LOG_ERR,
344                     "refclock_jupiter: time_pps_getcap failed: %m");
345                 return (0);
346         }
347         memset(&instance->pps_params, 0, sizeof(pps_params_t));
348         if (!instance->assert)
349                 instance->pps_params.mode = capability & PPS_CAPTURECLEAR;
350         else
351                 instance->pps_params.mode = capability & PPS_CAPTUREASSERT;
352         if (!(instance->pps_params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR))) {
353                 msyslog(LOG_ERR,
354                     "refclock_jupiter: invalid capture edge %d",
355                     instance->assert);
356                 return (0);
357         }
358         instance->pps_params.mode |= PPS_TSFMT_TSPEC;
359         if (time_pps_setparams(instance->pps_handle, &instance->pps_params) < 0) {
360                 msyslog(LOG_ERR,
361                     "refclock_jupiter: time_pps_setparams failed: %m");
362                 return (0);
363         }
364         if (instance->hardpps) {
365                 if (time_pps_kcbind(instance->pps_handle, PPS_KC_HARDPPS,
366                                     instance->pps_params.mode & ~PPS_TSFMT_TSPEC,
367                                     PPS_TSFMT_TSPEC) < 0) {
368                         msyslog(LOG_ERR,
369                             "refclock_jupiter: time_pps_kcbind failed: %m");
370                         return (0);
371                 }
372                 hardpps_enable = 1;
373         }
374 /*      instance->peer->precision = PPS_PRECISION; */
375
376 #if DEBUG
377         if (debug) {
378                 time_pps_getparams(instance->pps_handle, &instance->pps_params);
379                 jupiter_debug(instance->peer, __func__,
380                         "pps capability 0x%x version %d mode 0x%x kern %d",
381                         capability, instance->pps_params.api_version,
382                         instance->pps_params.mode, instance->hardpps);
383         }
384 #endif
385
386         return (1);
387 }
388
389 /*
390  * Get PPSAPI timestamps.
391  *
392  * Return 0 on failure and 1 on success.
393  */
394 static int
395 jupiter_pps(struct instance *instance)
396 {
397         pps_info_t pps_info;
398         struct timespec timeout, ts;
399         double dtemp;
400         l_fp tstmp;
401
402         /*
403          * Convert the timespec nanoseconds field to ntp l_fp units.
404          */ 
405         if (instance->pps_handle == 0)
406                 return 1;
407         timeout.tv_sec = 0;
408         timeout.tv_nsec = 0;
409         memcpy(&pps_info, &instance->pps_info, sizeof(pps_info_t));
410         if (time_pps_fetch(instance->pps_handle, PPS_TSFMT_TSPEC, &instance->pps_info,
411             &timeout) < 0)
412                 return 1;
413         if (instance->pps_params.mode & PPS_CAPTUREASSERT) {
414                 if (pps_info.assert_sequence ==
415                     instance->pps_info.assert_sequence)
416                         return 1;
417                 ts = instance->pps_info.assert_timestamp;
418         } else if (instance->pps_params.mode & PPS_CAPTURECLEAR) {
419                 if (pps_info.clear_sequence ==
420                     instance->pps_info.clear_sequence)
421                         return 1;
422                 ts = instance->pps_info.clear_timestamp;
423         } else {
424                 return 1;
425         }
426         if ((instance->ts.tv_sec == ts.tv_sec) && (instance->ts.tv_nsec == ts.tv_nsec))
427                 return 1;
428         instance->ts = ts;
429
430         tstmp.l_ui = (u_int32)ts.tv_sec + JAN_1970;
431         dtemp = ts.tv_nsec * FRAC / 1e9;
432         tstmp.l_uf = (u_int32)dtemp;
433         instance->peer->procptr->lastrec = tstmp;
434         return 0;
435 }
436 #endif /* HAVE_PPSAPI */
437
438 /*
439  * jupiter_poll - jupiter watchdog routine
440  */
441 static void
442 jupiter_poll(int unit, struct peer *peer)
443 {
444         struct instance *instance;
445         struct refclockproc *pp;
446
447         pp = peer->procptr;
448         instance = pp->unitptr;
449
450         /*
451          * You don't need to poll this clock.  It puts out timecodes
452          * once per second.  If asked for a timestamp, take note.
453          * The next time a timecode comes in, it will be fed back.
454          */
455
456         /*
457          * If we haven't had a response in a while, reset the receiver.
458          */
459         if (instance->pollcnt > 0) {
460                 instance->pollcnt--;
461         } else {
462                 refclock_report(peer, CEVNT_TIMEOUT);
463
464                 /* Request the receiver id to trigger a reconfig */
465                 jupiter_reqonemsg(instance, JUPITER_O_ID);
466                 instance->wantid = 0;
467         }
468
469         /*
470          * polled every 64 seconds. Ask jupiter_receive to hand in
471          * a timestamp.
472          */
473         instance->polled = 1;
474         pp->polls++;
475 }
476
477 /*
478  * jupiter_control - fudge control
479  */
480 static void
481 jupiter_control(
482         int unit,               /* unit (not used) */
483         const struct refclockstat *in, /* input parameters (not used) */
484         struct refclockstat *out, /* output parameters (not used) */
485         struct peer *peer       /* peer structure pointer */
486         )
487 {
488         struct refclockproc *pp;
489         struct instance *instance;
490         u_char sloppyclockflag;
491
492         pp = peer->procptr;
493         instance = pp->unitptr;
494
495         DTOLFP(pp->fudgetime2, &instance->limit);
496         /* Force positive value. */
497         if (L_ISNEG(&instance->limit))
498                 L_NEG(&instance->limit);
499
500 #ifdef HAVE_PPSAPI
501         instance->assert = !(pp->sloppyclockflag & CLK_FLAG3);
502         jupiter_ppsapi(instance);
503 #endif /* HAVE_PPSAPI */
504
505         sloppyclockflag = instance->sloppyclockflag;
506         instance->sloppyclockflag = pp->sloppyclockflag;
507         if ((instance->sloppyclockflag & CLK_FLAG2) !=
508             (sloppyclockflag & CLK_FLAG2)) {
509                 jupiter_debug(peer, __func__,
510                     "mode switch: reset receiver");
511                 jupiter_config(instance);
512                 return;
513         }
514 }
515
516 /*
517  * jupiter_receive - receive gps data
518  * Gag me!
519  */
520 static void
521 jupiter_receive(struct recvbuf *rbufp)
522 {
523         size_t bpcnt;
524         int cc, size, ppsret;
525         time_t last_timecode;
526         u_int32 laststime;
527         const char *cp;
528         u_char *bp;
529         u_short *sp;
530         struct jid *ip;
531         struct jheader *hp;
532         struct peer *peer;
533         struct refclockproc *pp;
534         struct instance *instance;
535         l_fp tstamp;
536
537         /* Initialize pointers and read the timecode and timestamp */
538         peer = rbufp->recv_peer;
539         pp = peer->procptr;
540         instance = pp->unitptr;
541
542         bp = (u_char *)rbufp->recv_buffer;
543         bpcnt = rbufp->recv_length;
544
545         /* This shouldn't happen */
546         if (bpcnt > sizeof(instance->sbuf) - instance->ssize)
547                 bpcnt = sizeof(instance->sbuf) - instance->ssize;
548
549         /* Append to input buffer */
550         memcpy((u_char *)instance->sbuf + instance->ssize, bp, bpcnt);
551         instance->ssize += bpcnt;
552
553         /* While there's at least a header and we parse an intact message */
554         while (instance->ssize > (int)sizeof(*hp) && (cc = jupiter_recv(instance)) > 0) {
555                 instance->pollcnt = 2;
556
557                 tstamp = rbufp->recv_time;
558                 hp = (struct jheader *)instance->sbuf;
559                 sp = (u_short *)(hp + 1);
560                 size = cc - sizeof(*hp);
561                 switch (getshort(hp->id)) {
562
563                 case JUPITER_O_PULSE:
564                         if (size != sizeof(struct jpulse)) {
565                                 jupiter_debug(peer, __func__,
566                                     "pulse: len %d != %u",
567                                     size, (int)sizeof(struct jpulse));
568                                 refclock_report(peer, CEVNT_BADREPLY);
569                                 break;
570                         }
571
572                         /*
573                          * There appears to be a firmware bug related
574                          * to the pulse message; in addition to the one
575                          * per second messages, we get an extra pulse
576                          * message once an hour (on the anniversary of
577                          * the cold start). It seems to come 200 ms
578                          * after the one requested. So if we've seen a
579                          * pulse message in the last 210 ms, we skip
580                          * this one.
581                          */
582                         laststime = instance->stime;
583                         instance->stime = DS2UI(((struct jpulse *)sp)->stime);
584                         if (laststime != 0 && instance->stime - laststime <= 21) {
585                                 jupiter_debug(peer, __func__,
586                                 "avoided firmware bug (stime %.2f, laststime %.2f)",
587                                 (double)instance->stime * 0.01, (double)laststime * 0.01);
588                                 break;
589                         }
590
591                         /* Retrieve pps timestamp */
592                         ppsret = jupiter_pps(instance);
593
594                         /*
595                          * Add one second if msg received early
596                          * (i.e. before limit, a.k.a. fudgetime2) in
597                          * the second.
598                          */
599                         L_SUB(&tstamp, &pp->lastrec);
600                         if (!L_ISGEQ(&tstamp, &instance->limit))
601                                 ++pp->lastrec.l_ui;
602
603                         /* Parse timecode (even when there's no pps) */
604                         last_timecode = instance->timecode;
605                         if ((cp = jupiter_parse_t(instance, sp)) != NULL) {
606                                 jupiter_debug(peer, __func__,
607                                     "pulse: %s", cp);
608                                 break;
609                         }
610
611                         /* Bail if we didn't get a pps timestamp */
612                         if (ppsret)
613                                 break;
614
615                         /* Bail if we don't have the last timecode yet */
616                         if (last_timecode == 0)
617                                 break;
618
619                         /* Add the new sample to a median filter */
620                         tstamp.l_ui = JAN_1970 + (u_int32)last_timecode;
621                         tstamp.l_uf = 0;
622
623                         refclock_process_offset(pp, tstamp, pp->lastrec, pp->fudgetime1);
624
625                         /*
626                          * The clock will blurt a timecode every second
627                          * but we only want one when polled.  If we
628                          * havn't been polled, bail out.
629                          */
630                         if (!instance->polled)
631                                 break;
632                         instance->polled = 0;
633
634                         /*
635                          * It's a live one!  Remember this time.
636                          */
637
638                         pp->lastref = pp->lastrec;
639                         refclock_receive(peer);
640
641                         /*
642                          * If we get here - what we got from the clock is
643                          * OK, so say so
644                          */
645                         refclock_report(peer, CEVNT_NOMINAL);
646
647                         /*
648                          * We have succeeded in answering the poll.
649                          * Turn off the flag and return
650                          */
651                         instance->polled = 0;
652                         break;
653
654                 case JUPITER_O_GPOS:
655                         if (size != sizeof(struct jgpos)) {
656                                 jupiter_debug(peer, __func__,
657                                     "gpos: len %d != %u",
658                                     size, (int)sizeof(struct jgpos));
659                                 refclock_report(peer, CEVNT_BADREPLY);
660                                 break;
661                         }
662
663                         if ((cp = jupiter_parse_gpos(instance, sp)) != NULL) {
664                                 jupiter_debug(peer, __func__,
665                                     "gpos: %s", cp);
666                                 break;
667                         }
668                         break;
669
670                 case JUPITER_O_ID:
671                         if (size != sizeof(struct jid)) {
672                                 jupiter_debug(peer, __func__,
673                                     "id: len %d != %u",
674                                     size, (int)sizeof(struct jid));
675                                 refclock_report(peer, CEVNT_BADREPLY);
676                                 break;
677                         }
678                         /*
679                          * If we got this message because the Jupiter
680                          * just powered instance, it needs to be reconfigured.
681                          */
682                         ip = (struct jid *)sp;
683                         jupiter_debug(peer, __func__,
684                             "%s chan ver %s, %s (%s)",
685                             ip->chans, ip->vers, ip->date, ip->opts);
686                         msyslog(LOG_DEBUG,
687                             "jupiter_receive: %s chan ver %s, %s (%s)",
688                             ip->chans, ip->vers, ip->date, ip->opts);
689                         if (instance->wantid)
690                                 instance->wantid = 0;
691                         else {
692                                 jupiter_debug(peer, __func__, "reset receiver");
693                                 jupiter_config(instance);
694                                 /*
695                                  * Restore since jupiter_config() just
696                                  * zeroed it
697                                  */
698                                 instance->ssize = cc;
699                         }
700                         break;
701
702                 default:
703                         jupiter_debug(peer, __func__, "unknown message id %d",
704                             getshort(hp->id));
705                         break;
706                 }
707                 instance->ssize -= cc;
708                 if (instance->ssize < 0) {
709                         fprintf(stderr, "jupiter_recv: negative ssize!\n");
710                         abort();
711                 } else if (instance->ssize > 0)
712                         memcpy(instance->sbuf, (u_char *)instance->sbuf + cc, instance->ssize);
713         }
714 }
715
716 static const char *
717 jupiter_parse_t(struct instance *instance, u_short *sp)
718 {
719         struct tm *tm;
720         char *cp;
721         struct jpulse *jp;
722         u_int32 sweek;
723         time_t last_timecode;
724         u_short flags;
725
726         jp = (struct jpulse *)sp;
727
728         /* The timecode is presented as seconds into the current GPS week */
729         sweek = DS2UI(jp->sweek) % WEEKSECS;
730
731         /*
732          * If we don't know the current GPS week, calculate it from the
733          * current time. (It's too bad they didn't include this
734          * important value in the pulse message). We'd like to pick it
735          * up from one of the other messages like gpos or chan but they
736          * don't appear to be synchronous with time keeping and changes
737          * too soon (something like 10 seconds before the new GPS
738          * week).
739          *
740          * If we already know the current GPS week, increment it when
741          * we wrap into a new week.
742          */
743         if (instance->gweek == 0) {
744                 if (!instance->gpos_gweek) {
745                         return ("jupiter_parse_t: Unknown gweek");
746                 }
747
748                 instance->gweek = instance->gpos_gweek;
749
750                 /*
751                  * Fix warps. GPOS has GPS time and PULSE has UTC.
752                  * Plus, GPOS need not be completely in synch with
753                  * the PPS signal.
754                  */
755                 if (instance->gpos_sweek >= sweek) {
756                         if ((instance->gpos_sweek - sweek) > WEEKSECS / 2)
757                                 ++instance->gweek;
758                 }
759                 else {
760                         if ((sweek - instance->gpos_sweek) > WEEKSECS / 2)
761                                 --instance->gweek;
762                 }
763         }
764         else if (sweek == 0 && instance->lastsweek == WEEKSECS - 1) {
765                 ++instance->gweek;
766                 jupiter_debug(instance->peer, __func__,
767                     "NEW gps week %u", instance->gweek);
768         }
769
770         /*
771          * See if the sweek stayed the same (this happens when there is
772          * no pps pulse).
773          *
774          * Otherwise, look for time warps:
775          *
776          *   - we have stored at least one lastsweek and
777          *   - the sweek didn't increase by one and
778          *   - we didn't wrap to a new GPS week
779          *
780          * Then we warped.
781          */
782         if (instance->lastsweek == sweek)
783                 jupiter_debug(instance->peer, __func__,
784                     "gps sweek not incrementing (%d)",
785                     sweek);
786         else if (instance->lastsweek != 2 * WEEKSECS &&
787             instance->lastsweek + 1 != sweek &&
788             !(sweek == 0 && instance->lastsweek == WEEKSECS - 1))
789                 jupiter_debug(instance->peer, __func__,
790                     "gps sweek jumped (was %d, now %d)",
791                     instance->lastsweek, sweek);
792         instance->lastsweek = sweek;
793
794         /* This timecode describes next pulse */
795         last_timecode = instance->timecode;
796         instance->timecode =
797             GPS_EPOCH + (instance->gweek * WEEKSECS) + sweek;
798
799         if (last_timecode == 0)
800                 /* XXX debugging */
801                 jupiter_debug(instance->peer, __func__,
802                     "UTC <none> (gweek/sweek %u/%u)",
803                     instance->gweek, sweek);
804         else {
805                 /* XXX debugging */
806                 tm = gmtime(&last_timecode);
807                 cp = asctime(tm);
808
809                 jupiter_debug(instance->peer, __func__,
810                     "UTC %.24s (gweek/sweek %u/%u)",
811                     cp, instance->gweek, sweek);
812
813                 /* Billboard last_timecode (which is now the current time) */
814                 instance->peer->procptr->year   = tm->tm_year + 1900;
815                 instance->peer->procptr->day    = tm->tm_yday + 1;
816                 instance->peer->procptr->hour   = tm->tm_hour;
817                 instance->peer->procptr->minute = tm->tm_min;
818                 instance->peer->procptr->second = tm->tm_sec;
819         }
820
821         flags = getshort(jp->flags);
822
823         /* Toss if not designated "valid" by the gps */
824         if ((flags & JUPITER_O_PULSE_VALID) == 0) {
825                 refclock_report(instance->peer, CEVNT_BADTIME);
826                 return ("time mark not valid");
827         }
828
829         /* We better be sync'ed to UTC... */
830         if ((flags & JUPITER_O_PULSE_UTC) == 0) {
831                 refclock_report(instance->peer, CEVNT_BADTIME);
832                 return ("time mark not sync'ed to UTC");
833         }
834
835         return (NULL);
836 }
837
838 static const char *
839 jupiter_parse_gpos(struct instance *instance, u_short *sp)
840 {
841         struct jgpos *jg;
842         time_t t;
843         struct tm *tm;
844         char *cp;
845
846         jg = (struct jgpos *)sp;
847
848         if (jg->navval != 0) {
849                 /*
850                  * Solution not valid. Use caution and refuse
851                  * to determine GPS week from this message.
852                  */
853                 instance->gpos_gweek = 0;
854                 instance->gpos_sweek = 0;
855                 return ("Navigation solution not valid");
856         }
857
858         instance->gpos_sweek = DS2UI(jg->sweek);
859         instance->gpos_gweek = get_full_week(get_base_week(),
860                                              getshort(jg->gweek));
861
862         /* according to the protocol spec, the seconds-in-week cannot
863          * exceed the nominal value: Is it really necessary to normalise
864          * the seconds???
865          */
866         while(instance->gpos_sweek >= WEEKSECS) {
867                 instance->gpos_sweek -= WEEKSECS;
868                 ++instance->gpos_gweek;
869         }
870         instance->gweek = 0;
871
872         t = GPS_EPOCH + (instance->gpos_gweek * WEEKSECS) + instance->gpos_sweek;
873         tm = gmtime(&t);
874         cp = asctime(tm);
875
876         jupiter_debug(instance->peer, __func__,
877                 "GPS %.24s (gweek/sweek %u/%u)",
878                 cp, instance->gpos_gweek, instance->gpos_sweek);
879         return (NULL);
880 }
881
882 /*
883  * jupiter_debug - print debug messages
884  */
885 static void
886 jupiter_debug(
887         struct peer *   peer,
888         const char *    function,
889         const char *    fmt,
890         ...
891         )
892 {
893         char    buffer[200];
894         va_list ap;
895
896         va_start(ap, fmt);
897         /*
898          * Print debug message to stdout
899          * In the future, we may want to get get more creative...
900          */
901         mvsnprintf(buffer, sizeof(buffer), fmt, ap);
902         record_clock_stats(&peer->srcadr, buffer);
903 #ifdef DEBUG
904         if (debug) {
905                 printf("%s: %s\n", function, buffer);
906                 fflush(stdout);
907         }
908 #endif
909
910         va_end(ap);
911 }
912
913 /* Checksum and transmit a message to the Jupiter */
914 static char *
915 jupiter_send(struct instance *instance, struct jheader *hp)
916 {
917         u_int len, size;
918         ssize_t cc;
919         u_short *sp;
920         static char errstr[132];
921
922         size = sizeof(*hp);
923         hp->hsum = putshort(jupiter_cksum((u_short *)hp,
924             (size / sizeof(u_short)) - 1));
925         len = getshort(hp->len);
926         if (len > 0) {
927                 sp = (u_short *)(hp + 1);
928                 sp[len] = putshort(jupiter_cksum(sp, len));
929                 size += (len + 1) * sizeof(u_short);
930         }
931
932         if ((cc = write(instance->peer->procptr->io.fd, (char *)hp, size)) < 0) {
933                 msnprintf(errstr, sizeof(errstr), "write: %m");
934                 return (errstr);
935         } else if (cc != (int)size) {
936                 snprintf(errstr, sizeof(errstr), "short write (%zd != %u)", cc, size);
937                 return (errstr);
938         }
939         return (NULL);
940 }
941
942 /* Request periodic message output */
943 static struct {
944         struct jheader jheader;
945         struct jrequest jrequest;
946 } reqmsg = {
947         { putshort(JUPITER_SYNC), 0,
948             putshort((sizeof(struct jrequest) / sizeof(u_short)) - 1),
949             0, JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK |
950             JUPITER_FLAG_CONN | JUPITER_FLAG_LOG, 0 },
951         { 0, 0, 0, 0 }
952 };
953
954 /* An interval of zero means to output on trigger */
955 static void
956 jupiter_reqmsg(struct instance *instance, u_int id,
957     u_int interval)
958 {
959         struct jheader *hp;
960         struct jrequest *rp;
961         char *cp;
962
963         hp = &reqmsg.jheader;
964         hp->id = putshort(id);
965         rp = &reqmsg.jrequest;
966         rp->trigger = putshort(interval == 0);
967         rp->interval = putshort(interval);
968         if ((cp = jupiter_send(instance, hp)) != NULL)
969                 jupiter_debug(instance->peer, __func__, "%u: %s", id, cp);
970 }
971
972 /* Cancel periodic message output */
973 static struct jheader canmsg = {
974         putshort(JUPITER_SYNC), 0, 0, 0,
975         JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_DISC,
976         0
977 };
978
979 static void
980 jupiter_canmsg(struct instance *instance, u_int id)
981 {
982         struct jheader *hp;
983         char *cp;
984
985         hp = &canmsg;
986         hp->id = putshort(id);
987         if ((cp = jupiter_send(instance, hp)) != NULL)
988                 jupiter_debug(instance->peer, __func__, "%u: %s", id, cp);
989 }
990
991 /* Request a single message output */
992 static struct jheader reqonemsg = {
993         putshort(JUPITER_SYNC), 0, 0, 0,
994         JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_QUERY,
995         0
996 };
997
998 static void
999 jupiter_reqonemsg(struct instance *instance, u_int id)
1000 {
1001         struct jheader *hp;
1002         char *cp;
1003
1004         hp = &reqonemsg;
1005         hp->id = putshort(id);
1006         if ((cp = jupiter_send(instance, hp)) != NULL)
1007                 jupiter_debug(instance->peer, __func__, "%u: %s", id, cp);
1008 }
1009
1010 /* Set the platform dynamics */
1011 static struct {
1012         struct jheader jheader;
1013         struct jplat jplat;
1014 } platmsg = {
1015         { putshort(JUPITER_SYNC), putshort(JUPITER_I_PLAT),
1016             putshort((sizeof(struct jplat) / sizeof(u_short)) - 1), 0,
1017             JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK, 0 },
1018         { 0, 0, 0 }
1019 };
1020
1021 static void
1022 jupiter_platform(struct instance *instance, u_int platform)
1023 {
1024         struct jheader *hp;
1025         struct jplat *pp;
1026         char *cp;
1027
1028         hp = &platmsg.jheader;
1029         pp = &platmsg.jplat;
1030         pp->platform = putshort(platform);
1031         if ((cp = jupiter_send(instance, hp)) != NULL)
1032                 jupiter_debug(instance->peer, __func__, "%u: %s", platform, cp);
1033 }
1034
1035 /* Checksum "len" shorts */
1036 static u_short
1037 jupiter_cksum(u_short *sp, u_int len)
1038 {
1039         u_short sum, x;
1040
1041         sum = 0;
1042         while (len-- > 0) {
1043                 x = *sp++;
1044                 sum += getshort(x);
1045         }
1046         return (~sum + 1);
1047 }
1048
1049 /* Return the size of the next message (or zero if we don't have it all yet) */
1050 static int
1051 jupiter_recv(struct instance *instance)
1052 {
1053         int n, len, size, cc;
1054         struct jheader *hp;
1055         u_char *bp;
1056         u_short *sp;
1057
1058         /* Must have at least a header's worth */
1059         cc = sizeof(*hp);
1060         size = instance->ssize;
1061         if (size < cc)
1062                 return (0);
1063
1064         /* Search for the sync short if missing */
1065         sp = instance->sbuf;
1066         hp = (struct jheader *)sp;
1067         if (getshort(hp->sync) != JUPITER_SYNC) {
1068                 /* Wasn't at the front, sync up */
1069                 jupiter_debug(instance->peer, __func__, "syncing");
1070                 bp = (u_char *)sp;
1071                 n = size;
1072                 while (n >= 2) {
1073                         if (bp[0] != (JUPITER_SYNC & 0xff)) {
1074                                 /*
1075                                 jupiter_debug(instance->peer, __func__,
1076                                     "{0x%x}", bp[0]);
1077                                 */
1078                                 ++bp;
1079                                 --n;
1080                                 continue;
1081                         }
1082                         if (bp[1] == ((JUPITER_SYNC >> 8) & 0xff))
1083                                 break;
1084                         /*
1085                         jupiter_debug(instance->peer, __func__,
1086                             "{0x%x 0x%x}", bp[0], bp[1]);
1087                         */
1088                         bp += 2;
1089                         n -= 2;
1090                 }
1091                 /*
1092                 jupiter_debug(instance->peer, __func__, "\n");
1093                 */
1094                 /* Shuffle data to front of input buffer */
1095                 if (n > 0)
1096                         memcpy(sp, bp, n);
1097                 size = n;
1098                 instance->ssize = size;
1099                 if (size < cc || hp->sync != JUPITER_SYNC)
1100                         return (0);
1101         }
1102
1103         if (jupiter_cksum(sp, (cc / sizeof(u_short) - 1)) !=
1104             getshort(hp->hsum)) {
1105             jupiter_debug(instance->peer, __func__, "bad header checksum!");
1106                 /* This is drastic but checksum errors should be rare */
1107                 instance->ssize = 0;
1108                 return (0);
1109         }
1110
1111         /* Check for a payload */
1112         len = getshort(hp->len);
1113         if (len > 0) {
1114                 n = (len + 1) * sizeof(u_short);
1115                 /* Not enough data yet */
1116                 if (size < cc + n)
1117                         return (0);
1118
1119                 /* Check payload checksum */
1120                 sp = (u_short *)(hp + 1);
1121                 if (jupiter_cksum(sp, len) != getshort(sp[len])) {
1122                         jupiter_debug(instance->peer,
1123                             __func__, "bad payload checksum!");
1124                         /* This is drastic but checksum errors should be rare */
1125                         instance->ssize = 0;
1126                         return (0);
1127                 }
1128                 cc += n;
1129         }
1130         return (cc);
1131 }
1132
1133 static u_int
1134 get_base_week(void)
1135 {
1136         static int      init_done /* = 0 */;
1137         static u_int    base_week;
1138
1139         /* Get the build date, convert to days since GPS epoch and
1140          * finally weeks since GPS epoch.  Note that the build stamp is
1141          * trusted once it is fetched -- only dates before the GPS epoch
1142          * are not permitted. This will permit proper synchronisation
1143          * for a time range of 1024 weeks starting with 00:00:00 of the
1144          * last Sunday on or before the build time.
1145          *
1146          * If the impossible happens and fetching the build date fails,
1147          * a 1024-week cycle starting with 2016-01-03 is assumed to
1148          * avoid catastropic errors. This will work until 2035-08-19.
1149          */
1150         if (!init_done) {
1151                 struct calendar bd;
1152                 if (ntpcal_get_build_date(&bd)) {
1153                         int32_t days = ntpcal_date_to_rd(&bd);
1154                         if (days > RDN_GPS_EPOCH)
1155                                 days -= RDN_GPS_EPOCH;
1156                         else
1157                                 days = 0;
1158                         base_week = days / 7; 
1159                 } else {
1160                         base_week = 1878; /* 2016-01-03, Sunday */
1161                         msyslog(LOG_ERR,
1162                                 "refclock_jupiter: ntpcal_get_build_date() failed: %s",
1163                                 "using 2016-01-03 as GPS base!");
1164                 }
1165                 init_done = 1;
1166         }
1167         return base_week;
1168 }
1169
1170 static u_int
1171 get_full_week(
1172         u_int base_week,
1173         u_int gpos_week
1174         )
1175 {
1176         /* Periodic extension on base week. Since the period is 1024
1177          * weeks and we do unsigned arithmetic here, we can do wonderful
1178          * things with masks and the well-defined overflow behaviour.
1179          */
1180         return base_week + ((gpos_week - base_week) & 1023);
1181 }
1182
1183 #else /* not (REFCLOCK && CLOCK_JUPITER && HAVE_PPSAPI) */
1184 int refclock_jupiter_bs;
1185 #endif /* not (REFCLOCK && CLOCK_JUPITER && HAVE_PPSAPI) */