1 /* 2 * ntp_refclock - processing support for reference clocks 3 */ 4 #ifdef HAVE_CONFIG_H 5 # include <config.h> 6 #endif 7 8 #include <stdio.h> 9 #include <sys/types.h> 10 #ifdef HAVE_SYS_IOCTL_H 11 # include <sys/ioctl.h> 12 #endif /* HAVE_SYS_IOCTL_H */ 13 14 #include "ntpd.h" 15 #include "ntp_io.h" 16 #include "ntp_unixtime.h" 17 #include "ntp_refclock.h" 18 #include "ntp_stdlib.h" 19 20 #ifdef REFCLOCK 21 22 #ifdef TTYCLK 23 # ifdef HAVE_SYS_CLKDEFS_H 24 # include <sys/clkdefs.h> 25 # endif 26 # ifdef HAVE_SYS_SIO_H 27 # include <sys/sio.h> 28 # endif 29 #endif /* TTYCLK */ 30 31 #ifdef HAVE_PPSCLOCK_H 32 #include <sys/ppsclock.h> 33 #endif /* HAVE_PPSCLOCK_H */ 34 35 #ifdef HAVE_PPSAPI 36 # ifdef HAVE_TIMEPPS_H 37 # include <timepps.h> 38 # else 39 # ifdef HAVE_SYS_TIMEPPS_H 40 # include <sys/timepps.h> 41 # endif 42 # endif 43 #endif /* HAVE_PPSAPI */ 44 45 /* 46 * Reference clock support is provided here by maintaining the fiction 47 * that the clock is actually a peer. As no packets are exchanged with a 48 * reference clock, however, we replace the transmit, receive and packet 49 * procedures with separate code to simulate them. Routines 50 * refclock_transmit() and refclock_receive() maintain the peer 51 * variables in a state analogous to an actual peer and pass reference 52 * clock data on through the filters. Routines refclock_peer() and 53 * refclock_unpeer() are called to initialize and terminate reference 54 * clock associations. A set of utility routines is included to open 55 * serial devices, process sample data, edit input lines to extract 56 * embedded timestamps and to peform various debugging functions. 57 * 58 * The main interface used by these routines is the refclockproc 59 * structure, which contains for most drivers the decimal equivalants of 60 * the year, day, month, hour, second and millisecond/microsecond 61 * decoded from the ASCII timecode. Additional information includes the 62 * receive timestamp, exception report, statistics tallies, etc. In 63 * addition, there may be a driver-specific unit structure used for 64 * local control of the device. 65 * 66 * The support routines are passed a pointer to the peer structure, 67 * which is used for all peer-specific processing and contains a pointer 68 * to the refclockproc structure, which in turn containes a pointer to 69 * the unit structure, if used. The peer structure is identified by an 70 * interface address in the dotted quad form 127.127.t.u, where t is the 71 * clock type and u the unit. Some legacy drivers derive the 72 * refclockproc structure pointer from the table typeunit[type][unit]. 73 * This interface is strongly discouraged and may be abandoned in 74 * future. 75 * 76 * The routines include support for the 1-pps signal provided by some 77 * radios and connected via a level converted described in the gadget 78 * directory. The signal is captured using a serial port and one of 79 * three STREAMS modules described in the refclock_atom.c file. For the 80 * highest precision, the signal is captured using the carrier-detect 81 * line of a serial port and either the ppsclock or ppsapi streams 82 * module or some devilish ioctl() folks keep slipping in as a patch. Be 83 * advised ALL support for other than the duly standardized ppsapi 84 * interface will eventually be withdrawn. 85 */ 86 #define MAXUNIT 4 /* max units */ 87 88 #if defined(PPS) || defined(HAVE_PPSAPI) 89 int fdpps; /* pps file descriptor */ 90 #endif /* PPS HAVE_PPSAPI */ 91 92 #define FUDGEFAC .1 /* fudge correction factor */ 93 94 /* 95 * Type/unit peer index. Used to find the peer structure for control and 96 * debugging. When all clock drivers have been converted to new style, 97 * this dissapears. 98 */ 99 static struct peer *typeunit[REFCLK_MAX + 1][MAXUNIT]; 100 101 /* 102 * Forward declarations 103 */ 104 #ifdef QSORT_USES_VOID_P 105 static int refclock_cmpl_fp P((const void *, const void *)); 106 #else 107 static int refclock_cmpl_fp P((const double *, const double *)); 108 #endif /* QSORT_USES_VOID_P */ 109 static int refclock_sample P((struct refclockproc *)); 110 111 #ifdef HAVE_PPSAPI 112 extern int pps_assert; /* capture edge 1:assert, 0:clear */ 113 extern int pps_hardpps; /* PPS kernel 1:on, 0:off */ 114 #endif /* HAVE_PPSAPI */ 115 116 /* 117 * refclock_report - note the occurance of an event 118 * 119 * This routine presently just remembers the report and logs it, but 120 * does nothing heroic for the trap handler. It tries to be a good 121 * citizen and bothers the system log only if things change. 122 */ 123 void 124 refclock_report( 125 struct peer *peer, 126 int code 127 ) 128 { 129 struct refclockproc *pp; 130 131 if (!(pp = peer->procptr)) 132 return; 133 if (code == CEVNT_BADREPLY) 134 pp->badformat++; 135 if (code == CEVNT_BADTIME) 136 pp->baddata++; 137 if (code == CEVNT_TIMEOUT) 138 pp->noreply++; 139 if (pp->currentstatus != code) { 140 pp->currentstatus = code; 141 pp->lastevent = code; 142 if (code == CEVNT_FAULT) 143 msyslog(LOG_ERR, 144 "clock %s event '%s' (0x%02x)", 145 refnumtoa(peer->srcadr.sin_addr.s_addr), 146 ceventstr(code), code); 147 else { 148 NLOG(NLOG_CLOCKEVENT) 149 msyslog(LOG_INFO, 150 "clock %s event '%s' (0x%02x)", 151 refnumtoa(peer->srcadr.sin_addr.s_addr), 152 ceventstr(code), code); 153 } 154 } 155 #ifdef DEBUG 156 if (debug) 157 printf("clock %s event '%s' (0x%02x)\n", 158 refnumtoa(peer->srcadr.sin_addr.s_addr), 159 ceventstr(code), code); 160 #endif 161 } 162 163 164 /* 165 * init_refclock - initialize the reference clock drivers 166 * 167 * This routine calls each of the drivers in turn to initialize internal 168 * variables, if necessary. Most drivers have nothing to say at this 169 * point. 170 */ 171 void 172 init_refclock(void) 173 { 174 int i, j; 175 176 for (i = 0; i < (int)num_refclock_conf; i++) { 177 if (refclock_conf[i]->clock_init != noentry) 178 (refclock_conf[i]->clock_init)(); 179 for (j = 0; j < MAXUNIT; j++) 180 typeunit[i][j] = 0; 181 } 182 } 183 184 185 /* 186 * refclock_newpeer - initialize and start a reference clock 187 * 188 * This routine allocates and initializes the interface structure which 189 * supports a reference clock in the form of an ordinary NTP peer. A 190 * driver-specific support routine completes the initialization, if 191 * used. Default peer variables which identify the clock and establish 192 * its reference ID and stratum are set here. It returns one if success 193 * and zero if the clock address is invalid or already running, 194 * insufficient resources are available or the driver declares a bum 195 * rap. 196 */ 197 int 198 refclock_newpeer( 199 struct peer *peer /* peer structure pointer */ 200 ) 201 { 202 struct refclockproc *pp; 203 u_char clktype; 204 int unit; 205 206 /* 207 * Check for valid clock address. If already running, shut it 208 * down first. 209 */ 210 if (!ISREFCLOCKADR(&peer->srcadr)) { 211 msyslog(LOG_ERR, 212 "refclock_newpeer: clock address %s invalid", 213 ntoa(&peer->srcadr)); 214 return (0); 215 } 216 clktype = (u_char)REFCLOCKTYPE(&peer->srcadr); 217 unit = REFCLOCKUNIT(&peer->srcadr); 218 if (clktype >= num_refclock_conf || unit >= MAXUNIT || 219 refclock_conf[clktype]->clock_start == noentry) { 220 msyslog(LOG_ERR, 221 "refclock_newpeer: clock type %d invalid\n", 222 clktype); 223 return (0); 224 } 225 refclock_unpeer(peer); 226 227 /* 228 * Allocate and initialize interface structure 229 */ 230 if (!(pp = (struct refclockproc *)emalloc(sizeof(struct refclockproc)))) 231 return (0); 232 memset((char *)pp, 0, sizeof(struct refclockproc)); 233 typeunit[clktype][unit] = peer; 234 peer->procptr = pp; 235 236 /* 237 * Initialize structures 238 */ 239 peer->refclktype = clktype; 240 peer->refclkunit = unit; 241 peer->flags |= FLAG_REFCLOCK; 242 peer->stratum = STRATUM_REFCLOCK; 243 peer->refid = peer->srcadr.sin_addr.s_addr; 244 peer->maxpoll = peer->minpoll; 245 246 pp->type = clktype; 247 pp->timestarted = current_time; 248 249 /* 250 * If the interface has been set to any_interface, set it to the 251 * loopback address if we have one. This is so that peers which 252 * are unreachable are easy to see in the peer display. 253 */ 254 if (peer->dstadr == any_interface && loopback_interface != 0) 255 peer->dstadr = loopback_interface; 256 257 /* 258 * Set peer.pmode based on the hmode. For appearances only. 259 */ 260 switch (peer->hmode) { 261 262 case MODE_ACTIVE: 263 peer->pmode = MODE_PASSIVE; 264 break; 265 266 default: 267 peer->pmode = MODE_SERVER; 268 break; 269 } 270 271 /* 272 * Do driver dependent initialization. The above defaults 273 * can be wiggled, then finish up for consistency. 274 */ 275 if (!((refclock_conf[clktype]->clock_start)(unit, peer))) { 276 free(pp); 277 return (0); 278 } 279 peer->hpoll = peer->minpoll; 280 peer->ppoll = peer->maxpoll; 281 if (peer->stratum <= 1) 282 peer->refid = pp->refid; 283 else 284 peer->refid = peer->srcadr.sin_addr.s_addr; 285 return (1); 286 } 287 288 289 /* 290 * refclock_unpeer - shut down a clock 291 */ 292 void 293 refclock_unpeer( 294 struct peer *peer /* peer structure pointer */ 295 ) 296 { 297 u_char clktype; 298 int unit; 299 300 /* 301 * Wiggle the driver to release its resources, then give back 302 * the interface structure. 303 */ 304 if (!peer->procptr) 305 return; 306 clktype = peer->refclktype; 307 unit = peer->refclkunit; 308 if (refclock_conf[clktype]->clock_shutdown != noentry) 309 (refclock_conf[clktype]->clock_shutdown)(unit, peer); 310 free(peer->procptr); 311 peer->procptr = 0; 312 } 313 314 315 /* 316 * refclock_transmit - simulate the transmit procedure 317 * 318 * This routine implements the NTP transmit procedure for a reference 319 * clock. This provides a mechanism to call the driver at the NTP poll 320 * interval, as well as provides a reachability mechanism to detect a 321 * broken radio or other madness. 322 */ 323 void 324 refclock_transmit( 325 struct peer *peer /* peer structure pointer */ 326 ) 327 { 328 u_char clktype; 329 int unit; 330 int hpoll; 331 u_long next; 332 333 clktype = peer->refclktype; 334 unit = peer->refclkunit; 335 peer->sent++; 336 337 /* 338 * This is a ripoff of the peer transmit routine, but 339 * specialized for reference clocks. We do a little less 340 * protocol here and call the driver-specific transmit routine. 341 */ 342 hpoll = peer->hpoll; 343 next = peer->outdate; 344 if (peer->burst == 0) { 345 u_char oreach; 346 #ifdef DEBUG 347 if (debug) 348 printf("refclock_transmit: at %ld %s\n", 349 current_time, ntoa(&(peer->srcadr))); 350 #endif 351 352 /* 353 * Update reachability and poll variables like the 354 * network code. 355 */ 356 oreach = peer->reach; 357 if (oreach & 0x01) 358 peer->valid++; 359 if (oreach & 0x80) 360 peer->valid--; 361 peer->reach <<= 1; 362 if (peer->reach == 0) { 363 if (oreach != 0) { 364 report_event(EVNT_UNREACH, peer); 365 peer->timereachable = current_time; 366 peer_clear(peer); 367 } 368 } else { 369 if ((oreach & 0x03) == 0) { 370 clock_filter(peer, 0., 0., MAXDISPERSE); 371 clock_select(); 372 } 373 if (peer->valid <= 2) { 374 hpoll--; 375 } else if (peer->valid > NTP_SHIFT - 2) 376 hpoll++; 377 if (peer->flags & FLAG_BURST) 378 peer->burst = NSTAGE; 379 } 380 next = current_time; 381 } 382 get_systime(&peer->xmt); 383 if (refclock_conf[clktype]->clock_poll != noentry) 384 (refclock_conf[clktype]->clock_poll)(unit, peer); 385 peer->outdate = next; 386 poll_update(peer, hpoll); 387 if (peer->burst > 0) 388 peer->burst--; 389 poll_update(peer, hpoll); 390 } 391 392 393 /* 394 * Compare two doubles - used with qsort() 395 */ 396 #ifdef QSORT_USES_VOID_P 397 static int 398 refclock_cmpl_fp( 399 const void *p1, 400 const void *p2 401 ) 402 { 403 const double *dp1 = (const double *)p1; 404 const double *dp2 = (const double *)p2; 405 406 if (*dp1 < *dp2) 407 return (-1); 408 if (*dp1 > *dp2) 409 return (1); 410 return (0); 411 } 412 #else 413 static int 414 refclock_cmpl_fp( 415 const double *dp1, 416 const double *dp2 417 ) 418 { 419 if (*dp1 < *dp2) 420 return (-1); 421 if (*dp1 > *dp2) 422 return (1); 423 return (0); 424 } 425 #endif /* QSORT_USES_VOID_P */ 426 427 428 /* 429 * refclock_process_offset - update median filter 430 * 431 * This routine uses the given offset and timestamps to construct a new entry in the median filter circular buffer. Samples that overflow the filter are quietly discarded. 432 */ 433 void 434 refclock_process_offset( 435 struct refclockproc *pp, 436 l_fp offset, 437 l_fp lastrec, 438 double fudge 439 ) 440 { 441 double doffset; 442 443 pp->lastref = offset; 444 pp->lastrec = lastrec; 445 pp->variance = 0; 446 L_SUB(&offset, &lastrec); 447 LFPTOD(&offset, doffset); 448 SAMPLE(doffset + fudge); 449 } 450 451 /* 452 * refclock_process - process a sample from the clock 453 * 454 * This routine converts the timecode in the form days, hours, minutes, 455 * seconds and milliseconds/microseconds to internal timestamp format, 456 * then constructs a new entry in the median filter circular buffer. 457 * Return success (1) if the data are correct and consistent with the 458 * converntional calendar. 459 */ 460 int 461 refclock_process( 462 struct refclockproc *pp 463 ) 464 { 465 l_fp offset; 466 467 /* 468 * Compute the timecode timestamp from the days, hours, minutes, 469 * seconds and milliseconds/microseconds of the timecode. Use 470 * clocktime() for the aggregate seconds and the msec/usec for 471 * the fraction, when present. Note that this code relies on the 472 * filesystem time for the years and does not use the years of 473 * the timecode. 474 */ 475 if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT, 476 pp->lastrec.l_ui, &pp->yearstart, &offset.l_ui)) 477 return (0); 478 if (pp->usec) { 479 TVUTOTSF(pp->usec, offset.l_uf); 480 } else { 481 MSUTOTSF(pp->msec, offset.l_uf); 482 } 483 refclock_process_offset(pp, offset, pp->lastrec, 484 pp->fudgetime1); 485 return (1); 486 } 487 488 /* 489 * refclock_sample - process a pile of samples from the clock 490 * 491 * This routine implements a recursive median filter to suppress spikes 492 * in the data, as well as determine a performance statistic. It 493 * calculates the mean offset and mean-square variance. A time 494 * adjustment fudgetime1 can be added to the final offset to compensate 495 * for various systematic errors. The routine returns the number of 496 * samples processed, which could be 0. 497 */ 498 static int 499 refclock_sample( 500 struct refclockproc *pp 501 ) 502 { 503 int i, j, k, n; 504 double offset, disp; 505 double off[MAXSTAGE]; 506 507 /* 508 * Copy the raw offsets and sort into ascending order. Don't do 509 * anything if the buffer is empty. 510 */ 511 if (pp->codeproc == pp->coderecv) 512 return (0); 513 n = 0; 514 while (pp->codeproc != pp->coderecv) 515 off[n++] = pp->filter[pp->codeproc++ % MAXSTAGE]; 516 if (n > 1) 517 qsort((char *)off, n, sizeof(double), refclock_cmpl_fp); 518 519 /* 520 * Reject the furthest from the median of the samples until 521 * approximately 60 percent of the samples remain. 522 */ 523 i = 0; j = n; 524 k = n - (n * 2) / NSTAGE; 525 while ((j - i) > k) { 526 offset = off[(j + i) / 2]; 527 if (off[j - 1] - offset < offset - off[i]) 528 i++; /* reject low end */ 529 else 530 j--; /* reject high end */ 531 } 532 533 /* 534 * Determine the offset and variance. 535 */ 536 offset = disp = 0; 537 for (; i < j; i++) { 538 offset += off[i]; 539 disp += SQUARE(off[i]); 540 } 541 offset /= k; 542 pp->offset = offset; 543 pp->variance += disp / k - SQUARE(offset); 544 #ifdef DEBUG 545 if (debug) 546 printf( 547 "refclock_sample: n %d offset %.6f disp %.6f std %.6f\n", 548 n, pp->offset, pp->disp, SQRT(pp->variance)); 549 #endif 550 return (n); 551 } 552 553 554 /* 555 * refclock_receive - simulate the receive and packet procedures 556 * 557 * This routine simulates the NTP receive and packet procedures for a 558 * reference clock. This provides a mechanism in which the ordinary NTP 559 * filter, selection and combining algorithms can be used to suppress 560 * misbehaving radios and to mitigate between them when more than one is 561 * available for backup. 562 */ 563 void 564 refclock_receive( 565 struct peer *peer /* peer structure pointer */ 566 ) 567 { 568 struct refclockproc *pp; 569 570 #ifdef DEBUG 571 if (debug) 572 printf("refclock_receive: at %lu %s\n", 573 current_time, ntoa(&peer->srcadr)); 574 #endif 575 576 /* 577 * Do a little sanity dance and update the peer structure. Groom 578 * the median filter samples and give the data to the clock 579 * filter. 580 */ 581 peer->received++; 582 pp = peer->procptr; 583 peer->processed++; 584 peer->timereceived = current_time; 585 peer->leap = pp->leap; 586 if (peer->leap == LEAP_NOTINSYNC) { 587 refclock_report(peer, CEVNT_FAULT); 588 return; 589 } 590 if (peer->reach == 0) 591 report_event(EVNT_REACH, peer); 592 peer->reach |= 1; 593 peer->reftime = peer->org = pp->lastrec; 594 peer->rootdispersion = pp->disp + SQRT(pp->variance); 595 get_systime(&peer->rec); 596 if (!refclock_sample(pp)) 597 return; 598 clock_filter(peer, pp->offset, 0., 0.); 599 clock_select(); 600 record_peer_stats(&peer->srcadr, ctlpeerstatus(peer), 601 peer->offset, peer->delay, CLOCK_PHI * (current_time - 602 peer->epoch), SQRT(peer->variance)); 603 if (pps_control && pp->sloppyclockflag & CLK_FLAG1) 604 pp->fudgetime1 -= pp->offset * FUDGEFAC; 605 } 606 607 /* 608 * refclock_gtlin - groom next input line and extract timestamp 609 * 610 * This routine processes the timecode received from the clock and 611 * removes the parity bit and control characters. If a timestamp is 612 * present in the timecode, as produced by the tty_clk STREAMS module, 613 * it returns that as the timestamp; otherwise, it returns the buffer 614 * timestamp. The routine return code is the number of characters in 615 * the line. 616 */ 617 int 618 refclock_gtlin( 619 struct recvbuf *rbufp, /* receive buffer pointer */ 620 char *lineptr, /* current line pointer */ 621 int bmax, /* remaining characters in line */ 622 l_fp *tsptr /* pointer to timestamp returned */ 623 ) 624 { 625 char *dpt, *dpend, *dp; 626 int i; 627 l_fp trtmp, tstmp; 628 char c; 629 #ifdef TIOCDCDTIMESTAMP 630 struct timeval dcd_time; 631 #endif /* TIOCDCDTIMESTAMP */ 632 #ifdef HAVE_PPSAPI 633 pps_info_t pi; 634 struct timespec timeout, *tsp; 635 double a; 636 #endif /* HAVE_PPSAPI */ 637 638 /* 639 * Check for the presence of a timestamp left by the tty_clock 640 * module and, if present, use that instead of the buffer 641 * timestamp captured by the I/O routines. We recognize a 642 * timestamp by noting its value is earlier than the buffer 643 * timestamp, but not more than one second earlier. 644 */ 645 dpt = (char *)&rbufp->recv_space; 646 dpend = dpt + rbufp->recv_length; 647 trtmp = rbufp->recv_time; 648 649 #ifdef HAVE_PPSAPI 650 timeout.tv_sec = 0; 651 timeout.tv_nsec = 0; 652 if ((rbufp->fd == fdpps) && 653 (time_pps_fetch(fdpps, PPS_TSFMT_TSPEC, &pi, &timeout) >= 0)) { 654 if(pps_assert) 655 tsp = &pi.assert_timestamp; 656 else 657 tsp = &pi.clear_timestamp; 658 a = tsp->tv_nsec; 659 a /= 1e9; 660 tstmp.l_uf = a * 4294967296.0; 661 tstmp.l_ui = tsp->tv_sec; 662 tstmp.l_ui += JAN_1970; 663 L_SUB(&trtmp, &tstmp); 664 if (trtmp.l_ui == 0) { 665 #ifdef DEBUG 666 if (debug > 1) { 667 printf( 668 "refclock_gtlin: fd %d time_pps_fetch %s", 669 fdpps, lfptoa(&tstmp, 6)); 670 printf(" sigio %s\n", lfptoa(&trtmp, 6)); 671 } 672 #endif 673 trtmp = tstmp; 674 goto gotit; 675 } else 676 trtmp = rbufp->recv_time; 677 } 678 #endif /* HAVE_PPSAPI */ 679 #ifdef TIOCDCDTIMESTAMP 680 if(ioctl(rbufp->fd, TIOCDCDTIMESTAMP, &dcd_time) != -1) { 681 TVTOTS(&dcd_time, &tstmp); 682 tstmp.l_ui += JAN_1970; 683 L_SUB(&trtmp, &tstmp); 684 if (trtmp.l_ui == 0) { 685 #ifdef DEBUG 686 if (debug > 1) { 687 printf( 688 "refclock_gtlin: fd %d DCDTIMESTAMP %s", 689 rbufp->fd, lfptoa(&tstmp, 6)); 690 printf(" sigio %s\n", lfptoa(&trtmp, 6)); 691 } 692 #endif 693 trtmp = tstmp; 694 goto gotit; 695 } else 696 trtmp = rbufp->recv_time; 697 } 698 else 699 /* XXX fallback to old method if kernel refuses TIOCDCDTIMESTAMP */ 700 #endif /* TIOCDCDTIMESTAMP */ 701 if (dpend >= dpt + 8) { 702 if (buftvtots(dpend - 8, &tstmp)) { 703 L_SUB(&trtmp, &tstmp); 704 if (trtmp.l_ui == 0) { 705 #ifdef DEBUG 706 if (debug > 1) { 707 printf( 708 "refclock_gtlin: fd %d ldisc %s", 709 rbufp->fd, lfptoa(&trtmp, 6)); 710 get_systime(&trtmp); 711 L_SUB(&trtmp, &tstmp); 712 printf(" sigio %s\n", lfptoa(&trtmp, 6)); 713 } 714 #endif 715 dpend -= 8; 716 trtmp = tstmp; 717 } else 718 trtmp = rbufp->recv_time; 719 } 720 } 721 722 #if defined(HAVE_PPSAPI) || defined(TIOCDCDTIMESTAMP) 723 gotit: 724 #endif 725 /* 726 * Edit timecode to remove control chars. Don't monkey with the 727 * line buffer if the input buffer contains no ASCII printing 728 * characters. 729 */ 730 if (dpend - dpt > bmax - 1) 731 dpend = dpt + bmax - 1; 732 for (dp = lineptr; dpt < dpend; dpt++) { 733 c = *dpt & 0x7f; 734 if (c >= ' ') 735 *dp++ = c; 736 } 737 i = dp - lineptr; 738 if (i > 0) 739 *dp = '\0'; 740 #ifdef DEBUG 741 if (debug > 1 && i > 0) 742 printf("refclock_gtlin: fd %d time %s timecode %d %s\n", 743 rbufp->fd, ulfptoa(&trtmp, 6), i, lineptr); 744 #endif 745 *tsptr = trtmp; 746 return (i); 747 } 748 749 /* 750 * The following code does not apply to WINNT & VMS ... 751 */ 752 #if !defined SYS_VXWORKS && !defined SYS_WINNT 753 #if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS) 754 755 /* 756 * refclock_open - open serial port for reference clock 757 * 758 * This routine opens a serial port for I/O and sets default options. It 759 * returns the file descriptor if success and zero if failure. 760 */ 761 int 762 refclock_open( 763 char *dev, /* device name pointer */ 764 int speed, /* serial port speed (code) */ 765 int lflags /* line discipline flags */ 766 ) 767 { 768 int fd, i; 769 int flags; 770 #ifdef HAVE_TERMIOS 771 struct termios ttyb, *ttyp; 772 #endif /* HAVE_TERMIOS */ 773 #ifdef HAVE_SYSV_TTYS 774 struct termio ttyb, *ttyp; 775 #endif /* HAVE_SYSV_TTYS */ 776 #ifdef HAVE_BSD_TTYS 777 struct sgttyb ttyb, *ttyp; 778 #endif /* HAVE_BSD_TTYS */ 779 #ifdef TIOCMGET 780 u_long ltemp; 781 #endif /* TIOCMGET */ 782 783 /* 784 * Open serial port and set default options 785 */ 786 flags = lflags; 787 if (strcmp(dev, pps_device) == 0) 788 flags |= LDISC_PPS; 789 #ifdef O_NONBLOCK 790 fd = open(dev, O_RDWR | O_NONBLOCK, 0777); 791 #else 792 fd = open(dev, O_RDWR, 0777); 793 #endif /* O_NONBLOCK */ 794 if (fd == -1) { 795 msyslog(LOG_ERR, "refclock_open: %s: %m", dev); 796 return (0); 797 } 798 799 /* 800 * The following sections initialize the serial line port in 801 * canonical (line-oriented) mode and set the specified line 802 * speed, 8 bits and no parity. The modem control, break, erase 803 * and kill functions are normally disabled. There is a 804 * different section for each terminal interface, as selected at 805 * compile time. 806 */ 807 ttyp = &ttyb; 808 809 #ifdef HAVE_TERMIOS 810 /* 811 * POSIX serial line parameters (termios interface) 812 */ 813 if (tcgetattr(fd, ttyp) < 0) { 814 msyslog(LOG_ERR, 815 "refclock_open: fd %d tcgetattr: %m", fd); 816 return (0); 817 } 818 819 /* 820 * Set canonical mode and local connection; set specified speed, 821 * 8 bits and no parity; map CR to NL; ignore break. 822 */ 823 ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL; 824 ttyp->c_oflag = 0; 825 ttyp->c_cflag = CS8 | CLOCAL | CREAD; 826 (void)cfsetispeed(&ttyb, (u_int)speed); 827 (void)cfsetospeed(&ttyb, (u_int)speed); 828 ttyp->c_lflag = ICANON; 829 for (i = 0; i < NCCS; ++i) 830 { 831 ttyp->c_cc[i] = '\0'; 832 } 833 834 /* 835 * Some special cases 836 */ 837 if (flags & LDISC_RAW) { 838 ttyp->c_iflag = 0; 839 ttyp->c_lflag = 0; 840 ttyp->c_cc[VMIN] = 1; 841 } 842 #if defined(TIOCMGET) && !defined(SCO5_CLOCK) 843 /* 844 * If we have modem control, check to see if modem leads are 845 * active; if so, set remote connection. This is necessary for 846 * the kernel pps mods to work. 847 */ 848 ltemp = 0; 849 if (ioctl(fd, TIOCMGET, (char *)<emp) < 0) 850 msyslog(LOG_ERR, 851 "refclock_open: fd %d TIOCMGET failed: %m", fd); 852 #ifdef DEBUG 853 if (debug) 854 printf("refclock_open: fd %d modem status 0x%lx\n", 855 fd, ltemp); 856 #endif 857 if (ltemp & TIOCM_DSR) 858 ttyp->c_cflag &= ~CLOCAL; 859 #endif /* TIOCMGET */ 860 if (tcsetattr(fd, TCSANOW, ttyp) < 0) { 861 msyslog(LOG_ERR, 862 "refclock_open: fd %d TCSANOW failed: %m", fd); 863 return (0); 864 } 865 if (tcflush(fd, TCIOFLUSH) < 0) { 866 msyslog(LOG_ERR, 867 "refclock_open: fd %d TCIOFLUSH failed: %m", fd); 868 return (0); 869 } 870 #endif /* HAVE_TERMIOS */ 871 872 #ifdef HAVE_SYSV_TTYS 873 874 /* 875 * System V serial line parameters (termio interface) 876 * 877 */ 878 if (ioctl(fd, TCGETA, ttyp) < 0) { 879 msyslog(LOG_ERR, 880 "refclock_open: fd %d TCGETA failed: %m", fd); 881 return (0); 882 } 883 884 /* 885 * Set canonical mode and local connection; set specified speed, 886 * 8 bits and no parity; map CR to NL; ignore break. 887 */ 888 ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL; 889 ttyp->c_oflag = 0; 890 ttyp->c_cflag = speed | CS8 | CLOCAL | CREAD; 891 ttyp->c_lflag = ICANON; 892 ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\0'; 893 894 /* 895 * Some special cases 896 */ 897 if (flags & LDISC_RAW) { 898 ttyp->c_iflag = 0; 899 ttyp->c_lflag = 0; 900 } 901 #ifdef TIOCMGET 902 /* 903 * If we have modem control, check to see if modem leads are 904 * active; if so, set remote connection. This is necessary for 905 * the kernel pps mods to work. 906 */ 907 ltemp = 0; 908 if (ioctl(fd, TIOCMGET, (char *)<emp) < 0) 909 msyslog(LOG_ERR, 910 "refclock_open: fd %d TIOCMGET failed: %m", fd); 911 #ifdef DEBUG 912 if (debug) 913 printf("refclock_open: fd %d modem status %lx\n", 914 fd, ltemp); 915 #endif 916 if (ltemp & TIOCM_DSR) 917 ttyp->c_cflag &= ~CLOCAL; 918 #endif /* TIOCMGET */ 919 if (ioctl(fd, TCSETA, ttyp) < 0) { 920 msyslog(LOG_ERR, 921 "refclock_open: fd %d TCSETA failed: %m", fd); 922 return (0); 923 } 924 #endif /* HAVE_SYSV_TTYS */ 925 926 #ifdef HAVE_BSD_TTYS 927 928 /* 929 * 4.3bsd serial line parameters (sgttyb interface) 930 */ 931 if (ioctl(fd, TIOCGETP, (char *)ttyp) < 0) { 932 msyslog(LOG_ERR, 933 "refclock_open: fd %d TIOCGETP %m", fd); 934 return (0); 935 } 936 ttyp->sg_ispeed = ttyp->sg_ospeed = speed; 937 ttyp->sg_flags = EVENP | ODDP | CRMOD; 938 if (ioctl(fd, TIOCSETP, (char *)ttyp) < 0) { 939 msyslog(LOG_ERR, 940 "refclock_open: TIOCSETP failed: %m"); 941 return (0); 942 } 943 #endif /* HAVE_BSD_TTYS */ 944 if (!refclock_ioctl(fd, flags)) { 945 (void)close(fd); 946 msyslog(LOG_ERR, 947 "refclock_open: fd %d ioctl failed: %m", fd); 948 return (0); 949 } 950 return (fd); 951 } 952 #endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */ 953 #endif /* SYS_VXWORKS SYS_WINNT */ 954 955 /* 956 * refclock_ioctl - set serial port control functions 957 * 958 * This routine attempts to hide the internal, system-specific details 959 * of serial ports. It can handle POSIX (termios), SYSV (termio) and BSD 960 * (sgtty) interfaces with varying degrees of success. The routine sets 961 * up optional features such as tty_clk, ppsclock and ppsapi, as well as 962 * their many other variants. The routine returns 1 if success and 0 if 963 * failure. 964 */ 965 int 966 refclock_ioctl( 967 int fd, /* file descriptor */ 968 int flags /* line discipline flags */ 969 ) 970 { 971 /* simply return 1 if no UNIX line discipline is supported */ 972 #if !defined SYS_VXWORKS && !defined SYS_WINNT 973 #if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS) 974 975 #ifdef TTYCLK 976 #ifdef HAVE_TERMIOS 977 struct termios ttyb, *ttyp; 978 #endif /* HAVE_TERMIOS */ 979 #ifdef HAVE_SYSV_TTYS 980 struct termio ttyb, *ttyp; 981 #endif /* HAVE_SYSV_TTYS */ 982 #ifdef HAVE_BSD_TTYS 983 struct sgttyb ttyb, *ttyp; 984 #endif /* HAVE_BSD_TTYS */ 985 #endif /* TTYCLK */ 986 987 #ifdef DEBUG 988 if (debug) 989 printf("refclock_ioctl: fd %d flags 0x%x\n", fd, flags); 990 #endif 991 992 /* 993 * The following sections select optional features, such as 994 * modem control, PPS capture and so forth. Some require 995 * specific operating system support in the form of STREAMS 996 * modules, which can be loaded and unloaded at run time without 997 * rebooting the kernel. The STREAMS modules require System 998 * V STREAMS support. The checking frenzy is attenuated here, 999 * since the device is already open. 1000 * 1001 * Note that the tty_clk and ppsclock modules are optional; if 1002 * configured and unavailable, the dang thing still works, but 1003 * the accuracy improvement using them will not be available. 1004 * The only known implmentations of these moldules are specific 1005 * to SunOS 4.x. Use the ppsclock module ONLY with Sun baseboard 1006 * ttya or ttyb. Using it with the SPIF multipexor crashes the 1007 * kernel. 1008 * 1009 * The preferred way to capture PPS timestamps is using the 1010 * ppsapi interface, which is machine independent. The SunOS 4.x 1011 * and Digital Unix 4.x interfaces use STREAMS modules and 1012 * support both the ppsapi specification and ppsclock 1013 * functionality, but other systems may vary widely. 1014 */ 1015 if (flags == 0) 1016 return (1); 1017 #if !(defined(HAVE_TERMIOS) || defined(HAVE_BSD_TTYS)) 1018 if (flags & (LDISC_CLK | LDISC_PPS | LDISC_ACTS)) { 1019 msyslog(LOG_ERR, 1020 "refclock_ioctl: unsupported terminal interface"); 1021 return (0); 1022 } 1023 #endif /* HAVE_TERMIOS HAVE_BSD_TTYS */ 1024 #ifdef TTYCLK 1025 ttyp = &ttyb; 1026 #endif /* TTYCLK */ 1027 1028 /* 1029 * The following features may or may not require System V 1030 * STREAMS support, depending on the particular implementation. 1031 */ 1032 #if defined(TTYCLK) 1033 /* 1034 * The TTYCLK option provides timestamping at the driver level. 1035 * It requires the tty_clk streams module and System V STREAMS 1036 * support. If not available, don't complain. 1037 */ 1038 if (flags & (LDISC_CLK | LDISC_CLKPPS | LDISC_ACTS)) { 1039 int rval = 0; 1040 1041 if (ioctl(fd, I_PUSH, "clk") < 0) { 1042 msyslog(LOG_NOTICE, 1043 "refclock_ioctl: I_PUSH clk failed: %m"); 1044 } else { 1045 char *str; 1046 1047 if (flags & LDISC_CLKPPS) 1048 str = "\377"; 1049 else if (flags & LDISC_ACTS) 1050 str = "*"; 1051 else 1052 str = "\n"; 1053 #ifdef CLK_SETSTR 1054 if ((rval = ioctl(fd, CLK_SETSTR, str)) < 0) 1055 msyslog(LOG_ERR, 1056 "refclock_ioctl: CLK_SETSTR failed: %m"); 1057 if (debug) 1058 printf("refclock_ioctl: fd %d CLK_SETSTR %d str %s\n", 1059 fd, rval, str); 1060 #endif 1061 } 1062 } 1063 #endif /* TTYCLK */ 1064 1065 #if defined(PPS) && !defined(HAVE_PPSAPI) 1066 /* 1067 * The PPS option provides timestamping at the driver level. 1068 * It uses a 1-pps signal and level converter (gadget box) and 1069 * requires the ppsclock streams module and System V STREAMS 1070 * support. This option has been superseded by the ppsapi 1071 * option and may be withdrawn in future. 1072 */ 1073 if (flags & LDISC_PPS) { 1074 int rval = 0; 1075 #ifdef HAVE_TIOCSPPS /* Solaris */ 1076 int one = 1; 1077 #endif /* HAVE_TIOCSPPS */ 1078 1079 if (fdpps > 0) { 1080 msyslog(LOG_ERR, 1081 "refclock_ioctl: PPS already configured"); 1082 return (0); 1083 } 1084 #ifdef HAVE_TIOCSPPS /* Solaris */ 1085 if (ioctl(fd, TIOCSPPS, &one) < 0) { 1086 msyslog(LOG_NOTICE, 1087 "refclock_ioctl: TIOCSPPS failed: %m"); 1088 return (0); 1089 } 1090 if (debug) 1091 printf("refclock_ioctl: fd %d TIOCSPPS %d\n", 1092 fd, rval); 1093 #else 1094 if (ioctl(fd, I_PUSH, "ppsclock") < 0) { 1095 msyslog(LOG_NOTICE, 1096 "refclock_ioctl: I_PUSH ppsclock failed: %m"); 1097 return (0); 1098 } 1099 if (debug) 1100 printf("refclock_ioctl: fd %d ppsclock %d\n", 1101 fd, rval); 1102 #endif /* not HAVE_TIOCSPPS */ 1103 fdpps = fd; 1104 } 1105 #endif /* PPS HAVE_PPSAPI */ 1106 1107 #ifdef HAVE_PPSAPI 1108 /* 1109 * The PPSAPI option provides timestamping at the driver level. 1110 * It uses a 1-pps signal and level converter (gadget box) and 1111 * requires ppsapi compiled into the kernel on non STREAMS 1112 * systems. This is the preferred way to capture PPS timestamps 1113 * and is expected to become an IETF cross-platform standard. 1114 */ 1115 if (flags & (LDISC_PPS | LDISC_CLKPPS)) { 1116 pps_params_t pp; 1117 int mode, temp; 1118 pps_handle_t handle; 1119 1120 memset((char *)&pp, 0, sizeof(pp)); 1121 if (fdpps > 0) { 1122 msyslog(LOG_ERR, 1123 "refclock_ioctl: ppsapi already configured"); 1124 return (0); 1125 } 1126 if (time_pps_create(fd, &handle) < 0) { 1127 msyslog(LOG_ERR, 1128 "refclock_ioctl: time_pps_create failed: %m"); 1129 return (0); 1130 } 1131 if (time_pps_getcap(handle, &mode) < 0) { 1132 msyslog(LOG_ERR, 1133 "refclock_ioctl: time_pps_getcap failed: %m"); 1134 return (0); 1135 } 1136 pp.mode = mode & PPS_CAPTUREBOTH; 1137 if (time_pps_setparams(handle, &pp) < 0) { 1138 msyslog(LOG_ERR, 1139 "refclock_ioctl: time_pps_setparams failed: %m"); 1140 return (0); 1141 } 1142 if (!pps_hardpps) 1143 temp = 0; 1144 else if (pps_assert) 1145 temp = mode & PPS_CAPTUREASSERT; 1146 else 1147 temp = mode & PPS_CAPTURECLEAR; 1148 if (time_pps_kcbind(handle, PPS_KC_HARDPPS, temp, 1149 PPS_TSFMT_TSPEC) < 0) { 1150 msyslog(LOG_ERR, 1151 "refclock_ioctl: time_pps_kcbind failed: %m"); 1152 return (0); 1153 } 1154 (void)time_pps_getparams(handle, &pp); 1155 fdpps = (int)handle; 1156 if (debug) 1157 printf( 1158 "refclock_ioctl: fd %d ppsapi vers %d mode 0x%x cap 0x%x\n", 1159 fdpps, pp.api_version, pp.mode, mode); 1160 } 1161 #endif /* HAVE_PPSAPI */ 1162 #endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */ 1163 #endif /* SYS_VXWORKS SYS_WINNT */ 1164 return (1); 1165 } 1166 1167 /* 1168 * refclock_control - set and/or return clock values 1169 * 1170 * This routine is used mainly for debugging. It returns designated 1171 * values from the interface structure that can be displayed using 1172 * ntpdc and the clockstat command. It can also be used to initialize 1173 * configuration variables, such as fudgetimes, fudgevalues, reference 1174 * ID and stratum. 1175 */ 1176 void 1177 refclock_control( 1178 struct sockaddr_in *srcadr, 1179 struct refclockstat *in, 1180 struct refclockstat *out 1181 ) 1182 { 1183 struct peer *peer; 1184 struct refclockproc *pp; 1185 u_char clktype; 1186 int unit; 1187 1188 /* 1189 * Check for valid address and running peer 1190 */ 1191 if (!ISREFCLOCKADR(srcadr)) 1192 return; 1193 clktype = (u_char)REFCLOCKTYPE(srcadr); 1194 unit = REFCLOCKUNIT(srcadr); 1195 if (clktype >= num_refclock_conf || unit >= MAXUNIT) 1196 return; 1197 if (!(peer = typeunit[clktype][unit])) 1198 return; 1199 pp = peer->procptr; 1200 1201 /* 1202 * Initialize requested data 1203 */ 1204 if (in != 0) { 1205 if (in->haveflags & CLK_HAVETIME1) 1206 pp->fudgetime1 = in->fudgetime1; 1207 if (in->haveflags & CLK_HAVETIME2) 1208 pp->fudgetime2 = in->fudgetime2; 1209 if (in->haveflags & CLK_HAVEVAL1) 1210 peer->stratum = (u_char) in->fudgeval1; 1211 if (in->haveflags & CLK_HAVEVAL2) 1212 pp->refid = in->fudgeval2; 1213 if (peer->stratum <= 1) 1214 peer->refid = pp->refid; 1215 else 1216 peer->refid = peer->srcadr.sin_addr.s_addr; 1217 if (in->haveflags & CLK_HAVEFLAG1) { 1218 pp->sloppyclockflag &= ~CLK_FLAG1; 1219 pp->sloppyclockflag |= in->flags & CLK_FLAG1; 1220 } 1221 if (in->haveflags & CLK_HAVEFLAG2) { 1222 pp->sloppyclockflag &= ~CLK_FLAG2; 1223 pp->sloppyclockflag |= in->flags & CLK_FLAG2; 1224 } 1225 if (in->haveflags & CLK_HAVEFLAG3) { 1226 pp->sloppyclockflag &= ~CLK_FLAG3; 1227 pp->sloppyclockflag |= in->flags & CLK_FLAG3; 1228 } 1229 if (in->haveflags & CLK_HAVEFLAG4) { 1230 pp->sloppyclockflag &= ~CLK_FLAG4; 1231 pp->sloppyclockflag |= in->flags & CLK_FLAG4; 1232 } 1233 } 1234 1235 /* 1236 * Readback requested data 1237 */ 1238 if (out != 0) { 1239 out->haveflags = CLK_HAVETIME1 | CLK_HAVEVAL1 | 1240 CLK_HAVEVAL2 | CLK_HAVEFLAG4; 1241 out->fudgetime1 = pp->fudgetime1; 1242 out->fudgetime2 = pp->fudgetime2; 1243 out->fudgeval1 = peer->stratum; 1244 out->fudgeval2 = pp->refid; 1245 out->flags = (u_char) pp->sloppyclockflag; 1246 1247 out->timereset = current_time - pp->timestarted; 1248 out->polls = pp->polls; 1249 out->noresponse = pp->noreply; 1250 out->badformat = pp->badformat; 1251 out->baddata = pp->baddata; 1252 1253 out->lastevent = pp->lastevent; 1254 out->currentstatus = pp->currentstatus; 1255 out->type = pp->type; 1256 out->clockdesc = pp->clockdesc; 1257 out->lencode = pp->lencode; 1258 out->p_lastcode = pp->a_lastcode; 1259 } 1260 1261 /* 1262 * Give the stuff to the clock 1263 */ 1264 if (refclock_conf[clktype]->clock_control != noentry) 1265 (refclock_conf[clktype]->clock_control)(unit, in, out, peer); 1266 } 1267 1268 1269 /* 1270 * refclock_buginfo - return debugging info 1271 * 1272 * This routine is used mainly for debugging. It returns designated 1273 * values from the interface structure that can be displayed using 1274 * ntpdc and the clkbug command. 1275 */ 1276 void 1277 refclock_buginfo( 1278 struct sockaddr_in *srcadr, /* clock address */ 1279 struct refclockbug *bug /* output structure */ 1280 ) 1281 { 1282 struct peer *peer; 1283 struct refclockproc *pp; 1284 u_char clktype; 1285 int unit; 1286 int i; 1287 1288 /* 1289 * Check for valid address and peer structure 1290 */ 1291 if (!ISREFCLOCKADR(srcadr)) 1292 return; 1293 clktype = (u_char) REFCLOCKTYPE(srcadr); 1294 unit = REFCLOCKUNIT(srcadr); 1295 if (clktype >= num_refclock_conf || unit >= MAXUNIT) 1296 return; 1297 if (!(peer = typeunit[clktype][unit])) 1298 return; 1299 pp = peer->procptr; 1300 1301 /* 1302 * Copy structure values 1303 */ 1304 bug->nvalues = 8; 1305 bug->svalues = 0x0000003f; 1306 bug->values[0] = pp->year; 1307 bug->values[1] = pp->day; 1308 bug->values[2] = pp->hour; 1309 bug->values[3] = pp->minute; 1310 bug->values[4] = pp->second; 1311 bug->values[5] = pp->msec; 1312 bug->values[6] = pp->yearstart; 1313 bug->values[7] = pp->coderecv; 1314 bug->stimes = 0xfffffffc; 1315 bug->times[0] = pp->lastref; 1316 bug->times[1] = pp->lastrec; 1317 for (i = 2; i < (int)bug->ntimes; i++) 1318 DTOLFP(pp->filter[i - 2], &bug->times[i]); 1319 1320 /* 1321 * Give the stuff to the clock 1322 */ 1323 if (refclock_conf[clktype]->clock_buginfo != noentry) 1324 (refclock_conf[clktype]->clock_buginfo)(unit, bug, peer); 1325 } 1326 1327 #endif /* REFCLOCK */ 1328