]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - contrib/ntp/ntpd/refclock_palisade.c
Fix multiple vulnerabilities in ntp. [SA-18:02.ntp]
[FreeBSD/releng/10.3.git] / contrib / ntp / ntpd / refclock_palisade.c
1 /*
2  * This software was developed by the Software and Component Technologies
3  * group of Trimble Navigation, Ltd.
4  *
5  * Copyright (c) 1997, 1998, 1999, 2000  Trimble Navigation Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *    This product includes software developed by Trimble Navigation, Ltd.
19  * 4. The name of Trimble Navigation Ltd. may not be used to endorse or
20  *    promote products derived from this software without specific prior
21  *    written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY TRIMBLE NAVIGATION LTD. ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL TRIMBLE NAVIGATION LTD. BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35
36 /*
37  * refclock_palisade - clock driver for the Trimble Palisade GPS
38  * timing receiver
39  *
40  * For detailed information on this program, please refer to the html 
41  * Refclock 29 page accompanying the NTP distribution.
42  *
43  * for questions / bugs / comments, contact:
44  * sven_dietrich@trimble.com
45  *
46  * Sven-Thorsten Dietrich
47  * 645 North Mary Avenue
48  * Post Office Box 3642
49  * Sunnyvale, CA 94088-3642
50  *
51  * Version 2.45; July 14, 1999
52  *
53  *
54  *
55  * 31/03/06: Added support for Thunderbolt GPS Disciplined Clock.
56  *           Contact: Fernando Pablo Hauscarriaga
57  *           E-mail: fernandoph@iar.unlp.edu.ar
58  *           Home page: www.iar.unlp.edu.ar/~fernandoph
59  *                Instituto Argentino de Radioastronomia
60  *                          www.iar.unlp.edu.ar
61  *
62  * 14/01/07: Conditinal compilation for Thunderbolt support no longer needed
63  *           now we use mode 2 for decode thunderbolt packets.
64  *           Fernando P. Hauscarriaga
65  *
66  * 30/08/09: Added support for Trimble Acutime Gold Receiver.
67  *           Fernando P. Hauscarriaga (fernandoph@iar.unlp.edu.ar)
68  */
69
70 #ifdef HAVE_CONFIG_H
71 # include "config.h"
72 #endif
73
74 #if defined(REFCLOCK) && defined(CLOCK_PALISADE)
75
76 #ifdef SYS_WINNT
77 extern int async_write(int, const void *, unsigned int);
78 #undef write
79 #define write(fd, data, octets) async_write(fd, data, octets)
80 #endif
81
82 #include "refclock_palisade.h"
83
84 #ifdef DEBUG
85 const char * Tracking_Status[15][15] = { 
86         { "Doing Fixes\0" }, { "Good 1SV\0" }, { "Approx. 1SV\0" },
87         {"Need Time\0" }, { "Need INIT\0" }, { "PDOP too High\0" },
88         { "Bad 1SV\0" }, { "0SV Usable\0" }, { "1SV Usable\0" },
89         { "2SV Usable\0" }, { "3SV Usable\0" }, { "No Integrity\0" },
90         { "Diff Corr\0" }, { "Overdet Clock\0" }, { "Invalid\0" } };
91 #endif
92
93 /*
94  * Transfer vector
95  */
96 struct refclock refclock_palisade = {
97         palisade_start,         /* start up driver */
98         palisade_shutdown,      /* shut down driver */
99         palisade_poll,          /* transmit poll message */
100         noentry,                /* not used  */
101         noentry,                /* initialize driver (not used) */
102         noentry,                /* not used */
103         NOFLAGS                 /* not used */
104 };
105
106 static int decode_date(struct refclockproc *pp, const char *cp);
107
108 /* Extract the clock type from the mode setting */
109 #define CLK_TYPE(x) ((int)(((x)->ttl) & 0x7F))
110
111 /* Supported clock types */
112 #define CLK_TRIMBLE     0       /* Trimble Palisade */
113 #define CLK_PRAECIS     1       /* Endrun Technologies Praecis */
114 #define CLK_THUNDERBOLT 2       /* Trimble Thunderbolt GPS Receiver */
115 #define CLK_ACUTIME     3       /* Trimble Acutime Gold */
116 #define CLK_ACUTIMEB    4       /* Trimble Actutime Gold Port B */
117
118 int praecis_msg;
119 static void praecis_parse(struct recvbuf *rbufp, struct peer *peer);
120
121 /* These routines are for sending packets to the Thunderbolt receiver
122  * They are taken from Markus Prosch
123  */
124
125 #ifdef PALISADE_SENDCMD_RESURRECTED
126 /*
127  * sendcmd - Build data packet for sending
128  */
129 static void 
130 sendcmd (
131         struct packettx *buffer,
132         int c
133         )
134 {
135         *buffer->data = DLE;
136         *(buffer->data + 1) = (unsigned char)c;
137         buffer->size = 2;
138 }
139 #endif  /* PALISADE_SENDCMD_RESURRECTED */
140
141 /*
142  * sendsupercmd - Build super data packet for sending
143  */
144 static void 
145 sendsupercmd (
146         struct packettx *buffer,
147         int c1,
148         int c2
149         )
150 {
151         *buffer->data = DLE;
152         *(buffer->data + 1) = (unsigned char)c1;
153         *(buffer->data + 2) = (unsigned char)c2;
154         buffer->size = 3;
155 }
156
157 /*
158  * sendbyte -
159  */
160 static void 
161 sendbyte (
162         struct packettx *buffer,
163         int b
164         )
165 {
166         if (b == DLE)
167                 *(buffer->data+buffer->size++) = DLE;
168         *(buffer->data+buffer->size++) = (unsigned char)b;
169 }
170
171 /*
172  * sendint -
173  */
174 static void 
175 sendint (
176         struct packettx *buffer,
177         int a
178         )
179 {
180         sendbyte(buffer, (unsigned char)((a>>8) & 0xff));
181         sendbyte(buffer, (unsigned char)(a & 0xff));
182 }
183
184 /*
185  * sendetx - Send packet or super packet to the device
186  */
187 static int 
188 sendetx (
189         struct packettx *buffer,
190         int fd
191         )
192 {
193         int result;
194         
195         *(buffer->data+buffer->size++) = DLE;
196         *(buffer->data+buffer->size++) = ETX;
197         result = write(fd, buffer->data, (unsigned long)buffer->size);
198         
199         if (result != -1)
200                 return (result);
201         else
202                 return (-1);
203 }
204
205 /*
206  * init_thunderbolt - Prepares Thunderbolt receiver to be used with
207  *                    NTP (also taken from Markus Prosch).
208  */
209 static void
210 init_thunderbolt (
211         int fd
212         )
213 {
214         struct packettx tx;
215         
216         tx.size = 0;
217         tx.data = (u_char *) emalloc(100);
218
219         /* set UTC time */
220         sendsupercmd (&tx, 0x8E, 0xA2);
221         sendbyte     (&tx, 0x3);
222         sendetx      (&tx, fd);
223         
224         /* activate packets 0x8F-AB and 0x8F-AC */
225         sendsupercmd (&tx, 0x8E, 0xA5);
226         sendint      (&tx, 0x5);
227         sendetx      (&tx, fd);
228
229         free(tx.data);
230 }
231
232 /*
233  * init_acutime - Prepares Acutime Receiver to be used with NTP
234  */
235 static void
236 init_acutime (
237         int fd
238         )
239 {
240         /* Disable all outputs, Enable Event-Polling on PortA so
241            we can ask for time packets */
242         struct packettx tx;
243
244         tx.size = 0;
245         tx.data = (u_char *) emalloc(100);
246
247         sendsupercmd(&tx, 0x8E, 0xA5);
248         sendbyte(&tx, 0x02);
249         sendbyte(&tx, 0x00);
250         sendbyte(&tx, 0x00);
251         sendbyte(&tx, 0x00);
252         sendetx(&tx, fd);
253
254         free(tx.data);
255 }
256
257 /*
258  * palisade_start - open the devices and initialize data for processing
259  */
260 static int
261 palisade_start (
262         int unit,
263         struct peer *peer
264         )
265 {
266         struct palisade_unit *up;
267         struct refclockproc *pp;
268         int fd;
269         char gpsdev[20];
270         struct termios tio;
271
272         snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit);
273
274         /*
275          * Open serial port. 
276          */
277         fd = refclock_open(gpsdev, SPEED232, LDISC_RAW);
278         if (fd <= 0) {
279 #ifdef DEBUG
280                 printf("Palisade(%d) start: open %s failed\n", unit, gpsdev);
281 #endif
282                 return 0;
283         }
284
285         msyslog(LOG_NOTICE, "Palisade(%d) fd: %d dev: %s", unit, fd,
286                 gpsdev);
287
288         if (tcgetattr(fd, &tio) < 0) {
289                 msyslog(LOG_ERR, 
290                         "Palisade(%d) tcgetattr(fd, &tio): %m",unit);
291 #ifdef DEBUG
292                 printf("Palisade(%d) tcgetattr(fd, &tio)\n",unit);
293 #endif
294                 close(fd);
295                 return (0);
296         }
297
298         tio.c_cflag |= (PARENB|PARODD);
299         tio.c_iflag &= ~ICRNL;
300
301         /*
302          * Allocate and initialize unit structure
303          */
304         up = emalloc_zero(sizeof(*up));
305
306         up->type = CLK_TYPE(peer);
307         switch (up->type) {
308             case CLK_TRIMBLE:
309                 /* Normal mode, do nothing */
310                 break;
311             case CLK_PRAECIS:
312                 msyslog(LOG_NOTICE, "Palisade(%d) Praecis mode enabled"
313                         ,unit);
314                 break;
315             case CLK_THUNDERBOLT:
316                 msyslog(LOG_NOTICE, "Palisade(%d) Thunderbolt mode enabled"
317                         ,unit);
318                 tio.c_cflag = (CS8|CLOCAL|CREAD);
319                 break;
320             case CLK_ACUTIME:
321                 msyslog(LOG_NOTICE, "Palisade(%d) Acutime Gold mode enabled"
322                         ,unit);
323                 break;
324             default:
325                 msyslog(LOG_NOTICE, "Palisade(%d) mode unknown",unit);
326                 break;
327         }
328         if (tcsetattr(fd, TCSANOW, &tio) == -1) {
329                 msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit);
330 #ifdef DEBUG
331                 printf("Palisade(%d) tcsetattr(fd, &tio)\n",unit);
332 #endif
333                 close(fd);
334                 free(up);
335                 return 0;
336         }
337
338         pp = peer->procptr;
339         pp->io.clock_recv = palisade_io;
340         pp->io.srcclock = peer;
341         pp->io.datalen = 0;
342         pp->io.fd = fd;
343         if (!io_addclock(&pp->io)) {
344 #ifdef DEBUG
345                 printf("Palisade(%d) io_addclock\n",unit);
346 #endif
347                 close(fd);
348                 pp->io.fd = -1;
349                 free(up);
350                 return (0);
351         }
352
353         /*
354          * Initialize miscellaneous variables
355          */
356         pp->unitptr = up;
357         pp->clockdesc = DESCRIPTION;
358
359         peer->precision = PRECISION;
360         peer->sstclktype = CTL_SST_TS_UHF;
361         peer->minpoll = TRMB_MINPOLL;
362         peer->maxpoll = TRMB_MAXPOLL;
363         memcpy((char *)&pp->refid, REFID, 4);
364         
365         up->leap_status = 0;
366         up->unit = (short) unit;
367         up->rpt_status = TSIP_PARSED_EMPTY;
368         up->rpt_cnt = 0;
369
370         if (up->type == CLK_THUNDERBOLT)
371                 init_thunderbolt(fd);
372         if (up->type == CLK_ACUTIME)
373                 init_acutime(fd);
374
375         return 1;
376 }
377
378
379 /*
380  * palisade_shutdown - shut down the clock
381  */
382 static void
383 palisade_shutdown (
384         int unit,
385         struct peer *peer
386         )
387 {
388         struct palisade_unit *up;
389         struct refclockproc *pp;
390         pp = peer->procptr;
391         up = pp->unitptr;
392         if (-1 != pp->io.fd)
393                 io_closeclock(&pp->io);
394         if (NULL != up)
395                 free(up);
396 }
397
398
399 /* 
400  * unpack helpers
401  */
402
403 static inline uint8_t
404 get_u8(
405         const char *cp)
406 {
407         return ((const u_char*)cp)[0];
408 }
409
410 static inline uint16_t
411 get_u16(
412         const char *cp)
413 {
414         return ((uint16_t)get_u8(cp) << 8) | get_u8(cp + 1);
415 }
416
417 /*
418  * unpack & fix date (the receiver provides a valid time for 1024 weeks
419  * after 1997-12-14 and therefore folds back in 2017, 2037,...)
420  *
421  * Returns -1 on error, day-of-month + (month * 32) othertwise.
422  */
423 int
424 decode_date(
425         struct refclockproc *pp,
426         const char          *cp)
427 {
428         static int32_t  s_baseday = 0;
429         
430         struct calendar jd;
431         int32_t         rd;
432
433         if (0 == s_baseday) {
434                 if (!ntpcal_get_build_date(&jd)) {
435                         jd.year     = 2015;
436                         jd.month    = 1;
437                         jd.monthday = 1;
438                 }
439                 s_baseday = ntpcal_date_to_rd(&jd);
440         }
441
442         /* get date fields and convert to RDN */
443         jd.monthday = get_u8 (  cp  );
444         jd.month    = get_u8 (cp + 1);
445         jd.year     = get_u16(cp + 2);
446         rd = ntpcal_date_to_rd(&jd);
447
448         /* for the paranoid: do reverse calculation and cross-check */
449         ntpcal_rd_to_date(&jd, rd);
450         if ((jd.monthday != get_u8 (  cp  )) ||
451             (jd.month    != get_u8 (cp + 1)) ||
452             (jd.year     != get_u16(cp + 2))  )
453                 return - 1;
454         
455         /* calculate cycle shift to base day and calculate re-folded
456          * date
457          *
458          * One could do a proper modulo calculation here, but a counting
459          * loop is probably faster for the next few rollovers...
460          */
461         while (rd < s_baseday)
462                 rd += 7*1024;
463         ntpcal_rd_to_date(&jd, rd);
464
465         /* fill refclock structure & indicate success */
466         pp->day  = jd.yearday;
467         pp->year = jd.year;     
468         return ((int)jd.month << 5) | jd.monthday;
469 }
470     
471
472 /* 
473  * TSIP_decode - decode the TSIP data packets 
474  */
475 int
476 TSIP_decode (
477         struct peer *peer
478         )
479 {
480         int st;
481         long   secint;
482         double secs;
483         double secfrac;
484         unsigned short event = 0;
485         int mmday;
486         
487         struct palisade_unit *up;
488         struct refclockproc *pp;
489
490         pp = peer->procptr;
491         up = pp->unitptr;
492
493         /*
494          * Check the time packet, decode its contents. 
495          * If the timecode has invalid length or is not in
496          * proper format, declare bad format and exit.
497          */
498
499         if ((up->type != CLK_THUNDERBOLT) & (up->type != CLK_ACUTIME)){
500                 if ((up->rpt_buf[0] == (char) 0x41) ||
501                     (up->rpt_buf[0] == (char) 0x46) ||
502                     (up->rpt_buf[0] == (char) 0x54) ||
503                     (up->rpt_buf[0] == (char) 0x4B) ||
504                     (up->rpt_buf[0] == (char) 0x6D)) {
505
506                         /* standard time packet - GPS time and GPS week number */
507 #ifdef DEBUG
508                         printf("Palisade Port B packets detected. Connect to Port A\n");
509 #endif
510
511                         return 0;       
512                 }
513         }
514
515         /*
516          * We cast both to u_char to as 0x8f uses the sign bit on a char
517          */
518         if ((u_char) up->rpt_buf[0] == (u_char) 0x8f) {
519                 /* 
520                  * Superpackets
521                  */
522                 event = (unsigned short) (getint((u_char *) &mb(1)) & 0xffff);
523                 if (!((pp->sloppyclockflag & CLK_FLAG2) || event)) 
524                         /* Ignore Packet */
525                         return 0;          
526         
527                 switch (mb(0) & 0xff) {
528                         int GPS_UTC_Offset;
529                         long tow;
530
531                     case PACKET_8F0B: 
532
533                         if (up->polled <= 0)
534                                 return 0;
535
536                         if (up->rpt_cnt != LENCODE_8F0B)  /* check length */
537                                 break;
538                 
539 #ifdef DEBUG
540                         if (debug > 1) {
541                                 int ts;
542                                 double lat, lon, alt;
543                                 lat = getdbl((u_char *) &mb(42)) * R2D;
544                                 lon = getdbl((u_char *) &mb(50)) * R2D;
545                                 alt = getdbl((u_char *) &mb(58));
546
547                                 printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
548                                        up->unit, lat,lon,alt);
549                                 printf("TSIP_decode: unit %d: Sats:",
550                                        up->unit);
551                                 for (st = 66, ts = 0; st <= 73; st++)
552                                         if (mb(st)) {
553                                                 if (mb(st) > 0) ts++;
554                                                 printf(" %02d", mb(st));
555                                         }
556                                 printf(" : Tracking %d\n", ts); 
557                         }
558 #endif
559
560                         GPS_UTC_Offset = getint((u_char *) &mb(16));  
561                         if (GPS_UTC_Offset == 0) { /* Check UTC offset */ 
562 #ifdef DEBUG
563                                 printf("TSIP_decode: UTC Offset Unknown\n");
564 #endif
565                                 break;
566                         }
567
568                         secs = getdbl((u_char *) &mb(3));
569                         secint = (long) secs;
570                         secfrac = secs - secint; /* 0.0 <= secfrac < 1.0 */
571
572                         pp->nsec = (long) (secfrac * 1000000000); 
573
574                         secint %= 86400;    /* Only care about today */
575                         pp->hour = secint / 3600;
576                         secint %= 3600;
577                         pp->minute = secint / 60;
578                         secint %= 60;
579                         pp->second = secint % 60;
580
581                         mmday = decode_date(pp, &mb(11));
582                         if (mmday < 0)
583                                 break;
584
585 #ifdef DEBUG
586                         if (debug > 1)
587                                 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d UTC %02d\n",
588                                        up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, 
589                                        pp->second, pp->nsec, (mmday >> 5), (mmday & 31), pp->year, GPS_UTC_Offset);
590 #endif
591                         /* Only use this packet when no
592                          * 8F-AD's are being received
593                          */
594
595                         if (up->leap_status) {
596                                 up->leap_status = 0;
597                                 return 0;
598                         }
599
600                         return 2;
601                         break;
602
603                     case PACKET_NTP:
604                         /* Palisade-NTP Packet */
605
606                         if (up->rpt_cnt != LENCODE_NTP) /* check length */
607                                 break;
608         
609                         up->leap_status = mb(19);
610
611                         if (up->polled  <= 0) 
612                                 return 0;
613                                 
614                         /* Check Tracking Status */
615                         st = mb(18);
616                         if (st < 0 || st > 14)
617                                 st = 14;
618                         if ((st >= 2 && st <= 7) || st == 11 || st == 12) {
619 #ifdef DEBUG
620                                 printf("TSIP_decode: Not Tracking Sats : %s\n",
621                                        *Tracking_Status[st]);
622 #endif
623                                 refclock_report(peer, CEVNT_BADTIME);
624                                 up->polled = -1;
625                                 return 0;
626                                 break;
627                         }
628
629                         mmday = decode_date(pp, &mb(14));
630                         if (mmday < 0)
631                                 break;
632                         up->month  = (mmday >> 5);  /* Save for LEAP check */
633
634                         if ( (up->leap_status & PALISADE_LEAP_PENDING) &&
635                         /* Avoid early announce: https://bugs.ntp.org/2773 */
636                                 (6 == up->month || 12 == up->month) ) {
637                                 if (up->leap_status & PALISADE_UTC_TIME)  
638                                         pp->leap = LEAP_ADDSECOND;
639                                 else
640                                         pp->leap = LEAP_DELSECOND;
641                         }
642                         else if (up->leap_status)
643                                 pp->leap = LEAP_NOWARNING;
644                 
645                         else {  /* UTC flag is not set:
646                                  * Receiver may have been reset, and lost
647                                  * its UTC almanac data */
648                                 pp->leap = LEAP_NOTINSYNC;
649 #ifdef DEBUG
650                                 printf("TSIP_decode: UTC Almanac unavailable: %d\n",
651                                        mb(19)); 
652 #endif
653                                 refclock_report(peer, CEVNT_BADTIME);
654                                 up->polled = -1;
655                                 return 0;
656                         }
657
658                         pp->nsec = (long) (getdbl((u_char *) &mb(3))
659                                            * 1000000000);
660
661                         pp->hour = mb(11);
662                         pp->minute = mb(12);
663                         pp->second = mb(13);
664
665 #ifdef DEBUG
666                         if (debug > 1)
667                                 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d UTC %02x %s\n",
668                                        up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, 
669                                        pp->second, pp->nsec, (mmday >> 5), (mmday & 31), pp->year,
670                                        mb(19), *Tracking_Status[st]);
671 #endif
672                         return 1;
673                         break;
674
675                     case PACKET_8FAC:   
676                         if (up->polled <= 0)
677                                 return 0; 
678
679                         if (up->rpt_cnt != LENCODE_8FAC)/* check length */
680                                 break;
681
682 #ifdef DEBUG
683                         if (debug > 1) {
684                                 double lat, lon, alt;
685                                 lat = getdbl((u_char *) &mb(36)) * R2D;
686                                 lon = getdbl((u_char *) &mb(44)) * R2D;
687                                 alt = getdbl((u_char *) &mb(52));
688
689                                 printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
690                                        up->unit, lat,lon,alt);
691                                 printf("TSIP_decode: unit %d\n", up->unit);
692                         }
693 #endif
694                         if ( (getint((u_char *) &mb(10)) & 0x80) &&
695                         /* Avoid early announce: https://bugs.ntp.org/2773 */
696                             (6 == up->month || 12 == up->month) )
697                                 pp->leap = LEAP_ADDSECOND;  /* we ASSUME addsecond */
698                         else 
699                                 pp->leap = LEAP_NOWARNING;
700
701 #ifdef DEBUG
702                         if (debug > 1) 
703                                 printf("TSIP_decode: unit %d: 0x%02x leap %d\n",
704                                        up->unit, mb(0) & 0xff, pp->leap);
705                         if (debug > 1) {
706                                 printf("Receiver MODE: 0x%02X\n", (u_char)mb(1));
707                                 if (mb(1) == 0x00)
708                                         printf("                AUTOMATIC\n");
709                                 if (mb(1) == 0x01)
710                                         printf("                SINGLE SATELLITE\n");   
711                                 if (mb(1) == 0x03)
712                                         printf("                HORIZONTAL(2D)\n");
713                                 if (mb(1) == 0x04)
714                                         printf("                FULL POSITION(3D)\n");
715                                 if (mb(1) == 0x05)
716                                         printf("                DGPR REFERENCE\n");
717                                 if (mb(1) == 0x06)
718                                         printf("                CLOCK HOLD(2D)\n");
719                                 if (mb(1) == 0x07)
720                                         printf("                OVERDETERMINED CLOCK\n");
721
722                                 printf("\n** Disciplining MODE 0x%02X:\n", (u_char)mb(2));
723                                 if (mb(2) == 0x00)
724                                         printf("                NORMAL\n");
725                                 if (mb(2) == 0x01)
726                                         printf("                POWER-UP\n");
727                                 if (mb(2) == 0x02)
728                                         printf("                AUTO HOLDOVER\n");
729                                 if (mb(2) == 0x03)
730                                         printf("                MANUAL HOLDOVER\n");
731                                 if (mb(2) == 0x04)
732                                         printf("                RECOVERY\n");
733                                 if (mb(2) == 0x06)
734                                         printf("                DISCIPLINING DISABLED\n");
735                         }
736 #endif   
737                         return 0;
738                         break;
739
740                     case PACKET_8FAB:
741                         /* Thunderbolt Primary Timing Packet */
742
743                         if (up->rpt_cnt != LENCODE_8FAB) /* check length */
744                                 break;
745
746                         if (up->polled  <= 0)
747                                 return 0;
748
749                         GPS_UTC_Offset = getint((u_char *) &mb(7));
750
751                         if (GPS_UTC_Offset == 0){ /* Check UTC Offset */
752 #ifdef DEBUG
753                                 printf("TSIP_decode: UTC Offset Unknown\n");
754 #endif
755                                 break;
756                         }
757
758
759                         if ((mb(9) & 0x1d) == 0x0) {
760                                 /* if we know the GPS time and the UTC offset,
761                                    we expect UTC timing information !!! */
762
763                                 pp->leap = LEAP_NOTINSYNC;
764                                 refclock_report(peer, CEVNT_BADTIME);
765                                 up->polled = -1;
766                                 return 0;
767                         }
768
769                         pp->nsec = 0;
770 #ifdef DEBUG            
771                         printf("\nTiming Flags are:\n");
772                         printf("Timing flag value is: 0x%X\n", mb(9));
773                         if ((mb(9) & 0x01) != 0)
774                                 printf ("       Getting UTC time\n");
775                         else
776                                 printf ("       Getting GPS time\n");
777                         if ((mb(9) & 0x02) != 0)
778                                 printf ("       PPS is from UTC\n");
779                         else
780                                 printf ("       PPS is from GPS\n");
781                         if ((mb(9) & 0x04) != 0)
782                                 printf ("       Time is not Set\n");
783                         else
784                                 printf ("       Time is Set\n");
785                         if ((mb(9) & 0x08) != 0)
786                                 printf("        I dont have UTC info\n");
787                         else
788                                 printf ("       I have UTC info\n");
789                         if ((mb(9) & 0x10) != 0)
790                                 printf ("       Time is from USER\n\n");
791                         else
792                                 printf ("       Time is from GPS\n\n"); 
793 #endif          
794
795                         mmday = decode_date(pp, &mb(13));
796                         if (mmday < 0)
797                                 break;
798                         tow = getlong((u_char *) &mb(1));
799 #ifdef DEBUG            
800                         if (debug > 1) {
801                                 printf("pp->day: %d\n", pp->day); 
802                                 printf("TOW: %ld\n", tow);
803                                 printf("DAY: %d\n", (mmday & 31));
804                         }
805 #endif
806                         pp->hour = mb(12);
807                         pp->minute = mb(11);
808                         pp->second = mb(10);
809
810
811 #ifdef DEBUG
812                         if (debug > 1)
813                                 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d ",
814                                        up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, pp->second,
815                                        pp->nsec, (mmday >> 5), (mmday & 31), pp->year);
816 #endif
817                         return 1;
818                         break;
819
820                     default:
821                         /* Ignore Packet */
822                         return 0;
823                 } /* switch */
824         } /* if 8F packets */
825
826         else if (up->rpt_buf[0] == (u_char)0x42) {
827                 printf("0x42\n");
828                 return 0;
829         }
830         else if (up->rpt_buf[0] == (u_char)0x43) {
831                 printf("0x43\n");
832                 return 0;
833         }
834         else if ((up->rpt_buf[0] == PACKET_41) & (up->type == CLK_THUNDERBOLT)){
835                 printf("Undocumented 0x41 packet on Thunderbolt\n");
836                 return 0;
837         }
838         else if ((up->rpt_buf[0] == PACKET_41A) & (up->type == CLK_ACUTIME)) {
839 #ifdef DEBUG
840                 printf("GPS TOW: %ld\n", (long)getlong((u_char *) &mb(0)));
841                 printf("GPS WN: %d\n", getint((u_char *) &mb(4)));
842                 printf("GPS UTC-GPS Offser: %ld\n", (long)getlong((u_char *) &mb(6)));
843 #endif
844                 return 0;
845         }
846
847         /* Health Status for Acutime Receiver */
848         else if ((up->rpt_buf[0] == PACKET_46) & (up->type == CLK_ACUTIME)) {
849 #ifdef DEBUG
850                 if (debug > 1)
851                 /* Status Codes */
852                         switch (mb(0)) {
853                             case 0x00:
854                                 printf ("Doing Position Fixes\n");
855                                 break;
856                             case 0x01:
857                                 printf ("Do no have GPS time yet\n");
858                                 break;
859                             case 0x03:
860                                 printf ("PDOP is too high\n");
861                                 break;
862                             case 0x08:
863                                 printf ("No usable satellites\n");
864                                 break;
865                             case 0x09:
866                                 printf ("Only 1 usable satellite\n");
867                                 break;
868                             case 0x0A:
869                                 printf ("Only 2 usable satellites\n");
870                                 break;
871                             case 0x0B:
872                                 printf ("Only 3 usable satellites\n");
873                                 break;
874                             case 0x0C:
875                                 printf("The Chosen satellite is unusable\n");
876                                 break;
877                         }
878 #endif
879                 /* Error Codes */
880                 if (mb(1) != 0) {
881                         
882                         refclock_report(peer, CEVNT_BADTIME);
883                         up->polled = -1;
884 #ifdef DEBUG
885                         if (debug > 1) {
886                                 if (mb(1) & 0x01)
887                                         printf ("Signal Processor Error, reset unit.\n");
888                                 if (mb(1) & 0x02)
889                                         printf ("Alignment error, channel or chip 1, reset unit.\n");
890                                 if (mb(1) & 0x03)
891                                         printf ("Alignment error, channel or chip 2, reset unit.\n");
892                                 if (mb(1) & 0x04)
893                                         printf ("Antenna feed line fault (open or short)\n");
894                                 if (mb(1) & 0x05)
895                                         printf ("Excessive reference frequency error, refer to packet 0x2D and packet 0x4D documentation for further information\n");
896                         }
897 #endif
898                 
899                 return 0;
900                 }
901         }
902         else if (up->rpt_buf[0] == 0x54)
903                 return 0;
904
905         else if (up->rpt_buf[0] == PACKET_6D) {
906 #ifdef DEBUG
907                 int sats;
908
909                 if ((mb(0) & 0x01) && (mb(0) & 0x02))
910                         printf("2d Fix Dimension\n");
911                 if (mb(0) & 0x04)
912                         printf("3d Fix Dimension\n");
913
914                 if (mb(0) & 0x08)
915                         printf("Fix Mode is MANUAL\n");
916                 else
917                         printf("Fix Mode is AUTO\n");
918         
919                 sats = mb(0) & 0xF0;
920                 sats = sats >> 4;
921                 printf("Tracking %d Satellites\n", sats);
922 #endif
923                 return 0;
924         } /* else if not super packet */
925         refclock_report(peer, CEVNT_BADREPLY);
926         up->polled = -1;
927 #ifdef DEBUG
928         printf("TSIP_decode: unit %d: bad packet %02x-%02x event %d len %d\n", 
929                up->unit, up->rpt_buf[0] & 0xff, mb(0) & 0xff, 
930                event, up->rpt_cnt);
931 #endif
932         return 0;
933 }
934
935 /*
936  * palisade__receive - receive data from the serial interface
937  */
938
939 static void
940 palisade_receive (
941         struct peer * peer
942         )
943 {
944         struct palisade_unit *up;
945         struct refclockproc *pp;
946
947         /*
948          * Initialize pointers and read the timecode and timestamp.
949          */
950         pp = peer->procptr;
951         up = pp->unitptr;
952                 
953         if (! TSIP_decode(peer)) return;
954         
955         if (up->polled <= 0) 
956                 return;   /* no poll pending, already received or timeout */
957
958         up->polled = 0;  /* Poll reply received */
959         pp->lencode = 0; /* clear time code */
960 #ifdef DEBUG
961         if (debug) 
962                 printf(
963                         "palisade_receive: unit %d: %4d %03d %02d:%02d:%02d.%09ld\n",
964                         up->unit, pp->year, pp->day, pp->hour, pp->minute, 
965                         pp->second, pp->nsec);
966 #endif
967
968         /*
969          * Process the sample
970          * Generate timecode: YYYY DoY HH:MM:SS.microsec 
971          * report and process 
972          */
973
974         snprintf(pp->a_lastcode, sizeof(pp->a_lastcode),
975                  "%4d %03d %02d:%02d:%02d.%09ld",
976                  pp->year, pp->day,
977                  pp->hour,pp->minute, pp->second, pp->nsec); 
978         pp->lencode = 24;
979
980         if (!refclock_process(pp)) {
981                 refclock_report(peer, CEVNT_BADTIME);
982
983 #ifdef DEBUG
984                 printf("palisade_receive: unit %d: refclock_process failed!\n",
985                        up->unit);
986 #endif
987                 return;
988         }
989
990         record_clock_stats(&peer->srcadr, pp->a_lastcode); 
991
992 #ifdef DEBUG
993         if (debug)
994                 printf("palisade_receive: unit %d: %s\n",
995                        up->unit, prettydate(&pp->lastrec));
996 #endif
997         pp->lastref = pp->lastrec;
998         refclock_receive(peer);
999 }
1000
1001
1002 /*
1003  * palisade_poll - called by the transmit procedure
1004  *
1005  */
1006 static void
1007 palisade_poll (
1008         int unit,
1009         struct peer *peer
1010         )
1011 {
1012         struct palisade_unit *up;
1013         struct refclockproc *pp;
1014         
1015         pp = peer->procptr;
1016         up = pp->unitptr;
1017
1018         pp->polls++;
1019         if (up->polled > 0) /* last reply never arrived or error */ 
1020                 refclock_report(peer, CEVNT_TIMEOUT);
1021
1022         up->polled = 2; /* synchronous packet + 1 event */
1023         
1024 #ifdef DEBUG
1025         if (debug)
1026                 printf("palisade_poll: unit %d: polling %s\n", unit,
1027                        (pp->sloppyclockflag & CLK_FLAG2) ? 
1028                        "synchronous packet" : "event");
1029 #endif 
1030
1031         if (pp->sloppyclockflag & CLK_FLAG2) 
1032                 return;  /* using synchronous packet input */
1033
1034         if(up->type == CLK_PRAECIS) {
1035                 if(write(peer->procptr->io.fd,"SPSTAT\r\n",8) < 0)
1036                         msyslog(LOG_ERR, "Palisade(%d) write: %m:",unit);
1037                 else {
1038                         praecis_msg = 1;
1039                         return;
1040                 }
1041         }
1042
1043         if (HW_poll(pp) < 0) 
1044                 refclock_report(peer, CEVNT_FAULT); 
1045 }
1046
1047 static void
1048 praecis_parse (
1049         struct recvbuf *rbufp,
1050         struct peer *peer
1051         )
1052 {
1053         static char buf[100];
1054         static int p = 0;
1055         struct refclockproc *pp;
1056
1057         pp = peer->procptr;
1058
1059         memcpy(buf+p,rbufp->recv_space.X_recv_buffer, rbufp->recv_length);
1060         p += rbufp->recv_length;
1061
1062         if(buf[p-2] == '\r' && buf[p-1] == '\n') {
1063                 buf[p-2] = '\0';
1064                 record_clock_stats(&peer->srcadr, buf);
1065
1066                 p = 0;
1067                 praecis_msg = 0;
1068
1069                 if (HW_poll(pp) < 0)
1070                         refclock_report(peer, CEVNT_FAULT);
1071
1072         }
1073 }
1074
1075 static void
1076 palisade_io (
1077         struct recvbuf *rbufp
1078         )
1079 {
1080         /*
1081          * Initialize pointers and read the timecode and timestamp.
1082          */
1083         struct palisade_unit *up;
1084         struct refclockproc *pp;
1085         struct peer *peer;
1086
1087         char * c, * d;
1088
1089         peer = rbufp->recv_peer;
1090         pp = peer->procptr;
1091         up = pp->unitptr;
1092
1093         if(up->type == CLK_PRAECIS) {
1094                 if(praecis_msg) {
1095                         praecis_parse(rbufp,peer);
1096                         return;
1097                 }
1098         }
1099
1100         c = (char *) &rbufp->recv_space;
1101         d = c + rbufp->recv_length;
1102                 
1103         while (c != d) {
1104
1105                 /* Build time packet */
1106                 switch (up->rpt_status) {
1107
1108                     case TSIP_PARSED_DLE_1:
1109                         switch (*c)
1110                         {
1111                             case 0:
1112                             case DLE:
1113                             case ETX:
1114                                 up->rpt_status = TSIP_PARSED_EMPTY;
1115                                 break;
1116
1117                             default:
1118                                 up->rpt_status = TSIP_PARSED_DATA;
1119                                 /* save packet ID */
1120                                 up->rpt_buf[0] = *c;
1121                                 break;
1122                         }
1123                         break;
1124
1125                     case TSIP_PARSED_DATA:
1126                         if (*c == DLE)
1127                                 up->rpt_status = TSIP_PARSED_DLE_2;
1128                         else 
1129                                 mb(up->rpt_cnt++) = *c;
1130                         break;
1131
1132                     case TSIP_PARSED_DLE_2:
1133                         if (*c == DLE) {
1134                                 up->rpt_status = TSIP_PARSED_DATA;
1135                                 mb(up->rpt_cnt++) = 
1136                                     *c;
1137                         }
1138                         else if (*c == ETX) 
1139                                 up->rpt_status = TSIP_PARSED_FULL;
1140                         else    {
1141                                 /* error: start new report packet */
1142                                 up->rpt_status = TSIP_PARSED_DLE_1;
1143                                 up->rpt_buf[0] = *c;
1144                         }
1145                         break;
1146
1147                     case TSIP_PARSED_FULL:
1148                     case TSIP_PARSED_EMPTY:
1149                     default:
1150                         if ( *c != DLE)
1151                                 up->rpt_status = TSIP_PARSED_EMPTY;
1152                         else 
1153                                 up->rpt_status = TSIP_PARSED_DLE_1;
1154                         break;
1155                 }
1156                 
1157                 c++;
1158
1159                 if (up->rpt_status == TSIP_PARSED_DLE_1) {
1160                         up->rpt_cnt = 0;
1161                         if (pp->sloppyclockflag & CLK_FLAG2) 
1162                                 /* stamp it */
1163                                 get_systime(&pp->lastrec);
1164                 }
1165                 else if (up->rpt_status == TSIP_PARSED_EMPTY)
1166                         up->rpt_cnt = 0;
1167
1168                 else if (up->rpt_cnt > BMAX) 
1169                         up->rpt_status =TSIP_PARSED_EMPTY;
1170
1171                 if (up->rpt_status == TSIP_PARSED_FULL) 
1172                         palisade_receive(peer);
1173
1174         } /* while chars in buffer */
1175 }
1176
1177
1178 /*
1179  * Trigger the Palisade's event input, which is driven off the RTS
1180  *
1181  * Take a system time stamp to match the GPS time stamp.
1182  *
1183  */
1184 long
1185 HW_poll (
1186         struct refclockproc * pp        /* pointer to unit structure */
1187         )
1188 {       
1189         int x;  /* state before & after RTS set */
1190         struct palisade_unit *up;
1191
1192         up = pp->unitptr;
1193
1194         /* read the current status, so we put things back right */
1195         if (ioctl(pp->io.fd, TIOCMGET, &x) < 0) {
1196                 DPRINTF(1, ("Palisade HW_poll: unit %d: GET %m\n",
1197                         up->unit));
1198                 msyslog(LOG_ERR, "Palisade(%d) HW_poll: ioctl(fd,GET): %m", 
1199                         up->unit);
1200                 return -1;
1201         }
1202   
1203         x |= TIOCM_RTS;        /* turn on RTS  */
1204
1205         /* Edge trigger */
1206         if (up->type == CLK_ACUTIME)
1207                 write (pp->io.fd, "", 1);
1208                 
1209         if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) { 
1210 #ifdef DEBUG
1211                 if (debug)
1212                         printf("Palisade HW_poll: unit %d: SET \n", up->unit);
1213 #endif
1214                 msyslog(LOG_ERR,
1215                         "Palisade(%d) HW_poll: ioctl(fd, SET, RTS_on): %m", 
1216                         up->unit);
1217                 return -1;
1218         }
1219
1220         x &= ~TIOCM_RTS;        /* turn off RTS  */
1221         
1222         /* poll timestamp */
1223         get_systime(&pp->lastrec);
1224
1225         if (ioctl(pp->io.fd, TIOCMSET, &x) == -1) {
1226 #ifdef DEBUG
1227                 if (debug)
1228                         printf("Palisade HW_poll: unit %d: UNSET \n", up->unit);
1229 #endif
1230                 msyslog(LOG_ERR,
1231                         "Palisade(%d) HW_poll: ioctl(fd, UNSET, RTS_off): %m", 
1232                         up->unit);
1233                 return -1;
1234         }
1235
1236         return 0;
1237 }
1238
1239 /*
1240  * copy/swap a big-endian palisade double into a host double
1241  */
1242 static double
1243 getdbl (
1244         u_char *bp
1245         )
1246 {
1247 #ifdef WORDS_BIGENDIAN
1248         double out;
1249
1250         memcpy(&out, bp, sizeof(out));
1251         return out;
1252 #else
1253         union {
1254                 u_char ch[8];
1255                 u_int32 u32[2];
1256         } ui;
1257                 
1258         union {
1259                 double out;
1260                 u_int32 u32[2];
1261         } uo;
1262
1263         memcpy(ui.ch, bp, sizeof(ui.ch));
1264         /* least-significant 32 bits of double from swapped bp[4] to bp[7] */
1265         uo.u32[0] = ntohl(ui.u32[1]);
1266         /* most-significant 32 bits from swapped bp[0] to bp[3] */
1267         uo.u32[1] = ntohl(ui.u32[0]);
1268
1269         return uo.out;
1270 #endif
1271 }
1272
1273 /*
1274  * copy/swap a big-endian palisade short into a host short
1275  */
1276 static short
1277 getint (
1278         u_char *bp
1279         )
1280 {
1281         u_short us;
1282
1283         memcpy(&us, bp, sizeof(us));
1284         return (short)ntohs(us);
1285 }
1286
1287 /*
1288  * copy/swap a big-endian palisade 32-bit int into a host 32-bit int
1289  */
1290 static int32
1291 getlong(
1292         u_char *bp
1293         )
1294 {
1295         u_int32 u32;
1296
1297         memcpy(&u32, bp, sizeof(u32));
1298         return (int32)(u_int32)ntohl(u32);
1299 }
1300
1301 #else   /* REFCLOCK && CLOCK_PALISADE*/
1302 int refclock_palisade_c_notempty;
1303 #endif