Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / ntp / ntpd / ntp_control.c
blob3a1685e5b0e8998c88e0aa406e7286524f91dd32
1 /* $NetBSD: ntp_control.c,v 1.8 2006/06/25 03:02:19 mrg Exp $ */
3 /*
4 * ntp_control.c - respond to control messages and send async traps
5 */
6 #ifdef HAVE_CONFIG_H
7 #include <config.h>
8 #endif
10 #include "ntpd.h"
11 #include "ntp_io.h"
12 #include "ntp_refclock.h"
13 #include "ntp_control.h"
14 #include "ntp_unixtime.h"
15 #include "ntp_stdlib.h"
17 #include <stdio.h>
18 #include <ctype.h>
19 #include <signal.h>
21 #include <netinet/in.h>
22 #include <arpa/inet.h>
25 * Structure to hold request procedure information
27 #define NOAUTH 0
28 #define AUTH 1
30 #define NO_REQUEST (-1)
32 struct ctl_proc {
33 short control_code; /* defined request code */
34 u_short flags; /* flags word */
35 void (*handler) P((struct recvbuf *, int)); /* handle request */
39 * Only one flag. Authentication required or not.
41 #define NOAUTH 0
42 #define AUTH 1
45 * Request processing routines
47 static void ctl_error P((int));
48 #ifdef REFCLOCK
49 static u_short ctlclkstatus P((struct refclockstat *));
50 #endif
51 static void ctl_flushpkt P((int));
52 static void ctl_putdata P((const char *, unsigned int, int));
53 static void ctl_putstr P((const char *, const char *,
54 unsigned int));
55 static void ctl_putdbl P((const char *, double));
56 static void ctl_putuint P((const char *, u_long));
57 static void ctl_puthex P((const char *, u_long));
58 static void ctl_putint P((const char *, long));
59 static void ctl_putts P((const char *, l_fp *));
60 static void ctl_putadr P((const char *, u_int32, struct sockaddr_storage*));
61 static void ctl_putid P((const char *, char *));
62 static void ctl_putarray P((const char *, double *, int));
63 static void ctl_putsys P((int));
64 static void ctl_putpeer P((int, struct peer *));
65 #ifdef OPENSSL
66 static void ctl_putfs P((const char *, tstamp_t));
67 #endif /* OPENSSL */
68 #ifdef REFCLOCK
69 static void ctl_putclock P((int, struct refclockstat *, int));
70 #endif /* REFCLOCK */
71 static struct ctl_var *ctl_getitem P((struct ctl_var *, char **));
72 static u_long count_var P((struct ctl_var *));
73 static void control_unspec P((struct recvbuf *, int));
74 static void read_status P((struct recvbuf *, int));
75 static void read_variables P((struct recvbuf *, int));
76 static void write_variables P((struct recvbuf *, int));
77 static void read_clock_status P((struct recvbuf *, int));
78 static void write_clock_status P((struct recvbuf *, int));
79 static void set_trap P((struct recvbuf *, int));
80 static void unset_trap P((struct recvbuf *, int));
81 static struct ctl_trap *ctlfindtrap P((struct sockaddr_storage *,
82 struct interface *));
84 static struct ctl_proc control_codes[] = {
85 { CTL_OP_UNSPEC, NOAUTH, control_unspec },
86 { CTL_OP_READSTAT, NOAUTH, read_status },
87 { CTL_OP_READVAR, NOAUTH, read_variables },
88 { CTL_OP_WRITEVAR, AUTH, write_variables },
89 { CTL_OP_READCLOCK, NOAUTH, read_clock_status },
90 { CTL_OP_WRITECLOCK, NOAUTH, write_clock_status },
91 { CTL_OP_SETTRAP, NOAUTH, set_trap },
92 { CTL_OP_UNSETTRAP, NOAUTH, unset_trap },
93 { NO_REQUEST, 0 }
97 * System variable values. The array can be indexed by the variable
98 * index to find the textual name.
100 static struct ctl_var sys_var[] = {
101 { 0, PADDING, "" }, /* 0 */
102 { CS_LEAP, RW, "leap" }, /* 1 */
103 { CS_STRATUM, RO, "stratum" }, /* 2 */
104 { CS_PRECISION, RO, "precision" }, /* 3 */
105 { CS_ROOTDELAY, RO, "rootdelay" }, /* 4 */
106 { CS_ROOTDISPERSION, RO, "rootdispersion" }, /* 5 */
107 { CS_REFID, RO, "refid" }, /* 6 */
108 { CS_REFTIME, RO, "reftime" }, /* 7 */
109 { CS_POLL, RO, "poll" }, /* 8 */
110 { CS_PEERID, RO, "peer" }, /* 9 */
111 { CS_STATE, RO, "state" }, /* 10 */
112 { CS_OFFSET, RO, "offset" }, /* 11 */
113 { CS_DRIFT, RO, "frequency" }, /* 12 */
114 { CS_JITTER, RO, "jitter" }, /* 13 */
115 { CS_ERROR, RO, "noise" }, /* 14 */
116 { CS_CLOCK, RO, "clock" }, /* 15 */
117 { CS_PROCESSOR, RO, "processor" }, /* 16 */
118 { CS_SYSTEM, RO, "system" }, /* 17 */
119 { CS_VERSION, RO, "version" }, /* 18 */
120 { CS_STABIL, RO, "stability" }, /* 19 */
121 { CS_VARLIST, RO, "sys_var_list" }, /* 20 */
122 #ifdef OPENSSL
123 { CS_FLAGS, RO, "flags" }, /* 21 */
124 { CS_HOST, RO, "hostname" }, /* 22 */
125 { CS_PUBLIC, RO, "update" }, /* 23 */
126 { CS_CERTIF, RO, "cert" }, /* 24 */
127 { CS_REVTIME, RO, "expire" }, /* 25 */
128 { CS_LEAPTAB, RO, "leapsec" }, /* 26 */
129 { CS_TAI, RO, "tai" }, /* 27 */
130 { CS_DIGEST, RO, "signature" }, /* 28 */
131 { CS_IDENT, RO, "ident" }, /* 29 */
132 { CS_REVOKE, RO, "expire" }, /* 30 */
133 #endif /* OPENSSL */
134 { 0, EOV, "" } /* 21/31 */
137 static struct ctl_var *ext_sys_var = (struct ctl_var *)0;
140 * System variables we print by default (in fuzzball order,
141 * more-or-less)
143 static u_char def_sys_var[] = {
144 CS_VERSION,
145 CS_PROCESSOR,
146 CS_SYSTEM,
147 CS_LEAP,
148 CS_STRATUM,
149 CS_PRECISION,
150 CS_ROOTDELAY,
151 CS_ROOTDISPERSION,
152 CS_PEERID,
153 CS_REFID,
154 CS_REFTIME,
155 CS_POLL,
156 CS_CLOCK,
157 CS_STATE,
158 CS_OFFSET,
159 CS_DRIFT,
160 CS_JITTER,
161 CS_ERROR,
162 CS_STABIL,
163 #ifdef OPENSSL
164 CS_HOST,
165 CS_DIGEST,
166 CS_FLAGS,
167 CS_PUBLIC,
168 CS_IDENT,
169 CS_LEAPTAB,
170 CS_TAI,
171 CS_CERTIF,
172 #endif /* OPENSSL */
178 * Peer variable list
180 static struct ctl_var peer_var[] = {
181 { 0, PADDING, "" }, /* 0 */
182 { CP_CONFIG, RO, "config" }, /* 1 */
183 { CP_AUTHENABLE, RO, "authenable" }, /* 2 */
184 { CP_AUTHENTIC, RO, "authentic" }, /* 3 */
185 { CP_SRCADR, RO, "srcadr" }, /* 4 */
186 { CP_SRCPORT, RO, "srcport" }, /* 5 */
187 { CP_DSTADR, RO, "dstadr" }, /* 6 */
188 { CP_DSTPORT, RO, "dstport" }, /* 7 */
189 { CP_LEAP, RO, "leap" }, /* 8 */
190 { CP_HMODE, RO, "hmode" }, /* 9 */
191 { CP_STRATUM, RO, "stratum" }, /* 10 */
192 { CP_PPOLL, RO, "ppoll" }, /* 11 */
193 { CP_HPOLL, RO, "hpoll" }, /* 12 */
194 { CP_PRECISION, RO, "precision" }, /* 13 */
195 { CP_ROOTDELAY, RO, "rootdelay" }, /* 14 */
196 { CP_ROOTDISPERSION, RO, "rootdispersion" }, /* 15 */
197 { CP_REFID, RO, "refid" }, /* 16 */
198 { CP_REFTIME, RO, "reftime" }, /* 17 */
199 { CP_ORG, RO, "org" }, /* 18 */
200 { CP_REC, RO, "rec" }, /* 19 */
201 { CP_XMT, RO, "xmt" }, /* 20 */
202 { CP_REACH, RO, "reach" }, /* 21 */
203 { CP_UNREACH, RO, "unreach" }, /* 22 */
204 { CP_TIMER, RO, "timer" }, /* 23 */
205 { CP_DELAY, RO, "delay" }, /* 24 */
206 { CP_OFFSET, RO, "offset" }, /* 25 */
207 { CP_JITTER, RO, "jitter" }, /* 26 */
208 { CP_DISPERSION, RO, "dispersion" }, /* 27 */
209 { CP_KEYID, RO, "keyid" }, /* 28 */
210 { CP_FILTDELAY, RO, "filtdelay=" }, /* 29 */
211 { CP_FILTOFFSET, RO, "filtoffset=" }, /* 30 */
212 { CP_PMODE, RO, "pmode" }, /* 31 */
213 { CP_RECEIVED, RO, "received"}, /* 32 */
214 { CP_SENT, RO, "sent" }, /* 33 */
215 { CP_FILTERROR, RO, "filtdisp=" }, /* 34 */
216 { CP_FLASH, RO, "flash" }, /* 35 */
217 { CP_TTL, RO, "ttl" }, /* 36 */
218 { CP_VARLIST, RO, "peer_var_list" }, /* 37 */
219 #ifdef OPENSSL
220 { CP_FLAGS, RO, "flags" }, /* 38 */
221 { CP_HOST, RO, "hostname" }, /* 39 */
222 { CP_VALID, RO, "valid" }, /* 40 */
223 { CP_INITSEQ, RO, "initsequence" }, /* 41 */
224 { CP_INITKEY, RO, "initkey" }, /* 42 */
225 { CP_INITTSP, RO, "timestamp" }, /* 43 */
226 { CP_DIGEST, RO, "signature" }, /* 44 */
227 { CP_IDENT, RO, "trust" }, /* 45 */
228 #endif /* OPENSSL */
229 { 0, EOV, "" } /* 38/46 */
234 * Peer variables we print by default
236 static u_char def_peer_var[] = {
237 CP_SRCADR,
238 CP_SRCPORT,
239 CP_DSTADR,
240 CP_DSTPORT,
241 CP_LEAP,
242 CP_STRATUM,
243 CP_PRECISION,
244 CP_ROOTDELAY,
245 CP_ROOTDISPERSION,
246 CP_REFID,
247 CP_REACH,
248 CP_UNREACH,
249 CP_HMODE,
250 CP_PMODE,
251 CP_HPOLL,
252 CP_PPOLL,
253 CP_FLASH,
254 CP_KEYID,
255 CP_TTL,
256 CP_OFFSET,
257 CP_DELAY,
258 CP_DISPERSION,
259 CP_JITTER,
260 CP_REFTIME,
261 CP_ORG,
262 CP_REC,
263 CP_XMT,
264 CP_FILTDELAY,
265 CP_FILTOFFSET,
266 CP_FILTERROR,
267 #ifdef OPENSSL
268 CP_HOST,
269 CP_DIGEST,
270 CP_VALID,
271 CP_FLAGS,
272 CP_IDENT,
273 CP_INITSEQ,
274 #endif /* OPENSSL */
279 #ifdef REFCLOCK
281 * Clock variable list
283 static struct ctl_var clock_var[] = {
284 { 0, PADDING, "" }, /* 0 */
285 { CC_TYPE, RO, "type" }, /* 1 */
286 { CC_TIMECODE, RO, "timecode" }, /* 2 */
287 { CC_POLL, RO, "poll" }, /* 3 */
288 { CC_NOREPLY, RO, "noreply" }, /* 4 */
289 { CC_BADFORMAT, RO, "badformat" }, /* 5 */
290 { CC_BADDATA, RO, "baddata" }, /* 6 */
291 { CC_FUDGETIME1, RO, "fudgetime1" }, /* 7 */
292 { CC_FUDGETIME2, RO, "fudgetime2" }, /* 8 */
293 { CC_FUDGEVAL1, RO, "stratum" }, /* 9 */
294 { CC_FUDGEVAL2, RO, "refid" }, /* 10 */
295 { CC_FLAGS, RO, "flags" }, /* 11 */
296 { CC_DEVICE, RO, "device" }, /* 12 */
297 { CC_VARLIST, RO, "clock_var_list" }, /* 13 */
298 { 0, EOV, "" } /* 14 */
303 * Clock variables printed by default
305 static u_char def_clock_var[] = {
306 CC_DEVICE,
307 CC_TYPE, /* won't be output if device = known */
308 CC_TIMECODE,
309 CC_POLL,
310 CC_NOREPLY,
311 CC_BADFORMAT,
312 CC_BADDATA,
313 CC_FUDGETIME1,
314 CC_FUDGETIME2,
315 CC_FUDGEVAL1,
316 CC_FUDGEVAL2,
317 CC_FLAGS,
320 #endif
324 * System and processor definitions.
326 #ifndef HAVE_UNAME
327 # ifndef STR_SYSTEM
328 # define STR_SYSTEM "UNIX"
329 # endif
330 # ifndef STR_PROCESSOR
331 # define STR_PROCESSOR "unknown"
332 # endif
334 static char str_system[] = STR_SYSTEM;
335 static char str_processor[] = STR_PROCESSOR;
336 #else
337 # include <sys/utsname.h>
338 static struct utsname utsnamebuf;
339 #endif /* HAVE_UNAME */
342 * Trap structures. We only allow a few of these, and send a copy of
343 * each async message to each live one. Traps time out after an hour, it
344 * is up to the trap receipient to keep resetting it to avoid being
345 * timed out.
347 /* ntp_request.c */
348 struct ctl_trap ctl_trap[CTL_MAXTRAPS];
349 int num_ctl_traps;
352 * Type bits, for ctlsettrap() call.
354 #define TRAP_TYPE_CONFIG 0 /* used by configuration code */
355 #define TRAP_TYPE_PRIO 1 /* priority trap */
356 #define TRAP_TYPE_NONPRIO 2 /* nonpriority trap */
360 * List relating reference clock types to control message time sources.
361 * Index by the reference clock type. This list will only be used iff
362 * the reference clock driver doesn't set peer->sstclktype to something
363 * different than CTL_SST_TS_UNSPEC.
365 static u_char clocktypes[] = {
366 CTL_SST_TS_NTP, /* REFCLK_NONE (0) */
367 CTL_SST_TS_LOCAL, /* REFCLK_LOCALCLOCK (1) */
368 CTL_SST_TS_UHF, /* deprecated REFCLK_GPS_TRAK (2) */
369 CTL_SST_TS_HF, /* REFCLK_WWV_PST (3) */
370 CTL_SST_TS_LF, /* REFCLK_WWVB_SPECTRACOM (4) */
371 CTL_SST_TS_UHF, /* REFCLK_TRUETIME (5) */
372 CTL_SST_TS_UHF, /* REFCLK_GOES_TRAK (6) IRIG_AUDIO? */
373 CTL_SST_TS_HF, /* REFCLK_CHU (7) */
374 CTL_SST_TS_LF, /* REFCLOCK_PARSE (default) (8) */
375 CTL_SST_TS_LF, /* REFCLK_GPS_MX4200 (9) */
376 CTL_SST_TS_UHF, /* REFCLK_GPS_AS2201 (10) */
377 CTL_SST_TS_UHF, /* REFCLK_GPS_ARBITER (11) */
378 CTL_SST_TS_UHF, /* REFCLK_IRIG_TPRO (12) */
379 CTL_SST_TS_ATOM, /* REFCLK_ATOM_LEITCH (13) */
380 CTL_SST_TS_LF, /* deprecated REFCLK_MSF_EES (14) */
381 CTL_SST_TS_NTP, /* not used (15) */
382 CTL_SST_TS_UHF, /* REFCLK_IRIG_BANCOMM (16) */
383 CTL_SST_TS_UHF, /* REFCLK_GPS_DATU (17) */
384 CTL_SST_TS_TELEPHONE, /* REFCLK_NIST_ACTS (18) */
385 CTL_SST_TS_HF, /* REFCLK_WWV_HEATH (19) */
386 CTL_SST_TS_UHF, /* REFCLK_GPS_NMEA (20) */
387 CTL_SST_TS_UHF, /* REFCLK_GPS_VME (21) */
388 CTL_SST_TS_ATOM, /* REFCLK_ATOM_PPS (22) */
389 CTL_SST_TS_NTP, /* not used (23) */
390 CTL_SST_TS_NTP, /* not used (24) */
391 CTL_SST_TS_NTP, /* not used (25) */
392 CTL_SST_TS_UHF, /* REFCLK_GPS_HP (26) */
393 CTL_SST_TS_TELEPHONE, /* REFCLK_ARCRON_MSF (27) */
394 CTL_SST_TS_TELEPHONE, /* REFCLK_SHM (28) */
395 CTL_SST_TS_UHF, /* REFCLK_PALISADE (29) */
396 CTL_SST_TS_UHF, /* REFCLK_ONCORE (30) */
397 CTL_SST_TS_UHF, /* REFCLK_JUPITER (31) */
398 CTL_SST_TS_LF, /* REFCLK_CHRONOLOG (32) */
399 CTL_SST_TS_LF, /* REFCLK_DUMBCLOCK (33) */
400 CTL_SST_TS_LF, /* REFCLK_ULINK (34) */
401 CTL_SST_TS_LF, /* REFCLK_PCF (35) */
402 CTL_SST_TS_LF, /* REFCLK_WWV (36) */
403 CTL_SST_TS_LF, /* REFCLK_FG (37) */
404 CTL_SST_TS_UHF, /* REFCLK_HOPF_SERIAL (38) */
405 CTL_SST_TS_UHF, /* REFCLK_HOPF_PCI (39) */
406 CTL_SST_TS_LF, /* REFCLK_JJY (40) */
407 CTL_SST_TS_UHF, /* REFCLK_TT560 (41) */
408 CTL_SST_TS_UHF, /* REFCLK_ZYFER (42) */
409 CTL_SST_TS_UHF, /* REFCLK_RIPENCC (43) */
410 CTL_SST_TS_UHF, /* REFCLK_NEOCLOCK4X (44) */
415 * Keyid used for authenticating write requests.
417 keyid_t ctl_auth_keyid;
420 * We keep track of the last error reported by the system internally
422 static u_char ctl_sys_last_event;
423 static u_char ctl_sys_num_events;
427 * Statistic counters to keep track of requests and responses.
429 u_long ctltimereset; /* time stats reset */
430 u_long numctlreq; /* number of requests we've received */
431 u_long numctlbadpkts; /* number of bad control packets */
432 u_long numctlresponses; /* number of resp packets sent with data */
433 u_long numctlfrags; /* number of fragments sent */
434 u_long numctlerrors; /* number of error responses sent */
435 u_long numctltooshort; /* number of too short input packets */
436 u_long numctlinputresp; /* number of responses on input */
437 u_long numctlinputfrag; /* number of fragments on input */
438 u_long numctlinputerr; /* number of input pkts with err bit set */
439 u_long numctlbadoffset; /* number of input pkts with nonzero offset */
440 u_long numctlbadversion; /* number of input pkts with unknown version */
441 u_long numctldatatooshort; /* data too short for count */
442 u_long numctlbadop; /* bad op code found in packet */
443 u_long numasyncmsgs; /* number of async messages we've sent */
446 * Response packet used by these routines. Also some state information
447 * so that we can handle packet formatting within a common set of
448 * subroutines. Note we try to enter data in place whenever possible,
449 * but the need to set the more bit correctly means we occasionally
450 * use the extra buffer and copy.
452 static struct ntp_control rpkt;
453 static u_char res_version;
454 static u_char res_opcode;
455 static associd_t res_associd;
456 static int res_offset;
457 static u_char * datapt;
458 static u_char * dataend;
459 static int datalinelen;
460 static int datanotbinflag;
461 static struct sockaddr_storage *rmt_addr;
462 static struct interface *lcl_inter;
464 static u_char res_authenticate;
465 static u_char res_authokay;
466 static keyid_t res_keyid;
468 #define MAXDATALINELEN (72)
470 static u_char res_async; /* set to 1 if this is async trap response */
473 * Pointers for saving state when decoding request packets
475 static char *reqpt;
476 static char *reqend;
479 * init_control - initialize request data
481 void
482 init_control(void)
484 int i;
486 #ifdef HAVE_UNAME
487 uname(&utsnamebuf);
488 #endif /* HAVE_UNAME */
490 ctl_clr_stats();
492 ctl_auth_keyid = 0;
493 ctl_sys_last_event = EVNT_UNSPEC;
494 ctl_sys_num_events = 0;
496 num_ctl_traps = 0;
497 for (i = 0; i < CTL_MAXTRAPS; i++)
498 ctl_trap[i].tr_flags = 0;
503 * ctl_error - send an error response for the current request
505 static void
506 ctl_error(
507 int errcode
510 #ifdef DEBUG
511 if (debug >= 4)
512 printf("sending control error %d\n", errcode);
513 #endif
515 * Fill in the fields. We assume rpkt.sequence and rpkt.associd
516 * have already been filled in.
518 rpkt.r_m_e_op = (u_char) (CTL_RESPONSE|CTL_ERROR|(res_opcode &
519 CTL_OP_MASK));
520 rpkt.status = htons((u_short) ((errcode<<8) & 0xff00));
521 rpkt.count = 0;
524 * send packet and bump counters
526 if (res_authenticate && sys_authenticate) {
527 int maclen;
529 *(u_int32 *)((u_char *)&rpkt + CTL_HEADER_LEN) =
530 htonl(res_keyid);
531 maclen = authencrypt(res_keyid, (u_int32 *)&rpkt,
532 CTL_HEADER_LEN);
533 sendpkt(rmt_addr, lcl_inter, -2, (struct pkt *)&rpkt,
534 CTL_HEADER_LEN + maclen);
535 } else {
536 sendpkt(rmt_addr, lcl_inter, -3, (struct pkt *)&rpkt,
537 CTL_HEADER_LEN);
539 numctlerrors++;
544 * process_control - process an incoming control message
546 void
547 process_control(
548 struct recvbuf *rbufp,
549 int restrict_mask
552 register struct ntp_control *pkt;
553 register int req_count;
554 register int req_data;
555 register struct ctl_proc *cc;
556 int properlen;
557 int maclen;
559 #ifdef DEBUG
560 if (debug > 2)
561 printf("in process_control()\n");
562 #endif
565 * Save the addresses for error responses
567 numctlreq++;
568 rmt_addr = &rbufp->recv_srcadr;
569 lcl_inter = rbufp->dstadr;
570 pkt = (struct ntp_control *)&rbufp->recv_pkt;
573 * If the length is less than required for the header, or
574 * it is a response or a fragment, ignore this.
576 if (rbufp->recv_length < CTL_HEADER_LEN
577 || pkt->r_m_e_op & (CTL_RESPONSE|CTL_MORE|CTL_ERROR)
578 || pkt->offset != 0) {
579 #ifdef DEBUG
580 if (debug)
581 printf("invalid format in control packet\n");
582 #endif
583 if (rbufp->recv_length < CTL_HEADER_LEN)
584 numctltooshort++;
585 if (pkt->r_m_e_op & CTL_RESPONSE)
586 numctlinputresp++;
587 if (pkt->r_m_e_op & CTL_MORE)
588 numctlinputfrag++;
589 if (pkt->r_m_e_op & CTL_ERROR)
590 numctlinputerr++;
591 if (pkt->offset != 0)
592 numctlbadoffset++;
593 return;
595 res_version = PKT_VERSION(pkt->li_vn_mode);
596 if (res_version > NTP_VERSION || res_version < NTP_OLDVERSION) {
597 #ifdef DEBUG
598 if (debug)
599 printf("unknown version %d in control packet\n",
600 res_version);
601 #endif
602 numctlbadversion++;
603 return;
607 * Pull enough data from the packet to make intelligent
608 * responses
610 rpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap, res_version,
611 MODE_CONTROL);
612 res_opcode = pkt->r_m_e_op;
613 rpkt.sequence = pkt->sequence;
614 rpkt.associd = pkt->associd;
615 rpkt.status = 0;
616 res_offset = 0;
617 res_associd = htons(pkt->associd);
618 res_async = 0;
619 res_authenticate = 0;
620 res_keyid = 0;
621 res_authokay = 0;
622 req_count = (int)htons(pkt->count);
623 datanotbinflag = 0;
624 datalinelen = 0;
625 datapt = rpkt.data;
626 dataend = &(rpkt.data[CTL_MAX_DATA_LEN]);
629 * We're set up now. Make sure we've got at least enough
630 * incoming data space to match the count.
632 req_data = rbufp->recv_length - CTL_HEADER_LEN;
633 if (req_data < req_count || rbufp->recv_length & 0x3) {
634 ctl_error(CERR_BADFMT);
635 numctldatatooshort++;
636 return;
639 properlen = req_count + CTL_HEADER_LEN;
640 #ifdef DEBUG
641 if (debug > 2 && (rbufp->recv_length & 0x3) != 0)
642 printf("Packet length %d unrounded\n",
643 rbufp->recv_length);
644 #endif
645 /* round up proper len to a 8 octet boundary */
647 properlen = (properlen + 7) & ~7;
648 maclen = rbufp->recv_length - properlen;
649 if ((rbufp->recv_length & (sizeof(u_long) - 1)) == 0 &&
650 maclen >= MIN_MAC_LEN && maclen <= MAX_MAC_LEN &&
651 sys_authenticate) {
652 res_authenticate = 1;
653 res_keyid = ntohl(*(u_int32 *)((u_char *)pkt +
654 properlen));
656 #ifdef DEBUG
657 if (debug > 2)
658 printf(
659 "recv_len %d, properlen %d, wants auth with keyid %08x, MAC length=%d\n",
660 rbufp->recv_length, properlen, res_keyid, maclen);
661 #endif
662 if (!authistrusted(res_keyid)) {
663 #ifdef DEBUG
664 if (debug > 2)
665 printf("invalid keyid %08x\n",
666 res_keyid);
667 #endif
668 } else if (authdecrypt(res_keyid, (u_int32 *)pkt,
669 rbufp->recv_length - maclen, maclen)) {
670 #ifdef DEBUG
671 if (debug > 2)
672 printf("authenticated okay\n");
673 #endif
674 res_authokay = 1;
675 } else {
676 #ifdef DEBUG
677 if (debug > 2)
678 printf("authentication failed\n");
679 #endif
680 res_keyid = 0;
685 * Set up translate pointers
687 reqpt = (char *)pkt->data;
688 reqend = reqpt + req_count;
691 * Look for the opcode processor
693 for (cc = control_codes; cc->control_code != NO_REQUEST; cc++) {
694 if (cc->control_code == res_opcode) {
695 #ifdef DEBUG
696 if (debug > 2)
697 printf("opcode %d, found command handler\n",
698 res_opcode);
699 #endif
700 if (cc->flags == AUTH && (!res_authokay ||
701 res_keyid != ctl_auth_keyid)) {
702 ctl_error(CERR_PERMISSION);
703 return;
705 (cc->handler)(rbufp, restrict_mask);
706 return;
711 * Can't find this one, return an error.
713 numctlbadop++;
714 ctl_error(CERR_BADOP);
715 return;
720 * ctlpeerstatus - return a status word for this peer
722 u_short
723 ctlpeerstatus(
724 register struct peer *peer
727 register u_short status;
729 status = peer->status;
730 if (peer->flags & FLAG_CONFIG)
731 status |= CTL_PST_CONFIG;
732 if (peer->flags & FLAG_AUTHENABLE)
733 status |= CTL_PST_AUTHENABLE;
734 if (peer->flags & FLAG_AUTHENTIC)
735 status |= CTL_PST_AUTHENTIC;
736 if (peer->reach != 0)
737 status |= CTL_PST_REACH;
738 return (u_short)CTL_PEER_STATUS(status, peer->num_events,
739 peer->last_event);
744 * ctlclkstatus - return a status word for this clock
746 #ifdef REFCLOCK
747 static u_short
748 ctlclkstatus(
749 struct refclockstat *this_clock
752 return ((u_short)(((this_clock->currentstatus) << 8) |
753 (this_clock->lastevent)));
755 #endif
759 * ctlsysstatus - return the system status word
761 u_short
762 ctlsysstatus(void)
764 register u_char this_clock;
766 this_clock = CTL_SST_TS_UNSPEC;
767 #ifdef REFCLOCK
768 if (sys_peer != 0) {
769 if (sys_peer->sstclktype != CTL_SST_TS_UNSPEC) {
770 this_clock = sys_peer->sstclktype;
771 if (pps_control)
772 this_clock |= CTL_SST_TS_PPS;
773 } else {
774 if (sys_peer->refclktype < sizeof(clocktypes))
775 this_clock =
776 clocktypes[sys_peer->refclktype];
777 if (pps_control)
778 this_clock |= CTL_SST_TS_PPS;
781 #endif /* REFCLOCK */
782 return (u_short)CTL_SYS_STATUS(sys_leap, this_clock,
783 ctl_sys_num_events, ctl_sys_last_event);
788 * ctl_flushpkt - write out the current packet and prepare
789 * another if necessary.
791 static void
792 ctl_flushpkt(
793 int more
796 int dlen;
797 int sendlen;
799 if (!more && datanotbinflag) {
801 * Big hack, output a trailing \r\n
803 *datapt++ = '\r';
804 *datapt++ = '\n';
806 dlen = datapt - (u_char *)rpkt.data;
807 sendlen = dlen + CTL_HEADER_LEN;
810 * Pad to a multiple of 32 bits
812 while (sendlen & 0x3) {
813 *datapt++ = '\0';
814 sendlen++;
818 * Fill in the packet with the current info
820 rpkt.r_m_e_op = (u_char)(CTL_RESPONSE|more|(res_opcode &
821 CTL_OP_MASK));
822 rpkt.count = htons((u_short) dlen);
823 rpkt.offset = htons( (u_short) res_offset);
824 if (res_async) {
825 register int i;
827 for (i = 0; i < CTL_MAXTRAPS; i++) {
828 if (ctl_trap[i].tr_flags & TRAP_INUSE) {
829 rpkt.li_vn_mode =
830 PKT_LI_VN_MODE(sys_leap,
831 ctl_trap[i].tr_version,
832 MODE_CONTROL);
833 rpkt.sequence =
834 htons(ctl_trap[i].tr_sequence);
835 sendpkt(&ctl_trap[i].tr_addr,
836 ctl_trap[i].tr_localaddr, -4,
837 (struct pkt *)&rpkt, sendlen);
838 if (!more)
839 ctl_trap[i].tr_sequence++;
840 numasyncmsgs++;
843 } else {
844 if (res_authenticate && sys_authenticate) {
845 int maclen;
846 int totlen = sendlen;
847 keyid_t keyid = htonl(res_keyid);
850 * If we are going to authenticate, then there
851 * is an additional requirement that the MAC
852 * begin on a 64 bit boundary.
854 while (totlen & 7) {
855 *datapt++ = '\0';
856 totlen++;
858 memcpy(datapt, &keyid, sizeof keyid);
859 maclen = authencrypt(res_keyid,
860 (u_int32 *)&rpkt, totlen);
861 sendpkt(rmt_addr, lcl_inter, -5,
862 (struct pkt *)&rpkt, totlen + maclen);
863 } else {
864 sendpkt(rmt_addr, lcl_inter, -6,
865 (struct pkt *)&rpkt, sendlen);
867 if (more)
868 numctlfrags++;
869 else
870 numctlresponses++;
874 * Set us up for another go around.
876 res_offset += dlen;
877 datapt = (u_char *)rpkt.data;
882 * ctl_putdata - write data into the packet, fragmenting and starting
883 * another if this one is full.
885 static void
886 ctl_putdata(
887 const char *dp,
888 unsigned int dlen,
889 int bin /* set to 1 when data is binary */
892 int overhead;
894 overhead = 0;
895 if (!bin) {
896 datanotbinflag = 1;
897 overhead = 3;
898 if (datapt != rpkt.data) {
899 *datapt++ = ',';
900 datalinelen++;
901 if ((dlen + datalinelen + 1) >= MAXDATALINELEN)
903 *datapt++ = '\r';
904 *datapt++ = '\n';
905 datalinelen = 0;
906 } else {
907 *datapt++ = ' ';
908 datalinelen++;
914 * Save room for trailing junk
916 if (dlen + overhead + datapt > dataend) {
918 * Not enough room in this one, flush it out.
920 ctl_flushpkt(CTL_MORE);
922 memmove((char *)datapt, dp, (unsigned)dlen);
923 datapt += dlen;
924 datalinelen += dlen;
929 * ctl_putstr - write a tagged string into the response packet
931 static void
932 ctl_putstr(
933 const char *tag,
934 const char *data,
935 unsigned int len
938 register char *cp;
939 register const char *cq;
940 char buffer[400];
942 cp = buffer;
943 cq = tag;
944 while (*cq != '\0')
945 *cp++ = *cq++;
946 if (len > 0) {
947 *cp++ = '=';
948 *cp++ = '"';
949 if (len > (int) (sizeof(buffer) - (cp - buffer) - 1))
950 len = sizeof(buffer) - (cp - buffer) - 1;
951 memmove(cp, data, (unsigned)len);
952 cp += len;
953 *cp++ = '"';
955 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
960 * ctl_putdbl - write a tagged, signed double into the response packet
962 static void
963 ctl_putdbl(
964 const char *tag,
965 double ts
968 register char *cp;
969 register const char *cq;
970 char buffer[200];
972 cp = buffer;
973 cq = tag;
974 while (*cq != '\0')
975 *cp++ = *cq++;
976 *cp++ = '=';
977 (void)sprintf(cp, "%.3f", ts);
978 while (*cp != '\0')
979 cp++;
980 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
984 * ctl_putuint - write a tagged unsigned integer into the response
986 static void
987 ctl_putuint(
988 const char *tag,
989 u_long uval
992 register char *cp;
993 register const char *cq;
994 char buffer[200];
996 cp = buffer;
997 cq = tag;
998 while (*cq != '\0')
999 *cp++ = *cq++;
1001 *cp++ = '=';
1002 (void) sprintf(cp, "%lu", uval);
1003 while (*cp != '\0')
1004 cp++;
1005 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1008 #ifdef OPENSSL
1010 * ctl_putfs - write a decoded filestamp into the response
1012 static void
1013 ctl_putfs(
1014 const char *tag,
1015 tstamp_t uval
1018 register char *cp;
1019 register const char *cq;
1020 char buffer[200];
1021 struct tm *tm = NULL;
1022 time_t fstamp;
1024 cp = buffer;
1025 cq = tag;
1026 while (*cq != '\0')
1027 *cp++ = *cq++;
1029 *cp++ = '=';
1030 fstamp = uval - JAN_1970;
1031 tm = gmtime(&fstamp);
1032 if (tm == NULL)
1033 return;
1035 sprintf(cp, "%04d%02d%02d%02d%02d", tm->tm_year + 1900,
1036 tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min);
1037 while (*cp != '\0')
1038 cp++;
1039 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1041 #endif /* OPENSSL */
1045 * ctl_puthex - write a tagged unsigned integer, in hex, into the response
1047 static void
1048 ctl_puthex(
1049 const char *tag,
1050 u_long uval
1053 register char *cp;
1054 register const char *cq;
1055 char buffer[200];
1057 cp = buffer;
1058 cq = tag;
1059 while (*cq != '\0')
1060 *cp++ = *cq++;
1062 *cp++ = '=';
1063 (void) sprintf(cp, "0x%lx", uval);
1064 while (*cp != '\0')
1065 cp++;
1066 ctl_putdata(buffer,(unsigned)( cp - buffer ), 0);
1071 * ctl_putint - write a tagged signed integer into the response
1073 static void
1074 ctl_putint(
1075 const char *tag,
1076 long ival
1079 register char *cp;
1080 register const char *cq;
1081 char buffer[200];
1083 cp = buffer;
1084 cq = tag;
1085 while (*cq != '\0')
1086 *cp++ = *cq++;
1088 *cp++ = '=';
1089 (void) sprintf(cp, "%ld", ival);
1090 while (*cp != '\0')
1091 cp++;
1092 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1097 * ctl_putts - write a tagged timestamp, in hex, into the response
1099 static void
1100 ctl_putts(
1101 const char *tag,
1102 l_fp *ts
1105 register char *cp;
1106 register const char *cq;
1107 char buffer[200];
1109 cp = buffer;
1110 cq = tag;
1111 while (*cq != '\0')
1112 *cp++ = *cq++;
1114 *cp++ = '=';
1115 (void) sprintf(cp, "0x%08lx.%08lx",
1116 ts->l_ui & ULONG_CONST(0xffffffff),
1117 ts->l_uf & ULONG_CONST(0xffffffff));
1118 while (*cp != '\0')
1119 cp++;
1120 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1125 * ctl_putadr - write an IP address into the response
1127 static void
1128 ctl_putadr(
1129 const char *tag,
1130 u_int32 addr32,
1131 struct sockaddr_storage* addr
1134 register char *cp;
1135 register const char *cq;
1136 char buffer[200];
1138 cp = buffer;
1139 cq = tag;
1140 while (*cq != '\0')
1141 *cp++ = *cq++;
1143 *cp++ = '=';
1144 if (addr == NULL)
1145 cq = numtoa(addr32);
1146 else
1147 cq = stoa(addr);
1148 while (*cq != '\0')
1149 *cp++ = *cq++;
1150 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1154 * ctl_putid - write a tagged clock ID into the response
1156 static void
1157 ctl_putid(
1158 const char *tag,
1159 char *id
1162 register char *cp;
1163 register const char *cq;
1164 char buffer[200];
1166 cp = buffer;
1167 cq = tag;
1168 while (*cq != '\0')
1169 *cp++ = *cq++;
1171 *cp++ = '=';
1172 cq = id;
1173 while (*cq != '\0' && (cq - id) < 4)
1174 *cp++ = *cq++;
1175 ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1180 * ctl_putarray - write a tagged eight element double array into the response
1182 static void
1183 ctl_putarray(
1184 const char *tag,
1185 double *arr,
1186 int start
1189 register char *cp;
1190 register const char *cq;
1191 char buffer[200];
1192 int i;
1193 cp = buffer;
1194 cq = tag;
1195 while (*cq != '\0')
1196 *cp++ = *cq++;
1197 i = start;
1198 do {
1199 if (i == 0)
1200 i = NTP_SHIFT;
1201 i--;
1202 (void)sprintf(cp, " %.2f", arr[i] * 1e3);
1203 while (*cp != '\0')
1204 cp++;
1205 } while(i != start);
1206 ctl_putdata(buffer, (unsigned)(cp - buffer), 0);
1211 * ctl_putsys - output a system variable
1213 static void
1214 ctl_putsys(
1215 int varid
1218 l_fp tmp;
1219 char str[256];
1220 #ifdef OPENSSL
1221 struct cert_info *cp;
1222 char cbuf[256];
1223 #endif /* OPENSSL */
1225 switch (varid) {
1227 case CS_LEAP:
1228 ctl_putuint(sys_var[CS_LEAP].text, sys_leap);
1229 break;
1231 case CS_STRATUM:
1232 ctl_putuint(sys_var[CS_STRATUM].text, sys_stratum);
1233 break;
1235 case CS_PRECISION:
1236 ctl_putint(sys_var[CS_PRECISION].text, sys_precision);
1237 break;
1239 case CS_ROOTDELAY:
1240 ctl_putdbl(sys_var[CS_ROOTDELAY].text, sys_rootdelay *
1241 1e3);
1242 break;
1244 case CS_ROOTDISPERSION:
1245 ctl_putdbl(sys_var[CS_ROOTDISPERSION].text,
1246 sys_rootdispersion * 1e3);
1247 break;
1249 case CS_REFID:
1250 if (sys_stratum > 1 && sys_stratum < STRATUM_UNSPEC)
1251 ctl_putadr(sys_var[CS_REFID].text, sys_refid, NULL);
1252 else
1253 ctl_putid(sys_var[CS_REFID].text,
1254 (char *)&sys_refid);
1255 break;
1257 case CS_REFTIME:
1258 ctl_putts(sys_var[CS_REFTIME].text, &sys_reftime);
1259 break;
1261 case CS_POLL:
1262 ctl_putuint(sys_var[CS_POLL].text, sys_poll);
1263 break;
1265 case CS_PEERID:
1266 if (sys_peer == NULL)
1267 ctl_putuint(sys_var[CS_PEERID].text, 0);
1268 else
1269 ctl_putuint(sys_var[CS_PEERID].text,
1270 sys_peer->associd);
1271 break;
1273 case CS_STATE:
1274 ctl_putuint(sys_var[CS_STATE].text, (unsigned)state);
1275 break;
1277 case CS_OFFSET:
1278 ctl_putdbl(sys_var[CS_OFFSET].text, last_offset * 1e3);
1279 break;
1281 case CS_DRIFT:
1282 ctl_putdbl(sys_var[CS_DRIFT].text, drift_comp * 1e6);
1283 break;
1285 case CS_JITTER:
1286 ctl_putdbl(sys_var[CS_JITTER].text, sys_jitter * 1e3);
1287 break;
1289 case CS_ERROR:
1290 ctl_putdbl(sys_var[CS_ERROR].text, clock_jitter * 1e3);
1291 break;
1293 case CS_CLOCK:
1294 get_systime(&tmp);
1295 ctl_putts(sys_var[CS_CLOCK].text, &tmp);
1296 break;
1298 case CS_PROCESSOR:
1299 #ifndef HAVE_UNAME
1300 ctl_putstr(sys_var[CS_PROCESSOR].text, str_processor,
1301 sizeof(str_processor) - 1);
1302 #else
1303 ctl_putstr(sys_var[CS_PROCESSOR].text,
1304 utsnamebuf.machine, strlen(utsnamebuf.machine));
1305 #endif /* HAVE_UNAME */
1306 break;
1308 case CS_SYSTEM:
1309 #ifndef HAVE_UNAME
1310 ctl_putstr(sys_var[CS_SYSTEM].text, str_system,
1311 sizeof(str_system) - 1);
1312 #else
1313 sprintf(str, "%s/%s", utsnamebuf.sysname, utsnamebuf.release);
1314 ctl_putstr(sys_var[CS_SYSTEM].text, str, strlen(str));
1315 #endif /* HAVE_UNAME */
1316 break;
1318 case CS_VERSION:
1319 ctl_putstr(sys_var[CS_VERSION].text, Version,
1320 strlen(Version));
1321 break;
1323 case CS_STABIL:
1324 ctl_putdbl(sys_var[CS_STABIL].text, clock_stability *
1325 1e6);
1326 break;
1328 case CS_VARLIST:
1330 char buf[CTL_MAX_DATA_LEN];
1331 register char *s, *t, *be;
1332 register const char *ss;
1333 register int i;
1334 register struct ctl_var *k;
1336 s = buf;
1337 be = buf + sizeof(buf) -
1338 strlen(sys_var[CS_VARLIST].text) - 4;
1339 if (s > be)
1340 break; /* really long var name */
1342 strcpy(s, sys_var[CS_VARLIST].text);
1343 strcat(s, "=\"");
1344 s += strlen(s);
1345 t = s;
1346 for (k = sys_var; !(k->flags &EOV); k++) {
1347 if (k->flags & PADDING)
1348 continue;
1349 i = strlen(k->text);
1350 if (s+i+1 >= be)
1351 break;
1353 if (s != t)
1354 *s++ = ',';
1355 strcpy(s, k->text);
1356 s += i;
1359 for (k = ext_sys_var; k && !(k->flags &EOV);
1360 k++) {
1361 if (k->flags & PADDING)
1362 continue;
1364 ss = k->text;
1365 if (!ss)
1366 continue;
1368 while (*ss && *ss != '=')
1369 ss++;
1370 i = ss - k->text;
1371 if (s + i + 1 >= be)
1372 break;
1374 if (s != t)
1375 *s++ = ',';
1376 strncpy(s, k->text,
1377 (unsigned)i);
1378 s += i;
1380 if (s+2 >= be)
1381 break;
1383 *s++ = '"';
1384 *s = '\0';
1386 ctl_putdata(buf, (unsigned)( s - buf ),
1389 break;
1391 #ifdef OPENSSL
1392 case CS_FLAGS:
1393 if (crypto_flags) {
1394 ctl_puthex(sys_var[CS_FLAGS].text, crypto_flags);
1396 break;
1398 case CS_DIGEST:
1399 if (crypto_flags) {
1400 const EVP_MD *dp;
1402 dp = EVP_get_digestbynid(crypto_flags >> 16);
1403 strcpy(str, OBJ_nid2ln(EVP_MD_pkey_type(dp)));
1404 ctl_putstr(sys_var[CS_DIGEST].text, str,
1405 strlen(str));
1407 break;
1409 case CS_HOST:
1410 if (sys_hostname != NULL)
1411 ctl_putstr(sys_var[CS_HOST].text, sys_hostname,
1412 strlen(sys_hostname));
1413 break;
1415 case CS_CERTIF:
1416 for (cp = cinfo; cp != NULL; cp = cp->link) {
1417 sprintf(cbuf, "%s %s 0x%x", cp->subject,
1418 cp->issuer, cp->flags);
1419 ctl_putstr(sys_var[CS_CERTIF].text, cbuf,
1420 strlen(cbuf));
1421 ctl_putfs(sys_var[CS_REVOKE].text, cp->last);
1423 break;
1425 case CS_PUBLIC:
1426 if (hostval.fstamp != 0)
1427 ctl_putfs(sys_var[CS_PUBLIC].text,
1428 ntohl(hostval.tstamp));
1429 break;
1431 case CS_REVTIME:
1432 if (hostval.tstamp != 0)
1433 ctl_putfs(sys_var[CS_REVTIME].text,
1434 ntohl(hostval.tstamp));
1435 break;
1437 case CS_IDENT:
1438 if (iffpar_pkey != NULL)
1439 ctl_putstr(sys_var[CS_IDENT].text,
1440 iffpar_file, strlen(iffpar_file));
1441 if (gqpar_pkey != NULL)
1442 ctl_putstr(sys_var[CS_IDENT].text,
1443 gqpar_file, strlen(gqpar_file));
1444 if (mvpar_pkey != NULL)
1445 ctl_putstr(sys_var[CS_IDENT].text,
1446 mvpar_file, strlen(mvpar_file));
1447 break;
1449 case CS_LEAPTAB:
1450 if (tai_leap.fstamp != 0)
1451 ctl_putfs(sys_var[CS_LEAPTAB].text,
1452 ntohl(tai_leap.fstamp));
1453 break;
1455 case CS_TAI:
1456 ctl_putuint(sys_var[CS_TAI].text, sys_tai);
1457 break;
1458 #endif /* OPENSSL */
1464 * ctl_putpeer - output a peer variable
1466 static void
1467 ctl_putpeer(
1468 int varid,
1469 struct peer *peer
1472 int temp;
1473 #ifdef OPENSSL
1474 char str[256];
1475 struct autokey *ap;
1476 #endif /* OPENSSL */
1478 switch (varid) {
1480 case CP_CONFIG:
1481 ctl_putuint(peer_var[CP_CONFIG].text,
1482 (unsigned)((peer->flags & FLAG_CONFIG) != 0));
1483 break;
1485 case CP_AUTHENABLE:
1486 ctl_putuint(peer_var[CP_AUTHENABLE].text,
1487 (unsigned)((peer->flags & FLAG_AUTHENABLE) != 0));
1488 break;
1490 case CP_AUTHENTIC:
1491 ctl_putuint(peer_var[CP_AUTHENTIC].text,
1492 (unsigned)((peer->flags & FLAG_AUTHENTIC) != 0));
1493 break;
1495 case CP_SRCADR:
1496 ctl_putadr(peer_var[CP_SRCADR].text, 0,
1497 &peer->srcadr);
1498 break;
1500 case CP_SRCPORT:
1501 ctl_putuint(peer_var[CP_SRCPORT].text,
1502 ntohs(((struct sockaddr_in*)&peer->srcadr)->sin_port));
1503 break;
1505 case CP_DSTADR:
1506 if (peer->dstadr) {
1507 ctl_putadr(peer_var[CP_DSTADR].text, 0,
1508 &(peer->dstadr->sin));
1509 } else {
1510 ctl_putadr(peer_var[CP_DSTADR].text, 0,
1511 NULL);
1513 break;
1515 case CP_DSTPORT:
1516 ctl_putuint(peer_var[CP_DSTPORT].text,
1517 (u_long)(peer->dstadr ?
1518 ntohs(((struct sockaddr_in*)&peer->dstadr->sin)->sin_port) : 0));
1519 break;
1521 case CP_LEAP:
1522 ctl_putuint(peer_var[CP_LEAP].text, peer->leap);
1523 break;
1525 case CP_HMODE:
1526 ctl_putuint(peer_var[CP_HMODE].text, peer->hmode);
1527 break;
1529 case CP_STRATUM:
1530 ctl_putuint(peer_var[CP_STRATUM].text, peer->stratum);
1531 break;
1533 case CP_PPOLL:
1534 ctl_putuint(peer_var[CP_PPOLL].text, peer->ppoll);
1535 break;
1537 case CP_HPOLL:
1538 ctl_putuint(peer_var[CP_HPOLL].text, peer->hpoll);
1539 break;
1541 case CP_PRECISION:
1542 ctl_putint(peer_var[CP_PRECISION].text,
1543 peer->precision);
1544 break;
1546 case CP_ROOTDELAY:
1547 ctl_putdbl(peer_var[CP_ROOTDELAY].text,
1548 peer->rootdelay * 1e3);
1549 break;
1551 case CP_ROOTDISPERSION:
1552 ctl_putdbl(peer_var[CP_ROOTDISPERSION].text,
1553 peer->rootdispersion * 1e3);
1554 break;
1556 case CP_REFID:
1557 if (peer->flags & FLAG_REFCLOCK) {
1558 ctl_putid(peer_var[CP_REFID].text,
1559 (char *)&peer->refid);
1560 } else {
1561 if (peer->stratum > 1 && peer->stratum <
1562 STRATUM_UNSPEC)
1563 ctl_putadr(peer_var[CP_REFID].text,
1564 peer->refid, NULL);
1565 else
1566 ctl_putid(peer_var[CP_REFID].text,
1567 (char *)&peer->refid);
1569 break;
1571 case CP_REFTIME:
1572 ctl_putts(peer_var[CP_REFTIME].text, &peer->reftime);
1573 break;
1575 case CP_ORG:
1576 ctl_putts(peer_var[CP_ORG].text, &peer->org);
1577 break;
1579 case CP_REC:
1580 ctl_putts(peer_var[CP_REC].text, &peer->rec);
1581 break;
1583 case CP_XMT:
1584 ctl_putts(peer_var[CP_XMT].text, &peer->xmt);
1585 break;
1587 case CP_REACH:
1588 ctl_puthex(peer_var[CP_REACH].text, peer->reach);
1589 break;
1591 case CP_FLASH:
1592 temp = peer->flash;
1593 ctl_puthex(peer_var[CP_FLASH].text, temp);
1594 break;
1596 case CP_TTL:
1597 ctl_putint(peer_var[CP_TTL].text, sys_ttl[peer->ttl]);
1598 break;
1600 case CP_UNREACH:
1601 ctl_putuint(peer_var[CP_UNREACH].text, peer->unreach);
1602 break;
1604 case CP_TIMER:
1605 ctl_putuint(peer_var[CP_TIMER].text,
1606 peer->nextdate - current_time);
1607 break;
1609 case CP_DELAY:
1610 ctl_putdbl(peer_var[CP_DELAY].text, peer->delay * 1e3);
1611 break;
1613 case CP_OFFSET:
1614 ctl_putdbl(peer_var[CP_OFFSET].text, peer->offset *
1615 1e3);
1616 break;
1618 case CP_JITTER:
1619 ctl_putdbl(peer_var[CP_JITTER].text, peer->jitter * 1e3);
1620 break;
1622 case CP_DISPERSION:
1623 ctl_putdbl(peer_var[CP_DISPERSION].text, peer->disp *
1624 1e3);
1625 break;
1627 case CP_KEYID:
1628 ctl_putuint(peer_var[CP_KEYID].text, peer->keyid);
1629 break;
1631 case CP_FILTDELAY:
1632 ctl_putarray(peer_var[CP_FILTDELAY].text,
1633 peer->filter_delay, (int)peer->filter_nextpt);
1634 break;
1636 case CP_FILTOFFSET:
1637 ctl_putarray(peer_var[CP_FILTOFFSET].text,
1638 peer->filter_offset, (int)peer->filter_nextpt);
1639 break;
1641 case CP_FILTERROR:
1642 ctl_putarray(peer_var[CP_FILTERROR].text,
1643 peer->filter_disp, (int)peer->filter_nextpt);
1644 break;
1646 case CP_PMODE:
1647 ctl_putuint(peer_var[CP_PMODE].text, peer->pmode);
1648 break;
1650 case CP_RECEIVED:
1651 ctl_putuint(peer_var[CP_RECEIVED].text, peer->received);
1652 break;
1654 case CP_SENT:
1655 ctl_putuint(peer_var[CP_SENT].text, peer->sent);
1656 break;
1658 case CP_VARLIST:
1660 char buf[CTL_MAX_DATA_LEN];
1661 register char *s, *t, *be;
1662 register int i;
1663 register struct ctl_var *k;
1665 s = buf;
1666 be = buf + sizeof(buf) -
1667 strlen(peer_var[CP_VARLIST].text) - 4;
1668 if (s > be)
1669 break; /* really long var name */
1671 strcpy(s, peer_var[CP_VARLIST].text);
1672 strcat(s, "=\"");
1673 s += strlen(s);
1674 t = s;
1675 for (k = peer_var; !(k->flags &EOV); k++) {
1676 if (k->flags & PADDING)
1677 continue;
1679 i = strlen(k->text);
1680 if (s + i + 1 >= be)
1681 break;
1683 if (s != t)
1684 *s++ = ',';
1685 strcpy(s, k->text);
1686 s += i;
1688 if (s+2 >= be)
1689 break;
1691 *s++ = '"';
1692 *s = '\0';
1693 ctl_putdata(buf, (unsigned)(s - buf), 0);
1695 break;
1696 #ifdef OPENSSL
1697 case CP_FLAGS:
1698 if (peer->crypto)
1699 ctl_puthex(peer_var[CP_FLAGS].text, peer->crypto);
1700 break;
1702 case CP_DIGEST:
1703 if (peer->crypto) {
1704 const EVP_MD *dp;
1706 dp = EVP_get_digestbynid(peer->crypto >> 16);
1707 strcpy(str, OBJ_nid2ln(EVP_MD_pkey_type(dp)));
1708 ctl_putstr(peer_var[CP_DIGEST].text, str,
1709 strlen(str));
1711 break;
1713 case CP_HOST:
1714 if (peer->subject != NULL)
1715 ctl_putstr(peer_var[CP_HOST].text,
1716 peer->subject, strlen(peer->subject));
1717 break;
1719 case CP_VALID: /* not used */
1720 break;
1722 case CP_IDENT:
1723 if (peer->issuer != NULL)
1724 ctl_putstr(peer_var[CP_IDENT].text,
1725 peer->issuer, strlen(peer->issuer));
1726 break;
1728 case CP_INITSEQ:
1729 if ((ap = (struct autokey *)peer->recval.ptr) == NULL)
1730 break;
1731 ctl_putint(peer_var[CP_INITSEQ].text, ap->seq);
1732 ctl_puthex(peer_var[CP_INITKEY].text, ap->key);
1733 ctl_putfs(peer_var[CP_INITTSP].text,
1734 ntohl(peer->recval.tstamp));
1735 break;
1736 #endif /* OPENSSL */
1741 #ifdef REFCLOCK
1743 * ctl_putclock - output clock variables
1745 static void
1746 ctl_putclock(
1747 int varid,
1748 struct refclockstat *clock_stat,
1749 int mustput
1752 switch(varid) {
1754 case CC_TYPE:
1755 if (mustput || clock_stat->clockdesc == NULL
1756 || *(clock_stat->clockdesc) == '\0') {
1757 ctl_putuint(clock_var[CC_TYPE].text, clock_stat->type);
1759 break;
1760 case CC_TIMECODE:
1761 ctl_putstr(clock_var[CC_TIMECODE].text,
1762 clock_stat->p_lastcode,
1763 (unsigned)clock_stat->lencode);
1764 break;
1766 case CC_POLL:
1767 ctl_putuint(clock_var[CC_POLL].text, clock_stat->polls);
1768 break;
1770 case CC_NOREPLY:
1771 ctl_putuint(clock_var[CC_NOREPLY].text,
1772 clock_stat->noresponse);
1773 break;
1775 case CC_BADFORMAT:
1776 ctl_putuint(clock_var[CC_BADFORMAT].text,
1777 clock_stat->badformat);
1778 break;
1780 case CC_BADDATA:
1781 ctl_putuint(clock_var[CC_BADDATA].text,
1782 clock_stat->baddata);
1783 break;
1785 case CC_FUDGETIME1:
1786 if (mustput || (clock_stat->haveflags & CLK_HAVETIME1))
1787 ctl_putdbl(clock_var[CC_FUDGETIME1].text,
1788 clock_stat->fudgetime1 * 1e3);
1789 break;
1791 case CC_FUDGETIME2:
1792 if (mustput || (clock_stat->haveflags & CLK_HAVETIME2)) ctl_putdbl(clock_var[CC_FUDGETIME2].text,
1793 clock_stat->fudgetime2 * 1e3);
1794 break;
1796 case CC_FUDGEVAL1:
1797 if (mustput || (clock_stat->haveflags & CLK_HAVEVAL1))
1798 ctl_putint(clock_var[CC_FUDGEVAL1].text,
1799 clock_stat->fudgeval1);
1800 break;
1802 case CC_FUDGEVAL2:
1803 if (mustput || (clock_stat->haveflags & CLK_HAVEVAL2)) {
1804 if (clock_stat->fudgeval1 > 1)
1805 ctl_putadr(clock_var[CC_FUDGEVAL2].text,
1806 (u_int32)clock_stat->fudgeval2, NULL);
1807 else
1808 ctl_putid(clock_var[CC_FUDGEVAL2].text,
1809 (char *)&clock_stat->fudgeval2);
1811 break;
1813 case CC_FLAGS:
1814 if (mustput || (clock_stat->haveflags & (CLK_HAVEFLAG1 |
1815 CLK_HAVEFLAG2 | CLK_HAVEFLAG3 | CLK_HAVEFLAG4)))
1816 ctl_putuint(clock_var[CC_FLAGS].text,
1817 clock_stat->flags);
1818 break;
1820 case CC_DEVICE:
1821 if (clock_stat->clockdesc == NULL ||
1822 *(clock_stat->clockdesc) == '\0') {
1823 if (mustput)
1824 ctl_putstr(clock_var[CC_DEVICE].text,
1825 "", 0);
1826 } else {
1827 ctl_putstr(clock_var[CC_DEVICE].text,
1828 clock_stat->clockdesc,
1829 strlen(clock_stat->clockdesc));
1831 break;
1833 case CC_VARLIST:
1835 char buf[CTL_MAX_DATA_LEN];
1836 register char *s, *t, *be;
1837 register const char *ss;
1838 register int i;
1839 register struct ctl_var *k;
1841 s = buf;
1842 be = buf + sizeof(buf);
1843 if (s + strlen(clock_var[CC_VARLIST].text) + 4 >
1845 break; /* really long var name */
1847 strcpy(s, clock_var[CC_VARLIST].text);
1848 strcat(s, "=\"");
1849 s += strlen(s);
1850 t = s;
1852 for (k = clock_var; !(k->flags &EOV); k++) {
1853 if (k->flags & PADDING)
1854 continue;
1856 i = strlen(k->text);
1857 if (s + i + 1 >= be)
1858 break;
1860 if (s != t)
1861 *s++ = ',';
1862 strcpy(s, k->text);
1863 s += i;
1866 for (k = clock_stat->kv_list; k && !(k->flags &
1867 EOV); k++) {
1868 if (k->flags & PADDING)
1869 continue;
1871 ss = k->text;
1872 if (!ss)
1873 continue;
1875 while (*ss && *ss != '=')
1876 ss++;
1877 i = ss - k->text;
1878 if (s+i+1 >= be)
1879 break;
1881 if (s != t)
1882 *s++ = ',';
1883 strncpy(s, k->text, (unsigned)i);
1884 s += i;
1885 *s = '\0';
1887 if (s+2 >= be)
1888 break;
1890 *s++ = '"';
1891 *s = '\0';
1892 ctl_putdata(buf, (unsigned)( s - buf ), 0);
1894 break;
1897 #endif
1902 * ctl_getitem - get the next data item from the incoming packet
1904 static struct ctl_var *
1905 ctl_getitem(
1906 struct ctl_var *var_list,
1907 char **data
1910 register struct ctl_var *v;
1911 register char *cp;
1912 register char *tp;
1913 static struct ctl_var eol = { 0, EOV, };
1914 static char buf[128];
1917 * Delete leading commas and white space
1919 while (reqpt < reqend && (*reqpt == ',' ||
1920 isspace((unsigned char)*reqpt)))
1921 reqpt++;
1922 if (reqpt >= reqend)
1923 return (0);
1925 if (var_list == (struct ctl_var *)0)
1926 return (&eol);
1929 * Look for a first character match on the tag. If we find
1930 * one, see if it is a full match.
1932 v = var_list;
1933 cp = reqpt;
1934 while (!(v->flags & EOV)) {
1935 if (!(v->flags & PADDING) && *cp == *(v->text)) {
1936 tp = v->text;
1937 while (*tp != '\0' && *tp != '=' && cp <
1938 reqend && *cp == *tp) {
1939 cp++;
1940 tp++;
1942 if ((*tp == '\0') || (*tp == '=')) {
1943 while (cp < reqend && isspace((unsigned char)*cp))
1944 cp++;
1945 if (cp == reqend || *cp == ',') {
1946 buf[0] = '\0';
1947 *data = buf;
1948 if (cp < reqend)
1949 cp++;
1950 reqpt = cp;
1951 return v;
1953 if (*cp == '=') {
1954 cp++;
1955 tp = buf;
1956 while (cp < reqend && isspace((unsigned char)*cp))
1957 cp++;
1958 while (cp < reqend && *cp != ',') {
1959 *tp++ = *cp++;
1960 if (tp >= buf + sizeof(buf)) {
1961 ctl_error(CERR_BADFMT);
1962 numctlbadpkts++;
1963 #if 0 /* Avoid possible DOS attack */
1964 /* If we get a smarter msyslog we can re-enable this */
1965 msyslog(LOG_WARNING,
1966 "Possible 'ntpdx' exploit from %s:%d (possibly spoofed)\n",
1967 stoa(rmt_addr), SRCPORT(rmt_addr)
1969 #endif
1970 return (0);
1973 if (cp < reqend)
1974 cp++;
1975 *tp-- = '\0';
1976 while (tp >= buf) {
1977 if (!isspace((unsigned int)(*tp)))
1978 break;
1979 *tp-- = '\0';
1981 reqpt = cp;
1982 *data = buf;
1983 return (v);
1986 cp = reqpt;
1988 v++;
1990 return v;
1995 * control_unspec - response to an unspecified op-code
1997 /*ARGSUSED*/
1998 static void
1999 control_unspec(
2000 struct recvbuf *rbufp,
2001 int restrict_mask
2004 struct peer *peer;
2007 * What is an appropriate response to an unspecified op-code?
2008 * I return no errors and no data, unless a specified assocation
2009 * doesn't exist.
2011 if (res_associd != 0) {
2012 if ((peer = findpeerbyassoc(res_associd)) == 0) {
2013 ctl_error(CERR_BADASSOC);
2014 return;
2016 rpkt.status = htons(ctlpeerstatus(peer));
2017 } else {
2018 rpkt.status = htons(ctlsysstatus());
2020 ctl_flushpkt(0);
2025 * read_status - return either a list of associd's, or a particular
2026 * peer's status.
2028 /*ARGSUSED*/
2029 static void
2030 read_status(
2031 struct recvbuf *rbufp,
2032 int restrict_mask
2035 register int i;
2036 register struct peer *peer;
2037 u_short ass_stat[CTL_MAX_DATA_LEN / sizeof(u_short)];
2039 #ifdef DEBUG
2040 if (debug > 2)
2041 printf("read_status: ID %d\n", res_associd);
2042 #endif
2044 * Two choices here. If the specified association ID is
2045 * zero we return all known assocation ID's. Otherwise
2046 * we return a bunch of stuff about the particular peer.
2048 if (res_associd == 0) {
2049 register int n;
2051 n = 0;
2052 rpkt.status = htons(ctlsysstatus());
2053 for (i = 0; i < NTP_HASH_SIZE; i++) {
2054 for (peer = assoc_hash[i]; peer != 0;
2055 peer = peer->ass_next) {
2056 ass_stat[n++] = htons(peer->associd);
2057 ass_stat[n++] =
2058 htons(ctlpeerstatus(peer));
2059 if (n ==
2060 CTL_MAX_DATA_LEN/sizeof(u_short)) {
2061 ctl_putdata((char *)ass_stat,
2062 n * sizeof(u_short), 1);
2063 n = 0;
2068 if (n != 0)
2069 ctl_putdata((char *)ass_stat, n *
2070 sizeof(u_short), 1);
2071 ctl_flushpkt(0);
2072 } else {
2073 peer = findpeerbyassoc(res_associd);
2074 if (peer == 0) {
2075 ctl_error(CERR_BADASSOC);
2076 } else {
2077 register u_char *cp;
2079 rpkt.status = htons(ctlpeerstatus(peer));
2080 if (res_authokay)
2081 peer->num_events = 0;
2083 * For now, output everything we know about the
2084 * peer. May be more selective later.
2086 for (cp = def_peer_var; *cp != 0; cp++)
2087 ctl_putpeer((int)*cp, peer);
2088 ctl_flushpkt(0);
2095 * read_variables - return the variables the caller asks for
2097 /*ARGSUSED*/
2098 static void
2099 read_variables(
2100 struct recvbuf *rbufp,
2101 int restrict_mask
2104 register struct ctl_var *v;
2105 register int i;
2106 char *valuep;
2107 u_char *wants;
2108 unsigned int gotvar = (CS_MAXCODE > CP_MAXCODE) ? (CS_MAXCODE +
2109 1) : (CP_MAXCODE + 1);
2110 if (res_associd == 0) {
2112 * Wants system variables. Figure out which he wants
2113 * and give them to him.
2115 rpkt.status = htons(ctlsysstatus());
2116 if (res_authokay)
2117 ctl_sys_num_events = 0;
2118 gotvar += count_var(ext_sys_var);
2119 wants = (u_char *)emalloc(gotvar);
2120 memset((char *)wants, 0, gotvar);
2121 gotvar = 0;
2122 while ((v = ctl_getitem(sys_var, &valuep)) != 0) {
2123 if (v->flags & EOV) {
2124 if ((v = ctl_getitem(ext_sys_var,
2125 &valuep)) != 0) {
2126 if (v->flags & EOV) {
2127 ctl_error(CERR_UNKNOWNVAR);
2128 free((char *)wants);
2129 return;
2131 wants[CS_MAXCODE + 1 +
2132 v->code] = 1;
2133 gotvar = 1;
2134 continue;
2135 } else {
2136 break; /* shouldn't happen ! */
2139 wants[v->code] = 1;
2140 gotvar = 1;
2142 if (gotvar) {
2143 for (i = 1; i <= CS_MAXCODE; i++)
2144 if (wants[i])
2145 ctl_putsys(i);
2146 for (i = 0; ext_sys_var &&
2147 !(ext_sys_var[i].flags & EOV); i++)
2148 if (wants[i + CS_MAXCODE + 1])
2149 ctl_putdata(ext_sys_var[i].text,
2150 strlen(ext_sys_var[i].text),
2152 } else {
2153 register u_char *cs;
2154 register struct ctl_var *kv;
2156 for (cs = def_sys_var; *cs != 0; cs++)
2157 ctl_putsys((int)*cs);
2158 for (kv = ext_sys_var; kv && !(kv->flags & EOV);
2159 kv++)
2160 if (kv->flags & DEF)
2161 ctl_putdata(kv->text,
2162 strlen(kv->text), 0);
2164 free((char *)wants);
2165 } else {
2166 register struct peer *peer;
2169 * Wants info for a particular peer. See if we know
2170 * the guy.
2172 peer = findpeerbyassoc(res_associd);
2173 if (peer == 0) {
2174 ctl_error(CERR_BADASSOC);
2175 return;
2177 rpkt.status = htons(ctlpeerstatus(peer));
2178 if (res_authokay)
2179 peer->num_events = 0;
2180 wants = (u_char *)emalloc(gotvar);
2181 memset((char*)wants, 0, gotvar);
2182 gotvar = 0;
2183 while ((v = ctl_getitem(peer_var, &valuep)) != 0) {
2184 if (v->flags & EOV) {
2185 ctl_error(CERR_UNKNOWNVAR);
2186 free((char *)wants);
2187 return;
2189 wants[v->code] = 1;
2190 gotvar = 1;
2192 if (gotvar) {
2193 for (i = 1; i <= CP_MAXCODE; i++)
2194 if (wants[i])
2195 ctl_putpeer(i, peer);
2196 } else {
2197 register u_char *cp;
2199 for (cp = def_peer_var; *cp != 0; cp++)
2200 ctl_putpeer((int)*cp, peer);
2202 free((char *)wants);
2204 ctl_flushpkt(0);
2209 * write_variables - write into variables. We only allow leap bit
2210 * writing this way.
2212 /*ARGSUSED*/
2213 static void
2214 write_variables(
2215 struct recvbuf *rbufp,
2216 int restrict_mask
2219 register struct ctl_var *v;
2220 register int ext_var;
2221 char *valuep;
2222 long val = 0;
2225 * If he's trying to write into a peer tell him no way
2227 if (res_associd != 0) {
2228 ctl_error(CERR_PERMISSION);
2229 return;
2233 * Set status
2235 rpkt.status = htons(ctlsysstatus());
2238 * Look through the variables. Dump out at the first sign of
2239 * trouble.
2241 while ((v = ctl_getitem(sys_var, &valuep)) != 0) {
2242 ext_var = 0;
2243 if (v->flags & EOV) {
2244 if ((v = ctl_getitem(ext_sys_var, &valuep)) !=
2245 0) {
2246 if (v->flags & EOV) {
2247 ctl_error(CERR_UNKNOWNVAR);
2248 return;
2250 ext_var = 1;
2251 } else {
2252 break;
2255 if (!(v->flags & CAN_WRITE)) {
2256 ctl_error(CERR_PERMISSION);
2257 return;
2259 if (!ext_var && (*valuep == '\0' || !atoint(valuep,
2260 &val))) {
2261 ctl_error(CERR_BADFMT);
2262 return;
2264 if (!ext_var && (val & ~LEAP_NOTINSYNC) != 0) {
2265 ctl_error(CERR_BADVALUE);
2266 return;
2269 if (ext_var) {
2270 char *s = (char *)emalloc(strlen(v->text) +
2271 strlen(valuep) + 2);
2272 const char *t;
2273 char *tt = s;
2275 t = v->text;
2276 while (*t && *t != '=')
2277 *tt++ = *t++;
2279 *tt++ = '=';
2280 strcat(tt, valuep);
2281 set_sys_var(s, strlen(s)+1, v->flags);
2282 free(s);
2283 } else {
2285 * This one seems sane. Save it.
2287 switch(v->code) {
2289 case CS_LEAP:
2290 default:
2291 ctl_error(CERR_UNSPEC); /* really */
2292 return;
2298 * If we got anything, do it. xxx nothing to do ***
2301 if (leapind != ~0 || leapwarn != ~0) {
2302 if (!leap_setleap((int)leapind, (int)leapwarn)) {
2303 ctl_error(CERR_PERMISSION);
2304 return;
2308 ctl_flushpkt(0);
2313 * read_clock_status - return clock radio status
2315 /*ARGSUSED*/
2316 static void
2317 read_clock_status(
2318 struct recvbuf *rbufp,
2319 int restrict_mask
2322 #ifndef REFCLOCK
2324 * If no refclock support, no data to return
2326 ctl_error(CERR_BADASSOC);
2327 #else
2328 register struct ctl_var *v;
2329 register int i;
2330 register struct peer *peer;
2331 char *valuep;
2332 u_char *wants;
2333 unsigned int gotvar;
2334 struct refclockstat clock_stat;
2336 if (res_associd == 0) {
2339 * Find a clock for this jerk. If the system peer
2340 * is a clock use it, else search the hash tables
2341 * for one.
2343 if (sys_peer != 0 && (sys_peer->flags & FLAG_REFCLOCK))
2345 peer = sys_peer;
2346 } else {
2347 peer = 0;
2348 for (i = 0; peer == 0 && i < NTP_HASH_SIZE; i++) {
2349 for (peer = assoc_hash[i]; peer != 0;
2350 peer = peer->ass_next) {
2351 if (peer->flags & FLAG_REFCLOCK)
2352 break;
2355 if (peer == 0) {
2356 ctl_error(CERR_BADASSOC);
2357 return;
2360 } else {
2361 peer = findpeerbyassoc(res_associd);
2362 if (peer == 0 || !(peer->flags & FLAG_REFCLOCK)) {
2363 ctl_error(CERR_BADASSOC);
2364 return;
2369 * If we got here we have a peer which is a clock. Get his
2370 * status.
2372 clock_stat.kv_list = (struct ctl_var *)0;
2373 refclock_control(&peer->srcadr, (struct refclockstat *)0,
2374 &clock_stat);
2377 * Look for variables in the packet.
2379 rpkt.status = htons(ctlclkstatus(&clock_stat));
2380 gotvar = CC_MAXCODE + 1 + count_var(clock_stat.kv_list);
2381 wants = (u_char *)emalloc(gotvar);
2382 memset((char*)wants, 0, gotvar);
2383 gotvar = 0;
2384 while ((v = ctl_getitem(clock_var, &valuep)) != 0) {
2385 if (v->flags & EOV) {
2386 if ((v = ctl_getitem(clock_stat.kv_list,
2387 &valuep)) != 0) {
2388 if (v->flags & EOV) {
2389 ctl_error(CERR_UNKNOWNVAR);
2390 free((char*)wants);
2391 free_varlist(clock_stat.kv_list);
2392 return;
2394 wants[CC_MAXCODE + 1 + v->code] = 1;
2395 gotvar = 1;
2396 continue;
2397 } else {
2398 break; /* shouldn't happen ! */
2401 wants[v->code] = 1;
2402 gotvar = 1;
2405 if (gotvar) {
2406 for (i = 1; i <= CC_MAXCODE; i++)
2407 if (wants[i])
2408 ctl_putclock(i, &clock_stat, 1);
2409 for (i = 0; clock_stat.kv_list &&
2410 !(clock_stat.kv_list[i].flags & EOV); i++)
2411 if (wants[i + CC_MAXCODE + 1])
2412 ctl_putdata(clock_stat.kv_list[i].text,
2413 strlen(clock_stat.kv_list[i].text),
2415 } else {
2416 register u_char *cc;
2417 register struct ctl_var *kv;
2419 for (cc = def_clock_var; *cc != 0; cc++)
2420 ctl_putclock((int)*cc, &clock_stat, 0);
2421 for (kv = clock_stat.kv_list; kv && !(kv->flags & EOV);
2422 kv++)
2423 if (kv->flags & DEF)
2424 ctl_putdata(kv->text, strlen(kv->text),
2428 free((char*)wants);
2429 free_varlist(clock_stat.kv_list);
2431 ctl_flushpkt(0);
2432 #endif
2437 * write_clock_status - we don't do this
2439 /*ARGSUSED*/
2440 static void
2441 write_clock_status(
2442 struct recvbuf *rbufp,
2443 int restrict_mask
2446 ctl_error(CERR_PERMISSION);
2450 * Trap support from here on down. We send async trap messages when the
2451 * upper levels report trouble. Traps can by set either by control
2452 * messages or by configuration.
2455 * set_trap - set a trap in response to a control message
2457 static void
2458 set_trap(
2459 struct recvbuf *rbufp,
2460 int restrict_mask
2463 int traptype;
2466 * See if this guy is allowed
2468 if (restrict_mask & RES_NOTRAP) {
2469 ctl_error(CERR_PERMISSION);
2470 return;
2474 * Determine his allowed trap type.
2476 traptype = TRAP_TYPE_PRIO;
2477 if (restrict_mask & RES_LPTRAP)
2478 traptype = TRAP_TYPE_NONPRIO;
2481 * Call ctlsettrap() to do the work. Return
2482 * an error if it can't assign the trap.
2484 if (!ctlsettrap(&rbufp->recv_srcadr, rbufp->dstadr, traptype,
2485 (int)res_version))
2486 ctl_error(CERR_NORESOURCE);
2487 ctl_flushpkt(0);
2492 * unset_trap - unset a trap in response to a control message
2494 static void
2495 unset_trap(
2496 struct recvbuf *rbufp,
2497 int restrict_mask
2500 int traptype;
2503 * We don't prevent anyone from removing his own trap unless the
2504 * trap is configured. Note we also must be aware of the
2505 * possibility that restriction flags were changed since this
2506 * guy last set his trap. Set the trap type based on this.
2508 traptype = TRAP_TYPE_PRIO;
2509 if (restrict_mask & RES_LPTRAP)
2510 traptype = TRAP_TYPE_NONPRIO;
2513 * Call ctlclrtrap() to clear this out.
2515 if (!ctlclrtrap(&rbufp->recv_srcadr, rbufp->dstadr, traptype))
2516 ctl_error(CERR_BADASSOC);
2517 ctl_flushpkt(0);
2522 * ctlsettrap - called to set a trap
2525 ctlsettrap(
2526 struct sockaddr_storage *raddr,
2527 struct interface *linter,
2528 int traptype,
2529 int version
2532 register struct ctl_trap *tp;
2533 register struct ctl_trap *tptouse;
2536 * See if we can find this trap. If so, we only need update
2537 * the flags and the time.
2539 if ((tp = ctlfindtrap(raddr, linter)) != NULL) {
2540 switch (traptype) {
2542 case TRAP_TYPE_CONFIG:
2543 tp->tr_flags = TRAP_INUSE|TRAP_CONFIGURED;
2544 break;
2546 case TRAP_TYPE_PRIO:
2547 if (tp->tr_flags & TRAP_CONFIGURED)
2548 return (1); /* don't change anything */
2549 tp->tr_flags = TRAP_INUSE;
2550 break;
2552 case TRAP_TYPE_NONPRIO:
2553 if (tp->tr_flags & TRAP_CONFIGURED)
2554 return (1); /* don't change anything */
2555 tp->tr_flags = TRAP_INUSE|TRAP_NONPRIO;
2556 break;
2558 tp->tr_settime = current_time;
2559 tp->tr_resets++;
2560 return (1);
2564 * First we heard of this guy. Try to find a trap structure
2565 * for him to use, clearing out lesser priority guys if we
2566 * have to. Clear out anyone who's expired while we're at it.
2568 tptouse = NULL;
2569 for (tp = ctl_trap; tp < &ctl_trap[CTL_MAXTRAPS]; tp++) {
2570 if ((tp->tr_flags & TRAP_INUSE) &&
2571 !(tp->tr_flags & TRAP_CONFIGURED) &&
2572 ((tp->tr_settime + CTL_TRAPTIME) > current_time)) {
2573 tp->tr_flags = 0;
2574 num_ctl_traps--;
2576 if (!(tp->tr_flags & TRAP_INUSE)) {
2577 tptouse = tp;
2578 } else if (!(tp->tr_flags & TRAP_CONFIGURED)) {
2579 switch (traptype) {
2581 case TRAP_TYPE_CONFIG:
2582 if (tptouse == NULL) {
2583 tptouse = tp;
2584 break;
2586 if (tptouse->tr_flags & TRAP_NONPRIO &&
2587 !(tp->tr_flags & TRAP_NONPRIO))
2588 break;
2590 if (!(tptouse->tr_flags & TRAP_NONPRIO)
2591 && tp->tr_flags & TRAP_NONPRIO) {
2592 tptouse = tp;
2593 break;
2595 if (tptouse->tr_origtime <
2596 tp->tr_origtime)
2597 tptouse = tp;
2598 break;
2600 case TRAP_TYPE_PRIO:
2601 if (tp->tr_flags & TRAP_NONPRIO) {
2602 if (tptouse == NULL ||
2603 (tptouse->tr_flags &
2604 TRAP_INUSE &&
2605 tptouse->tr_origtime <
2606 tp->tr_origtime))
2607 tptouse = tp;
2609 break;
2611 case TRAP_TYPE_NONPRIO:
2612 break;
2618 * If we don't have room for him return an error.
2620 if (tptouse == NULL)
2621 return (0);
2624 * Set up this structure for him.
2626 tptouse->tr_settime = tptouse->tr_origtime = current_time;
2627 tptouse->tr_count = tptouse->tr_resets = 0;
2628 tptouse->tr_sequence = 1;
2629 tptouse->tr_addr = *raddr;
2630 tptouse->tr_localaddr = linter;
2631 tptouse->tr_version = (u_char) version;
2632 tptouse->tr_flags = TRAP_INUSE;
2633 if (traptype == TRAP_TYPE_CONFIG)
2634 tptouse->tr_flags |= TRAP_CONFIGURED;
2635 else if (traptype == TRAP_TYPE_NONPRIO)
2636 tptouse->tr_flags |= TRAP_NONPRIO;
2637 num_ctl_traps++;
2638 return (1);
2643 * ctlclrtrap - called to clear a trap
2646 ctlclrtrap(
2647 struct sockaddr_storage *raddr,
2648 struct interface *linter,
2649 int traptype
2652 register struct ctl_trap *tp;
2654 if ((tp = ctlfindtrap(raddr, linter)) == NULL)
2655 return (0);
2657 if (tp->tr_flags & TRAP_CONFIGURED
2658 && traptype != TRAP_TYPE_CONFIG)
2659 return (0);
2661 tp->tr_flags = 0;
2662 num_ctl_traps--;
2663 return (1);
2668 * ctlfindtrap - find a trap given the remote and local addresses
2670 static struct ctl_trap *
2671 ctlfindtrap(
2672 struct sockaddr_storage *raddr,
2673 struct interface *linter
2676 register struct ctl_trap *tp;
2678 for (tp = ctl_trap; tp < &ctl_trap[CTL_MAXTRAPS]; tp++) {
2679 if ((tp->tr_flags & TRAP_INUSE)
2680 && (NSRCPORT(raddr) == NSRCPORT(&tp->tr_addr))
2681 && SOCKCMP(raddr, &tp->tr_addr)
2682 && (linter == tp->tr_localaddr) )
2683 return (tp);
2685 return (struct ctl_trap *)NULL;
2690 * report_event - report an event to the trappers
2692 void
2693 report_event(
2694 int err,
2695 struct peer *peer
2698 register int i;
2701 * Record error code in proper spots, but have mercy on the
2702 * log file.
2704 if (!(err & (PEER_EVENT | CRPT_EVENT))) {
2705 if (ctl_sys_num_events < CTL_SYS_MAXEVENTS)
2706 ctl_sys_num_events++;
2707 if (ctl_sys_last_event != (u_char)err) {
2708 NLOG(NLOG_SYSEVENT)
2709 msyslog(LOG_INFO, "system event '%s' (0x%02x) status '%s' (0x%02x)",
2710 eventstr(err), err,
2711 sysstatstr(ctlsysstatus()), ctlsysstatus());
2712 #ifdef DEBUG
2713 if (debug)
2714 printf("report_event: system event '%s' (0x%02x) status '%s' (0x%02x)\n",
2715 eventstr(err), err,
2716 sysstatstr(ctlsysstatus()),
2717 ctlsysstatus());
2718 #endif
2719 ctl_sys_last_event = (u_char)err;
2721 } else if (peer != 0) {
2722 char *src;
2724 #ifdef REFCLOCK
2725 if (ISREFCLOCKADR(&peer->srcadr))
2726 src = refnumtoa(&peer->srcadr);
2727 else
2728 #endif
2729 src = stoa(&peer->srcadr);
2731 peer->last_event = (u_char)(err & ~PEER_EVENT);
2732 if (peer->num_events < CTL_PEER_MAXEVENTS)
2733 peer->num_events++;
2734 NLOG(NLOG_PEEREVENT)
2735 msyslog(LOG_INFO, "peer %s event '%s' (0x%02x) status '%s' (0x%02x)",
2736 src, eventstr(err), err,
2737 peerstatstr(ctlpeerstatus(peer)),
2738 ctlpeerstatus(peer));
2739 #ifdef DEBUG
2740 if (debug)
2741 printf( "peer %s event '%s' (0x%02x) status '%s' (0x%02x)\n",
2742 src, eventstr(err), err,
2743 peerstatstr(ctlpeerstatus(peer)),
2744 ctlpeerstatus(peer));
2745 #endif
2746 } else {
2747 msyslog(LOG_ERR,
2748 "report_event: err '%s' (0x%02x), no peer",
2749 eventstr(err), err);
2750 #ifdef DEBUG
2751 printf(
2752 "report_event: peer event '%s' (0x%02x), no peer\n",
2753 eventstr(err), err);
2754 #endif
2755 return;
2759 * If no trappers, return.
2761 if (num_ctl_traps <= 0)
2762 return;
2765 * Set up the outgoing packet variables
2767 res_opcode = CTL_OP_ASYNCMSG;
2768 res_offset = 0;
2769 res_async = 1;
2770 res_authenticate = 0;
2771 datapt = rpkt.data;
2772 dataend = &(rpkt.data[CTL_MAX_DATA_LEN]);
2773 if (!(err & PEER_EVENT)) {
2774 rpkt.associd = 0;
2775 rpkt.status = htons(ctlsysstatus());
2778 * For now, put everything we know about system
2779 * variables. Don't send crypto strings.
2781 for (i = 1; i <= CS_MAXCODE; i++) {
2782 #ifdef OPENSSL
2783 if (i > CS_VARLIST)
2784 continue;
2785 #endif /* OPENSSL */
2786 ctl_putsys(i);
2788 #ifdef REFCLOCK
2790 * for clock exception events: add clock variables to
2791 * reflect info on exception
2793 if (err == EVNT_CLOCKEXCPT) {
2794 struct refclockstat clock_stat;
2795 struct ctl_var *kv;
2797 clock_stat.kv_list = (struct ctl_var *)0;
2798 refclock_control(&peer->srcadr,
2799 (struct refclockstat *)0, &clock_stat);
2800 ctl_puthex("refclockstatus",
2801 ctlclkstatus(&clock_stat));
2802 for (i = 1; i <= CC_MAXCODE; i++)
2803 ctl_putclock(i, &clock_stat, 0);
2804 for (kv = clock_stat.kv_list; kv &&
2805 !(kv->flags & EOV); kv++)
2806 if (kv->flags & DEF)
2807 ctl_putdata(kv->text,
2808 strlen(kv->text), 0);
2809 free_varlist(clock_stat.kv_list);
2811 #endif /* REFCLOCK */
2812 } else {
2813 rpkt.associd = htons(peer->associd);
2814 rpkt.status = htons(ctlpeerstatus(peer));
2817 * Dump it all. Later, maybe less.
2819 for (i = 1; i <= CP_MAXCODE; i++) {
2820 #ifdef OPENSSL
2821 if (i > CP_VARLIST)
2822 continue;
2823 #endif /* OPENSSL */
2824 ctl_putpeer(i, peer);
2826 #ifdef REFCLOCK
2828 * for clock exception events: add clock variables to
2829 * reflect info on exception
2831 if (err == EVNT_PEERCLOCK) {
2832 struct refclockstat clock_stat;
2833 struct ctl_var *kv;
2835 clock_stat.kv_list = (struct ctl_var *)0;
2836 refclock_control(&peer->srcadr,
2837 (struct refclockstat *)0, &clock_stat);
2839 ctl_puthex("refclockstatus",
2840 ctlclkstatus(&clock_stat));
2842 for (i = 1; i <= CC_MAXCODE; i++)
2843 ctl_putclock(i, &clock_stat, 0);
2844 for (kv = clock_stat.kv_list; kv &&
2845 !(kv->flags & EOV); kv++)
2846 if (kv->flags & DEF)
2847 ctl_putdata(kv->text,
2848 strlen(kv->text), 0);
2849 free_varlist(clock_stat.kv_list);
2851 #endif /* REFCLOCK */
2855 * We're done, return.
2857 ctl_flushpkt(0);
2862 * ctl_clr_stats - clear stat counters
2864 void
2865 ctl_clr_stats(void)
2867 ctltimereset = current_time;
2868 numctlreq = 0;
2869 numctlbadpkts = 0;
2870 numctlresponses = 0;
2871 numctlfrags = 0;
2872 numctlerrors = 0;
2873 numctlfrags = 0;
2874 numctltooshort = 0;
2875 numctlinputresp = 0;
2876 numctlinputfrag = 0;
2877 numctlinputerr = 0;
2878 numctlbadoffset = 0;
2879 numctlbadversion = 0;
2880 numctldatatooshort = 0;
2881 numctlbadop = 0;
2882 numasyncmsgs = 0;
2885 static u_long
2886 count_var(
2887 struct ctl_var *k
2890 register u_long c;
2892 if (!k)
2893 return (0);
2895 c = 0;
2896 while (!(k++->flags & EOV))
2897 c++;
2898 return (c);
2901 char *
2902 add_var(
2903 struct ctl_var **kv,
2904 u_long size,
2905 u_short def
2908 register u_long c;
2909 register struct ctl_var *k;
2911 c = count_var(*kv);
2913 k = *kv;
2914 *kv = (struct ctl_var *)emalloc((c+2)*sizeof(struct ctl_var));
2915 if (k) {
2916 memmove((char *)*kv, (char *)k,
2917 sizeof(struct ctl_var)*c);
2918 free((char *)k);
2920 (*kv)[c].code = (u_short) c;
2921 (*kv)[c].text = (char *)emalloc(size);
2922 (*kv)[c].flags = def;
2923 (*kv)[c+1].code = 0;
2924 (*kv)[c+1].text = (char *)0;
2925 (*kv)[c+1].flags = EOV;
2926 return (char *)(*kv)[c].text;
2929 void
2930 set_var(
2931 struct ctl_var **kv,
2932 const char *data,
2933 u_long size,
2934 u_short def
2937 register struct ctl_var *k;
2938 register const char *s;
2939 register const char *t;
2940 char *td;
2942 if (!data || !size)
2943 return;
2945 k = *kv;
2946 if (k != NULL) {
2947 while (!(k->flags & EOV)) {
2948 s = data;
2949 t = k->text;
2950 if (t) {
2951 while (*t != '=' && *s - *t == 0) {
2952 s++;
2953 t++;
2955 if (*s == *t && ((*t == '=') || !*t)) {
2956 free((void *)k->text);
2957 td = (char *)emalloc(size);
2958 memmove(td, data, size);
2959 k->text =td;
2960 k->flags = def;
2961 return;
2963 } else {
2964 td = (char *)emalloc(size);
2965 memmove(td, data, size);
2966 k->text = td;
2967 k->flags = def;
2968 return;
2970 k++;
2973 td = add_var(kv, size, def);
2974 memmove(td, data, size);
2977 void
2978 set_sys_var(
2979 const char *data,
2980 u_long size,
2981 u_short def
2984 set_var(&ext_sys_var, data, size, def);
2987 void
2988 free_varlist(
2989 struct ctl_var *kv
2992 struct ctl_var *k;
2993 if (kv) {
2994 for (k = kv; !(k->flags & EOV); k++)
2995 free((void *)k->text);
2996 free((void *)kv);