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

📄 ntp_request.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * ntp_request.c - respond to information requests */#ifdef HAVE_CONFIG_H# include <config.h>#endif#include "ntpd.h"#include "ntp_io.h"#include "ntp_request.h"#include "ntp_control.h"#include "ntp_refclock.h"#include "ntp_if.h"#include "ntp_stdlib.h"#include <stdio.h>#include <stddef.h>#include <signal.h>#include <netinet/in.h>#include <arpa/inet.h>#include "recvbuff.h"#ifdef KERNEL_PLL#include "ntp_syscall.h"#endif /* KERNEL_PLL *//* * Structure to hold request procedure information */#define	NOAUTH	0#define	AUTH	1#define	NO_REQUEST	(-1)/* * Because we now have v6 addresses in the messages, we need to compensate * for the larger size.  Therefore, we introduce the alternate size to  * keep us friendly with older implementations.  A little ugly. */static int client_v6_capable = 0;   /* the client can handle longer messages */#define v6sizeof(type)	(client_v6_capable ? sizeof(type) : v4sizeof(type))struct req_proc {	short request_code;	/* defined request code */	short needs_auth;	/* true when authentication needed */	short sizeofitem;	/* size of request data item (older size)*/	short v6_sizeofitem;	/* size of request data item (new size)*/	void (*handler) P((struct sockaddr_storage *, struct interface *,			   struct req_pkt *));	/* routine to handle request */};/* * Universal request codes */static	struct req_proc univ_codes[] = {	{ NO_REQUEST,		NOAUTH,	 0,	0 }};static	void	req_ack	P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int));static	char *	prepare_pkt	P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_int));static	char *	more_pkt	P((void));static	void	flush_pkt	P((void));static	void	peer_list	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	peer_list_sum	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	peer_info	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	peer_stats	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	sys_info	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	sys_stats	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	mem_stats	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	io_stats	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	timer_stats	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	loop_info	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	do_conf		P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	do_unconf	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	set_sys_flag	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	clr_sys_flag	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	setclr_flags	P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_long));static	void	list_restrict	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	do_resaddflags	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	do_ressubflags	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	do_unrestrict	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	do_restrict	P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int));static	void	mon_getlist_0	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	mon_getlist_1	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	reset_stats	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	reset_peer	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	do_key_reread	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	trust_key	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	untrust_key	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	do_trustkey	P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_long));static	void	get_auth_info	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	reset_auth_stats P((void));static	void	req_get_traps	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	req_set_trap	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	req_clr_trap	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	do_setclr_trap	P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int));static	void	set_request_keyid P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	set_control_keyid P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	get_ctl_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *));#ifdef KERNEL_PLLstatic	void	get_kernel_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));#endif /* KERNEL_PLL */#ifdef REFCLOCKstatic	void	get_clock_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));static	void	set_clock_fudge P((struct sockaddr_storage *, struct interface *, struct req_pkt *));#endif	/* REFCLOCK */#ifdef REFCLOCKstatic	void	get_clkbug_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));#endif	/* REFCLOCK *//* * ntpd request codes */static	struct req_proc ntp_codes[] = {	{ REQ_PEER_LIST,	NOAUTH,	0, 0,	peer_list },	{ REQ_PEER_LIST_SUM,	NOAUTH,	0, 0,	peer_list_sum },	{ REQ_PEER_INFO,    NOAUTH, v4sizeof(struct info_peer_list),				sizeof(struct info_peer_list), peer_info},	{ REQ_PEER_STATS,   NOAUTH, v4sizeof(struct info_peer_list),				sizeof(struct info_peer_list), peer_stats},	{ REQ_SYS_INFO,		NOAUTH,	0, 0,	sys_info },	{ REQ_SYS_STATS,	NOAUTH,	0, 0,	sys_stats },	{ REQ_IO_STATS,		NOAUTH,	0, 0,	io_stats },	{ REQ_MEM_STATS,	NOAUTH,	0, 0,	mem_stats },	{ REQ_LOOP_INFO,	NOAUTH,	0, 0,	loop_info },	{ REQ_TIMER_STATS,	NOAUTH,	0, 0,	timer_stats },	{ REQ_CONFIG,	    AUTH, v4sizeof(struct conf_peer),				sizeof(struct conf_peer), do_conf },	{ REQ_UNCONFIG,	    AUTH, v4sizeof(struct conf_unpeer),				sizeof(struct conf_unpeer), do_unconf },	{ REQ_SET_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags),				sizeof(struct conf_sys_flags), set_sys_flag },	{ REQ_CLR_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags), 				sizeof(struct conf_sys_flags),  clr_sys_flag },	{ REQ_GET_RESTRICT,	NOAUTH,	0, 0,	list_restrict },	{ REQ_RESADDFLAGS, AUTH, v4sizeof(struct conf_restrict),				sizeof(struct conf_restrict), do_resaddflags },	{ REQ_RESSUBFLAGS, AUTH, v4sizeof(struct conf_restrict),				sizeof(struct conf_restrict), do_ressubflags },	{ REQ_UNRESTRICT, AUTH, v4sizeof(struct conf_restrict),				sizeof(struct conf_restrict), do_unrestrict },	{ REQ_MON_GETLIST,	NOAUTH,	0, 0,	mon_getlist_0 },	{ REQ_MON_GETLIST_1,	NOAUTH,	0, 0,	mon_getlist_1 },	{ REQ_RESET_STATS, AUTH, sizeof(struct reset_flags), 0, reset_stats },	{ REQ_RESET_PEER,  AUTH, v4sizeof(struct conf_unpeer),				sizeof(struct conf_unpeer), reset_peer },	{ REQ_REREAD_KEYS,	AUTH,	0, 0,	do_key_reread },	{ REQ_TRUSTKEY,   AUTH, sizeof(u_long), sizeof(u_long), trust_key },	{ REQ_UNTRUSTKEY, AUTH, sizeof(u_long), sizeof(u_long), untrust_key },	{ REQ_AUTHINFO,		NOAUTH,	0, 0,	get_auth_info },	{ REQ_TRAPS,		NOAUTH, 0, 0,	req_get_traps },	{ REQ_ADD_TRAP,	AUTH, v4sizeof(struct conf_trap),				sizeof(struct conf_trap), req_set_trap },	{ REQ_CLR_TRAP,	AUTH, v4sizeof(struct conf_trap),				sizeof(struct conf_trap), req_clr_trap },	{ REQ_REQUEST_KEY, AUTH, sizeof(u_long), sizeof(u_long), 				set_request_keyid },	{ REQ_CONTROL_KEY, AUTH, sizeof(u_long), sizeof(u_long), 				set_control_keyid },	{ REQ_GET_CTLSTATS,	NOAUTH,	0, 0,	get_ctl_stats },#ifdef KERNEL_PLL	{ REQ_GET_KERNEL,	NOAUTH,	0, 0,	get_kernel_info },#endif#ifdef REFCLOCK	{ REQ_GET_CLOCKINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32), 				get_clock_info },	{ REQ_SET_CLKFUDGE, AUTH, sizeof(struct conf_fudge), 				sizeof(struct conf_fudge), set_clock_fudge },	{ REQ_GET_CLKBUGINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32),				get_clkbug_info },#endif	{ NO_REQUEST,		NOAUTH,	0, 0,	0 }};/* * Authentication keyid used to authenticate requests.  Zero means we * don't allow writing anything. */keyid_t info_auth_keyid;/* * Statistic counters to keep track of requests and responses. */u_long numrequests;		/* number of requests we've received */u_long numresppkts;		/* number of resp packets sent with data */u_long errorcounter[INFO_ERR_AUTH+1];	/* lazy way to count errors, indexed *//* by the error code *//* * A hack.  To keep the authentication module clear of ntp-ism's, we * include a time reset variable for its stats here. */static u_long auth_timereset;/* * 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 resp_pkt rpkt;static int reqver;static int seqno;static int nitems;static int itemsize;static int databytes;static char exbuf[RESP_DATA_SIZE];static int usingexbuf;static struct sockaddr_storage *toaddr;static struct interface *frominter;/* * init_request - initialize request data */voidinit_request (void){	int i;	numrequests = 0;	numresppkts = 0;	auth_timereset = 0;	info_auth_keyid = 0;	/* by default, can't do this */	for (i = 0; i < sizeof(errorcounter)/sizeof(errorcounter[0]); i++)	    errorcounter[i] = 0;}/* * req_ack - acknowledge request with no data */static voidreq_ack(	struct sockaddr_storage *srcadr,	struct interface *inter,	struct req_pkt *inpkt,	int errcode	){	/*	 * fill in the fields	 */	rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver);	rpkt.auth_seq = AUTH_SEQ(0, 0);	rpkt.implementation = inpkt->implementation;	rpkt.request = inpkt->request;	rpkt.err_nitems = ERR_NITEMS(errcode, 0);	rpkt.mbz_itemsize = MBZ_ITEMSIZE(0);	/*	 * send packet and bump counters	 */	sendpkt(srcadr, inter, -1, (struct pkt *)&rpkt, RESP_HEADER_SIZE);	errorcounter[errcode]++;}/* * prepare_pkt - prepare response packet for transmission, return pointer *		 to storage for data item. */static char *prepare_pkt(	struct sockaddr_storage *srcadr,	struct interface *inter,	struct req_pkt *pkt,	u_int structsize	){#ifdef DEBUG	if (debug > 3)	    printf("request: preparing pkt\n");#endif	/*	 * Fill in the implementation, request and itemsize fields	 * since these won't change.	 */	rpkt.implementation = pkt->implementation;	rpkt.request = pkt->request;	rpkt.mbz_itemsize = MBZ_ITEMSIZE(structsize);	/*	 * Compute the static data needed to carry on.	 */	toaddr = srcadr;	frominter = inter;	seqno = 0;	nitems = 0;	itemsize = structsize;	databytes = 0;	usingexbuf = 0;	/*	 * return the beginning of the packet buffer.	 */	return &rpkt.data[0];}/* * more_pkt - return a data pointer for a new item. */static char *more_pkt(void){	/*	 * If we were using the extra buffer, send the packet.	 */	if (usingexbuf) {#ifdef DEBUG		if (debug > 2)		    printf("request: sending pkt\n");#endif		rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, MORE_BIT, reqver);		rpkt.auth_seq = AUTH_SEQ(0, seqno);		rpkt.err_nitems = htons((u_short)nitems);		sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt,			RESP_HEADER_SIZE+databytes);		numresppkts++;		/*		 * Copy data out of exbuf into the packet.		 */		memmove(&rpkt.data[0], exbuf, (unsigned)itemsize);		seqno++;		databytes = 0;		nitems = 0;		usingexbuf = 0;	}	databytes += itemsize;	nitems++;	if (databytes + itemsize <= RESP_DATA_SIZE) {#ifdef DEBUG		if (debug > 3)		    printf("request: giving him more data\n");#endif		/*		 * More room in packet.  Give him the		 * next address.		 */		return &rpkt.data[databytes];	} else {		/*		 * No room in packet.  Give him the extra		 * buffer unless this was the last in the sequence.		 */#ifdef DEBUG		if (debug > 3)		    printf("request: into extra buffer\n");#endif		if (seqno == MAXSEQ)		    return (char *)0;		else {			usingexbuf = 1;			return exbuf;		}	}}/* * flush_pkt - we're done, return remaining information. */static voidflush_pkt(void){#ifdef DEBUG	if (debug > 2)	    printf("request: flushing packet, %d items\n", nitems);#endif	/*	 * Must send the last packet.  If nothing in here and nothing	 * has been sent, send an error saying no data to be found.	 */	if (seqno == 0 && nitems == 0)	    req_ack(toaddr, frominter, (struct req_pkt *)&rpkt,		    INFO_ERR_NODATA);	else {		rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver);		rpkt.auth_seq = AUTH_SEQ(0, seqno);		rpkt.err_nitems = htons((u_short)nitems);		sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt,			RESP_HEADER_SIZE+databytes);		numresppkts++;	}}/* * process_private - process private mode (7) packets */voidprocess_private(	struct recvbuf *rbufp,	int mod_okay	){	struct req_pkt *inpkt;	struct req_pkt_tail *tailinpkt;	struct sockaddr_storage *srcadr;	struct interface *inter;	struct req_proc *proc;	int ec;	short temp_size;	/*	 * Initialize pointers, for convenience	 */	inpkt = (struct req_pkt *)&rbufp->recv_pkt;	srcadr = &rbufp->recv_srcadr;	inter = rbufp->dstadr;#ifdef DEBUG	if (debug > 2)	    printf("process_private: impl %d req %d\n",		   inpkt->implementation, inpkt->request);#endif	/*	 * Do some sanity checks on the packet.  Return a format	 * error if it fails.	 */	ec = 0;	if (   (++ec, ISRESPONSE(inpkt->rm_vn_mode))	    || (++ec, ISMORE(inpkt->rm_vn_mode))	    || (++ec, INFO_VERSION(inpkt->rm_vn_mode) > NTP_VERSION)	    || (++ec, INFO_VERSION(inpkt->rm_vn_mode) < NTP_OLDVERSION)	    || (++ec, INFO_SEQ(inpkt->auth_seq) != 0)	    || (++ec, INFO_ERR(inpkt->err_nitems) != 0)	    || (++ec, INFO_MBZ(inpkt->mbz_itemsize) != 0)	    || (++ec, rbufp->recv_length < REQ_LEN_HDR)		) {		msyslog(LOG_ERR, "process_private: INFO_ERR_FMT: test %d failed, pkt from %s", ec, stoa(srcadr));		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);		return;	}	reqver = INFO_VERSION(inpkt->rm_vn_mode);	/*	 * Get the appropriate procedure list to search.	 */	if (inpkt->implementation == IMPL_UNIV)	    proc = univ_codes;	else if ((inpkt->implementation == IMPL_XNTPD) ||		 (inpkt->implementation == IMPL_XNTPD_OLD))	    proc = ntp_codes;	else {		req_ack(srcadr, inter, inpkt, INFO_ERR_IMPL);		return;	}	/*	 * Search the list for the request codes.  If it isn't one	 * we know, return an error.	 */	while (proc->request_code != NO_REQUEST) {		if (proc->request_code == (short) inpkt->request)		    break;		proc++;	}	if (proc->request_code == NO_REQUEST) {		req_ack(srcadr, inter, inpkt, INFO_ERR_REQ);		return;	}#ifdef DEBUG	if (debug > 3)	    printf("found request in tables\n");#endif	/*	 * If we need data, check to see if we have some.  If we	 * don't, check to see that there is none (picky, picky).	 */		/* This part is a bit tricky, we want to be sure that the size	 * returned is either the old or the new size.  We also can find	 * out if the client can accept both types of messages this way. 	 *	 * Handle the exception of REQ_CONFIG. It can have two data sizes.	 */	temp_size = INFO_ITEMSIZE(inpkt->mbz_itemsize);	if ((temp_size != proc->sizeofitem &&	    temp_size != proc->v6_sizeofitem) &&	    !(inpkt->implementation == IMPL_XNTPD &&	    inpkt->request == REQ_CONFIG &&	    temp_size == sizeof(struct old_conf_peer))) {#ifdef DEBUG		if (debug > 2)			printf("process_private: wrong item size, received %d, should be %d or %d\n",			    temp_size, proc->sizeofitem, proc->v6_sizeofitem);

⌨️ 快捷键说明

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