]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ntp/ntpd/refclock_jupiter.c
Fix multiple denial of service in ntpd.
[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 /* This clock *REQUIRES* the PPS API to be available */
39 #if defined(REFCLOCK) && defined(CLOCK_JUPITER) && defined(HAVE_PPSAPI)
40
41 #include "ntpd.h"
42 #include "ntp_io.h"
43 #include "ntp_refclock.h"
44 #include "ntp_unixtime.h"
45 #include "ntp_stdlib.h"
46 #include "ntp_calendar.h"
47 #include "ntp_calgps.h"
48 #include "timespecops.h"
49
50 #include <stdio.h>
51 #include <ctype.h>
52
53 #include "jupiter.h"
54 #include "ppsapi_timepps.h"
55
56 #ifdef WORDS_BIGENDIAN
57 #define getshort(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
58 #define putshort(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
59 #else
60 #define getshort(s) ((u_short)(s))
61 #define putshort(s) ((u_short)(s))
62 #endif
63
64 /*
65  * This driver supports the Rockwell Jupiter GPS Receiver board
66  * adapted to precision timing applications.  It requires the
67  * ppsclock line discipline or streams module described in the
68  * Line Disciplines and Streams Drivers page. It also requires a
69  * gadget box and 1-PPS level converter, such as described in the
70  * Pulse-per-second (PPS) Signal Interfacing page.
71  *
72  * It may work (with minor modifications) with other Rockwell GPS
73  * receivers such as the CityTracker.
74  */
75
76 /*
77  * GPS Definitions
78  */
79 #define DEVICE          "/dev/gps%d"    /* device name and unit */
80 #define SPEED232        B9600           /* baud */
81
82 /*
83  * Radio interface parameters
84  */
85 #define PRECISION       (-18)   /* precision assumed (about 4 us) */
86 #define REFID   "GPS\0"         /* reference id */
87 #define DESCRIPTION     "Rockwell Jupiter GPS Receiver" /* who we are */
88 #define DEFFUDGETIME    0       /* default fudge time (ms) */
89
90 /* Unix timestamp for the GPS epoch: January 6, 1980 */
91 #define GPS_EPOCH 315964800
92
93 /* Rata Die Number of first day of GPS epoch. This is the number of days
94  * since 0000-12-31 to 1980-01-06 in the proleptic Gregorian Calendar.
95  */
96 #define RDN_GPS_EPOCH (4*146097 + 138431 + 1)
97
98 /* Double short to unsigned int */
99 #define DS2UI(p) ((getshort((p)[1]) << 16) | getshort((p)[0]))
100
101 /* Double short to signed int */
102 #define DS2I(p) ((getshort((p)[1]) << 16) | getshort((p)[0]))
103
104 /* One week's worth of seconds */
105 #define WEEKSECS (7 * 24 * 60 * 60)
106
107 /*
108  * Jupiter unit control structure.
109  */
110 struct instance {
111         struct peer *peer;              /* peer */
112
113         pps_params_t pps_params;        /* pps parameters */
114         pps_info_t pps_info;            /* last pps data */
115         pps_handle_t pps_handle;        /* pps handle */
116         u_int   assert;                 /* pps edge to use */
117         u_int   hardpps;                /* enable kernel mode */
118         l_fp            rcv_pps;        /* last pps timestamp */
119         l_fp            rcv_next;       /* rcv time of next reftime */
120         TGpsDatum       ref_next;       /* next GPS time stamp to use with PPS */
121         TGpsDatum       piv_next;       /* pivot for week date unfolding */
122         uint16_t        piv_hold;       /* TTL for pivot value */
123         uint16_t        rcvtout;        /* receive timeout ticker */
124         int wantid;                     /* don't reconfig on channel id msg */
125         u_int  moving;                  /* mobile platform? */
126         u_char sloppyclockflag;         /* fudge flags */
127         u_short sbuf[512];              /* local input buffer */
128         int ssize;                      /* space used in sbuf */
129 };
130
131 /*
132  * Function prototypes
133  */
134 static  void    jupiter_canmsg  (struct instance * const, u_int);
135 static  u_short jupiter_cksum   (u_short *, u_int);
136 static  int     jupiter_config  (struct instance * const);
137 static  void    jupiter_debug   (struct peer *, const char *,
138                                  const char *, ...) NTP_PRINTF(3, 4);
139 static  const char *    jupiter_parse_t (struct instance * const, u_short *, l_fp);
140 static  const char *    jupiter_parse_gpos(struct instance * const, u_short *);
141 static  void    jupiter_platform(struct instance * const, u_int);
142 static  void    jupiter_poll    (int, struct peer *);
143 static  void    jupiter_control (int, const struct refclockstat *,
144                                  struct refclockstat *, struct peer *);
145 static  int     jupiter_ppsapi  (struct instance * const);
146 static  int     jupiter_pps     (struct instance * const);
147 static  int     jupiter_recv    (struct instance * const);
148 static  void    jupiter_receive (struct recvbuf * const rbufp);
149 static  void    jupiter_reqmsg  (struct instance * const, u_int, u_int);
150 static  void    jupiter_reqonemsg(struct instance * const, u_int);
151 static  char *  jupiter_send    (struct instance * const, struct jheader *);
152 static  void    jupiter_shutdown(int, struct peer *);
153 static  int     jupiter_start   (int, struct peer *);
154 static  void    jupiter_ticker  (int, struct peer *);
155
156 /*
157  * Transfer vector
158  */
159 struct  refclock refclock_jupiter = {
160         jupiter_start,          /* start up driver */
161         jupiter_shutdown,       /* shut down driver */
162         jupiter_poll,           /* transmit poll message */
163         jupiter_control,        /* (clock control) */
164         noentry,                /* (clock init) */
165         noentry,                /* (clock buginfo) */
166         jupiter_ticker          /* 1HZ ticker */
167 };
168
169 /*
170  * jupiter_start - open the devices and initialize data for processing
171  */
172 static int
173 jupiter_start(
174         int unit,
175         struct peer *peer
176         )
177 {
178         struct refclockproc * const pp = peer->procptr;
179         struct instance * up;
180         int fd;
181         char gpsdev[20];
182
183         /*
184          * Open serial port
185          */
186         snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit);
187         fd = refclock_open(gpsdev, SPEED232, LDISC_RAW);
188         if (fd <= 0) {
189                 jupiter_debug(peer, "jupiter_start", "open %s: %m",
190                               gpsdev);
191                 return (0);
192         }
193
194         /* Allocate unit structure */
195         up = emalloc_zero(sizeof(*up));
196         up->peer = peer;
197         pp->io.clock_recv = jupiter_receive;
198         pp->io.srcclock = peer;
199         pp->io.datalen = 0;
200         pp->io.fd = fd;
201         if (!io_addclock(&pp->io)) {
202                 close(fd);
203                 pp->io.fd = -1;
204                 free(up);
205                 return (0);
206         }
207         pp->unitptr = up;
208
209         /*
210          * Initialize miscellaneous variables
211          */
212         peer->precision = PRECISION;
213         pp->clockdesc = DESCRIPTION;
214         memcpy((char *)&pp->refid, REFID, 4);
215
216         up->assert = 1;
217         up->hardpps = 0;
218         /*
219          * Start the PPSAPI interface if it is there. Default to use
220          * the assert edge and do not enable the kernel hardpps.
221          */
222         if (time_pps_create(fd, &up->pps_handle) < 0) {
223                 up->pps_handle = 0;
224                 msyslog(LOG_ERR,
225                         "refclock_jupiter: time_pps_create failed: %m");
226         }
227         else if (!jupiter_ppsapi(up))
228                 goto clean_up;
229         
230         /* Ensure the receiver is properly configured */
231         if (!jupiter_config(up))
232                 goto clean_up;
233
234         jupiter_pps(up);        /* get current PPS state */
235         return (1);
236
237 clean_up:
238         jupiter_shutdown(unit, peer);
239         pp->unitptr = 0;
240         return (0);
241 }
242
243 /*
244  * jupiter_shutdown - shut down the clock
245  */
246 static void
247 jupiter_shutdown(int unit, struct peer *peer)
248 {
249         struct refclockproc * const pp = peer->procptr;
250         struct instance *     const up = pp->unitptr;
251         
252         if (!up)
253                 return;
254
255         if (up->pps_handle) {
256                 time_pps_destroy(up->pps_handle);
257                 up->pps_handle = 0;
258         }
259
260         if (pp->io.fd != -1)
261                 io_closeclock(&pp->io);
262         free(up);
263 }
264
265 /*
266  * jupiter_config - Configure the receiver
267  */
268 static int
269 jupiter_config(struct instance * const up)
270 {
271         jupiter_debug(up->peer, __func__, "init receiver");
272
273         /*
274          * Initialize the unit variables
275          */
276         up->sloppyclockflag = up->peer->procptr->sloppyclockflag;
277         up->moving = !!(up->sloppyclockflag & CLK_FLAG2);
278         if (up->moving)
279                 jupiter_debug(up->peer, __func__, "mobile platform");
280
281         ZERO(up->rcv_next);
282         ZERO(up->ref_next);
283         ZERO(up->piv_next);
284         up->ssize = 0;
285
286         /* Stop outputting all messages */
287         jupiter_canmsg(up, JUPITER_ALL);
288
289         /* Request the receiver id so we can syslog the firmware version */
290         jupiter_reqonemsg(up, JUPITER_O_ID);
291
292         /* Flag that this the id was requested (so we don't get called again) */
293         up->wantid = 1;
294
295         /* Request perodic time mark pulse messages */
296         jupiter_reqmsg(up, JUPITER_O_PULSE, 1);
297
298         /* Request perodic geodetic position status */
299         jupiter_reqmsg(up, JUPITER_O_GPOS, 1);
300
301         /* Set application platform type */
302         if (up->moving)
303                 jupiter_platform(up, JUPITER_I_PLAT_MED);
304         else
305                 jupiter_platform(up, JUPITER_I_PLAT_LOW);
306
307         return (1);
308 }
309
310 static void
311 jupiter_checkpps(
312         struct refclockproc * const pp,
313         struct instance *     const up
314         )
315 {
316         l_fp            tstamp, delta;
317         struct calendar cd;
318         
319         if (jupiter_pps(up) || !up->piv_next.weeks)
320                 return;
321
322         /* check delay between pulse message and pulse. */
323         delta = up->rcv_pps;            /* set by jupiter_pps() */
324         L_SUB(&delta, &up->rcv_next);   /* recv time pulse message */
325         if (delta.l_ui != 0 || delta.l_uf >= 0xC0000000) {
326                 up->ref_next.weeks = 0; /* consider as consumed... */
327                 return;
328         }
329         
330         pp->lastrec = up->rcv_pps;
331         tstamp = ntpfp_from_gpsdatum(&up->ref_next);
332         refclock_process_offset(pp, tstamp, up->rcv_pps, pp->fudgetime1);
333         up->rcvtout = 2;
334
335         gpscal_to_calendar(&cd, &up->ref_next);
336         refclock_save_lcode(pp, ntpcal_iso8601std(NULL, 0, &cd),
337                             (size_t)-1);
338         up->ref_next.weeks = 0; /* consumed... */
339 }
340
341 /*
342  * jupiter_ticker - process periodic checks
343  */
344 static void
345 jupiter_ticker(int unit, struct peer *peer)
346 {
347         struct refclockproc * const pp = peer->procptr;
348         struct instance *     const up = pp->unitptr;
349
350         if (!up)
351                 return;
352
353         /* check if we can add another sample now */
354         jupiter_checkpps(pp, up);
355
356         /* check the pivot update cycle */
357         if (up->piv_hold && !--up->piv_hold)
358                 ZERO(up->piv_next);
359
360         if (up->rcvtout)
361                 --up->rcvtout;
362         else if (pp->coderecv != pp->codeproc)
363                 refclock_samples_expire(pp, 1);
364 }
365
366 /*
367  * Initialize PPSAPI
368  */
369 int
370 jupiter_ppsapi(
371         struct instance * const up      /* unit structure pointer */
372         )
373 {
374         int capability;
375
376         if (time_pps_getcap(up->pps_handle, &capability) < 0) {
377                 msyslog(LOG_ERR,
378                     "refclock_jupiter: time_pps_getcap failed: %m");
379                 return (0);
380         }
381         memset(&up->pps_params, 0, sizeof(pps_params_t));
382         if (!up->assert)
383                 up->pps_params.mode = capability & PPS_CAPTURECLEAR;
384         else
385                 up->pps_params.mode = capability & PPS_CAPTUREASSERT;
386         if (!(up->pps_params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR))) {
387                 msyslog(LOG_ERR,
388                     "refclock_jupiter: invalid capture edge %d",
389                     up->assert);
390                 return (0);
391         }
392         up->pps_params.mode |= PPS_TSFMT_TSPEC;
393         if (time_pps_setparams(up->pps_handle, &up->pps_params) < 0) {
394                 msyslog(LOG_ERR,
395                     "refclock_jupiter: time_pps_setparams failed: %m");
396                 return (0);
397         }
398         if (up->hardpps) {
399                 if (time_pps_kcbind(up->pps_handle, PPS_KC_HARDPPS,
400                                     up->pps_params.mode & ~PPS_TSFMT_TSPEC,
401                                     PPS_TSFMT_TSPEC) < 0) {
402                         msyslog(LOG_ERR,
403                             "refclock_jupiter: time_pps_kcbind failed: %m");
404                         return (0);
405                 }
406                 hardpps_enable = 1;
407         }
408 /*      up->peer->precision = PPS_PRECISION; */
409
410 #if DEBUG
411         if (debug) {
412                 time_pps_getparams(up->pps_handle, &up->pps_params);
413                 jupiter_debug(up->peer, __func__,
414                         "pps capability 0x%x version %d mode 0x%x kern %d",
415                         capability, up->pps_params.api_version,
416                         up->pps_params.mode, up->hardpps);
417         }
418 #endif
419
420         return (1);
421 }
422
423 /*
424  * Get PPSAPI timestamps.
425  *
426  * Return 0 on failure and 1 on success.
427  */
428 static int
429 jupiter_pps(struct instance * const up)
430 {
431         pps_info_t pps_info;
432         struct timespec timeout, ts;
433         l_fp tstmp;
434
435         /*
436          * Convert the timespec nanoseconds field to ntp l_fp units.
437          */ 
438         if (up->pps_handle == 0)
439                 return 1;
440         timeout.tv_sec = 0;
441         timeout.tv_nsec = 0;
442         memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t));
443         if (time_pps_fetch(up->pps_handle, PPS_TSFMT_TSPEC, &up->pps_info,
444             &timeout) < 0)
445                 return 1;
446         if (up->pps_params.mode & PPS_CAPTUREASSERT) {
447                 if (pps_info.assert_sequence ==
448                     up->pps_info.assert_sequence)
449                         return 1;
450                 ts = up->pps_info.assert_timestamp;
451         } else if (up->pps_params.mode & PPS_CAPTURECLEAR) {
452                 if (pps_info.clear_sequence ==
453                     up->pps_info.clear_sequence)
454                         return 1;
455                 ts = up->pps_info.clear_timestamp;
456         } else {
457                 return 1;
458         }
459
460         tstmp = tspec_stamp_to_lfp(ts);         
461         if (L_ISEQU(&tstmp, &up->rcv_pps))
462                 return 1;
463
464         up->rcv_pps = tstmp;
465         return 0;
466 }
467
468 /*
469  * jupiter_poll - jupiter watchdog routine
470  */
471 static void
472 jupiter_poll(int unit, struct peer *peer)
473 {
474         struct refclockproc * const pp = peer->procptr;
475         struct instance *     const up = pp->unitptr;
476
477         pp->polls++;
478
479         /*
480          * If we have new samples since last poll, everything is fine.
481          * if not, blarb loudly.
482          */
483         if (pp->coderecv != pp->codeproc) {
484                 refclock_receive(peer);
485                 refclock_report(peer, CEVNT_NOMINAL);
486         } else {
487                 refclock_report(peer, CEVNT_TIMEOUT);
488
489                 /* Request the receiver id to trigger a reconfig */
490                 jupiter_reqonemsg(up, JUPITER_O_ID);
491                 up->wantid = 0;
492         }
493 }
494
495 /*
496  * jupiter_control - fudge control
497  */
498 static void
499 jupiter_control(
500         int unit,               /* unit (not used) */
501         const struct refclockstat *in, /* input parameters (not used) */
502         struct refclockstat *out, /* output parameters (not used) */
503         struct peer *peer       /* peer structure pointer */
504         )
505 {
506         struct refclockproc * const pp = peer->procptr;
507         struct instance *     const up = pp->unitptr;
508         
509         u_char sloppyclockflag;
510
511         up->assert = !(pp->sloppyclockflag & CLK_FLAG3);
512         jupiter_ppsapi(up);
513
514         sloppyclockflag = up->sloppyclockflag;
515         up->sloppyclockflag = pp->sloppyclockflag;
516         if ((up->sloppyclockflag & CLK_FLAG2) !=
517             (sloppyclockflag & CLK_FLAG2)) {
518                 jupiter_debug(peer, __func__,
519                     "mode switch: reset receiver");
520                 jupiter_config(up);
521                 return;
522         }
523 }
524
525 /*
526  * jupiter_receive - receive gps data
527  * Gag me!
528  */
529 static void
530 jupiter_receive(struct recvbuf * const rbufp)
531 {
532         struct peer *         const peer = rbufp->recv_peer;
533         struct refclockproc * const pp   = peer->procptr;
534         struct instance *     const up   = pp->unitptr;
535
536         size_t bpcnt;
537         int cc, size;
538         const char *cp;
539         u_char *bp;
540         u_short *sp;
541         struct jid *ip;
542         struct jheader *hp;
543
544         /* Initialize pointers and read the timecode and timestamp */
545         bp = (u_char *)rbufp->recv_buffer;
546         bpcnt = rbufp->recv_length;
547
548         /* This shouldn't happen */
549         if (bpcnt > sizeof(up->sbuf) - up->ssize)
550                 bpcnt = sizeof(up->sbuf) - up->ssize;
551
552         /* Append to input buffer */
553         memcpy((u_char *)up->sbuf + up->ssize, bp, bpcnt);
554         up->ssize += bpcnt;
555
556         /* While there's at least a header and we parse an intact message */
557         while (up->ssize > (int)sizeof(*hp) && (cc = jupiter_recv(up)) > 0) {
558                 hp = (struct jheader *)up->sbuf;
559                 sp = (u_short *)(hp + 1);
560                 size = cc - sizeof(*hp);
561                 switch (getshort(hp->id)) {
562
563                 case JUPITER_O_PULSE:
564                         /* first see if we can push another sample: */
565                         jupiter_checkpps(pp, up);
566
567                         if (size != sizeof(struct jpulse)) {
568                                 jupiter_debug(peer, __func__,
569                                     "pulse: len %d != %u",
570                                     size, (int)sizeof(struct jpulse));
571                                 refclock_report(peer, CEVNT_BADREPLY);
572                                 break;
573                         }
574                         
575                         /* Parse timecode (even when there's no pps)
576                          *
577                          * There appears to be a firmware bug related to
578                          * the pulse message; in addition to the one per
579                          * second messages, we get an extra pulse
580                          * message once an hour (on the anniversary of
581                          * the cold start). It seems to come 200 ms
582                          * after the one requested.
583                          *
584                          * But since we feed samples only when a new PPS
585                          * pulse is found we can simply ignore that and
586                          * aggregate/update any existing timing message.
587                          */
588                         if ((cp = jupiter_parse_t(up, sp, rbufp->recv_time)) != NULL) {
589                                 jupiter_debug(peer, __func__,
590                                     "pulse: %s", cp);
591                         }
592                         break;
593
594                 case JUPITER_O_GPOS:
595                         if (size != sizeof(struct jgpos)) {
596                                 jupiter_debug(peer, __func__,
597                                     "gpos: len %d != %u",
598                                     size, (int)sizeof(struct jgpos));
599                                 refclock_report(peer, CEVNT_BADREPLY);
600                                 break;
601                         }
602
603                         if ((cp = jupiter_parse_gpos(up, sp)) != NULL) {
604                                 jupiter_debug(peer, __func__,
605                                     "gpos: %s", cp);
606                                 break;
607                         }
608                         break;
609
610                 case JUPITER_O_ID:
611                         if (size != sizeof(struct jid)) {
612                                 jupiter_debug(peer, __func__,
613                                     "id: len %d != %u",
614                                     size, (int)sizeof(struct jid));
615                                 refclock_report(peer, CEVNT_BADREPLY);
616                                 break;
617                         }
618                         /*
619                          * If we got this message because the Jupiter
620                          * just powered instance, it needs to be reconfigured.
621                          */
622                         ip = (struct jid *)sp;
623                         jupiter_debug(peer, __func__,
624                             "%s chan ver %s, %s (%s)",
625                             ip->chans, ip->vers, ip->date, ip->opts);
626                         msyslog(LOG_DEBUG,
627                             "jupiter_receive: %s chan ver %s, %s (%s)",
628                             ip->chans, ip->vers, ip->date, ip->opts);
629                         if (up->wantid)
630                                 up->wantid = 0;
631                         else {
632                                 jupiter_debug(peer, __func__, "reset receiver");
633                                 jupiter_config(up);
634                                 /*
635                                  * Restore since jupiter_config() just
636                                  * zeroed it
637                                  */
638                                 up->ssize = cc;
639                         }
640                         break;
641
642                 default:
643                         jupiter_debug(peer, __func__, "unknown message id %d",
644                             getshort(hp->id));
645                         break;
646                 }
647                 up->ssize -= cc;
648                 if (up->ssize < 0) {
649                         fprintf(stderr, "jupiter_recv: negative ssize!\n");
650                         abort();
651                 } else if (up->ssize > 0)
652                         memcpy(up->sbuf, (u_char *)up->sbuf + cc, up->ssize);
653         }
654 }
655
656 static const char *
657 jupiter_parse_t(
658         struct instance * const up,
659         u_short *               sp,
660         l_fp               rcvtime
661         )
662 {
663         struct jpulse *jp;
664         u_int32 sweek;
665         u_short flags;
666         l_fp fofs;
667         
668         jp = (struct jpulse *)sp;
669         flags = getshort(jp->flags);
670
671         /* Toss if not designated "valid" by the gps.
672          * !!NOTE!! do *not* kill data received so far!
673          */
674         if ((flags & JUPITER_O_PULSE_VALID) == 0) {
675                 refclock_report(up->peer, CEVNT_BADTIME);
676                 return ("time mark not valid");
677         }
678
679         up->rcv_next = rcvtime; /* remember when this happened */
680         
681         /* The timecode is presented as seconds into the current GPS week */
682         sweek = DS2UI(jp->sweek) % WEEKSECS;
683         /* check if we have to apply the UTC offset ourselves */
684         if ((flags & JUPITER_O_PULSE_UTC) == 0) {
685                 struct timespec tofs;
686                 tofs.tv_sec  = getshort(jp->offs);
687                 tofs.tv_nsec = DS2I(jp->offns);
688                 fofs = tspec_intv_to_lfp(tofs);
689                 L_NEG(&fofs);
690         } else {
691                 ZERO(fofs);
692         }
693         
694         /*
695          * If we don't know the current GPS week, calculate it from the
696          * current time. (It's too bad they didn't include this
697          * important value in the pulse message).
698          * 
699          * So we pick the pivot value from the other messages like gpos
700          * or chan if we can. Of course, the PULSE message can be in UTC
701          * or GPS time scale, and the other messages are simply always
702          * GPS time.
703          *
704          * But as long as the difference between the time stamps is less
705          * than a half week, the unfolding of a week time is unambigeous
706          * and well suited for the problem we have here. And we won't
707          * see *that* many leap seconds, ever.
708          */
709         if (up->piv_next.weeks) {
710                 up->ref_next = gpscal_from_weektime2(
711                         sweek, fofs, &up->piv_next);
712                 up->piv_next = up->ref_next;
713         } else {
714                 up->ref_next = gpscal_from_weektime1(
715                         sweek, fofs, rcvtime);
716         }
717                         
718
719
720         return (NULL);
721 }
722
723 static const char *
724 jupiter_parse_gpos(
725         struct instance * const up,
726         u_short *               sp
727         )
728 {
729         struct jgpos *jg;
730         struct calendar tref;
731         char *cp;
732         struct timespec tofs;
733         uint16_t        raw_week;
734         uint32_t        raw_secs;
735
736         jg = (struct jgpos *)sp;
737
738         if (jg->navval != 0) {
739                 /*
740                  * Solution not valid. Use caution and refuse
741                  * to determine GPS week from this message.
742                  */
743                 return ("Navigation solution not valid");
744         }
745
746         raw_week = getshort(jg->gweek);
747         raw_secs = DS2UI(jg->sweek);
748         tofs.tv_sec  = 0;
749         tofs.tv_nsec = DS2UI(jg->nsweek);
750         up->piv_next = gpscal_from_gpsweek(raw_week, raw_secs,
751                                            tspec_intv_to_lfp(tofs));
752         up->piv_hold = 60;
753
754         gpscal_to_calendar(&tref, &up->piv_next);
755         cp = ntpcal_iso8601std(NULL, 0, &tref);
756         jupiter_debug(up->peer, __func__,
757                 "GPS %s (gweek/sweek %hu/%u)",
758                       cp, (unsigned short)raw_week, (unsigned int)raw_secs);
759         return (NULL);
760 }
761
762 /*
763  * jupiter_debug - print debug messages
764  */
765 static void
766 jupiter_debug(
767         struct peer *   peer,
768         const char *    function,
769         const char *    fmt,
770         ...
771         )
772 {
773         char    buffer[200];
774         va_list ap;
775
776         va_start(ap, fmt);
777         /*
778          * Print debug message to stdout
779          * In the future, we may want to get get more creative...
780          */
781         mvsnprintf(buffer, sizeof(buffer), fmt, ap);
782         record_clock_stats(&peer->srcadr, buffer);
783 #ifdef DEBUG
784         if (debug) {
785                 printf("%s: %s\n", function, buffer);
786                 fflush(stdout);
787         }
788 #endif
789
790         va_end(ap);
791 }
792
793 /* Checksum and transmit a message to the Jupiter */
794 static char *
795 jupiter_send(
796         struct instance * const up,
797         struct jheader *        hp
798         )
799 {
800         u_int len, size;
801         ssize_t cc;
802         u_short *sp;
803         static char errstr[132];
804
805         size = sizeof(*hp);
806         hp->hsum = putshort(jupiter_cksum((u_short *)hp,
807             (size / sizeof(u_short)) - 1));
808         len = getshort(hp->len);
809         if (len > 0) {
810                 sp = (u_short *)(hp + 1);
811                 sp[len] = putshort(jupiter_cksum(sp, len));
812                 size += (len + 1) * sizeof(u_short);
813         }
814
815         if ((cc = write(up->peer->procptr->io.fd, (char *)hp, size)) < 0) {
816                 msnprintf(errstr, sizeof(errstr), "write: %m");
817                 return (errstr);
818         } else if (cc != (int)size) {
819                 snprintf(errstr, sizeof(errstr), "short write (%zd != %u)", cc, size);
820                 return (errstr);
821         }
822         return (NULL);
823 }
824
825 /* Request periodic message output */
826 static struct {
827         struct jheader jheader;
828         struct jrequest jrequest;
829 } reqmsg = {
830         { putshort(JUPITER_SYNC), 0,
831             putshort((sizeof(struct jrequest) / sizeof(u_short)) - 1),
832             0, JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK |
833             JUPITER_FLAG_CONN | JUPITER_FLAG_LOG, 0 },
834         { 0, 0, 0, 0 }
835 };
836
837 /* An interval of zero means to output on trigger */
838 static void
839 jupiter_reqmsg(
840         struct instance * const up,
841         u_int                   id,
842         u_int             interval
843         )
844 {
845         struct jheader *hp;
846         struct jrequest *rp;
847         char *cp;
848
849         hp = &reqmsg.jheader;
850         hp->id = putshort(id);
851         rp = &reqmsg.jrequest;
852         rp->trigger = putshort(interval == 0);
853         rp->interval = putshort(interval);
854         if ((cp = jupiter_send(up, hp)) != NULL)
855                 jupiter_debug(up->peer, __func__, "%u: %s", id, cp);
856 }
857
858 /* Cancel periodic message output */
859 static struct jheader canmsg = {
860         putshort(JUPITER_SYNC), 0, 0, 0,
861         JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_DISC,
862         0
863 };
864
865 static void
866 jupiter_canmsg(
867         struct instance * const up,
868         u_int                   id
869         )
870 {
871         struct jheader *hp;
872         char *cp;
873
874         hp = &canmsg;
875         hp->id = putshort(id);
876         if ((cp = jupiter_send(up, hp)) != NULL)
877                 jupiter_debug(up->peer, __func__, "%u: %s", id, cp);
878 }
879
880 /* Request a single message output */
881 static struct jheader reqonemsg = {
882         putshort(JUPITER_SYNC), 0, 0, 0,
883         JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_QUERY,
884         0
885 };
886
887 static void
888 jupiter_reqonemsg(
889         struct instance * const up,
890         u_int                   id
891         )
892 {
893         struct jheader *hp;
894         char *cp;
895
896         hp = &reqonemsg;
897         hp->id = putshort(id);
898         if ((cp = jupiter_send(up, hp)) != NULL)
899                 jupiter_debug(up->peer, __func__, "%u: %s", id, cp);
900 }
901
902 /* Set the platform dynamics */
903 static struct {
904         struct jheader jheader;
905         struct jplat jplat;
906 } platmsg = {
907         { putshort(JUPITER_SYNC), putshort(JUPITER_I_PLAT),
908             putshort((sizeof(struct jplat) / sizeof(u_short)) - 1), 0,
909             JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK, 0 },
910         { 0, 0, 0 }
911 };
912
913 static void
914 jupiter_platform(
915         struct instance * const up,
916         u_int             platform
917         )
918 {
919         struct jheader *hp;
920         struct jplat *pp;
921         char *cp;
922
923         hp = &platmsg.jheader;
924         pp = &platmsg.jplat;
925         pp->platform = putshort(platform);
926         if ((cp = jupiter_send(up, hp)) != NULL)
927                 jupiter_debug(up->peer, __func__, "%u: %s", platform, cp);
928 }
929
930 /* Checksum "len" shorts */
931 static u_short
932 jupiter_cksum(u_short *sp, u_int len)
933 {
934         u_short sum, x;
935
936         sum = 0;
937         while (len-- > 0) {
938                 x = *sp++;
939                 sum += getshort(x);
940         }
941         return (~sum + 1);
942 }
943
944 /* Return the size of the next message (or zero if we don't have it all yet) */
945 static int
946 jupiter_recv(
947         struct instance * const up
948         )
949 {
950         int n, len, size, cc;
951         struct jheader *hp;
952         u_char *bp;
953         u_short *sp;
954
955         /* Must have at least a header's worth */
956         cc = sizeof(*hp);
957         size = up->ssize;
958         if (size < cc)
959                 return (0);
960
961         /* Search for the sync short if missing */
962         sp = up->sbuf;
963         hp = (struct jheader *)sp;
964         if (getshort(hp->sync) != JUPITER_SYNC) {
965                 /* Wasn't at the front, sync up */
966                 jupiter_debug(up->peer, __func__, "syncing");
967                 bp = (u_char *)sp;
968                 n = size;
969                 while (n >= 2) {
970                         if (bp[0] != (JUPITER_SYNC & 0xff)) {
971                                 /*
972                                 jupiter_debug(up->peer, __func__,
973                                     "{0x%x}", bp[0]);
974                                 */
975                                 ++bp;
976                                 --n;
977                                 continue;
978                         }
979                         if (bp[1] == ((JUPITER_SYNC >> 8) & 0xff))
980                                 break;
981                         /*
982                         jupiter_debug(up->peer, __func__,
983                             "{0x%x 0x%x}", bp[0], bp[1]);
984                         */
985                         bp += 2;
986                         n -= 2;
987                 }
988                 /*
989                 jupiter_debug(up->peer, __func__, "\n");
990                 */
991                 /* Shuffle data to front of input buffer */
992                 if (n > 0)
993                         memcpy(sp, bp, n);
994                 size = n;
995                 up->ssize = size;
996                 if (size < cc || hp->sync != JUPITER_SYNC)
997                         return (0);
998         }
999
1000         if (jupiter_cksum(sp, (cc / sizeof(u_short) - 1)) !=
1001             getshort(hp->hsum)) {
1002             jupiter_debug(up->peer, __func__, "bad header checksum!");
1003                 /* This is drastic but checksum errors should be rare */
1004                 up->ssize = 0;
1005                 return (0);
1006         }
1007
1008         /* Check for a payload */
1009         len = getshort(hp->len);
1010         if (len > 0) {
1011                 n = (len + 1) * sizeof(u_short);
1012                 /* Not enough data yet */
1013                 if (size < cc + n)
1014                         return (0);
1015
1016                 /* Check payload checksum */
1017                 sp = (u_short *)(hp + 1);
1018                 if (jupiter_cksum(sp, len) != getshort(sp[len])) {
1019                         jupiter_debug(up->peer,
1020                             __func__, "bad payload checksum!");
1021                         /* This is drastic but checksum errors should be rare */
1022                         up->ssize = 0;
1023                         return (0);
1024                 }
1025                 cc += n;
1026         }
1027         return (cc);
1028 }
1029
1030 #else /* not (REFCLOCK && CLOCK_JUPITER && HAVE_PPSAPI) */
1031 int refclock_jupiter_bs;
1032 #endif /* not (REFCLOCK && CLOCK_JUPITER && HAVE_PPSAPI) */