]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ntp/ntpd/refclock_jupiter.c
Update ntpd to 4.2.8p13 to fix authenticated denial of service.
[FreeBSD/FreeBSD.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 *, ...) NTP_PRINTF(3, 4);
143 static  const char *    jupiter_parse_t (struct instance *, u_short *);
144 static  const char *    jupiter_parse_gpos      (struct instance *, u_short *);
145 static  void    jupiter_platform        (struct instance *, u_int);
146 static  void    jupiter_poll    (int, struct peer *);
147 static  void    jupiter_control (int, const struct refclockstat *,
148                                  struct refclockstat *, struct peer *);
149 #ifdef HAVE_PPSAPI
150 static  int     jupiter_ppsapi  (struct instance *);
151 static  int     jupiter_pps     (struct instance *);
152 #endif /* HAVE_PPSAPI */
153 static  int     jupiter_recv    (struct instance *);
154 static  void    jupiter_receive (struct recvbuf *rbufp);
155 static  void    jupiter_reqmsg  (struct instance *, u_int, u_int);
156 static  void    jupiter_reqonemsg(struct instance *, u_int);
157 static  char *  jupiter_send    (struct instance *, struct jheader *);
158 static  void    jupiter_shutdown(int, struct peer *);
159 static  int     jupiter_start   (int, struct peer *);
160
161 /*
162  * Transfer vector
163  */
164 struct  refclock refclock_jupiter = {
165         jupiter_start,          /* start up driver */
166         jupiter_shutdown,       /* shut down driver */
167         jupiter_poll,           /* transmit poll message */
168         jupiter_control,        /* (clock control) */
169         noentry,                /* (clock init) */
170         noentry,                /* (clock buginfo) */
171         NOFLAGS                 /* not used */
172 };
173
174 /*
175  * jupiter_start - open the devices and initialize data for processing
176  */
177 static int
178 jupiter_start(
179         int unit,
180         struct peer *peer
181         )
182 {
183         struct refclockproc *pp;
184         struct instance *instance;
185         int fd;
186         char gpsdev[20];
187
188         /*
189          * Open serial port
190          */
191         snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit);
192         fd = refclock_open(gpsdev, SPEED232, LDISC_RAW);
193         if (fd <= 0) {
194                 jupiter_debug(peer, "jupiter_start", "open %s: %m",
195                               gpsdev);
196                 return (0);
197         }
198
199         /* Allocate unit structure */
200         instance = emalloc_zero(sizeof(*instance));
201         instance->peer = peer;
202         pp = peer->procptr;
203         pp->io.clock_recv = jupiter_receive;
204         pp->io.srcclock = peer;
205         pp->io.datalen = 0;
206         pp->io.fd = fd;
207         if (!io_addclock(&pp->io)) {
208                 close(fd);
209                 pp->io.fd = -1;
210                 free(instance);
211                 return (0);
212         }
213         pp->unitptr = instance;
214
215         /*
216          * Initialize miscellaneous variables
217          */
218         peer->precision = PRECISION;
219         pp->clockdesc = DESCRIPTION;
220         memcpy((char *)&pp->refid, REFID, 4);
221
222 #ifdef HAVE_PPSAPI
223         instance->assert = 1;
224         instance->hardpps = 0;
225         /*
226          * Start the PPSAPI interface if it is there. Default to use
227          * the assert edge and do not enable the kernel hardpps.
228          */
229         if (time_pps_create(fd, &instance->pps_handle) < 0) {
230                 instance->pps_handle = 0;
231                 msyslog(LOG_ERR,
232                         "refclock_jupiter: time_pps_create failed: %m");
233         }
234         else if (!jupiter_ppsapi(instance))
235                 goto clean_up;
236 #endif /* HAVE_PPSAPI */
237
238         /* Ensure the receiver is properly configured */
239         if (!jupiter_config(instance))
240                 goto clean_up;
241
242         return (1);
243
244 clean_up:
245         jupiter_shutdown(unit, peer);
246         pp->unitptr = 0;
247         return (0);
248 }
249
250 /*
251  * jupiter_shutdown - shut down the clock
252  */
253 static void
254 jupiter_shutdown(int unit, struct peer *peer)
255 {
256         struct instance *instance;
257         struct refclockproc *pp;
258
259         pp = peer->procptr;
260         instance = pp->unitptr;
261         if (!instance)
262                 return;
263
264 #ifdef HAVE_PPSAPI
265         if (instance->pps_handle) {
266                 time_pps_destroy(instance->pps_handle);
267                 instance->pps_handle = 0;
268         }
269 #endif /* HAVE_PPSAPI */
270
271         if (pp->io.fd != -1)
272                 io_closeclock(&pp->io);
273         free(instance);
274 }
275
276 /*
277  * jupiter_config - Configure the receiver
278  */
279 static int
280 jupiter_config(struct instance *instance)
281 {
282         jupiter_debug(instance->peer, __func__, "init receiver");
283
284         /*
285          * Initialize the unit variables
286          */
287         instance->sloppyclockflag = instance->peer->procptr->sloppyclockflag;
288         instance->moving = !!(instance->sloppyclockflag & CLK_FLAG2);
289         if (instance->moving)
290                 jupiter_debug(instance->peer, __func__, "mobile platform");
291
292         instance->pollcnt     = 2;
293         instance->polled      = 0;
294         instance->gpos_gweek = 0;
295         instance->gpos_sweek = 0;
296         instance->gweek = 0;
297         instance->lastsweek = 2 * WEEKSECS;
298         instance->timecode = 0;
299         instance->stime = 0;
300         instance->ssize = 0;
301
302         /* Stop outputting all messages */
303         jupiter_canmsg(instance, JUPITER_ALL);
304
305         /* Request the receiver id so we can syslog the firmware version */
306         jupiter_reqonemsg(instance, JUPITER_O_ID);
307
308         /* Flag that this the id was requested (so we don't get called again) */
309         instance->wantid = 1;
310
311         /* Request perodic time mark pulse messages */
312         jupiter_reqmsg(instance, JUPITER_O_PULSE, 1);
313
314         /* Request perodic geodetic position status */
315         jupiter_reqmsg(instance, JUPITER_O_GPOS, 1);
316
317         /* Set application platform type */
318         if (instance->moving)
319                 jupiter_platform(instance, JUPITER_I_PLAT_MED);
320         else
321                 jupiter_platform(instance, JUPITER_I_PLAT_LOW);
322
323         return (1);
324 }
325
326 #ifdef HAVE_PPSAPI
327 /*
328  * Initialize PPSAPI
329  */
330 int
331 jupiter_ppsapi(
332         struct instance *instance       /* unit structure pointer */
333         )
334 {
335         int capability;
336
337         if (time_pps_getcap(instance->pps_handle, &capability) < 0) {
338                 msyslog(LOG_ERR,
339                     "refclock_jupiter: time_pps_getcap failed: %m");
340                 return (0);
341         }
342         memset(&instance->pps_params, 0, sizeof(pps_params_t));
343         if (!instance->assert)
344                 instance->pps_params.mode = capability & PPS_CAPTURECLEAR;
345         else
346                 instance->pps_params.mode = capability & PPS_CAPTUREASSERT;
347         if (!(instance->pps_params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR))) {
348                 msyslog(LOG_ERR,
349                     "refclock_jupiter: invalid capture edge %d",
350                     instance->assert);
351                 return (0);
352         }
353         instance->pps_params.mode |= PPS_TSFMT_TSPEC;
354         if (time_pps_setparams(instance->pps_handle, &instance->pps_params) < 0) {
355                 msyslog(LOG_ERR,
356                     "refclock_jupiter: time_pps_setparams failed: %m");
357                 return (0);
358         }
359         if (instance->hardpps) {
360                 if (time_pps_kcbind(instance->pps_handle, PPS_KC_HARDPPS,
361                                     instance->pps_params.mode & ~PPS_TSFMT_TSPEC,
362                                     PPS_TSFMT_TSPEC) < 0) {
363                         msyslog(LOG_ERR,
364                             "refclock_jupiter: time_pps_kcbind failed: %m");
365                         return (0);
366                 }
367                 hardpps_enable = 1;
368         }
369 /*      instance->peer->precision = PPS_PRECISION; */
370
371 #if DEBUG
372         if (debug) {
373                 time_pps_getparams(instance->pps_handle, &instance->pps_params);
374                 jupiter_debug(instance->peer, __func__,
375                         "pps capability 0x%x version %d mode 0x%x kern %d",
376                         capability, instance->pps_params.api_version,
377                         instance->pps_params.mode, instance->hardpps);
378         }
379 #endif
380
381         return (1);
382 }
383
384 /*
385  * Get PPSAPI timestamps.
386  *
387  * Return 0 on failure and 1 on success.
388  */
389 static int
390 jupiter_pps(struct instance *instance)
391 {
392         pps_info_t pps_info;
393         struct timespec timeout, ts;
394         double dtemp;
395         l_fp tstmp;
396
397         /*
398          * Convert the timespec nanoseconds field to ntp l_fp units.
399          */ 
400         if (instance->pps_handle == 0)
401                 return 1;
402         timeout.tv_sec = 0;
403         timeout.tv_nsec = 0;
404         memcpy(&pps_info, &instance->pps_info, sizeof(pps_info_t));
405         if (time_pps_fetch(instance->pps_handle, PPS_TSFMT_TSPEC, &instance->pps_info,
406             &timeout) < 0)
407                 return 1;
408         if (instance->pps_params.mode & PPS_CAPTUREASSERT) {
409                 if (pps_info.assert_sequence ==
410                     instance->pps_info.assert_sequence)
411                         return 1;
412                 ts = instance->pps_info.assert_timestamp;
413         } else if (instance->pps_params.mode & PPS_CAPTURECLEAR) {
414                 if (pps_info.clear_sequence ==
415                     instance->pps_info.clear_sequence)
416                         return 1;
417                 ts = instance->pps_info.clear_timestamp;
418         } else {
419                 return 1;
420         }
421         if ((instance->ts.tv_sec == ts.tv_sec) && (instance->ts.tv_nsec == ts.tv_nsec))
422                 return 1;
423         instance->ts = ts;
424
425         tstmp.l_ui = (u_int32)ts.tv_sec + JAN_1970;
426         dtemp = ts.tv_nsec * FRAC / 1e9;
427         tstmp.l_uf = (u_int32)dtemp;
428         instance->peer->procptr->lastrec = tstmp;
429         return 0;
430 }
431 #endif /* HAVE_PPSAPI */
432
433 /*
434  * jupiter_poll - jupiter watchdog routine
435  */
436 static void
437 jupiter_poll(int unit, struct peer *peer)
438 {
439         struct instance *instance;
440         struct refclockproc *pp;
441
442         pp = peer->procptr;
443         instance = pp->unitptr;
444
445         /*
446          * You don't need to poll this clock.  It puts out timecodes
447          * once per second.  If asked for a timestamp, take note.
448          * The next time a timecode comes in, it will be fed back.
449          */
450
451         /*
452          * If we haven't had a response in a while, reset the receiver.
453          */
454         if (instance->pollcnt > 0) {
455                 instance->pollcnt--;
456         } else {
457                 refclock_report(peer, CEVNT_TIMEOUT);
458
459                 /* Request the receiver id to trigger a reconfig */
460                 jupiter_reqonemsg(instance, JUPITER_O_ID);
461                 instance->wantid = 0;
462         }
463
464         /*
465          * polled every 64 seconds. Ask jupiter_receive to hand in
466          * a timestamp.
467          */
468         instance->polled = 1;
469         pp->polls++;
470 }
471
472 /*
473  * jupiter_control - fudge control
474  */
475 static void
476 jupiter_control(
477         int unit,               /* unit (not used) */
478         const struct refclockstat *in, /* input parameters (not used) */
479         struct refclockstat *out, /* output parameters (not used) */
480         struct peer *peer       /* peer structure pointer */
481         )
482 {
483         struct refclockproc *pp;
484         struct instance *instance;
485         u_char sloppyclockflag;
486
487         pp = peer->procptr;
488         instance = pp->unitptr;
489
490         DTOLFP(pp->fudgetime2, &instance->limit);
491         /* Force positive value. */
492         if (L_ISNEG(&instance->limit))
493                 L_NEG(&instance->limit);
494
495 #ifdef HAVE_PPSAPI
496         instance->assert = !(pp->sloppyclockflag & CLK_FLAG3);
497         jupiter_ppsapi(instance);
498 #endif /* HAVE_PPSAPI */
499
500         sloppyclockflag = instance->sloppyclockflag;
501         instance->sloppyclockflag = pp->sloppyclockflag;
502         if ((instance->sloppyclockflag & CLK_FLAG2) !=
503             (sloppyclockflag & CLK_FLAG2)) {
504                 jupiter_debug(peer, __func__,
505                     "mode switch: reset receiver");
506                 jupiter_config(instance);
507                 return;
508         }
509 }
510
511 /*
512  * jupiter_receive - receive gps data
513  * Gag me!
514  */
515 static void
516 jupiter_receive(struct recvbuf *rbufp)
517 {
518         size_t bpcnt;
519         int cc, size, ppsret;
520         time_t last_timecode;
521         u_int32 laststime;
522         const char *cp;
523         u_char *bp;
524         u_short *sp;
525         struct jid *ip;
526         struct jheader *hp;
527         struct peer *peer;
528         struct refclockproc *pp;
529         struct instance *instance;
530         l_fp tstamp;
531
532         /* Initialize pointers and read the timecode and timestamp */
533         peer = rbufp->recv_peer;
534         pp = peer->procptr;
535         instance = pp->unitptr;
536
537         bp = (u_char *)rbufp->recv_buffer;
538         bpcnt = rbufp->recv_length;
539
540         /* This shouldn't happen */
541         if (bpcnt > sizeof(instance->sbuf) - instance->ssize)
542                 bpcnt = sizeof(instance->sbuf) - instance->ssize;
543
544         /* Append to input buffer */
545         memcpy((u_char *)instance->sbuf + instance->ssize, bp, bpcnt);
546         instance->ssize += bpcnt;
547
548         /* While there's at least a header and we parse an intact message */
549         while (instance->ssize > (int)sizeof(*hp) && (cc = jupiter_recv(instance)) > 0) {
550                 instance->pollcnt = 2;
551
552                 tstamp = rbufp->recv_time;
553                 hp = (struct jheader *)instance->sbuf;
554                 sp = (u_short *)(hp + 1);
555                 size = cc - sizeof(*hp);
556                 switch (getshort(hp->id)) {
557
558                 case JUPITER_O_PULSE:
559                         if (size != sizeof(struct jpulse)) {
560                                 jupiter_debug(peer, __func__,
561                                     "pulse: len %d != %u",
562                                     size, (int)sizeof(struct jpulse));
563                                 refclock_report(peer, CEVNT_BADREPLY);
564                                 break;
565                         }
566
567                         /*
568                          * There appears to be a firmware bug related
569                          * to the pulse message; in addition to the one
570                          * per second messages, we get an extra pulse
571                          * message once an hour (on the anniversary of
572                          * the cold start). It seems to come 200 ms
573                          * after the one requested. So if we've seen a
574                          * pulse message in the last 210 ms, we skip
575                          * this one.
576                          */
577                         laststime = instance->stime;
578                         instance->stime = DS2UI(((struct jpulse *)sp)->stime);
579                         if (laststime != 0 && instance->stime - laststime <= 21) {
580                                 jupiter_debug(peer, __func__,
581                                 "avoided firmware bug (stime %.2f, laststime %.2f)",
582                                 (double)instance->stime * 0.01, (double)laststime * 0.01);
583                                 break;
584                         }
585
586                         /* Retrieve pps timestamp */
587                         ppsret = jupiter_pps(instance);
588
589                         /*
590                          * Add one second if msg received early
591                          * (i.e. before limit, a.k.a. fudgetime2) in
592                          * the second.
593                          */
594                         L_SUB(&tstamp, &pp->lastrec);
595                         if (!L_ISGEQ(&tstamp, &instance->limit))
596                                 ++pp->lastrec.l_ui;
597
598                         /* Parse timecode (even when there's no pps) */
599                         last_timecode = instance->timecode;
600                         if ((cp = jupiter_parse_t(instance, sp)) != NULL) {
601                                 jupiter_debug(peer, __func__,
602                                     "pulse: %s", cp);
603                                 break;
604                         }
605
606                         /* Bail if we didn't get a pps timestamp */
607                         if (ppsret)
608                                 break;
609
610                         /* Bail if we don't have the last timecode yet */
611                         if (last_timecode == 0)
612                                 break;
613
614                         /* Add the new sample to a median filter */
615                         tstamp.l_ui = JAN_1970 + (u_int32)last_timecode;
616                         tstamp.l_uf = 0;
617
618                         refclock_process_offset(pp, tstamp, pp->lastrec, pp->fudgetime1);
619
620                         /*
621                          * The clock will blurt a timecode every second
622                          * but we only want one when polled.  If we
623                          * havn't been polled, bail out.
624                          */
625                         if (!instance->polled)
626                                 break;
627                         instance->polled = 0;
628
629                         /*
630                          * It's a live one!  Remember this time.
631                          */
632
633                         pp->lastref = pp->lastrec;
634                         refclock_receive(peer);
635
636                         /*
637                          * If we get here - what we got from the clock is
638                          * OK, so say so
639                          */
640                         refclock_report(peer, CEVNT_NOMINAL);
641
642                         /*
643                          * We have succeeded in answering the poll.
644                          * Turn off the flag and return
645                          */
646                         instance->polled = 0;
647                         break;
648
649                 case JUPITER_O_GPOS:
650                         if (size != sizeof(struct jgpos)) {
651                                 jupiter_debug(peer, __func__,
652                                     "gpos: len %d != %u",
653                                     size, (int)sizeof(struct jgpos));
654                                 refclock_report(peer, CEVNT_BADREPLY);
655                                 break;
656                         }
657
658                         if ((cp = jupiter_parse_gpos(instance, sp)) != NULL) {
659                                 jupiter_debug(peer, __func__,
660                                     "gpos: %s", cp);
661                                 break;
662                         }
663                         break;
664
665                 case JUPITER_O_ID:
666                         if (size != sizeof(struct jid)) {
667                                 jupiter_debug(peer, __func__,
668                                     "id: len %d != %u",
669                                     size, (int)sizeof(struct jid));
670                                 refclock_report(peer, CEVNT_BADREPLY);
671                                 break;
672                         }
673                         /*
674                          * If we got this message because the Jupiter
675                          * just powered instance, it needs to be reconfigured.
676                          */
677                         ip = (struct jid *)sp;
678                         jupiter_debug(peer, __func__,
679                             "%s chan ver %s, %s (%s)",
680                             ip->chans, ip->vers, ip->date, ip->opts);
681                         msyslog(LOG_DEBUG,
682                             "jupiter_receive: %s chan ver %s, %s (%s)",
683                             ip->chans, ip->vers, ip->date, ip->opts);
684                         if (instance->wantid)
685                                 instance->wantid = 0;
686                         else {
687                                 jupiter_debug(peer, __func__, "reset receiver");
688                                 jupiter_config(instance);
689                                 /*
690                                  * Restore since jupiter_config() just
691                                  * zeroed it
692                                  */
693                                 instance->ssize = cc;
694                         }
695                         break;
696
697                 default:
698                         jupiter_debug(peer, __func__, "unknown message id %d",
699                             getshort(hp->id));
700                         break;
701                 }
702                 instance->ssize -= cc;
703                 if (instance->ssize < 0) {
704                         fprintf(stderr, "jupiter_recv: negative ssize!\n");
705                         abort();
706                 } else if (instance->ssize > 0)
707                         memcpy(instance->sbuf, (u_char *)instance->sbuf + cc, instance->ssize);
708         }
709 }
710
711 static const char *
712 jupiter_parse_t(struct instance *instance, u_short *sp)
713 {
714         struct tm *tm;
715         char *cp;
716         struct jpulse *jp;
717         u_int32 sweek;
718         time_t last_timecode;
719         u_short flags;
720
721         jp = (struct jpulse *)sp;
722
723         /* The timecode is presented as seconds into the current GPS week */
724         sweek = DS2UI(jp->sweek) % WEEKSECS;
725
726         /*
727          * If we don't know the current GPS week, calculate it from the
728          * current time. (It's too bad they didn't include this
729          * important value in the pulse message). We'd like to pick it
730          * up from one of the other messages like gpos or chan but they
731          * don't appear to be synchronous with time keeping and changes
732          * too soon (something like 10 seconds before the new GPS
733          * week).
734          *
735          * If we already know the current GPS week, increment it when
736          * we wrap into a new week.
737          */
738         if (instance->gweek == 0) {
739                 if (!instance->gpos_gweek) {
740                         return ("jupiter_parse_t: Unknown gweek");
741                 }
742
743                 instance->gweek = instance->gpos_gweek;
744
745                 /*
746                  * Fix warps. GPOS has GPS time and PULSE has UTC.
747                  * Plus, GPOS need not be completely in synch with
748                  * the PPS signal.
749                  */
750                 if (instance->gpos_sweek >= sweek) {
751                         if ((instance->gpos_sweek - sweek) > WEEKSECS / 2)
752                                 ++instance->gweek;
753                 }
754                 else {
755                         if ((sweek - instance->gpos_sweek) > WEEKSECS / 2)
756                                 --instance->gweek;
757                 }
758         }
759         else if (sweek == 0 && instance->lastsweek == WEEKSECS - 1) {
760                 ++instance->gweek;
761                 jupiter_debug(instance->peer, __func__,
762                     "NEW gps week %u", instance->gweek);
763         }
764
765         /*
766          * See if the sweek stayed the same (this happens when there is
767          * no pps pulse).
768          *
769          * Otherwise, look for time warps:
770          *
771          *   - we have stored at least one lastsweek and
772          *   - the sweek didn't increase by one and
773          *   - we didn't wrap to a new GPS week
774          *
775          * Then we warped.
776          */
777         if (instance->lastsweek == sweek)
778                 jupiter_debug(instance->peer, __func__,
779                     "gps sweek not incrementing (%d)",
780                     sweek);
781         else if (instance->lastsweek != 2 * WEEKSECS &&
782             instance->lastsweek + 1 != sweek &&
783             !(sweek == 0 && instance->lastsweek == WEEKSECS - 1))
784                 jupiter_debug(instance->peer, __func__,
785                     "gps sweek jumped (was %d, now %d)",
786                     instance->lastsweek, sweek);
787         instance->lastsweek = sweek;
788
789         /* This timecode describes next pulse */
790         last_timecode = instance->timecode;
791         instance->timecode =
792             GPS_EPOCH + (instance->gweek * WEEKSECS) + sweek;
793
794         if (last_timecode == 0)
795                 /* XXX debugging */
796                 jupiter_debug(instance->peer, __func__,
797                     "UTC <none> (gweek/sweek %u/%u)",
798                     instance->gweek, sweek);
799         else {
800                 /* XXX debugging */
801                 tm = gmtime(&last_timecode);
802                 cp = asctime(tm);
803
804                 jupiter_debug(instance->peer, __func__,
805                     "UTC %.24s (gweek/sweek %u/%u)",
806                     cp, instance->gweek, sweek);
807
808                 /* Billboard last_timecode (which is now the current time) */
809                 instance->peer->procptr->year   = tm->tm_year + 1900;
810                 instance->peer->procptr->day    = tm->tm_yday + 1;
811                 instance->peer->procptr->hour   = tm->tm_hour;
812                 instance->peer->procptr->minute = tm->tm_min;
813                 instance->peer->procptr->second = tm->tm_sec;
814         }
815
816         flags = getshort(jp->flags);
817
818         /* Toss if not designated "valid" by the gps */
819         if ((flags & JUPITER_O_PULSE_VALID) == 0) {
820                 refclock_report(instance->peer, CEVNT_BADTIME);
821                 return ("time mark not valid");
822         }
823
824         /* We better be sync'ed to UTC... */
825         if ((flags & JUPITER_O_PULSE_UTC) == 0) {
826                 refclock_report(instance->peer, CEVNT_BADTIME);
827                 return ("time mark not sync'ed to UTC");
828         }
829
830         return (NULL);
831 }
832
833 static const char *
834 jupiter_parse_gpos(struct instance *instance, u_short *sp)
835 {
836         struct jgpos *jg;
837         time_t t;
838         struct tm *tm;
839         char *cp;
840
841         jg = (struct jgpos *)sp;
842
843         if (jg->navval != 0) {
844                 /*
845                  * Solution not valid. Use caution and refuse
846                  * to determine GPS week from this message.
847                  */
848                 instance->gpos_gweek = 0;
849                 instance->gpos_sweek = 0;
850                 return ("Navigation solution not valid");
851         }
852
853         instance->gpos_sweek = DS2UI(jg->sweek);
854         instance->gpos_gweek = basedate_expand_gpsweek(getshort(jg->gweek));
855
856         /* according to the protocol spec, the seconds-in-week cannot
857          * exceed the nominal value: Is it really necessary to normalise
858          * the seconds???
859          */
860         while(instance->gpos_sweek >= WEEKSECS) {
861                 instance->gpos_sweek -= WEEKSECS;
862                 ++instance->gpos_gweek;
863         }
864         instance->gweek = 0;
865
866         t = GPS_EPOCH + (instance->gpos_gweek * WEEKSECS) + instance->gpos_sweek;
867         tm = gmtime(&t);
868         cp = asctime(tm);
869
870         jupiter_debug(instance->peer, __func__,
871                 "GPS %.24s (gweek/sweek %u/%u)",
872                 cp, instance->gpos_gweek, instance->gpos_sweek);
873         return (NULL);
874 }
875
876 /*
877  * jupiter_debug - print debug messages
878  */
879 static void
880 jupiter_debug(
881         struct peer *   peer,
882         const char *    function,
883         const char *    fmt,
884         ...
885         )
886 {
887         char    buffer[200];
888         va_list ap;
889
890         va_start(ap, fmt);
891         /*
892          * Print debug message to stdout
893          * In the future, we may want to get get more creative...
894          */
895         mvsnprintf(buffer, sizeof(buffer), fmt, ap);
896         record_clock_stats(&peer->srcadr, buffer);
897 #ifdef DEBUG
898         if (debug) {
899                 printf("%s: %s\n", function, buffer);
900                 fflush(stdout);
901         }
902 #endif
903
904         va_end(ap);
905 }
906
907 /* Checksum and transmit a message to the Jupiter */
908 static char *
909 jupiter_send(struct instance *instance, struct jheader *hp)
910 {
911         u_int len, size;
912         ssize_t cc;
913         u_short *sp;
914         static char errstr[132];
915
916         size = sizeof(*hp);
917         hp->hsum = putshort(jupiter_cksum((u_short *)hp,
918             (size / sizeof(u_short)) - 1));
919         len = getshort(hp->len);
920         if (len > 0) {
921                 sp = (u_short *)(hp + 1);
922                 sp[len] = putshort(jupiter_cksum(sp, len));
923                 size += (len + 1) * sizeof(u_short);
924         }
925
926         if ((cc = write(instance->peer->procptr->io.fd, (char *)hp, size)) < 0) {
927                 msnprintf(errstr, sizeof(errstr), "write: %m");
928                 return (errstr);
929         } else if (cc != (int)size) {
930                 snprintf(errstr, sizeof(errstr), "short write (%zd != %u)", cc, size);
931                 return (errstr);
932         }
933         return (NULL);
934 }
935
936 /* Request periodic message output */
937 static struct {
938         struct jheader jheader;
939         struct jrequest jrequest;
940 } reqmsg = {
941         { putshort(JUPITER_SYNC), 0,
942             putshort((sizeof(struct jrequest) / sizeof(u_short)) - 1),
943             0, JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK |
944             JUPITER_FLAG_CONN | JUPITER_FLAG_LOG, 0 },
945         { 0, 0, 0, 0 }
946 };
947
948 /* An interval of zero means to output on trigger */
949 static void
950 jupiter_reqmsg(struct instance *instance, u_int id,
951     u_int interval)
952 {
953         struct jheader *hp;
954         struct jrequest *rp;
955         char *cp;
956
957         hp = &reqmsg.jheader;
958         hp->id = putshort(id);
959         rp = &reqmsg.jrequest;
960         rp->trigger = putshort(interval == 0);
961         rp->interval = putshort(interval);
962         if ((cp = jupiter_send(instance, hp)) != NULL)
963                 jupiter_debug(instance->peer, __func__, "%u: %s", id, cp);
964 }
965
966 /* Cancel periodic message output */
967 static struct jheader canmsg = {
968         putshort(JUPITER_SYNC), 0, 0, 0,
969         JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_DISC,
970         0
971 };
972
973 static void
974 jupiter_canmsg(struct instance *instance, u_int id)
975 {
976         struct jheader *hp;
977         char *cp;
978
979         hp = &canmsg;
980         hp->id = putshort(id);
981         if ((cp = jupiter_send(instance, hp)) != NULL)
982                 jupiter_debug(instance->peer, __func__, "%u: %s", id, cp);
983 }
984
985 /* Request a single message output */
986 static struct jheader reqonemsg = {
987         putshort(JUPITER_SYNC), 0, 0, 0,
988         JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_QUERY,
989         0
990 };
991
992 static void
993 jupiter_reqonemsg(struct instance *instance, u_int id)
994 {
995         struct jheader *hp;
996         char *cp;
997
998         hp = &reqonemsg;
999         hp->id = putshort(id);
1000         if ((cp = jupiter_send(instance, hp)) != NULL)
1001                 jupiter_debug(instance->peer, __func__, "%u: %s", id, cp);
1002 }
1003
1004 /* Set the platform dynamics */
1005 static struct {
1006         struct jheader jheader;
1007         struct jplat jplat;
1008 } platmsg = {
1009         { putshort(JUPITER_SYNC), putshort(JUPITER_I_PLAT),
1010             putshort((sizeof(struct jplat) / sizeof(u_short)) - 1), 0,
1011             JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK, 0 },
1012         { 0, 0, 0 }
1013 };
1014
1015 static void
1016 jupiter_platform(struct instance *instance, u_int platform)
1017 {
1018         struct jheader *hp;
1019         struct jplat *pp;
1020         char *cp;
1021
1022         hp = &platmsg.jheader;
1023         pp = &platmsg.jplat;
1024         pp->platform = putshort(platform);
1025         if ((cp = jupiter_send(instance, hp)) != NULL)
1026                 jupiter_debug(instance->peer, __func__, "%u: %s", platform, cp);
1027 }
1028
1029 /* Checksum "len" shorts */
1030 static u_short
1031 jupiter_cksum(u_short *sp, u_int len)
1032 {
1033         u_short sum, x;
1034
1035         sum = 0;
1036         while (len-- > 0) {
1037                 x = *sp++;
1038                 sum += getshort(x);
1039         }
1040         return (~sum + 1);
1041 }
1042
1043 /* Return the size of the next message (or zero if we don't have it all yet) */
1044 static int
1045 jupiter_recv(struct instance *instance)
1046 {
1047         int n, len, size, cc;
1048         struct jheader *hp;
1049         u_char *bp;
1050         u_short *sp;
1051
1052         /* Must have at least a header's worth */
1053         cc = sizeof(*hp);
1054         size = instance->ssize;
1055         if (size < cc)
1056                 return (0);
1057
1058         /* Search for the sync short if missing */
1059         sp = instance->sbuf;
1060         hp = (struct jheader *)sp;
1061         if (getshort(hp->sync) != JUPITER_SYNC) {
1062                 /* Wasn't at the front, sync up */
1063                 jupiter_debug(instance->peer, __func__, "syncing");
1064                 bp = (u_char *)sp;
1065                 n = size;
1066                 while (n >= 2) {
1067                         if (bp[0] != (JUPITER_SYNC & 0xff)) {
1068                                 /*
1069                                 jupiter_debug(instance->peer, __func__,
1070                                     "{0x%x}", bp[0]);
1071                                 */
1072                                 ++bp;
1073                                 --n;
1074                                 continue;
1075                         }
1076                         if (bp[1] == ((JUPITER_SYNC >> 8) & 0xff))
1077                                 break;
1078                         /*
1079                         jupiter_debug(instance->peer, __func__,
1080                             "{0x%x 0x%x}", bp[0], bp[1]);
1081                         */
1082                         bp += 2;
1083                         n -= 2;
1084                 }
1085                 /*
1086                 jupiter_debug(instance->peer, __func__, "\n");
1087                 */
1088                 /* Shuffle data to front of input buffer */
1089                 if (n > 0)
1090                         memcpy(sp, bp, n);
1091                 size = n;
1092                 instance->ssize = size;
1093                 if (size < cc || hp->sync != JUPITER_SYNC)
1094                         return (0);
1095         }
1096
1097         if (jupiter_cksum(sp, (cc / sizeof(u_short) - 1)) !=
1098             getshort(hp->hsum)) {
1099             jupiter_debug(instance->peer, __func__, "bad header checksum!");
1100                 /* This is drastic but checksum errors should be rare */
1101                 instance->ssize = 0;
1102                 return (0);
1103         }
1104
1105         /* Check for a payload */
1106         len = getshort(hp->len);
1107         if (len > 0) {
1108                 n = (len + 1) * sizeof(u_short);
1109                 /* Not enough data yet */
1110                 if (size < cc + n)
1111                         return (0);
1112
1113                 /* Check payload checksum */
1114                 sp = (u_short *)(hp + 1);
1115                 if (jupiter_cksum(sp, len) != getshort(sp[len])) {
1116                         jupiter_debug(instance->peer,
1117                             __func__, "bad payload checksum!");
1118                         /* This is drastic but checksum errors should be rare */
1119                         instance->ssize = 0;
1120                         return (0);
1121                 }
1122                 cc += n;
1123         }
1124         return (cc);
1125 }
1126
1127 #else /* not (REFCLOCK && CLOCK_JUPITER && HAVE_PPSAPI) */
1128 int refclock_jupiter_bs;
1129 #endif /* not (REFCLOCK && CLOCK_JUPITER && HAVE_PPSAPI) */