1 /* 2 * ntp_control.c - respond to control messages and send async traps 3 */ 4 5 /* 6 * $FreeBSD$ 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 33 struct 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 */ 48 static void ctl_error P((int)); 49 static u_short ctlclkstatus P((struct refclockstat *)); 50 static void ctl_flushpkt P((int)); 51 static void ctl_putdata P((const char *, unsigned int, int)); 52 static void ctl_putstr P((const char *, const char *, unsigned int)); 53 static void ctl_putdbl P((const char *, double)); 54 static void ctl_putuint P((const char *, u_long)); 55 static void ctl_puthex P((const char *, u_long)); 56 static void ctl_putint P((const char *, long)); 57 static void ctl_putts P((const char *, l_fp *)); 58 static void ctl_putadr P((const char *, u_int32)); 59 static void ctl_putid P((const char *, char *)); 60 static void ctl_putarray P((const char *, double *, int)); 61 static void ctl_putsys P((int)); 62 static void ctl_putpeer P((int, struct peer *)); 63 #ifdef REFCLOCK 64 static void ctl_putclock P((int, struct refclockstat *, int)); 65 #endif /* REFCLOCK */ 66 static struct ctl_var *ctl_getitem P((struct ctl_var *, char **)); 67 static u_long count_var P((struct ctl_var *)); 68 static void control_unspec P((struct recvbuf *, int)); 69 static void read_status P((struct recvbuf *, int)); 70 static void read_variables P((struct recvbuf *, int)); 71 static void write_variables P((struct recvbuf *, int)); 72 static void read_clock_status P((struct recvbuf *, int)); 73 static void write_clock_status P((struct recvbuf *, int)); 74 static void set_trap P((struct recvbuf *, int)); 75 static void unset_trap P((struct recvbuf *, int)); 76 static struct ctl_trap *ctlfindtrap P((struct sockaddr_in *, struct interface *)); 77 78 static 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 */ 94 static 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 117 static 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 */ 122 static 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 */ 147 static 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 */ 193 static 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 */ 231 static 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 */ 253 static 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 282 static char str_system[] = STR_SYSTEM; 283 static char str_processor[] = STR_PROCESSOR; 284 #else 285 # include <sys/utsname.h> 286 static 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 */ 296 struct ctl_trap ctl_trap[CTL_MAXTRAPS]; 297 int 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 */ 313 static 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 */ 358 u_long ctl_auth_keyid; 359 360 /* 361 * We keep track of the last error reported by the system internally 362 */ 363 static u_char ctl_sys_last_event; 364 static u_char ctl_sys_num_events; 365 366 367 /* 368 * Statistic counters to keep track of requests and responses. 369 */ 370 u_long ctltimereset; /* time stats reset */ 371 u_long numctlreq; /* number of requests we've received */ 372 u_long numctlbadpkts; /* number of bad control packets */ 373 u_long numctlresponses; /* number of resp packets sent with data */ 374 u_long numctlfrags; /* number of fragments sent */ 375 u_long numctlerrors; /* number of error responses sent */ 376 u_long numctltooshort; /* number of too short input packets */ 377 u_long numctlinputresp; /* number of responses on input */ 378 u_long numctlinputfrag; /* number of fragments on input */ 379 u_long numctlinputerr; /* number of input pkts with err bit set */ 380 u_long numctlbadoffset; /* number of input pkts with nonzero offset */ 381 u_long numctlbadversion; /* number of input pkts with unknown version */ 382 u_long numctldatatooshort; /* data too short for count */ 383 u_long numctlbadop; /* bad op code found in packet */ 384 u_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 */ 393 static struct ntp_control rpkt; 394 static u_char res_version; 395 static u_char res_opcode; 396 static u_short res_associd; 397 static int res_offset; 398 static u_char * datapt; 399 static u_char * dataend; 400 static int datalinelen; 401 static int datanotbinflag; 402 static struct sockaddr_in *rmt_addr; 403 static struct interface *lcl_inter; 404 405 static u_char res_authenticate; 406 static u_char res_authokay; 407 static u_long res_keyid; 408 409 #define MAXDATALINELEN (72) 410 411 static 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 */ 416 static char *reqpt; 417 static char *reqend; 418 419 /* 420 * init_control - initialize request data 421 */ 422 void 423 init_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 */ 446 static void 447 ctl_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 */ 486 void 487 process_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 */ 657 u_short 658 ctlpeerstatus( 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 */ 681 static u_short 682 ctlclkstatus( 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 */ 695 u_short 696 ctlsysstatus(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 */ 723 static void 724 ctl_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 */ 814 static void 815 ctl_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 */ 860 static void 861 ctl_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 */ 893 static void 894 ctl_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 */ 917 static void 918 ctl_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 */ 944 static void 945 ctl_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 */ 971 static void 972 ctl_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 */ 998 static void 999 ctl_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 */ 1026 static void 1027 ctl_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 */ 1053 static void 1054 ctl_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 */ 1080 static void 1081 ctl_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 */ 1112 static void 1113 ctl_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 */ 1265 static void 1266 ctl_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 */ 1460 static void 1461 ctl_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 */ 1603 static struct ctl_var * 1604 ctl_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 return (0); 1661 } 1662 if (cp < reqend) 1663 cp++; 1664 *tp = '\0'; 1665 while (tp != buf && isspace((unsigned char)(*(tp-1)))) 1666 *(--tp) = '\0'; 1667 reqpt = cp; 1668 *data = buf; 1669 return v; 1670 } 1671 } 1672 cp = reqpt; 1673 } 1674 v++; 1675 } 1676 return v; 1677 } 1678 1679 1680 /* 1681 * control_unspec - response to an unspecified op-code 1682 */ 1683 /*ARGSUSED*/ 1684 static void 1685 control_unspec( 1686 struct recvbuf *rbufp, 1687 int restrict_mask 1688 ) 1689 { 1690 struct peer *peer; 1691 1692 /* 1693 * What is an appropriate response to an unspecified op-code? 1694 * I return no errors and no data, unless a specified assocation 1695 * doesn't exist. 1696 */ 1697 if (res_associd != 0) { 1698 if ((peer = findpeerbyassoc((int)res_associd)) == 0) { 1699 ctl_error(CERR_BADASSOC); 1700 return; 1701 } 1702 rpkt.status = htons(ctlpeerstatus(peer)); 1703 } else { 1704 rpkt.status = htons(ctlsysstatus()); 1705 } 1706 ctl_flushpkt(0); 1707 } 1708 1709 1710 /* 1711 * read_status - return either a list of associd's, or a particular 1712 * peer's status. 1713 */ 1714 /*ARGSUSED*/ 1715 static void 1716 read_status( 1717 struct recvbuf *rbufp, 1718 int restrict_mask 1719 ) 1720 { 1721 register int i; 1722 register struct peer *peer; 1723 u_short ass_stat[CTL_MAX_DATA_LEN/sizeof(u_short)]; 1724 1725 #ifdef DEBUG 1726 if (debug >= 2) 1727 printf("read_status: ID %d\n", res_associd); 1728 #endif 1729 /* 1730 * Two choices here. If the specified association ID is 1731 * zero we return all known assocation ID's. Otherwise 1732 * we return a bunch of stuff about the particular peer. 1733 */ 1734 if (res_associd == 0) { 1735 register int n; 1736 1737 n = 0; 1738 rpkt.status = htons(ctlsysstatus()); 1739 for (i = 0; i < HASH_SIZE; i++) { 1740 for (peer = assoc_hash[i]; peer != 0; 1741 peer = peer->ass_next) { 1742 ass_stat[n++] = htons(peer->associd); 1743 ass_stat[n++] = htons(ctlpeerstatus(peer)); 1744 if (n == CTL_MAX_DATA_LEN/sizeof(u_short)) { 1745 ctl_putdata((char *)ass_stat, 1746 n * sizeof(u_short), 1); 1747 n = 0; 1748 } 1749 } 1750 } 1751 1752 if (n != 0) 1753 ctl_putdata((char *)ass_stat, n * sizeof(u_short), 1); 1754 ctl_flushpkt(0); 1755 } else { 1756 peer = findpeerbyassoc((int)res_associd); 1757 if (peer == 0) { 1758 ctl_error(CERR_BADASSOC); 1759 } else { 1760 register u_char *cp; 1761 1762 rpkt.status = htons(ctlpeerstatus(peer)); 1763 if (res_authokay) 1764 peer->num_events = 0; 1765 /* 1766 * For now, output everything we know about the peer. 1767 * May be more selective later. 1768 */ 1769 for (cp = def_peer_var; *cp != 0; cp++) 1770 ctl_putpeer((int)*cp, peer); 1771 ctl_flushpkt(0); 1772 } 1773 } 1774 } 1775 1776 1777 /* 1778 * read_variables - return the variables the caller asks for 1779 */ 1780 /*ARGSUSED*/ 1781 static void 1782 read_variables( 1783 struct recvbuf *rbufp, 1784 int restrict_mask 1785 ) 1786 { 1787 register struct ctl_var *v; 1788 register int i; 1789 char *valuep; 1790 u_char *wants; 1791 unsigned int gotvar = (CS_MAXCODE>CP_MAXCODE) ? (CS_MAXCODE+1) : (CP_MAXCODE+1); 1792 1793 if (res_associd == 0) { 1794 /* 1795 * Wants system variables. Figure out which he wants 1796 * and give them to him. 1797 */ 1798 rpkt.status = htons(ctlsysstatus()); 1799 if (res_authokay) 1800 ctl_sys_num_events = 0; 1801 gotvar += count_var(ext_sys_var); 1802 wants = (u_char *)emalloc(gotvar); 1803 memset((char *)wants, 0, gotvar); 1804 gotvar = 0; 1805 while ((v = ctl_getitem(sys_var, &valuep)) != 0) { 1806 if (v->flags & EOV) { 1807 if ((v = ctl_getitem(ext_sys_var, &valuep)) != 0) { 1808 if (v->flags & EOV) { 1809 ctl_error(CERR_UNKNOWNVAR); 1810 free((char *)wants); 1811 return; 1812 } 1813 wants[CS_MAXCODE+1+v->code] = 1; 1814 gotvar = 1; 1815 continue; 1816 } else { 1817 break; /* shouldn't happen ! */ 1818 } 1819 } 1820 wants[v->code] = 1; 1821 gotvar = 1; 1822 } 1823 if (gotvar) { 1824 for (i = 1; i <= CS_MAXCODE; i++) 1825 if (wants[i]) 1826 ctl_putsys(i); 1827 for (i = 0; ext_sys_var && !(ext_sys_var[i].flags & EOV); i++) 1828 if (wants[i+CS_MAXCODE+1]) 1829 ctl_putdata(ext_sys_var[i].text, 1830 strlen(ext_sys_var[i].text), 0); 1831 } else { 1832 register u_char *cs; 1833 register struct ctl_var *kv; 1834 1835 for (cs = def_sys_var; *cs != 0; cs++) 1836 ctl_putsys((int)*cs); 1837 for (kv = ext_sys_var; kv && !(kv->flags & EOV); kv++) 1838 if (kv->flags & DEF) 1839 ctl_putdata(kv->text, strlen(kv->text), 0); 1840 } 1841 free((char *)wants); 1842 } else { 1843 register struct peer *peer; 1844 1845 /* 1846 * Wants info for a particular peer. See if we know 1847 * the guy. 1848 */ 1849 peer = findpeerbyassoc((int)res_associd); 1850 if (peer == 0) { 1851 ctl_error(CERR_BADASSOC); 1852 return; 1853 } 1854 1855 rpkt.status = htons(ctlpeerstatus(peer)); 1856 if (res_authokay) 1857 peer->num_events = 0; 1858 wants = (u_char *)emalloc(gotvar); 1859 memset((char*)wants, 0, gotvar); 1860 gotvar = 0; 1861 while ((v = ctl_getitem(peer_var, &valuep)) != 0) { 1862 if (v->flags & EOV) { 1863 ctl_error(CERR_UNKNOWNVAR); 1864 free((char *)wants); 1865 return; 1866 } 1867 wants[v->code] = 1; 1868 gotvar = 1; 1869 } 1870 if (gotvar) { 1871 for (i = 1; i <= CP_MAXCODE; i++) 1872 if (wants[i]) 1873 ctl_putpeer(i, peer); 1874 } else { 1875 register u_char *cp; 1876 1877 for (cp = def_peer_var; *cp != 0; cp++) 1878 ctl_putpeer((int)*cp, peer); 1879 } 1880 free((char *)wants); 1881 } 1882 ctl_flushpkt(0); 1883 } 1884 1885 1886 /* 1887 * write_variables - write into variables. We only allow leap bit writing 1888 * this way. 1889 */ 1890 /*ARGSUSED*/ 1891 static void 1892 write_variables( 1893 struct recvbuf *rbufp, 1894 int restrict_mask 1895 ) 1896 { 1897 register struct ctl_var *v; 1898 register int ext_var; 1899 char *valuep; 1900 long val; 1901 /*int leapind, leapwarn;*/ 1902 1903 /* 1904 * If he's trying to write into a peer tell him no way 1905 */ 1906 if (res_associd != 0) { 1907 ctl_error(CERR_PERMISSION); 1908 return; 1909 } 1910 1911 /* 1912 * Set status 1913 */ 1914 rpkt.status = htons(ctlsysstatus()); 1915 1916 /* 1917 * Set flags to not-in-sync so we can tell when we get something. 1918 */ 1919 /* 1920 leapind = ~0; 1921 leapwarn = ~0; 1922 */ 1923 1924 /* 1925 * Look through the variables. Dump out at the first sign of trouble. 1926 */ 1927 while ((v = ctl_getitem(sys_var, &valuep)) != 0) { 1928 ext_var = 0; 1929 if (v->flags & EOV) { 1930 if ((v = ctl_getitem(ext_sys_var, &valuep)) != 0) { 1931 if (v->flags & EOV) { 1932 ctl_error(CERR_UNKNOWNVAR); 1933 return; 1934 } 1935 ext_var = 1; 1936 } else { 1937 break; 1938 } 1939 } 1940 if (!(v->flags & CAN_WRITE)) { 1941 ctl_error(CERR_PERMISSION); 1942 return; 1943 } 1944 if (!ext_var && (*valuep == '\0' || !atoint(valuep, &val))) { 1945 ctl_error(CERR_BADFMT); 1946 return; 1947 } 1948 if (!ext_var && (val & ~LEAP_NOTINSYNC) != 0) { 1949 ctl_error(CERR_BADVALUE); 1950 return; 1951 } 1952 1953 if (ext_var) { 1954 char *s = (char *)emalloc(strlen(v->text)+strlen(valuep)+2); 1955 const char *t; 1956 char *tt = s; 1957 1958 t = v->text; 1959 while (*t && *t != '=') 1960 *tt++ = *t++; 1961 1962 *tt++ = '='; 1963 strcat(tt, valuep); 1964 1965 set_sys_var(s, strlen(s)+1, v->flags); 1966 free(s); 1967 } else { 1968 /* 1969 * This one seems sane. Save it. 1970 */ 1971 switch(v->code) { 1972 case CS_LEAP: 1973 default: 1974 ctl_error(CERR_UNSPEC); /* our fault, really */ 1975 return; 1976 } 1977 } 1978 } 1979 1980 /* 1981 * If we got anything, do it. 1982 */ 1983 /* 1984 if (leapind != ~0 || leapwarn != ~0) { 1985 if (!leap_setleap((int)leapind, (int)leapwarn)) { 1986 ctl_error(CERR_PERMISSION); 1987 return; 1988 } 1989 } 1990 */ 1991 ctl_flushpkt(0); 1992 } 1993 1994 1995 /* 1996 * read_clock_status - return clock radio status 1997 */ 1998 /*ARGSUSED*/ 1999 static void 2000 read_clock_status( 2001 struct recvbuf *rbufp, 2002 int restrict_mask 2003 ) 2004 { 2005 #ifndef REFCLOCK 2006 /* 2007 * If no refclock support, no data to return 2008 */ 2009 ctl_error(CERR_BADASSOC); 2010 #else 2011 register struct ctl_var *v; 2012 register int i; 2013 register struct peer *peer; 2014 char *valuep; 2015 u_char *wants; 2016 unsigned int gotvar; 2017 struct refclockstat clock_stat; 2018 2019 if (res_associd == 0) { 2020 /* 2021 * Find a clock for this jerk. If the system peer 2022 * is a clock use it, else search the hash tables 2023 * for one. 2024 */ 2025 if (sys_peer != 0 && (sys_peer->flags & FLAG_REFCLOCK)) { 2026 peer = sys_peer; 2027 } else { 2028 peer = 0; 2029 for (i = 0; peer == 0 && i < HASH_SIZE; i++) { 2030 for (peer = assoc_hash[i]; peer != 0; 2031 peer = peer->ass_next) { 2032 if (peer->flags & FLAG_REFCLOCK) 2033 break; 2034 } 2035 } 2036 if (peer == 0) { 2037 ctl_error(CERR_BADASSOC); 2038 return; 2039 } 2040 } 2041 } else { 2042 peer = findpeerbyassoc((int)res_associd); 2043 if (peer == 0 || !(peer->flags & FLAG_REFCLOCK)) { 2044 ctl_error(CERR_BADASSOC); 2045 return; 2046 } 2047 } 2048 2049 /* 2050 * If we got here we have a peer which is a clock. Get his status. 2051 */ 2052 clock_stat.kv_list = (struct ctl_var *)0; 2053 2054 refclock_control(&peer->srcadr, (struct refclockstat *)0, &clock_stat); 2055 2056 /* 2057 * Look for variables in the packet. 2058 */ 2059 rpkt.status = htons(ctlclkstatus(&clock_stat)); 2060 gotvar = CC_MAXCODE+1+count_var(clock_stat.kv_list); 2061 wants = (u_char *)emalloc(gotvar); 2062 memset((char*)wants, 0, gotvar); 2063 gotvar = 0; 2064 while ((v = ctl_getitem(clock_var, &valuep)) != 0) { 2065 if (v->flags & EOV) { 2066 if ((v = ctl_getitem(clock_stat.kv_list, &valuep)) != 0) { 2067 if (v->flags & EOV) { 2068 ctl_error(CERR_UNKNOWNVAR); 2069 free((char*)wants); 2070 free_varlist(clock_stat.kv_list); 2071 return; 2072 } 2073 wants[CC_MAXCODE+1+v->code] = 1; 2074 gotvar = 1; 2075 continue; 2076 } else { 2077 break; /* shouldn't happen ! */ 2078 } 2079 } 2080 wants[v->code] = 1; 2081 gotvar = 1; 2082 } 2083 2084 if (gotvar) { 2085 for (i = 1; i <= CC_MAXCODE; i++) 2086 if (wants[i]) 2087 ctl_putclock(i, &clock_stat, 1); 2088 for (i = 0; clock_stat.kv_list && !(clock_stat.kv_list[i].flags & EOV); i++) 2089 if (wants[i+CC_MAXCODE+1]) 2090 ctl_putdata(clock_stat.kv_list[i].text, 2091 strlen(clock_stat.kv_list[i].text), 0); 2092 } else { 2093 register u_char *cc; 2094 register struct ctl_var *kv; 2095 2096 for (cc = def_clock_var; *cc != 0; cc++) 2097 ctl_putclock((int)*cc, &clock_stat, 0); 2098 for (kv = clock_stat.kv_list; kv && !(kv->flags & EOV); kv++) 2099 if (kv->flags & DEF) 2100 ctl_putdata(kv->text, strlen(kv->text), 0); 2101 } 2102 2103 free((char*)wants); 2104 free_varlist(clock_stat.kv_list); 2105 2106 ctl_flushpkt(0); 2107 #endif 2108 } 2109 2110 2111 /* 2112 * write_clock_status - we don't do this 2113 */ 2114 /*ARGSUSED*/ 2115 static void 2116 write_clock_status( 2117 struct recvbuf *rbufp, 2118 int restrict_mask 2119 ) 2120 { 2121 ctl_error(CERR_PERMISSION); 2122 } 2123 2124 /* 2125 * Trap support from here on down. We send async trap messages when the 2126 * upper levels report trouble. Traps can by set either by control 2127 * messages or by configuration. 2128 */ 2129 2130 /* 2131 * set_trap - set a trap in response to a control message 2132 */ 2133 static void 2134 set_trap( 2135 struct recvbuf *rbufp, 2136 int restrict_mask 2137 ) 2138 { 2139 int traptype; 2140 2141 /* 2142 * See if this guy is allowed 2143 */ 2144 if (restrict_mask & RES_NOTRAP) { 2145 ctl_error(CERR_PERMISSION); 2146 return; 2147 } 2148 2149 /* 2150 * Determine his allowed trap type. 2151 */ 2152 traptype = TRAP_TYPE_PRIO; 2153 if (restrict_mask & RES_LPTRAP) 2154 traptype = TRAP_TYPE_NONPRIO; 2155 2156 /* 2157 * Call ctlsettrap() to do the work. Return 2158 * an error if it can't assign the trap. 2159 */ 2160 if (!ctlsettrap(&rbufp->recv_srcadr, rbufp->dstadr, traptype, 2161 (int)res_version)) 2162 ctl_error(CERR_NORESOURCE); 2163 ctl_flushpkt(0); 2164 } 2165 2166 2167 /* 2168 * unset_trap - unset a trap in response to a control message 2169 */ 2170 static void 2171 unset_trap( 2172 struct recvbuf *rbufp, 2173 int restrict_mask 2174 ) 2175 { 2176 int traptype; 2177 2178 /* 2179 * We don't prevent anyone from removing his own 2180 * trap unless the trap is configured. Note we also 2181 * must be aware of the possibility that restriction 2182 * flags were changed since this guy last set his trap. 2183 * Set the trap type based on this. 2184 */ 2185 traptype = TRAP_TYPE_PRIO; 2186 if (restrict_mask & RES_LPTRAP) 2187 traptype = TRAP_TYPE_NONPRIO; 2188 2189 /* 2190 * Call ctlclrtrap() to clear this out. 2191 */ 2192 if (!ctlclrtrap(&rbufp->recv_srcadr, rbufp->dstadr, traptype)) 2193 ctl_error(CERR_BADASSOC); 2194 ctl_flushpkt(0); 2195 } 2196 2197 2198 /* 2199 * ctlsettrap - called to set a trap 2200 */ 2201 int 2202 ctlsettrap( 2203 struct sockaddr_in *raddr, 2204 struct interface *linter, 2205 int traptype, 2206 int version 2207 ) 2208 { 2209 register struct ctl_trap *tp; 2210 register struct ctl_trap *tptouse; 2211 2212 /* 2213 * See if we can find this trap. If so, we only need update 2214 * the flags and the time. 2215 */ 2216 if ((tp = ctlfindtrap(raddr, linter)) != NULL) { 2217 switch (traptype) { 2218 case TRAP_TYPE_CONFIG: 2219 tp->tr_flags = TRAP_INUSE|TRAP_CONFIGURED; 2220 break; 2221 case TRAP_TYPE_PRIO: 2222 if (tp->tr_flags & TRAP_CONFIGURED) 2223 return 1; /* don't change anything */ 2224 tp->tr_flags = TRAP_INUSE; 2225 break; 2226 case TRAP_TYPE_NONPRIO: 2227 if (tp->tr_flags & TRAP_CONFIGURED) 2228 return 1; /* don't change anything */ 2229 tp->tr_flags = TRAP_INUSE|TRAP_NONPRIO; 2230 break; 2231 } 2232 tp->tr_settime = current_time; 2233 tp->tr_resets++; 2234 return 1; 2235 } 2236 2237 /* 2238 * First we heard of this guy. Try to find a trap structure 2239 * for him to use, clearing out lesser priority guys if we 2240 * have to. Clear out anyone who's expired while we're at it. 2241 */ 2242 tptouse = NULL; 2243 for (tp = ctl_trap; tp < &ctl_trap[CTL_MAXTRAPS]; tp++) { 2244 if ((tp->tr_flags & TRAP_INUSE) && 2245 !(tp->tr_flags & TRAP_CONFIGURED) && 2246 ((tp->tr_settime + CTL_TRAPTIME) > current_time)) { 2247 tp->tr_flags = 0; 2248 num_ctl_traps--; 2249 } 2250 2251 if (!(tp->tr_flags & TRAP_INUSE)) { 2252 tptouse = tp; 2253 } else if (!(tp->tr_flags & TRAP_CONFIGURED)) { 2254 switch (traptype) { 2255 case TRAP_TYPE_CONFIG: 2256 if (tptouse == NULL) { 2257 tptouse = tp; 2258 break; 2259 } 2260 if (tptouse->tr_flags & TRAP_NONPRIO 2261 && !(tp->tr_flags & TRAP_NONPRIO)) 2262 break; 2263 if (!(tptouse->tr_flags & TRAP_NONPRIO) 2264 && tp->tr_flags & TRAP_NONPRIO) { 2265 tptouse = tp; 2266 break; 2267 } 2268 if (tptouse->tr_origtime < tp->tr_origtime) 2269 tptouse = tp; 2270 break; 2271 case TRAP_TYPE_PRIO: 2272 if (tp->tr_flags & TRAP_NONPRIO) { 2273 if (tptouse == NULL || 2274 (tptouse->tr_flags & TRAP_INUSE 2275 && tptouse->tr_origtime 2276 < tp->tr_origtime)) 2277 tptouse = tp; 2278 } 2279 break; 2280 case TRAP_TYPE_NONPRIO: 2281 break; 2282 } 2283 } 2284 } 2285 2286 /* 2287 * If we don't have room for him return an error. 2288 */ 2289 if (tptouse == NULL) 2290 return 0; 2291 2292 /* 2293 * Set up this structure for him. 2294 */ 2295 tptouse->tr_settime = tptouse->tr_origtime = current_time; 2296 tptouse->tr_count = tptouse->tr_resets = 0; 2297 tptouse->tr_sequence = 1; 2298 tptouse->tr_addr = *raddr; 2299 tptouse->tr_localaddr = linter; 2300 tptouse->tr_version = version; 2301 2302 tptouse->tr_flags = TRAP_INUSE; 2303 if (traptype == TRAP_TYPE_CONFIG) 2304 tptouse->tr_flags |= TRAP_CONFIGURED; 2305 else if (traptype == TRAP_TYPE_NONPRIO) 2306 tptouse->tr_flags |= TRAP_NONPRIO; 2307 num_ctl_traps++; 2308 return 1; 2309 } 2310 2311 2312 /* 2313 * ctlclrtrap - called to clr a trap 2314 */ 2315 int 2316 ctlclrtrap( 2317 struct sockaddr_in *raddr, 2318 struct interface *linter, 2319 int traptype 2320 ) 2321 { 2322 register struct ctl_trap *tp; 2323 2324 if ((tp = ctlfindtrap(raddr, linter)) == NULL) 2325 return 0; 2326 2327 if (tp->tr_flags & TRAP_CONFIGURED 2328 && traptype != TRAP_TYPE_CONFIG) 2329 return 0; 2330 2331 tp->tr_flags = 0; 2332 num_ctl_traps--; 2333 return 1; 2334 } 2335 2336 2337 /* 2338 * ctlfindtrap - find a trap given the remote and local addresses 2339 */ 2340 static struct ctl_trap * 2341 ctlfindtrap( 2342 struct sockaddr_in *raddr, 2343 struct interface *linter 2344 ) 2345 { 2346 register struct ctl_trap *tp; 2347 2348 for (tp = ctl_trap; tp < &ctl_trap[CTL_MAXTRAPS]; tp++) { 2349 if (tp->tr_flags & TRAP_INUSE 2350 && NSRCADR(raddr) == NSRCADR(&tp->tr_addr) 2351 && NSRCPORT(raddr) == NSRCPORT(&tp->tr_addr) 2352 && linter == tp->tr_localaddr) 2353 return tp; 2354 } 2355 return (struct ctl_trap *)NULL; 2356 } 2357 2358 2359 /* 2360 * report_event - report an event to the trappers 2361 */ 2362 void 2363 report_event( 2364 int err, 2365 struct peer *peer 2366 ) 2367 { 2368 register int i; 2369 2370 /* 2371 * Record error code in proper spots, but have mercy on the 2372 * log file. 2373 */ 2374 if (!(err & PEER_EVENT)) { 2375 if (ctl_sys_num_events < CTL_SYS_MAXEVENTS) 2376 ctl_sys_num_events++; 2377 if (ctl_sys_last_event != (u_char)err) { 2378 NLOG(NLOG_SYSEVENT) 2379 msyslog(LOG_INFO, "system event '%s' (0x%02x) status '%s' (0x%02x)", 2380 eventstr(err), err, 2381 sysstatstr(ctlsysstatus()), ctlsysstatus()); 2382 #ifdef DEBUG 2383 if (debug) 2384 printf("report_event: system event '%s' (0x%02x) status '%s' (0x%02x)\n", 2385 eventstr(err), err, 2386 sysstatstr(ctlsysstatus()), ctlsysstatus()); 2387 #endif 2388 ctl_sys_last_event = (u_char)err; 2389 } 2390 } else if (peer != 0) { 2391 char *src; 2392 2393 #ifdef REFCLOCK 2394 if (ISREFCLOCKADR(&peer->srcadr)) 2395 src = refnumtoa(peer->srcadr.sin_addr.s_addr); 2396 else 2397 #endif 2398 src = ntoa(&peer->srcadr); 2399 2400 peer->last_event = (u_char)(err & ~PEER_EVENT); 2401 if (peer->num_events < CTL_PEER_MAXEVENTS) 2402 peer->num_events++; 2403 NLOG(NLOG_PEEREVENT) 2404 msyslog(LOG_INFO, "peer %s event '%s' (0x%02x) status '%s' (0x%02x)", 2405 src, eventstr(err), err, 2406 peerstatstr(ctlpeerstatus(peer)), ctlpeerstatus(peer)); 2407 #ifdef DEBUG 2408 if (debug) 2409 printf( "peer %s event '%s' (0x%02x) status '%s' (0x%02x)\n", 2410 src, eventstr(err), err, 2411 peerstatstr(ctlpeerstatus(peer)), ctlpeerstatus(peer)); 2412 #endif 2413 } else { 2414 msyslog(LOG_ERR, "report_event: err '%s' (0x%02x), no peer", eventstr(err), err); 2415 #ifdef DEBUG 2416 printf("report_event: peer event '%s' (0x%02x), no peer\n", eventstr(err), err); 2417 #endif 2418 return; 2419 } 2420 2421 /* 2422 * If no trappers, return. 2423 */ 2424 if (num_ctl_traps <= 0) 2425 return; 2426 2427 /* 2428 * Set up the outgoing packet variables 2429 */ 2430 res_opcode = CTL_OP_ASYNCMSG; 2431 res_offset = 0; 2432 res_async = 1; 2433 res_authenticate = 0; 2434 datapt = rpkt.data; 2435 dataend = &(rpkt.data[CTL_MAX_DATA_LEN]); 2436 2437 if (!(err & PEER_EVENT)) { 2438 rpkt.associd = 0; 2439 rpkt.status = htons(ctlsysstatus()); 2440 2441 /* 2442 * For now, put everything we know about system 2443 * variables. Maybe more selective later 2444 */ 2445 for (i = 1; i <= CS_MAXCODE; i++) 2446 ctl_putsys(i); 2447 #ifdef REFCLOCK 2448 /* 2449 * for clock exception events: 2450 * add clock variables to reflect info on exception 2451 */ 2452 if (err == EVNT_CLOCKEXCPT) { 2453 struct refclockstat clock_stat; 2454 struct ctl_var *kv; 2455 2456 clock_stat.kv_list = (struct ctl_var *)0; 2457 2458 refclock_control(&peer->srcadr, 2459 (struct refclockstat *)0, &clock_stat); 2460 ctl_puthex("refclockstatus", ctlclkstatus(&clock_stat)); 2461 2462 for (i = 1; i <= CC_MAXCODE; i++) 2463 ctl_putclock(i, &clock_stat, 0); 2464 for (kv = clock_stat.kv_list; kv && !(kv->flags & EOV); kv++) 2465 if (kv->flags & DEF) 2466 ctl_putdata(kv->text, strlen(kv->text), 0); 2467 2468 free_varlist(clock_stat.kv_list); 2469 } 2470 #endif /*REFCLOCK*/ 2471 } else { 2472 rpkt.associd = htons(peer->associd); 2473 rpkt.status = htons(ctlpeerstatus(peer)); 2474 2475 /* 2476 * Dump it all. Later, maybe less. 2477 */ 2478 for (i = 1; i <= CP_MAXCODE; i++) 2479 ctl_putpeer(i, peer); 2480 #ifdef REFCLOCK 2481 /* 2482 * for clock exception events: 2483 * add clock variables to reflect info on exception 2484 */ 2485 if (err == EVNT_PEERCLOCK) { 2486 struct refclockstat clock_stat; 2487 struct ctl_var *kv; 2488 2489 clock_stat.kv_list = (struct ctl_var *)0; 2490 2491 refclock_control(&peer->srcadr, 2492 (struct refclockstat *)0, 2493 &clock_stat); 2494 2495 ctl_puthex("refclockstatus", 2496 ctlclkstatus(&clock_stat)); 2497 2498 for (i = 1; i <= CC_MAXCODE; i++) 2499 ctl_putclock(i, &clock_stat, 0); 2500 for (kv = clock_stat.kv_list; kv && !(kv->flags & EOV); kv++) 2501 if (kv->flags & DEF) 2502 ctl_putdata(kv->text, strlen(kv->text), 0); 2503 2504 free_varlist(clock_stat.kv_list); 2505 } 2506 #endif /*REFCLOCK*/ 2507 } 2508 2509 /* 2510 * We're done, return. 2511 */ 2512 ctl_flushpkt(0); 2513 } 2514 2515 2516 /* 2517 * ctl_clr_stats - clear stat counters 2518 */ 2519 void 2520 ctl_clr_stats(void) 2521 { 2522 ctltimereset = current_time; 2523 numctlreq = 0; 2524 numctlbadpkts = 0; 2525 numctlresponses = 0; 2526 numctlfrags = 0; 2527 numctlerrors = 0; 2528 numctlfrags = 0; 2529 numctltooshort = 0; 2530 numctlinputresp = 0; 2531 numctlinputfrag = 0; 2532 numctlinputerr = 0; 2533 numctlbadoffset = 0; 2534 numctlbadversion = 0; 2535 numctldatatooshort = 0; 2536 numctlbadop = 0; 2537 numasyncmsgs = 0; 2538 } 2539 2540 static u_long 2541 count_var( 2542 struct ctl_var *k 2543 ) 2544 { 2545 register u_long c; 2546 2547 if (!k) 2548 return 0; 2549 2550 c = 0; 2551 2552 while (!(k++->flags & EOV)) 2553 c++; 2554 2555 return c; 2556 } 2557 2558 char * 2559 add_var( 2560 struct ctl_var **kv, 2561 u_long size, 2562 int def 2563 ) 2564 { 2565 register u_long c; 2566 register struct ctl_var *k; 2567 2568 c = count_var(*kv); 2569 2570 k = *kv; 2571 *kv = (struct ctl_var *)emalloc((c+2)*sizeof(struct ctl_var)); 2572 if (k) 2573 { 2574 memmove((char *)*kv, (char *)k, sizeof(struct ctl_var)*c); 2575 free((char *)k); 2576 } 2577 2578 (*kv)[c].code = (u_short) c; 2579 (*kv)[c].text = (char *)emalloc(size); 2580 (*kv)[c].flags = def; 2581 (*kv)[c+1].code = 0; 2582 (*kv)[c+1].text = (char *)0; 2583 (*kv)[c+1].flags = EOV; 2584 return (char *)(*kv)[c].text; 2585 } 2586 2587 void 2588 set_var( 2589 struct ctl_var **kv, 2590 const char *data, 2591 u_long size, 2592 int def 2593 ) 2594 { 2595 register struct ctl_var *k; 2596 register const char *s; 2597 register const char *t; 2598 char *td; 2599 2600 if (!data || !size) 2601 return; 2602 2603 if ((k = *kv)) 2604 { 2605 while (!(k->flags & EOV)) 2606 { 2607 s = data; 2608 t = k->text; 2609 if (t) 2610 { 2611 while (*t != '=' && *s - *t == 0) 2612 { 2613 s++; 2614 t++; 2615 } 2616 if (*s == *t && ((*t == '=') || !*t)) 2617 { 2618 free((void *)k->text); 2619 td = (char *)emalloc(size); 2620 memmove(td, data, size); 2621 k->text =td; 2622 k->flags = def; 2623 return; 2624 } 2625 } 2626 else 2627 { 2628 td = (char *)emalloc(size); 2629 memmove(td, data, size); 2630 k->text = td; 2631 k->flags = def; 2632 return; 2633 } 2634 k++; 2635 } 2636 } 2637 td = add_var(kv, size, def); 2638 memmove(td, data, size); 2639 } 2640 2641 void 2642 set_sys_var( 2643 char *data, 2644 u_long size, 2645 int def 2646 ) 2647 { 2648 set_var(&ext_sys_var, data, size, def); 2649 } 2650 2651 void 2652 free_varlist( 2653 struct ctl_var *kv 2654 ) 2655 { 2656 struct ctl_var *k; 2657 if (kv) 2658 { 2659 for (k = kv; !(k->flags & EOV); k++) 2660 free((void *)k->text); 2661 free((void *)kv); 2662 } 2663 } 2664