ntp_control.c revision 75259
1/* 2 * ntp_control.c - respond to control messages and send async traps 3 */ 4 5/* 6 * $FreeBSD: head/contrib/ntp/ntpd/ntp_control.c 75259 2001-04-06 14:15:38Z jedgar $ 7 */ 8 9#ifdef HAVE_CONFIG_H 10#include <config.h> 11#endif 12 13#include <stdio.h> 14#include <ctype.h> 15#include <sys/types.h> 16#include <signal.h> 17#include <sys/time.h> 18 19#include "ntpd.h" 20#include "ntp_io.h" 21#include "ntp_refclock.h" 22#include "ntp_control.h" 23#include "ntp_stdlib.h" 24 25/* 26 * Structure to hold request procedure information 27 */ 28#define NOAUTH 0 29#define AUTH 1 30 31#define NO_REQUEST (-1) 32 33struct ctl_proc { 34 short control_code; /* defined request code */ 35 u_short flags; /* flags word */ 36 void (*handler) P((struct recvbuf *, int)); /* routine to handle request */ 37}; 38 39/* 40 * Only one flag. Authentication required or not. 41 */ 42#define NOAUTH 0 43#define AUTH 1 44 45/* 46 * Request processing routines 47 */ 48static void ctl_error P((int)); 49static u_short ctlclkstatus P((struct refclockstat *)); 50static void ctl_flushpkt P((int)); 51static void ctl_putdata P((const char *, unsigned int, int)); 52static void ctl_putstr P((const char *, const char *, unsigned int)); 53static void ctl_putdbl P((const char *, double)); 54static void ctl_putuint P((const char *, u_long)); 55static void ctl_puthex P((const char *, u_long)); 56static void ctl_putint P((const char *, long)); 57static void ctl_putts P((const char *, l_fp *)); 58static void ctl_putadr P((const char *, u_int32)); 59static void ctl_putid P((const char *, char *)); 60static void ctl_putarray P((const char *, double *, int)); 61static void ctl_putsys P((int)); 62static void ctl_putpeer P((int, struct peer *)); 63#ifdef REFCLOCK 64static void ctl_putclock P((int, struct refclockstat *, int)); 65#endif /* REFCLOCK */ 66static struct ctl_var *ctl_getitem P((struct ctl_var *, char **)); 67static u_long count_var P((struct ctl_var *)); 68static void control_unspec P((struct recvbuf *, int)); 69static void read_status P((struct recvbuf *, int)); 70static void read_variables P((struct recvbuf *, int)); 71static void write_variables P((struct recvbuf *, int)); 72static void read_clock_status P((struct recvbuf *, int)); 73static void write_clock_status P((struct recvbuf *, int)); 74static void set_trap P((struct recvbuf *, int)); 75static void unset_trap P((struct recvbuf *, int)); 76static struct ctl_trap *ctlfindtrap P((struct sockaddr_in *, struct interface *)); 77 78static struct ctl_proc control_codes[] = { 79 { CTL_OP_UNSPEC, NOAUTH, control_unspec }, 80 { CTL_OP_READSTAT, NOAUTH, read_status }, 81 { CTL_OP_READVAR, NOAUTH, read_variables }, 82 { CTL_OP_WRITEVAR, AUTH, write_variables }, 83 { CTL_OP_READCLOCK, NOAUTH, read_clock_status }, 84 { CTL_OP_WRITECLOCK, NOAUTH, write_clock_status }, 85 { CTL_OP_SETTRAP, NOAUTH, set_trap }, 86 { CTL_OP_UNSETTRAP, NOAUTH, unset_trap }, 87 { NO_REQUEST, 0 } 88}; 89 90/* 91 * System variable values. The array can be indexed by 92 * the variable index to find the textual name. 93 */ 94static struct ctl_var sys_var[] = { 95 { 0, PADDING, "" }, /* 0 */ 96 { CS_LEAP, RW, "leap" }, /* 1 */ 97 { CS_STRATUM, RO, "stratum" }, /* 2 */ 98 { CS_PRECISION, RO, "precision" }, /* 3 */ 99 { CS_ROOTDELAY, RO, "rootdelay" }, /* 4 */ 100 { CS_ROOTDISPERSION, RO, "rootdispersion" }, /* 5 */ 101 { CS_REFID, RO, "refid" }, /* 6 */ 102 { CS_REFTIME, RO, "reftime" }, /* 7 */ 103 { CS_POLL, RO, "poll" }, /* 8 */ 104 { CS_PEERID, RO, "peer" }, /* 9 */ 105 { CS_STATE, RO, "state" }, /* 10 */ 106 { CS_OFFSET, RO, "phase" }, /* 11 */ 107 { CS_DRIFT, RO, "frequency" }, /* 12 */ 108 { CS_COMPLIANCE, RO, "jitter" }, /* 13 */ 109 { CS_CLOCK, RO, "clock" }, /* 14 */ 110 { CS_PROCESSOR, RO, "processor" }, /* 15 */ 111 { CS_SYSTEM, RO, "system" }, /* 16 */ 112 { CS_STABIL, RO, "stability" }, /* 17 */ 113 { CS_VARLIST, RO, "sys_var_list" }, /* 18 */ 114 { 0, EOV, "" } 115}; 116 117static struct ctl_var *ext_sys_var = (struct ctl_var *)0; 118 119/* 120 * System variables we print by default (in fuzzball order, more-or-less) 121 */ 122static u_char def_sys_var[] = { 123 CS_PROCESSOR, 124 CS_SYSTEM, 125 CS_LEAP, 126 CS_STRATUM, 127 CS_PRECISION, 128 CS_ROOTDELAY, 129 CS_ROOTDISPERSION, 130 CS_PEERID, 131 CS_REFID, 132 CS_REFTIME, 133 CS_POLL, 134 CS_CLOCK, 135 CS_STATE, 136 CS_OFFSET, 137 CS_DRIFT, 138 CS_COMPLIANCE, 139 CS_STABIL, 140 0 141}; 142 143 144/* 145 * Peer variable list 146 */ 147static struct ctl_var peer_var[] = { 148 { 0, PADDING, "" }, /* 0 */ 149 { CP_CONFIG, RO, "config" }, /* 1 */ 150 { CP_AUTHENABLE, RO, "authenable" }, /* 2 */ 151 { CP_AUTHENTIC, RO, "authentic" }, /* 3 */ 152 { CP_SRCADR, RO, "srcadr" }, /* 4 */ 153 { CP_SRCPORT, RO, "srcport" }, /* 5 */ 154 { CP_DSTADR, RO, "dstadr" }, /* 6 */ 155 { CP_DSTPORT, RO, "dstport" }, /* 7 */ 156 { CP_LEAP, RO, "leap" }, /* 8 */ 157 { CP_HMODE, RO, "hmode" }, /* 9 */ 158 { CP_STRATUM, RO, "stratum" }, /* 10 */ 159 { CP_PPOLL, RO, "ppoll" }, /* 11 */ 160 { CP_HPOLL, RO, "hpoll" }, /* 12 */ 161 { CP_PRECISION, RO, "precision" }, /* 13 */ 162 { CP_ROOTDELAY, RO, "rootdelay" }, /* 14 */ 163 { CP_ROOTDISPERSION, RO, "rootdispersion" }, /* 15 */ 164 { CP_REFID, RO, "refid" }, /* 16 */ 165 { CP_REFTIME, RO, "reftime" }, /* 17 */ 166 { CP_ORG, RO, "org" }, /* 18 */ 167 { CP_REC, RO, "rec" }, /* 19 */ 168 { CP_XMT, RO, "xmt" }, /* 20 */ 169 { CP_REACH, RO, "reach" }, /* 21 */ 170 { CP_VALID, RO, "valid" }, /* 22 */ 171 { CP_TIMER, RO, "timer" }, /* 23 */ 172 { CP_DELAY, RO, "delay" }, /* 24 */ 173 { CP_OFFSET, RO, "offset" }, /* 25 */ 174 { CP_JITTER, RO, "jitter" }, /* 26 */ 175 { CP_DISPERSION,RO, "dispersion" }, /* 27 */ 176 { CP_KEYID, RO, "keyid" }, /* 28 */ 177 { CP_FILTDELAY, RO, "filtdelay=" }, /* 29 */ 178 { CP_FILTOFFSET, RO, "filtoffset=" }, /* 30 */ 179 { CP_PMODE, RO, "pmode" }, /* 31 */ 180 { CP_RECEIVED, RO, "received"}, /* 32 */ 181 { CP_SENT, RO, "sent" }, /* 33 */ 182 { CP_FILTERROR, RO, "filtdisp=" }, /* 34 */ 183 { CP_FLASH, RO, "flash" }, /* 35 */ 184 { CP_DISP, PADDING,"" }, /* 36 */ 185 { CP_VARLIST, RO, "peer_var_list" }, /* 37 */ 186 { 0, EOV, "" } 187}; 188 189 190/* 191 * Peer variables we print by default 192 */ 193static u_char def_peer_var[] = { 194 CP_SRCADR, 195 CP_SRCPORT, 196 CP_DSTADR, 197 CP_DSTPORT, 198 CP_KEYID, 199 CP_STRATUM, 200 CP_PRECISION, 201 CP_ROOTDELAY, 202 CP_ROOTDISPERSION, 203 CP_REFID, 204 CP_REFTIME, 205 CP_DELAY, 206 CP_OFFSET, 207 CP_JITTER, 208 CP_DISPERSION, 209 CP_REACH, 210 CP_VALID, 211 CP_HMODE, 212 CP_PMODE, 213 CP_HPOLL, 214 CP_PPOLL, 215 CP_LEAP, 216 CP_FLASH, 217 CP_ORG, 218 CP_REC, 219 CP_XMT, 220 CP_FILTDELAY, 221 CP_FILTOFFSET, 222 CP_FILTERROR, 223 0 224}; 225 226 227#ifdef REFCLOCK 228/* 229 * Clock variable list 230 */ 231static struct ctl_var clock_var[] = { 232 { 0, PADDING, "" }, /* 0 */ 233 { CC_TYPE, RO, "type" }, /* 1 */ 234 { CC_TIMECODE, RO, "timecode" }, /* 2 */ 235 { CC_POLL, RO, "poll" }, /* 3 */ 236 { CC_NOREPLY, RO, "noreply" }, /* 4 */ 237 { CC_BADFORMAT, RO, "badformat" }, /* 5 */ 238 { CC_BADDATA, RO, "baddata" }, /* 6 */ 239 { CC_FUDGETIME1, RO, "fudgetime1" }, /* 7 */ 240 { CC_FUDGETIME2, RO, "fudgetime2" }, /* 8 */ 241 { CC_FUDGEVAL1, RO, "stratum" }, /* 9 */ 242 { CC_FUDGEVAL2, RO, "refid" }, /* 10 */ 243 { CC_FLAGS, RO, "flags" }, /* 11 */ 244 { CC_DEVICE, RO, "device" }, /* 12 */ 245 { CC_VARLIST, RO, "clock_var_list" },/* 13 */ 246 { 0, EOV, "" } 247}; 248 249 250/* 251 * Clock variables printed by default 252 */ 253static u_char def_clock_var[] = { 254 CC_DEVICE, 255 CC_TYPE, /* won't be output if device= known */ 256 CC_TIMECODE, 257 CC_POLL, 258 CC_NOREPLY, 259 CC_BADFORMAT, 260 CC_BADDATA, 261 CC_FUDGETIME1, 262 CC_FUDGETIME2, 263 CC_FUDGEVAL1, 264 CC_FUDGEVAL2, 265 CC_FLAGS, 266 0 267}; 268#endif 269 270 271/* 272 * System and processor definitions. These will change for the gizmo board. 273 */ 274#ifndef HAVE_UNAME 275# ifndef STR_SYSTEM 276# define STR_SYSTEM "UNIX" 277# endif 278# ifndef STR_PROCESSOR 279# define STR_PROCESSOR "unknown" 280# endif 281 282static char str_system[] = STR_SYSTEM; 283static char str_processor[] = STR_PROCESSOR; 284#else 285# include <sys/utsname.h> 286static struct utsname utsnamebuf; 287#endif /* HAVE_UNAME */ 288 289/* 290 * Trap structures. We only allow a few of these, and send 291 * a copy of each async message to each live one. Traps time 292 * out after an hour, it is up to the trap receipient to 293 * keep resetting it to avoid being timed out. 294 */ 295/* ntp_request.c */ 296struct ctl_trap ctl_trap[CTL_MAXTRAPS]; 297int num_ctl_traps; 298 299/* 300 * Type bits, for ctlsettrap() call. 301 */ 302#define TRAP_TYPE_CONFIG 0 /* used by configuration code */ 303#define TRAP_TYPE_PRIO 1 /* priority trap */ 304#define TRAP_TYPE_NONPRIO 2 /* nonpriority trap */ 305 306 307/* 308 * List relating reference clock types to control message time sources. 309 * Index by the reference clock type. 310 * This list will only be used iff the reference clock driver doesn't 311 * set peer->sstclktype to something different than CTL_SST_TS_UNSPEC. 312 */ 313static u_char clocktypes[] = { 314 CTL_SST_TS_NTP, /* REFCLK_NONE (0) */ 315 CTL_SST_TS_LOCAL, /* REFCLK_LOCALCLOCK (1) */ 316 CTL_SST_TS_UHF, /* REFCLK_GPS_TRAK (2) */ 317 CTL_SST_TS_HF, /* REFCLK_WWV_PST (3) */ 318 CTL_SST_TS_LF, /* REFCLK_WWVB_SPECTRACOM (4) */ 319 CTL_SST_TS_UHF, /* REFCLK_TRUETIME (5) */ 320 CTL_SST_TS_UHF, /* REFCLK_GOES_TRAK (6) */ 321 CTL_SST_TS_HF, /* REFCLK_CHU (7) */ 322 CTL_SST_TS_LF, /* REFCLOCK_PARSE (default) (8) */ 323 CTL_SST_TS_LF, /* REFCLK_GPS_MX4200 (9) */ 324 CTL_SST_TS_UHF, /* REFCLK_GPS_AS2201 (10) */ 325 CTL_SST_TS_UHF, /* REFCLK_GPS_ARBITER (11) */ 326 CTL_SST_TS_UHF, /* REFCLK_IRIG_TPRO (12) */ 327 CTL_SST_TS_ATOM, /* REFCLK_ATOM_LEITCH (13) */ 328 CTL_SST_TS_LF, /* REFCLK_MSF_EES (14) */ 329 CTL_SST_TS_UHF, /* REFCLK_TRUETIME (15) */ 330 CTL_SST_TS_UHF, /* REFCLK_IRIG_BANCOMM (16) */ 331 CTL_SST_TS_UHF, /* REFCLK_GPS_DATU (17) */ 332 CTL_SST_TS_TELEPHONE, /* REFCLK_NIST_ACTS (18) */ 333 CTL_SST_TS_HF, /* REFCLK_WWV_HEATH (19) */ 334 CTL_SST_TS_UHF, /* REFCLK_GPS_NMEA (20) */ 335 CTL_SST_TS_UHF, /* REFCLK_GPS_VME (21) */ 336 CTL_SST_TS_ATOM, /* REFCLK_ATOM_PPS (22) */ 337 CTL_SST_TS_TELEPHONE, /* REFCLK_PTB_ACTS (23) */ 338 CTL_SST_TS_TELEPHONE, /* REFCLK_USNO (24) */ 339 CTL_SST_TS_UHF, /* REFCLK_TRUETIME (25) */ 340 CTL_SST_TS_UHF, /* REFCLK_GPS_HP (26) */ 341 CTL_SST_TS_TELEPHONE, /* REFCLK_ARCRON_MSF (27) */ 342 CTL_SST_TS_TELEPHONE, /* REFCLK_SHM (28) */ 343 CTL_SST_TS_UHF, /* REFCLK_PALISADE (29) */ 344 CTL_SST_TS_UHF, /* REFCLK_ONCORE (30) */ 345 CTL_SST_TS_UHF, /* REFCLK_JUPITER (31) */ 346 CTL_SST_TS_LF, /* REFCLK_CHRONOLOG (32) */ 347 CTL_SST_TS_LF, /* REFCLK_DUMBCLOCK (32) */ 348 CTL_SST_TS_LF, /* REFCLK_ULINK (33) */ 349 CTL_SST_TS_LF, /* REFCLK_PCF (35) */ 350 CTL_SST_TS_LF, /* REFCLK_WWW (36) */ 351 CTL_SST_TS_LF, /* REFCLK_FG (37) */ 352}; 353 354 355/* 356 * Keyid used for authenticating write requests. 357 */ 358u_long ctl_auth_keyid; 359 360/* 361 * We keep track of the last error reported by the system internally 362 */ 363static u_char ctl_sys_last_event; 364static u_char ctl_sys_num_events; 365 366 367/* 368 * Statistic counters to keep track of requests and responses. 369 */ 370u_long ctltimereset; /* time stats reset */ 371u_long numctlreq; /* number of requests we've received */ 372u_long numctlbadpkts; /* number of bad control packets */ 373u_long numctlresponses; /* number of resp packets sent with data */ 374u_long numctlfrags; /* number of fragments sent */ 375u_long numctlerrors; /* number of error responses sent */ 376u_long numctltooshort; /* number of too short input packets */ 377u_long numctlinputresp; /* number of responses on input */ 378u_long numctlinputfrag; /* number of fragments on input */ 379u_long numctlinputerr; /* number of input pkts with err bit set */ 380u_long numctlbadoffset; /* number of input pkts with nonzero offset */ 381u_long numctlbadversion; /* number of input pkts with unknown version */ 382u_long numctldatatooshort; /* data too short for count */ 383u_long numctlbadop; /* bad op code found in packet */ 384u_long numasyncmsgs; /* number of async messages we've sent */ 385 386/* 387 * Response packet used by these routines. Also some state information 388 * so that we can handle packet formatting within a common set of 389 * subroutines. Note we try to enter data in place whenever possible, 390 * but the need to set the more bit correctly means we occasionally 391 * use the extra buffer and copy. 392 */ 393static struct ntp_control rpkt; 394static u_char res_version; 395static u_char res_opcode; 396static u_short res_associd; 397static int res_offset; 398static u_char * datapt; 399static u_char * dataend; 400static int datalinelen; 401static int datanotbinflag; 402static struct sockaddr_in *rmt_addr; 403static struct interface *lcl_inter; 404 405static u_char res_authenticate; 406static u_char res_authokay; 407static u_long res_keyid; 408 409#define MAXDATALINELEN (72) 410 411static u_char res_async; /* set to 1 if this is async trap response */ 412 413/* 414 * Pointers for saving state when decoding request packets 415 */ 416static char *reqpt; 417static char *reqend; 418 419/* 420 * init_control - initialize request data 421 */ 422void 423init_control(void) 424{ 425 int i; 426 427#ifdef HAVE_UNAME 428 uname(&utsnamebuf); 429#endif /* HAVE_UNAME */ 430 431 ctl_clr_stats(); 432 433 ctl_auth_keyid = 0; 434 ctl_sys_last_event = EVNT_UNSPEC; 435 ctl_sys_num_events = 0; 436 437 num_ctl_traps = 0; 438 for (i = 0; i < CTL_MAXTRAPS; i++) 439 ctl_trap[i].tr_flags = 0; 440} 441 442 443/* 444 * ctl_error - send an error response for the current request 445 */ 446static void 447ctl_error( 448 int errcode 449 ) 450{ 451#ifdef DEBUG 452 if (debug >= 4) 453 printf("sending control error %d\n", errcode); 454#endif 455 /* 456 * fill in the fields. We assume rpkt.sequence and rpkt.associd 457 * have already been filled in. 458 */ 459 rpkt.r_m_e_op = (u_char) (CTL_RESPONSE|CTL_ERROR|(res_opcode & CTL_OP_MASK)); 460 rpkt.status = htons((u_short) ((errcode<<8) & 0xff00)); 461 rpkt.count = 0; 462 463 /* 464 * send packet and bump counters 465 */ 466 if (res_authenticate && sys_authenticate) { 467 int maclen; 468 469 *(u_int32 *)((u_char *)&rpkt + CTL_HEADER_LEN) 470 = htonl(res_keyid); 471 maclen = authencrypt(res_keyid, (u_int32 *)&rpkt, 472 CTL_HEADER_LEN); 473 sendpkt(rmt_addr, lcl_inter, -2, (struct pkt *)&rpkt, 474 CTL_HEADER_LEN + maclen); 475 } else { 476 sendpkt(rmt_addr, lcl_inter, -3, (struct pkt *)&rpkt, 477 CTL_HEADER_LEN); 478 } 479 numctlerrors++; 480} 481 482 483/* 484 * process_control - process an incoming control message 485 */ 486void 487process_control( 488 struct recvbuf *rbufp, 489 int restrict_mask 490 ) 491{ 492 register struct ntp_control *pkt; 493 register int req_count; 494 register int req_data; 495 register struct ctl_proc *cc; 496 int properlen; 497 int maclen; 498 499#ifdef DEBUG 500 if (debug > 1) 501 printf("in process_control()\n"); 502#endif 503 504 /* 505 * Save the addresses for error responses 506 */ 507 numctlreq++; 508 rmt_addr = &rbufp->recv_srcadr; 509 lcl_inter = rbufp->dstadr; 510 pkt = (struct ntp_control *)&rbufp->recv_pkt; 511 512 /* 513 * If the length is less than required for the header, or 514 * it is a response or a fragment, ignore this. 515 */ 516 if (rbufp->recv_length < CTL_HEADER_LEN 517 || pkt->r_m_e_op & (CTL_RESPONSE|CTL_MORE|CTL_ERROR) 518 || pkt->offset != 0) { 519#ifdef DEBUG 520 if (debug) 521 printf("invalid format in control packet\n"); 522#endif 523 if (rbufp->recv_length < CTL_HEADER_LEN) 524 numctltooshort++; 525 if (pkt->r_m_e_op & CTL_RESPONSE) 526 numctlinputresp++; 527 if (pkt->r_m_e_op & CTL_MORE) 528 numctlinputfrag++; 529 if (pkt->r_m_e_op & CTL_ERROR) 530 numctlinputerr++; 531 if (pkt->offset != 0) 532 numctlbadoffset++; 533 return; 534 } 535 res_version = PKT_VERSION(pkt->li_vn_mode); 536 if (res_version > NTP_VERSION || res_version < NTP_OLDVERSION) { 537#ifdef DEBUG 538 if (debug) 539 printf("unknown version %d in control packet\n", 540 res_version); 541#endif 542 numctlbadversion++; 543 return; 544 } 545 546 /* 547 * Pull enough data from the packet to make intelligent responses 548 */ 549 rpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap, res_version, MODE_CONTROL); 550 res_opcode = pkt->r_m_e_op; 551 rpkt.sequence = pkt->sequence; 552 rpkt.associd = pkt->associd; 553 rpkt.status = 0; 554 res_offset = 0; 555 res_associd = htons(pkt->associd); 556 res_async = 0; 557 res_authenticate = 0; 558 res_keyid = 0; 559 res_authokay = 0; 560 req_count = (int)htons(pkt->count); 561 datanotbinflag = 0; 562 datalinelen = 0; 563 datapt = rpkt.data; 564 dataend = &(rpkt.data[CTL_MAX_DATA_LEN]); 565 566 /* 567 * We're set up now. Make sure we've got at least 568 * enough incoming data space to match the count. 569 */ 570 req_data = rbufp->recv_length - CTL_HEADER_LEN; 571 if (req_data < req_count || rbufp->recv_length & 0x3) { 572 ctl_error(CERR_BADFMT); 573 numctldatatooshort++; 574 return; 575 } 576 577 properlen = req_count + CTL_HEADER_LEN; 578#ifdef DEBUG 579 if (debug >= 2 && (rbufp->recv_length & 0x3) != 0) 580 printf("Packet length %d unrounded\n", rbufp->recv_length); 581#endif 582 /* round up proper len to a 8 octet boundary */ 583 584 properlen = (properlen + 7) & ~7; 585 maclen = rbufp->recv_length - properlen; 586 if ((rbufp->recv_length & (sizeof(u_long) - 1)) == 0 && 587 maclen >= MIN_MAC_LEN && maclen <= MAX_MAC_LEN && 588 sys_authenticate) { 589 res_authenticate = 1; 590 res_keyid = ntohl(*(u_int32 *)((u_char *)pkt + properlen)); 591 592#ifdef DEBUG 593 if (debug >= 3) 594 printf( 595 "recv_len %d, properlen %d, wants auth with keyid %ld, MAC length=%d\n", 596 rbufp->recv_length, properlen, res_keyid, maclen); 597#endif 598 if (!authistrusted(res_keyid)) { 599#ifdef DEBUG 600 if (debug >= 2) 601 printf("invalid keyid %lu\n", res_keyid); 602#endif 603 } else if (authdecrypt(res_keyid, (u_int32 *)pkt, 604 rbufp->recv_length - maclen, maclen)) { 605#ifdef DEBUG 606 if (debug >= 3) 607 printf("authenticated okay\n"); 608#endif 609 res_authokay = 1; 610 } else { 611#ifdef DEBUG 612 if (debug >= 3) 613 printf("authentication failed\n"); 614#endif 615 res_keyid = 0; 616 } 617 } 618 619 /* 620 * Set up translate pointers 621 */ 622 reqpt = (char *)pkt->data; 623 reqend = reqpt + req_count; 624 625 /* 626 * Look for the opcode processor 627 */ 628 for (cc = control_codes; cc->control_code != NO_REQUEST; cc++) { 629 if (cc->control_code == res_opcode) { 630#ifdef DEBUG 631 if (debug >= 2) 632 printf("opcode %d, found command handler\n", 633 res_opcode); 634#endif 635 if (cc->flags == AUTH && (!res_authokay 636 || res_keyid != ctl_auth_keyid)) { 637 ctl_error(CERR_PERMISSION); 638 return; 639 } 640 (cc->handler)(rbufp, restrict_mask); 641 return; 642 } 643 } 644 645 /* 646 * Can't find this one, return an error. 647 */ 648 numctlbadop++; 649 ctl_error(CERR_BADOP); 650 return; 651} 652 653 654/* 655 * ctlpeerstatus - return a status word for this peer 656 */ 657u_short 658ctlpeerstatus( 659 register struct peer *peer 660 ) 661{ 662 register u_short status; 663 664 status = peer->status; 665 if (peer->flags & FLAG_CONFIG) 666 status |= CTL_PST_CONFIG; 667 if (peer->flags & FLAG_AUTHENABLE) 668 status |= CTL_PST_AUTHENABLE; 669 if (peer->flags & FLAG_AUTHENTIC) 670 status |= CTL_PST_AUTHENTIC; 671 if (peer->reach != 0) 672 status |= CTL_PST_REACH; 673 return (u_short)CTL_PEER_STATUS(status, peer->num_events, 674 peer->last_event); 675} 676 677 678/* 679 * ctlclkstatus - return a status word for this clock 680 */ 681static u_short 682ctlclkstatus( 683 struct refclockstat *this_clock 684 ) 685{ 686 return ((u_short)(this_clock->currentstatus) << 8) 687 | (u_short)(this_clock->lastevent); 688} 689 690 691 692/* 693 * ctlsysstatus - return the system status word 694 */ 695u_short 696ctlsysstatus(void) 697{ 698 register u_char this_clock; 699 700 this_clock = CTL_SST_TS_UNSPEC; 701 if (sys_peer != 0) { 702 if (sys_peer->sstclktype != CTL_SST_TS_UNSPEC) { 703 this_clock = sys_peer->sstclktype; 704 if (pps_control) 705 this_clock |= CTL_SST_TS_PPS; 706 } else { 707 if (sys_peer->refclktype < sizeof(clocktypes)) 708 this_clock = clocktypes[sys_peer->refclktype]; 709 if (pps_control) 710 this_clock |= CTL_SST_TS_PPS; 711 } 712 } 713 return (u_short)CTL_SYS_STATUS(sys_leap, this_clock, 714 ctl_sys_num_events, ctl_sys_last_event); 715} 716 717 718 719/* 720 * ctl_flushpkt - write out the current packet and prepare 721 * another if necessary. 722 */ 723static void 724ctl_flushpkt( 725 int more 726 ) 727{ 728 int dlen; 729 int sendlen; 730 731 if (!more && datanotbinflag) { 732 /* 733 * Big hack, output a trailing \r\n 734 */ 735 *datapt++ = '\r'; 736 *datapt++ = '\n'; 737 } 738 dlen = datapt - (u_char *)rpkt.data; 739 sendlen = dlen + CTL_HEADER_LEN; 740 741 /* 742 * Pad to a multiple of 32 bits 743 */ 744 while (sendlen & 0x3) { 745 *datapt++ = '\0'; 746 sendlen++; 747 } 748 749 /* 750 * Fill in the packet with the current info 751 */ 752 rpkt.r_m_e_op = (u_char)(CTL_RESPONSE|more|(res_opcode & CTL_OP_MASK)); 753 rpkt.count = htons((u_short) dlen); 754 rpkt.offset = htons( (u_short) res_offset); 755 if (res_async) { 756 register int i; 757 758 for (i = 0; i < CTL_MAXTRAPS; i++) { 759 if (ctl_trap[i].tr_flags & TRAP_INUSE) { 760 rpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap, 761 ctl_trap[i].tr_version, MODE_CONTROL); 762 rpkt.sequence = htons(ctl_trap[i].tr_sequence); 763 sendpkt(&ctl_trap[i].tr_addr, 764 ctl_trap[i].tr_localaddr, 765 -4, 766 (struct pkt *)&rpkt, sendlen); 767 if (!more) 768 ctl_trap[i].tr_sequence++; 769 numasyncmsgs++; 770 } 771 } 772 } else { 773 if (res_authenticate && sys_authenticate) { 774 int maclen; 775 int totlen = sendlen; 776 u_long keyid = htonl(res_keyid); 777 778 /* 779 * If we are going to authenticate, then there is 780 * an additional requirement that the MAC begin on 781 * a 64 bit boundary. 782 */ 783 while (totlen & 7) { 784 *datapt++ = '\0'; 785 totlen++; 786 } 787 memcpy(datapt, &keyid, sizeof keyid); 788 maclen = authencrypt(res_keyid, (u_int32 *)&rpkt, 789 totlen); 790 sendpkt(rmt_addr, lcl_inter, -5, (struct pkt *)&rpkt, 791 totlen + maclen); 792 } else { 793 sendpkt(rmt_addr, lcl_inter, -6, (struct pkt *)&rpkt, 794 sendlen); 795 } 796 if (more) 797 numctlfrags++; 798 else 799 numctlresponses++; 800 } 801 802 /* 803 * Set us up for another go around. 804 */ 805 res_offset += dlen; 806 datapt = (u_char *)rpkt.data; 807} 808 809 810/* 811 * ctl_putdata - write data into the packet, fragmenting and 812 * starting another if this one is full. 813 */ 814static void 815ctl_putdata( 816 const char *dp, 817 unsigned int dlen, 818 int bin /* set to 1 when data is binary */ 819 ) 820{ 821 int overhead; 822 823 overhead = 0; 824 if (!bin) { 825 datanotbinflag = 1; 826 overhead = 3; 827 if (datapt != rpkt.data) { 828 *datapt++ = ','; 829 datalinelen++; 830 if ((dlen + datalinelen + 1) >= MAXDATALINELEN) { 831 *datapt++ = '\r'; 832 *datapt++ = '\n'; 833 datalinelen = 0; 834 } else { 835 *datapt++ = ' '; 836 datalinelen++; 837 } 838 } 839 } 840 841 /* 842 * Save room for trailing junk 843 */ 844 if (dlen + overhead + datapt > dataend) { 845 /* 846 * Not enough room in this one, flush it out. 847 */ 848 ctl_flushpkt(CTL_MORE); 849 } 850 851 memmove((char *)datapt, dp, (unsigned)dlen); 852 datapt += dlen; 853 datalinelen += dlen; 854} 855 856 857/* 858 * ctl_putstr - write a tagged string into the response packet 859 */ 860static void 861ctl_putstr( 862 const char *tag, 863 const char *data, 864 unsigned int len 865 ) 866{ 867 register char *cp; 868 register const char *cq; 869 char buffer[400]; 870 871 cp = buffer; 872 cq = tag; 873 while (*cq != '\0') 874 *cp++ = *cq++; 875 876 if (len > 0) { 877 *cp++ = '='; 878 *cp++ = '"'; 879 if (len > (int) (sizeof(buffer) - (cp - buffer) - 1)) 880 len = sizeof(buffer) - (cp - buffer) - 1; 881 memmove(cp, data, (unsigned)len); 882 cp += len; 883 *cp++ = '"'; 884 } 885 886 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0); 887} 888 889 890/* 891 * ctl_putdbl - write a tagged, signed double into the response packet 892 */ 893static void 894ctl_putdbl( 895 const char *tag, 896 double ts 897 ) 898{ 899 register char *cp; 900 register const char *cq; 901 char buffer[200]; 902 903 cp = buffer; 904 cq = tag; 905 while (*cq != '\0') 906 *cp++ = *cq++; 907 *cp++ = '='; 908 (void)sprintf(cp, "%.3f", ts); 909 while (*cp != '\0') 910 cp++; 911 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0); 912} 913 914/* 915 * ctl_putuint - write a tagged unsigned integer into the response 916 */ 917static void 918ctl_putuint( 919 const char *tag, 920 u_long uval 921 ) 922{ 923 register char *cp; 924 register const char *cq; 925 char buffer[200]; 926 927 cp = buffer; 928 cq = tag; 929 while (*cq != '\0') 930 *cp++ = *cq++; 931 932 *cp++ = '='; 933 (void) sprintf(cp, "%lu", uval); 934 while (*cp != '\0') 935 cp++; 936 937 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0); 938} 939 940 941/* 942 * ctl_puthex - write a tagged unsigned integer, in hex, into the response 943 */ 944static void 945ctl_puthex( 946 const char *tag, 947 u_long uval 948 ) 949{ 950 register char *cp; 951 register const char *cq; 952 char buffer[200]; 953 954 cp = buffer; 955 cq = tag; 956 while (*cq != '\0') 957 *cp++ = *cq++; 958 959 *cp++ = '='; 960 (void) sprintf(cp, "0x%lx", uval); 961 while (*cp != '\0') 962 cp++; 963 964 ctl_putdata(buffer,(unsigned)( cp - buffer ), 0); 965} 966 967 968/* 969 * ctl_putint - write a tagged signed integer into the response 970 */ 971static void 972ctl_putint( 973 const char *tag, 974 long ival 975 ) 976{ 977 register char *cp; 978 register const char *cq; 979 char buffer[200]; 980 981 cp = buffer; 982 cq = tag; 983 while (*cq != '\0') 984 *cp++ = *cq++; 985 986 *cp++ = '='; 987 (void) sprintf(cp, "%ld", ival); 988 while (*cp != '\0') 989 cp++; 990 991 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0); 992} 993 994 995/* 996 * ctl_putts - write a tagged timestamp, in hex, into the response 997 */ 998static void 999ctl_putts( 1000 const char *tag, 1001 l_fp *ts 1002 ) 1003{ 1004 register char *cp; 1005 register const char *cq; 1006 char buffer[200]; 1007 1008 cp = buffer; 1009 cq = tag; 1010 while (*cq != '\0') 1011 *cp++ = *cq++; 1012 1013 *cp++ = '='; 1014 (void) sprintf(cp, "0x%08lx.%08lx", ts->l_ui & 0xffffffffL, 1015 ts->l_uf & 0xffffffffL); 1016 while (*cp != '\0') 1017 cp++; 1018 1019 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0); 1020} 1021 1022 1023/* 1024 * ctl_putadr - write a dotted quad IP address into the response 1025 */ 1026static void 1027ctl_putadr( 1028 const char *tag, 1029 u_int32 addr 1030 ) 1031{ 1032 register char *cp; 1033 register const char *cq; 1034 char buffer[200]; 1035 1036 cp = buffer; 1037 cq = tag; 1038 while (*cq != '\0') 1039 *cp++ = *cq++; 1040 1041 *cp++ = '='; 1042 cq = numtoa(addr); 1043 while (*cq != '\0') 1044 *cp++ = *cq++; 1045 1046 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0); 1047} 1048 1049 1050/* 1051 * ctl_putid - write a tagged clock ID into the response 1052 */ 1053static void 1054ctl_putid( 1055 const char *tag, 1056 char *id 1057 ) 1058{ 1059 register char *cp; 1060 register const char *cq; 1061 char buffer[200]; 1062 1063 cp = buffer; 1064 cq = tag; 1065 while (*cq != '\0') 1066 *cp++ = *cq++; 1067 1068 *cp++ = '='; 1069 cq = id; 1070 while (*cq != '\0' && (cq - id) < 4) 1071 *cp++ = *cq++; 1072 1073 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0); 1074} 1075 1076 1077/* 1078 * ctl_putarray - write a tagged eight element double array into the response 1079 */ 1080static void 1081ctl_putarray( 1082 const char *tag, 1083 double *arr, 1084 int start 1085 ) 1086{ 1087 register char *cp; 1088 register const char *cq; 1089 char buffer[200]; 1090 int i; 1091 1092 cp = buffer; 1093 cq = tag; 1094 while (*cq != '\0') 1095 *cp++ = *cq++; 1096 i = start; 1097 do { 1098 if (i == 0) 1099 i = NTP_SHIFT; 1100 i--; 1101 (void)sprintf(cp, " %.2f", arr[i] * 1e3); 1102 while (*cp != '\0') 1103 cp++; 1104 } while(i != start); 1105 ctl_putdata(buffer, (unsigned)(cp - buffer), 0); 1106} 1107 1108 1109/* 1110 * ctl_putsys - output a system variable 1111 */ 1112static void 1113ctl_putsys( 1114 int varid 1115 ) 1116{ 1117 l_fp tmp; 1118#ifdef HAVE_UNAME 1119 char str[50]; 1120#endif 1121 1122 switch (varid) { 1123 case CS_LEAP: 1124 ctl_putuint(sys_var[CS_LEAP].text, sys_leap); 1125 break; 1126 case CS_STRATUM: 1127 ctl_putuint(sys_var[CS_STRATUM].text, sys_stratum); 1128 break; 1129 case CS_PRECISION: 1130 ctl_putint(sys_var[CS_PRECISION].text, sys_precision); 1131 break; 1132 case CS_ROOTDELAY: 1133 ctl_putdbl(sys_var[CS_ROOTDELAY].text, sys_rootdelay * 1e3); 1134 break; 1135 case CS_ROOTDISPERSION: 1136 ctl_putdbl(sys_var[CS_ROOTDISPERSION].text, 1137 sys_rootdispersion * 1e3); 1138 break; 1139 case CS_REFID: 1140 if (sys_stratum > 1) 1141 ctl_putadr(sys_var[CS_REFID].text, sys_refid); 1142 else 1143 ctl_putid(sys_var[CS_REFID].text, (char *)&sys_refid); 1144 break; 1145 case CS_REFTIME: 1146 ctl_putts(sys_var[CS_REFTIME].text, &sys_reftime); 1147 break; 1148 case CS_POLL: 1149 ctl_putuint(sys_var[CS_POLL].text, sys_poll); 1150 break; 1151 case CS_PEERID: 1152 if (sys_peer == NULL) 1153 ctl_putuint(sys_var[CS_PEERID].text, 0); 1154 else 1155 ctl_putuint(sys_var[CS_PEERID].text, 1156 sys_peer->associd); 1157 break; 1158 case CS_STATE: 1159 ctl_putuint(sys_var[CS_STATE].text, (unsigned)state); 1160 break; 1161 case CS_OFFSET: 1162 ctl_putdbl(sys_var[CS_OFFSET].text, last_offset * 1e3); 1163 break; 1164 case CS_DRIFT: 1165 ctl_putdbl(sys_var[CS_DRIFT].text, drift_comp * 1e6); 1166 break; 1167 case CS_COMPLIANCE: 1168 ctl_putdbl(sys_var[CS_COMPLIANCE].text, sys_error * 1e3); 1169 break; 1170 case CS_CLOCK: 1171 get_systime(&tmp); 1172 ctl_putts(sys_var[CS_CLOCK].text, &tmp); 1173 break; 1174 case CS_PROCESSOR: 1175#ifndef HAVE_UNAME 1176 ctl_putstr(sys_var[CS_PROCESSOR].text, str_processor, 1177 sizeof(str_processor) - 1); 1178#else 1179 ctl_putstr(sys_var[CS_PROCESSOR].text, utsnamebuf.machine, 1180 strlen(utsnamebuf.machine)); 1181#endif /* HAVE_UNAME */ 1182 break; 1183 case CS_SYSTEM: 1184#ifndef HAVE_UNAME 1185 ctl_putstr(sys_var[CS_SYSTEM].text, str_system, 1186 sizeof(str_system) - 1); 1187#else 1188 (void)strcpy(str, utsnamebuf.sysname); 1189 (void)strcat(str, utsnamebuf.release); 1190 ctl_putstr(sys_var[CS_SYSTEM].text, str, strlen(str)); 1191#endif /* HAVE_UNAME */ 1192 break; 1193 case CS_STABIL: 1194 ctl_putdbl(sys_var[CS_STABIL].text, clock_stability * 1e6); 1195 break; 1196 case CS_VARLIST: 1197 { 1198 char buf[CTL_MAX_DATA_LEN]; 1199 register char *s, *t, *be; 1200 register const char *ss; 1201 register int i; 1202 register struct ctl_var *k; 1203 1204 s = buf; 1205 be = buf + sizeof(buf) - strlen(sys_var[CS_VARLIST].text) - 4; 1206 if (s > be) 1207 break; /* really long var name 8-( - Killer */ 1208 1209 strcpy(s, sys_var[CS_VARLIST].text); 1210 strcat(s, "=\""); 1211 s += strlen(s); 1212 t = s; 1213 1214 for (k = sys_var; !(k->flags &EOV); k++) 1215 { 1216 if (k->flags & PADDING) 1217 continue; 1218 1219 i = strlen(k->text); 1220 if (s+i+1 >= be) 1221 break; 1222 if (s != t) 1223 *s++ = ','; 1224 strcpy(s, k->text); 1225 s += i; 1226 } 1227 1228 for (k = ext_sys_var; k && !(k->flags &EOV); k++) 1229 { 1230 if (k->flags & PADDING) 1231 continue; 1232 1233 ss = k->text; 1234 if (!ss) 1235 continue; 1236 1237 while (*ss && *ss != '=') 1238 ss++; 1239 1240 i = ss - k->text; 1241 if (s+i+1 >= be) 1242 break; 1243 if (s != t) 1244 *s++ = ','; 1245 strncpy(s, k->text, (unsigned)i); 1246 s += i; 1247 } 1248 1249 if (s+2 >= be) 1250 break; 1251 1252 *s++ = '"'; 1253 *s = '\0'; 1254 1255 ctl_putdata(buf, (unsigned)( s - buf ), 0); 1256 } 1257 break; 1258 } 1259} 1260 1261 1262/* 1263 * ctl_putpeer - output a peer variable 1264 */ 1265static void 1266ctl_putpeer( 1267 int varid, 1268 struct peer *peer 1269 ) 1270{ 1271 switch (varid) { 1272 case CP_CONFIG: 1273 ctl_putuint(peer_var[CP_CONFIG].text, 1274 (unsigned)((peer->flags & FLAG_CONFIG) != 0)); 1275 break; 1276 case CP_AUTHENABLE: 1277 ctl_putuint(peer_var[CP_AUTHENABLE].text, 1278 (unsigned)((peer->flags & FLAG_AUTHENABLE) != 0)); 1279 break; 1280 case CP_AUTHENTIC: 1281 ctl_putuint(peer_var[CP_AUTHENTIC].text, 1282 (unsigned)((peer->flags & FLAG_AUTHENTIC) != 0)); 1283 break; 1284 case CP_SRCADR: 1285 ctl_putadr(peer_var[CP_SRCADR].text, 1286 peer->srcadr.sin_addr.s_addr); 1287 break; 1288 case CP_SRCPORT: 1289 ctl_putuint(peer_var[CP_SRCPORT].text, 1290 ntohs(peer->srcadr.sin_port)); 1291 break; 1292 case CP_DSTADR: 1293 ctl_putadr(peer_var[CP_DSTADR].text, 1294 peer->processed ? 1295 peer->cast_flags & MDF_BCAST ? 1296 peer->dstadr->bcast.sin_addr.s_addr: 1297 peer->cast_flags ? 1298 peer->dstadr->sin.sin_addr.s_addr ? 1299 peer->dstadr->sin.sin_addr.s_addr: 1300 peer->dstadr->bcast.sin_addr.s_addr: 1301 8 : 12); 1302 break; 1303 case CP_DSTPORT: 1304 ctl_putuint(peer_var[CP_DSTPORT].text, 1305 (u_long)(peer->dstadr 1306 ? ntohs(peer->dstadr->sin.sin_port) 1307 : 0 1308 ) 1309 ); 1310 break; 1311 case CP_LEAP: 1312 ctl_putuint(peer_var[CP_LEAP].text, peer->leap); 1313 break; 1314 case CP_HMODE: 1315 ctl_putuint(peer_var[CP_HMODE].text, peer->hmode); 1316 break; 1317 case CP_STRATUM: 1318 ctl_putuint(peer_var[CP_STRATUM].text, peer->stratum); 1319 break; 1320 case CP_PPOLL: 1321 ctl_putuint(peer_var[CP_PPOLL].text, peer->ppoll); 1322 break; 1323 case CP_HPOLL: 1324 ctl_putuint(peer_var[CP_HPOLL].text, peer->hpoll); 1325 break; 1326 case CP_PRECISION: 1327 ctl_putint(peer_var[CP_PRECISION].text, peer->precision); 1328 break; 1329 case CP_ROOTDELAY: 1330 ctl_putdbl(peer_var[CP_ROOTDELAY].text, peer->rootdelay * 1e3); 1331 break; 1332 case CP_ROOTDISPERSION: 1333 ctl_putdbl(peer_var[CP_ROOTDISPERSION].text, 1334 peer->rootdispersion * 1e3); 1335 break; 1336 case CP_REFID: 1337 if (peer->stratum > 1) 1338 { 1339 if (peer->flags & FLAG_REFCLOCK) 1340 ctl_putadr(peer_var[CP_REFID].text, 1341 peer->srcadr.sin_addr.s_addr); 1342 else 1343 ctl_putadr(peer_var[CP_REFID].text, 1344 peer->refid); 1345 } 1346 else 1347 ctl_putid(peer_var[CP_REFID].text, 1348 (char *)&peer->refid); 1349 break; 1350 case CP_REFTIME: 1351 ctl_putts(peer_var[CP_REFTIME].text, &peer->reftime); 1352 break; 1353 case CP_ORG: 1354 ctl_putts(peer_var[CP_ORG].text, &peer->org); 1355 break; 1356 case CP_REC: 1357 ctl_putts(peer_var[CP_REC].text, &peer->rec); 1358 break; 1359 case CP_XMT: 1360 ctl_putts(peer_var[CP_XMT].text, &peer->xmt); 1361 break; 1362 case CP_REACH: 1363 ctl_puthex(peer_var[CP_REACH].text, peer->reach); 1364 break; 1365 case CP_FLASH: 1366 ctl_puthex(peer_var[CP_FLASH].text, peer->flash); 1367 break; 1368 case CP_VALID: 1369 ctl_putuint(peer_var[CP_VALID].text, peer->valid); 1370 break; 1371 case CP_TIMER: 1372 ctl_putuint(peer_var[CP_TIMER].text, 1373 peer->nextdate - current_time); 1374 break; 1375 case CP_DELAY: 1376 ctl_putdbl(peer_var[CP_DELAY].text, peer->delay * 1e3); 1377 break; 1378 case CP_OFFSET: 1379 ctl_putdbl(peer_var[CP_OFFSET].text, peer->offset * 1e3); 1380 break; 1381 case CP_JITTER: 1382 ctl_putdbl(peer_var[CP_JITTER].text, 1383 SQRT(peer->variance) * 1e3); 1384 break; 1385 case CP_DISPERSION: 1386 ctl_putdbl(peer_var[CP_DISPERSION].text, peer->disp * 1e3); 1387 break; 1388 case CP_KEYID: 1389 ctl_putuint(peer_var[CP_KEYID].text, peer->keyid); 1390 break; 1391 case CP_FILTDELAY: 1392 ctl_putarray(peer_var[CP_FILTDELAY].text, 1393 peer->filter_delay, (int)peer->filter_nextpt); 1394 break; 1395 case CP_FILTOFFSET: 1396 ctl_putarray(peer_var[CP_FILTOFFSET].text, 1397 peer->filter_offset, (int)peer->filter_nextpt); 1398 break; 1399 case CP_FILTERROR: 1400 ctl_putarray(peer_var[CP_FILTERROR].text, 1401 peer->filter_disp, (int)peer->filter_nextpt); 1402 break; 1403 case CP_PMODE: 1404 ctl_putuint(peer_var[CP_PMODE].text, peer->pmode); 1405 break; 1406 case CP_RECEIVED: 1407 ctl_putuint(peer_var[CP_RECEIVED].text, peer->received); 1408 break; 1409 case CP_SENT: 1410 ctl_putuint(peer_var[CP_SENT].text, peer->sent); 1411 break; 1412 case CP_VARLIST: 1413 { 1414 char buf[CTL_MAX_DATA_LEN]; 1415 register char *s, *t, *be; 1416 register int i; 1417 register struct ctl_var *k; 1418 1419 s = buf; 1420 be = buf + sizeof(buf) - strlen(peer_var[CP_VARLIST].text) - 4; 1421 if (s > be) 1422 break; /* really long var name 8-( - Killer */ 1423 1424 strcpy(s, peer_var[CP_VARLIST].text); 1425 strcat(s, "=\""); 1426 s += strlen(s); 1427 t = s; 1428 1429 for (k = peer_var; !(k->flags &EOV); k++) 1430 { 1431 if (k->flags & PADDING) 1432 continue; 1433 1434 i = strlen(k->text); 1435 if (s+i+1 >= be) 1436 break; 1437 if (s != t) 1438 *s++ = ','; 1439 strcpy(s, k->text); 1440 s += i; 1441 } 1442 1443 if (s+2 >= be) 1444 break; 1445 1446 *s++ = '"'; 1447 *s = '\0'; 1448 1449 ctl_putdata(buf, (unsigned)(s - buf), 0); 1450 } 1451 break; 1452 } 1453} 1454 1455 1456#ifdef REFCLOCK 1457/* 1458 * ctl_putclock - output clock variables 1459 */ 1460static void 1461ctl_putclock( 1462 int varid, 1463 struct refclockstat *clock_stat, 1464 int mustput 1465 ) 1466{ 1467 switch(varid) { 1468 case CC_TYPE: 1469 if (mustput || clock_stat->clockdesc == NULL 1470 || *(clock_stat->clockdesc) == '\0') { 1471 ctl_putuint(clock_var[CC_TYPE].text, clock_stat->type); 1472 } 1473 break; 1474 case CC_TIMECODE: 1475 ctl_putstr(clock_var[CC_TIMECODE].text, clock_stat->p_lastcode, 1476 (unsigned)clock_stat->lencode); 1477 break; 1478 case CC_POLL: 1479 ctl_putuint(clock_var[CC_POLL].text, clock_stat->polls); 1480 break; 1481 case CC_NOREPLY: 1482 ctl_putuint(clock_var[CC_NOREPLY].text, clock_stat->noresponse); 1483 break; 1484 case CC_BADFORMAT: 1485 ctl_putuint(clock_var[CC_BADFORMAT].text, clock_stat->badformat); 1486 break; 1487 case CC_BADDATA: 1488 ctl_putuint(clock_var[CC_BADDATA].text, clock_stat->baddata); 1489 break; 1490 case CC_FUDGETIME1: 1491 if (mustput || (clock_stat->haveflags & CLK_HAVETIME1)) { 1492 ctl_putdbl(clock_var[CC_FUDGETIME1].text, 1493 clock_stat->fudgetime1 * 1e3); 1494 } 1495 break; 1496 case CC_FUDGETIME2: 1497 if (mustput || (clock_stat->haveflags & CLK_HAVETIME2)) { 1498 ctl_putdbl(clock_var[CC_FUDGETIME2].text, 1499 clock_stat->fudgetime2 * 1e3); 1500 } 1501 break; 1502 case CC_FUDGEVAL1: 1503 if (mustput || (clock_stat->haveflags & CLK_HAVEVAL1)) 1504 ctl_putint(clock_var[CC_FUDGEVAL1].text, 1505 clock_stat->fudgeval1); 1506 break; 1507 case CC_FUDGEVAL2: 1508 if (mustput || (clock_stat->haveflags & CLK_HAVEVAL2)) { 1509 if (clock_stat->fudgeval1 > 1) 1510 ctl_putadr(clock_var[CC_FUDGEVAL2].text, 1511 (u_int32)clock_stat->fudgeval2); 1512 else 1513 ctl_putid(clock_var[CC_FUDGEVAL2].text, 1514 (char *)&clock_stat->fudgeval2); 1515 } 1516 break; 1517 case CC_FLAGS: 1518 if (mustput || (clock_stat->haveflags & 1519 (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4))) 1520 ctl_putuint(clock_var[CC_FLAGS].text, clock_stat->flags); 1521 break; 1522 case CC_DEVICE: 1523 if (clock_stat->clockdesc == NULL || *(clock_stat->clockdesc) == '\0') { 1524 if (mustput) 1525 ctl_putstr(clock_var[CC_DEVICE].text, "", 0); 1526 } else { 1527 ctl_putstr(clock_var[CC_DEVICE].text, clock_stat->clockdesc, 1528 strlen(clock_stat->clockdesc)); 1529 } 1530 break; 1531 case CC_VARLIST: 1532 { 1533 char buf[CTL_MAX_DATA_LEN]; 1534 register char *s, *t, *be; 1535 register const char *ss; 1536 register int i; 1537 register struct ctl_var *k; 1538 1539 s = buf; 1540 be = buf + sizeof(buf); 1541 if (s + strlen(clock_var[CC_VARLIST].text) + 4 > be) 1542 break; /* really long var name 8-( - Killer */ 1543 1544 strcpy(s, clock_var[CC_VARLIST].text); 1545 strcat(s, "=\""); 1546 s += strlen(s); 1547 t = s; 1548 1549 for (k = clock_var; !(k->flags &EOV); k++) 1550 { 1551 if (k->flags & PADDING) 1552 continue; 1553 1554 i = strlen(k->text); 1555 if (s+i+1 >= be) 1556 break; 1557 if (s != t) 1558 *s++ = ','; 1559 strcpy(s, k->text); 1560 s += i; 1561 } 1562 1563 for (k = clock_stat->kv_list; k && !(k->flags &EOV); k++) 1564 { 1565 if (k->flags & PADDING) 1566 continue; 1567 1568 ss = k->text; 1569 if (!ss) 1570 continue; 1571 1572 while (*ss && *ss != '=') 1573 ss++; 1574 1575 i = ss - k->text; 1576 if (s+i+1 >= be) 1577 break; 1578 if (s != t) 1579 *s++ = ','; 1580 strncpy(s, k->text, (unsigned)i); 1581 s += i; 1582 *s = '\0'; 1583 } 1584 1585 if (s+2 >= be) 1586 break; 1587 1588 *s++ = '"'; 1589 *s = '\0'; 1590 1591 ctl_putdata(buf, (unsigned)( s - buf ), 0); 1592 } 1593 break; 1594 } 1595} 1596#endif 1597 1598 1599 1600/* 1601 * ctl_getitem - get the next data item from the incoming packet 1602 */ 1603static struct ctl_var * 1604ctl_getitem( 1605 struct ctl_var *var_list, 1606 char **data 1607 ) 1608{ 1609 register struct ctl_var *v; 1610 register char *cp; 1611 register char *tp; 1612 static struct ctl_var eol = { 0, EOV, }; 1613 static char buf[128]; 1614 1615 /* 1616 * Delete leading commas and white space 1617 */ 1618 while (reqpt < reqend && (*reqpt == ',' || isspace((unsigned char)*reqpt))) { 1619 reqpt++; 1620 } 1621 1622 if (reqpt >= reqend) 1623 return 0; 1624 1625 if (var_list == (struct ctl_var *)0) 1626 return &eol; 1627 1628 /* 1629 * Look for a first character match on the tag. If we find 1630 * one, see if it is a full match. 1631 */ 1632 v = var_list; 1633 cp = reqpt; 1634 while (!(v->flags & EOV)) { 1635 if (!(v->flags & PADDING) && *cp == *(v->text)) { 1636 tp = v->text; 1637 while (*tp != '\0' && *tp != '=' && cp < reqend && *cp == *tp) { 1638 cp++; 1639 tp++; 1640 } 1641 if ((*tp == '\0') || (*tp == '=')) { 1642 while (cp < reqend && isspace((unsigned char)*cp)) 1643 cp++; 1644 if (cp == reqend || *cp == ',') { 1645 buf[0] = '\0'; 1646 *data = buf; 1647 if (cp < reqend) 1648 cp++; 1649 reqpt = cp; 1650 return v; 1651 } 1652 if (*cp == '=') { 1653 cp++; 1654 tp = buf; 1655 while (cp < reqend && isspace((unsigned char)*cp)) 1656 cp++; 1657 while (cp < reqend && *cp != ',') { 1658 *tp++ = *cp++; 1659 if (tp >= buf + sizeof(buf)) { 1660 msyslog(LOG_WARNING, "Attempted \"ntpdx\" exploit from IP %d.%d.%d.%d:%d (possibly spoofed)\n", 1661 (ntohl(rmt_addr->sin_addr.s_addr) >> 24) & 0xff, 1662 (ntohl(rmt_addr->sin_addr.s_addr) >> 16) & 0xff, 1663 (ntohl(rmt_addr->sin_addr.s_addr) >> 8) & 0xff, 1664 (ntohl(rmt_addr->sin_addr.s_addr) >> 0) & 0xff, 1665 ntohs(rmt_addr->sin_port) 1666); 1667 1668 return (0); 1669 } 1670 } 1671 if (cp < reqend) 1672 cp++; 1673 *tp = '\0'; 1674 while (tp != buf && isspace((unsigned char)(*(tp-1)))) 1675 *(--tp) = '\0'; 1676 reqpt = cp; 1677 *data = buf; 1678 return v; 1679 } 1680 } 1681 cp = reqpt; 1682 } 1683 v++; 1684 } 1685 return v; 1686} 1687 1688 1689/* 1690 * control_unspec - response to an unspecified op-code 1691 */ 1692/*ARGSUSED*/ 1693static void 1694control_unspec( 1695 struct recvbuf *rbufp, 1696 int restrict_mask 1697 ) 1698{ 1699 struct peer *peer; 1700 1701 /* 1702 * What is an appropriate response to an unspecified op-code? 1703 * I return no errors and no data, unless a specified assocation 1704 * doesn't exist. 1705 */ 1706 if (res_associd != 0) { 1707 if ((peer = findpeerbyassoc((int)res_associd)) == 0) { 1708 ctl_error(CERR_BADASSOC); 1709 return; 1710 } 1711 rpkt.status = htons(ctlpeerstatus(peer)); 1712 } else { 1713 rpkt.status = htons(ctlsysstatus()); 1714 } 1715 ctl_flushpkt(0); 1716} 1717 1718 1719/* 1720 * read_status - return either a list of associd's, or a particular 1721 * peer's status. 1722 */ 1723/*ARGSUSED*/ 1724static void 1725read_status( 1726 struct recvbuf *rbufp, 1727 int restrict_mask 1728 ) 1729{ 1730 register int i; 1731 register struct peer *peer; 1732 u_short ass_stat[CTL_MAX_DATA_LEN/sizeof(u_short)]; 1733 1734#ifdef DEBUG 1735 if (debug >= 2) 1736 printf("read_status: ID %d\n", res_associd); 1737#endif 1738 /* 1739 * Two choices here. If the specified association ID is 1740 * zero we return all known assocation ID's. Otherwise 1741 * we return a bunch of stuff about the particular peer. 1742 */ 1743 if (res_associd == 0) { 1744 register int n; 1745 1746 n = 0; 1747 rpkt.status = htons(ctlsysstatus()); 1748 for (i = 0; i < HASH_SIZE; i++) { 1749 for (peer = assoc_hash[i]; peer != 0; 1750 peer = peer->ass_next) { 1751 ass_stat[n++] = htons(peer->associd); 1752 ass_stat[n++] = htons(ctlpeerstatus(peer)); 1753 if (n == CTL_MAX_DATA_LEN/sizeof(u_short)) { 1754 ctl_putdata((char *)ass_stat, 1755 n * sizeof(u_short), 1); 1756 n = 0; 1757 } 1758 } 1759 } 1760 1761 if (n != 0) 1762 ctl_putdata((char *)ass_stat, n * sizeof(u_short), 1); 1763 ctl_flushpkt(0); 1764 } else { 1765 peer = findpeerbyassoc((int)res_associd); 1766 if (peer == 0) { 1767 ctl_error(CERR_BADASSOC); 1768 } else { 1769 register u_char *cp; 1770 1771 rpkt.status = htons(ctlpeerstatus(peer)); 1772 if (res_authokay) 1773 peer->num_events = 0; 1774 /* 1775 * For now, output everything we know about the peer. 1776 * May be more selective later. 1777 */ 1778 for (cp = def_peer_var; *cp != 0; cp++) 1779 ctl_putpeer((int)*cp, peer); 1780 ctl_flushpkt(0); 1781 } 1782 } 1783} 1784 1785 1786/* 1787 * read_variables - return the variables the caller asks for 1788 */ 1789/*ARGSUSED*/ 1790static void 1791read_variables( 1792 struct recvbuf *rbufp, 1793 int restrict_mask 1794 ) 1795{ 1796 register struct ctl_var *v; 1797 register int i; 1798 char *valuep; 1799 u_char *wants; 1800 unsigned int gotvar = (CS_MAXCODE>CP_MAXCODE) ? (CS_MAXCODE+1) : (CP_MAXCODE+1); 1801 1802 if (res_associd == 0) { 1803 /* 1804 * Wants system variables. Figure out which he wants 1805 * and give them to him. 1806 */ 1807 rpkt.status = htons(ctlsysstatus()); 1808 if (res_authokay) 1809 ctl_sys_num_events = 0; 1810 gotvar += count_var(ext_sys_var); 1811 wants = (u_char *)emalloc(gotvar); 1812 memset((char *)wants, 0, gotvar); 1813 gotvar = 0; 1814 while ((v = ctl_getitem(sys_var, &valuep)) != 0) { 1815 if (v->flags & EOV) { 1816 if ((v = ctl_getitem(ext_sys_var, &valuep)) != 0) { 1817 if (v->flags & EOV) { 1818 ctl_error(CERR_UNKNOWNVAR); 1819 free((char *)wants); 1820 return; 1821 } 1822 wants[CS_MAXCODE+1+v->code] = 1; 1823 gotvar = 1; 1824 continue; 1825 } else { 1826 break; /* shouldn't happen ! */ 1827 } 1828 } 1829 wants[v->code] = 1; 1830 gotvar = 1; 1831 } 1832 if (gotvar) { 1833 for (i = 1; i <= CS_MAXCODE; i++) 1834 if (wants[i]) 1835 ctl_putsys(i); 1836 for (i = 0; ext_sys_var && !(ext_sys_var[i].flags & EOV); i++) 1837 if (wants[i+CS_MAXCODE+1]) 1838 ctl_putdata(ext_sys_var[i].text, 1839 strlen(ext_sys_var[i].text), 0); 1840 } else { 1841 register u_char *cs; 1842 register struct ctl_var *kv; 1843 1844 for (cs = def_sys_var; *cs != 0; cs++) 1845 ctl_putsys((int)*cs); 1846 for (kv = ext_sys_var; kv && !(kv->flags & EOV); kv++) 1847 if (kv->flags & DEF) 1848 ctl_putdata(kv->text, strlen(kv->text), 0); 1849 } 1850 free((char *)wants); 1851 } else { 1852 register struct peer *peer; 1853 1854 /* 1855 * Wants info for a particular peer. See if we know 1856 * the guy. 1857 */ 1858 peer = findpeerbyassoc((int)res_associd); 1859 if (peer == 0) { 1860 ctl_error(CERR_BADASSOC); 1861 return; 1862 } 1863 1864 rpkt.status = htons(ctlpeerstatus(peer)); 1865 if (res_authokay) 1866 peer->num_events = 0; 1867 wants = (u_char *)emalloc(gotvar); 1868 memset((char*)wants, 0, gotvar); 1869 gotvar = 0; 1870 while ((v = ctl_getitem(peer_var, &valuep)) != 0) { 1871 if (v->flags & EOV) { 1872 ctl_error(CERR_UNKNOWNVAR); 1873 free((char *)wants); 1874 return; 1875 } 1876 wants[v->code] = 1; 1877 gotvar = 1; 1878 } 1879 if (gotvar) { 1880 for (i = 1; i <= CP_MAXCODE; i++) 1881 if (wants[i]) 1882 ctl_putpeer(i, peer); 1883 } else { 1884 register u_char *cp; 1885 1886 for (cp = def_peer_var; *cp != 0; cp++) 1887 ctl_putpeer((int)*cp, peer); 1888 } 1889 free((char *)wants); 1890 } 1891 ctl_flushpkt(0); 1892} 1893 1894 1895/* 1896 * write_variables - write into variables. We only allow leap bit writing 1897 * this way. 1898 */ 1899/*ARGSUSED*/ 1900static void 1901write_variables( 1902 struct recvbuf *rbufp, 1903 int restrict_mask 1904 ) 1905{ 1906 register struct ctl_var *v; 1907 register int ext_var; 1908 char *valuep; 1909 long val; 1910 /*int leapind, leapwarn;*/ 1911 1912 /* 1913 * If he's trying to write into a peer tell him no way 1914 */ 1915 if (res_associd != 0) { 1916 ctl_error(CERR_PERMISSION); 1917 return; 1918 } 1919 1920 /* 1921 * Set status 1922 */ 1923 rpkt.status = htons(ctlsysstatus()); 1924 1925 /* 1926 * Set flags to not-in-sync so we can tell when we get something. 1927 */ 1928 /* 1929 leapind = ~0; 1930 leapwarn = ~0; 1931 */ 1932 1933 /* 1934 * Look through the variables. Dump out at the first sign of trouble. 1935 */ 1936 while ((v = ctl_getitem(sys_var, &valuep)) != 0) { 1937 ext_var = 0; 1938 if (v->flags & EOV) { 1939 if ((v = ctl_getitem(ext_sys_var, &valuep)) != 0) { 1940 if (v->flags & EOV) { 1941 ctl_error(CERR_UNKNOWNVAR); 1942 return; 1943 } 1944 ext_var = 1; 1945 } else { 1946 break; 1947 } 1948 } 1949 if (!(v->flags & CAN_WRITE)) { 1950 ctl_error(CERR_PERMISSION); 1951 return; 1952 } 1953 if (!ext_var && (*valuep == '\0' || !atoint(valuep, &val))) { 1954 ctl_error(CERR_BADFMT); 1955 return; 1956 } 1957 if (!ext_var && (val & ~LEAP_NOTINSYNC) != 0) { 1958 ctl_error(CERR_BADVALUE); 1959 return; 1960 } 1961 1962 if (ext_var) { 1963 char *s = (char *)emalloc(strlen(v->text)+strlen(valuep)+2); 1964 const char *t; 1965 char *tt = s; 1966 1967 t = v->text; 1968 while (*t && *t != '=') 1969 *tt++ = *t++; 1970 1971 *tt++ = '='; 1972 strcat(tt, valuep); 1973 1974 set_sys_var(s, strlen(s)+1, v->flags); 1975 free(s); 1976 } else { 1977 /* 1978 * This one seems sane. Save it. 1979 */ 1980 switch(v->code) { 1981 case CS_LEAP: 1982 default: 1983 ctl_error(CERR_UNSPEC); /* our fault, really */ 1984 return; 1985 } 1986 } 1987 } 1988 1989 /* 1990 * If we got anything, do it. 1991 */ 1992 /* 1993 if (leapind != ~0 || leapwarn != ~0) { 1994 if (!leap_setleap((int)leapind, (int)leapwarn)) { 1995 ctl_error(CERR_PERMISSION); 1996 return; 1997 } 1998 } 1999 */ 2000 ctl_flushpkt(0); 2001} 2002 2003 2004/* 2005 * read_clock_status - return clock radio status 2006 */ 2007/*ARGSUSED*/ 2008static void 2009read_clock_status( 2010 struct recvbuf *rbufp, 2011 int restrict_mask 2012 ) 2013{ 2014#ifndef REFCLOCK 2015 /* 2016 * If no refclock support, no data to return 2017 */ 2018 ctl_error(CERR_BADASSOC); 2019#else 2020 register struct ctl_var *v; 2021 register int i; 2022 register struct peer *peer; 2023 char *valuep; 2024 u_char *wants; 2025 unsigned int gotvar; 2026 struct refclockstat clock_stat; 2027 2028 if (res_associd == 0) { 2029 /* 2030 * Find a clock for this jerk. If the system peer 2031 * is a clock use it, else search the hash tables 2032 * for one. 2033 */ 2034 if (sys_peer != 0 && (sys_peer->flags & FLAG_REFCLOCK)) { 2035 peer = sys_peer; 2036 } else { 2037 peer = 0; 2038 for (i = 0; peer == 0 && i < HASH_SIZE; i++) { 2039 for (peer = assoc_hash[i]; peer != 0; 2040 peer = peer->ass_next) { 2041 if (peer->flags & FLAG_REFCLOCK) 2042 break; 2043 } 2044 } 2045 if (peer == 0) { 2046 ctl_error(CERR_BADASSOC); 2047 return; 2048 } 2049 } 2050 } else { 2051 peer = findpeerbyassoc((int)res_associd); 2052 if (peer == 0 || !(peer->flags & FLAG_REFCLOCK)) { 2053 ctl_error(CERR_BADASSOC); 2054 return; 2055 } 2056 } 2057 2058 /* 2059 * If we got here we have a peer which is a clock. Get his status. 2060 */ 2061 clock_stat.kv_list = (struct ctl_var *)0; 2062 2063 refclock_control(&peer->srcadr, (struct refclockstat *)0, &clock_stat); 2064 2065 /* 2066 * Look for variables in the packet. 2067 */ 2068 rpkt.status = htons(ctlclkstatus(&clock_stat)); 2069 gotvar = CC_MAXCODE+1+count_var(clock_stat.kv_list); 2070 wants = (u_char *)emalloc(gotvar); 2071 memset((char*)wants, 0, gotvar); 2072 gotvar = 0; 2073 while ((v = ctl_getitem(clock_var, &valuep)) != 0) { 2074 if (v->flags & EOV) { 2075 if ((v = ctl_getitem(clock_stat.kv_list, &valuep)) != 0) { 2076 if (v->flags & EOV) { 2077 ctl_error(CERR_UNKNOWNVAR); 2078 free((char*)wants); 2079 free_varlist(clock_stat.kv_list); 2080 return; 2081 } 2082 wants[CC_MAXCODE+1+v->code] = 1; 2083 gotvar = 1; 2084 continue; 2085 } else { 2086 break; /* shouldn't happen ! */ 2087 } 2088 } 2089 wants[v->code] = 1; 2090 gotvar = 1; 2091 } 2092 2093 if (gotvar) { 2094 for (i = 1; i <= CC_MAXCODE; i++) 2095 if (wants[i]) 2096 ctl_putclock(i, &clock_stat, 1); 2097 for (i = 0; clock_stat.kv_list && !(clock_stat.kv_list[i].flags & EOV); i++) 2098 if (wants[i+CC_MAXCODE+1]) 2099 ctl_putdata(clock_stat.kv_list[i].text, 2100 strlen(clock_stat.kv_list[i].text), 0); 2101 } else { 2102 register u_char *cc; 2103 register struct ctl_var *kv; 2104 2105 for (cc = def_clock_var; *cc != 0; cc++) 2106 ctl_putclock((int)*cc, &clock_stat, 0); 2107 for (kv = clock_stat.kv_list; kv && !(kv->flags & EOV); kv++) 2108 if (kv->flags & DEF) 2109 ctl_putdata(kv->text, strlen(kv->text), 0); 2110 } 2111 2112 free((char*)wants); 2113 free_varlist(clock_stat.kv_list); 2114 2115 ctl_flushpkt(0); 2116#endif 2117} 2118 2119 2120/* 2121 * write_clock_status - we don't do this 2122 */ 2123/*ARGSUSED*/ 2124static void 2125write_clock_status( 2126 struct recvbuf *rbufp, 2127 int restrict_mask 2128 ) 2129{ 2130 ctl_error(CERR_PERMISSION); 2131} 2132 2133/* 2134 * Trap support from here on down. We send async trap messages when the 2135 * upper levels report trouble. Traps can by set either by control 2136 * messages or by configuration. 2137 */ 2138 2139/* 2140 * set_trap - set a trap in response to a control message 2141 */ 2142static void 2143set_trap( 2144 struct recvbuf *rbufp, 2145 int restrict_mask 2146 ) 2147{ 2148 int traptype; 2149 2150 /* 2151 * See if this guy is allowed 2152 */ 2153 if (restrict_mask & RES_NOTRAP) { 2154 ctl_error(CERR_PERMISSION); 2155 return; 2156 } 2157 2158 /* 2159 * Determine his allowed trap type. 2160 */ 2161 traptype = TRAP_TYPE_PRIO; 2162 if (restrict_mask & RES_LPTRAP) 2163 traptype = TRAP_TYPE_NONPRIO; 2164 2165 /* 2166 * Call ctlsettrap() to do the work. Return 2167 * an error if it can't assign the trap. 2168 */ 2169 if (!ctlsettrap(&rbufp->recv_srcadr, rbufp->dstadr, traptype, 2170 (int)res_version)) 2171 ctl_error(CERR_NORESOURCE); 2172 ctl_flushpkt(0); 2173} 2174 2175 2176/* 2177 * unset_trap - unset a trap in response to a control message 2178 */ 2179static void 2180unset_trap( 2181 struct recvbuf *rbufp, 2182 int restrict_mask 2183 ) 2184{ 2185 int traptype; 2186 2187 /* 2188 * We don't prevent anyone from removing his own 2189 * trap unless the trap is configured. Note we also 2190 * must be aware of the possibility that restriction 2191 * flags were changed since this guy last set his trap. 2192 * Set the trap type based on this. 2193 */ 2194 traptype = TRAP_TYPE_PRIO; 2195 if (restrict_mask & RES_LPTRAP) 2196 traptype = TRAP_TYPE_NONPRIO; 2197 2198 /* 2199 * Call ctlclrtrap() to clear this out. 2200 */ 2201 if (!ctlclrtrap(&rbufp->recv_srcadr, rbufp->dstadr, traptype)) 2202 ctl_error(CERR_BADASSOC); 2203 ctl_flushpkt(0); 2204} 2205 2206 2207/* 2208 * ctlsettrap - called to set a trap 2209 */ 2210int 2211ctlsettrap( 2212 struct sockaddr_in *raddr, 2213 struct interface *linter, 2214 int traptype, 2215 int version 2216 ) 2217{ 2218 register struct ctl_trap *tp; 2219 register struct ctl_trap *tptouse; 2220 2221 /* 2222 * See if we can find this trap. If so, we only need update 2223 * the flags and the time. 2224 */ 2225 if ((tp = ctlfindtrap(raddr, linter)) != NULL) { 2226 switch (traptype) { 2227 case TRAP_TYPE_CONFIG: 2228 tp->tr_flags = TRAP_INUSE|TRAP_CONFIGURED; 2229 break; 2230 case TRAP_TYPE_PRIO: 2231 if (tp->tr_flags & TRAP_CONFIGURED) 2232 return 1; /* don't change anything */ 2233 tp->tr_flags = TRAP_INUSE; 2234 break; 2235 case TRAP_TYPE_NONPRIO: 2236 if (tp->tr_flags & TRAP_CONFIGURED) 2237 return 1; /* don't change anything */ 2238 tp->tr_flags = TRAP_INUSE|TRAP_NONPRIO; 2239 break; 2240 } 2241 tp->tr_settime = current_time; 2242 tp->tr_resets++; 2243 return 1; 2244 } 2245 2246 /* 2247 * First we heard of this guy. Try to find a trap structure 2248 * for him to use, clearing out lesser priority guys if we 2249 * have to. Clear out anyone who's expired while we're at it. 2250 */ 2251 tptouse = NULL; 2252 for (tp = ctl_trap; tp < &ctl_trap[CTL_MAXTRAPS]; tp++) { 2253 if ((tp->tr_flags & TRAP_INUSE) && 2254 !(tp->tr_flags & TRAP_CONFIGURED) && 2255 ((tp->tr_settime + CTL_TRAPTIME) > current_time)) { 2256 tp->tr_flags = 0; 2257 num_ctl_traps--; 2258 } 2259 2260 if (!(tp->tr_flags & TRAP_INUSE)) { 2261 tptouse = tp; 2262 } else if (!(tp->tr_flags & TRAP_CONFIGURED)) { 2263 switch (traptype) { 2264 case TRAP_TYPE_CONFIG: 2265 if (tptouse == NULL) { 2266 tptouse = tp; 2267 break; 2268 } 2269 if (tptouse->tr_flags & TRAP_NONPRIO 2270 && !(tp->tr_flags & TRAP_NONPRIO)) 2271 break; 2272 if (!(tptouse->tr_flags & TRAP_NONPRIO) 2273 && tp->tr_flags & TRAP_NONPRIO) { 2274 tptouse = tp; 2275 break; 2276 } 2277 if (tptouse->tr_origtime < tp->tr_origtime) 2278 tptouse = tp; 2279 break; 2280 case TRAP_TYPE_PRIO: 2281 if (tp->tr_flags & TRAP_NONPRIO) { 2282 if (tptouse == NULL || 2283 (tptouse->tr_flags & TRAP_INUSE 2284 && tptouse->tr_origtime 2285 < tp->tr_origtime)) 2286 tptouse = tp; 2287 } 2288 break; 2289 case TRAP_TYPE_NONPRIO: 2290 break; 2291 } 2292 } 2293 } 2294 2295 /* 2296 * If we don't have room for him return an error. 2297 */ 2298 if (tptouse == NULL) 2299 return 0; 2300 2301 /* 2302 * Set up this structure for him. 2303 */ 2304 tptouse->tr_settime = tptouse->tr_origtime = current_time; 2305 tptouse->tr_count = tptouse->tr_resets = 0; 2306 tptouse->tr_sequence = 1; 2307 tptouse->tr_addr = *raddr; 2308 tptouse->tr_localaddr = linter; 2309 tptouse->tr_version = version; 2310 2311 tptouse->tr_flags = TRAP_INUSE; 2312 if (traptype == TRAP_TYPE_CONFIG) 2313 tptouse->tr_flags |= TRAP_CONFIGURED; 2314 else if (traptype == TRAP_TYPE_NONPRIO) 2315 tptouse->tr_flags |= TRAP_NONPRIO; 2316 num_ctl_traps++; 2317 return 1; 2318} 2319 2320 2321/* 2322 * ctlclrtrap - called to clr a trap 2323 */ 2324int 2325ctlclrtrap( 2326 struct sockaddr_in *raddr, 2327 struct interface *linter, 2328 int traptype 2329 ) 2330{ 2331 register struct ctl_trap *tp; 2332 2333 if ((tp = ctlfindtrap(raddr, linter)) == NULL) 2334 return 0; 2335 2336 if (tp->tr_flags & TRAP_CONFIGURED 2337 && traptype != TRAP_TYPE_CONFIG) 2338 return 0; 2339 2340 tp->tr_flags = 0; 2341 num_ctl_traps--; 2342 return 1; 2343} 2344 2345 2346/* 2347 * ctlfindtrap - find a trap given the remote and local addresses 2348 */ 2349static struct ctl_trap * 2350ctlfindtrap( 2351 struct sockaddr_in *raddr, 2352 struct interface *linter 2353 ) 2354{ 2355 register struct ctl_trap *tp; 2356 2357 for (tp = ctl_trap; tp < &ctl_trap[CTL_MAXTRAPS]; tp++) { 2358 if (tp->tr_flags & TRAP_INUSE 2359 && NSRCADR(raddr) == NSRCADR(&tp->tr_addr) 2360 && NSRCPORT(raddr) == NSRCPORT(&tp->tr_addr) 2361 && linter == tp->tr_localaddr) 2362 return tp; 2363 } 2364 return (struct ctl_trap *)NULL; 2365} 2366 2367 2368/* 2369 * report_event - report an event to the trappers 2370 */ 2371void 2372report_event( 2373 int err, 2374 struct peer *peer 2375 ) 2376{ 2377 register int i; 2378 2379 /* 2380 * Record error code in proper spots, but have mercy on the 2381 * log file. 2382 */ 2383 if (!(err & PEER_EVENT)) { 2384 if (ctl_sys_num_events < CTL_SYS_MAXEVENTS) 2385 ctl_sys_num_events++; 2386 if (ctl_sys_last_event != (u_char)err) { 2387 NLOG(NLOG_SYSEVENT) 2388 msyslog(LOG_INFO, "system event '%s' (0x%02x) status '%s' (0x%02x)", 2389 eventstr(err), err, 2390 sysstatstr(ctlsysstatus()), ctlsysstatus()); 2391#ifdef DEBUG 2392 if (debug) 2393 printf("report_event: system event '%s' (0x%02x) status '%s' (0x%02x)\n", 2394 eventstr(err), err, 2395 sysstatstr(ctlsysstatus()), ctlsysstatus()); 2396#endif 2397 ctl_sys_last_event = (u_char)err; 2398 } 2399 } else if (peer != 0) { 2400 char *src; 2401 2402#ifdef REFCLOCK 2403 if (ISREFCLOCKADR(&peer->srcadr)) 2404 src = refnumtoa(peer->srcadr.sin_addr.s_addr); 2405 else 2406#endif 2407 src = ntoa(&peer->srcadr); 2408 2409 peer->last_event = (u_char)(err & ~PEER_EVENT); 2410 if (peer->num_events < CTL_PEER_MAXEVENTS) 2411 peer->num_events++; 2412 NLOG(NLOG_PEEREVENT) 2413 msyslog(LOG_INFO, "peer %s event '%s' (0x%02x) status '%s' (0x%02x)", 2414 src, eventstr(err), err, 2415 peerstatstr(ctlpeerstatus(peer)), ctlpeerstatus(peer)); 2416#ifdef DEBUG 2417 if (debug) 2418 printf( "peer %s event '%s' (0x%02x) status '%s' (0x%02x)\n", 2419 src, eventstr(err), err, 2420 peerstatstr(ctlpeerstatus(peer)), ctlpeerstatus(peer)); 2421#endif 2422 } else { 2423 msyslog(LOG_ERR, "report_event: err '%s' (0x%02x), no peer", eventstr(err), err); 2424#ifdef DEBUG 2425 printf("report_event: peer event '%s' (0x%02x), no peer\n", eventstr(err), err); 2426#endif 2427 return; 2428 } 2429 2430 /* 2431 * If no trappers, return. 2432 */ 2433 if (num_ctl_traps <= 0) 2434 return; 2435 2436 /* 2437 * Set up the outgoing packet variables 2438 */ 2439 res_opcode = CTL_OP_ASYNCMSG; 2440 res_offset = 0; 2441 res_async = 1; 2442 res_authenticate = 0; 2443 datapt = rpkt.data; 2444 dataend = &(rpkt.data[CTL_MAX_DATA_LEN]); 2445 2446 if (!(err & PEER_EVENT)) { 2447 rpkt.associd = 0; 2448 rpkt.status = htons(ctlsysstatus()); 2449 2450 /* 2451 * For now, put everything we know about system 2452 * variables. Maybe more selective later 2453 */ 2454 for (i = 1; i <= CS_MAXCODE; i++) 2455 ctl_putsys(i); 2456#ifdef REFCLOCK 2457 /* 2458 * for clock exception events: 2459 * add clock variables to reflect info on exception 2460 */ 2461 if (err == EVNT_CLOCKEXCPT) { 2462 struct refclockstat clock_stat; 2463 struct ctl_var *kv; 2464 2465 clock_stat.kv_list = (struct ctl_var *)0; 2466 2467 refclock_control(&peer->srcadr, 2468 (struct refclockstat *)0, &clock_stat); 2469 ctl_puthex("refclockstatus", ctlclkstatus(&clock_stat)); 2470 2471 for (i = 1; i <= CC_MAXCODE; i++) 2472 ctl_putclock(i, &clock_stat, 0); 2473 for (kv = clock_stat.kv_list; kv && !(kv->flags & EOV); kv++) 2474 if (kv->flags & DEF) 2475 ctl_putdata(kv->text, strlen(kv->text), 0); 2476 2477 free_varlist(clock_stat.kv_list); 2478 } 2479#endif /*REFCLOCK*/ 2480 } else { 2481 rpkt.associd = htons(peer->associd); 2482 rpkt.status = htons(ctlpeerstatus(peer)); 2483 2484 /* 2485 * Dump it all. Later, maybe less. 2486 */ 2487 for (i = 1; i <= CP_MAXCODE; i++) 2488 ctl_putpeer(i, peer); 2489#ifdef REFCLOCK 2490 /* 2491 * for clock exception events: 2492 * add clock variables to reflect info on exception 2493 */ 2494 if (err == EVNT_PEERCLOCK) { 2495 struct refclockstat clock_stat; 2496 struct ctl_var *kv; 2497 2498 clock_stat.kv_list = (struct ctl_var *)0; 2499 2500 refclock_control(&peer->srcadr, 2501 (struct refclockstat *)0, 2502 &clock_stat); 2503 2504 ctl_puthex("refclockstatus", 2505 ctlclkstatus(&clock_stat)); 2506 2507 for (i = 1; i <= CC_MAXCODE; i++) 2508 ctl_putclock(i, &clock_stat, 0); 2509 for (kv = clock_stat.kv_list; kv && !(kv->flags & EOV); kv++) 2510 if (kv->flags & DEF) 2511 ctl_putdata(kv->text, strlen(kv->text), 0); 2512 2513 free_varlist(clock_stat.kv_list); 2514 } 2515#endif /*REFCLOCK*/ 2516 } 2517 2518 /* 2519 * We're done, return. 2520 */ 2521 ctl_flushpkt(0); 2522} 2523 2524 2525/* 2526 * ctl_clr_stats - clear stat counters 2527 */ 2528void 2529ctl_clr_stats(void) 2530{ 2531 ctltimereset = current_time; 2532 numctlreq = 0; 2533 numctlbadpkts = 0; 2534 numctlresponses = 0; 2535 numctlfrags = 0; 2536 numctlerrors = 0; 2537 numctlfrags = 0; 2538 numctltooshort = 0; 2539 numctlinputresp = 0; 2540 numctlinputfrag = 0; 2541 numctlinputerr = 0; 2542 numctlbadoffset = 0; 2543 numctlbadversion = 0; 2544 numctldatatooshort = 0; 2545 numctlbadop = 0; 2546 numasyncmsgs = 0; 2547} 2548 2549static u_long 2550count_var( 2551 struct ctl_var *k 2552 ) 2553{ 2554 register u_long c; 2555 2556 if (!k) 2557 return 0; 2558 2559 c = 0; 2560 2561 while (!(k++->flags & EOV)) 2562 c++; 2563 2564 return c; 2565} 2566 2567char * 2568add_var( 2569 struct ctl_var **kv, 2570 u_long size, 2571 int def 2572 ) 2573{ 2574 register u_long c; 2575 register struct ctl_var *k; 2576 2577 c = count_var(*kv); 2578 2579 k = *kv; 2580 *kv = (struct ctl_var *)emalloc((c+2)*sizeof(struct ctl_var)); 2581 if (k) 2582 { 2583 memmove((char *)*kv, (char *)k, sizeof(struct ctl_var)*c); 2584 free((char *)k); 2585 } 2586 2587 (*kv)[c].code = (u_short) c; 2588 (*kv)[c].text = (char *)emalloc(size); 2589 (*kv)[c].flags = def; 2590 (*kv)[c+1].code = 0; 2591 (*kv)[c+1].text = (char *)0; 2592 (*kv)[c+1].flags = EOV; 2593 return (char *)(*kv)[c].text; 2594} 2595 2596void 2597set_var( 2598 struct ctl_var **kv, 2599 const char *data, 2600 u_long size, 2601 int def 2602 ) 2603{ 2604 register struct ctl_var *k; 2605 register const char *s; 2606 register const char *t; 2607 char *td; 2608 2609 if (!data || !size) 2610 return; 2611 2612 if ((k = *kv)) 2613 { 2614 while (!(k->flags & EOV)) 2615 { 2616 s = data; 2617 t = k->text; 2618 if (t) 2619 { 2620 while (*t != '=' && *s - *t == 0) 2621 { 2622 s++; 2623 t++; 2624 } 2625 if (*s == *t && ((*t == '=') || !*t)) 2626 { 2627 free((void *)k->text); 2628 td = (char *)emalloc(size); 2629 memmove(td, data, size); 2630 k->text =td; 2631 k->flags = def; 2632 return; 2633 } 2634 } 2635 else 2636 { 2637 td = (char *)emalloc(size); 2638 memmove(td, data, size); 2639 k->text = td; 2640 k->flags = def; 2641 return; 2642 } 2643 k++; 2644 } 2645 } 2646 td = add_var(kv, size, def); 2647 memmove(td, data, size); 2648} 2649 2650void 2651set_sys_var( 2652 char *data, 2653 u_long size, 2654 int def 2655 ) 2656{ 2657 set_var(&ext_sys_var, data, size, def); 2658} 2659 2660void 2661free_varlist( 2662 struct ctl_var *kv 2663 ) 2664{ 2665 struct ctl_var *k; 2666 if (kv) 2667 { 2668 for (k = kv; !(k->flags & EOV); k++) 2669 free((void *)k->text); 2670 free((void *)kv); 2671 } 2672} 2673