⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ntp_control.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * 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_unixtime.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 REFCLOCKstatic	u_short ctlclkstatus	P((struct refclockstat *));#endifstatic	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 *));static	void	ctl_putfs	P((const char *, tstamp_t));#ifdef REFCLOCKstatic	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_ERROR,	RO, "noise" },		/* 14 */	{ CS_CLOCK,	RO, "clock" },		/* 15 */	{ CS_PROCESSOR, RO, "processor" },	/* 16 */	{ CS_SYSTEM,	RO, "system" },		/* 17 */	{ CS_VERSION,	RO, "version" },	/* 18 */	{ CS_STABIL,	RO, "stability" },	/* 19 */	{ CS_VARLIST,	RO, "sys_var_list" },	/* 20 */#ifdef OPENSSL	{ CS_FLAGS,	RO, "flags" },		/* 21 */	{ CS_HOST,	RO, "hostname" },	/* 22 */	{ CS_PUBLIC,	RO, "update" },		/* 23 */	{ CS_CERTIF,	RO, "cert" },		/* 24 */	{ CS_REVTIME,	RO, "expire" },		/* 25 */	{ CS_LEAPTAB,	RO, "leapsec" },	/* 26 */	{ CS_TAI,	RO, "tai" },		/* 27 */	{ CS_DIGEST,	RO, "signature" },	/* 28 */	{ CS_IDENT,	RO, "ident" },		/* 29 */	{ CS_REVOKE,	RO, "expire" },		/* 30 */#endif /* OPENSSL */	{ 0,		EOV, "" }		/* 21/31 */};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_ERROR,	CS_STABIL,#ifdef OPENSSL	CS_HOST,	CS_DIGEST,	CS_FLAGS,	CS_PUBLIC,	CS_IDENT,	CS_LEAPTAB,	CS_TAI,	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_UNREACH,	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_VARLIST,	RO, "peer_var_list" },	/* 37 */#ifdef OPENSSL	{ CP_FLAGS,	RO, "flags" },		/* 38 */	{ CP_HOST,	RO, "hostname" },	/* 39 */	{ CP_VALID,	RO, "valid" },		/* 40 */	{ CP_INITSEQ,	RO, "initsequence" },   /* 41 */	{ CP_INITKEY,	RO, "initkey" },	/* 42 */	{ CP_INITTSP,	RO, "timestamp" },	/* 43 */	{ CP_DIGEST,	RO, "signature" },	/* 44 */	{ CP_IDENT,	RO, "trust" },		/* 45 */#endif /* OPENSSL */	{ 0,		EOV, "" }		/* 38/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_UNREACH,	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_VALID,	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"# endifstatic 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_NTP, 	/* not used (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_NTP,		/* not used (23) */	CTL_SST_TS_NTP,		/* not used (24) */	CTL_SST_TS_NTP, 	/* not used (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 (33) */	CTL_SST_TS_LF,		/* REFCLK_ULINK (34) */	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 */voidinit_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 voidctl_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 */voidprocess_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++;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -