1 /* 2 * refclock_acts - clock driver for the NIST/USNO/PTB/NPL Computer Time 3 * Services 4 */ 5 #ifdef HAVE_CONFIG_H 6 #include <config.h> 7 #endif 8 9 #if defined(REFCLOCK) && defined(CLOCK_ACTS) 10 11 #include "ntpd.h" 12 #include "ntp_io.h" 13 #include "ntp_unixtime.h" 14 #include "ntp_refclock.h" 15 #include "ntp_stdlib.h" 16 #include "ntp_control.h" 17 18 #include <stdio.h> 19 #include <ctype.h> 20 #ifdef HAVE_SYS_IOCTL_H 21 # include <sys/ioctl.h> 22 #endif /* HAVE_SYS_IOCTL_H */ 23 24 /* 25 * This driver supports the US (NIST, USNO) and European (PTB, NPL, 26 * etc.) modem time services, as well as Spectracom GPS and WWVB 27 * receivers connected via a modem. The driver periodically dials a 28 * number from a telephone list, receives the timecode data and 29 * calculates the local clock correction. It is designed primarily for 30 * use as backup when neither a radio clock nor connectivity to Internet 31 * time servers is available. 32 * 33 * This driver requires a modem with a Hayes-compatible command set and 34 * control over the modem data terminal ready (DTR) control line. The 35 * modem setup string is hard-coded in the driver and may require 36 * changes for nonstandard modems or special circumstances. 37 * 38 * When enabled, the calling program dials the first number in the 39 * phones file. If that call fails, it dials the second number and 40 * so on. The phone number is specified by the Hayes ATDT prefix 41 * followed by the number itself, including the long-distance prefix 42 * and delay code, if necessary. The calling program is enabled 43 * when (a) fudge flag1 is set by ntpdc, (b) at each poll interval 44 * when no other synchronization sources are present, and (c) at each 45 * poll interval whether or not other synchronization sources are 46 * present. The calling program disconnects if (a) the called party 47 * is busy or does not answer, (b) the called party disconnects 48 * before a sufficient nuimber of timecodes have been received. 49 * 50 * The driver is transparent to each of the modem time services and 51 * Spectracom radios. It selects the parsing algorithm depending on the 52 * message length. There is some hazard should the message be corrupted. 53 * However, the data format is checked carefully and only if all checks 54 * succeed is the message accepted. Corrupted lines are discarded 55 * without complaint. 56 * 57 * Fudge controls 58 * 59 * flag1 force a call in manual mode 60 * flag2 enable port locking (not verified) 61 * flag3 not used 62 * flag4 not used 63 * 64 * time1 offset adjustment (s) 65 * 66 * Ordinarily, the serial port is connected to a modem and the phones 67 * list is defined. If no phones list is defined, the port can be 68 * connected directly to a device or another computer. In this case the 69 * driver will send a single character 'T' at each poll event. If 70 * fudge flag2 is enabled, port locking allows the modem to be shared 71 * when not in use by this driver. 72 */ 73 /* 74 * National Institute of Science and Technology (NIST) 75 * 76 * Phone: (303) 494-4774 (Boulder, CO); (808) 335-4721 (Hawaii) 77 * 78 * Data Format 79 * 80 * National Institute of Standards and Technology 81 * Telephone Time Service, Generator 3B 82 * Enter question mark "?" for HELP 83 * D L D 84 * MJD YR MO DA H M S ST S UT1 msADV <OTM> 85 * 47999 90-04-18 21:39:15 50 0 +.1 045.0 UTC(NIST) *<CR><LF> 86 * ... 87 * 88 * MJD, DST, DUT1 and UTC are not used by this driver. The "*" or "#" is 89 * the on-time markers echoed by the driver and used by NIST to measure 90 * and correct for the propagation delay. Note: the ACTS timecode has 91 * recently been changed to eliminate the * on-time indicator. The 92 * reason for this and the long term implications are not clear. 93 * 94 * US Naval Observatory (USNO) 95 * 96 * Phone: (202) 762-1594 (Washington, DC); (719) 567-6742 (Boulder, CO) 97 * 98 * Data Format (two lines, repeating at one-second intervals) 99 * 100 * jjjjj nnn hhmmss UTC<CR><LF> 101 * *<CR><LF> 102 * 103 * jjjjj modified Julian day number (not used) 104 * nnn day of year 105 * hhmmss second of day 106 * * on-time marker for previous timecode 107 * ... 108 * 109 * USNO does not correct for the propagation delay. A fudge time1 of 110 * about .06 s is advisable. 111 * 112 * European Services (PTB, NPL, etc.) 113 * 114 * PTB: +49 531 512038 (Germany) 115 * NPL: 0906 851 6333 (UK only) 116 * 117 * Data format (see the documentation for phone numbers and formats.) 118 * 119 * 1995-01-23 20:58:51 MEZ 10402303260219950123195849740+40000500<CR><LF> 120 * 121 * Spectracom GPS and WWVB Receivers 122 * 123 * If a modem is connected to a Spectracom receiver, this driver will 124 * call it up and retrieve the time in one of two formats. As this 125 * driver does not send anything, the radio will have to either be 126 * configured in continuous mode or be polled by another local driver. 127 */ 128 /* 129 * Interface definitions 130 */ 131 #define DEVICE "/dev/acts%d" /* device name and unit */ 132 #define SPEED232 B19200 /* uart speed (19200 bps) */ 133 #define PRECISION (-10) /* precision assumed (about 1 ms) */ 134 #define LOCKFILE "/var/spool/lock/LCK..cua%d" 135 #define DESCRIPTION "Automated Computer Time Service" /* WRU */ 136 #define REFID "NONE" /* default reference ID */ 137 #define MSGCNT 20 /* max message count */ 138 #define MAXPHONE 10 /* max number of phone numbers */ 139 140 /* 141 * Calling program modes (mode) 142 */ 143 #define MODE_BACKUP 0 /* backup mode */ 144 #define MODE_AUTO 1 /* automatic mode */ 145 #define MODE_MANUAL 2 /* manual mode */ 146 147 /* 148 * Service identifiers (message length) 149 */ 150 #define REFACTS "NIST" /* NIST reference ID */ 151 #define LENACTS 50 /* NIST format A */ 152 #define REFUSNO "USNO" /* USNO reference ID */ 153 #define LENUSNO 20 /* USNO */ 154 #define REFPTB "PTB\0" /* PTB/NPL reference ID */ 155 #define LENPTB 78 /* PTB/NPL format */ 156 #define REFWWVB "WWVB" /* WWVB reference ID */ 157 #define LENWWVB0 22 /* WWVB format 0 */ 158 #define LENWWVB2 24 /* WWVB format 2 */ 159 #define LF 0x0a /* ASCII LF */ 160 161 /* 162 * Modem setup strings. These may have to be changed for 163 * some modems. 164 * 165 * AT command prefix 166 * B1 US answer tone 167 * &C0 disable carrier detect 168 * &D2 hang up and return to command mode on DTR transition 169 * E0 modem command echo disabled 170 * L1 set modem speaker volume to low level 171 * M1 speaker enabled until carrier detect 172 * Q0 return result codes 173 * V1 return result codes as English words 174 * Y1 enable long-space disconnect 175 */ 176 const char def_modem_setup[] = "ATB1&C0&D2E0L1M1Q0V1Y1"; 177 const char *modem_setup = def_modem_setup; 178 179 /* 180 * Timeouts (all in seconds) 181 */ 182 #define SETUP 3 /* setup timeout */ 183 #define REDIAL 30 /* redial timeout */ 184 #define ANSWER 60 /* answer timeout */ 185 #define TIMECODE 60 /* message timeout */ 186 #define MAXCODE 20 /* max timecodes */ 187 188 /* 189 * State machine codes 190 */ 191 typedef enum { 192 S_IDLE, /* wait for poll */ 193 S_SETUP, /* send modem setup */ 194 S_CONNECT, /* wait for answer */ 195 S_MSG /* wait for timecode */ 196 } teModemState; 197 198 /* 199 * Unit control structure 200 */ 201 struct actsunit { 202 int unit; /* unit number */ 203 int state; /* the first one was Delaware */ 204 int timer; /* timeout counter */ 205 int retry; /* retry index */ 206 int msgcnt; /* count of messages received */ 207 l_fp tstamp; /* on-time timestamp */ 208 char *bufptr; /* next incoming char stored here */ 209 char buf[BMAX]; /* bufptr roams within buf[] */ 210 }; 211 212 /* 213 * Function prototypes 214 */ 215 static int acts_start (int, struct peer *); 216 static void acts_shutdown (int, struct peer *); 217 static void acts_receive (struct recvbuf *); 218 static void acts_message (struct peer *, const char *); 219 static void acts_timecode (struct peer *, const char *); 220 static void acts_poll (int, struct peer *); 221 static void acts_timeout (struct peer *, teModemState); 222 static void acts_timer (int, struct peer *); 223 static void acts_close (struct peer *); 224 225 /* 226 * Transfer vector (conditional structure name) 227 */ 228 struct refclock refclock_acts = { 229 acts_start, /* start up driver */ 230 acts_shutdown, /* shut down driver */ 231 acts_poll, /* transmit poll message */ 232 noentry, /* not used */ 233 noentry, /* not used */ 234 noentry, /* not used */ 235 acts_timer /* housekeeping timer */ 236 }; 237 238 /* 239 * Initialize data for processing 240 */ 241 static int 242 acts_start( 243 int unit, 244 struct peer *peer 245 ) 246 { 247 struct actsunit *up; 248 struct refclockproc *pp; 249 const char *setup; 250 251 /* 252 * Allocate and initialize unit structure 253 */ 254 up = emalloc_zero(sizeof(struct actsunit)); 255 up->unit = unit; 256 pp = peer->procptr; 257 pp->unitptr = up; 258 pp->io.clock_recv = acts_receive; 259 pp->io.srcclock = peer; 260 pp->io.datalen = 0; 261 pp->io.fd = -1; 262 263 /* 264 * Initialize miscellaneous variables 265 */ 266 peer->precision = PRECISION; 267 pp->clockdesc = DESCRIPTION; 268 memcpy(&pp->refid, REFID, 4); 269 peer->sstclktype = CTL_SST_TS_TELEPHONE; 270 up->bufptr = up->buf; 271 if (def_modem_setup == modem_setup) { 272 setup = get_ext_sys_var("modemsetup"); 273 if (setup != NULL) 274 modem_setup = estrdup(setup); 275 } 276 277 return (1); 278 } 279 280 281 /* 282 * acts_shutdown - shut down the clock 283 */ 284 static void 285 acts_shutdown( 286 int unit, 287 struct peer *peer 288 ) 289 { 290 struct actsunit *up; 291 struct refclockproc *pp; 292 293 /* 294 * Warning: do this only when a call is not in progress. 295 */ 296 pp = peer->procptr; 297 up = pp->unitptr; 298 acts_close(peer); 299 free(up); 300 } 301 302 303 /* 304 * acts_receive - receive data from the serial interface 305 */ 306 static void 307 acts_receive( 308 struct recvbuf *rbufp 309 ) 310 { 311 struct actsunit *up; 312 struct refclockproc *pp; 313 struct peer *peer; 314 char tbuf[sizeof(up->buf)]; 315 char * tptr; 316 int octets; 317 318 /* 319 * Initialize pointers and read the timecode and timestamp. Note 320 * we are in raw mode and victim of whatever the terminal 321 * interface kicks up; so, we have to reassemble messages from 322 * arbitrary fragments. Capture the timecode at the beginning of 323 * the message and at the '*' and '#' on-time characters. 324 */ 325 peer = rbufp->recv_peer; 326 pp = peer->procptr; 327 up = pp->unitptr; 328 octets = sizeof(up->buf) - (up->bufptr - up->buf); 329 refclock_gtraw(rbufp, tbuf, octets, &pp->lastrec); 330 for (tptr = tbuf; *tptr != '\0'; tptr++) { 331 if (*tptr == LF) { 332 if (up->bufptr == up->buf) { 333 up->tstamp = pp->lastrec; 334 continue; 335 } else { 336 *up->bufptr = '\0'; 337 up->bufptr = up->buf; 338 acts_message(peer, up->buf); 339 } 340 } else if (!iscntrl((unsigned char)*tptr)) { 341 *up->bufptr++ = *tptr; 342 if (*tptr == '*' || *tptr == '#') { 343 up->tstamp = pp->lastrec; 344 refclock_write(peer, tptr, 1, "data"); 345 } 346 } 347 } 348 } 349 350 351 /* 352 * acts_message - process message 353 */ 354 void 355 acts_message( 356 struct peer *peer, 357 const char *msg 358 ) 359 { 360 struct actsunit *up; 361 struct refclockproc *pp; 362 char tbuf[BMAX]; 363 int dtr = TIOCM_DTR; 364 365 DPRINTF(1, ("acts: %d %s\n", (int)strlen(msg), msg)); 366 367 /* 368 * What to do depends on the state and the first token in the 369 * message. 370 */ 371 pp = peer->procptr; 372 up = pp->unitptr; 373 374 /* 375 * Extract the first token in the line. 376 */ 377 strlcpy(tbuf, msg, sizeof(tbuf)); 378 strtok(tbuf, " "); 379 switch (up->state) { 380 381 /* 382 * We are waiting for the OK response to the modem setup 383 * command. When this happens, dial the number followed. 384 * If anything other than OK is received, just ignore it 385 * and wait for timeoue. 386 */ 387 case S_SETUP: 388 if (strcmp(tbuf, "OK") != 0) { 389 /* 390 * We disable echo with MODEM_SETUP's E0 but 391 * if the modem was previously E1, we will 392 * see MODEM_SETUP echoed before the OK/ERROR. 393 * Ignore it. 394 */ 395 if (!strcmp(tbuf, modem_setup)) 396 return; 397 break; 398 } 399 400 mprintf_event(PEVNT_CLOCK, peer, "DIAL #%d %s", 401 up->retry, sys_phone[up->retry]); 402 if (ioctl(pp->io.fd, TIOCMBIS, &dtr) < 0) 403 msyslog(LOG_ERR, "acts: ioctl(TIOCMBIS) failed: %m"); 404 refclock_write(peer, sys_phone[up->retry], 405 strlen(sys_phone[up->retry]), 406 "DIAL"); 407 refclock_write(peer, "\r", 1, "CR"); 408 up->retry++; 409 up->state = S_CONNECT; 410 up->timer = ANSWER; 411 return; 412 413 /* 414 * We are waiting for the CONNECT response to the dial 415 * command. When this happens, listen for timecodes. If 416 * somthing other than CONNECT is received, like BUSY 417 * or NO CARRIER, abort the call. 418 */ 419 case S_CONNECT: 420 if (strcmp(tbuf, "CONNECT") != 0) 421 break; 422 423 report_event(PEVNT_CLOCK, peer, msg); 424 up->state = S_MSG; 425 up->timer = TIMECODE; 426 return; 427 428 /* 429 * We are waiting for a timecode response. Pass it to 430 * the parser. If NO CARRIER is received, save the 431 * messages and abort the call. 432 */ 433 case S_MSG: 434 if (strcmp(tbuf, "NO") == 0) 435 report_event(PEVNT_CLOCK, peer, msg); 436 if (up->msgcnt < MAXCODE) 437 acts_timecode(peer, msg); 438 else 439 acts_timeout(peer, S_MSG); 440 return; 441 } 442 443 /* 444 * Other response. Tell us about it. 445 */ 446 report_event(PEVNT_CLOCK, peer, msg); 447 acts_close(peer); 448 } 449 450 451 /* 452 * acts_timeout - called on timeout 453 */ 454 static void 455 acts_timeout( 456 struct peer *peer, 457 teModemState dstate 458 ) 459 { 460 struct actsunit *up; 461 struct refclockproc *pp; 462 int fd; 463 char device[20]; 464 char lockfile[128], pidbuf[8]; 465 466 /* 467 * The state machine is driven by messages from the modem, 468 * when first started and at timeout. 469 */ 470 pp = peer->procptr; 471 up = pp->unitptr; 472 switch (dstate) { 473 474 /* 475 * System poll event. Lock the modem port, open the device 476 * and send the setup command. 477 */ 478 case S_IDLE: 479 if (-1 != pp->io.fd) 480 return; /* port is already open */ 481 482 /* 483 * Lock the modem port. If busy, retry later. Note: if 484 * something fails between here and the close, the lock 485 * file may not be removed. 486 */ 487 if (pp->sloppyclockflag & CLK_FLAG2) { 488 snprintf(lockfile, sizeof(lockfile), LOCKFILE, 489 up->unit); 490 fd = open(lockfile, O_WRONLY | O_CREAT | O_EXCL, 491 0644); 492 if (fd < 0) { 493 report_event(PEVNT_CLOCK, peer, "acts: port busy"); 494 return; 495 } 496 snprintf(pidbuf, sizeof(pidbuf), "%d\n", 497 (u_int)getpid()); 498 if (write(fd, pidbuf, strlen(pidbuf)) < 0) 499 msyslog(LOG_ERR, "acts: write lock fails %m"); 500 close(fd); 501 } 502 503 /* 504 * Open the device in raw mode and link the I/O. 505 */ 506 snprintf(device, sizeof(device), DEVICE, 507 up->unit); 508 fd = refclock_open(&peer->srcadr, device, SPEED232, LDISC_ACTS | 509 LDISC_RAW | LDISC_REMOTE); 510 if (fd < 0) { 511 msyslog(LOG_ERR, "acts: open fails %m"); 512 return; 513 } 514 pp->io.fd = fd; 515 if (!io_addclock(&pp->io)) { 516 msyslog(LOG_ERR, "acts: addclock fails"); 517 close(fd); 518 pp->io.fd = -1; 519 return; 520 } 521 up->msgcnt = 0; 522 up->bufptr = up->buf; 523 524 /* 525 * If the port is directly connected to the device, skip 526 * the modem business and send 'T' for Spectrabum. 527 */ 528 if (sys_phone[up->retry] == NULL) { 529 refclock_write(peer, "T", 1, "T"); 530 up->state = S_MSG; 531 up->timer = TIMECODE; 532 return; 533 } 534 535 /* 536 * Initialize the modem. This works with Hayes- 537 * compatible modems. 538 */ 539 mprintf_event(PEVNT_CLOCK, peer, "SETUP %s", 540 modem_setup); 541 refclock_write(peer, modem_setup, strlen(modem_setup), 542 "SETUP"); 543 refclock_write(peer, "\r", 1, "CR"); 544 up->state = S_SETUP; 545 up->timer = SETUP; 546 return; 547 548 /* 549 * In SETUP state the modem did not respond OK to setup string. 550 */ 551 case S_SETUP: 552 report_event(PEVNT_CLOCK, peer, "no modem"); 553 break; 554 555 /* 556 * In CONNECT state the call did not complete. Abort the call. 557 */ 558 case S_CONNECT: 559 report_event(PEVNT_CLOCK, peer, "no answer"); 560 break; 561 562 /* 563 * In MSG states no further timecodes are expected. If any 564 * timecodes have arrived, update the clock. In any case, 565 * terminate the call. 566 */ 567 case S_MSG: 568 if (up->msgcnt == 0) { 569 report_event(PEVNT_CLOCK, peer, "no timecodes"); 570 } else { 571 pp->lastref = pp->lastrec; 572 record_clock_stats(&peer->srcadr, pp->a_lastcode); 573 refclock_receive(peer); 574 } 575 break; 576 } 577 acts_close(peer); 578 } 579 580 581 /* 582 * acts_close - close and prepare for next call. 583 * 584 * In ClOSE state no further protocol actions are required 585 * other than to close and release the device and prepare to 586 * dial the next number if necessary. 587 */ 588 void 589 acts_close( 590 struct peer *peer 591 ) 592 { 593 struct actsunit *up; 594 struct refclockproc *pp; 595 char lockfile[128]; 596 int dtr; 597 598 pp = peer->procptr; 599 up = pp->unitptr; 600 if (pp->io.fd != -1) { 601 report_event(PEVNT_CLOCK, peer, "close"); 602 dtr = TIOCM_DTR; 603 if (ioctl(pp->io.fd, TIOCMBIC, &dtr) < 0) 604 msyslog(LOG_ERR, "acts: ioctl(TIOCMBIC) failed: %m"); 605 io_closeclock(&pp->io); 606 pp->io.fd = -1; 607 } 608 if (pp->sloppyclockflag & CLK_FLAG2) { 609 snprintf(lockfile, sizeof(lockfile), 610 LOCKFILE, up->unit); 611 unlink(lockfile); 612 } 613 if (up->msgcnt == 0 && up->retry > 0) { 614 if (sys_phone[up->retry] != NULL) { 615 up->state = S_IDLE; 616 up->timer = REDIAL; 617 return; 618 } 619 } 620 up->state = S_IDLE; 621 up->timer = 0; 622 } 623 624 625 /* 626 * acts_poll - called by the transmit routine 627 */ 628 static void 629 acts_poll( 630 int unit, 631 struct peer *peer 632 ) 633 { 634 struct actsunit *up; 635 struct refclockproc *pp; 636 637 /* 638 * This routine is called at every system poll. All it does is 639 * set flag1 under certain conditions. The real work is done by 640 * the timeout routine and state machine. 641 */ 642 pp = peer->procptr; 643 up = pp->unitptr; 644 switch (peer->ttl) { 645 646 /* 647 * In manual mode the calling program is activated by the ntpdc 648 * program using the enable flag (fudge flag1), either manually 649 * or by a cron job. 650 */ 651 case MODE_MANUAL: 652 return; 653 654 /* 655 * In automatic mode the calling program runs continuously at 656 * intervals determined by the poll event or specified timeout. 657 */ 658 case MODE_AUTO: 659 break; 660 661 /* 662 * In backup mode the calling program runs continuously as long 663 * as either no peers are available or this peer is selected. 664 */ 665 case MODE_BACKUP: 666 if (!(sys_peer == NULL || sys_peer == peer)) 667 return; 668 669 break; 670 } 671 pp->polls++; 672 if (S_IDLE == up->state) { 673 up->retry = 0; 674 acts_timeout(peer, S_IDLE); 675 } 676 } 677 678 679 /* 680 * acts_timer - called at one-second intervals 681 */ 682 static void 683 acts_timer( 684 int unit, 685 struct peer *peer 686 ) 687 { 688 struct actsunit *up; 689 struct refclockproc *pp; 690 691 /* 692 * This routine implments a timeout which runs for a programmed 693 * interval. The counter is initialized by the state machine and 694 * counts down to zero. Upon reaching zero, the state machine is 695 * called. If flag1 is set while timer is zero, force a call. 696 */ 697 pp = peer->procptr; 698 up = pp->unitptr; 699 if (up->timer == 0) { 700 if (pp->sloppyclockflag & CLK_FLAG1) { 701 pp->sloppyclockflag &= ~CLK_FLAG1; 702 acts_timeout(peer, S_IDLE); 703 } 704 } else { 705 up->timer--; 706 if (up->timer == 0) 707 acts_timeout(peer, up->state); 708 } 709 } 710 711 /* 712 * acts_timecode - identify the service and parse the timecode message 713 */ 714 void 715 acts_timecode( 716 struct peer * peer, /* peer structure pointer */ 717 const char * str /* timecode string */ 718 ) 719 { 720 struct actsunit *up; 721 struct refclockproc *pp; 722 int day; /* day of the month */ 723 int month; /* month of the year */ 724 u_long mjd; /* Modified Julian Day */ 725 double dut1; /* DUT adjustment */ 726 727 u_int dst; /* ACTS daylight/standard time */ 728 u_int leap; /* ACTS leap indicator */ 729 double msADV; /* ACTS transmit advance (ms) */ 730 char utc[10]; /* ACTS timescale */ 731 char flag; /* ACTS on-time character (* or #) */ 732 733 char synchar; /* WWVB synchronized indicator */ 734 char qualchar; /* WWVB quality indicator */ 735 char leapchar; /* WWVB leap indicator */ 736 char dstchar; /* WWVB daylight/savings indicator */ 737 int tz; /* WWVB timezone */ 738 739 int leapmonth; /* PTB/NPL month of leap */ 740 char leapdir; /* PTB/NPL leap direction */ 741 742 /* 743 * The parser selects the modem format based on the message 744 * length. Since the data are checked carefully, occasional 745 * errors due noise are forgivable. 746 */ 747 pp = peer->procptr; 748 up = pp->unitptr; 749 pp->nsec = 0; 750 switch (strlen(str)) { 751 752 /* 753 * For USNO format on-time character '*', which is on a line by 754 * itself. Be sure a timecode has been received. 755 */ 756 case 1: 757 if (*str == '*' && up->msgcnt > 0) 758 break; 759 760 return; 761 762 /* 763 * ACTS format A: "jjjjj yy-mm-dd hh:mm:ss ds l uuu aaaaa 764 * UTC(NIST) *". 765 */ 766 case LENACTS: 767 if (sscanf(str, 768 "%5ld %2d-%2d-%2d %2d:%2d:%2d %2d %1d %3lf %5lf %9s %c", 769 &mjd, &pp->year, &month, &day, &pp->hour, 770 &pp->minute, &pp->second, &dst, &leap, &dut1, 771 &msADV, utc, &flag) != 13) { 772 refclock_report(peer, CEVNT_BADREPLY); 773 return; 774 } 775 pp->day = ymd2yd(pp->year, month, day); 776 pp->leap = LEAP_NOWARNING; 777 if (leap == 1) 778 pp->leap = LEAP_ADDSECOND; 779 else if (leap == 2) 780 pp->leap = LEAP_DELSECOND; 781 memcpy(&pp->refid, REFACTS, 4); 782 up->msgcnt++; 783 if (flag != '#' && up->msgcnt < 10) 784 return; 785 786 break; 787 788 /* 789 * USNO format: "jjjjj nnn hhmmss UTC" 790 */ 791 case LENUSNO: 792 if (sscanf(str, "%5ld %3d %2d%2d%2d %3s", 793 &mjd, &pp->day, &pp->hour, &pp->minute, 794 &pp->second, utc) != 6) { 795 refclock_report(peer, CEVNT_BADREPLY); 796 return; 797 } 798 799 /* 800 * Wait for the on-time character, which follows in a 801 * separate message. There is no provision for leap 802 * warning. 803 */ 804 pp->leap = LEAP_NOWARNING; 805 memcpy(&pp->refid, REFUSNO, 4); 806 up->msgcnt++; 807 break; 808 809 /* 810 * PTB/NPL format: "yyyy-mm-dd hh:mm:ss MEZ" 811 */ 812 case LENPTB: 813 if (sscanf(str, 814 "%*4d-%*2d-%*2d %*2d:%*2d:%2d %*5c%*12c%4d%2d%2d%2d%2d%5ld%2lf%c%2d%3lf%*15c%c", 815 &pp->second, &pp->year, &month, &day, &pp->hour, 816 &pp->minute, &mjd, &dut1, &leapdir, &leapmonth, 817 &msADV, &flag) != 12) { 818 refclock_report(peer, CEVNT_BADREPLY); 819 return; 820 } 821 pp->leap = LEAP_NOWARNING; 822 if (leapmonth == month) { 823 if (leapdir == '+') 824 pp->leap = LEAP_ADDSECOND; 825 else if (leapdir == '-') 826 pp->leap = LEAP_DELSECOND; 827 } 828 pp->day = ymd2yd(pp->year, month, day); 829 memcpy(&pp->refid, REFPTB, 4); 830 up->msgcnt++; 831 break; 832 833 834 /* 835 * WWVB format 0: "I ddd hh:mm:ss DTZ=nn" 836 */ 837 case LENWWVB0: 838 if (sscanf(str, "%c %3d %2d:%2d:%2d %cTZ=%2d", 839 &synchar, &pp->day, &pp->hour, &pp->minute, 840 &pp->second, &dstchar, &tz) != 7) { 841 refclock_report(peer, CEVNT_BADREPLY); 842 return; 843 } 844 pp->leap = LEAP_NOWARNING; 845 if (synchar != ' ') 846 pp->leap = LEAP_NOTINSYNC; 847 memcpy(&pp->refid, REFWWVB, 4); 848 up->msgcnt++; 849 break; 850 851 /* 852 * WWVB format 2: "IQyy ddd hh:mm:ss.mmm LD" 853 */ 854 case LENWWVB2: 855 if (sscanf(str, "%c%c%2d %3d %2d:%2d:%2d.%3ld%c%c%c", 856 &synchar, &qualchar, &pp->year, &pp->day, 857 &pp->hour, &pp->minute, &pp->second, &pp->nsec, 858 &dstchar, &leapchar, &dstchar) != 11) { 859 refclock_report(peer, CEVNT_BADREPLY); 860 return; 861 } 862 pp->nsec *= 1000000; 863 pp->leap = LEAP_NOWARNING; 864 if (synchar != ' ') 865 pp->leap = LEAP_NOTINSYNC; 866 else if (leapchar == 'L') 867 pp->leap = LEAP_ADDSECOND; 868 memcpy(&pp->refid, REFWWVB, 4); 869 up->msgcnt++; 870 break; 871 872 /* 873 * None of the above. Just forget about it and wait for the next 874 * message or timeout. 875 */ 876 default: 877 return; 878 } 879 880 /* 881 * We have a valid timecode. The fudge time1 value is added to 882 * each sample by the main line routines. Note that in current 883 * telephone networks the propatation time can be different for 884 * each call and can reach 200 ms for some calls. 885 */ 886 peer->refid = pp->refid; 887 pp->lastrec = up->tstamp; 888 if (up->msgcnt == 0) 889 return; 890 891 strlcpy(pp->a_lastcode, str, sizeof(pp->a_lastcode)); 892 pp->lencode = strlen(pp->a_lastcode); 893 if (!refclock_process(pp)) { 894 refclock_report(peer, CEVNT_BADTIME); 895 return; 896 } 897 pp->lastref = pp->lastrec; 898 } 899 #else 900 NONEMPTY_TRANSLATION_UNIT 901 #endif /* REFCLOCK */ 902