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