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

📄 ntp_peer.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * ntp_peer.c - management of data maintained for peer associations */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#include <sys/types.h>#include "ntpd.h"#include "ntp_stdlib.h"#include <ntp_random.h>#ifdef OPENSSL#include "openssl/rand.h"#endif /* OPENSSL *//* *                  Table of valid association combinations *                  --------------------------------------- * *                             packet->mode * peer->mode      | UNSPEC  ACTIVE PASSIVE  CLIENT  SERVER  BCAST * ----------      | --------------------------------------------- * NO_PEER         |   e       1       0       1       1       1 * ACTIVE          |   e       1       1       0       0       0 * PASSIVE         |   e       1       e       0       0       0 * CLIENT          |   e       0       0       0       1       1 * SERVER          |   e       0       0       0       0       0 * BCAST	   |   e       0       0       0       0       0 * BCLIENT         |   e       0       0       0       e       1 * * One point to note here: a packet in BCAST mode can potentially match * a peer in CLIENT mode, but we that is a special case and we check for * that early in the decision process.  This avoids having to keep track * of what kind of associations are possible etc...  We actually * circumvent that problem by requiring that the first b(m)roadcast * received after the change back to BCLIENT mode sets the clock. */#define AM_MODES	7	/* number of rows and columns */#define NO_PEER		0	/* action when no peer is found */int AM[AM_MODES][AM_MODES] = {/*	{ UNSPEC,   ACTIVE,     PASSIVE,    CLIENT,     SERVER,     BCAST } *//*NONE*/{ AM_ERR, AM_NEWPASS, AM_NOMATCH, AM_FXMIT,   AM_MANYCAST, AM_NEWBCL},/*A*/	{ AM_ERR, AM_PROCPKT, AM_PROCPKT, AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},/*P*/	{ AM_ERR, AM_PROCPKT, AM_ERR,     AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},/*C*/	{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_PROCPKT,  AM_POSSBCL},/*S*/	{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},/*BCST*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},/*BCL*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH,  AM_PROCPKT},};#define MATCH_ASSOC(x,y)	AM[(x)][(y)]/* * These routines manage the allocation of memory to peer structures * and the maintenance of the peer hash table. The two main entry * points are findpeer(), which looks for matching peer sturctures in * the peer list, newpeer(), which allocates a new peer structure and * adds it to the list, and unpeer(), which demobilizes the association * and deallocates the structure. *//* * Peer hash tables */struct peer *peer_hash[NTP_HASH_SIZE];	/* peer hash table */int peer_hash_count[NTP_HASH_SIZE];	/* peers in each bucket */struct peer *assoc_hash[NTP_HASH_SIZE];	/* association ID hash table */int assoc_hash_count[NTP_HASH_SIZE];	/* peers in each bucket */static struct peer *peer_free;		/* peer structures free list */int peer_free_count;			/* count of free structures *//* * Association ID.  We initialize this value randomly, then assign a new * value every time the peer structure is incremented. */static associd_t current_association_ID; /* association ID *//* * Memory allocation watermarks. */#define	INIT_PEER_ALLOC		15	/* initialize for 15 peers */#define	INC_PEER_ALLOC		5	/* when run out, add 5 more *//* * Miscellaneous statistic counters which may be queried. */u_long peer_timereset;			/* time stat counters zeroed */u_long findpeer_calls;			/* calls to findpeer */u_long assocpeer_calls;			/* calls to findpeerbyassoc */u_long peer_allocations;		/* allocations from free list */u_long peer_demobilizations;		/* structs freed to free list */int total_peer_structs;			/* peer structs */int peer_associations;			/* mobilized associations */int peer_preempt;			/* preemptable associations */static struct peer init_peer_alloc[INIT_PEER_ALLOC]; /* init alloc */static	void	getmorepeermem	P((void));/* * init_peer - initialize peer data structures and counters * * N.B. We use the random number routine in here. It had better be * initialized prior to getting here. */voidinit_peer(void){	register int i;	/*	 * Clear hash table and counters.	 */	for (i = 0; i < NTP_HASH_SIZE; i++) {		peer_hash[i] = 0;		peer_hash_count[i] = 0;		assoc_hash[i] = 0;		assoc_hash_count[i] = 0;	}	/*	 * Clear stat counters	 */	findpeer_calls = peer_allocations = 0;	assocpeer_calls = peer_demobilizations = 0;	/*	 * Initialize peer memory.	 */	peer_free = 0;	for (i = 0; i < INIT_PEER_ALLOC; i++) {		init_peer_alloc[i].next = peer_free;		peer_free = &init_peer_alloc[i];	}	total_peer_structs = INIT_PEER_ALLOC;	peer_free_count = INIT_PEER_ALLOC;	/*	 * Initialize our first association ID	 */	while ((current_association_ID = ntp_random() & 0xffff) == 0);}/* * getmorepeermem - add more peer structures to the free list */static voidgetmorepeermem(void){	register int i;	register struct peer *peer;	peer = (struct peer *)emalloc(INC_PEER_ALLOC *	    sizeof(struct peer));	for (i = 0; i < INC_PEER_ALLOC; i++) {		peer->next = peer_free;		peer_free = peer;		peer++;	}	total_peer_structs += INC_PEER_ALLOC;	peer_free_count += INC_PEER_ALLOC;}/* * findexistingpeer - return a pointer to a peer in the hash table */struct peer *findexistingpeer(	struct sockaddr_storage *addr,	struct peer *start_peer,	int mode	){	register struct peer *peer;	/*	 * start_peer is included so we can locate instances of the	 * same peer through different interfaces in the hash table.	 */	if (start_peer == 0)		peer = peer_hash[NTP_HASH_ADDR(addr)];	else		peer = start_peer->next;		while (peer != 0) {		if (SOCKCMP(addr, &peer->srcadr)		    && NSRCPORT(addr) == NSRCPORT(&peer->srcadr)) {			if (mode == -1)				return (peer);			else if (peer->hmode == mode)				break;		}		peer = peer->next;	}	return (peer);}/* * findpeer - find and return a peer in the hash table. */struct peer *findpeer(	struct sockaddr_storage *srcadr,	struct interface *dstadr,	int	pkt_mode,	int	*action	){	register struct peer *peer;	int hash;	findpeer_calls++;	hash = NTP_HASH_ADDR(srcadr);	for (peer = peer_hash[hash]; peer != NULL; peer = peer->next) {		if (SOCKCMP(srcadr, &peer->srcadr) &&		    NSRCPORT(srcadr) == NSRCPORT(&peer->srcadr)) {			/*			 * if the association matching rules determine			 * that this is not a valid combination, then			 * look for the next valid peer association.			 */			*action = MATCH_ASSOC(peer->hmode, pkt_mode);			/*			 * if an error was returned, exit back right			 * here.			 */			if (*action == AM_ERR)				return ((struct peer *)0);			/*			 * if a match is found, we stop our search.			 */			if (*action != AM_NOMATCH)				break;		}	}	/*	 * If no matching association is found	 */	if (peer == 0) {		*action = MATCH_ASSOC(NO_PEER, pkt_mode);		return ((struct peer *)0);	}	peer->dstadr = dstadr;	return (peer);}/* * findpeerbyassocid - find and return a peer using his association ID */struct peer *findpeerbyassoc(	u_int assoc	){	register struct peer *peer;	int hash;	assocpeer_calls++;	hash = assoc & NTP_HASH_MASK;	for (peer = assoc_hash[hash]; peer != 0; peer =	    peer->ass_next) {		if (assoc == peer->associd)		    return (peer);	}	return (NULL);}/* * clear_all - flush all time values for all associations */voidclear_all(void){	struct peer *peer, *next_peer;	int n;	/*	 * This routine is called when the clock is stepped, and so all	 * previously saved time values are untrusted.	 */	for (n = 0; n < NTP_HASH_SIZE; n++) {		for (peer = peer_hash[n]; peer != 0; peer = next_peer) {			next_peer = peer->next;			if (!(peer->cast_flags & (MDF_ACAST | MDF_MCAST |			    MDF_BCAST))) {				peer->hpoll = peer->minpoll;				peer_clear(peer, "STEP");			}		}	}#ifdef DEBUG	if (debug)		printf("clear_all: at %lu\n", current_time);#endif}/* * unpeer - remove peer structure from hash table and free structure */voidunpeer(	struct peer *peer_to_remove	){	int hash;#ifdef OPENSSL	char	statstr[NTP_MAXSTRLEN]; /* statistics for filegen */	if (peer_to_remove->flags & FLAG_SKEY) {		sprintf(statstr, "unpeer %d flash %x reach %03o flags %04x",		    peer_to_remove->associd, peer_to_remove->flash,		    peer_to_remove->reach, peer_to_remove->flags);		record_crypto_stats(&peer_to_remove->srcadr, statstr);#ifdef DEBUG		if (debug)			printf("peer: %s\n", statstr);#endif	}#endif /* OPENSSL */#ifdef DEBUG	if (debug)		printf("demobilize %u %d %d\n", peer_to_remove->associd,		    peer_associations, peer_preempt);#endif	hash = NTP_HASH_ADDR(&peer_to_remove->srcadr);	peer_hash_count[hash]--;	peer_demobilizations++;	peer_associations--;	if (peer_to_remove->flags & FLAG_PREEMPT)		peer_preempt--;#ifdef REFCLOCK	/*	 * If this peer is actually a clock, shut it down first	 */	if (peer_to_remove->flags & FLAG_REFCLOCK)		refclock_unpeer(peer_to_remove);#endif	peer_to_remove->action = 0;	/* disable timeout actions */	if (peer_hash[hash] == peer_to_remove)		peer_hash[hash] = peer_to_remove->next;	else {		register struct peer *peer;		peer = peer_hash[hash];		while (peer != 0 && peer->next != peer_to_remove)		    peer = peer->next;				if (peer == 0) {			peer_hash_count[hash]++;			msyslog(LOG_ERR, "peer struct for %s not in table!",				stoa(&peer->srcadr));		} else {			peer->next = peer_to_remove->next;		}	}	/*	 * Remove him from the association hash as well.	 */	hash = peer_to_remove->associd & NTP_HASH_MASK;	assoc_hash_count[hash]--;	if (assoc_hash[hash] == peer_to_remove)		assoc_hash[hash] = peer_to_remove->ass_next;	else {		register struct peer *peer;		peer = assoc_hash[hash];		while (peer != 0 && peer->ass_next != peer_to_remove)		    peer = peer->ass_next;				if (peer == 0) {			assoc_hash_count[hash]++;			msyslog(LOG_ERR,				"peer struct for %s not in association table!",				stoa(&peer->srcadr));		} else {			peer->ass_next = peer_to_remove->ass_next;		}	}	peer_to_remove->next = peer_free;	peer_free = peer_to_remove;	peer_free_count++;}/* * peer_config - configure a new association */struct peer *peer_config(	struct sockaddr_storage *srcadr,	struct interface *dstadr,	int hmode,	int version,	int minpoll,	int maxpoll,	u_int flags,	int ttl,	keyid_t key,	u_char *keystr	){	register struct peer *peer;	u_char cast_flags;	/*	 * First search from the beginning for an association with given	 * remote address and mode. If an interface is given, search	 * from there to find the association which matches that	 * destination.	 */	peer = findexistingpeer(srcadr, (struct peer *)0, hmode);	if (dstadr != 0) {		while (peer != 0) {			if (peer->dstadr == dstadr)				break;			peer = findexistingpeer(srcadr, peer, hmode);		}	}	/*

⌨️ 快捷键说明

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