2 * ntp_control.c - respond to control messages and send async traps
15 #include "ntp_refclock.h"
16 #include "ntp_control.h"
17 #include "ntp_unixtime.h"
18 #include "ntp_stdlib.h"
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
28 #define MIN(a, b) (((a) <= (b)) ? (a) : (b))
32 * Structure to hold request procedure information
37 #define NO_REQUEST (-1)
40 short control_code; /* defined request code */
41 u_short flags; /* flags word */
42 void (*handler) P((struct recvbuf *, int)); /* handle request */
46 * Only one flag. Authentication required or not.
52 * Request processing routines
54 static void ctl_error P((int));
56 static u_short ctlclkstatus P((struct refclockstat *));
58 static void ctl_flushpkt P((int));
59 static void ctl_putdata P((const char *, unsigned int, int));
60 static void ctl_putstr P((const char *, const char *,
62 static void ctl_putdbl P((const char *, double));
63 static void ctl_putuint P((const char *, u_long));
64 static void ctl_puthex P((const char *, u_long));
65 static void ctl_putint P((const char *, long));
66 static void ctl_putts P((const char *, l_fp *));
67 static void ctl_putadr P((const char *, u_int32, struct sockaddr_storage*));
68 static void ctl_putid P((const char *, char *));
69 static void ctl_putarray P((const char *, double *, int));
70 static void ctl_putsys P((int));
71 static void ctl_putpeer P((int, struct peer *));
73 static void ctl_putfs P((const char *, tstamp_t));
76 static void ctl_putclock P((int, struct refclockstat *, int));
78 static struct ctl_var *ctl_getitem P((struct ctl_var *, char **));
79 static u_long count_var P((struct ctl_var *));
80 static void control_unspec P((struct recvbuf *, int));
81 static void read_status P((struct recvbuf *, int));
82 static void read_variables P((struct recvbuf *, int));
83 static void write_variables P((struct recvbuf *, int));
84 static void read_clock_status P((struct recvbuf *, int));
85 static void write_clock_status P((struct recvbuf *, int));
86 static void set_trap P((struct recvbuf *, int));
87 static void unset_trap P((struct recvbuf *, int));
88 static struct ctl_trap *ctlfindtrap P((struct sockaddr_storage *,
91 static struct ctl_proc control_codes[] = {
92 { CTL_OP_UNSPEC, NOAUTH, control_unspec },
93 { CTL_OP_READSTAT, NOAUTH, read_status },
94 { CTL_OP_READVAR, NOAUTH, read_variables },
95 { CTL_OP_WRITEVAR, AUTH, write_variables },
96 { CTL_OP_READCLOCK, NOAUTH, read_clock_status },
97 { CTL_OP_WRITECLOCK, NOAUTH, write_clock_status },
98 { CTL_OP_SETTRAP, NOAUTH, set_trap },
99 { CTL_OP_UNSETTRAP, NOAUTH, unset_trap },
104 * System variable values. The array can be indexed by the variable
105 * index to find the textual name.
107 static struct ctl_var sys_var[] = {
108 { 0, PADDING, "" }, /* 0 */
109 { CS_LEAP, RW, "leap" }, /* 1 */
110 { CS_STRATUM, RO, "stratum" }, /* 2 */
111 { CS_PRECISION, RO, "precision" }, /* 3 */
112 { CS_ROOTDELAY, RO, "rootdelay" }, /* 4 */
113 { CS_ROOTDISPERSION, RO, "rootdispersion" }, /* 5 */
114 { CS_REFID, RO, "refid" }, /* 6 */
115 { CS_REFTIME, RO, "reftime" }, /* 7 */
116 { CS_POLL, RO, "poll" }, /* 8 */
117 { CS_PEERID, RO, "peer" }, /* 9 */
118 { CS_STATE, RO, "state" }, /* 10 */
119 { CS_OFFSET, RO, "offset" }, /* 11 */
120 { CS_DRIFT, RO, "frequency" }, /* 12 */
121 { CS_JITTER, RO, "jitter" }, /* 13 */
122 { CS_ERROR, RO, "noise" }, /* 14 */
123 { CS_CLOCK, RO, "clock" }, /* 15 */
124 { CS_PROCESSOR, RO, "processor" }, /* 16 */
125 { CS_SYSTEM, RO, "system" }, /* 17 */
126 { CS_VERSION, RO, "version" }, /* 18 */
127 { CS_STABIL, RO, "stability" }, /* 19 */
128 { CS_VARLIST, RO, "sys_var_list" }, /* 20 */
130 { CS_FLAGS, RO, "flags" }, /* 21 */
131 { CS_HOST, RO, "hostname" }, /* 22 */
132 { CS_PUBLIC, RO, "update" }, /* 23 */
133 { CS_CERTIF, RO, "cert" }, /* 24 */
134 { CS_REVTIME, RO, "expire" }, /* 25 */
135 { CS_LEAPTAB, RO, "leapsec" }, /* 26 */
136 { CS_TAI, RO, "tai" }, /* 27 */
137 { CS_DIGEST, RO, "signature" }, /* 28 */
138 { CS_IDENT, RO, "ident" }, /* 29 */
139 { CS_REVOKE, RO, "expire" }, /* 30 */
141 { 0, EOV, "" } /* 21/31 */
144 static struct ctl_var *ext_sys_var = (struct ctl_var *)0;
147 * System variables we print by default (in fuzzball order,
150 static u_char def_sys_var[] = {
187 static struct ctl_var peer_var[] = {
188 { 0, PADDING, "" }, /* 0 */
189 { CP_CONFIG, RO, "config" }, /* 1 */
190 { CP_AUTHENABLE, RO, "authenable" }, /* 2 */
191 { CP_AUTHENTIC, RO, "authentic" }, /* 3 */
192 { CP_SRCADR, RO, "srcadr" }, /* 4 */
193 { CP_SRCPORT, RO, "srcport" }, /* 5 */
194 { CP_DSTADR, RO, "dstadr" }, /* 6 */
195 { CP_DSTPORT, RO, "dstport" }, /* 7 */
196 { CP_LEAP, RO, "leap" }, /* 8 */
197 { CP_HMODE, RO, "hmode" }, /* 9 */
198 { CP_STRATUM, RO, "stratum" }, /* 10 */
199 { CP_PPOLL, RO, "ppoll" }, /* 11 */
200 { CP_HPOLL, RO, "hpoll" }, /* 12 */
201 { CP_PRECISION, RO, "precision" }, /* 13 */
202 { CP_ROOTDELAY, RO, "rootdelay" }, /* 14 */
203 { CP_ROOTDISPERSION, RO, "rootdispersion" }, /* 15 */
204 { CP_REFID, RO, "refid" }, /* 16 */
205 { CP_REFTIME, RO, "reftime" }, /* 17 */
206 { CP_ORG, RO, "org" }, /* 18 */
207 { CP_REC, RO, "rec" }, /* 19 */
208 { CP_XMT, RO, "xmt" }, /* 20 */
209 { CP_REACH, RO, "reach" }, /* 21 */
210 { CP_UNREACH, RO, "unreach" }, /* 22 */
211 { CP_TIMER, RO, "timer" }, /* 23 */
212 { CP_DELAY, RO, "delay" }, /* 24 */
213 { CP_OFFSET, RO, "offset" }, /* 25 */
214 { CP_JITTER, RO, "jitter" }, /* 26 */
215 { CP_DISPERSION, RO, "dispersion" }, /* 27 */
216 { CP_KEYID, RO, "keyid" }, /* 28 */
217 { CP_FILTDELAY, RO, "filtdelay=" }, /* 29 */
218 { CP_FILTOFFSET, RO, "filtoffset=" }, /* 30 */
219 { CP_PMODE, RO, "pmode" }, /* 31 */
220 { CP_RECEIVED, RO, "received"}, /* 32 */
221 { CP_SENT, RO, "sent" }, /* 33 */
222 { CP_FILTERROR, RO, "filtdisp=" }, /* 34 */
223 { CP_FLASH, RO, "flash" }, /* 35 */
224 { CP_TTL, RO, "ttl" }, /* 36 */
225 { CP_VARLIST, RO, "peer_var_list" }, /* 37 */
227 { CP_FLAGS, RO, "flags" }, /* 38 */
228 { CP_HOST, RO, "hostname" }, /* 39 */
229 { CP_VALID, RO, "valid" }, /* 40 */
230 { CP_INITSEQ, RO, "initsequence" }, /* 41 */
231 { CP_INITKEY, RO, "initkey" }, /* 42 */
232 { CP_INITTSP, RO, "timestamp" }, /* 43 */
233 { CP_DIGEST, RO, "signature" }, /* 44 */
234 { CP_IDENT, RO, "trust" }, /* 45 */
236 { 0, EOV, "" } /* 38/46 */
241 * Peer variables we print by default
243 static u_char def_peer_var[] = {
288 * Clock variable list
290 static struct ctl_var clock_var[] = {
291 { 0, PADDING, "" }, /* 0 */
292 { CC_TYPE, RO, "type" }, /* 1 */
293 { CC_TIMECODE, RO, "timecode" }, /* 2 */
294 { CC_POLL, RO, "poll" }, /* 3 */
295 { CC_NOREPLY, RO, "noreply" }, /* 4 */
296 { CC_BADFORMAT, RO, "badformat" }, /* 5 */
297 { CC_BADDATA, RO, "baddata" }, /* 6 */
298 { CC_FUDGETIME1, RO, "fudgetime1" }, /* 7 */
299 { CC_FUDGETIME2, RO, "fudgetime2" }, /* 8 */
300 { CC_FUDGEVAL1, RO, "stratum" }, /* 9 */
301 { CC_FUDGEVAL2, RO, "refid" }, /* 10 */
302 { CC_FLAGS, RO, "flags" }, /* 11 */
303 { CC_DEVICE, RO, "device" }, /* 12 */
304 { CC_VARLIST, RO, "clock_var_list" }, /* 13 */
305 { 0, EOV, "" } /* 14 */
310 * Clock variables printed by default
312 static u_char def_clock_var[] = {
314 CC_TYPE, /* won't be output if device = known */
331 * System and processor definitions.
335 # define STR_SYSTEM "UNIX"
337 # ifndef STR_PROCESSOR
338 # define STR_PROCESSOR "unknown"
341 static char str_system[] = STR_SYSTEM;
342 static char str_processor[] = STR_PROCESSOR;
344 # include <sys/utsname.h>
345 static struct utsname utsnamebuf;
346 #endif /* HAVE_UNAME */
349 * Trap structures. We only allow a few of these, and send a copy of
350 * each async message to each live one. Traps time out after an hour, it
351 * is up to the trap receipient to keep resetting it to avoid being
355 struct ctl_trap ctl_trap[CTL_MAXTRAPS];
359 * Type bits, for ctlsettrap() call.
361 #define TRAP_TYPE_CONFIG 0 /* used by configuration code */
362 #define TRAP_TYPE_PRIO 1 /* priority trap */
363 #define TRAP_TYPE_NONPRIO 2 /* nonpriority trap */
367 * List relating reference clock types to control message time sources.
368 * Index by the reference clock type. This list will only be used iff
369 * the reference clock driver doesn't set peer->sstclktype to something
370 * different than CTL_SST_TS_UNSPEC.
372 static u_char clocktypes[] = {
373 CTL_SST_TS_NTP, /* REFCLK_NONE (0) */
374 CTL_SST_TS_LOCAL, /* REFCLK_LOCALCLOCK (1) */
375 CTL_SST_TS_UHF, /* deprecated REFCLK_GPS_TRAK (2) */
376 CTL_SST_TS_HF, /* REFCLK_WWV_PST (3) */
377 CTL_SST_TS_LF, /* REFCLK_WWVB_SPECTRACOM (4) */
378 CTL_SST_TS_UHF, /* REFCLK_TRUETIME (5) */
379 CTL_SST_TS_UHF, /* REFCLK_GOES_TRAK (6) IRIG_AUDIO? */
380 CTL_SST_TS_HF, /* REFCLK_CHU (7) */
381 CTL_SST_TS_LF, /* REFCLOCK_PARSE (default) (8) */
382 CTL_SST_TS_LF, /* REFCLK_GPS_MX4200 (9) */
383 CTL_SST_TS_UHF, /* REFCLK_GPS_AS2201 (10) */
384 CTL_SST_TS_UHF, /* REFCLK_GPS_ARBITER (11) */
385 CTL_SST_TS_UHF, /* REFCLK_IRIG_TPRO (12) */
386 CTL_SST_TS_ATOM, /* REFCLK_ATOM_LEITCH (13) */
387 CTL_SST_TS_LF, /* deprecated REFCLK_MSF_EES (14) */
388 CTL_SST_TS_NTP, /* not used (15) */
389 CTL_SST_TS_UHF, /* REFCLK_IRIG_BANCOMM (16) */
390 CTL_SST_TS_UHF, /* REFCLK_GPS_DATU (17) */
391 CTL_SST_TS_TELEPHONE, /* REFCLK_NIST_ACTS (18) */
392 CTL_SST_TS_HF, /* REFCLK_WWV_HEATH (19) */
393 CTL_SST_TS_UHF, /* REFCLK_GPS_NMEA (20) */
394 CTL_SST_TS_UHF, /* REFCLK_GPS_VME (21) */
395 CTL_SST_TS_ATOM, /* REFCLK_ATOM_PPS (22) */
396 CTL_SST_TS_NTP, /* not used (23) */
397 CTL_SST_TS_NTP, /* not used (24) */
398 CTL_SST_TS_NTP, /* not used (25) */
399 CTL_SST_TS_UHF, /* REFCLK_GPS_HP (26) */
400 CTL_SST_TS_TELEPHONE, /* REFCLK_ARCRON_MSF (27) */
401 CTL_SST_TS_TELEPHONE, /* REFCLK_SHM (28) */
402 CTL_SST_TS_UHF, /* REFCLK_PALISADE (29) */
403 CTL_SST_TS_UHF, /* REFCLK_ONCORE (30) */
404 CTL_SST_TS_UHF, /* REFCLK_JUPITER (31) */
405 CTL_SST_TS_LF, /* REFCLK_CHRONOLOG (32) */
406 CTL_SST_TS_LF, /* REFCLK_DUMBCLOCK (33) */
407 CTL_SST_TS_LF, /* REFCLK_ULINK (34) */
408 CTL_SST_TS_LF, /* REFCLK_PCF (35) */
409 CTL_SST_TS_LF, /* REFCLK_WWV (36) */
410 CTL_SST_TS_LF, /* REFCLK_FG (37) */
411 CTL_SST_TS_UHF, /* REFCLK_HOPF_SERIAL (38) */
412 CTL_SST_TS_UHF, /* REFCLK_HOPF_PCI (39) */
413 CTL_SST_TS_LF, /* REFCLK_JJY (40) */
414 CTL_SST_TS_UHF, /* REFCLK_TT560 (41) */
415 CTL_SST_TS_UHF, /* REFCLK_ZYFER (42) */
416 CTL_SST_TS_UHF, /* REFCLK_RIPENCC (43) */
417 CTL_SST_TS_UHF, /* REFCLK_NEOCLOCK4X (44) */
422 * Keyid used for authenticating write requests.
424 keyid_t ctl_auth_keyid;
427 * We keep track of the last error reported by the system internally
429 static u_char ctl_sys_last_event;
430 static u_char ctl_sys_num_events;
434 * Statistic counters to keep track of requests and responses.
436 u_long ctltimereset; /* time stats reset */
437 u_long numctlreq; /* number of requests we've received */
438 u_long numctlbadpkts; /* number of bad control packets */
439 u_long numctlresponses; /* number of resp packets sent with data */
440 u_long numctlfrags; /* number of fragments sent */
441 u_long numctlerrors; /* number of error responses sent */
442 u_long numctltooshort; /* number of too short input packets */
443 u_long numctlinputresp; /* number of responses on input */
444 u_long numctlinputfrag; /* number of fragments on input */
445 u_long numctlinputerr; /* number of input pkts with err bit set */
446 u_long numctlbadoffset; /* number of input pkts with nonzero offset */
447 u_long numctlbadversion; /* number of input pkts with unknown version */
448 u_long numctldatatooshort; /* data too short for count */
449 u_long numctlbadop; /* bad op code found in packet */
450 u_long numasyncmsgs; /* number of async messages we've sent */
453 * Response packet used by these routines. Also some state information
454 * so that we can handle packet formatting within a common set of
455 * subroutines. Note we try to enter data in place whenever possible,
456 * but the need to set the more bit correctly means we occasionally
457 * use the extra buffer and copy.
459 static struct ntp_control rpkt;
460 static u_char res_version;
461 static u_char res_opcode;
462 static associd_t res_associd;
463 static int res_offset;
464 static u_char * datapt;
465 static u_char * dataend;
466 static int datalinelen;
467 static int datanotbinflag;
468 static struct sockaddr_storage *rmt_addr;
469 static struct interface *lcl_inter;
471 static u_char res_authenticate;
472 static u_char res_authokay;
473 static keyid_t res_keyid;
475 #define MAXDATALINELEN (72)
477 static u_char res_async; /* set to 1 if this is async trap response */
480 * Pointers for saving state when decoding request packets
486 * init_control - initialize request data
495 #endif /* HAVE_UNAME */
500 ctl_sys_last_event = EVNT_UNSPEC;
501 ctl_sys_num_events = 0;
504 for (i = 0; i < CTL_MAXTRAPS; i++)
505 ctl_trap[i].tr_flags = 0;
510 * ctl_error - send an error response for the current request
519 printf("sending control error %d\n", errcode);
522 * Fill in the fields. We assume rpkt.sequence and rpkt.associd
523 * have already been filled in.
525 rpkt.r_m_e_op = (u_char) (CTL_RESPONSE|CTL_ERROR|(res_opcode &
527 rpkt.status = htons((u_short) ((errcode<<8) & 0xff00));
531 * send packet and bump counters
533 if (res_authenticate && sys_authenticate) {
536 *(u_int32 *)((u_char *)&rpkt + CTL_HEADER_LEN) =
538 maclen = authencrypt(res_keyid, (u_int32 *)&rpkt,
540 sendpkt(rmt_addr, lcl_inter, -2, (struct pkt *)&rpkt,
541 CTL_HEADER_LEN + maclen);
543 sendpkt(rmt_addr, lcl_inter, -3, (struct pkt *)&rpkt,
551 * process_control - process an incoming control message
555 struct recvbuf *rbufp,
559 register struct ntp_control *pkt;
560 register int req_count;
561 register int req_data;
562 register struct ctl_proc *cc;
568 printf("in process_control()\n");
572 * Save the addresses for error responses
575 rmt_addr = &rbufp->recv_srcadr;
576 lcl_inter = rbufp->dstadr;
577 pkt = (struct ntp_control *)&rbufp->recv_pkt;
580 * If the length is less than required for the header, or
581 * it is a response or a fragment, ignore this.
583 if (rbufp->recv_length < CTL_HEADER_LEN
584 || pkt->r_m_e_op & (CTL_RESPONSE|CTL_MORE|CTL_ERROR)
585 || pkt->offset != 0) {
588 printf("invalid format in control packet\n");
590 if (rbufp->recv_length < CTL_HEADER_LEN)
592 if (pkt->r_m_e_op & CTL_RESPONSE)
594 if (pkt->r_m_e_op & CTL_MORE)
596 if (pkt->r_m_e_op & CTL_ERROR)
598 if (pkt->offset != 0)
602 res_version = PKT_VERSION(pkt->li_vn_mode);
603 if (res_version > NTP_VERSION || res_version < NTP_OLDVERSION) {
606 printf("unknown version %d in control packet\n",
614 * Pull enough data from the packet to make intelligent
617 rpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap, res_version,
619 res_opcode = pkt->r_m_e_op;
620 rpkt.sequence = pkt->sequence;
621 rpkt.associd = pkt->associd;
624 res_associd = htons(pkt->associd);
626 res_authenticate = 0;
629 req_count = (int)htons(pkt->count);
633 dataend = &(rpkt.data[CTL_MAX_DATA_LEN]);
636 * We're set up now. Make sure we've got at least enough
637 * incoming data space to match the count.
639 req_data = rbufp->recv_length - CTL_HEADER_LEN;
640 if (req_data < req_count || rbufp->recv_length & 0x3) {
641 ctl_error(CERR_BADFMT);
642 numctldatatooshort++;
646 properlen = req_count + CTL_HEADER_LEN;
648 if (debug > 2 && (rbufp->recv_length & 0x3) != 0)
649 printf("Packet length %d unrounded\n",
652 /* round up proper len to a 8 octet boundary */
654 properlen = (properlen + 7) & ~7;
655 maclen = rbufp->recv_length - properlen;
656 if ((rbufp->recv_length & (sizeof(u_long) - 1)) == 0 &&
657 maclen >= MIN_MAC_LEN && maclen <= MAX_MAC_LEN &&
659 res_authenticate = 1;
660 res_keyid = ntohl(*(u_int32 *)((u_char *)pkt +
666 "recv_len %d, properlen %d, wants auth with keyid %08x, MAC length=%d\n",
667 rbufp->recv_length, properlen, res_keyid, maclen);
669 if (!authistrusted(res_keyid)) {
672 printf("invalid keyid %08x\n",
675 } else if (authdecrypt(res_keyid, (u_int32 *)pkt,
676 rbufp->recv_length - maclen, maclen)) {
679 printf("authenticated okay\n");
685 printf("authentication failed\n");
692 * Set up translate pointers
694 reqpt = (char *)pkt->data;
695 reqend = reqpt + req_count;
698 * Look for the opcode processor
700 for (cc = control_codes; cc->control_code != NO_REQUEST; cc++) {
701 if (cc->control_code == res_opcode) {
704 printf("opcode %d, found command handler\n",
707 if (cc->flags == AUTH && (!res_authokay ||
708 res_keyid != ctl_auth_keyid)) {
709 ctl_error(CERR_PERMISSION);
712 (cc->handler)(rbufp, restrict_mask);
718 * Can't find this one, return an error.
721 ctl_error(CERR_BADOP);
727 * ctlpeerstatus - return a status word for this peer
731 register struct peer *peer
734 register u_short status;
736 status = peer->status;
737 if (peer->flags & FLAG_CONFIG)
738 status |= CTL_PST_CONFIG;
739 if (peer->flags & FLAG_AUTHENABLE)
740 status |= CTL_PST_AUTHENABLE;
741 if (peer->flags & FLAG_AUTHENTIC)
742 status |= CTL_PST_AUTHENTIC;
743 if (peer->reach != 0)
744 status |= CTL_PST_REACH;
745 return (u_short)CTL_PEER_STATUS(status, peer->num_events,
751 * ctlclkstatus - return a status word for this clock
756 struct refclockstat *this_clock
759 return ((u_short)(((this_clock->currentstatus) << 8) |
760 (this_clock->lastevent)));
766 * ctlsysstatus - return the system status word
771 register u_char this_clock;
773 this_clock = CTL_SST_TS_UNSPEC;
776 if (sys_peer->sstclktype != CTL_SST_TS_UNSPEC) {
777 this_clock = sys_peer->sstclktype;
779 this_clock |= CTL_SST_TS_PPS;
781 if (sys_peer->refclktype < sizeof(clocktypes))
783 clocktypes[sys_peer->refclktype];
785 this_clock |= CTL_SST_TS_PPS;
788 #endif /* REFCLOCK */
789 return (u_short)CTL_SYS_STATUS(sys_leap, this_clock,
790 ctl_sys_num_events, ctl_sys_last_event);
795 * ctl_flushpkt - write out the current packet and prepare
796 * another if necessary.
806 if (!more && datanotbinflag) {
808 * Big hack, output a trailing \r\n
813 dlen = datapt - (u_char *)rpkt.data;
814 sendlen = dlen + CTL_HEADER_LEN;
817 * Pad to a multiple of 32 bits
819 while (sendlen & 0x3) {
825 * Fill in the packet with the current info
827 rpkt.r_m_e_op = (u_char)(CTL_RESPONSE|more|(res_opcode &
829 rpkt.count = htons((u_short) dlen);
830 rpkt.offset = htons( (u_short) res_offset);
834 for (i = 0; i < CTL_MAXTRAPS; i++) {
835 if (ctl_trap[i].tr_flags & TRAP_INUSE) {
837 PKT_LI_VN_MODE(sys_leap,
838 ctl_trap[i].tr_version,
841 htons(ctl_trap[i].tr_sequence);
842 sendpkt(&ctl_trap[i].tr_addr,
843 ctl_trap[i].tr_localaddr, -4,
844 (struct pkt *)&rpkt, sendlen);
846 ctl_trap[i].tr_sequence++;
851 if (res_authenticate && sys_authenticate) {
853 int totlen = sendlen;
854 keyid_t keyid = htonl(res_keyid);
857 * If we are going to authenticate, then there
858 * is an additional requirement that the MAC
859 * begin on a 64 bit boundary.
865 memcpy(datapt, &keyid, sizeof keyid);
866 maclen = authencrypt(res_keyid,
867 (u_int32 *)&rpkt, totlen);
868 sendpkt(rmt_addr, lcl_inter, -5,
869 (struct pkt *)&rpkt, totlen + maclen);
871 sendpkt(rmt_addr, lcl_inter, -6,
872 (struct pkt *)&rpkt, sendlen);
881 * Set us up for another go around.
884 datapt = (u_char *)rpkt.data;
889 * ctl_putdata - write data into the packet, fragmenting and starting
890 * another if this one is full.
896 int bin /* set to 1 when data is binary */
900 unsigned int currentlen;
906 if (datapt != rpkt.data) {
909 if ((dlen + datalinelen + 1) >= MAXDATALINELEN)
922 * Save room for trailing junk
924 while (dlen + overhead + datapt > dataend) {
926 * Not enough room in this one, flush it out.
928 currentlen = MIN(dlen, dataend - datapt);
930 memcpy(datapt, dp, currentlen);
932 datapt += currentlen;
935 datalinelen += currentlen;
937 ctl_flushpkt(CTL_MORE);
940 memmove((char *)datapt, dp, (unsigned)dlen);
947 * ctl_putstr - write a tagged string into the response packet
957 register const char *cq;
967 if (len > (int) (sizeof(buffer) - (cp - buffer) - 1))
968 len = sizeof(buffer) - (cp - buffer) - 1;
969 memmove(cp, data, (unsigned)len);
973 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
978 * ctl_putdbl - write a tagged, signed double into the response packet
987 register const char *cq;
995 (void)sprintf(cp, "%.3f", ts);
998 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1002 * ctl_putuint - write a tagged unsigned integer into the response
1011 register const char *cq;
1020 (void) sprintf(cp, "%lu", uval);
1023 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1027 * ctl_putfs - write a decoded filestamp into the response
1037 register const char *cq;
1039 struct tm *tm = NULL;
1048 fstamp = uval - JAN_1970;
1049 tm = gmtime(&fstamp);
1053 sprintf(cp, "%04d%02d%02d%02d%02d", tm->tm_year + 1900,
1054 tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min);
1057 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1063 * ctl_puthex - write a tagged unsigned integer, in hex, into the response
1072 register const char *cq;
1081 (void) sprintf(cp, "0x%lx", uval);
1084 ctl_putdata(buffer,(unsigned)( cp - buffer ), 0);
1089 * ctl_putint - write a tagged signed integer into the response
1098 register const char *cq;
1107 (void) sprintf(cp, "%ld", ival);
1110 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1115 * ctl_putts - write a tagged timestamp, in hex, into the response
1124 register const char *cq;
1133 (void) sprintf(cp, "0x%08lx.%08lx",
1134 ts->l_ui & ULONG_CONST(0xffffffff),
1135 ts->l_uf & ULONG_CONST(0xffffffff));
1138 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1143 * ctl_putadr - write an IP address into the response
1149 struct sockaddr_storage* addr
1153 register const char *cq;
1163 cq = numtoa(addr32);
1168 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1172 * ctl_putid - write a tagged clock ID into the response
1181 register const char *cq;
1191 while (*cq != '\0' && (cq - id) < 4)
1193 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1198 * ctl_putarray - write a tagged eight element double array into the response
1208 register const char *cq;
1220 (void)sprintf(cp, " %.2f", arr[i] * 1e3);
1223 } while(i != start);
1224 ctl_putdata(buffer, (unsigned)(cp - buffer), 0);
1229 * ctl_putsys - output a system variable
1239 struct cert_info *cp;
1241 #endif /* OPENSSL */
1246 ctl_putuint(sys_var[CS_LEAP].text, sys_leap);
1250 ctl_putuint(sys_var[CS_STRATUM].text, sys_stratum);
1254 ctl_putint(sys_var[CS_PRECISION].text, sys_precision);
1258 ctl_putdbl(sys_var[CS_ROOTDELAY].text, sys_rootdelay *
1262 case CS_ROOTDISPERSION:
1263 ctl_putdbl(sys_var[CS_ROOTDISPERSION].text,
1264 sys_rootdispersion * 1e3);
1268 if (sys_stratum > 1 && sys_stratum < STRATUM_UNSPEC)
1269 ctl_putadr(sys_var[CS_REFID].text, sys_refid, NULL);
1271 ctl_putid(sys_var[CS_REFID].text,
1272 (char *)&sys_refid);
1276 ctl_putts(sys_var[CS_REFTIME].text, &sys_reftime);
1280 ctl_putuint(sys_var[CS_POLL].text, sys_poll);
1284 if (sys_peer == NULL)
1285 ctl_putuint(sys_var[CS_PEERID].text, 0);
1287 ctl_putuint(sys_var[CS_PEERID].text,
1292 ctl_putuint(sys_var[CS_STATE].text, (unsigned)state);
1296 ctl_putdbl(sys_var[CS_OFFSET].text, last_offset * 1e3);
1300 ctl_putdbl(sys_var[CS_DRIFT].text, drift_comp * 1e6);
1304 ctl_putdbl(sys_var[CS_JITTER].text, sys_jitter * 1e3);
1308 ctl_putdbl(sys_var[CS_ERROR].text, clock_jitter * 1e3);
1313 ctl_putts(sys_var[CS_CLOCK].text, &tmp);
1318 ctl_putstr(sys_var[CS_PROCESSOR].text, str_processor,
1319 sizeof(str_processor) - 1);
1321 ctl_putstr(sys_var[CS_PROCESSOR].text,
1322 utsnamebuf.machine, strlen(utsnamebuf.machine));
1323 #endif /* HAVE_UNAME */
1328 ctl_putstr(sys_var[CS_SYSTEM].text, str_system,
1329 sizeof(str_system) - 1);
1331 sprintf(str, "%s/%s", utsnamebuf.sysname, utsnamebuf.release);
1332 ctl_putstr(sys_var[CS_SYSTEM].text, str, strlen(str));
1333 #endif /* HAVE_UNAME */
1337 ctl_putstr(sys_var[CS_VERSION].text, Version,
1342 ctl_putdbl(sys_var[CS_STABIL].text, clock_stability *
1348 char buf[CTL_MAX_DATA_LEN];
1349 register char *s, *t, *be;
1350 register const char *ss;
1352 register struct ctl_var *k;
1355 be = buf + sizeof(buf) -
1356 strlen(sys_var[CS_VARLIST].text) - 4;
1358 break; /* really long var name */
1360 strcpy(s, sys_var[CS_VARLIST].text);
1364 for (k = sys_var; !(k->flags &EOV); k++) {
1365 if (k->flags & PADDING)
1367 i = strlen(k->text);
1377 for (k = ext_sys_var; k && !(k->flags &EOV);
1379 if (k->flags & PADDING)
1386 while (*ss && *ss != '=')
1389 if (s + i + 1 >= be)
1404 ctl_putdata(buf, (unsigned)( s - buf ),
1412 ctl_puthex(sys_var[CS_FLAGS].text, crypto_flags);
1420 dp = EVP_get_digestbynid(crypto_flags >> 16);
1421 strcpy(str, OBJ_nid2ln(EVP_MD_pkey_type(dp)));
1422 ctl_putstr(sys_var[CS_DIGEST].text, str,
1428 if (sys_hostname != NULL)
1429 ctl_putstr(sys_var[CS_HOST].text, sys_hostname,
1430 strlen(sys_hostname));
1434 for (cp = cinfo; cp != NULL; cp = cp->link) {
1435 sprintf(cbuf, "%s %s 0x%x", cp->subject,
1436 cp->issuer, cp->flags);
1437 ctl_putstr(sys_var[CS_CERTIF].text, cbuf,
1439 ctl_putfs(sys_var[CS_REVOKE].text, cp->last);
1444 if (hostval.fstamp != 0)
1445 ctl_putfs(sys_var[CS_PUBLIC].text,
1446 ntohl(hostval.tstamp));
1450 if (hostval.tstamp != 0)
1451 ctl_putfs(sys_var[CS_REVTIME].text,
1452 ntohl(hostval.tstamp));
1456 if (iffpar_pkey != NULL)
1457 ctl_putstr(sys_var[CS_IDENT].text,
1458 iffpar_file, strlen(iffpar_file));
1459 if (gqpar_pkey != NULL)
1460 ctl_putstr(sys_var[CS_IDENT].text,
1461 gqpar_file, strlen(gqpar_file));
1462 if (mvpar_pkey != NULL)
1463 ctl_putstr(sys_var[CS_IDENT].text,
1464 mvpar_file, strlen(mvpar_file));
1468 if (tai_leap.fstamp != 0)
1469 ctl_putfs(sys_var[CS_LEAPTAB].text,
1470 ntohl(tai_leap.fstamp));
1474 ctl_putuint(sys_var[CS_TAI].text, sys_tai);
1476 #endif /* OPENSSL */
1482 * ctl_putpeer - output a peer variable
1494 #endif /* OPENSSL */
1499 ctl_putuint(peer_var[CP_CONFIG].text,
1500 (unsigned)((peer->flags & FLAG_CONFIG) != 0));
1504 ctl_putuint(peer_var[CP_AUTHENABLE].text,
1505 (unsigned)((peer->flags & FLAG_AUTHENABLE) != 0));
1509 ctl_putuint(peer_var[CP_AUTHENTIC].text,
1510 (unsigned)((peer->flags & FLAG_AUTHENTIC) != 0));
1514 ctl_putadr(peer_var[CP_SRCADR].text, 0,
1519 ctl_putuint(peer_var[CP_SRCPORT].text,
1520 ntohs(((struct sockaddr_in*)&peer->srcadr)->sin_port));
1525 ctl_putadr(peer_var[CP_DSTADR].text, 0,
1526 &(peer->dstadr->sin));
1528 ctl_putadr(peer_var[CP_DSTADR].text, 0,
1534 ctl_putuint(peer_var[CP_DSTPORT].text,
1535 (u_long)(peer->dstadr ?
1536 ntohs(((struct sockaddr_in*)&peer->dstadr->sin)->sin_port) : 0));
1540 ctl_putuint(peer_var[CP_LEAP].text, peer->leap);
1544 ctl_putuint(peer_var[CP_HMODE].text, peer->hmode);
1548 ctl_putuint(peer_var[CP_STRATUM].text, peer->stratum);
1552 ctl_putuint(peer_var[CP_PPOLL].text, peer->ppoll);
1556 ctl_putuint(peer_var[CP_HPOLL].text, peer->hpoll);
1560 ctl_putint(peer_var[CP_PRECISION].text,
1565 ctl_putdbl(peer_var[CP_ROOTDELAY].text,
1566 peer->rootdelay * 1e3);
1569 case CP_ROOTDISPERSION:
1570 ctl_putdbl(peer_var[CP_ROOTDISPERSION].text,
1571 peer->rootdispersion * 1e3);
1575 if (peer->flags & FLAG_REFCLOCK) {
1576 ctl_putid(peer_var[CP_REFID].text,
1577 (char *)&peer->refid);
1579 if (peer->stratum > 1 && peer->stratum <
1581 ctl_putadr(peer_var[CP_REFID].text,
1584 ctl_putid(peer_var[CP_REFID].text,
1585 (char *)&peer->refid);
1590 ctl_putts(peer_var[CP_REFTIME].text, &peer->reftime);
1594 ctl_putts(peer_var[CP_ORG].text, &peer->org);
1598 ctl_putts(peer_var[CP_REC].text, &peer->rec);
1602 ctl_putts(peer_var[CP_XMT].text, &peer->xmt);
1606 ctl_puthex(peer_var[CP_REACH].text, peer->reach);
1611 ctl_puthex(peer_var[CP_FLASH].text, temp);
1615 ctl_putint(peer_var[CP_TTL].text, sys_ttl[peer->ttl]);
1619 ctl_putuint(peer_var[CP_UNREACH].text, peer->unreach);
1623 ctl_putuint(peer_var[CP_TIMER].text,
1624 peer->nextdate - current_time);
1628 ctl_putdbl(peer_var[CP_DELAY].text, peer->delay * 1e3);
1632 ctl_putdbl(peer_var[CP_OFFSET].text, peer->offset *
1637 ctl_putdbl(peer_var[CP_JITTER].text, peer->jitter * 1e3);
1641 ctl_putdbl(peer_var[CP_DISPERSION].text, peer->disp *
1646 ctl_putuint(peer_var[CP_KEYID].text, peer->keyid);
1650 ctl_putarray(peer_var[CP_FILTDELAY].text,
1651 peer->filter_delay, (int)peer->filter_nextpt);
1655 ctl_putarray(peer_var[CP_FILTOFFSET].text,
1656 peer->filter_offset, (int)peer->filter_nextpt);
1660 ctl_putarray(peer_var[CP_FILTERROR].text,
1661 peer->filter_disp, (int)peer->filter_nextpt);
1665 ctl_putuint(peer_var[CP_PMODE].text, peer->pmode);
1669 ctl_putuint(peer_var[CP_RECEIVED].text, peer->received);
1673 ctl_putuint(peer_var[CP_SENT].text, peer->sent);
1678 char buf[CTL_MAX_DATA_LEN];
1679 register char *s, *t, *be;
1681 register struct ctl_var *k;
1684 be = buf + sizeof(buf) -
1685 strlen(peer_var[CP_VARLIST].text) - 4;
1687 break; /* really long var name */
1689 strcpy(s, peer_var[CP_VARLIST].text);
1693 for (k = peer_var; !(k->flags &EOV); k++) {
1694 if (k->flags & PADDING)
1697 i = strlen(k->text);
1698 if (s + i + 1 >= be)
1711 ctl_putdata(buf, (unsigned)(s - buf), 0);
1717 ctl_puthex(peer_var[CP_FLAGS].text, peer->crypto);
1724 dp = EVP_get_digestbynid(peer->crypto >> 16);
1725 strcpy(str, OBJ_nid2ln(EVP_MD_pkey_type(dp)));
1726 ctl_putstr(peer_var[CP_DIGEST].text, str,
1732 if (peer->subject != NULL)
1733 ctl_putstr(peer_var[CP_HOST].text,
1734 peer->subject, strlen(peer->subject));
1737 case CP_VALID: /* not used */
1741 if (peer->issuer != NULL)
1742 ctl_putstr(peer_var[CP_IDENT].text,
1743 peer->issuer, strlen(peer->issuer));
1747 if ((ap = (struct autokey *)peer->recval.ptr) == NULL)
1749 ctl_putint(peer_var[CP_INITSEQ].text, ap->seq);
1750 ctl_puthex(peer_var[CP_INITKEY].text, ap->key);
1751 ctl_putfs(peer_var[CP_INITTSP].text,
1752 ntohl(peer->recval.tstamp));
1754 #endif /* OPENSSL */
1761 * ctl_putclock - output clock variables
1766 struct refclockstat *clock_stat,
1773 if (mustput || clock_stat->clockdesc == NULL
1774 || *(clock_stat->clockdesc) == '\0') {
1775 ctl_putuint(clock_var[CC_TYPE].text, clock_stat->type);
1779 ctl_putstr(clock_var[CC_TIMECODE].text,
1780 clock_stat->p_lastcode,
1781 (unsigned)clock_stat->lencode);
1785 ctl_putuint(clock_var[CC_POLL].text, clock_stat->polls);
1789 ctl_putuint(clock_var[CC_NOREPLY].text,
1790 clock_stat->noresponse);
1794 ctl_putuint(clock_var[CC_BADFORMAT].text,
1795 clock_stat->badformat);
1799 ctl_putuint(clock_var[CC_BADDATA].text,
1800 clock_stat->baddata);
1804 if (mustput || (clock_stat->haveflags & CLK_HAVETIME1))
1805 ctl_putdbl(clock_var[CC_FUDGETIME1].text,
1806 clock_stat->fudgetime1 * 1e3);
1810 if (mustput || (clock_stat->haveflags & CLK_HAVETIME2)) ctl_putdbl(clock_var[CC_FUDGETIME2].text,
1811 clock_stat->fudgetime2 * 1e3);
1815 if (mustput || (clock_stat->haveflags & CLK_HAVEVAL1))
1816 ctl_putint(clock_var[CC_FUDGEVAL1].text,
1817 clock_stat->fudgeval1);
1821 if (mustput || (clock_stat->haveflags & CLK_HAVEVAL2)) {
1822 if (clock_stat->fudgeval1 > 1)
1823 ctl_putadr(clock_var[CC_FUDGEVAL2].text,
1824 (u_int32)clock_stat->fudgeval2, NULL);
1826 ctl_putid(clock_var[CC_FUDGEVAL2].text,
1827 (char *)&clock_stat->fudgeval2);
1832 if (mustput || (clock_stat->haveflags & (CLK_HAVEFLAG1 |
1833 CLK_HAVEFLAG2 | CLK_HAVEFLAG3 | CLK_HAVEFLAG4)))
1834 ctl_putuint(clock_var[CC_FLAGS].text,
1839 if (clock_stat->clockdesc == NULL ||
1840 *(clock_stat->clockdesc) == '\0') {
1842 ctl_putstr(clock_var[CC_DEVICE].text,
1845 ctl_putstr(clock_var[CC_DEVICE].text,
1846 clock_stat->clockdesc,
1847 strlen(clock_stat->clockdesc));
1853 char buf[CTL_MAX_DATA_LEN];
1854 register char *s, *t, *be;
1855 register const char *ss;
1857 register struct ctl_var *k;
1860 be = buf + sizeof(buf);
1861 if (s + strlen(clock_var[CC_VARLIST].text) + 4 >
1863 break; /* really long var name */
1865 strcpy(s, clock_var[CC_VARLIST].text);
1870 for (k = clock_var; !(k->flags &EOV); k++) {
1871 if (k->flags & PADDING)
1874 i = strlen(k->text);
1875 if (s + i + 1 >= be)
1884 for (k = clock_stat->kv_list; k && !(k->flags &
1886 if (k->flags & PADDING)
1893 while (*ss && *ss != '=')
1901 strncpy(s, k->text, (unsigned)i);
1910 ctl_putdata(buf, (unsigned)( s - buf ), 0);
1920 * ctl_getitem - get the next data item from the incoming packet
1922 static struct ctl_var *
1924 struct ctl_var *var_list,
1928 register struct ctl_var *v;
1931 static struct ctl_var eol = { 0, EOV, };
1932 static char buf[128];
1935 * Delete leading commas and white space
1937 while (reqpt < reqend && (*reqpt == ',' ||
1938 isspace((unsigned char)*reqpt)))
1940 if (reqpt >= reqend)
1943 if (var_list == (struct ctl_var *)0)
1947 * Look for a first character match on the tag. If we find
1948 * one, see if it is a full match.
1952 while (!(v->flags & EOV)) {
1953 if (!(v->flags & PADDING) && *cp == *(v->text)) {
1955 while (*tp != '\0' && *tp != '=' && cp <
1956 reqend && *cp == *tp) {
1960 if ((*tp == '\0') || (*tp == '=')) {
1961 while (cp < reqend && isspace((unsigned char)*cp))
1963 if (cp == reqend || *cp == ',') {
1974 while (cp < reqend && isspace((unsigned char)*cp))
1976 while (cp < reqend && *cp != ',') {
1978 if (tp >= buf + sizeof(buf)) {
1979 ctl_error(CERR_BADFMT);
1981 #if 0 /* Avoid possible DOS attack */
1982 /* If we get a smarter msyslog we can re-enable this */
1983 msyslog(LOG_WARNING,
1984 "Possible 'ntpdx' exploit from %s:%d (possibly spoofed)\n",
1985 stoa(rmt_addr), SRCPORT(rmt_addr)
1995 if (!isspace((unsigned int)(*tp)))
2013 * control_unspec - response to an unspecified op-code
2018 struct recvbuf *rbufp,
2025 * What is an appropriate response to an unspecified op-code?
2026 * I return no errors and no data, unless a specified assocation
2029 if (res_associd != 0) {
2030 if ((peer = findpeerbyassoc(res_associd)) == 0) {
2031 ctl_error(CERR_BADASSOC);
2034 rpkt.status = htons(ctlpeerstatus(peer));
2036 rpkt.status = htons(ctlsysstatus());
2043 * read_status - return either a list of associd's, or a particular
2049 struct recvbuf *rbufp,
2054 register struct peer *peer;
2055 u_short ass_stat[CTL_MAX_DATA_LEN / sizeof(u_short)];
2059 printf("read_status: ID %d\n", res_associd);
2062 * Two choices here. If the specified association ID is
2063 * zero we return all known assocation ID's. Otherwise
2064 * we return a bunch of stuff about the particular peer.
2066 if (res_associd == 0) {
2070 rpkt.status = htons(ctlsysstatus());
2071 for (i = 0; i < NTP_HASH_SIZE; i++) {
2072 for (peer = assoc_hash[i]; peer != 0;
2073 peer = peer->ass_next) {
2074 ass_stat[n++] = htons(peer->associd);
2076 htons(ctlpeerstatus(peer));
2078 CTL_MAX_DATA_LEN/sizeof(u_short)) {
2079 ctl_putdata((char *)ass_stat,
2080 n * sizeof(u_short), 1);
2087 ctl_putdata((char *)ass_stat, n *
2088 sizeof(u_short), 1);
2091 peer = findpeerbyassoc(res_associd);
2093 ctl_error(CERR_BADASSOC);
2095 register u_char *cp;
2097 rpkt.status = htons(ctlpeerstatus(peer));
2099 peer->num_events = 0;
2101 * For now, output everything we know about the
2102 * peer. May be more selective later.
2104 for (cp = def_peer_var; *cp != 0; cp++)
2105 ctl_putpeer((int)*cp, peer);
2113 * read_variables - return the variables the caller asks for
2118 struct recvbuf *rbufp,
2122 register struct ctl_var *v;
2126 unsigned int gotvar = (CS_MAXCODE > CP_MAXCODE) ? (CS_MAXCODE +
2127 1) : (CP_MAXCODE + 1);
2128 if (res_associd == 0) {
2130 * Wants system variables. Figure out which he wants
2131 * and give them to him.
2133 rpkt.status = htons(ctlsysstatus());
2135 ctl_sys_num_events = 0;
2136 gotvar += count_var(ext_sys_var);
2137 wants = (u_char *)emalloc(gotvar);
2138 memset((char *)wants, 0, gotvar);
2140 while ((v = ctl_getitem(sys_var, &valuep)) != 0) {
2141 if (v->flags & EOV) {
2142 if ((v = ctl_getitem(ext_sys_var,
2144 if (v->flags & EOV) {
2145 ctl_error(CERR_UNKNOWNVAR);
2146 free((char *)wants);
2149 wants[CS_MAXCODE + 1 +
2154 break; /* shouldn't happen ! */
2161 for (i = 1; i <= CS_MAXCODE; i++)
2164 for (i = 0; ext_sys_var &&
2165 !(ext_sys_var[i].flags & EOV); i++)
2166 if (wants[i + CS_MAXCODE + 1])
2167 ctl_putdata(ext_sys_var[i].text,
2168 strlen(ext_sys_var[i].text),
2171 register u_char *cs;
2172 register struct ctl_var *kv;
2174 for (cs = def_sys_var; *cs != 0; cs++)
2175 ctl_putsys((int)*cs);
2176 for (kv = ext_sys_var; kv && !(kv->flags & EOV);
2178 if (kv->flags & DEF)
2179 ctl_putdata(kv->text,
2180 strlen(kv->text), 0);
2182 free((char *)wants);
2184 register struct peer *peer;
2187 * Wants info for a particular peer. See if we know
2190 peer = findpeerbyassoc(res_associd);
2192 ctl_error(CERR_BADASSOC);
2195 rpkt.status = htons(ctlpeerstatus(peer));
2197 peer->num_events = 0;
2198 wants = (u_char *)emalloc(gotvar);
2199 memset((char*)wants, 0, gotvar);
2201 while ((v = ctl_getitem(peer_var, &valuep)) != 0) {
2202 if (v->flags & EOV) {
2203 ctl_error(CERR_UNKNOWNVAR);
2204 free((char *)wants);
2211 for (i = 1; i <= CP_MAXCODE; i++)
2213 ctl_putpeer(i, peer);
2215 register u_char *cp;
2217 for (cp = def_peer_var; *cp != 0; cp++)
2218 ctl_putpeer((int)*cp, peer);
2220 free((char *)wants);
2227 * write_variables - write into variables. We only allow leap bit
2233 struct recvbuf *rbufp,
2237 register struct ctl_var *v;
2238 register int ext_var;
2243 * If he's trying to write into a peer tell him no way
2245 if (res_associd != 0) {
2246 ctl_error(CERR_PERMISSION);
2253 rpkt.status = htons(ctlsysstatus());
2256 * Look through the variables. Dump out at the first sign of
2259 while ((v = ctl_getitem(sys_var, &valuep)) != 0) {
2261 if (v->flags & EOV) {
2262 if ((v = ctl_getitem(ext_sys_var, &valuep)) !=
2264 if (v->flags & EOV) {
2265 ctl_error(CERR_UNKNOWNVAR);
2273 if (!(v->flags & CAN_WRITE)) {
2274 ctl_error(CERR_PERMISSION);
2277 if (!ext_var && (*valuep == '\0' || !atoint(valuep,
2279 ctl_error(CERR_BADFMT);
2282 if (!ext_var && (val & ~LEAP_NOTINSYNC) != 0) {
2283 ctl_error(CERR_BADVALUE);
2288 char *s = (char *)emalloc(strlen(v->text) +
2289 strlen(valuep) + 2);
2294 while (*t && *t != '=')
2299 set_sys_var(s, strlen(s)+1, v->flags);
2303 * This one seems sane. Save it.
2309 ctl_error(CERR_UNSPEC); /* really */
2316 * If we got anything, do it. xxx nothing to do ***
2319 if (leapind != ~0 || leapwarn != ~0) {
2320 if (!leap_setleap((int)leapind, (int)leapwarn)) {
2321 ctl_error(CERR_PERMISSION);
2331 * read_clock_status - return clock radio status
2336 struct recvbuf *rbufp,
2342 * If no refclock support, no data to return
2344 ctl_error(CERR_BADASSOC);
2346 register struct ctl_var *v;
2348 register struct peer *peer;
2351 unsigned int gotvar;
2352 struct refclockstat clock_stat;
2354 if (res_associd == 0) {
2357 * Find a clock for this jerk. If the system peer
2358 * is a clock use it, else search the hash tables
2361 if (sys_peer != 0 && (sys_peer->flags & FLAG_REFCLOCK))
2366 for (i = 0; peer == 0 && i < NTP_HASH_SIZE; i++) {
2367 for (peer = assoc_hash[i]; peer != 0;
2368 peer = peer->ass_next) {
2369 if (peer->flags & FLAG_REFCLOCK)
2374 ctl_error(CERR_BADASSOC);
2379 peer = findpeerbyassoc(res_associd);
2380 if (peer == 0 || !(peer->flags & FLAG_REFCLOCK)) {
2381 ctl_error(CERR_BADASSOC);
2387 * If we got here we have a peer which is a clock. Get his
2390 clock_stat.kv_list = (struct ctl_var *)0;
2391 refclock_control(&peer->srcadr, (struct refclockstat *)0,
2395 * Look for variables in the packet.
2397 rpkt.status = htons(ctlclkstatus(&clock_stat));
2398 gotvar = CC_MAXCODE + 1 + count_var(clock_stat.kv_list);
2399 wants = (u_char *)emalloc(gotvar);
2400 memset((char*)wants, 0, gotvar);
2402 while ((v = ctl_getitem(clock_var, &valuep)) != 0) {
2403 if (v->flags & EOV) {
2404 if ((v = ctl_getitem(clock_stat.kv_list,
2406 if (v->flags & EOV) {
2407 ctl_error(CERR_UNKNOWNVAR);
2409 free_varlist(clock_stat.kv_list);
2412 wants[CC_MAXCODE + 1 + v->code] = 1;
2416 break; /* shouldn't happen ! */
2424 for (i = 1; i <= CC_MAXCODE; i++)
2426 ctl_putclock(i, &clock_stat, 1);
2427 for (i = 0; clock_stat.kv_list &&
2428 !(clock_stat.kv_list[i].flags & EOV); i++)
2429 if (wants[i + CC_MAXCODE + 1])
2430 ctl_putdata(clock_stat.kv_list[i].text,
2431 strlen(clock_stat.kv_list[i].text),
2434 register u_char *cc;
2435 register struct ctl_var *kv;
2437 for (cc = def_clock_var; *cc != 0; cc++)
2438 ctl_putclock((int)*cc, &clock_stat, 0);
2439 for (kv = clock_stat.kv_list; kv && !(kv->flags & EOV);
2441 if (kv->flags & DEF)
2442 ctl_putdata(kv->text, strlen(kv->text),
2447 free_varlist(clock_stat.kv_list);
2455 * write_clock_status - we don't do this
2460 struct recvbuf *rbufp,
2464 ctl_error(CERR_PERMISSION);
2468 * Trap support from here on down. We send async trap messages when the
2469 * upper levels report trouble. Traps can by set either by control
2470 * messages or by configuration.
2473 * set_trap - set a trap in response to a control message
2477 struct recvbuf *rbufp,
2484 * See if this guy is allowed
2486 if (restrict_mask & RES_NOTRAP) {
2487 ctl_error(CERR_PERMISSION);
2492 * Determine his allowed trap type.
2494 traptype = TRAP_TYPE_PRIO;
2495 if (restrict_mask & RES_LPTRAP)
2496 traptype = TRAP_TYPE_NONPRIO;
2499 * Call ctlsettrap() to do the work. Return
2500 * an error if it can't assign the trap.
2502 if (!ctlsettrap(&rbufp->recv_srcadr, rbufp->dstadr, traptype,
2504 ctl_error(CERR_NORESOURCE);
2510 * unset_trap - unset a trap in response to a control message
2514 struct recvbuf *rbufp,
2521 * We don't prevent anyone from removing his own trap unless the
2522 * trap is configured. Note we also must be aware of the
2523 * possibility that restriction flags were changed since this
2524 * guy last set his trap. Set the trap type based on this.
2526 traptype = TRAP_TYPE_PRIO;
2527 if (restrict_mask & RES_LPTRAP)
2528 traptype = TRAP_TYPE_NONPRIO;
2531 * Call ctlclrtrap() to clear this out.
2533 if (!ctlclrtrap(&rbufp->recv_srcadr, rbufp->dstadr, traptype))
2534 ctl_error(CERR_BADASSOC);
2540 * ctlsettrap - called to set a trap
2544 struct sockaddr_storage *raddr,
2545 struct interface *linter,
2550 register struct ctl_trap *tp;
2551 register struct ctl_trap *tptouse;
2554 * See if we can find this trap. If so, we only need update
2555 * the flags and the time.
2557 if ((tp = ctlfindtrap(raddr, linter)) != NULL) {
2560 case TRAP_TYPE_CONFIG:
2561 tp->tr_flags = TRAP_INUSE|TRAP_CONFIGURED;
2564 case TRAP_TYPE_PRIO:
2565 if (tp->tr_flags & TRAP_CONFIGURED)
2566 return (1); /* don't change anything */
2567 tp->tr_flags = TRAP_INUSE;
2570 case TRAP_TYPE_NONPRIO:
2571 if (tp->tr_flags & TRAP_CONFIGURED)
2572 return (1); /* don't change anything */
2573 tp->tr_flags = TRAP_INUSE|TRAP_NONPRIO;
2576 tp->tr_settime = current_time;
2582 * First we heard of this guy. Try to find a trap structure
2583 * for him to use, clearing out lesser priority guys if we
2584 * have to. Clear out anyone who's expired while we're at it.
2587 for (tp = ctl_trap; tp < &ctl_trap[CTL_MAXTRAPS]; tp++) {
2588 if ((tp->tr_flags & TRAP_INUSE) &&
2589 !(tp->tr_flags & TRAP_CONFIGURED) &&
2590 ((tp->tr_settime + CTL_TRAPTIME) > current_time)) {
2594 if (!(tp->tr_flags & TRAP_INUSE)) {
2596 } else if (!(tp->tr_flags & TRAP_CONFIGURED)) {
2599 case TRAP_TYPE_CONFIG:
2600 if (tptouse == NULL) {
2604 if (tptouse->tr_flags & TRAP_NONPRIO &&
2605 !(tp->tr_flags & TRAP_NONPRIO))
2608 if (!(tptouse->tr_flags & TRAP_NONPRIO)
2609 && tp->tr_flags & TRAP_NONPRIO) {
2613 if (tptouse->tr_origtime <
2618 case TRAP_TYPE_PRIO:
2619 if (tp->tr_flags & TRAP_NONPRIO) {
2620 if (tptouse == NULL ||
2621 (tptouse->tr_flags &
2623 tptouse->tr_origtime <
2629 case TRAP_TYPE_NONPRIO:
2636 * If we don't have room for him return an error.
2638 if (tptouse == NULL)
2642 * Set up this structure for him.
2644 tptouse->tr_settime = tptouse->tr_origtime = current_time;
2645 tptouse->tr_count = tptouse->tr_resets = 0;
2646 tptouse->tr_sequence = 1;
2647 tptouse->tr_addr = *raddr;
2648 tptouse->tr_localaddr = linter;
2649 tptouse->tr_version = (u_char) version;
2650 tptouse->tr_flags = TRAP_INUSE;
2651 if (traptype == TRAP_TYPE_CONFIG)
2652 tptouse->tr_flags |= TRAP_CONFIGURED;
2653 else if (traptype == TRAP_TYPE_NONPRIO)
2654 tptouse->tr_flags |= TRAP_NONPRIO;
2661 * ctlclrtrap - called to clear a trap
2665 struct sockaddr_storage *raddr,
2666 struct interface *linter,
2670 register struct ctl_trap *tp;
2672 if ((tp = ctlfindtrap(raddr, linter)) == NULL)
2675 if (tp->tr_flags & TRAP_CONFIGURED
2676 && traptype != TRAP_TYPE_CONFIG)
2686 * ctlfindtrap - find a trap given the remote and local addresses
2688 static struct ctl_trap *
2690 struct sockaddr_storage *raddr,
2691 struct interface *linter
2694 register struct ctl_trap *tp;
2696 for (tp = ctl_trap; tp < &ctl_trap[CTL_MAXTRAPS]; tp++) {
2697 if ((tp->tr_flags & TRAP_INUSE)
2698 && (NSRCPORT(raddr) == NSRCPORT(&tp->tr_addr))
2699 && SOCKCMP(raddr, &tp->tr_addr)
2700 && (linter == tp->tr_localaddr) )
2703 return (struct ctl_trap *)NULL;
2708 * report_event - report an event to the trappers
2719 * Record error code in proper spots, but have mercy on the
2722 if (!(err & (PEER_EVENT | CRPT_EVENT))) {
2723 if (ctl_sys_num_events < CTL_SYS_MAXEVENTS)
2724 ctl_sys_num_events++;
2725 if (ctl_sys_last_event != (u_char)err) {
2727 msyslog(LOG_INFO, "system event '%s' (0x%02x) status '%s' (0x%02x)",
2729 sysstatstr(ctlsysstatus()), ctlsysstatus());
2732 printf("report_event: system event '%s' (0x%02x) status '%s' (0x%02x)\n",
2734 sysstatstr(ctlsysstatus()),
2737 ctl_sys_last_event = (u_char)err;
2739 } else if (peer != 0) {
2743 if (ISREFCLOCKADR(&peer->srcadr))
2744 src = refnumtoa(&peer->srcadr);
2747 src = stoa(&peer->srcadr);
2749 peer->last_event = (u_char)(err & ~PEER_EVENT);
2750 if (peer->num_events < CTL_PEER_MAXEVENTS)
2752 NLOG(NLOG_PEEREVENT)
2753 msyslog(LOG_INFO, "peer %s event '%s' (0x%02x) status '%s' (0x%02x)",
2754 src, eventstr(err), err,
2755 peerstatstr(ctlpeerstatus(peer)),
2756 ctlpeerstatus(peer));
2759 printf( "peer %s event '%s' (0x%02x) status '%s' (0x%02x)\n",
2760 src, eventstr(err), err,
2761 peerstatstr(ctlpeerstatus(peer)),
2762 ctlpeerstatus(peer));
2766 "report_event: err '%s' (0x%02x), no peer",
2767 eventstr(err), err);
2770 "report_event: peer event '%s' (0x%02x), no peer\n",
2771 eventstr(err), err);
2777 * If no trappers, return.
2779 if (num_ctl_traps <= 0)
2783 * Set up the outgoing packet variables
2785 res_opcode = CTL_OP_ASYNCMSG;
2788 res_authenticate = 0;
2790 dataend = &(rpkt.data[CTL_MAX_DATA_LEN]);
2791 if (!(err & PEER_EVENT)) {
2793 rpkt.status = htons(ctlsysstatus());
2796 * For now, put everything we know about system
2797 * variables. Don't send crypto strings.
2799 for (i = 1; i <= CS_MAXCODE; i++) {
2803 #endif /* OPENSSL */
2808 * for clock exception events: add clock variables to
2809 * reflect info on exception
2811 if (err == EVNT_CLOCKEXCPT) {
2812 struct refclockstat clock_stat;
2815 clock_stat.kv_list = (struct ctl_var *)0;
2816 refclock_control(&peer->srcadr,
2817 (struct refclockstat *)0, &clock_stat);
2818 ctl_puthex("refclockstatus",
2819 ctlclkstatus(&clock_stat));
2820 for (i = 1; i <= CC_MAXCODE; i++)
2821 ctl_putclock(i, &clock_stat, 0);
2822 for (kv = clock_stat.kv_list; kv &&
2823 !(kv->flags & EOV); kv++)
2824 if (kv->flags & DEF)
2825 ctl_putdata(kv->text,
2826 strlen(kv->text), 0);
2827 free_varlist(clock_stat.kv_list);
2829 #endif /* REFCLOCK */
2831 rpkt.associd = htons(peer->associd);
2832 rpkt.status = htons(ctlpeerstatus(peer));
2835 * Dump it all. Later, maybe less.
2837 for (i = 1; i <= CP_MAXCODE; i++) {
2841 #endif /* OPENSSL */
2842 ctl_putpeer(i, peer);
2846 * for clock exception events: add clock variables to
2847 * reflect info on exception
2849 if (err == EVNT_PEERCLOCK) {
2850 struct refclockstat clock_stat;
2853 clock_stat.kv_list = (struct ctl_var *)0;
2854 refclock_control(&peer->srcadr,
2855 (struct refclockstat *)0, &clock_stat);
2857 ctl_puthex("refclockstatus",
2858 ctlclkstatus(&clock_stat));
2860 for (i = 1; i <= CC_MAXCODE; i++)
2861 ctl_putclock(i, &clock_stat, 0);
2862 for (kv = clock_stat.kv_list; kv &&
2863 !(kv->flags & EOV); kv++)
2864 if (kv->flags & DEF)
2865 ctl_putdata(kv->text,
2866 strlen(kv->text), 0);
2867 free_varlist(clock_stat.kv_list);
2869 #endif /* REFCLOCK */
2873 * We're done, return.
2880 * ctl_clr_stats - clear stat counters
2885 ctltimereset = current_time;
2888 numctlresponses = 0;
2893 numctlinputresp = 0;
2894 numctlinputfrag = 0;
2896 numctlbadoffset = 0;
2897 numctlbadversion = 0;
2898 numctldatatooshort = 0;
2914 while (!(k++->flags & EOV))
2921 struct ctl_var **kv,
2927 register struct ctl_var *k;
2932 *kv = (struct ctl_var *)emalloc((c+2)*sizeof(struct ctl_var));
2934 memmove((char *)*kv, (char *)k,
2935 sizeof(struct ctl_var)*c);
2938 (*kv)[c].code = (u_short) c;
2939 (*kv)[c].text = (char *)emalloc(size);
2940 (*kv)[c].flags = def;
2941 (*kv)[c+1].code = 0;
2942 (*kv)[c+1].text = (char *)0;
2943 (*kv)[c+1].flags = EOV;
2944 return (char *)(*kv)[c].text;
2949 struct ctl_var **kv,
2955 register struct ctl_var *k;
2956 register const char *s;
2957 register const char *t;
2965 while (!(k->flags & EOV)) {
2969 while (*t != '=' && *s - *t == 0) {
2973 if (*s == *t && ((*t == '=') || !*t)) {
2974 free((void *)k->text);
2975 td = (char *)emalloc(size);
2976 memmove(td, data, size);
2982 td = (char *)emalloc(size);
2983 memmove(td, data, size);
2991 td = add_var(kv, size, def);
2992 memmove(td, data, size);
3002 set_var(&ext_sys_var, data, size, def);
3012 for (k = kv; !(k->flags & EOV); k++)
3013 free((void *)k->text);