summaryrefslogtreecommitdiffstats
path: root/contrib/ntp/ntpd/ntp_control.c
diff options
context:
space:
mode:
authorroberto <roberto@FreeBSD.org>2008-08-17 17:37:33 +0000
committerroberto <roberto@FreeBSD.org>2008-08-17 17:37:33 +0000
commit4ded1c1fa0bc21c61f91a2dbe864835986745121 (patch)
tree16d100fbc9dae63888d48b464e471ba0e5065193 /contrib/ntp/ntpd/ntp_control.c
parent8b5a86d4fda08a9c68231415812edcb26be52f79 (diff)
downloadFreeBSD-src-4ded1c1fa0bc21c61f91a2dbe864835986745121.zip
FreeBSD-src-4ded1c1fa0bc21c61f91a2dbe864835986745121.tar.gz
Flatten the dist and various 4.n.n trees in preparation of future ntp imports.
Diffstat (limited to 'contrib/ntp/ntpd/ntp_control.c')
-rw-r--r--contrib/ntp/ntpd/ntp_control.c2928
1 files changed, 0 insertions, 2928 deletions
diff --git a/contrib/ntp/ntpd/ntp_control.c b/contrib/ntp/ntpd/ntp_control.c
deleted file mode 100644
index 0ac0404..0000000
--- a/contrib/ntp/ntpd/ntp_control.c
+++ /dev/null
@@ -1,2928 +0,0 @@
-/*
- * ntp_control.c - respond to control messages and send async traps
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_control.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-#include <signal.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-/*
- * Structure to hold request procedure information
- */
-#define NOAUTH 0
-#define AUTH 1
-
-#define NO_REQUEST (-1)
-
-struct ctl_proc {
- short control_code; /* defined request code */
- u_short flags; /* flags word */
- void (*handler) P((struct recvbuf *, int)); /* handle request */
-};
-
-/*
- * Only one flag. Authentication required or not.
- */
-#define NOAUTH 0
-#define AUTH 1
-
-/*
- * Request processing routines
- */
-static void ctl_error P((int));
-#ifdef REFCLOCK
-static u_short ctlclkstatus P((struct refclockstat *));
-#endif
-static void ctl_flushpkt P((int));
-static void ctl_putdata P((const char *, unsigned int, int));
-static void ctl_putstr P((const char *, const char *,
- unsigned int));
-static void ctl_putdbl P((const char *, double));
-static void ctl_putuint P((const char *, u_long));
-static void ctl_puthex P((const char *, u_long));
-static void ctl_putint P((const char *, long));
-static void ctl_putts P((const char *, l_fp *));
-static void ctl_putadr P((const char *, u_int32, struct sockaddr_storage*));
-static void ctl_putid P((const char *, char *));
-static void ctl_putarray P((const char *, double *, int));
-static void ctl_putsys P((int));
-static void ctl_putpeer P((int, struct peer *));
-#ifdef REFCLOCK
-static void ctl_putclock P((int, struct refclockstat *, int));
-#endif /* REFCLOCK */
-static struct ctl_var *ctl_getitem P((struct ctl_var *, char **));
-static u_long count_var P((struct ctl_var *));
-static void control_unspec P((struct recvbuf *, int));
-static void read_status P((struct recvbuf *, int));
-static void read_variables P((struct recvbuf *, int));
-static void write_variables P((struct recvbuf *, int));
-static void read_clock_status P((struct recvbuf *, int));
-static void write_clock_status P((struct recvbuf *, int));
-static void set_trap P((struct recvbuf *, int));
-static void unset_trap P((struct recvbuf *, int));
-static struct ctl_trap *ctlfindtrap P((struct sockaddr_storage *,
- struct interface *));
-
-static struct ctl_proc control_codes[] = {
- { CTL_OP_UNSPEC, NOAUTH, control_unspec },
- { CTL_OP_READSTAT, NOAUTH, read_status },
- { CTL_OP_READVAR, NOAUTH, read_variables },
- { CTL_OP_WRITEVAR, AUTH, write_variables },
- { CTL_OP_READCLOCK, NOAUTH, read_clock_status },
- { CTL_OP_WRITECLOCK, NOAUTH, write_clock_status },
- { CTL_OP_SETTRAP, NOAUTH, set_trap },
- { CTL_OP_UNSETTRAP, NOAUTH, unset_trap },
- { NO_REQUEST, 0 }
-};
-
-/*
- * System variable values. The array can be indexed by the variable
- * index to find the textual name.
- */
-static struct ctl_var sys_var[] = {
- { 0, PADDING, "" }, /* 0 */
- { CS_LEAP, RW, "leap" }, /* 1 */
- { CS_STRATUM, RO, "stratum" }, /* 2 */
- { CS_PRECISION, RO, "precision" }, /* 3 */
- { CS_ROOTDELAY, RO, "rootdelay" }, /* 4 */
- { CS_ROOTDISPERSION, RO, "rootdispersion" }, /* 5 */
- { CS_REFID, RO, "refid" }, /* 6 */
- { CS_REFTIME, RO, "reftime" }, /* 7 */
- { CS_POLL, RO, "poll" }, /* 8 */
- { CS_PEERID, RO, "peer" }, /* 9 */
- { CS_STATE, RO, "state" }, /* 10 */
- { CS_OFFSET, RO, "offset" }, /* 11 */
- { CS_DRIFT, RO, "frequency" }, /* 12 */
- { CS_JITTER, RO, "jitter" }, /* 13 */
- { CS_CLOCK, RO, "clock" }, /* 14 */
- { CS_PROCESSOR, RO, "processor" }, /* 15 */
- { CS_SYSTEM, RO, "system" }, /* 16 */
- { CS_VERSION, RO, "version" }, /* 17 */
- { CS_STABIL, RO, "stability" }, /* 18 */
- { CS_VARLIST, RO, "sys_var_list" }, /* 19 */
-#ifdef OPENSSL
- { CS_FLAGS, RO, "flags" }, /* 20 */
- { CS_HOST, RO, "hostname" }, /* 21 */
- { CS_PUBLIC, RO, "hostkey" }, /* 22 */
- { CS_CERTIF, RO, "cert" }, /* 23 */
- { CS_REVTIME, RO, "refresh" }, /* 24 */
- { CS_LEAPTAB, RO, "leapseconds" }, /* 25 */
- { CS_TAI, RO, "tai" }, /* 26 */
- { CS_DIGEST, RO, "signature" }, /* 27 */
-#endif /* OPENSSL */
- { 0, EOV, "" } /* 28 */
-};
-
-static struct ctl_var *ext_sys_var = (struct ctl_var *)0;
-
-/*
- * System variables we print by default (in fuzzball order,
- * more-or-less)
- */
-static u_char def_sys_var[] = {
- CS_VERSION,
- CS_PROCESSOR,
- CS_SYSTEM,
- CS_LEAP,
- CS_STRATUM,
- CS_PRECISION,
- CS_ROOTDELAY,
- CS_ROOTDISPERSION,
- CS_PEERID,
- CS_REFID,
- CS_REFTIME,
- CS_POLL,
- CS_CLOCK,
- CS_STATE,
- CS_OFFSET,
- CS_DRIFT,
- CS_JITTER,
- CS_STABIL,
-#ifdef OPENSSL
- CS_HOST,
- CS_DIGEST,
- CS_FLAGS,
- CS_PUBLIC,
- CS_REVTIME,
- CS_LEAPTAB,
- CS_CERTIF,
-#endif /* OPENSSL */
- 0
-};
-
-
-/*
- * Peer variable list
- */
-static struct ctl_var peer_var[] = {
- { 0, PADDING, "" }, /* 0 */
- { CP_CONFIG, RO, "config" }, /* 1 */
- { CP_AUTHENABLE, RO, "authenable" }, /* 2 */
- { CP_AUTHENTIC, RO, "authentic" }, /* 3 */
- { CP_SRCADR, RO, "srcadr" }, /* 4 */
- { CP_SRCPORT, RO, "srcport" }, /* 5 */
- { CP_DSTADR, RO, "dstadr" }, /* 6 */
- { CP_DSTPORT, RO, "dstport" }, /* 7 */
- { CP_LEAP, RO, "leap" }, /* 8 */
- { CP_HMODE, RO, "hmode" }, /* 9 */
- { CP_STRATUM, RO, "stratum" }, /* 10 */
- { CP_PPOLL, RO, "ppoll" }, /* 11 */
- { CP_HPOLL, RO, "hpoll" }, /* 12 */
- { CP_PRECISION, RO, "precision" }, /* 13 */
- { CP_ROOTDELAY, RO, "rootdelay" }, /* 14 */
- { CP_ROOTDISPERSION, RO, "rootdispersion" }, /* 15 */
- { CP_REFID, RO, "refid" }, /* 16 */
- { CP_REFTIME, RO, "reftime" }, /* 17 */
- { CP_ORG, RO, "org" }, /* 18 */
- { CP_REC, RO, "rec" }, /* 19 */
- { CP_XMT, RO, "xmt" }, /* 20 */
- { CP_REACH, RO, "reach" }, /* 21 */
- { CP_VALID, RO, "unreach" }, /* 22 */
- { CP_TIMER, RO, "timer" }, /* 23 */
- { CP_DELAY, RO, "delay" }, /* 24 */
- { CP_OFFSET, RO, "offset" }, /* 25 */
- { CP_JITTER, RO, "jitter" }, /* 26 */
- { CP_DISPERSION, RO, "dispersion" }, /* 27 */
- { CP_KEYID, RO, "keyid" }, /* 28 */
- { CP_FILTDELAY, RO, "filtdelay=" }, /* 29 */
- { CP_FILTOFFSET, RO, "filtoffset=" }, /* 30 */
- { CP_PMODE, RO, "pmode" }, /* 31 */
- { CP_RECEIVED, RO, "received"}, /* 32 */
- { CP_SENT, RO, "sent" }, /* 33 */
- { CP_FILTERROR, RO, "filtdisp=" }, /* 34 */
- { CP_FLASH, RO, "flash" }, /* 35 */
- { CP_TTL, RO, "ttl" }, /* 36 */
- { CP_RANK, RO, "rank" }, /* 37 */
- { CP_VARLIST, RO, "peer_var_list" }, /* 38 */
-#ifdef OPENSSL
- { CP_FLAGS, RO, "flags" }, /* 39 */
- { CP_HOST, RO, "hostname" }, /* 40 */
- { CP_INITSEQ, RO, "initsequence" }, /* 41 */
- { CP_INITKEY, RO, "initkey" }, /* 42 */
- { CP_INITTSP, RO, "timestamp" }, /* 43 */
- { CP_DIGEST, RO, "signature" }, /* 44 */
- { CP_IDENT, RO, "identity" }, /* 45 */
-#endif /* OPENSSL */
- { 0, EOV, "" } /* 39/46 */
-};
-
-
-/*
- * Peer variables we print by default
- */
-static u_char def_peer_var[] = {
- CP_SRCADR,
- CP_SRCPORT,
- CP_DSTADR,
- CP_DSTPORT,
- CP_LEAP,
- CP_STRATUM,
- CP_PRECISION,
- CP_ROOTDELAY,
- CP_ROOTDISPERSION,
- CP_REFID,
- CP_REACH,
- CP_VALID,
- CP_HMODE,
- CP_PMODE,
- CP_HPOLL,
- CP_PPOLL,
- CP_FLASH,
- CP_KEYID,
- CP_TTL,
- CP_OFFSET,
- CP_DELAY,
- CP_DISPERSION,
- CP_JITTER,
- CP_REFTIME,
- CP_ORG,
- CP_REC,
- CP_XMT,
- CP_FILTDELAY,
- CP_FILTOFFSET,
- CP_FILTERROR,
-#ifdef OPENSSL
- CP_HOST,
- CP_DIGEST,
- CP_FLAGS,
- CP_IDENT,
- CP_INITSEQ,
-#endif /* OPENSSL */
- 0
-};
-
-
-#ifdef REFCLOCK
-/*
- * Clock variable list
- */
-static struct ctl_var clock_var[] = {
- { 0, PADDING, "" }, /* 0 */
- { CC_TYPE, RO, "type" }, /* 1 */
- { CC_TIMECODE, RO, "timecode" }, /* 2 */
- { CC_POLL, RO, "poll" }, /* 3 */
- { CC_NOREPLY, RO, "noreply" }, /* 4 */
- { CC_BADFORMAT, RO, "badformat" }, /* 5 */
- { CC_BADDATA, RO, "baddata" }, /* 6 */
- { CC_FUDGETIME1, RO, "fudgetime1" }, /* 7 */
- { CC_FUDGETIME2, RO, "fudgetime2" }, /* 8 */
- { CC_FUDGEVAL1, RO, "stratum" }, /* 9 */
- { CC_FUDGEVAL2, RO, "refid" }, /* 10 */
- { CC_FLAGS, RO, "flags" }, /* 11 */
- { CC_DEVICE, RO, "device" }, /* 12 */
- { CC_VARLIST, RO, "clock_var_list" }, /* 13 */
- { 0, EOV, "" } /* 14 */
-};
-
-
-/*
- * Clock variables printed by default
- */
-static u_char def_clock_var[] = {
- CC_DEVICE,
- CC_TYPE, /* won't be output if device = known */
- CC_TIMECODE,
- CC_POLL,
- CC_NOREPLY,
- CC_BADFORMAT,
- CC_BADDATA,
- CC_FUDGETIME1,
- CC_FUDGETIME2,
- CC_FUDGEVAL1,
- CC_FUDGEVAL2,
- CC_FLAGS,
- 0
-};
-#endif
-
-
-/*
- * System and processor definitions.
- */
-#ifndef HAVE_UNAME
-# ifndef STR_SYSTEM
-# define STR_SYSTEM "UNIX"
-# endif
-# ifndef STR_PROCESSOR
-# define STR_PROCESSOR "unknown"
-# endif
-
-static char str_system[] = STR_SYSTEM;
-static char str_processor[] = STR_PROCESSOR;
-#else
-# include <sys/utsname.h>
-static struct utsname utsnamebuf;
-#endif /* HAVE_UNAME */
-
-/*
- * Trap structures. We only allow a few of these, and send a copy of
- * each async message to each live one. Traps time out after an hour, it
- * is up to the trap receipient to keep resetting it to avoid being
- * timed out.
- */
-/* ntp_request.c */
-struct ctl_trap ctl_trap[CTL_MAXTRAPS];
-int num_ctl_traps;
-
-/*
- * Type bits, for ctlsettrap() call.
- */
-#define TRAP_TYPE_CONFIG 0 /* used by configuration code */
-#define TRAP_TYPE_PRIO 1 /* priority trap */
-#define TRAP_TYPE_NONPRIO 2 /* nonpriority trap */
-
-
-/*
- * List relating reference clock types to control message time sources.
- * Index by the reference clock type. This list will only be used iff
- * the reference clock driver doesn't set peer->sstclktype to something
- * different than CTL_SST_TS_UNSPEC.
- */
-static u_char clocktypes[] = {
- CTL_SST_TS_NTP, /* REFCLK_NONE (0) */
- CTL_SST_TS_LOCAL, /* REFCLK_LOCALCLOCK (1) */
- CTL_SST_TS_UHF, /* REFCLK_GPS_TRAK (2) */
- CTL_SST_TS_HF, /* REFCLK_WWV_PST (3) */
- CTL_SST_TS_LF, /* REFCLK_WWVB_SPECTRACOM (4) */
- CTL_SST_TS_UHF, /* REFCLK_TRUETIME (5) */
- CTL_SST_TS_UHF, /* REFCLK_GOES_TRAK (6) */
- CTL_SST_TS_HF, /* REFCLK_CHU (7) */
- CTL_SST_TS_LF, /* REFCLOCK_PARSE (default) (8) */
- CTL_SST_TS_LF, /* REFCLK_GPS_MX4200 (9) */
- CTL_SST_TS_UHF, /* REFCLK_GPS_AS2201 (10) */
- CTL_SST_TS_UHF, /* REFCLK_GPS_ARBITER (11) */
- CTL_SST_TS_UHF, /* REFCLK_IRIG_TPRO (12) */
- CTL_SST_TS_ATOM, /* REFCLK_ATOM_LEITCH (13) */
- CTL_SST_TS_LF, /* REFCLK_MSF_EES (14) */
- CTL_SST_TS_UHF, /* REFCLK_TRUETIME (15) */
- CTL_SST_TS_UHF, /* REFCLK_IRIG_BANCOMM (16) */
- CTL_SST_TS_UHF, /* REFCLK_GPS_DATU (17) */
- CTL_SST_TS_TELEPHONE, /* REFCLK_NIST_ACTS (18) */
- CTL_SST_TS_HF, /* REFCLK_WWV_HEATH (19) */
- CTL_SST_TS_UHF, /* REFCLK_GPS_NMEA (20) */
- CTL_SST_TS_UHF, /* REFCLK_GPS_VME (21) */
- CTL_SST_TS_ATOM, /* REFCLK_ATOM_PPS (22) */
- CTL_SST_TS_TELEPHONE, /* REFCLK_PTB_ACTS (23) */
- CTL_SST_TS_TELEPHONE, /* REFCLK_USNO (24) */
- CTL_SST_TS_UHF, /* REFCLK_TRUETIME (25) */
- CTL_SST_TS_UHF, /* REFCLK_GPS_HP (26) */
- CTL_SST_TS_TELEPHONE, /* REFCLK_ARCRON_MSF (27) */
- CTL_SST_TS_TELEPHONE, /* REFCLK_SHM (28) */
- CTL_SST_TS_UHF, /* REFCLK_PALISADE (29) */
- CTL_SST_TS_UHF, /* REFCLK_ONCORE (30) */
- CTL_SST_TS_UHF, /* REFCLK_JUPITER (31) */
- CTL_SST_TS_LF, /* REFCLK_CHRONOLOG (32) */
- CTL_SST_TS_LF, /* REFCLK_DUMBCLOCK (32) */
- CTL_SST_TS_LF, /* REFCLK_ULINK (33) */
- CTL_SST_TS_LF, /* REFCLK_PCF (35) */
- CTL_SST_TS_LF, /* REFCLK_WWV (36) */
- CTL_SST_TS_LF, /* REFCLK_FG (37) */
- CTL_SST_TS_UHF, /* REFCLK_HOPF_SERIAL (38) */
- CTL_SST_TS_UHF, /* REFCLK_HOPF_PCI (39) */
- CTL_SST_TS_LF, /* REFCLK_JJY (40) */
- CTL_SST_TS_UHF, /* REFCLK_TT560 (41) */
- CTL_SST_TS_UHF, /* REFCLK_ZYFER (42) */
- CTL_SST_TS_UHF, /* REFCLK_RIPENCC (43) */
- CTL_SST_TS_UHF, /* REFCLK_NEOCLOCK4X (44) */
-};
-
-
-/*
- * Keyid used for authenticating write requests.
- */
-keyid_t ctl_auth_keyid;
-
-/*
- * We keep track of the last error reported by the system internally
- */
-static u_char ctl_sys_last_event;
-static u_char ctl_sys_num_events;
-
-
-/*
- * Statistic counters to keep track of requests and responses.
- */
-u_long ctltimereset; /* time stats reset */
-u_long numctlreq; /* number of requests we've received */
-u_long numctlbadpkts; /* number of bad control packets */
-u_long numctlresponses; /* number of resp packets sent with data */
-u_long numctlfrags; /* number of fragments sent */
-u_long numctlerrors; /* number of error responses sent */
-u_long numctltooshort; /* number of too short input packets */
-u_long numctlinputresp; /* number of responses on input */
-u_long numctlinputfrag; /* number of fragments on input */
-u_long numctlinputerr; /* number of input pkts with err bit set */
-u_long numctlbadoffset; /* number of input pkts with nonzero offset */
-u_long numctlbadversion; /* number of input pkts with unknown version */
-u_long numctldatatooshort; /* data too short for count */
-u_long numctlbadop; /* bad op code found in packet */
-u_long numasyncmsgs; /* number of async messages we've sent */
-
-/*
- * Response packet used by these routines. Also some state information
- * so that we can handle packet formatting within a common set of
- * subroutines. Note we try to enter data in place whenever possible,
- * but the need to set the more bit correctly means we occasionally
- * use the extra buffer and copy.
- */
-static struct ntp_control rpkt;
-static u_char res_version;
-static u_char res_opcode;
-static associd_t res_associd;
-static int res_offset;
-static u_char * datapt;
-static u_char * dataend;
-static int datalinelen;
-static int datanotbinflag;
-static struct sockaddr_storage *rmt_addr;
-static struct interface *lcl_inter;
-
-static u_char res_authenticate;
-static u_char res_authokay;
-static keyid_t res_keyid;
-
-#define MAXDATALINELEN (72)
-
-static u_char res_async; /* set to 1 if this is async trap response */
-
-/*
- * Pointers for saving state when decoding request packets
- */
-static char *reqpt;
-static char *reqend;
-
-/*
- * init_control - initialize request data
- */
-void
-init_control(void)
-{
- int i;
-
-#ifdef HAVE_UNAME
- uname(&utsnamebuf);
-#endif /* HAVE_UNAME */
-
- ctl_clr_stats();
-
- ctl_auth_keyid = 0;
- ctl_sys_last_event = EVNT_UNSPEC;
- ctl_sys_num_events = 0;
-
- num_ctl_traps = 0;
- for (i = 0; i < CTL_MAXTRAPS; i++)
- ctl_trap[i].tr_flags = 0;
-}
-
-
-/*
- * ctl_error - send an error response for the current request
- */
-static void
-ctl_error(
- int errcode
- )
-{
-#ifdef DEBUG
- if (debug >= 4)
- printf("sending control error %d\n", errcode);
-#endif
- /*
- * Fill in the fields. We assume rpkt.sequence and rpkt.associd
- * have already been filled in.
- */
- rpkt.r_m_e_op = (u_char) (CTL_RESPONSE|CTL_ERROR|(res_opcode &
- CTL_OP_MASK));
- rpkt.status = htons((u_short) ((errcode<<8) & 0xff00));
- rpkt.count = 0;
-
- /*
- * send packet and bump counters
- */
- if (res_authenticate && sys_authenticate) {
- int maclen;
-
- *(u_int32 *)((u_char *)&rpkt + CTL_HEADER_LEN) =
- htonl(res_keyid);
- maclen = authencrypt(res_keyid, (u_int32 *)&rpkt,
- CTL_HEADER_LEN);
- sendpkt(rmt_addr, lcl_inter, -2, (struct pkt *)&rpkt,
- CTL_HEADER_LEN + maclen);
- } else {
- sendpkt(rmt_addr, lcl_inter, -3, (struct pkt *)&rpkt,
- CTL_HEADER_LEN);
- }
- numctlerrors++;
-}
-
-
-/*
- * process_control - process an incoming control message
- */
-void
-process_control(
- struct recvbuf *rbufp,
- int restrict_mask
- )
-{
- register struct ntp_control *pkt;
- register int req_count;
- register int req_data;
- register struct ctl_proc *cc;
- int properlen;
- int maclen;
-
-#ifdef DEBUG
- if (debug > 2)
- printf("in process_control()\n");
-#endif
-
- /*
- * Save the addresses for error responses
- */
- numctlreq++;
- rmt_addr = &rbufp->recv_srcadr;
- lcl_inter = rbufp->dstadr;
- pkt = (struct ntp_control *)&rbufp->recv_pkt;
-
- /*
- * If the length is less than required for the header, or
- * it is a response or a fragment, ignore this.
- */
- if (rbufp->recv_length < CTL_HEADER_LEN
- || pkt->r_m_e_op & (CTL_RESPONSE|CTL_MORE|CTL_ERROR)
- || pkt->offset != 0) {
-#ifdef DEBUG
- if (debug)
- printf("invalid format in control packet\n");
-#endif
- if (rbufp->recv_length < CTL_HEADER_LEN)
- numctltooshort++;
- if (pkt->r_m_e_op & CTL_RESPONSE)
- numctlinputresp++;
- if (pkt->r_m_e_op & CTL_MORE)
- numctlinputfrag++;
- if (pkt->r_m_e_op & CTL_ERROR)
- numctlinputerr++;
- if (pkt->offset != 0)
- numctlbadoffset++;
- return;
- }
- res_version = PKT_VERSION(pkt->li_vn_mode);
- if (res_version > NTP_VERSION || res_version < NTP_OLDVERSION) {
-#ifdef DEBUG
- if (debug)
- printf("unknown version %d in control packet\n",
- res_version);
-#endif
- numctlbadversion++;
- return;
- }
-
- /*
- * Pull enough data from the packet to make intelligent
- * responses
- */
- rpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap, res_version,
- MODE_CONTROL);
- res_opcode = pkt->r_m_e_op;
- rpkt.sequence = pkt->sequence;
- rpkt.associd = pkt->associd;
- rpkt.status = 0;
- res_offset = 0;
- res_associd = htons(pkt->associd);
- res_async = 0;
- res_authenticate = 0;
- res_keyid = 0;
- res_authokay = 0;
- req_count = (int)htons(pkt->count);
- datanotbinflag = 0;
- datalinelen = 0;
- datapt = rpkt.data;
- dataend = &(rpkt.data[CTL_MAX_DATA_LEN]);
-
- /*
- * We're set up now. Make sure we've got at least enough
- * incoming data space to match the count.
- */
- req_data = rbufp->recv_length - CTL_HEADER_LEN;
- if (req_data < req_count || rbufp->recv_length & 0x3) {
- ctl_error(CERR_BADFMT);
- numctldatatooshort++;
- return;
- }
-
- properlen = req_count + CTL_HEADER_LEN;
-#ifdef DEBUG
- if (debug > 2 && (rbufp->recv_length & 0x3) != 0)
- printf("Packet length %d unrounded\n",
- rbufp->recv_length);
-#endif
- /* round up proper len to a 8 octet boundary */
-
- properlen = (properlen + 7) & ~7;
- maclen = rbufp->recv_length - properlen;
- if ((rbufp->recv_length & (sizeof(u_long) - 1)) == 0 &&
- maclen >= MIN_MAC_LEN && maclen <= MAX_MAC_LEN &&
- sys_authenticate) {
- res_authenticate = 1;
- res_keyid = ntohl(*(u_int32 *)((u_char *)pkt +
- properlen));
-
-#ifdef DEBUG
- if (debug > 2)
- printf(
- "recv_len %d, properlen %d, wants auth with keyid %08x, MAC length=%d\n",
- rbufp->recv_length, properlen, res_keyid, maclen);
-#endif
- if (!authistrusted(res_keyid)) {
-#ifdef DEBUG
- if (debug > 2)
- printf("invalid keyid %08x\n",
- res_keyid);
-#endif
- } else if (authdecrypt(res_keyid, (u_int32 *)pkt,
- rbufp->recv_length - maclen, maclen)) {
-#ifdef DEBUG
- if (debug > 2)
- printf("authenticated okay\n");
-#endif
- res_authokay = 1;
- } else {
-#ifdef DEBUG
- if (debug > 2)
- printf("authentication failed\n");
-#endif
- res_keyid = 0;
- }
- }
-
- /*
- * Set up translate pointers
- */
- reqpt = (char *)pkt->data;
- reqend = reqpt + req_count;
-
- /*
- * Look for the opcode processor
- */
- for (cc = control_codes; cc->control_code != NO_REQUEST; cc++) {
- if (cc->control_code == res_opcode) {
-#ifdef DEBUG
- if (debug > 2)
- printf("opcode %d, found command handler\n",
- res_opcode);
-#endif
- if (cc->flags == AUTH && (!res_authokay ||
- res_keyid != ctl_auth_keyid)) {
- ctl_error(CERR_PERMISSION);
- return;
- }
- (cc->handler)(rbufp, restrict_mask);
- return;
- }
- }
-
- /*
- * Can't find this one, return an error.
- */
- numctlbadop++;
- ctl_error(CERR_BADOP);
- return;
-}
-
-
-/*
- * ctlpeerstatus - return a status word for this peer
- */
-u_short
-ctlpeerstatus(
- register struct peer *peer
- )
-{
- register u_short status;
-
- status = peer->status;
- if (peer->flags & FLAG_CONFIG)
- status |= CTL_PST_CONFIG;
- if (peer->flags & FLAG_AUTHENABLE)
- status |= CTL_PST_AUTHENABLE;
- if (peer->flags & FLAG_AUTHENTIC)
- status |= CTL_PST_AUTHENTIC;
- if (peer->reach != 0)
- status |= CTL_PST_REACH;
- return (u_short)CTL_PEER_STATUS(status, peer->num_events,
- peer->last_event);
-}
-
-
-/*
- * ctlclkstatus - return a status word for this clock
- */
-#ifdef REFCLOCK
-static u_short
-ctlclkstatus(
- struct refclockstat *this_clock
- )
-{
- return ((u_short)(((this_clock->currentstatus) << 8) |
- (this_clock->lastevent)));
-}
-#endif
-
-
-/*
- * ctlsysstatus - return the system status word
- */
-u_short
-ctlsysstatus(void)
-{
- register u_char this_clock;
-
- this_clock = CTL_SST_TS_UNSPEC;
- if (sys_peer != 0) {
- if (sys_peer->sstclktype != CTL_SST_TS_UNSPEC) {
- this_clock = sys_peer->sstclktype;
- if (pps_control)
- this_clock |= CTL_SST_TS_PPS;
- } else {
- if (sys_peer->refclktype < sizeof(clocktypes))
- this_clock =
- clocktypes[sys_peer->refclktype];
- if (pps_control)
- this_clock |= CTL_SST_TS_PPS;
- }
- }
- return (u_short)CTL_SYS_STATUS(sys_leap, this_clock,
- ctl_sys_num_events, ctl_sys_last_event);
-}
-
-
-/*
- * ctl_flushpkt - write out the current packet and prepare
- * another if necessary.
- */
-static void
-ctl_flushpkt(
- int more
- )
-{
- int dlen;
- int sendlen;
-
- if (!more && datanotbinflag) {
- /*
- * Big hack, output a trailing \r\n
- */
- *datapt++ = '\r';
- *datapt++ = '\n';
- }
- dlen = datapt - (u_char *)rpkt.data;
- sendlen = dlen + CTL_HEADER_LEN;
-
- /*
- * Pad to a multiple of 32 bits
- */
- while (sendlen & 0x3) {
- *datapt++ = '\0';
- sendlen++;
- }
-
- /*
- * Fill in the packet with the current info
- */
- rpkt.r_m_e_op = (u_char)(CTL_RESPONSE|more|(res_opcode &
- CTL_OP_MASK));
- rpkt.count = htons((u_short) dlen);
- rpkt.offset = htons( (u_short) res_offset);
- if (res_async) {
- register int i;
-
- for (i = 0; i < CTL_MAXTRAPS; i++) {
- if (ctl_trap[i].tr_flags & TRAP_INUSE) {
- rpkt.li_vn_mode =
- PKT_LI_VN_MODE(sys_leap,
- ctl_trap[i].tr_version,
- MODE_CONTROL);
- rpkt.sequence =
- htons(ctl_trap[i].tr_sequence);
- sendpkt(&ctl_trap[i].tr_addr,
- ctl_trap[i].tr_localaddr, -4,
- (struct pkt *)&rpkt, sendlen);
- if (!more)
- ctl_trap[i].tr_sequence++;
- numasyncmsgs++;
- }
- }
- } else {
- if (res_authenticate && sys_authenticate) {
- int maclen;
- int totlen = sendlen;
- keyid_t keyid = htonl(res_keyid);
-
- /*
- * If we are going to authenticate, then there
- * is an additional requirement that the MAC
- * begin on a 64 bit boundary.
- */
- while (totlen & 7) {
- *datapt++ = '\0';
- totlen++;
- }
- memcpy(datapt, &keyid, sizeof keyid);
- maclen = authencrypt(res_keyid,
- (u_int32 *)&rpkt, totlen);
- sendpkt(rmt_addr, lcl_inter, -5,
- (struct pkt *)&rpkt, totlen + maclen);
- } else {
- sendpkt(rmt_addr, lcl_inter, -6,
- (struct pkt *)&rpkt, sendlen);
- }
- if (more)
- numctlfrags++;
- else
- numctlresponses++;
- }
-
- /*
- * Set us up for another go around.
- */
- res_offset += dlen;
- datapt = (u_char *)rpkt.data;
-}
-
-
-/*
- * ctl_putdata - write data into the packet, fragmenting and starting
- * another if this one is full.
- */
-static void
-ctl_putdata(
- const char *dp,
- unsigned int dlen,
- int bin /* set to 1 when data is binary */
- )
-{
- int overhead;
-
- overhead = 0;
- if (!bin) {
- datanotbinflag = 1;
- overhead = 3;
- if (datapt != rpkt.data) {
- *datapt++ = ',';
- datalinelen++;
- if ((dlen + datalinelen + 1) >= MAXDATALINELEN)
- {
- *datapt++ = '\r';
- *datapt++ = '\n';
- datalinelen = 0;
- } else {
- *datapt++ = ' ';
- datalinelen++;
- }
- }
- }
-
- /*
- * Save room for trailing junk
- */
- if (dlen + overhead + datapt > dataend) {
- /*
- * Not enough room in this one, flush it out.
- */
- ctl_flushpkt(CTL_MORE);
- }
- memmove((char *)datapt, dp, (unsigned)dlen);
- datapt += dlen;
- datalinelen += dlen;
-}
-
-
-/*
- * ctl_putstr - write a tagged string into the response packet
- */
-static void
-ctl_putstr(
- const char *tag,
- const char *data,
- unsigned int len
- )
-{
- register char *cp;
- register const char *cq;
- char buffer[400];
-
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
- if (len > 0) {
- *cp++ = '=';
- *cp++ = '"';
- if (len > (int) (sizeof(buffer) - (cp - buffer) - 1))
- len = sizeof(buffer) - (cp - buffer) - 1;
- memmove(cp, data, (unsigned)len);
- cp += len;
- *cp++ = '"';
- }
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
-}
-
-
-/*
- * ctl_putdbl - write a tagged, signed double into the response packet
- */
-static void
-ctl_putdbl(
- const char *tag,
- double ts
- )
-{
- register char *cp;
- register const char *cq;
- char buffer[200];
-
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
- *cp++ = '=';
- (void)sprintf(cp, "%.3f", ts);
- while (*cp != '\0')
- cp++;
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
-}
-
-/*
- * ctl_putuint - write a tagged unsigned integer into the response
- */
-static void
-ctl_putuint(
- const char *tag,
- u_long uval
- )
-{
- register char *cp;
- register const char *cq;
- char buffer[200];
-
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
-
- *cp++ = '=';
- (void) sprintf(cp, "%lu", uval);
- while (*cp != '\0')
- cp++;
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
-}
-
-
-/*
- * ctl_puthex - write a tagged unsigned integer, in hex, into the response
- */
-static void
-ctl_puthex(
- const char *tag,
- u_long uval
- )
-{
- register char *cp;
- register const char *cq;
- char buffer[200];
-
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
-
- *cp++ = '=';
- (void) sprintf(cp, "0x%lx", uval);
- while (*cp != '\0')
- cp++;
- ctl_putdata(buffer,(unsigned)( cp - buffer ), 0);
-}
-
-
-/*
- * ctl_putint - write a tagged signed integer into the response
- */
-static void
-ctl_putint(
- const char *tag,
- long ival
- )
-{
- register char *cp;
- register const char *cq;
- char buffer[200];
-
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
-
- *cp++ = '=';
- (void) sprintf(cp, "%ld", ival);
- while (*cp != '\0')
- cp++;
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
-}
-
-
-/*
- * ctl_putts - write a tagged timestamp, in hex, into the response
- */
-static void
-ctl_putts(
- const char *tag,
- l_fp *ts
- )
-{
- register char *cp;
- register const char *cq;
- char buffer[200];
-
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
-
- *cp++ = '=';
- (void) sprintf(cp, "0x%08lx.%08lx", ts->l_ui & 0xffffffffL,
- ts->l_uf & 0xffffffffL);
- while (*cp != '\0')
- cp++;
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
-}
-
-
-/*
- * ctl_putadr - write an IP address into the response
- */
-static void
-ctl_putadr(
- const char *tag,
- u_int32 addr32,
- struct sockaddr_storage* addr
- )
-{
- register char *cp;
- register const char *cq;
- char buffer[200];
-
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
-
- *cp++ = '=';
- if (addr == NULL)
- cq = numtoa(addr32);
- else
- cq = stoa(addr);
- while (*cq != '\0')
- *cp++ = *cq++;
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
-}
-
-
-/*
- * ctl_putid - write a tagged clock ID into the response
- */
-static void
-ctl_putid(
- const char *tag,
- char *id
- )
-{
- register char *cp;
- register const char *cq;
- char buffer[200];
-
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
-
- *cp++ = '=';
- cq = id;
- while (*cq != '\0' && (cq - id) < 4)
- *cp++ = *cq++;
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
-}
-
-
-/*
- * ctl_putarray - write a tagged eight element double array into the response
- */
-static void
-ctl_putarray(
- const char *tag,
- double *arr,
- int start
- )
-{
- register char *cp;
- register const char *cq;
- char buffer[200];
- int i;
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
- i = start;
- do {
- if (i == 0)
- i = NTP_SHIFT;
- i--;
- (void)sprintf(cp, " %.2f", arr[i] * 1e3);
- while (*cp != '\0')
- cp++;
- } while(i != start);
- ctl_putdata(buffer, (unsigned)(cp - buffer), 0);
-}
-
-
-/*
- * ctl_putsys - output a system variable
- */
-static void
-ctl_putsys(
- int varid
- )
-{
- l_fp tmp;
- char str[256];
-#ifdef OPENSSL
- struct cert_info *cp;
- char cbuf[256];
-#endif /* OPENSSL */
-
- switch (varid) {
-
- case CS_LEAP:
- ctl_putuint(sys_var[CS_LEAP].text, sys_leap);
- break;
-
- case CS_STRATUM:
- ctl_putuint(sys_var[CS_STRATUM].text, sys_stratum);
- break;
-
- case CS_PRECISION:
- ctl_putint(sys_var[CS_PRECISION].text, sys_precision);
- break;
-
- case CS_ROOTDELAY:
- ctl_putdbl(sys_var[CS_ROOTDELAY].text, sys_rootdelay *
- 1e3);
- break;
-
- case CS_ROOTDISPERSION:
- ctl_putdbl(sys_var[CS_ROOTDISPERSION].text,
- sys_rootdispersion * 1e3);
- break;
-
- case CS_REFID:
- if (sys_stratum > 1 && sys_stratum < STRATUM_UNSPEC)
- ctl_putadr(sys_var[CS_REFID].text, sys_refid, NULL);
- else
- ctl_putid(sys_var[CS_REFID].text,
- (char *)&sys_refid);
- break;
-
- case CS_REFTIME:
- ctl_putts(sys_var[CS_REFTIME].text, &sys_reftime);
- break;
-
- case CS_POLL:
- ctl_putuint(sys_var[CS_POLL].text, sys_poll);
- break;
-
- case CS_PEERID:
- if (sys_peer == NULL)
- ctl_putuint(sys_var[CS_PEERID].text, 0);
- else
- ctl_putuint(sys_var[CS_PEERID].text,
- sys_peer->associd);
- break;
-
- case CS_STATE:
- ctl_putuint(sys_var[CS_STATE].text, (unsigned)state);
- break;
-
- case CS_OFFSET:
- ctl_putdbl(sys_var[CS_OFFSET].text, last_offset * 1e3);
- break;
-
- case CS_DRIFT:
- ctl_putdbl(sys_var[CS_DRIFT].text, drift_comp * 1e6);
- break;
-
- case CS_JITTER:
- ctl_putdbl(sys_var[CS_JITTER].text, sys_jitter * 1e3);
- break;
-
- case CS_CLOCK:
- get_systime(&tmp);
- ctl_putts(sys_var[CS_CLOCK].text, &tmp);
- break;
-
- case CS_PROCESSOR:
-#ifndef HAVE_UNAME
- ctl_putstr(sys_var[CS_PROCESSOR].text, str_processor,
- sizeof(str_processor) - 1);
-#else
- ctl_putstr(sys_var[CS_PROCESSOR].text,
- utsnamebuf.machine, strlen(utsnamebuf.machine));
-#endif /* HAVE_UNAME */
- break;
-
- case CS_SYSTEM:
-#ifndef HAVE_UNAME
- ctl_putstr(sys_var[CS_SYSTEM].text, str_system,
- sizeof(str_system) - 1);
-#else
- sprintf(str, "%s/%s", utsnamebuf.sysname, utsnamebuf.release);
- ctl_putstr(sys_var[CS_SYSTEM].text, str, strlen(str));
-#endif /* HAVE_UNAME */
- break;
-
- case CS_VERSION:
- ctl_putstr(sys_var[CS_VERSION].text, Version,
- strlen(Version));
- break;
-
- case CS_STABIL:
- ctl_putdbl(sys_var[CS_STABIL].text, clock_stability *
- 1e6);
- break;
-
- case CS_VARLIST:
- {
- char buf[CTL_MAX_DATA_LEN];
- register char *s, *t, *be;
- register const char *ss;
- register int i;
- register struct ctl_var *k;
-
- s = buf;
- be = buf + sizeof(buf) -
- strlen(sys_var[CS_VARLIST].text) - 4;
- if (s > be)
- break; /* really long var name */
-
- strcpy(s, sys_var[CS_VARLIST].text);
- strcat(s, "=\"");
- s += strlen(s);
- t = s;
- for (k = sys_var; !(k->flags &EOV); k++) {
- if (k->flags & PADDING)
- continue;
- i = strlen(k->text);
- if (s+i+1 >= be)
- break;
-
- if (s != t)
- *s++ = ',';
- strcpy(s, k->text);
- s += i;
- }
-
- for (k = ext_sys_var; k && !(k->flags &EOV);
- k++) {
- if (k->flags & PADDING)
- continue;
-
- ss = k->text;
- if (!ss)
- continue;
-
- while (*ss && *ss != '=')
- ss++;
- i = ss - k->text;
- if (s + i + 1 >= be)
- break;
-
- if (s != t)
- *s++ = ',';
- strncpy(s, k->text,
- (unsigned)i);
- s += i;
- }
- if (s+2 >= be)
- break;
-
- *s++ = '"';
- *s = '\0';
-
- ctl_putdata(buf, (unsigned)( s - buf ),
- 0);
- }
- break;
-
-#ifdef OPENSSL
- case CS_FLAGS:
- if (crypto_flags) {
- ctl_puthex(sys_var[CS_FLAGS].text, crypto_flags);
- }
- break;
-
- case CS_DIGEST:
- if (crypto_flags) {
- const EVP_MD *dp;
-
- dp = EVP_get_digestbynid(crypto_flags >> 16);
- strcpy(str, OBJ_nid2ln(EVP_MD_pkey_type(dp)));
- ctl_putstr(sys_var[CS_DIGEST].text, str,
- strlen(str));
- }
- break;
-
- case CS_HOST:
- if (sys_hostname != NULL)
- ctl_putstr(sys_var[CS_HOST].text, sys_hostname,
- strlen(sys_hostname));
- break;
-
- case CS_CERTIF:
- for (cp = cinfo; cp != NULL; cp = cp->link) {
- sprintf(cbuf, "%s %s 0x%x %u", cp->subject,
- cp->issuer, cp->flags,
- ntohl(cp->cert.fstamp));
- ctl_putstr(sys_var[CS_CERTIF].text, cbuf,
- strlen(cbuf));
- }
- break;
-
- case CS_PUBLIC:
- if (hostval.fstamp != 0)
- ctl_putuint(sys_var[CS_PUBLIC].text,
- ntohl(hostval.fstamp));
- break;
-
- case CS_REVTIME:
- if (hostval.tstamp != 0)
- ctl_putuint(sys_var[CS_REVTIME].text,
- ntohl(hostval.tstamp));
- break;
-
- case CS_LEAPTAB:
- if (tai_leap.fstamp != 0)
- ctl_putuint(sys_var[CS_LEAPTAB].text,
- ntohl(tai_leap.fstamp));
- if (sys_tai != 0)
- ctl_putuint(sys_var[CS_TAI].text, sys_tai);
- break;
-#endif /* OPENSSL */
- }
-}
-
-
-/*
- * ctl_putpeer - output a peer variable
- */
-static void
-ctl_putpeer(
- int varid,
- struct peer *peer
- )
-{
-#ifdef OPENSSL
- char str[256];
- struct autokey *ap;
-#endif /* OPENSSL */
-
- switch (varid) {
-
- case CP_CONFIG:
- ctl_putuint(peer_var[CP_CONFIG].text,
- (unsigned)((peer->flags & FLAG_CONFIG) != 0));
- break;
-
- case CP_AUTHENABLE:
- ctl_putuint(peer_var[CP_AUTHENABLE].text,
- (unsigned)((peer->flags & FLAG_AUTHENABLE) != 0));
- break;
-
- case CP_AUTHENTIC:
- ctl_putuint(peer_var[CP_AUTHENTIC].text,
- (unsigned)((peer->flags & FLAG_AUTHENTIC) != 0));
- break;
-
- case CP_SRCADR:
- ctl_putadr(peer_var[CP_SRCADR].text, 0,
- &peer->srcadr);
- break;
-
- case CP_SRCPORT:
- ctl_putuint(peer_var[CP_SRCPORT].text,
- ntohs(((struct sockaddr_in*)&peer->srcadr)->sin_port));
- break;
-
- case CP_DSTADR:
- ctl_putadr(peer_var[CP_DSTADR].text, 0,
- &(peer->dstadr->sin));
- break;
-
- case CP_DSTPORT:
- ctl_putuint(peer_var[CP_DSTPORT].text,
- (u_long)(peer->dstadr ?
- ntohs(((struct sockaddr_in*)&peer->dstadr->sin)->sin_port) : 0));
- break;
-
- case CP_LEAP:
- ctl_putuint(peer_var[CP_LEAP].text, peer->leap);
- break;
-
- case CP_HMODE:
- ctl_putuint(peer_var[CP_HMODE].text, peer->hmode);
- break;
-
- case CP_STRATUM:
- ctl_putuint(peer_var[CP_STRATUM].text, peer->stratum);
- break;
-
- case CP_PPOLL:
- ctl_putuint(peer_var[CP_PPOLL].text, peer->ppoll);
- break;
-
- case CP_HPOLL:
- ctl_putuint(peer_var[CP_HPOLL].text, peer->hpoll);
- break;
-
- case CP_PRECISION:
- ctl_putint(peer_var[CP_PRECISION].text,
- peer->precision);
- break;
-
- case CP_ROOTDELAY:
- ctl_putdbl(peer_var[CP_ROOTDELAY].text,
- peer->rootdelay * 1e3);
- break;
-
- case CP_ROOTDISPERSION:
- ctl_putdbl(peer_var[CP_ROOTDISPERSION].text,
- peer->rootdispersion * 1e3);
- break;
-
- case CP_REFID:
- if (peer->flags & FLAG_REFCLOCK) {
- if (peer->stratum > 0 && peer->stratum <
- STRATUM_UNSPEC)
- ctl_putadr(peer_var[CP_REFID].text,
- peer->refid, NULL);
- else
- ctl_putid(peer_var[CP_REFID].text,
- (char *)&peer->refid);
- } else {
- if (peer->stratum > 1 && peer->stratum <
- STRATUM_UNSPEC)
- ctl_putadr(peer_var[CP_REFID].text,
- peer->refid, NULL);
- else
- ctl_putid(peer_var[CP_REFID].text,
- (char *)&peer->refid);
- }
- break;
-
- case CP_REFTIME:
- ctl_putts(peer_var[CP_REFTIME].text, &peer->reftime);
- break;
-
- case CP_ORG:
- ctl_putts(peer_var[CP_ORG].text, &peer->org);
- break;
-
- case CP_REC:
- ctl_putts(peer_var[CP_REC].text, &peer->rec);
- break;
-
- case CP_XMT:
- ctl_putts(peer_var[CP_XMT].text, &peer->xmt);
- break;
-
- case CP_REACH:
- ctl_puthex(peer_var[CP_REACH].text, peer->reach);
- break;
-
- case CP_FLASH:
- ctl_puthex(peer_var[CP_FLASH].text, peer->flash);
- break;
-
- case CP_TTL:
- ctl_putint(peer_var[CP_TTL].text, sys_ttl[peer->ttl]);
- break;
-
- case CP_VALID:
- ctl_putuint(peer_var[CP_VALID].text, peer->unreach);
- break;
-
- case CP_RANK:
- ctl_putuint(peer_var[CP_RANK].text, peer->rank);
- break;
-
- case CP_TIMER:
- ctl_putuint(peer_var[CP_TIMER].text,
- peer->nextdate - current_time);
- break;
-
- case CP_DELAY:
- ctl_putdbl(peer_var[CP_DELAY].text, peer->delay * 1e3);
- break;
-
- case CP_OFFSET:
- ctl_putdbl(peer_var[CP_OFFSET].text, peer->offset *
- 1e3);
- break;
-
- case CP_JITTER:
- ctl_putdbl(peer_var[CP_JITTER].text,
- SQRT(peer->jitter) * 1e3);
- break;
-
- case CP_DISPERSION:
- ctl_putdbl(peer_var[CP_DISPERSION].text, peer->disp *
- 1e3);
- break;
-
- case CP_KEYID:
- ctl_putuint(peer_var[CP_KEYID].text, peer->keyid);
- break;
-
- case CP_FILTDELAY:
- ctl_putarray(peer_var[CP_FILTDELAY].text,
- peer->filter_delay, (int)peer->filter_nextpt);
- break;
-
- case CP_FILTOFFSET:
- ctl_putarray(peer_var[CP_FILTOFFSET].text,
- peer->filter_offset, (int)peer->filter_nextpt);
- break;
-
- case CP_FILTERROR:
- ctl_putarray(peer_var[CP_FILTERROR].text,
- peer->filter_disp, (int)peer->filter_nextpt);
- break;
-
- case CP_PMODE:
- ctl_putuint(peer_var[CP_PMODE].text, peer->pmode);
- break;
-
- case CP_RECEIVED:
- ctl_putuint(peer_var[CP_RECEIVED].text, peer->received);
- break;
-
- case CP_SENT:
- ctl_putuint(peer_var[CP_SENT].text, peer->sent);
- break;
-
- case CP_VARLIST:
- {
- char buf[CTL_MAX_DATA_LEN];
- register char *s, *t, *be;
- register int i;
- register struct ctl_var *k;
-
- s = buf;
- be = buf + sizeof(buf) -
- strlen(peer_var[CP_VARLIST].text) - 4;
- if (s > be)
- break; /* really long var name */
-
- strcpy(s, peer_var[CP_VARLIST].text);
- strcat(s, "=\"");
- s += strlen(s);
- t = s;
- for (k = peer_var; !(k->flags &EOV); k++) {
- if (k->flags & PADDING)
- continue;
-
- i = strlen(k->text);
- if (s + i + 1 >= be)
- break;
-
- if (s != t)
- *s++ = ',';
- strcpy(s, k->text);
- s += i;
- }
- if (s+2 >= be)
- break;
-
- *s++ = '"';
- *s = '\0';
- ctl_putdata(buf, (unsigned)(s - buf), 0);
- }
- break;
-#ifdef OPENSSL
- case CP_FLAGS:
- if (peer->crypto)
- ctl_puthex(peer_var[CP_FLAGS].text, peer->crypto);
- break;
-
- case CP_DIGEST:
- if (peer->crypto) {
- const EVP_MD *dp;
-
- dp = EVP_get_digestbynid(peer->crypto >> 16);
- strcpy(str, OBJ_nid2ln(EVP_MD_pkey_type(dp)));
- ctl_putstr(peer_var[CP_DIGEST].text, str,
- strlen(str));
- }
- break;
-
- case CP_HOST:
- if (peer->subject != NULL)
- ctl_putstr(peer_var[CP_HOST].text, peer->subject,
- strlen(peer->subject));
- break;
-
- case CP_IDENT:
- if (peer->issuer != NULL)
- ctl_putstr(peer_var[CP_IDENT].text, peer->issuer,
- strlen(peer->issuer));
- break;
-
- case CP_INITSEQ:
- if ((ap = (struct autokey *)peer->recval.ptr) == NULL)
- break;
- ctl_putint(peer_var[CP_INITSEQ].text, ap->seq);
- ctl_puthex(peer_var[CP_INITKEY].text, ap->key);
- ctl_putuint(peer_var[CP_INITTSP].text,
- ntohl(peer->recval.tstamp));
- break;
-#endif /* OPENSSL */
- }
-}
-
-
-#ifdef REFCLOCK
-/*
- * ctl_putclock - output clock variables
- */
-static void
-ctl_putclock(
- int varid,
- struct refclockstat *clock_stat,
- int mustput
- )
-{
- switch(varid) {
-
- case CC_TYPE:
- if (mustput || clock_stat->clockdesc == NULL
- || *(clock_stat->clockdesc) == '\0') {
- ctl_putuint(clock_var[CC_TYPE].text, clock_stat->type);
- }
- break;
- case CC_TIMECODE:
- ctl_putstr(clock_var[CC_TIMECODE].text,
- clock_stat->p_lastcode,
- (unsigned)clock_stat->lencode);
- break;
-
- case CC_POLL:
- ctl_putuint(clock_var[CC_POLL].text, clock_stat->polls);
- break;
-
- case CC_NOREPLY:
- ctl_putuint(clock_var[CC_NOREPLY].text,
- clock_stat->noresponse);
- break;
-
- case CC_BADFORMAT:
- ctl_putuint(clock_var[CC_BADFORMAT].text,
- clock_stat->badformat);
- break;
-
- case CC_BADDATA:
- ctl_putuint(clock_var[CC_BADDATA].text,
- clock_stat->baddata);
- break;
-
- case CC_FUDGETIME1:
- if (mustput || (clock_stat->haveflags & CLK_HAVETIME1))
- ctl_putdbl(clock_var[CC_FUDGETIME1].text,
- clock_stat->fudgetime1 * 1e3);
- break;
-
- case CC_FUDGETIME2:
- if (mustput || (clock_stat->haveflags & CLK_HAVETIME2)) ctl_putdbl(clock_var[CC_FUDGETIME2].text,
- clock_stat->fudgetime2 * 1e3);
- break;
-
- case CC_FUDGEVAL1:
- if (mustput || (clock_stat->haveflags & CLK_HAVEVAL1))
- ctl_putint(clock_var[CC_FUDGEVAL1].text,
- clock_stat->fudgeval1);
- break;
-
- case CC_FUDGEVAL2:
- if (mustput || (clock_stat->haveflags & CLK_HAVEVAL2)) {
- if (clock_stat->fudgeval1 > 1)
- ctl_putadr(clock_var[CC_FUDGEVAL2].text,
- (u_int32)clock_stat->fudgeval2, NULL);
- else
- ctl_putid(clock_var[CC_FUDGEVAL2].text,
- (char *)&clock_stat->fudgeval2);
- }
- break;
-
- case CC_FLAGS:
- if (mustput || (clock_stat->haveflags & (CLK_HAVEFLAG1 |
- CLK_HAVEFLAG2 | CLK_HAVEFLAG3 | CLK_HAVEFLAG4)))
- ctl_putuint(clock_var[CC_FLAGS].text,
- clock_stat->flags);
- break;
-
- case CC_DEVICE:
- if (clock_stat->clockdesc == NULL ||
- *(clock_stat->clockdesc) == '\0') {
- if (mustput)
- ctl_putstr(clock_var[CC_DEVICE].text,
- "", 0);
- } else {
- ctl_putstr(clock_var[CC_DEVICE].text,
- clock_stat->clockdesc,
- strlen(clock_stat->clockdesc));
- }
- break;
-
- case CC_VARLIST:
- {
- char buf[CTL_MAX_DATA_LEN];
- register char *s, *t, *be;
- register const char *ss;
- register int i;
- register struct ctl_var *k;
-
- s = buf;
- be = buf + sizeof(buf);
- if (s + strlen(clock_var[CC_VARLIST].text) + 4 >
- be)
- break; /* really long var name */
-
- strcpy(s, clock_var[CC_VARLIST].text);
- strcat(s, "=\"");
- s += strlen(s);
- t = s;
-
- for (k = clock_var; !(k->flags &EOV); k++) {
- if (k->flags & PADDING)
- continue;
-
- i = strlen(k->text);
- if (s + i + 1 >= be)
- break;
-
- if (s != t)
- *s++ = ',';
- strcpy(s, k->text);
- s += i;
- }
-
- for (k = clock_stat->kv_list; k && !(k->flags &
- EOV); k++) {
- if (k->flags & PADDING)
- continue;
-
- ss = k->text;
- if (!ss)
- continue;
-
- while (*ss && *ss != '=')
- ss++;
- i = ss - k->text;
- if (s+i+1 >= be)
- break;
-
- if (s != t)
- *s++ = ',';
- strncpy(s, k->text, (unsigned)i);
- s += i;
- *s = '\0';
- }
- if (s+2 >= be)
- break;
-
- *s++ = '"';
- *s = '\0';
- ctl_putdata(buf, (unsigned)( s - buf ), 0);
- }
- break;
- }
-}
-#endif
-
-
-
-/*
- * ctl_getitem - get the next data item from the incoming packet
- */
-static struct ctl_var *
-ctl_getitem(
- struct ctl_var *var_list,
- char **data
- )
-{
- register struct ctl_var *v;
- register char *cp;
- register char *tp;
- static struct ctl_var eol = { 0, EOV, };
- static char buf[128];
-
- /*
- * Delete leading commas and white space
- */
- while (reqpt < reqend && (*reqpt == ',' ||
- isspace((int)*reqpt)))
- reqpt++;
- if (reqpt >= reqend)
- return (0);
-
- if (var_list == (struct ctl_var *)0)
- return (&eol);
-
- /*
- * Look for a first character match on the tag. If we find
- * one, see if it is a full match.
- */
- v = var_list;
- cp = reqpt;
- while (!(v->flags & EOV)) {
- if (!(v->flags & PADDING) && *cp == *(v->text)) {
- tp = v->text;
- while (*tp != '\0' && *tp != '=' && cp <
- reqend && *cp == *tp) {
- cp++;
- tp++;
- }
- if ((*tp == '\0') || (*tp == '=')) {
- while (cp < reqend && isspace((int)*cp))
- cp++;
- if (cp == reqend || *cp == ',') {
- buf[0] = '\0';
- *data = buf;
- if (cp < reqend)
- cp++;
- reqpt = cp;
- return v;
- }
- if (*cp == '=') {
- cp++;
- tp = buf;
- while (cp < reqend && isspace((int)*cp))
- cp++;
- while (cp < reqend && *cp != ',') {
- *tp++ = *cp++;
- if (tp >= buf + sizeof(buf)) {
- ctl_error(CERR_BADFMT);
- numctlbadpkts++;
- msyslog(LOG_WARNING,
- "Possible 'ntpdx' exploit from %s:%d (possibly spoofed)\n",
- stoa(rmt_addr), SRCPORT(rmt_addr)
- );
- return (0);
- }
- }
- if (cp < reqend)
- cp++;
- *tp-- = '\0';
- while (tp >= buf) {
- if (!isspace((int)(*tp)))
- break;
- *tp-- = '\0';
- }
- reqpt = cp;
- *data = buf;
- return (v);
- }
- }
- cp = reqpt;
- }
- v++;
- }
- return v;
-}
-
-
-/*
- * control_unspec - response to an unspecified op-code
- */
-/*ARGSUSED*/
-static void
-control_unspec(
- struct recvbuf *rbufp,
- int restrict_mask
- )
-{
- struct peer *peer;
-
- /*
- * What is an appropriate response to an unspecified op-code?
- * I return no errors and no data, unless a specified assocation
- * doesn't exist.
- */
- if (res_associd != 0) {
- if ((peer = findpeerbyassoc(res_associd)) == 0) {
- ctl_error(CERR_BADASSOC);
- return;
- }
- rpkt.status = htons(ctlpeerstatus(peer));
- } else {
- rpkt.status = htons(ctlsysstatus());
- }
- ctl_flushpkt(0);
-}
-
-
-/*
- * read_status - return either a list of associd's, or a particular
- * peer's status.
- */
-/*ARGSUSED*/
-static void
-read_status(
- struct recvbuf *rbufp,
- int restrict_mask
- )
-{
- register int i;
- register struct peer *peer;
- u_short ass_stat[CTL_MAX_DATA_LEN / sizeof(u_short)];
-
-#ifdef DEBUG
- if (debug > 2)
- printf("read_status: ID %d\n", res_associd);
-#endif
- /*
- * Two choices here. If the specified association ID is
- * zero we return all known assocation ID's. Otherwise
- * we return a bunch of stuff about the particular peer.
- */
- if (res_associd == 0) {
- register int n;
-
- n = 0;
- rpkt.status = htons(ctlsysstatus());
- for (i = 0; i < HASH_SIZE; i++) {
- for (peer = assoc_hash[i]; peer != 0;
- peer = peer->ass_next) {
- ass_stat[n++] = htons(peer->associd);
- ass_stat[n++] =
- htons(ctlpeerstatus(peer));
- if (n ==
- CTL_MAX_DATA_LEN/sizeof(u_short)) {
- ctl_putdata((char *)ass_stat,
- n * sizeof(u_short), 1);
- n = 0;
- }
- }
- }
-
- if (n != 0)
- ctl_putdata((char *)ass_stat, n *
- sizeof(u_short), 1);
- ctl_flushpkt(0);
- } else {
- peer = findpeerbyassoc(res_associd);
- if (peer == 0) {
- ctl_error(CERR_BADASSOC);
- } else {
- register u_char *cp;
-
- rpkt.status = htons(ctlpeerstatus(peer));
- if (res_authokay)
- peer->num_events = 0;
- /*
- * For now, output everything we know about the
- * peer. May be more selective later.
- */
- for (cp = def_peer_var; *cp != 0; cp++)
- ctl_putpeer((int)*cp, peer);
- ctl_flushpkt(0);
- }
- }
-}
-
-
-/*
- * read_variables - return the variables the caller asks for
- */
-/*ARGSUSED*/
-static void
-read_variables(
- struct recvbuf *rbufp,
- int restrict_mask
- )
-{
- register struct ctl_var *v;
- register int i;
- char *valuep;
- u_char *wants;
- unsigned int gotvar = (CS_MAXCODE > CP_MAXCODE) ? (CS_MAXCODE +
- 1) : (CP_MAXCODE + 1);
- if (res_associd == 0) {
- /*
- * Wants system variables. Figure out which he wants
- * and give them to him.
- */
- rpkt.status = htons(ctlsysstatus());
- if (res_authokay)
- ctl_sys_num_events = 0;
- gotvar += count_var(ext_sys_var);
- wants = (u_char *)emalloc(gotvar);
- memset((char *)wants, 0, gotvar);
- gotvar = 0;
- while ((v = ctl_getitem(sys_var, &valuep)) != 0) {
- if (v->flags & EOV) {
- if ((v = ctl_getitem(ext_sys_var,
- &valuep)) != 0) {
- if (v->flags & EOV) {
- ctl_error(CERR_UNKNOWNVAR);
- free((char *)wants);
- return;
- }
- wants[CS_MAXCODE + 1 +
- v->code] = 1;
- gotvar = 1;
- continue;
- } else {
- break; /* shouldn't happen ! */
- }
- }
- wants[v->code] = 1;
- gotvar = 1;
- }
- if (gotvar) {
- for (i = 1; i <= CS_MAXCODE; i++)
- if (wants[i])
- ctl_putsys(i);
- for (i = 0; ext_sys_var &&
- !(ext_sys_var[i].flags & EOV); i++)
- if (wants[i + CS_MAXCODE + 1])
- ctl_putdata(ext_sys_var[i].text,
- strlen(ext_sys_var[i].text),
- 0);
- } else {
- register u_char *cs;
- register struct ctl_var *kv;
-
- for (cs = def_sys_var; *cs != 0; cs++)
- ctl_putsys((int)*cs);
- for (kv = ext_sys_var; kv && !(kv->flags & EOV);
- kv++)
- if (kv->flags & DEF)
- ctl_putdata(kv->text,
- strlen(kv->text), 0);
- }
- free((char *)wants);
- } else {
- register struct peer *peer;
-
- /*
- * Wants info for a particular peer. See if we know
- * the guy.
- */
- peer = findpeerbyassoc(res_associd);
- if (peer == 0) {
- ctl_error(CERR_BADASSOC);
- return;
- }
- rpkt.status = htons(ctlpeerstatus(peer));
- if (res_authokay)
- peer->num_events = 0;
- wants = (u_char *)emalloc(gotvar);
- memset((char*)wants, 0, gotvar);
- gotvar = 0;
- while ((v = ctl_getitem(peer_var, &valuep)) != 0) {
- if (v->flags & EOV) {
- ctl_error(CERR_UNKNOWNVAR);
- free((char *)wants);
- return;
- }
- wants[v->code] = 1;
- gotvar = 1;
- }
- if (gotvar) {
- for (i = 1; i <= CP_MAXCODE; i++)
- if (wants[i])
- ctl_putpeer(i, peer);
- } else {
- register u_char *cp;
-
- for (cp = def_peer_var; *cp != 0; cp++)
- ctl_putpeer((int)*cp, peer);
- }
- free((char *)wants);
- }
- ctl_flushpkt(0);
-}
-
-
-/*
- * write_variables - write into variables. We only allow leap bit
- * writing this way.
- */
-/*ARGSUSED*/
-static void
-write_variables(
- struct recvbuf *rbufp,
- int restrict_mask
- )
-{
- register struct ctl_var *v;
- register int ext_var;
- char *valuep;
- long val = 0;
-
- /*
- * If he's trying to write into a peer tell him no way
- */
- if (res_associd != 0) {
- ctl_error(CERR_PERMISSION);
- return;
- }
-
- /*
- * Set status
- */
- rpkt.status = htons(ctlsysstatus());
-
- /*
- * Look through the variables. Dump out at the first sign of
- * trouble.
- */
- while ((v = ctl_getitem(sys_var, &valuep)) != 0) {
- ext_var = 0;
- if (v->flags & EOV) {
- if ((v = ctl_getitem(ext_sys_var, &valuep)) !=
- 0) {
- if (v->flags & EOV) {
- ctl_error(CERR_UNKNOWNVAR);
- return;
- }
- ext_var = 1;
- } else {
- break;
- }
- }
- if (!(v->flags & CAN_WRITE)) {
- ctl_error(CERR_PERMISSION);
- return;
- }
- if (!ext_var && (*valuep == '\0' || !atoint(valuep,
- &val))) {
- ctl_error(CERR_BADFMT);
- return;
- }
- if (!ext_var && (val & ~LEAP_NOTINSYNC) != 0) {
- ctl_error(CERR_BADVALUE);
- return;
- }
-
- if (ext_var) {
- char *s = (char *)emalloc(strlen(v->text) +
- strlen(valuep) + 2);
- const char *t;
- char *tt = s;
-
- t = v->text;
- while (*t && *t != '=')
- *tt++ = *t++;
-
- *tt++ = '=';
- strcat(tt, valuep);
- set_sys_var(s, strlen(s)+1, v->flags);
- free(s);
- } else {
- /*
- * This one seems sane. Save it.
- */
- switch(v->code) {
-
- case CS_LEAP:
- default:
- ctl_error(CERR_UNSPEC); /* really */
- return;
- }
- }
- }
-
- /*
- * If we got anything, do it. xxx nothing to do ***
- */
- /*
- if (leapind != ~0 || leapwarn != ~0) {
- if (!leap_setleap((int)leapind, (int)leapwarn)) {
- ctl_error(CERR_PERMISSION);
- return;
- }
- }
- */
- ctl_flushpkt(0);
-}
-
-
-/*
- * read_clock_status - return clock radio status
- */
-/*ARGSUSED*/
-static void
-read_clock_status(
- struct recvbuf *rbufp,
- int restrict_mask
- )
-{
-#ifndef REFCLOCK
- /*
- * If no refclock support, no data to return
- */
- ctl_error(CERR_BADASSOC);
-#else
- register struct ctl_var *v;
- register int i;
- register struct peer *peer;
- char *valuep;
- u_char *wants;
- unsigned int gotvar;
- struct refclockstat clock_stat;
-
- if (res_associd == 0) {
-
- /*
- * Find a clock for this jerk. If the system peer
- * is a clock use it, else search the hash tables
- * for one.
- */
- if (sys_peer != 0 && (sys_peer->flags & FLAG_REFCLOCK))
- {
- peer = sys_peer;
- } else {
- peer = 0;
- for (i = 0; peer == 0 && i < HASH_SIZE; i++) {
- for (peer = assoc_hash[i]; peer != 0;
- peer = peer->ass_next) {
- if (peer->flags & FLAG_REFCLOCK)
- break;
- }
- }
- if (peer == 0) {
- ctl_error(CERR_BADASSOC);
- return;
- }
- }
- } else {
- peer = findpeerbyassoc(res_associd);
- if (peer == 0 || !(peer->flags & FLAG_REFCLOCK)) {
- ctl_error(CERR_BADASSOC);
- return;
- }
- }
-
- /*
- * If we got here we have a peer which is a clock. Get his
- * status.
- */
- clock_stat.kv_list = (struct ctl_var *)0;
- refclock_control(&peer->srcadr, (struct refclockstat *)0,
- &clock_stat);
-
- /*
- * Look for variables in the packet.
- */
- rpkt.status = htons(ctlclkstatus(&clock_stat));
- gotvar = CC_MAXCODE + 1 + count_var(clock_stat.kv_list);
- wants = (u_char *)emalloc(gotvar);
- memset((char*)wants, 0, gotvar);
- gotvar = 0;
- while ((v = ctl_getitem(clock_var, &valuep)) != 0) {
- if (v->flags & EOV) {
- if ((v = ctl_getitem(clock_stat.kv_list,
- &valuep)) != 0) {
- if (v->flags & EOV) {
- ctl_error(CERR_UNKNOWNVAR);
- free((char*)wants);
- free_varlist(clock_stat.kv_list);
- return;
- }
- wants[CC_MAXCODE + 1 + v->code] = 1;
- gotvar = 1;
- continue;
- } else {
- break; /* shouldn't happen ! */
- }
- }
- wants[v->code] = 1;
- gotvar = 1;
- }
-
- if (gotvar) {
- for (i = 1; i <= CC_MAXCODE; i++)
- if (wants[i])
- ctl_putclock(i, &clock_stat, 1);
- for (i = 0; clock_stat.kv_list &&
- !(clock_stat.kv_list[i].flags & EOV); i++)
- if (wants[i + CC_MAXCODE + 1])
- ctl_putdata(clock_stat.kv_list[i].text,
- strlen(clock_stat.kv_list[i].text),
- 0);
- } else {
- register u_char *cc;
- register struct ctl_var *kv;
-
- for (cc = def_clock_var; *cc != 0; cc++)
- ctl_putclock((int)*cc, &clock_stat, 0);
- for (kv = clock_stat.kv_list; kv && !(kv->flags & EOV);
- kv++)
- if (kv->flags & DEF)
- ctl_putdata(kv->text, strlen(kv->text),
- 0);
- }
-
- free((char*)wants);
- free_varlist(clock_stat.kv_list);
-
- ctl_flushpkt(0);
-#endif
-}
-
-
-/*
- * write_clock_status - we don't do this
- */
-/*ARGSUSED*/
-static void
-write_clock_status(
- struct recvbuf *rbufp,
- int restrict_mask
- )
-{
- ctl_error(CERR_PERMISSION);
-}
-
-/*
- * Trap support from here on down. We send async trap messages when the
- * upper levels report trouble. Traps can by set either by control
- * messages or by configuration.
- */
-/*
- * set_trap - set a trap in response to a control message
- */
-static void
-set_trap(
- struct recvbuf *rbufp,
- int restrict_mask
- )
-{
- int traptype;
-
- /*
- * See if this guy is allowed
- */
- if (restrict_mask & RES_NOTRAP) {
- ctl_error(CERR_PERMISSION);
- return;
- }
-
- /*
- * Determine his allowed trap type.
- */
- traptype = TRAP_TYPE_PRIO;
- if (restrict_mask & RES_LPTRAP)
- traptype = TRAP_TYPE_NONPRIO;
-
- /*
- * Call ctlsettrap() to do the work. Return
- * an error if it can't assign the trap.
- */
- if (!ctlsettrap(&rbufp->recv_srcadr, rbufp->dstadr, traptype,
- (int)res_version))
- ctl_error(CERR_NORESOURCE);
- ctl_flushpkt(0);
-}
-
-
-/*
- * unset_trap - unset a trap in response to a control message
- */
-static void
-unset_trap(
- struct recvbuf *rbufp,
- int restrict_mask
- )
-{
- int traptype;
-
- /*
- * We don't prevent anyone from removing his own trap unless the
- * trap is configured. Note we also must be aware of the
- * possibility that restriction flags were changed since this
- * guy last set his trap. Set the trap type based on this.
- */
- traptype = TRAP_TYPE_PRIO;
- if (restrict_mask & RES_LPTRAP)
- traptype = TRAP_TYPE_NONPRIO;
-
- /*
- * Call ctlclrtrap() to clear this out.
- */
- if (!ctlclrtrap(&rbufp->recv_srcadr, rbufp->dstadr, traptype))
- ctl_error(CERR_BADASSOC);
- ctl_flushpkt(0);
-}
-
-
-/*
- * ctlsettrap - called to set a trap
- */
-int
-ctlsettrap(
- struct sockaddr_storage *raddr,
- struct interface *linter,
- int traptype,
- int version
- )
-{
- register struct ctl_trap *tp;
- register struct ctl_trap *tptouse;
-
- /*
- * See if we can find this trap. If so, we only need update
- * the flags and the time.
- */
- if ((tp = ctlfindtrap(raddr, linter)) != NULL) {
- switch (traptype) {
-
- case TRAP_TYPE_CONFIG:
- tp->tr_flags = TRAP_INUSE|TRAP_CONFIGURED;
- break;
-
- case TRAP_TYPE_PRIO:
- if (tp->tr_flags & TRAP_CONFIGURED)
- return (1); /* don't change anything */
- tp->tr_flags = TRAP_INUSE;
- break;
-
- case TRAP_TYPE_NONPRIO:
- if (tp->tr_flags & TRAP_CONFIGURED)
- return (1); /* don't change anything */
- tp->tr_flags = TRAP_INUSE|TRAP_NONPRIO;
- break;
- }
- tp->tr_settime = current_time;
- tp->tr_resets++;
- return (1);
- }
-
- /*
- * First we heard of this guy. Try to find a trap structure
- * for him to use, clearing out lesser priority guys if we
- * have to. Clear out anyone who's expired while we're at it.
- */
- tptouse = NULL;
- for (tp = ctl_trap; tp < &ctl_trap[CTL_MAXTRAPS]; tp++) {
- if ((tp->tr_flags & TRAP_INUSE) &&
- !(tp->tr_flags & TRAP_CONFIGURED) &&
- ((tp->tr_settime + CTL_TRAPTIME) > current_time)) {
- tp->tr_flags = 0;
- num_ctl_traps--;
- }
- if (!(tp->tr_flags & TRAP_INUSE)) {
- tptouse = tp;
- } else if (!(tp->tr_flags & TRAP_CONFIGURED)) {
- switch (traptype) {
-
- case TRAP_TYPE_CONFIG:
- if (tptouse == NULL) {
- tptouse = tp;
- break;
- }
- if (tptouse->tr_flags & TRAP_NONPRIO &&
- !(tp->tr_flags & TRAP_NONPRIO))
- break;
-
- if (!(tptouse->tr_flags & TRAP_NONPRIO)
- && tp->tr_flags & TRAP_NONPRIO) {
- tptouse = tp;
- break;
- }
- if (tptouse->tr_origtime <
- tp->tr_origtime)
- tptouse = tp;
- break;
-
- case TRAP_TYPE_PRIO:
- if (tp->tr_flags & TRAP_NONPRIO) {
- if (tptouse == NULL ||
- (tptouse->tr_flags &
- TRAP_INUSE &&
- tptouse->tr_origtime <
- tp->tr_origtime))
- tptouse = tp;
- }
- break;
-
- case TRAP_TYPE_NONPRIO:
- break;
- }
- }
- }
-
- /*
- * If we don't have room for him return an error.
- */
- if (tptouse == NULL)
- return (0);
-
- /*
- * Set up this structure for him.
- */
- tptouse->tr_settime = tptouse->tr_origtime = current_time;
- tptouse->tr_count = tptouse->tr_resets = 0;
- tptouse->tr_sequence = 1;
- tptouse->tr_addr = *raddr;
- tptouse->tr_localaddr = linter;
- tptouse->tr_version = (u_char) version;
- tptouse->tr_flags = TRAP_INUSE;
- if (traptype == TRAP_TYPE_CONFIG)
- tptouse->tr_flags |= TRAP_CONFIGURED;
- else if (traptype == TRAP_TYPE_NONPRIO)
- tptouse->tr_flags |= TRAP_NONPRIO;
- num_ctl_traps++;
- return (1);
-}
-
-
-/*
- * ctlclrtrap - called to clear a trap
- */
-int
-ctlclrtrap(
- struct sockaddr_storage *raddr,
- struct interface *linter,
- int traptype
- )
-{
- register struct ctl_trap *tp;
-
- if ((tp = ctlfindtrap(raddr, linter)) == NULL)
- return (0);
-
- if (tp->tr_flags & TRAP_CONFIGURED
- && traptype != TRAP_TYPE_CONFIG)
- return (0);
-
- tp->tr_flags = 0;
- num_ctl_traps--;
- return (1);
-}
-
-
-/*
- * ctlfindtrap - find a trap given the remote and local addresses
- */
-static struct ctl_trap *
-ctlfindtrap(
- struct sockaddr_storage *raddr,
- struct interface *linter
- )
-{
- register struct ctl_trap *tp;
-
- for (tp = ctl_trap; tp < &ctl_trap[CTL_MAXTRAPS]; tp++) {
- if ((tp->tr_flags & TRAP_INUSE)
- && (NSRCPORT(raddr) == NSRCPORT(&tp->tr_addr))
- && SOCKCMP(raddr, &tp->tr_addr)
- && (linter == tp->tr_localaddr) )
- return (tp);
- }
- return (struct ctl_trap *)NULL;
-}
-
-
-/*
- * report_event - report an event to the trappers
- */
-void
-report_event(
- int err,
- struct peer *peer
- )
-{
- register int i;
-
- /*
- * Record error code in proper spots, but have mercy on the
- * log file.
- */
- if (!(err & (PEER_EVENT | CRPT_EVENT))) {
- if (ctl_sys_num_events < CTL_SYS_MAXEVENTS)
- ctl_sys_num_events++;
- if (ctl_sys_last_event != (u_char)err) {
- NLOG(NLOG_SYSEVENT)
- msyslog(LOG_INFO, "system event '%s' (0x%02x) status '%s' (0x%02x)",
- eventstr(err), err,
- sysstatstr(ctlsysstatus()), ctlsysstatus());
-#ifdef DEBUG
- if (debug)
- printf("report_event: system event '%s' (0x%02x) status '%s' (0x%02x)\n",
- eventstr(err), err,
- sysstatstr(ctlsysstatus()),
- ctlsysstatus());
-#endif
- ctl_sys_last_event = (u_char)err;
- }
- } else if (peer != 0) {
- char *src;
-
-#ifdef REFCLOCK
- if (ISREFCLOCKADR(&peer->srcadr))
- src = refnumtoa(&peer->srcadr);
- else
-#endif
- src = stoa(&peer->srcadr);
-
- peer->last_event = (u_char)(err & ~PEER_EVENT);
- if (peer->num_events < CTL_PEER_MAXEVENTS)
- peer->num_events++;
- NLOG(NLOG_PEEREVENT)
- msyslog(LOG_INFO, "peer %s event '%s' (0x%02x) status '%s' (0x%02x)",
- src, eventstr(err), err,
- peerstatstr(ctlpeerstatus(peer)),
- ctlpeerstatus(peer));
-#ifdef DEBUG
- if (debug)
- printf( "peer %s event '%s' (0x%02x) status '%s' (0x%02x)\n",
- src, eventstr(err), err,
- peerstatstr(ctlpeerstatus(peer)),
- ctlpeerstatus(peer));
-#endif
- } else {
- msyslog(LOG_ERR,
- "report_event: err '%s' (0x%02x), no peer",
- eventstr(err), err);
-#ifdef DEBUG
- printf(
- "report_event: peer event '%s' (0x%02x), no peer\n",
- eventstr(err), err);
-#endif
- return;
- }
-
- /*
- * If no trappers, return.
- */
- if (num_ctl_traps <= 0)
- return;
-
- /*
- * Set up the outgoing packet variables
- */
- res_opcode = CTL_OP_ASYNCMSG;
- res_offset = 0;
- res_async = 1;
- res_authenticate = 0;
- datapt = rpkt.data;
- dataend = &(rpkt.data[CTL_MAX_DATA_LEN]);
- if (!(err & PEER_EVENT)) {
- rpkt.associd = 0;
- rpkt.status = htons(ctlsysstatus());
-
- /*
- * For now, put everything we know about system
- * variables. Don't send crypto strings.
- */
- for (i = 1; i <= CS_MAXCODE; i++) {
-#ifdef OPENSSL
- if (i > CS_VARLIST)
- continue;
-#endif /* OPENSSL */
- ctl_putsys(i);
- }
-#ifdef REFCLOCK
- /*
- * for clock exception events: add clock variables to
- * reflect info on exception
- */
- if (err == EVNT_CLOCKEXCPT) {
- struct refclockstat clock_stat;
- struct ctl_var *kv;
-
- clock_stat.kv_list = (struct ctl_var *)0;
- refclock_control(&peer->srcadr,
- (struct refclockstat *)0, &clock_stat);
- ctl_puthex("refclockstatus",
- ctlclkstatus(&clock_stat));
- for (i = 1; i <= CC_MAXCODE; i++)
- ctl_putclock(i, &clock_stat, 0);
- for (kv = clock_stat.kv_list; kv &&
- !(kv->flags & EOV); kv++)
- if (kv->flags & DEF)
- ctl_putdata(kv->text,
- strlen(kv->text), 0);
- free_varlist(clock_stat.kv_list);
- }
-#endif /* REFCLOCK */
- } else {
- rpkt.associd = htons(peer->associd);
- rpkt.status = htons(ctlpeerstatus(peer));
-
- /*
- * Dump it all. Later, maybe less.
- */
- for (i = 1; i <= CP_MAXCODE; i++) {
-#ifdef OPENSSL
- if (i > CP_VARLIST)
- continue;
-#endif /* OPENSSL */
- ctl_putpeer(i, peer);
- }
-#ifdef REFCLOCK
- /*
- * for clock exception events: add clock variables to
- * reflect info on exception
- */
- if (err == EVNT_PEERCLOCK) {
- struct refclockstat clock_stat;
- struct ctl_var *kv;
-
- clock_stat.kv_list = (struct ctl_var *)0;
- refclock_control(&peer->srcadr,
- (struct refclockstat *)0, &clock_stat);
-
- ctl_puthex("refclockstatus",
- ctlclkstatus(&clock_stat));
-
- for (i = 1; i <= CC_MAXCODE; i++)
- ctl_putclock(i, &clock_stat, 0);
- for (kv = clock_stat.kv_list; kv &&
- !(kv->flags & EOV); kv++)
- if (kv->flags & DEF)
- ctl_putdata(kv->text,
- strlen(kv->text), 0);
- free_varlist(clock_stat.kv_list);
- }
-#endif /* REFCLOCK */
- }
-
- /*
- * We're done, return.
- */
- ctl_flushpkt(0);
-}
-
-
-/*
- * ctl_clr_stats - clear stat counters
- */
-void
-ctl_clr_stats(void)
-{
- ctltimereset = current_time;
- numctlreq = 0;
- numctlbadpkts = 0;
- numctlresponses = 0;
- numctlfrags = 0;
- numctlerrors = 0;
- numctlfrags = 0;
- numctltooshort = 0;
- numctlinputresp = 0;
- numctlinputfrag = 0;
- numctlinputerr = 0;
- numctlbadoffset = 0;
- numctlbadversion = 0;
- numctldatatooshort = 0;
- numctlbadop = 0;
- numasyncmsgs = 0;
-}
-
-static u_long
-count_var(
- struct ctl_var *k
- )
-{
- register u_long c;
-
- if (!k)
- return (0);
-
- c = 0;
- while (!(k++->flags & EOV))
- c++;
- return (c);
-}
-
-char *
-add_var(
- struct ctl_var **kv,
- u_long size,
- u_short def
- )
-{
- register u_long c;
- register struct ctl_var *k;
-
- c = count_var(*kv);
-
- k = *kv;
- *kv = (struct ctl_var *)emalloc((c+2)*sizeof(struct ctl_var));
- if (k) {
- memmove((char *)*kv, (char *)k,
- sizeof(struct ctl_var)*c);
- free((char *)k);
- }
- (*kv)[c].code = (u_short) c;
- (*kv)[c].text = (char *)emalloc(size);
- (*kv)[c].flags = def;
- (*kv)[c+1].code = 0;
- (*kv)[c+1].text = (char *)0;
- (*kv)[c+1].flags = EOV;
- return (char *)(*kv)[c].text;
-}
-
-void
-set_var(
- struct ctl_var **kv,
- const char *data,
- u_long size,
- u_short def
- )
-{
- register struct ctl_var *k;
- register const char *s;
- register const char *t;
- char *td;
-
- if (!data || !size)
- return;
-
- k = *kv;
- if (k != NULL) {
- while (!(k->flags & EOV)) {
- s = data;
- t = k->text;
- if (t) {
- while (*t != '=' && *s - *t == 0) {
- s++;
- t++;
- }
- if (*s == *t && ((*t == '=') || !*t)) {
- free((void *)k->text);
- td = (char *)emalloc(size);
- memmove(td, data, size);
- k->text =td;
- k->flags = def;
- return;
- }
- } else {
- td = (char *)emalloc(size);
- memmove(td, data, size);
- k->text = td;
- k->flags = def;
- return;
- }
- k++;
- }
- }
- td = add_var(kv, size, def);
- memmove(td, data, size);
-}
-
-void
-set_sys_var(
- char *data,
- u_long size,
- u_short def
- )
-{
- set_var(&ext_sys_var, data, size, def);
-}
-
-void
-free_varlist(
- struct ctl_var *kv
- )
-{
- struct ctl_var *k;
- if (kv) {
- for (k = kv; !(k->flags & EOV); k++)
- free((void *)k->text);
- free((void *)kv);
- }
-}
OpenPOWER on IntegriCloud