ntp_refclock.c revision 182007
1112158Sdas/* 2112158Sdas * ntp_refclock - processing support for reference clocks 3112158Sdas */ 4112158Sdas#ifdef HAVE_CONFIG_H 5112158Sdas# include <config.h> 6112158Sdas#endif 7112158Sdas 8112158Sdas#include "ntpd.h" 9112158Sdas#include "ntp_io.h" 10112158Sdas#include "ntp_unixtime.h" 11112158Sdas#include "ntp_tty.h" 12112158Sdas#include "ntp_refclock.h" 13112158Sdas#include "ntp_stdlib.h" 14112158Sdas 15112158Sdas#include <stdio.h> 16112158Sdas 17112158Sdas#ifdef HAVE_SYS_IOCTL_H 18112158Sdas# include <sys/ioctl.h> 19112158Sdas#endif /* HAVE_SYS_IOCTL_H */ 20112158Sdas 21112158Sdas#ifdef REFCLOCK 22112158Sdas 23112158Sdas#ifdef TTYCLK 24112158Sdas# ifdef HAVE_SYS_CLKDEFS_H 25112158Sdas# include <sys/clkdefs.h> 26112158Sdas# include <stropts.h> 27112158Sdas# endif 28112158Sdas# ifdef HAVE_SYS_SIO_H 29165743Sdas# include <sys/sio.h> 30165743Sdas# endif 31112158Sdas#endif /* TTYCLK */ 32112158Sdas 33112158Sdas#ifdef KERNEL_PLL 34112158Sdas#include "ntp_syscall.h" 35112158Sdas#endif /* KERNEL_PLL */ 36112158Sdas 37187808Sdas/* 38112158Sdas * Reference clock support is provided here by maintaining the fiction 39187808Sdas * that the clock is actually a peer. As no packets are exchanged with a 40112158Sdas * reference clock, however, we replace the transmit, receive and packet 41112158Sdas * procedures with separate code to simulate them. Routines 42112158Sdas * refclock_transmit() and refclock_receive() maintain the peer 43112158Sdas * variables in a state analogous to an actual peer and pass reference 44112158Sdas * clock data on through the filters. Routines refclock_peer() and 45112158Sdas * refclock_unpeer() are called to initialize and terminate reference 46112158Sdas * clock associations. A set of utility routines is included to open 47112158Sdas * serial devices, process sample data, edit input lines to extract 48112158Sdas * embedded timestamps and to peform various debugging functions. 49112158Sdas * 50112158Sdas * The main interface used by these routines is the refclockproc 51112158Sdas * structure, which contains for most drivers the decimal equivalants of 52112158Sdas * the year, day, month, hour, second and millisecond/microsecond 53112158Sdas * decoded from the ASCII timecode. Additional information includes the 54112158Sdas * receive timestamp, exception report, statistics tallies, etc. In 55112158Sdas * addition, there may be a driver-specific unit structure used for 56112158Sdas * local control of the device. 57112158Sdas * 58112158Sdas * The support routines are passed a pointer to the peer structure, 59112158Sdas * which is used for all peer-specific processing and contains a pointer 60112158Sdas * to the refclockproc structure, which in turn containes a pointer to 61112158Sdas * the unit structure, if used. The peer structure is identified by an 62112158Sdas * interface address in the dotted quad form 127.127.t.u (for now only 63187808Sdas * IPv4 addresses are used, so we need to be sure the address is it), 64112158Sdas * where t is the clock type and u the unit. Some legacy drivers derive 65112158Sdas * the refclockproc structure pointer from the table 66187808Sdas * typeunit[type][unit]. This interface is strongly discouraged and may 67112158Sdas * be abandoned in future. 68112158Sdas */ 69112158Sdas#define MAXUNIT 4 /* max units */ 70112158Sdas#define FUDGEFAC .1 /* fudge correction factor */ 71112158Sdas#define LF 0x0a /* ASCII LF */ 72112158Sdas 73112158Sdas#ifdef PPS 74112158Sdasint fdpps; /* ppsclock legacy */ 75112158Sdas#endif /* PPS */ 76112158Sdasint cal_enable; /* enable refclock calibrate */ 77112158Sdas 78112158Sdas/* 79112158Sdas * Type/unit peer index. Used to find the peer structure for control and 80219557Sdas * debugging. When all clock drivers have been converted to new style, 81112158Sdas * this dissapears. 82112158Sdas */ 83219557Sdasstatic struct peer *typeunit[REFCLK_MAX + 1][MAXUNIT]; 84219557Sdas 85112158Sdas/* 86112158Sdas * Forward declarations 87112158Sdas */ 88219557Sdas#ifdef QSORT_USES_VOID_P 89112158Sdasstatic int refclock_cmpl_fp P((const void *, const void *)); 90219557Sdas#else 91112158Sdasstatic int refclock_cmpl_fp P((const double *, const double *)); 92112158Sdas#endif /* QSORT_USES_VOID_P */ 93112158Sdasstatic int refclock_sample P((struct refclockproc *)); 94219557Sdas 95112158Sdas 96219557Sdas/* 97112158Sdas * refclock_report - note the occurance of an event 98112158Sdas * 99112158Sdas * This routine presently just remembers the report and logs it, but 100219557Sdas * does nothing heroic for the trap handler. It tries to be a good 101112158Sdas * citizen and bothers the system log only if things change. 102112158Sdas */ 103219557Sdasvoid 104112158Sdasrefclock_report( 105112158Sdas struct peer *peer, 106219557Sdas int code 107112158Sdas ) 108112158Sdas{ 109112158Sdas struct refclockproc *pp; 110112158Sdas 111112158Sdas pp = peer->procptr; 112112158Sdas if (pp == NULL) 113112158Sdas return; 114112158Sdas 115112158Sdas switch (code) { 116112158Sdas case CEVNT_NOMINAL: 117112158Sdas break; 118112158Sdas 119112158Sdas case CEVNT_TIMEOUT: 120112158Sdas pp->noreply++; 121112158Sdas break; 122112158Sdas 123112158Sdas case CEVNT_BADREPLY: 124112158Sdas pp->badformat++; 125112158Sdas break; 126112158Sdas 127112158Sdas case CEVNT_FAULT: 128112158Sdas break; 129112158Sdas 130112158Sdas case CEVNT_PROP: 131112158Sdas break; 132112158Sdas 133112158Sdas case CEVNT_BADDATE: 134112158Sdas case CEVNT_BADTIME: 135112158Sdas pp->baddata++; 136112158Sdas break; 137112158Sdas 138112158Sdas default: 139112158Sdas /* shouldn't happen */ 140112158Sdas break; 141112158Sdas } 142112158Sdas 143112158Sdas if (pp->currentstatus != code) { 144112158Sdas pp->currentstatus = (u_char)code; 145112158Sdas 146112158Sdas /* RFC1305: copy only iff not CEVNT_NOMINAL */ 147112158Sdas if (code != CEVNT_NOMINAL) 148112158Sdas pp->lastevent = (u_char)code; 149112158Sdas 150112158Sdas if (code == CEVNT_FAULT) 151112158Sdas msyslog(LOG_ERR, 152112158Sdas "clock %s event '%s' (0x%02x)", 153112158Sdas refnumtoa(&peer->srcadr), 154112158Sdas ceventstr(code), code); 155112158Sdas else { 156112158Sdas NLOG(NLOG_CLOCKEVENT) 157112158Sdas msyslog(LOG_INFO, 158112158Sdas "clock %s event '%s' (0x%02x)", 159112158Sdas refnumtoa(&peer->srcadr), 160112158Sdas ceventstr(code), code); 161112158Sdas } 162112158Sdas 163112158Sdas /* RFC1305: post peer clock event */ 164112158Sdas report_event(EVNT_PEERCLOCK, peer); 165112158Sdas } 166112158Sdas} 167112158Sdas 168112158Sdas/* 169112158Sdas * init_refclock - initialize the reference clock drivers 170112158Sdas * 171112158Sdas * This routine calls each of the drivers in turn to initialize internal 172112158Sdas * variables, if necessary. Most drivers have nothing to say at this 173112158Sdas * point. 174112158Sdas */ 175112158Sdasvoid 176112158Sdasinit_refclock(void) 177112158Sdas{ 178112158Sdas int i, j; 179112158Sdas 180112158Sdas for (i = 0; i < (int)num_refclock_conf; i++) { 181112158Sdas if (refclock_conf[i]->clock_init != noentry) 182112158Sdas (refclock_conf[i]->clock_init)(); 183112158Sdas for (j = 0; j < MAXUNIT; j++) 184112158Sdas typeunit[i][j] = 0; 185112158Sdas } 186112158Sdas} 187112158Sdas 188112158Sdas 189112158Sdas/* 190112158Sdas * refclock_newpeer - initialize and start a reference clock 191112158Sdas * 192 * This routine allocates and initializes the interface structure which 193 * supports a reference clock in the form of an ordinary NTP peer. A 194 * driver-specific support routine completes the initialization, if 195 * used. Default peer variables which identify the clock and establish 196 * its reference ID and stratum are set here. It returns one if success 197 * and zero if the clock address is invalid or already running, 198 * insufficient resources are available or the driver declares a bum 199 * rap. 200 */ 201int 202refclock_newpeer( 203 struct peer *peer /* peer structure pointer */ 204 ) 205{ 206 struct refclockproc *pp; 207 u_char clktype; 208 int unit; 209 210 /* 211 * Check for valid clock address. If already running, shut it 212 * down first. 213 */ 214 if (peer->srcadr.ss_family != AF_INET) { 215 msyslog(LOG_ERR, 216 "refclock_newpeer: clock address %s invalid, address family not implemented for refclock", 217 stoa(&peer->srcadr)); 218 return (0); 219 } 220 if (!ISREFCLOCKADR(&peer->srcadr)) { 221 msyslog(LOG_ERR, 222 "refclock_newpeer: clock address %s invalid", 223 stoa(&peer->srcadr)); 224 return (0); 225 } 226 clktype = (u_char)REFCLOCKTYPE(&peer->srcadr); 227 unit = REFCLOCKUNIT(&peer->srcadr); 228 if (clktype >= num_refclock_conf || unit >= MAXUNIT || 229 refclock_conf[clktype]->clock_start == noentry) { 230 msyslog(LOG_ERR, 231 "refclock_newpeer: clock type %d invalid\n", 232 clktype); 233 return (0); 234 } 235 236 /* 237 * Allocate and initialize interface structure 238 */ 239 pp = (struct refclockproc *)emalloc(sizeof(struct refclockproc)); 240 if (pp == NULL) 241 return (0); 242 243 memset((char *)pp, 0, sizeof(struct refclockproc)); 244 typeunit[clktype][unit] = peer; 245 peer->procptr = pp; 246 247 /* 248 * Initialize structures 249 */ 250 peer->refclktype = clktype; 251 peer->refclkunit = (u_char)unit; 252 peer->flags |= FLAG_REFCLOCK | FLAG_FIXPOLL; 253 peer->leap = LEAP_NOTINSYNC; 254 peer->stratum = STRATUM_REFCLOCK; 255 peer->ppoll = peer->maxpoll; 256 pp->type = clktype; 257 pp->timestarted = current_time; 258 259 /* 260 * Set peer.pmode based on the hmode. For appearances only. 261 */ 262 switch (peer->hmode) { 263 case MODE_ACTIVE: 264 peer->pmode = MODE_PASSIVE; 265 break; 266 267 default: 268 peer->pmode = MODE_SERVER; 269 break; 270 } 271 272 /* 273 * Do driver dependent initialization. The above defaults 274 * can be wiggled, then finish up for consistency. 275 */ 276 if (!((refclock_conf[clktype]->clock_start)(unit, peer))) { 277 refclock_unpeer(peer); 278 return (0); 279 } 280 peer->refid = pp->refid; 281 return (1); 282} 283 284 285/* 286 * refclock_unpeer - shut down a clock 287 */ 288void 289refclock_unpeer( 290 struct peer *peer /* peer structure pointer */ 291 ) 292{ 293 u_char clktype; 294 int unit; 295 296 /* 297 * Wiggle the driver to release its resources, then give back 298 * the interface structure. 299 */ 300 if (!peer->procptr) 301 return; 302 303 clktype = peer->refclktype; 304 unit = peer->refclkunit; 305 if (refclock_conf[clktype]->clock_shutdown != noentry) 306 (refclock_conf[clktype]->clock_shutdown)(unit, peer); 307 free(peer->procptr); 308 peer->procptr = 0; 309} 310 311 312/* 313 * refclock_timer - called once per second for housekeeping. 314 */ 315void 316refclock_timer( 317 struct peer *peer /* peer structure pointer */ 318 ) 319{ 320 u_char clktype; 321 int unit; 322 323 clktype = peer->refclktype; 324 unit = peer->refclkunit; 325 if (refclock_conf[clktype]->clock_timer != noentry) 326 (refclock_conf[clktype]->clock_timer)(unit, peer); 327} 328 329 330/* 331 * refclock_transmit - simulate the transmit procedure 332 * 333 * This routine implements the NTP transmit procedure for a reference 334 * clock. This provides a mechanism to call the driver at the NTP poll 335 * interval, as well as provides a reachability mechanism to detect a 336 * broken radio or other madness. 337 */ 338void 339refclock_transmit( 340 struct peer *peer /* peer structure pointer */ 341 ) 342{ 343 u_char clktype; 344 int unit; 345 346 clktype = peer->refclktype; 347 unit = peer->refclkunit; 348 peer->sent++; 349 get_systime(&peer->xmt); 350 351 /* 352 * This is a ripoff of the peer transmit routine, but 353 * specialized for reference clocks. We do a little less 354 * protocol here and call the driver-specific transmit routine. 355 */ 356 if (peer->burst == 0) { 357 u_char oreach; 358#ifdef DEBUG 359 if (debug) 360 printf("refclock_transmit: at %ld %s\n", 361 current_time, stoa(&(peer->srcadr))); 362#endif 363 364 /* 365 * Update reachability and poll variables like the 366 * network code. 367 */ 368 oreach = peer->reach; 369 peer->reach <<= 1; 370 peer->outdate = current_time; 371 if (!peer->reach) { 372 if (oreach) { 373 report_event(EVNT_UNREACH, peer); 374 peer->timereachable = current_time; 375 } 376 } else { 377 if (!(oreach & 0x07)) { 378 clock_filter(peer, 0., 0., MAXDISPERSE); 379 clock_select(); 380 } 381 if (peer->flags & FLAG_BURST) 382 peer->burst = NSTAGE; 383 } 384 } else { 385 peer->burst--; 386 } 387 if (refclock_conf[clktype]->clock_poll != noentry) 388 (refclock_conf[clktype]->clock_poll)(unit, peer); 389 poll_update(peer, peer->hpoll); 390} 391 392 393/* 394 * Compare two doubles - used with qsort() 395 */ 396#ifdef QSORT_USES_VOID_P 397static int 398refclock_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 409 if (*dp1 > *dp2) 410 return (1); 411 412 return (0); 413} 414 415#else 416static int 417refclock_cmpl_fp( 418 const double *dp1, 419 const double *dp2 420 ) 421{ 422 if (*dp1 < *dp2) 423 return (-1); 424 425 if (*dp1 > *dp2) 426 return (1); 427 428 return (0); 429} 430#endif /* QSORT_USES_VOID_P */ 431 432 433/* 434 * refclock_process_offset - update median filter 435 * 436 * This routine uses the given offset and timestamps to construct a new 437 * entry in the median filter circular buffer. Samples that overflow the 438 * filter are quietly discarded. 439 */ 440void 441refclock_process_offset( 442 struct refclockproc *pp, /* refclock structure pointer */ 443 l_fp lasttim, /* last timecode timestamp */ 444 l_fp lastrec, /* last receive timestamp */ 445 double fudge 446 ) 447{ 448 l_fp lftemp; 449 double doffset; 450 451 pp->lastrec = lastrec; 452 lftemp = lasttim; 453 L_SUB(&lftemp, &lastrec); 454 LFPTOD(&lftemp, doffset); 455 SAMPLE(doffset + fudge); 456} 457 458 459/* 460 * refclock_process - process a sample from the clock 461 * 462 * This routine converts the timecode in the form days, hours, minutes, 463 * seconds and milliseconds/microseconds to internal timestamp format, 464 * then constructs a new entry in the median filter circular buffer. 465 * Return success (1) if the data are correct and consistent with the 466 * converntional calendar. 467 * 468 * Important for PPS users: Normally, the pp->lastrec is set to the 469 * system time when the on-time character is received and the pp->year, 470 * ..., pp->second decoded and the seconds fraction pp->nsec in 471 * nanoseconds). When a PPS offset is available, pp->nsec is forced to 472 * zero and the fraction for pp->lastrec is set to the PPS offset. 473 */ 474int 475refclock_process( 476 struct refclockproc *pp /* refclock structure pointer */ 477 ) 478{ 479 l_fp offset, ltemp; 480 481 /* 482 * Compute the timecode timestamp from the days, hours, minutes, 483 * seconds and milliseconds/microseconds of the timecode. Use 484 * clocktime() for the aggregate seconds and the msec/usec for 485 * the fraction, when present. Note that this code relies on the 486 * filesystem time for the years and does not use the years of 487 * the timecode. 488 */ 489 if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT, 490 pp->lastrec.l_ui, &pp->yearstart, &offset.l_ui)) 491 return (0); 492 493 offset.l_uf = 0; 494 DTOLFP(pp->nsec / 1e9, <emp); 495 L_ADD(&offset, <emp); 496 refclock_process_offset(pp, offset, pp->lastrec, 497 pp->fudgetime1); 498 return (1); 499} 500 501 502/* 503 * refclock_sample - process a pile of samples from the clock 504 * 505 * This routine implements a recursive median filter to suppress spikes 506 * in the data, as well as determine a performance statistic. It 507 * calculates the mean offset and RMS jitter. A time adjustment 508 * fudgetime1 can be added to the final offset to compensate for various 509 * systematic errors. The routine returns the number of samples 510 * processed, which could be zero. 511 */ 512static int 513refclock_sample( 514 struct refclockproc *pp /* refclock structure pointer */ 515 ) 516{ 517 int i, j, k, m, n; 518 double off[MAXSTAGE]; 519 double offset; 520 521 /* 522 * Copy the raw offsets and sort into ascending order. Don't do 523 * anything if the buffer is empty. 524 */ 525 n = 0; 526 while (pp->codeproc != pp->coderecv) { 527 pp->codeproc = (pp->codeproc + 1) % MAXSTAGE; 528 off[n] = pp->filter[pp->codeproc]; 529 n++; 530 } 531 if (n == 0) 532 return (0); 533 534 if (n > 1) 535 qsort( 536#ifdef QSORT_USES_VOID_P 537 (void *) 538#else 539 (char *) 540#endif 541 off, (size_t)n, sizeof(double), refclock_cmpl_fp); 542 543 /* 544 * Reject the furthest from the median of the samples until 545 * approximately 60 percent of the samples remain. 546 */ 547 i = 0; j = n; 548 m = n - (n * 4) / 10; 549 while ((j - i) > m) { 550 offset = off[(j + i) / 2]; 551 if (off[j - 1] - offset < offset - off[i]) 552 i++; /* reject low end */ 553 else 554 j--; /* reject high end */ 555 } 556 557 /* 558 * Determine the offset and jitter. 559 */ 560 pp->offset = 0; 561 pp->jitter = 0; 562 for (k = i; k < j; k++) { 563 pp->offset += off[k]; 564 if (k > i) 565 pp->jitter += SQUARE(off[k] - off[k - 1]); 566 } 567 pp->offset /= m; 568 pp->jitter = max(SQRT(pp->jitter / m), LOGTOD(sys_precision)); 569#ifdef DEBUG 570 if (debug) 571 printf( 572 "refclock_sample: n %d offset %.6f disp %.6f jitter %.6f\n", 573 n, pp->offset, pp->disp, pp->jitter); 574#endif 575 return (n); 576} 577 578 579/* 580 * refclock_receive - simulate the receive and packet procedures 581 * 582 * This routine simulates the NTP receive and packet procedures for a 583 * reference clock. This provides a mechanism in which the ordinary NTP 584 * filter, selection and combining algorithms can be used to suppress 585 * misbehaving radios and to mitigate between them when more than one is 586 * available for backup. 587 */ 588void 589refclock_receive( 590 struct peer *peer /* peer structure pointer */ 591 ) 592{ 593 struct refclockproc *pp; 594 595#ifdef DEBUG 596 if (debug) 597 printf("refclock_receive: at %lu %s\n", 598 current_time, stoa(&peer->srcadr)); 599#endif 600 601 /* 602 * Do a little sanity dance and update the peer structure. Groom 603 * the median filter samples and give the data to the clock 604 * filter. 605 */ 606 pp = peer->procptr; 607 peer->leap = pp->leap; 608 if (peer->leap == LEAP_NOTINSYNC) 609 return; 610 611 peer->received++; 612 peer->timereceived = current_time; 613 if (!peer->reach) { 614 report_event(EVNT_REACH, peer); 615 peer->timereachable = current_time; 616 } 617 peer->reach |= 1; 618 peer->reftime = pp->lastref; 619 peer->org = pp->lastrec; 620 peer->rootdispersion = pp->disp; 621 get_systime(&peer->rec); 622 if (!refclock_sample(pp)) 623 return; 624 625 clock_filter(peer, pp->offset, 0., pp->jitter); 626 record_peer_stats(&peer->srcadr, ctlpeerstatus(peer), 627 peer->offset, peer->delay, clock_phi * (current_time - 628 peer->epoch), peer->jitter); 629 if (cal_enable && last_offset < MINDISPERSE) { 630#ifdef KERNEL_PLL 631 if (peer != sys_peer || pll_status & STA_PPSTIME) 632#else 633 if (peer != sys_peer) 634#endif /* KERNEL_PLL */ 635 pp->fudgetime1 -= pp->offset * FUDGEFAC; 636 else 637 pp->fudgetime1 -= pp->fudgetime1 * FUDGEFAC; 638 } 639} 640 641 642/* 643 * refclock_gtlin - groom next input line and extract timestamp 644 * 645 * This routine processes the timecode received from the clock and 646 * strips the parity bit and control characters. It returns the number 647 * of characters in the line followed by a NULL character ('\0'), which 648 * is not included in the count. In case of an empty line, the previous 649 * line is preserved. 650 */ 651int 652refclock_gtlin( 653 struct recvbuf *rbufp, /* receive buffer pointer */ 654 char *lineptr, /* current line pointer */ 655 int bmax, /* remaining characters in line */ 656 l_fp *tsptr /* pointer to timestamp returned */ 657 ) 658{ 659 char s[BMAX]; 660 char *dpt, *dpend, *dp; 661 662 dpt = s; 663 dpend = s + refclock_gtraw(rbufp, s, BMAX - 1, tsptr); 664 if (dpend - dpt > bmax - 1) 665 dpend = dpt + bmax - 1; 666 for (dp = lineptr; dpt < dpend; dpt++) { 667 char c; 668 669 c = *dpt & 0x7f; 670 if (c >= 0x20 && c < 0x7f) 671 *dp++ = c; 672 } 673 if (dp == lineptr) 674 return (0); 675 676 *dp = '\0'; 677 return (dp - lineptr); 678} 679 680 681/* 682 * refclock_gtraw - get next line/chunk of data 683 * 684 * This routine returns the raw data received from the clock in both 685 * canonical or raw modes. The terminal interface routines map CR to LF. 686 * In canonical mode this results in two lines, one containing data 687 * followed by LF and another containing only LF. In raw mode the 688 * interface routines can deliver arbitraty chunks of data from one 689 * character to a maximum specified by the calling routine. In either 690 * mode the routine returns the number of characters in the line 691 * followed by a NULL character ('\0'), which is not included in the 692 * count. 693 * 694 * If a timestamp is present in the timecode, as produced by the tty_clk 695 * STREAMS module, it returns that as the timestamp; otherwise, it 696 * returns the buffer timestamp. 697 */ 698int 699refclock_gtraw( 700 struct recvbuf *rbufp, /* receive buffer pointer */ 701 char *lineptr, /* current line pointer */ 702 int bmax, /* remaining characters in line */ 703 l_fp *tsptr /* pointer to timestamp returned */ 704 ) 705{ 706 char *dpt, *dpend, *dp; 707 l_fp trtmp, tstmp; 708 int i; 709 710 /* 711 * Check for the presence of a timestamp left by the tty_clock 712 * module and, if present, use that instead of the buffer 713 * timestamp captured by the I/O routines. We recognize a 714 * timestamp by noting its value is earlier than the buffer 715 * timestamp, but not more than one second earlier. 716 */ 717 dpt = (char *)rbufp->recv_buffer; 718 dpend = dpt + rbufp->recv_length; 719 trtmp = rbufp->recv_time; 720 if (dpend >= dpt + 8) { 721 if (buftvtots(dpend - 8, &tstmp)) { 722 L_SUB(&trtmp, &tstmp); 723 if (trtmp.l_ui == 0) { 724#ifdef DEBUG 725 if (debug > 1) { 726 printf( 727 "refclock_gtlin: fd %d ldisc %s", 728 rbufp->fd, lfptoa(&trtmp, 729 6)); 730 get_systime(&trtmp); 731 L_SUB(&trtmp, &tstmp); 732 printf(" sigio %s\n", 733 lfptoa(&trtmp, 6)); 734 } 735#endif 736 dpend -= 8; 737 trtmp = tstmp; 738 } else 739 trtmp = rbufp->recv_time; 740 } 741 } 742 743 /* 744 * Copy the raw buffer to the user string. The string is padded 745 * with a NULL, which is not included in the character count. 746 */ 747 if (dpend - dpt > bmax - 1) 748 dpend = dpt + bmax - 1; 749 for (dp = lineptr; dpt < dpend; dpt++) 750 *dp++ = *dpt; 751 *dp = '\0'; 752 i = dp - lineptr; 753#ifdef DEBUG 754 if (debug > 1) 755 printf("refclock_gtraw: fd %d time %s timecode %d %s\n", 756 rbufp->fd, ulfptoa(&trtmp, 6), i, lineptr); 757#endif 758 *tsptr = trtmp; 759 return (i); 760} 761 762 763/* 764 * The following code does not apply to WINNT & VMS ... 765 */ 766#if !defined SYS_VXWORKS && !defined SYS_WINNT 767#if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS) 768 769/* 770 * refclock_open - open serial port for reference clock 771 * 772 * This routine opens a serial port for I/O and sets default options. It 773 * returns the file descriptor if success and zero if failure. 774 */ 775int 776refclock_open( 777 char *dev, /* device name pointer */ 778 u_int speed, /* serial port speed (code) */ 779 u_int lflags /* line discipline flags */ 780 ) 781{ 782 int fd; 783 int omode; 784 785 /* 786 * Open serial port and set default options 787 */ 788 omode = O_RDWR; 789#ifdef O_NONBLOCK 790 omode |= O_NONBLOCK; 791#endif 792#ifdef O_NOCTTY 793 omode |= O_NOCTTY; 794#endif 795 796 fd = open(dev, omode, 0777); 797 if (fd < 0) { 798 msyslog(LOG_ERR, "refclock_open %s: %m", dev); 799 return (0); 800 } 801 if (!refclock_setup(fd, speed, lflags)) { 802 close(fd); 803 return (0); 804 } 805 if (!refclock_ioctl(fd, lflags)) { 806 close(fd); 807 return (0); 808 } 809 return (fd); 810} 811 812/* 813 * refclock_setup - initialize terminal interface structure 814 */ 815int 816refclock_setup( 817 int fd, /* file descriptor */ 818 u_int speed, /* serial port speed (code) */ 819 u_int lflags /* line discipline flags */ 820 ) 821{ 822 int i; 823 TTY ttyb, *ttyp; 824#ifdef PPS 825 fdpps = fd; /* ppsclock legacy */ 826#endif /* PPS */ 827 828 /* 829 * By default, the serial line port is initialized in canonical 830 * (line-oriented) mode at specified line speed, 8 bits and no 831 * parity. LF ends the line and CR is mapped to LF. The break, 832 * erase and kill functions are disabled. There is a different 833 * section for each terminal interface, as selected at compile 834 * time. The flag bits can be used to set raw mode and echo. 835 */ 836 ttyp = &ttyb; 837#ifdef HAVE_TERMIOS 838 839 /* 840 * POSIX serial line parameters (termios interface) 841 */ 842 if (tcgetattr(fd, ttyp) < 0) { 843 msyslog(LOG_ERR, 844 "refclock_setup fd %d tcgetattr: %m", fd); 845 return (0); 846 } 847 848 /* 849 * Set canonical mode and local connection; set specified speed, 850 * 8 bits and no parity; map CR to NL; ignore break. 851 */ 852 if (speed) { 853 u_int ltemp = 0; 854 855 ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL; 856 ttyp->c_oflag = 0; 857 ttyp->c_cflag = CS8 | CLOCAL | CREAD; 858 if (lflags & LDISC_7O1) { 859 /* HP Z3801A needs 7-bit, odd parity */ 860 ttyp->c_cflag = CS7 | PARENB | PARODD | CLOCAL | CREAD; 861 } 862 cfsetispeed(&ttyb, speed); 863 cfsetospeed(&ttyb, speed); 864 for (i = 0; i < NCCS; ++i) 865 ttyp->c_cc[i] = '\0'; 866 867#if defined(TIOCMGET) && !defined(SCO5_CLOCK) 868 869 /* 870 * If we have modem control, check to see if modem leads 871 * are active; if so, set remote connection. This is 872 * necessary for the kernel pps mods to work. 873 */ 874 if (ioctl(fd, TIOCMGET, (char *)<emp) < 0) 875 msyslog(LOG_ERR, 876 "refclock_setup fd %d TIOCMGET: %m", fd); 877#ifdef DEBUG 878 if (debug) 879 printf("refclock_setup fd %d modem status: 0x%x\n", 880 fd, ltemp); 881#endif 882 if (ltemp & TIOCM_DSR && lflags & LDISC_REMOTE) 883 ttyp->c_cflag &= ~CLOCAL; 884#endif /* TIOCMGET */ 885 } 886 887 /* 888 * Set raw and echo modes. These can be changed on-fly. 889 */ 890 ttyp->c_lflag = ICANON; 891 if (lflags & LDISC_RAW) { 892 ttyp->c_lflag = 0; 893 ttyp->c_iflag = 0; 894 ttyp->c_cc[VMIN] = 1; 895 } 896 if (lflags & LDISC_ECHO) 897 ttyp->c_lflag |= ECHO; 898 if (tcsetattr(fd, TCSANOW, ttyp) < 0) { 899 msyslog(LOG_ERR, 900 "refclock_setup fd %d TCSANOW: %m", fd); 901 return (0); 902 } 903#endif /* HAVE_TERMIOS */ 904 905#ifdef HAVE_SYSV_TTYS 906 907 /* 908 * System V serial line parameters (termio interface) 909 * 910 */ 911 if (ioctl(fd, TCGETA, ttyp) < 0) { 912 msyslog(LOG_ERR, 913 "refclock_setup fd %d TCGETA: %m", fd); 914 return (0); 915 } 916 917 /* 918 * Set canonical mode and local connection; set specified speed, 919 * 8 bits and no parity; map CR to NL; ignore break. 920 */ 921 if (speed) { 922 u_int ltemp = 0; 923 924 ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL; 925 ttyp->c_oflag = 0; 926 ttyp->c_cflag = speed | CS8 | CLOCAL | CREAD; 927 for (i = 0; i < NCCS; ++i) 928 ttyp->c_cc[i] = '\0'; 929 930#if defined(TIOCMGET) && !defined(SCO5_CLOCK) 931 932 /* 933 * If we have modem control, check to see if modem leads 934 * are active; if so, set remote connection. This is 935 * necessary for the kernel pps mods to work. 936 */ 937 if (ioctl(fd, TIOCMGET, (char *)<emp) < 0) 938 msyslog(LOG_ERR, 939 "refclock_setup fd %d TIOCMGET: %m", fd); 940#ifdef DEBUG 941 if (debug) 942 printf("refclock_setup fd %d modem status: %x\n", 943 fd, ltemp); 944#endif 945 if (ltemp & TIOCM_DSR) 946 ttyp->c_cflag &= ~CLOCAL; 947#endif /* TIOCMGET */ 948 } 949 950 /* 951 * Set raw and echo modes. These can be changed on-fly. 952 */ 953 ttyp->c_lflag = ICANON; 954 if (lflags & LDISC_RAW) { 955 ttyp->c_lflag = 0; 956 ttyp->c_iflag = 0; 957 ttyp->c_cc[VMIN] = 1; 958 } 959 if (ioctl(fd, TCSETA, ttyp) < 0) { 960 msyslog(LOG_ERR, 961 "refclock_setup fd %d TCSETA: %m", fd); 962 return (0); 963 } 964#endif /* HAVE_SYSV_TTYS */ 965 966#ifdef HAVE_BSD_TTYS 967 968 /* 969 * 4.3bsd serial line parameters (sgttyb interface) 970 */ 971 if (ioctl(fd, TIOCGETP, (char *)ttyp) < 0) { 972 msyslog(LOG_ERR, 973 "refclock_setup fd %d TIOCGETP: %m", fd); 974 return (0); 975 } 976 if (speed) 977 ttyp->sg_ispeed = ttyp->sg_ospeed = speed; 978 ttyp->sg_flags = EVENP | ODDP | CRMOD; 979 if (ioctl(fd, TIOCSETP, (char *)ttyp) < 0) { 980 msyslog(LOG_ERR, 981 "refclock_setup TIOCSETP: %m"); 982 return (0); 983 } 984#endif /* HAVE_BSD_TTYS */ 985 return(1); 986} 987#endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */ 988#endif /* SYS_VXWORKS SYS_WINNT */ 989 990 991/* 992 * refclock_ioctl - set serial port control functions 993 * 994 * This routine attempts to hide the internal, system-specific details 995 * of serial ports. It can handle POSIX (termios), SYSV (termio) and BSD 996 * (sgtty) interfaces with varying degrees of success. The routine sets 997 * up optional features such as tty_clk. The routine returns 1 if 998 * success and 0 if failure. 999 */ 1000int 1001refclock_ioctl( 1002 int fd, /* file descriptor */ 1003 u_int lflags /* line discipline flags */ 1004 ) 1005{ 1006 /* 1007 * simply return 1 if no UNIX line discipline is supported 1008 */ 1009#if !defined SYS_VXWORKS && !defined SYS_WINNT 1010#if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS) 1011 1012#ifdef DEBUG 1013 if (debug) 1014 printf("refclock_ioctl: fd %d flags 0x%x\n", fd, 1015 lflags); 1016#endif 1017#ifdef TTYCLK 1018 1019 /* 1020 * The TTYCLK option provides timestamping at the driver level. 1021 * It requires the tty_clk streams module and System V STREAMS 1022 * support. If not available, don't complain. 1023 */ 1024 if (lflags & (LDISC_CLK | LDISC_CLKPPS | LDISC_ACTS)) { 1025 int rval = 0; 1026 1027 if (ioctl(fd, I_PUSH, "clk") < 0) { 1028 msyslog(LOG_NOTICE, 1029 "refclock_ioctl fd %d I_PUSH: %m", fd); 1030 return (0); 1031#ifdef CLK_SETSTR 1032 } else { 1033 char *str; 1034 1035 if (lflags & LDISC_CLKPPS) 1036 str = "\377"; 1037 else if (lflags & LDISC_ACTS) 1038 str = "*"; 1039 else 1040 str = "\n"; 1041 if (ioctl(fd, CLK_SETSTR, str) < 0) { 1042 msyslog(LOG_ERR, 1043 "refclock_ioctl fd %d CLK_SETSTR: %m", fd); 1044 return (0); 1045 } 1046#endif /*CLK_SETSTR */ 1047 } 1048 } 1049#endif /* TTYCLK */ 1050#endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */ 1051#endif /* SYS_VXWORKS SYS_WINNT */ 1052 return (1); 1053} 1054 1055 1056/* 1057 * refclock_control - set and/or return clock values 1058 * 1059 * This routine is used mainly for debugging. It returns designated 1060 * values from the interface structure that can be displayed using 1061 * ntpdc and the clockstat command. It can also be used to initialize 1062 * configuration variables, such as fudgetimes, fudgevalues, reference 1063 * ID and stratum. 1064 */ 1065void 1066refclock_control( 1067 struct sockaddr_storage *srcadr, 1068 struct refclockstat *in, 1069 struct refclockstat *out 1070 ) 1071{ 1072 struct peer *peer; 1073 struct refclockproc *pp; 1074 u_char clktype; 1075 int unit; 1076 1077 /* 1078 * Check for valid address and running peer 1079 */ 1080 if (srcadr->ss_family != AF_INET) 1081 return; 1082 1083 if (!ISREFCLOCKADR(srcadr)) 1084 return; 1085 1086 clktype = (u_char)REFCLOCKTYPE(srcadr); 1087 unit = REFCLOCKUNIT(srcadr); 1088 if (clktype >= num_refclock_conf || unit >= MAXUNIT) 1089 return; 1090 1091 peer = typeunit[clktype][unit]; 1092 if (peer == NULL) 1093 return; 1094 1095 if (peer->procptr == NULL) 1096 return; 1097 1098 pp = peer->procptr; 1099 1100 /* 1101 * Initialize requested data 1102 */ 1103 if (in != 0) { 1104 if (in->haveflags & CLK_HAVETIME1) 1105 pp->fudgetime1 = in->fudgetime1; 1106 if (in->haveflags & CLK_HAVETIME2) 1107 pp->fudgetime2 = in->fudgetime2; 1108 if (in->haveflags & CLK_HAVEVAL1) 1109 peer->stratum = pp->stratum = (u_char)in->fudgeval1; 1110 if (in->haveflags & CLK_HAVEVAL2) 1111 peer->refid = pp->refid = in->fudgeval2; 1112 if (in->haveflags & CLK_HAVEFLAG1) { 1113 pp->sloppyclockflag &= ~CLK_FLAG1; 1114 pp->sloppyclockflag |= in->flags & CLK_FLAG1; 1115 } 1116 if (in->haveflags & CLK_HAVEFLAG2) { 1117 pp->sloppyclockflag &= ~CLK_FLAG2; 1118 pp->sloppyclockflag |= in->flags & CLK_FLAG2; 1119 } 1120 if (in->haveflags & CLK_HAVEFLAG3) { 1121 pp->sloppyclockflag &= ~CLK_FLAG3; 1122 pp->sloppyclockflag |= in->flags & CLK_FLAG3; 1123 } 1124 if (in->haveflags & CLK_HAVEFLAG4) { 1125 pp->sloppyclockflag &= ~CLK_FLAG4; 1126 pp->sloppyclockflag |= in->flags & CLK_FLAG4; 1127 } 1128 } 1129 1130 /* 1131 * Readback requested data 1132 */ 1133 if (out != 0) { 1134 out->haveflags = CLK_HAVETIME1 | CLK_HAVEVAL1 | 1135 CLK_HAVEVAL2 | CLK_HAVEFLAG4; 1136 out->fudgetime1 = pp->fudgetime1; 1137 out->fudgetime2 = pp->fudgetime2; 1138 out->fudgeval1 = pp->stratum; 1139 out->fudgeval2 = pp->refid; 1140 out->flags = (u_char) pp->sloppyclockflag; 1141 1142 out->timereset = current_time - pp->timestarted; 1143 out->polls = pp->polls; 1144 out->noresponse = pp->noreply; 1145 out->badformat = pp->badformat; 1146 out->baddata = pp->baddata; 1147 1148 out->lastevent = pp->lastevent; 1149 out->currentstatus = pp->currentstatus; 1150 out->type = pp->type; 1151 out->clockdesc = pp->clockdesc; 1152 out->lencode = pp->lencode; 1153 out->p_lastcode = pp->a_lastcode; 1154 } 1155 1156 /* 1157 * Give the stuff to the clock 1158 */ 1159 if (refclock_conf[clktype]->clock_control != noentry) 1160 (refclock_conf[clktype]->clock_control)(unit, in, out, peer); 1161} 1162 1163 1164/* 1165 * refclock_buginfo - return debugging info 1166 * 1167 * This routine is used mainly for debugging. It returns designated 1168 * values from the interface structure that can be displayed using 1169 * ntpdc and the clkbug command. 1170 */ 1171void 1172refclock_buginfo( 1173 struct sockaddr_storage *srcadr, /* clock address */ 1174 struct refclockbug *bug /* output structure */ 1175 ) 1176{ 1177 struct peer *peer; 1178 struct refclockproc *pp; 1179 u_char clktype; 1180 int unit; 1181 int i; 1182 1183 /* 1184 * Check for valid address and peer structure 1185 */ 1186 if (srcadr->ss_family != AF_INET) 1187 return; 1188 1189 if (!ISREFCLOCKADR(srcadr)) 1190 return; 1191 1192 clktype = (u_char) REFCLOCKTYPE(srcadr); 1193 unit = REFCLOCKUNIT(srcadr); 1194 if (clktype >= num_refclock_conf || unit >= MAXUNIT) 1195 return; 1196 1197 peer = typeunit[clktype][unit]; 1198 if (peer == NULL) 1199 return; 1200 1201 pp = peer->procptr; 1202 1203 /* 1204 * Copy structure values 1205 */ 1206 bug->nvalues = 8; 1207 bug->svalues = 0x0000003f; 1208 bug->values[0] = pp->year; 1209 bug->values[1] = pp->day; 1210 bug->values[2] = pp->hour; 1211 bug->values[3] = pp->minute; 1212 bug->values[4] = pp->second; 1213 bug->values[5] = pp->nsec; 1214 bug->values[6] = pp->yearstart; 1215 bug->values[7] = pp->coderecv; 1216 bug->stimes = 0xfffffffc; 1217 bug->times[0] = pp->lastref; 1218 bug->times[1] = pp->lastrec; 1219 for (i = 2; i < (int)bug->ntimes; i++) 1220 DTOLFP(pp->filter[i - 2], &bug->times[i]); 1221 1222 /* 1223 * Give the stuff to the clock 1224 */ 1225 if (refclock_conf[clktype]->clock_buginfo != noentry) 1226 (refclock_conf[clktype]->clock_buginfo)(unit, bug, peer); 1227} 1228 1229#endif /* REFCLOCK */ 1230