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