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