1 /* $NetBSD: ntp_control.c,v 1.8 2006/06/25 03:02:19 mrg Exp $ */
4 * ntp_control.c - respond to control messages and send async traps
12 #include "ntp_refclock.h"
13 #include "ntp_control.h"
14 #include "ntp_unixtime.h"
15 #include "ntp_stdlib.h"
21 #include <netinet/in.h>
22 #include <arpa/inet.h>
25 * Structure to hold request procedure information
30 #define NO_REQUEST (-1)
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.
45 * Request processing routines
47 static void ctl_error
P((int));
49 static u_short ctlclkstatus
P((struct refclockstat
*));
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 *,
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
*));
66 static void ctl_putfs
P((const char *, tstamp_t
));
69 static void ctl_putclock
P((int, struct refclockstat
*, int));
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
*,
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
},
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 */
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 */
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,
143 static u_char def_sys_var
[] = {
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 */
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 */
229 { 0, EOV
, "" } /* 38/46 */
234 * Peer variables we print by default
236 static u_char def_peer_var
[] = {
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
[] = {
307 CC_TYPE
, /* won't be output if device = known */
324 * System and processor definitions.
328 # define STR_SYSTEM "UNIX"
330 # ifndef STR_PROCESSOR
331 # define STR_PROCESSOR "unknown"
334 static char str_system
[] = STR_SYSTEM
;
335 static char str_processor
[] = STR_PROCESSOR
;
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
348 struct ctl_trap ctl_trap
[CTL_MAXTRAPS
];
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
479 * init_control - initialize request data
488 #endif /* HAVE_UNAME */
493 ctl_sys_last_event
= EVNT_UNSPEC
;
494 ctl_sys_num_events
= 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
512 printf("sending control error %d\n", errcode
);
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
&
520 rpkt
.status
= htons((u_short
) ((errcode
<<8) & 0xff00));
524 * send packet and bump counters
526 if (res_authenticate
&& sys_authenticate
) {
529 *(u_int32
*)((u_char
*)&rpkt
+ CTL_HEADER_LEN
) =
531 maclen
= authencrypt(res_keyid
, (u_int32
*)&rpkt
,
533 sendpkt(rmt_addr
, lcl_inter
, -2, (struct pkt
*)&rpkt
,
534 CTL_HEADER_LEN
+ maclen
);
536 sendpkt(rmt_addr
, lcl_inter
, -3, (struct pkt
*)&rpkt
,
544 * process_control - process an incoming control message
548 struct recvbuf
*rbufp
,
552 register struct ntp_control
*pkt
;
553 register int req_count
;
554 register int req_data
;
555 register struct ctl_proc
*cc
;
561 printf("in process_control()\n");
565 * Save the addresses for error responses
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) {
581 printf("invalid format in control packet\n");
583 if (rbufp
->recv_length
< CTL_HEADER_LEN
)
585 if (pkt
->r_m_e_op
& CTL_RESPONSE
)
587 if (pkt
->r_m_e_op
& CTL_MORE
)
589 if (pkt
->r_m_e_op
& CTL_ERROR
)
591 if (pkt
->offset
!= 0)
595 res_version
= PKT_VERSION(pkt
->li_vn_mode
);
596 if (res_version
> NTP_VERSION
|| res_version
< NTP_OLDVERSION
) {
599 printf("unknown version %d in control packet\n",
607 * Pull enough data from the packet to make intelligent
610 rpkt
.li_vn_mode
= PKT_LI_VN_MODE(sys_leap
, res_version
,
612 res_opcode
= pkt
->r_m_e_op
;
613 rpkt
.sequence
= pkt
->sequence
;
614 rpkt
.associd
= pkt
->associd
;
617 res_associd
= htons(pkt
->associd
);
619 res_authenticate
= 0;
622 req_count
= (int)htons(pkt
->count
);
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
++;
639 properlen
= req_count
+ CTL_HEADER_LEN
;
641 if (debug
> 2 && (rbufp
->recv_length
& 0x3) != 0)
642 printf("Packet length %d unrounded\n",
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
&&
652 res_authenticate
= 1;
653 res_keyid
= ntohl(*(u_int32
*)((u_char
*)pkt
+
659 "recv_len %d, properlen %d, wants auth with keyid %08x, MAC length=%d\n",
660 rbufp
->recv_length
, properlen
, res_keyid
, maclen
);
662 if (!authistrusted(res_keyid
)) {
665 printf("invalid keyid %08x\n",
668 } else if (authdecrypt(res_keyid
, (u_int32
*)pkt
,
669 rbufp
->recv_length
- maclen
, maclen
)) {
672 printf("authenticated okay\n");
678 printf("authentication failed\n");
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
) {
697 printf("opcode %d, found command handler\n",
700 if (cc
->flags
== AUTH
&& (!res_authokay
||
701 res_keyid
!= ctl_auth_keyid
)) {
702 ctl_error(CERR_PERMISSION
);
705 (cc
->handler
)(rbufp
, restrict_mask
);
711 * Can't find this one, return an error.
714 ctl_error(CERR_BADOP
);
720 * ctlpeerstatus - return a status word for this peer
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
,
744 * ctlclkstatus - return a status word for this clock
749 struct refclockstat
*this_clock
752 return ((u_short
)(((this_clock
->currentstatus
) << 8) |
753 (this_clock
->lastevent
)));
759 * ctlsysstatus - return the system status word
764 register u_char this_clock
;
766 this_clock
= CTL_SST_TS_UNSPEC
;
769 if (sys_peer
->sstclktype
!= CTL_SST_TS_UNSPEC
) {
770 this_clock
= sys_peer
->sstclktype
;
772 this_clock
|= CTL_SST_TS_PPS
;
774 if (sys_peer
->refclktype
< sizeof(clocktypes
))
776 clocktypes
[sys_peer
->refclktype
];
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.
799 if (!more
&& datanotbinflag
) {
801 * Big hack, output a trailing \r\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) {
818 * Fill in the packet with the current info
820 rpkt
.r_m_e_op
= (u_char
)(CTL_RESPONSE
|more
|(res_opcode
&
822 rpkt
.count
= htons((u_short
) dlen
);
823 rpkt
.offset
= htons( (u_short
) res_offset
);
827 for (i
= 0; i
< CTL_MAXTRAPS
; i
++) {
828 if (ctl_trap
[i
].tr_flags
& TRAP_INUSE
) {
830 PKT_LI_VN_MODE(sys_leap
,
831 ctl_trap
[i
].tr_version
,
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
);
839 ctl_trap
[i
].tr_sequence
++;
844 if (res_authenticate
&& sys_authenticate
) {
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.
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
);
864 sendpkt(rmt_addr
, lcl_inter
, -6,
865 (struct pkt
*)&rpkt
, sendlen
);
874 * Set us up for another go around.
877 datapt
= (u_char
*)rpkt
.data
;
882 * ctl_putdata - write data into the packet, fragmenting and starting
883 * another if this one is full.
889 int bin
/* set to 1 when data is binary */
898 if (datapt
!= rpkt
.data
) {
901 if ((dlen
+ datalinelen
+ 1) >= MAXDATALINELEN
)
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
);
929 * ctl_putstr - write a tagged string into the response packet
939 register const char *cq
;
949 if (len
> (int) (sizeof(buffer
) - (cp
- buffer
) - 1))
950 len
= sizeof(buffer
) - (cp
- buffer
) - 1;
951 memmove(cp
, data
, (unsigned)len
);
955 ctl_putdata(buffer
, (unsigned)( cp
- buffer
), 0);
960 * ctl_putdbl - write a tagged, signed double into the response packet
969 register const char *cq
;
977 (void)sprintf(cp
, "%.3f", ts
);
980 ctl_putdata(buffer
, (unsigned)( cp
- buffer
), 0);
984 * ctl_putuint - write a tagged unsigned integer into the response
993 register const char *cq
;
1002 (void) sprintf(cp
, "%lu", uval
);
1005 ctl_putdata(buffer
, (unsigned)( cp
- buffer
), 0);
1010 * ctl_putfs - write a decoded filestamp into the response
1019 register const char *cq
;
1021 struct tm
*tm
= NULL
;
1030 fstamp
= uval
- JAN_1970
;
1031 tm
= gmtime(&fstamp
);
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
);
1039 ctl_putdata(buffer
, (unsigned)( cp
- buffer
), 0);
1041 #endif /* OPENSSL */
1045 * ctl_puthex - write a tagged unsigned integer, in hex, into the response
1054 register const char *cq
;
1063 (void) sprintf(cp
, "0x%lx", uval
);
1066 ctl_putdata(buffer
,(unsigned)( cp
- buffer
), 0);
1071 * ctl_putint - write a tagged signed integer into the response
1080 register const char *cq
;
1089 (void) sprintf(cp
, "%ld", ival
);
1092 ctl_putdata(buffer
, (unsigned)( cp
- buffer
), 0);
1097 * ctl_putts - write a tagged timestamp, in hex, into the response
1106 register const char *cq
;
1115 (void) sprintf(cp
, "0x%08lx.%08lx",
1116 ts
->l_ui
& ULONG_CONST(0xffffffff),
1117 ts
->l_uf
& ULONG_CONST(0xffffffff));
1120 ctl_putdata(buffer
, (unsigned)( cp
- buffer
), 0);
1125 * ctl_putadr - write an IP address into the response
1131 struct sockaddr_storage
* addr
1135 register const char *cq
;
1145 cq
= numtoa(addr32
);
1150 ctl_putdata(buffer
, (unsigned)( cp
- buffer
), 0);
1154 * ctl_putid - write a tagged clock ID into the response
1163 register const char *cq
;
1173 while (*cq
!= '\0' && (cq
- id
) < 4)
1175 ctl_putdata(buffer
, (unsigned)( cp
- buffer
), 0);
1180 * ctl_putarray - write a tagged eight element double array into the response
1190 register const char *cq
;
1202 (void)sprintf(cp
, " %.2f", arr
[i
] * 1e3
);
1205 } while(i
!= start
);
1206 ctl_putdata(buffer
, (unsigned)(cp
- buffer
), 0);
1211 * ctl_putsys - output a system variable
1221 struct cert_info
*cp
;
1223 #endif /* OPENSSL */
1228 ctl_putuint(sys_var
[CS_LEAP
].text
, sys_leap
);
1232 ctl_putuint(sys_var
[CS_STRATUM
].text
, sys_stratum
);
1236 ctl_putint(sys_var
[CS_PRECISION
].text
, sys_precision
);
1240 ctl_putdbl(sys_var
[CS_ROOTDELAY
].text
, sys_rootdelay
*
1244 case CS_ROOTDISPERSION
:
1245 ctl_putdbl(sys_var
[CS_ROOTDISPERSION
].text
,
1246 sys_rootdispersion
* 1e3
);
1250 if (sys_stratum
> 1 && sys_stratum
< STRATUM_UNSPEC
)
1251 ctl_putadr(sys_var
[CS_REFID
].text
, sys_refid
, NULL
);
1253 ctl_putid(sys_var
[CS_REFID
].text
,
1254 (char *)&sys_refid
);
1258 ctl_putts(sys_var
[CS_REFTIME
].text
, &sys_reftime
);
1262 ctl_putuint(sys_var
[CS_POLL
].text
, sys_poll
);
1266 if (sys_peer
== NULL
)
1267 ctl_putuint(sys_var
[CS_PEERID
].text
, 0);
1269 ctl_putuint(sys_var
[CS_PEERID
].text
,
1274 ctl_putuint(sys_var
[CS_STATE
].text
, (unsigned)state
);
1278 ctl_putdbl(sys_var
[CS_OFFSET
].text
, last_offset
* 1e3
);
1282 ctl_putdbl(sys_var
[CS_DRIFT
].text
, drift_comp
* 1e6
);
1286 ctl_putdbl(sys_var
[CS_JITTER
].text
, sys_jitter
* 1e3
);
1290 ctl_putdbl(sys_var
[CS_ERROR
].text
, clock_jitter
* 1e3
);
1295 ctl_putts(sys_var
[CS_CLOCK
].text
, &tmp
);
1300 ctl_putstr(sys_var
[CS_PROCESSOR
].text
, str_processor
,
1301 sizeof(str_processor
) - 1);
1303 ctl_putstr(sys_var
[CS_PROCESSOR
].text
,
1304 utsnamebuf
.machine
, strlen(utsnamebuf
.machine
));
1305 #endif /* HAVE_UNAME */
1310 ctl_putstr(sys_var
[CS_SYSTEM
].text
, str_system
,
1311 sizeof(str_system
) - 1);
1313 sprintf(str
, "%s/%s", utsnamebuf
.sysname
, utsnamebuf
.release
);
1314 ctl_putstr(sys_var
[CS_SYSTEM
].text
, str
, strlen(str
));
1315 #endif /* HAVE_UNAME */
1319 ctl_putstr(sys_var
[CS_VERSION
].text
, Version
,
1324 ctl_putdbl(sys_var
[CS_STABIL
].text
, clock_stability
*
1330 char buf
[CTL_MAX_DATA_LEN
];
1331 register char *s
, *t
, *be
;
1332 register const char *ss
;
1334 register struct ctl_var
*k
;
1337 be
= buf
+ sizeof(buf
) -
1338 strlen(sys_var
[CS_VARLIST
].text
) - 4;
1340 break; /* really long var name */
1342 strcpy(s
, sys_var
[CS_VARLIST
].text
);
1346 for (k
= sys_var
; !(k
->flags
&EOV
); k
++) {
1347 if (k
->flags
& PADDING
)
1349 i
= strlen(k
->text
);
1359 for (k
= ext_sys_var
; k
&& !(k
->flags
&EOV
);
1361 if (k
->flags
& PADDING
)
1368 while (*ss
&& *ss
!= '=')
1371 if (s
+ i
+ 1 >= be
)
1386 ctl_putdata(buf
, (unsigned)( s
- buf
),
1394 ctl_puthex(sys_var
[CS_FLAGS
].text
, crypto_flags
);
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
,
1410 if (sys_hostname
!= NULL
)
1411 ctl_putstr(sys_var
[CS_HOST
].text
, sys_hostname
,
1412 strlen(sys_hostname
));
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
,
1421 ctl_putfs(sys_var
[CS_REVOKE
].text
, cp
->last
);
1426 if (hostval
.fstamp
!= 0)
1427 ctl_putfs(sys_var
[CS_PUBLIC
].text
,
1428 ntohl(hostval
.tstamp
));
1432 if (hostval
.tstamp
!= 0)
1433 ctl_putfs(sys_var
[CS_REVTIME
].text
,
1434 ntohl(hostval
.tstamp
));
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
));
1450 if (tai_leap
.fstamp
!= 0)
1451 ctl_putfs(sys_var
[CS_LEAPTAB
].text
,
1452 ntohl(tai_leap
.fstamp
));
1456 ctl_putuint(sys_var
[CS_TAI
].text
, sys_tai
);
1458 #endif /* OPENSSL */
1464 * ctl_putpeer - output a peer variable
1476 #endif /* OPENSSL */
1481 ctl_putuint(peer_var
[CP_CONFIG
].text
,
1482 (unsigned)((peer
->flags
& FLAG_CONFIG
) != 0));
1486 ctl_putuint(peer_var
[CP_AUTHENABLE
].text
,
1487 (unsigned)((peer
->flags
& FLAG_AUTHENABLE
) != 0));
1491 ctl_putuint(peer_var
[CP_AUTHENTIC
].text
,
1492 (unsigned)((peer
->flags
& FLAG_AUTHENTIC
) != 0));
1496 ctl_putadr(peer_var
[CP_SRCADR
].text
, 0,
1501 ctl_putuint(peer_var
[CP_SRCPORT
].text
,
1502 ntohs(((struct sockaddr_in
*)&peer
->srcadr
)->sin_port
));
1507 ctl_putadr(peer_var
[CP_DSTADR
].text
, 0,
1508 &(peer
->dstadr
->sin
));
1510 ctl_putadr(peer_var
[CP_DSTADR
].text
, 0,
1516 ctl_putuint(peer_var
[CP_DSTPORT
].text
,
1517 (u_long
)(peer
->dstadr
?
1518 ntohs(((struct sockaddr_in
*)&peer
->dstadr
->sin
)->sin_port
) : 0));
1522 ctl_putuint(peer_var
[CP_LEAP
].text
, peer
->leap
);
1526 ctl_putuint(peer_var
[CP_HMODE
].text
, peer
->hmode
);
1530 ctl_putuint(peer_var
[CP_STRATUM
].text
, peer
->stratum
);
1534 ctl_putuint(peer_var
[CP_PPOLL
].text
, peer
->ppoll
);
1538 ctl_putuint(peer_var
[CP_HPOLL
].text
, peer
->hpoll
);
1542 ctl_putint(peer_var
[CP_PRECISION
].text
,
1547 ctl_putdbl(peer_var
[CP_ROOTDELAY
].text
,
1548 peer
->rootdelay
* 1e3
);
1551 case CP_ROOTDISPERSION
:
1552 ctl_putdbl(peer_var
[CP_ROOTDISPERSION
].text
,
1553 peer
->rootdispersion
* 1e3
);
1557 if (peer
->flags
& FLAG_REFCLOCK
) {
1558 ctl_putid(peer_var
[CP_REFID
].text
,
1559 (char *)&peer
->refid
);
1561 if (peer
->stratum
> 1 && peer
->stratum
<
1563 ctl_putadr(peer_var
[CP_REFID
].text
,
1566 ctl_putid(peer_var
[CP_REFID
].text
,
1567 (char *)&peer
->refid
);
1572 ctl_putts(peer_var
[CP_REFTIME
].text
, &peer
->reftime
);
1576 ctl_putts(peer_var
[CP_ORG
].text
, &peer
->org
);
1580 ctl_putts(peer_var
[CP_REC
].text
, &peer
->rec
);
1584 ctl_putts(peer_var
[CP_XMT
].text
, &peer
->xmt
);
1588 ctl_puthex(peer_var
[CP_REACH
].text
, peer
->reach
);
1593 ctl_puthex(peer_var
[CP_FLASH
].text
, temp
);
1597 ctl_putint(peer_var
[CP_TTL
].text
, sys_ttl
[peer
->ttl
]);
1601 ctl_putuint(peer_var
[CP_UNREACH
].text
, peer
->unreach
);
1605 ctl_putuint(peer_var
[CP_TIMER
].text
,
1606 peer
->nextdate
- current_time
);
1610 ctl_putdbl(peer_var
[CP_DELAY
].text
, peer
->delay
* 1e3
);
1614 ctl_putdbl(peer_var
[CP_OFFSET
].text
, peer
->offset
*
1619 ctl_putdbl(peer_var
[CP_JITTER
].text
, peer
->jitter
* 1e3
);
1623 ctl_putdbl(peer_var
[CP_DISPERSION
].text
, peer
->disp
*
1628 ctl_putuint(peer_var
[CP_KEYID
].text
, peer
->keyid
);
1632 ctl_putarray(peer_var
[CP_FILTDELAY
].text
,
1633 peer
->filter_delay
, (int)peer
->filter_nextpt
);
1637 ctl_putarray(peer_var
[CP_FILTOFFSET
].text
,
1638 peer
->filter_offset
, (int)peer
->filter_nextpt
);
1642 ctl_putarray(peer_var
[CP_FILTERROR
].text
,
1643 peer
->filter_disp
, (int)peer
->filter_nextpt
);
1647 ctl_putuint(peer_var
[CP_PMODE
].text
, peer
->pmode
);
1651 ctl_putuint(peer_var
[CP_RECEIVED
].text
, peer
->received
);
1655 ctl_putuint(peer_var
[CP_SENT
].text
, peer
->sent
);
1660 char buf
[CTL_MAX_DATA_LEN
];
1661 register char *s
, *t
, *be
;
1663 register struct ctl_var
*k
;
1666 be
= buf
+ sizeof(buf
) -
1667 strlen(peer_var
[CP_VARLIST
].text
) - 4;
1669 break; /* really long var name */
1671 strcpy(s
, peer_var
[CP_VARLIST
].text
);
1675 for (k
= peer_var
; !(k
->flags
&EOV
); k
++) {
1676 if (k
->flags
& PADDING
)
1679 i
= strlen(k
->text
);
1680 if (s
+ i
+ 1 >= be
)
1693 ctl_putdata(buf
, (unsigned)(s
- buf
), 0);
1699 ctl_puthex(peer_var
[CP_FLAGS
].text
, peer
->crypto
);
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
,
1714 if (peer
->subject
!= NULL
)
1715 ctl_putstr(peer_var
[CP_HOST
].text
,
1716 peer
->subject
, strlen(peer
->subject
));
1719 case CP_VALID
: /* not used */
1723 if (peer
->issuer
!= NULL
)
1724 ctl_putstr(peer_var
[CP_IDENT
].text
,
1725 peer
->issuer
, strlen(peer
->issuer
));
1729 if ((ap
= (struct autokey
*)peer
->recval
.ptr
) == NULL
)
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
));
1736 #endif /* OPENSSL */
1743 * ctl_putclock - output clock variables
1748 struct refclockstat
*clock_stat
,
1755 if (mustput
|| clock_stat
->clockdesc
== NULL
1756 || *(clock_stat
->clockdesc
) == '\0') {
1757 ctl_putuint(clock_var
[CC_TYPE
].text
, clock_stat
->type
);
1761 ctl_putstr(clock_var
[CC_TIMECODE
].text
,
1762 clock_stat
->p_lastcode
,
1763 (unsigned)clock_stat
->lencode
);
1767 ctl_putuint(clock_var
[CC_POLL
].text
, clock_stat
->polls
);
1771 ctl_putuint(clock_var
[CC_NOREPLY
].text
,
1772 clock_stat
->noresponse
);
1776 ctl_putuint(clock_var
[CC_BADFORMAT
].text
,
1777 clock_stat
->badformat
);
1781 ctl_putuint(clock_var
[CC_BADDATA
].text
,
1782 clock_stat
->baddata
);
1786 if (mustput
|| (clock_stat
->haveflags
& CLK_HAVETIME1
))
1787 ctl_putdbl(clock_var
[CC_FUDGETIME1
].text
,
1788 clock_stat
->fudgetime1
* 1e3
);
1792 if (mustput
|| (clock_stat
->haveflags
& CLK_HAVETIME2
)) ctl_putdbl(clock_var
[CC_FUDGETIME2
].text
,
1793 clock_stat
->fudgetime2
* 1e3
);
1797 if (mustput
|| (clock_stat
->haveflags
& CLK_HAVEVAL1
))
1798 ctl_putint(clock_var
[CC_FUDGEVAL1
].text
,
1799 clock_stat
->fudgeval1
);
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
);
1808 ctl_putid(clock_var
[CC_FUDGEVAL2
].text
,
1809 (char *)&clock_stat
->fudgeval2
);
1814 if (mustput
|| (clock_stat
->haveflags
& (CLK_HAVEFLAG1
|
1815 CLK_HAVEFLAG2
| CLK_HAVEFLAG3
| CLK_HAVEFLAG4
)))
1816 ctl_putuint(clock_var
[CC_FLAGS
].text
,
1821 if (clock_stat
->clockdesc
== NULL
||
1822 *(clock_stat
->clockdesc
) == '\0') {
1824 ctl_putstr(clock_var
[CC_DEVICE
].text
,
1827 ctl_putstr(clock_var
[CC_DEVICE
].text
,
1828 clock_stat
->clockdesc
,
1829 strlen(clock_stat
->clockdesc
));
1835 char buf
[CTL_MAX_DATA_LEN
];
1836 register char *s
, *t
, *be
;
1837 register const char *ss
;
1839 register struct ctl_var
*k
;
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
);
1852 for (k
= clock_var
; !(k
->flags
&EOV
); k
++) {
1853 if (k
->flags
& PADDING
)
1856 i
= strlen(k
->text
);
1857 if (s
+ i
+ 1 >= be
)
1866 for (k
= clock_stat
->kv_list
; k
&& !(k
->flags
&
1868 if (k
->flags
& PADDING
)
1875 while (*ss
&& *ss
!= '=')
1883 strncpy(s
, k
->text
, (unsigned)i
);
1892 ctl_putdata(buf
, (unsigned)( s
- buf
), 0);
1902 * ctl_getitem - get the next data item from the incoming packet
1904 static struct ctl_var
*
1906 struct ctl_var
*var_list
,
1910 register struct ctl_var
*v
;
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
)))
1922 if (reqpt
>= reqend
)
1925 if (var_list
== (struct ctl_var
*)0)
1929 * Look for a first character match on the tag. If we find
1930 * one, see if it is a full match.
1934 while (!(v
->flags
& EOV
)) {
1935 if (!(v
->flags
& PADDING
) && *cp
== *(v
->text
)) {
1937 while (*tp
!= '\0' && *tp
!= '=' && cp
<
1938 reqend
&& *cp
== *tp
) {
1942 if ((*tp
== '\0') || (*tp
== '=')) {
1943 while (cp
< reqend
&& isspace((unsigned char)*cp
))
1945 if (cp
== reqend
|| *cp
== ',') {
1956 while (cp
< reqend
&& isspace((unsigned char)*cp
))
1958 while (cp
< reqend
&& *cp
!= ',') {
1960 if (tp
>= buf
+ sizeof(buf
)) {
1961 ctl_error(CERR_BADFMT
);
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
)
1977 if (!isspace((unsigned int)(*tp
)))
1995 * control_unspec - response to an unspecified op-code
2000 struct recvbuf
*rbufp
,
2007 * What is an appropriate response to an unspecified op-code?
2008 * I return no errors and no data, unless a specified assocation
2011 if (res_associd
!= 0) {
2012 if ((peer
= findpeerbyassoc(res_associd
)) == 0) {
2013 ctl_error(CERR_BADASSOC
);
2016 rpkt
.status
= htons(ctlpeerstatus(peer
));
2018 rpkt
.status
= htons(ctlsysstatus());
2025 * read_status - return either a list of associd's, or a particular
2031 struct recvbuf
*rbufp
,
2036 register struct peer
*peer
;
2037 u_short ass_stat
[CTL_MAX_DATA_LEN
/ sizeof(u_short
)];
2041 printf("read_status: ID %d\n", res_associd
);
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) {
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
);
2058 htons(ctlpeerstatus(peer
));
2060 CTL_MAX_DATA_LEN
/sizeof(u_short
)) {
2061 ctl_putdata((char *)ass_stat
,
2062 n
* sizeof(u_short
), 1);
2069 ctl_putdata((char *)ass_stat
, n
*
2070 sizeof(u_short
), 1);
2073 peer
= findpeerbyassoc(res_associd
);
2075 ctl_error(CERR_BADASSOC
);
2077 register u_char
*cp
;
2079 rpkt
.status
= htons(ctlpeerstatus(peer
));
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
);
2095 * read_variables - return the variables the caller asks for
2100 struct recvbuf
*rbufp
,
2104 register struct ctl_var
*v
;
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());
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
);
2122 while ((v
= ctl_getitem(sys_var
, &valuep
)) != 0) {
2123 if (v
->flags
& EOV
) {
2124 if ((v
= ctl_getitem(ext_sys_var
,
2126 if (v
->flags
& EOV
) {
2127 ctl_error(CERR_UNKNOWNVAR
);
2128 free((char *)wants
);
2131 wants
[CS_MAXCODE
+ 1 +
2136 break; /* shouldn't happen ! */
2143 for (i
= 1; i
<= CS_MAXCODE
; 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
),
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
);
2160 if (kv
->flags
& DEF
)
2161 ctl_putdata(kv
->text
,
2162 strlen(kv
->text
), 0);
2164 free((char *)wants
);
2166 register struct peer
*peer
;
2169 * Wants info for a particular peer. See if we know
2172 peer
= findpeerbyassoc(res_associd
);
2174 ctl_error(CERR_BADASSOC
);
2177 rpkt
.status
= htons(ctlpeerstatus(peer
));
2179 peer
->num_events
= 0;
2180 wants
= (u_char
*)emalloc(gotvar
);
2181 memset((char*)wants
, 0, gotvar
);
2183 while ((v
= ctl_getitem(peer_var
, &valuep
)) != 0) {
2184 if (v
->flags
& EOV
) {
2185 ctl_error(CERR_UNKNOWNVAR
);
2186 free((char *)wants
);
2193 for (i
= 1; i
<= CP_MAXCODE
; i
++)
2195 ctl_putpeer(i
, peer
);
2197 register u_char
*cp
;
2199 for (cp
= def_peer_var
; *cp
!= 0; cp
++)
2200 ctl_putpeer((int)*cp
, peer
);
2202 free((char *)wants
);
2209 * write_variables - write into variables. We only allow leap bit
2215 struct recvbuf
*rbufp
,
2219 register struct ctl_var
*v
;
2220 register int ext_var
;
2225 * If he's trying to write into a peer tell him no way
2227 if (res_associd
!= 0) {
2228 ctl_error(CERR_PERMISSION
);
2235 rpkt
.status
= htons(ctlsysstatus());
2238 * Look through the variables. Dump out at the first sign of
2241 while ((v
= ctl_getitem(sys_var
, &valuep
)) != 0) {
2243 if (v
->flags
& EOV
) {
2244 if ((v
= ctl_getitem(ext_sys_var
, &valuep
)) !=
2246 if (v
->flags
& EOV
) {
2247 ctl_error(CERR_UNKNOWNVAR
);
2255 if (!(v
->flags
& CAN_WRITE
)) {
2256 ctl_error(CERR_PERMISSION
);
2259 if (!ext_var
&& (*valuep
== '\0' || !atoint(valuep
,
2261 ctl_error(CERR_BADFMT
);
2264 if (!ext_var
&& (val
& ~LEAP_NOTINSYNC
) != 0) {
2265 ctl_error(CERR_BADVALUE
);
2270 char *s
= (char *)emalloc(strlen(v
->text
) +
2271 strlen(valuep
) + 2);
2276 while (*t
&& *t
!= '=')
2281 set_sys_var(s
, strlen(s
)+1, v
->flags
);
2285 * This one seems sane. Save it.
2291 ctl_error(CERR_UNSPEC
); /* really */
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);
2313 * read_clock_status - return clock radio status
2318 struct recvbuf
*rbufp
,
2324 * If no refclock support, no data to return
2326 ctl_error(CERR_BADASSOC
);
2328 register struct ctl_var
*v
;
2330 register struct peer
*peer
;
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
2343 if (sys_peer
!= 0 && (sys_peer
->flags
& FLAG_REFCLOCK
))
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
)
2356 ctl_error(CERR_BADASSOC
);
2361 peer
= findpeerbyassoc(res_associd
);
2362 if (peer
== 0 || !(peer
->flags
& FLAG_REFCLOCK
)) {
2363 ctl_error(CERR_BADASSOC
);
2369 * If we got here we have a peer which is a clock. Get his
2372 clock_stat
.kv_list
= (struct ctl_var
*)0;
2373 refclock_control(&peer
->srcadr
, (struct refclockstat
*)0,
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
);
2384 while ((v
= ctl_getitem(clock_var
, &valuep
)) != 0) {
2385 if (v
->flags
& EOV
) {
2386 if ((v
= ctl_getitem(clock_stat
.kv_list
,
2388 if (v
->flags
& EOV
) {
2389 ctl_error(CERR_UNKNOWNVAR
);
2391 free_varlist(clock_stat
.kv_list
);
2394 wants
[CC_MAXCODE
+ 1 + v
->code
] = 1;
2398 break; /* shouldn't happen ! */
2406 for (i
= 1; i
<= CC_MAXCODE
; 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
),
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
);
2423 if (kv
->flags
& DEF
)
2424 ctl_putdata(kv
->text
, strlen(kv
->text
),
2429 free_varlist(clock_stat
.kv_list
);
2437 * write_clock_status - we don't do this
2442 struct recvbuf
*rbufp
,
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
2459 struct recvbuf
*rbufp
,
2466 * See if this guy is allowed
2468 if (restrict_mask
& RES_NOTRAP
) {
2469 ctl_error(CERR_PERMISSION
);
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
,
2486 ctl_error(CERR_NORESOURCE
);
2492 * unset_trap - unset a trap in response to a control message
2496 struct recvbuf
*rbufp
,
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
);
2522 * ctlsettrap - called to set a trap
2526 struct sockaddr_storage
*raddr
,
2527 struct interface
*linter
,
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
) {
2542 case TRAP_TYPE_CONFIG
:
2543 tp
->tr_flags
= TRAP_INUSE
|TRAP_CONFIGURED
;
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
;
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
;
2558 tp
->tr_settime
= current_time
;
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.
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
)) {
2576 if (!(tp
->tr_flags
& TRAP_INUSE
)) {
2578 } else if (!(tp
->tr_flags
& TRAP_CONFIGURED
)) {
2581 case TRAP_TYPE_CONFIG
:
2582 if (tptouse
== NULL
) {
2586 if (tptouse
->tr_flags
& TRAP_NONPRIO
&&
2587 !(tp
->tr_flags
& TRAP_NONPRIO
))
2590 if (!(tptouse
->tr_flags
& TRAP_NONPRIO
)
2591 && tp
->tr_flags
& TRAP_NONPRIO
) {
2595 if (tptouse
->tr_origtime
<
2600 case TRAP_TYPE_PRIO
:
2601 if (tp
->tr_flags
& TRAP_NONPRIO
) {
2602 if (tptouse
== NULL
||
2603 (tptouse
->tr_flags
&
2605 tptouse
->tr_origtime
<
2611 case TRAP_TYPE_NONPRIO
:
2618 * If we don't have room for him return an error.
2620 if (tptouse
== NULL
)
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
;
2643 * ctlclrtrap - called to clear a trap
2647 struct sockaddr_storage
*raddr
,
2648 struct interface
*linter
,
2652 register struct ctl_trap
*tp
;
2654 if ((tp
= ctlfindtrap(raddr
, linter
)) == NULL
)
2657 if (tp
->tr_flags
& TRAP_CONFIGURED
2658 && traptype
!= TRAP_TYPE_CONFIG
)
2668 * ctlfindtrap - find a trap given the remote and local addresses
2670 static struct ctl_trap
*
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
) )
2685 return (struct ctl_trap
*)NULL
;
2690 * report_event - report an event to the trappers
2701 * Record error code in proper spots, but have mercy on the
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
) {
2709 msyslog(LOG_INFO
, "system event '%s' (0x%02x) status '%s' (0x%02x)",
2711 sysstatstr(ctlsysstatus()), ctlsysstatus());
2714 printf("report_event: system event '%s' (0x%02x) status '%s' (0x%02x)\n",
2716 sysstatstr(ctlsysstatus()),
2719 ctl_sys_last_event
= (u_char
)err
;
2721 } else if (peer
!= 0) {
2725 if (ISREFCLOCKADR(&peer
->srcadr
))
2726 src
= refnumtoa(&peer
->srcadr
);
2729 src
= stoa(&peer
->srcadr
);
2731 peer
->last_event
= (u_char
)(err
& ~PEER_EVENT
);
2732 if (peer
->num_events
< CTL_PEER_MAXEVENTS
)
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
));
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
));
2748 "report_event: err '%s' (0x%02x), no peer",
2749 eventstr(err
), err
);
2752 "report_event: peer event '%s' (0x%02x), no peer\n",
2753 eventstr(err
), err
);
2759 * If no trappers, return.
2761 if (num_ctl_traps
<= 0)
2765 * Set up the outgoing packet variables
2767 res_opcode
= CTL_OP_ASYNCMSG
;
2770 res_authenticate
= 0;
2772 dataend
= &(rpkt
.data
[CTL_MAX_DATA_LEN
]);
2773 if (!(err
& PEER_EVENT
)) {
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
++) {
2785 #endif /* OPENSSL */
2790 * for clock exception events: add clock variables to
2791 * reflect info on exception
2793 if (err
== EVNT_CLOCKEXCPT
) {
2794 struct refclockstat clock_stat
;
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 */
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
++) {
2823 #endif /* OPENSSL */
2824 ctl_putpeer(i
, peer
);
2828 * for clock exception events: add clock variables to
2829 * reflect info on exception
2831 if (err
== EVNT_PEERCLOCK
) {
2832 struct refclockstat clock_stat
;
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.
2862 * ctl_clr_stats - clear stat counters
2867 ctltimereset
= current_time
;
2870 numctlresponses
= 0;
2875 numctlinputresp
= 0;
2876 numctlinputfrag
= 0;
2878 numctlbadoffset
= 0;
2879 numctlbadversion
= 0;
2880 numctldatatooshort
= 0;
2896 while (!(k
++->flags
& EOV
))
2903 struct ctl_var
**kv
,
2909 register struct ctl_var
*k
;
2914 *kv
= (struct ctl_var
*)emalloc((c
+2)*sizeof(struct ctl_var
));
2916 memmove((char *)*kv
, (char *)k
,
2917 sizeof(struct ctl_var
)*c
);
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
;
2931 struct ctl_var
**kv
,
2937 register struct ctl_var
*k
;
2938 register const char *s
;
2939 register const char *t
;
2947 while (!(k
->flags
& EOV
)) {
2951 while (*t
!= '=' && *s
- *t
== 0) {
2955 if (*s
== *t
&& ((*t
== '=') || !*t
)) {
2956 free((void *)k
->text
);
2957 td
= (char *)emalloc(size
);
2958 memmove(td
, data
, size
);
2964 td
= (char *)emalloc(size
);
2965 memmove(td
, data
, size
);
2973 td
= add_var(kv
, size
, def
);
2974 memmove(td
, data
, size
);
2984 set_var(&ext_sys_var
, data
, size
, def
);
2994 for (k
= kv
; !(k
->flags
& EOV
); k
++)
2995 free((void *)k
->text
);