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