Home | History | Annotate | Line # | Download | only in ntpd
ntp_peer.c revision 1.6
      1  1.6  christos /*	$NetBSD: ntp_peer.c,v 1.6 2015/04/07 17:34:19 christos Exp $	*/
      2  1.1    kardel 
      3  1.1    kardel /*
      4  1.1    kardel  * ntp_peer.c - management of data maintained for peer associations
      5  1.1    kardel  */
      6  1.1    kardel #ifdef HAVE_CONFIG_H
      7  1.1    kardel #include <config.h>
      8  1.1    kardel #endif
      9  1.1    kardel 
     10  1.1    kardel #include <stdio.h>
     11  1.1    kardel #include <sys/types.h>
     12  1.1    kardel 
     13  1.1    kardel #include "ntpd.h"
     14  1.1    kardel #include "ntp_lists.h"
     15  1.1    kardel #include "ntp_stdlib.h"
     16  1.1    kardel #include "ntp_control.h"
     17  1.1    kardel #include <ntp_random.h>
     18  1.1    kardel 
     19  1.1    kardel /*
     20  1.4  christos  *		    Table of valid association combinations
     21  1.4  christos  *		    ---------------------------------------
     22  1.1    kardel  *
     23  1.1    kardel  *                             packet->mode
     24  1.1    kardel  * peer->mode      | UNSPEC  ACTIVE PASSIVE  CLIENT  SERVER  BCAST
     25  1.1    kardel  * ----------      | ---------------------------------------------
     26  1.1    kardel  * NO_PEER         |   e       1       0       1       1       1
     27  1.1    kardel  * ACTIVE          |   e       1       1       0       0       0
     28  1.1    kardel  * PASSIVE         |   e       1       e       0       0       0
     29  1.1    kardel  * CLIENT          |   e       0       0       0       1       0
     30  1.1    kardel  * SERVER          |   e       0       0       0       0       0
     31  1.1    kardel  * BCAST           |   e       0       0       0       0       0
     32  1.1    kardel  * BCLIENT         |   e       0       0       0       e       1
     33  1.1    kardel  *
     34  1.1    kardel  * One point to note here: a packet in BCAST mode can potentially match
     35  1.1    kardel  * a peer in CLIENT mode, but we that is a special case and we check for
     36  1.1    kardel  * that early in the decision process.  This avoids having to keep track
     37  1.1    kardel  * of what kind of associations are possible etc...  We actually
     38  1.1    kardel  * circumvent that problem by requiring that the first b(m)roadcast
     39  1.1    kardel  * received after the change back to BCLIENT mode sets the clock.
     40  1.1    kardel  */
     41  1.1    kardel #define AM_MODES	7	/* number of rows and columns */
     42  1.1    kardel #define NO_PEER		0	/* action when no peer is found */
     43  1.1    kardel 
     44  1.1    kardel int AM[AM_MODES][AM_MODES] = {
     45  1.4  christos /*			packet->mode					    */
     46  1.4  christos /* peer { UNSPEC,   ACTIVE,     PASSIVE,    CLIENT,     SERVER,     BCAST } */
     47  1.4  christos /* mode */
     48  1.1    kardel /*NONE*/{ AM_ERR, AM_NEWPASS, AM_NOMATCH, AM_FXMIT,   AM_MANYCAST, AM_NEWBCL},
     49  1.1    kardel 
     50  1.1    kardel /*A*/	{ AM_ERR, AM_PROCPKT, AM_PROCPKT, AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},
     51  1.1    kardel 
     52  1.1    kardel /*P*/	{ AM_ERR, AM_PROCPKT, AM_ERR,     AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},
     53  1.1    kardel 
     54  1.1    kardel /*C*/	{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_PROCPKT,  AM_NOMATCH},
     55  1.1    kardel 
     56  1.1    kardel /*S*/	{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},
     57  1.1    kardel 
     58  1.1    kardel /*BCST*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},
     59  1.1    kardel 
     60  1.1    kardel /*BCL*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH,  AM_PROCPKT},
     61  1.1    kardel };
     62  1.1    kardel 
     63  1.1    kardel #define MATCH_ASSOC(x, y)	AM[(x)][(y)]
     64  1.1    kardel 
     65  1.1    kardel /*
     66  1.1    kardel  * These routines manage the allocation of memory to peer structures
     67  1.4  christos  * and the maintenance of three data structures involving all peers:
     68  1.4  christos  *
     69  1.4  christos  * - peer_list is a single list with all peers, suitable for scanning
     70  1.4  christos  *   operations over all peers.
     71  1.4  christos  * - peer_adr_hash is an array of lists indexed by hashed peer address.
     72  1.4  christos  * - peer_aid_hash is an array of lists indexed by hashed associd.
     73  1.4  christos  *
     74  1.4  christos  * They also maintain a free list of peer structures, peer_free.
     75  1.4  christos  *
     76  1.4  christos  * The three main entry points are findpeer(), which looks for matching
     77  1.4  christos  * peer structures in the peer list, newpeer(), which allocates a new
     78  1.4  christos  * peer structure and adds it to the list, and unpeer(), which
     79  1.4  christos  * demobilizes the association and deallocates the structure.
     80  1.1    kardel  */
     81  1.1    kardel /*
     82  1.1    kardel  * Peer hash tables
     83  1.1    kardel  */
     84  1.1    kardel struct peer *peer_hash[NTP_HASH_SIZE];	/* peer hash table */
     85  1.1    kardel int	peer_hash_count[NTP_HASH_SIZE];	/* peers in each bucket */
     86  1.1    kardel struct peer *assoc_hash[NTP_HASH_SIZE];	/* association ID hash table */
     87  1.4  christos int	assoc_hash_count[NTP_HASH_SIZE];/* peers in each bucket */
     88  1.4  christos struct peer *peer_list;			/* peer structures list */
     89  1.1    kardel static struct peer *peer_free;		/* peer structures free list */
     90  1.1    kardel int	peer_free_count;		/* count of free structures */
     91  1.1    kardel 
     92  1.1    kardel /*
     93  1.1    kardel  * Association ID.  We initialize this value randomly, then assign a new
     94  1.4  christos  * value every time an association is mobilized.
     95  1.1    kardel  */
     96  1.1    kardel static associd_t current_association_ID; /* association ID */
     97  1.6  christos static associd_t initial_association_ID; /* association ID */
     98  1.1    kardel 
     99  1.1    kardel /*
    100  1.1    kardel  * Memory allocation watermarks.
    101  1.1    kardel  */
    102  1.4  christos #define	INIT_PEER_ALLOC		8	/* static preallocation */
    103  1.4  christos #define	INC_PEER_ALLOC		4	/* add N more when empty */
    104  1.1    kardel 
    105  1.1    kardel /*
    106  1.1    kardel  * Miscellaneous statistic counters which may be queried.
    107  1.1    kardel  */
    108  1.1    kardel u_long	peer_timereset;			/* time stat counters zeroed */
    109  1.1    kardel u_long	findpeer_calls;			/* calls to findpeer */
    110  1.1    kardel u_long	assocpeer_calls;		/* calls to findpeerbyassoc */
    111  1.1    kardel u_long	peer_allocations;		/* allocations from free list */
    112  1.1    kardel u_long	peer_demobilizations;		/* structs freed to free list */
    113  1.1    kardel int	total_peer_structs;		/* peer structs */
    114  1.1    kardel int	peer_associations;		/* mobilized associations */
    115  1.1    kardel int	peer_preempt;			/* preemptable associations */
    116  1.1    kardel static struct peer init_peer_alloc[INIT_PEER_ALLOC]; /* init alloc */
    117  1.1    kardel 
    118  1.4  christos static struct peer *	findexistingpeer_name(const char *, u_short,
    119  1.4  christos 					      struct peer *, int);
    120  1.4  christos static struct peer *	findexistingpeer_addr(sockaddr_u *,
    121  1.4  christos 					      struct peer *, int,
    122  1.4  christos 					      u_char);
    123  1.4  christos static void		free_peer(struct peer *, int);
    124  1.4  christos static void		getmorepeermem(void);
    125  1.4  christos static int		score(struct peer *);
    126  1.1    kardel 
    127  1.1    kardel 
    128  1.1    kardel /*
    129  1.1    kardel  * init_peer - initialize peer data structures and counters
    130  1.1    kardel  *
    131  1.1    kardel  * N.B. We use the random number routine in here. It had better be
    132  1.1    kardel  * initialized prior to getting here.
    133  1.1    kardel  */
    134  1.1    kardel void
    135  1.1    kardel init_peer(void)
    136  1.1    kardel {
    137  1.4  christos 	int i;
    138  1.1    kardel 
    139  1.1    kardel 	/*
    140  1.4  christos 	 * Initialize peer free list from static allocation.
    141  1.1    kardel 	 */
    142  1.4  christos 	for (i = COUNTOF(init_peer_alloc) - 1; i >= 0; i--)
    143  1.4  christos 		LINK_SLIST(peer_free, &init_peer_alloc[i], p_link);
    144  1.4  christos 	total_peer_structs = COUNTOF(init_peer_alloc);
    145  1.4  christos 	peer_free_count = COUNTOF(init_peer_alloc);
    146  1.1    kardel 
    147  1.1    kardel 	/*
    148  1.1    kardel 	 * Initialize our first association ID
    149  1.1    kardel 	 */
    150  1.4  christos 	do
    151  1.4  christos 		current_association_ID = ntp_random() & ASSOCID_MAX;
    152  1.4  christos 	while (!current_association_ID);
    153  1.6  christos 	initial_association_ID = current_association_ID;
    154  1.1    kardel }
    155  1.1    kardel 
    156  1.1    kardel 
    157  1.1    kardel /*
    158  1.1    kardel  * getmorepeermem - add more peer structures to the free list
    159  1.1    kardel  */
    160  1.1    kardel static void
    161  1.1    kardel getmorepeermem(void)
    162  1.1    kardel {
    163  1.4  christos 	int i;
    164  1.4  christos 	struct peer *peers;
    165  1.1    kardel 
    166  1.4  christos 	peers = emalloc_zero(INC_PEER_ALLOC * sizeof(*peers));
    167  1.4  christos 
    168  1.4  christos 	for (i = INC_PEER_ALLOC - 1; i >= 0; i--)
    169  1.4  christos 		LINK_SLIST(peer_free, &peers[i], p_link);
    170  1.1    kardel 
    171  1.1    kardel 	total_peer_structs += INC_PEER_ALLOC;
    172  1.1    kardel 	peer_free_count += INC_PEER_ALLOC;
    173  1.1    kardel }
    174  1.1    kardel 
    175  1.1    kardel 
    176  1.4  christos static struct peer *
    177  1.4  christos findexistingpeer_name(
    178  1.4  christos 	const char *	hostname,
    179  1.4  christos 	u_short		hname_fam,
    180  1.4  christos 	struct peer *	start_peer,
    181  1.4  christos 	int		mode
    182  1.4  christos 	)
    183  1.4  christos {
    184  1.4  christos 	struct peer *p;
    185  1.4  christos 
    186  1.4  christos 	if (NULL == start_peer)
    187  1.4  christos 		p = peer_list;
    188  1.4  christos 	else
    189  1.4  christos 		p = start_peer->p_link;
    190  1.4  christos 	for (; p != NULL; p = p->p_link)
    191  1.4  christos 		if (p->hostname != NULL
    192  1.4  christos 		    && (-1 == mode || p->hmode == mode)
    193  1.4  christos 		    && (AF_UNSPEC == hname_fam
    194  1.4  christos 			|| AF_UNSPEC == AF(&p->srcadr)
    195  1.4  christos 			|| hname_fam == AF(&p->srcadr))
    196  1.4  christos 		    && !strcasecmp(p->hostname, hostname))
    197  1.4  christos 			break;
    198  1.4  christos 	return p;
    199  1.4  christos }
    200  1.4  christos 
    201  1.4  christos 
    202  1.4  christos static
    203  1.4  christos struct peer *
    204  1.4  christos findexistingpeer_addr(
    205  1.3    kardel 	sockaddr_u *	addr,
    206  1.3    kardel 	struct peer *	start_peer,
    207  1.3    kardel 	int		mode,
    208  1.3    kardel 	u_char		cast_flags
    209  1.1    kardel 	)
    210  1.1    kardel {
    211  1.4  christos 	struct peer *peer;
    212  1.4  christos 
    213  1.4  christos 	DPRINTF(2, ("findexistingpeer_addr(%s, %s, %d, 0x%x)\n",
    214  1.4  christos 		sptoa(addr),
    215  1.4  christos 		(start_peer)
    216  1.4  christos 		    ? sptoa(&start_peer->srcadr)
    217  1.4  christos 		    : "NULL",
    218  1.4  christos 		mode, (u_int)cast_flags));
    219  1.1    kardel 
    220  1.1    kardel 	/*
    221  1.1    kardel 	 * start_peer is included so we can locate instances of the
    222  1.1    kardel 	 * same peer through different interfaces in the hash table.
    223  1.3    kardel 	 * Without MDF_BCLNT, a match requires the same mode and remote
    224  1.3    kardel 	 * address.  MDF_BCLNT associations start out as MODE_CLIENT
    225  1.3    kardel 	 * if broadcastdelay is not specified, and switch to
    226  1.3    kardel 	 * MODE_BCLIENT after estimating the one-way delay.  Duplicate
    227  1.3    kardel 	 * associations are expanded in definition to match any other
    228  1.3    kardel 	 * MDF_BCLNT with the same srcadr (remote, unicast address).
    229  1.1    kardel 	 */
    230  1.1    kardel 	if (NULL == start_peer)
    231  1.1    kardel 		peer = peer_hash[NTP_HASH_ADDR(addr)];
    232  1.1    kardel 	else
    233  1.4  christos 		peer = start_peer->adr_link;
    234  1.1    kardel 
    235  1.1    kardel 	while (peer != NULL) {
    236  1.4  christos 		DPRINTF(3, ("%s %s %d %d 0x%x 0x%x ", sptoa(addr),
    237  1.4  christos 			sptoa(&peer->srcadr), mode, peer->hmode,
    238  1.4  christos 			(u_int)cast_flags, (u_int)peer->cast_flags));
    239  1.4  christos  		if ((-1 == mode || peer->hmode == mode ||
    240  1.4  christos 		     ((MDF_BCLNT & peer->cast_flags) &&
    241  1.4  christos 		      (MDF_BCLNT & cast_flags))) &&
    242  1.4  christos 		    ADDR_PORT_EQ(addr, &peer->srcadr)) {
    243  1.4  christos 			DPRINTF(3, ("found.\n"));
    244  1.1    kardel 			break;
    245  1.4  christos 		}
    246  1.4  christos 		DPRINTF(3, ("\n"));
    247  1.4  christos 		peer = peer->adr_link;
    248  1.1    kardel 	}
    249  1.3    kardel 
    250  1.3    kardel 	return peer;
    251  1.1    kardel }
    252  1.1    kardel 
    253  1.1    kardel 
    254  1.1    kardel /*
    255  1.4  christos  * findexistingpeer - search by address and return a pointer to a peer.
    256  1.4  christos  */
    257  1.4  christos struct peer *
    258  1.4  christos findexistingpeer(
    259  1.4  christos 	sockaddr_u *	addr,
    260  1.4  christos 	const char *	hostname,
    261  1.4  christos 	struct peer *	start_peer,
    262  1.4  christos 	int		mode,
    263  1.4  christos 	u_char		cast_flags
    264  1.4  christos 	)
    265  1.4  christos {
    266  1.4  christos 	if (hostname != NULL)
    267  1.4  christos 		return findexistingpeer_name(hostname, AF(addr),
    268  1.4  christos 					     start_peer, mode);
    269  1.4  christos 	else
    270  1.4  christos 		return findexistingpeer_addr(addr, start_peer, mode,
    271  1.4  christos 					     cast_flags);
    272  1.4  christos }
    273  1.4  christos 
    274  1.4  christos 
    275  1.4  christos /*
    276  1.3    kardel  * findpeer - find and return a peer match for a received datagram in
    277  1.3    kardel  *	      the peer_hash table.
    278  1.1    kardel  */
    279  1.1    kardel struct peer *
    280  1.1    kardel findpeer(
    281  1.3    kardel 	struct recvbuf *rbufp,
    282  1.3    kardel 	int		pkt_mode,
    283  1.3    kardel 	int *		action
    284  1.1    kardel 	)
    285  1.1    kardel {
    286  1.3    kardel 	struct peer *	p;
    287  1.3    kardel 	sockaddr_u *	srcadr;
    288  1.3    kardel 	u_int		hash;
    289  1.3    kardel 	struct pkt *	pkt;
    290  1.3    kardel 	l_fp		pkt_org;
    291  1.1    kardel 
    292  1.1    kardel 	findpeer_calls++;
    293  1.3    kardel 	srcadr = &rbufp->recv_srcadr;
    294  1.1    kardel 	hash = NTP_HASH_ADDR(srcadr);
    295  1.4  christos 	for (p = peer_hash[hash]; p != NULL; p = p->adr_link) {
    296  1.4  christos 		if (ADDR_PORT_EQ(srcadr, &p->srcadr)) {
    297  1.1    kardel 
    298  1.1    kardel 			/*
    299  1.1    kardel 			 * if the association matching rules determine
    300  1.1    kardel 			 * that this is not a valid combination, then
    301  1.1    kardel 			 * look for the next valid peer association.
    302  1.1    kardel 			 */
    303  1.3    kardel 			*action = MATCH_ASSOC(p->hmode, pkt_mode);
    304  1.3    kardel 
    305  1.3    kardel 			/*
    306  1.3    kardel 			 * A response to our manycastclient solicitation
    307  1.3    kardel 			 * might be misassociated with an ephemeral peer
    308  1.3    kardel 			 * already spun for the server.  If the packet's
    309  1.3    kardel 			 * org timestamp doesn't match the peer's, check
    310  1.3    kardel 			 * if it matches the ACST prototype peer's.  If
    311  1.3    kardel 			 * so it is a redundant solicitation response,
    312  1.3    kardel 			 * return AM_ERR to discard it.  [Bug 1762]
    313  1.3    kardel 			 */
    314  1.3    kardel 			if (MODE_SERVER == pkt_mode &&
    315  1.3    kardel 			    AM_PROCPKT == *action) {
    316  1.3    kardel 				pkt = &rbufp->recv_pkt;
    317  1.3    kardel 				NTOHL_FP(&pkt->org, &pkt_org);
    318  1.3    kardel 				if (!L_ISEQU(&p->aorg, &pkt_org) &&
    319  1.3    kardel 				    findmanycastpeer(rbufp))
    320  1.3    kardel 					*action = AM_ERR;
    321  1.3    kardel 			}
    322  1.1    kardel 
    323  1.1    kardel 			/*
    324  1.1    kardel 			 * if an error was returned, exit back right
    325  1.1    kardel 			 * here.
    326  1.1    kardel 			 */
    327  1.1    kardel 			if (*action == AM_ERR)
    328  1.3    kardel 				return NULL;
    329  1.1    kardel 
    330  1.1    kardel 			/*
    331  1.1    kardel 			 * if a match is found, we stop our search.
    332  1.1    kardel 			 */
    333  1.1    kardel 			if (*action != AM_NOMATCH)
    334  1.1    kardel 				break;
    335  1.1    kardel 		}
    336  1.1    kardel 	}
    337  1.1    kardel 
    338  1.1    kardel 	/*
    339  1.1    kardel 	 * If no matching association is found
    340  1.1    kardel 	 */
    341  1.3    kardel 	if (NULL == p) {
    342  1.1    kardel 		*action = MATCH_ASSOC(NO_PEER, pkt_mode);
    343  1.3    kardel 	} else if (p->dstadr != rbufp->dstadr) {
    344  1.3    kardel 		set_peerdstadr(p, rbufp->dstadr);
    345  1.3    kardel 		if (p->dstadr == rbufp->dstadr) {
    346  1.3    kardel 			DPRINTF(1, ("Changed %s local address to match response\n",
    347  1.3    kardel 				    stoa(&p->srcadr)));
    348  1.3    kardel 			return findpeer(rbufp, pkt_mode, action);
    349  1.3    kardel 		}
    350  1.1    kardel 	}
    351  1.3    kardel 	return p;
    352  1.1    kardel }
    353  1.1    kardel 
    354  1.1    kardel /*
    355  1.4  christos  * findpeerbyassoc - find and return a peer using his association ID
    356  1.1    kardel  */
    357  1.1    kardel struct peer *
    358  1.1    kardel findpeerbyassoc(
    359  1.4  christos 	associd_t assoc
    360  1.1    kardel 	)
    361  1.1    kardel {
    362  1.3    kardel 	struct peer *p;
    363  1.1    kardel 	u_int hash;
    364  1.1    kardel 
    365  1.1    kardel 	assocpeer_calls++;
    366  1.1    kardel 	hash = assoc & NTP_HASH_MASK;
    367  1.4  christos 	for (p = assoc_hash[hash]; p != NULL; p = p->aid_link)
    368  1.3    kardel 		if (assoc == p->associd)
    369  1.4  christos 			break;
    370  1.4  christos 	return p;
    371  1.1    kardel }
    372  1.1    kardel 
    373  1.1    kardel 
    374  1.1    kardel /*
    375  1.1    kardel  * clear_all - flush all time values for all associations
    376  1.1    kardel  */
    377  1.1    kardel void
    378  1.1    kardel clear_all(void)
    379  1.1    kardel {
    380  1.4  christos 	struct peer *p;
    381  1.1    kardel 
    382  1.1    kardel 	/*
    383  1.1    kardel 	 * This routine is called when the clock is stepped, and so all
    384  1.1    kardel 	 * previously saved time values are untrusted.
    385  1.1    kardel 	 */
    386  1.4  christos 	for (p = peer_list; p != NULL; p = p->p_link)
    387  1.4  christos 		if (!(MDF_TXONLY_MASK & p->cast_flags))
    388  1.4  christos 			peer_clear(p, "STEP");
    389  1.4  christos 
    390  1.4  christos 	DPRINTF(1, ("clear_all: at %lu\n", current_time));
    391  1.1    kardel }
    392  1.1    kardel 
    393  1.1    kardel 
    394  1.1    kardel /*
    395  1.1    kardel  * score_all() - determine if an association can be demobilized
    396  1.1    kardel  */
    397  1.1    kardel int
    398  1.1    kardel score_all(
    399  1.1    kardel 	struct peer *peer	/* peer structure pointer */
    400  1.1    kardel 	)
    401  1.1    kardel {
    402  1.4  christos 	struct peer *speer;
    403  1.1    kardel 	int	temp, tamp;
    404  1.4  christos 	int	x;
    405  1.1    kardel 
    406  1.1    kardel 	/*
    407  1.4  christos 	 * This routine finds the minimum score for all preemptible
    408  1.4  christos 	 * associations and returns > 0 if the association can be
    409  1.1    kardel 	 * demobilized.
    410  1.1    kardel 	 */
    411  1.1    kardel 	tamp = score(peer);
    412  1.1    kardel 	temp = 100;
    413  1.4  christos 	for (speer = peer_list; speer != NULL; speer = speer->p_link)
    414  1.4  christos 		if (speer->flags & FLAG_PREEMPT) {
    415  1.4  christos 			x = score(speer);
    416  1.4  christos 			if (x < temp)
    417  1.1    kardel 				temp = x;
    418  1.1    kardel 		}
    419  1.4  christos 	DPRINTF(1, ("score_all: at %lu score %d min %d\n",
    420  1.4  christos 		    current_time, tamp, temp));
    421  1.4  christos 
    422  1.1    kardel 	if (tamp != temp)
    423  1.1    kardel 		temp = 0;
    424  1.4  christos 
    425  1.4  christos 	return temp;
    426  1.1    kardel }
    427  1.1    kardel 
    428  1.1    kardel 
    429  1.1    kardel /*
    430  1.1    kardel  * score() - calculate preemption score
    431  1.1    kardel  */
    432  1.1    kardel static int
    433  1.1    kardel score(
    434  1.1    kardel 	struct peer *peer	/* peer structure pointer */
    435  1.1    kardel 	)
    436  1.1    kardel {
    437  1.1    kardel 	int	temp;
    438  1.1    kardel 
    439  1.1    kardel 	/*
    440  1.1    kardel 	 * This routine calculates the premption score from the peer
    441  1.1    kardel 	 * error bits and status. Increasing values are more cherished.
    442  1.1    kardel 	 */
    443  1.1    kardel 	temp = 0;
    444  1.1    kardel 	if (!(peer->flash & TEST10))
    445  1.1    kardel 		temp++;			/* 1 good synch and stratum */
    446  1.1    kardel 	if (!(peer->flash & TEST13))
    447  1.1    kardel 		temp++;			/* 2 reachable */
    448  1.1    kardel 	if (!(peer->flash & TEST12))
    449  1.1    kardel 		temp++;			/* 3 no loop */
    450  1.1    kardel 	if (!(peer->flash & TEST11))
    451  1.1    kardel 		temp++;			/* 4 good distance */
    452  1.1    kardel 	if (peer->status >= CTL_PST_SEL_SELCAND)
    453  1.1    kardel 		temp++;			/* 5 in the hunt */
    454  1.1    kardel 	if (peer->status != CTL_PST_SEL_EXCESS)
    455  1.1    kardel 		temp++;			/* 6 not spare tire */
    456  1.1    kardel 	return (temp);			/* selection status */
    457  1.1    kardel }
    458  1.1    kardel 
    459  1.1    kardel 
    460  1.1    kardel /*
    461  1.4  christos  * free_peer - internal routine to free memory referred to by a struct
    462  1.4  christos  *	       peer and return it to the peer free list.  If unlink is
    463  1.4  christos  *	       nonzero, unlink from the various lists.
    464  1.4  christos  */
    465  1.4  christos static void
    466  1.4  christos free_peer(
    467  1.4  christos 	struct peer *	p,
    468  1.4  christos 	int		unlink_peer
    469  1.4  christos 	)
    470  1.4  christos {
    471  1.4  christos 	struct peer *	unlinked;
    472  1.4  christos 	int		hash;
    473  1.4  christos 
    474  1.4  christos 	if (unlink_peer) {
    475  1.4  christos 		hash = NTP_HASH_ADDR(&p->srcadr);
    476  1.4  christos 		peer_hash_count[hash]--;
    477  1.4  christos 
    478  1.4  christos 		UNLINK_SLIST(unlinked, peer_hash[hash], p, adr_link,
    479  1.4  christos 			     struct peer);
    480  1.4  christos 		if (NULL == unlinked) {
    481  1.4  christos 			peer_hash_count[hash]++;
    482  1.4  christos 			msyslog(LOG_ERR, "peer %s not in address table!",
    483  1.4  christos 				stoa(&p->srcadr));
    484  1.4  christos 		}
    485  1.4  christos 
    486  1.4  christos 		/*
    487  1.4  christos 		 * Remove him from the association hash as well.
    488  1.4  christos 		 */
    489  1.4  christos 		hash = p->associd & NTP_HASH_MASK;
    490  1.4  christos 		assoc_hash_count[hash]--;
    491  1.4  christos 
    492  1.4  christos 		UNLINK_SLIST(unlinked, assoc_hash[hash], p, aid_link,
    493  1.4  christos 			     struct peer);
    494  1.4  christos 		if (NULL == unlinked) {
    495  1.4  christos 			assoc_hash_count[hash]++;
    496  1.4  christos 			msyslog(LOG_ERR,
    497  1.4  christos 				"peer %s not in association ID table!",
    498  1.4  christos 				stoa(&p->srcadr));
    499  1.4  christos 		}
    500  1.4  christos 
    501  1.4  christos 		/* Remove him from the overall list. */
    502  1.4  christos 		UNLINK_SLIST(unlinked, peer_list, p, p_link,
    503  1.4  christos 			     struct peer);
    504  1.4  christos 		if (NULL == unlinked)
    505  1.4  christos 			msyslog(LOG_ERR, "%s not in peer list!",
    506  1.4  christos 				stoa(&p->srcadr));
    507  1.4  christos 	}
    508  1.4  christos 
    509  1.4  christos 	if (p->hostname != NULL)
    510  1.4  christos 		free(p->hostname);
    511  1.4  christos 
    512  1.4  christos 	if (p->ident != NULL)
    513  1.4  christos 		free(p->ident);
    514  1.4  christos 
    515  1.4  christos 	if (p->addrs != NULL)
    516  1.4  christos 		free(p->addrs);		/* from copy_addrinfo_list() */
    517  1.4  christos 
    518  1.4  christos 	/* Add his corporeal form to peer free list */
    519  1.4  christos 	ZERO(*p);
    520  1.4  christos 	LINK_SLIST(peer_free, p, p_link);
    521  1.4  christos 	peer_free_count++;
    522  1.4  christos }
    523  1.4  christos 
    524  1.4  christos 
    525  1.4  christos /*
    526  1.1    kardel  * unpeer - remove peer structure from hash table and free structure
    527  1.1    kardel  */
    528  1.1    kardel void
    529  1.1    kardel unpeer(
    530  1.4  christos 	struct peer *peer
    531  1.1    kardel 	)
    532  1.1    kardel {
    533  1.4  christos 	mprintf_event(PEVNT_DEMOBIL, peer, "assoc %u", peer->associd);
    534  1.4  christos 	restrict_source(&peer->srcadr, 1, 0);
    535  1.4  christos 	set_peerdstadr(peer, NULL);
    536  1.1    kardel 	peer_demobilizations++;
    537  1.1    kardel 	peer_associations--;
    538  1.4  christos 	if (FLAG_PREEMPT & peer->flags)
    539  1.1    kardel 		peer_preempt--;
    540  1.1    kardel #ifdef REFCLOCK
    541  1.1    kardel 	/*
    542  1.1    kardel 	 * If this peer is actually a clock, shut it down first
    543  1.1    kardel 	 */
    544  1.4  christos 	if (FLAG_REFCLOCK & peer->flags)
    545  1.4  christos 		refclock_unpeer(peer);
    546  1.1    kardel #endif
    547  1.1    kardel 
    548  1.4  christos 	free_peer(peer, TRUE);
    549  1.1    kardel }
    550  1.1    kardel 
    551  1.1    kardel 
    552  1.1    kardel /*
    553  1.1    kardel  * peer_config - configure a new association
    554  1.1    kardel  */
    555  1.1    kardel struct peer *
    556  1.1    kardel peer_config(
    557  1.4  christos 	sockaddr_u *	srcadr,
    558  1.4  christos 	const char *	hostname,
    559  1.4  christos 	endpt *		dstadr,
    560  1.4  christos 	u_char		hmode,
    561  1.4  christos 	u_char		version,
    562  1.4  christos 	u_char		minpoll,
    563  1.4  christos 	u_char		maxpoll,
    564  1.4  christos 	u_int		flags,
    565  1.4  christos 	u_int32		ttl,
    566  1.4  christos 	keyid_t		key,
    567  1.4  christos 	const char *	ident		/* autokey group */
    568  1.1    kardel 	)
    569  1.1    kardel {
    570  1.1    kardel 	u_char cast_flags;
    571  1.1    kardel 
    572  1.1    kardel 	/*
    573  1.1    kardel 	 * We do a dirty little jig to figure the cast flags. This is
    574  1.1    kardel 	 * probably not the best place to do this, at least until the
    575  1.1    kardel 	 * configure code is rebuilt. Note only one flag can be set.
    576  1.1    kardel 	 */
    577  1.1    kardel 	switch (hmode) {
    578  1.1    kardel 	case MODE_BROADCAST:
    579  1.1    kardel 		if (IS_MCAST(srcadr))
    580  1.1    kardel 			cast_flags = MDF_MCAST;
    581  1.1    kardel 		else
    582  1.1    kardel 			cast_flags = MDF_BCAST;
    583  1.1    kardel 		break;
    584  1.1    kardel 
    585  1.1    kardel 	case MODE_CLIENT:
    586  1.4  christos 		if (hostname != NULL && SOCK_UNSPEC(srcadr))
    587  1.4  christos 			cast_flags = MDF_POOL;
    588  1.4  christos 		else if (IS_MCAST(srcadr))
    589  1.1    kardel 			cast_flags = MDF_ACAST;
    590  1.1    kardel 		else
    591  1.1    kardel 			cast_flags = MDF_UCAST;
    592  1.1    kardel 		break;
    593  1.1    kardel 
    594  1.1    kardel 	default:
    595  1.1    kardel 		cast_flags = MDF_UCAST;
    596  1.1    kardel 	}
    597  1.1    kardel 
    598  1.1    kardel 	/*
    599  1.1    kardel 	 * Mobilize the association and initialize its variables. If
    600  1.4  christos 	 * emulating ntpdate, force iburst.  For pool and manycastclient
    601  1.4  christos 	 * strip FLAG_PREEMPT as the prototype associations are not
    602  1.4  christos 	 * themselves preemptible, though the resulting associations
    603  1.4  christos 	 * are.
    604  1.1    kardel 	 */
    605  1.4  christos 	flags |= FLAG_CONFIG;
    606  1.1    kardel 	if (mode_ntpdate)
    607  1.1    kardel 		flags |= FLAG_IBURST;
    608  1.4  christos 	if ((MDF_ACAST | MDF_POOL) & cast_flags)
    609  1.4  christos 		flags &= ~FLAG_PREEMPT;
    610  1.4  christos 	return newpeer(srcadr, hostname, dstadr, hmode, version,
    611  1.4  christos 	    minpoll, maxpoll, flags, cast_flags, ttl, key, ident);
    612  1.1    kardel }
    613  1.1    kardel 
    614  1.1    kardel /*
    615  1.1    kardel  * setup peer dstadr field keeping it in sync with the interface
    616  1.1    kardel  * structures
    617  1.1    kardel  */
    618  1.1    kardel void
    619  1.1    kardel set_peerdstadr(
    620  1.3    kardel 	struct peer *	p,
    621  1.3    kardel 	endpt *		dstadr
    622  1.1    kardel 	)
    623  1.1    kardel {
    624  1.3    kardel 	struct peer *	unlinked;
    625  1.1    kardel 
    626  1.3    kardel 	if (p->dstadr == dstadr)
    627  1.3    kardel 		return;
    628  1.1    kardel 
    629  1.3    kardel 	/*
    630  1.3    kardel 	 * Don't accept updates to a separate multicast receive-only
    631  1.3    kardel 	 * endpt while a BCLNT peer is running its unicast protocol.
    632  1.3    kardel 	 */
    633  1.3    kardel 	if (dstadr != NULL && (FLAG_BC_VOL & p->flags) &&
    634  1.3    kardel 	    (INT_MCASTIF & dstadr->flags) && MODE_CLIENT == p->hmode) {
    635  1.3    kardel 		return;
    636  1.3    kardel 	}
    637  1.3    kardel 	if (p->dstadr != NULL) {
    638  1.3    kardel 		p->dstadr->peercnt--;
    639  1.3    kardel 		UNLINK_SLIST(unlinked, p->dstadr->peers, p, ilink,
    640  1.3    kardel 			     struct peer);
    641  1.4  christos 		msyslog(LOG_INFO, "%s local addr %s -> %s",
    642  1.4  christos 			stoa(&p->srcadr), latoa(p->dstadr),
    643  1.4  christos 			latoa(dstadr));
    644  1.3    kardel 	}
    645  1.3    kardel 	p->dstadr = dstadr;
    646  1.3    kardel 	if (dstadr != NULL) {
    647  1.3    kardel 		LINK_SLIST(dstadr->peers, p, ilink);
    648  1.3    kardel 		dstadr->peercnt++;
    649  1.1    kardel 	}
    650  1.1    kardel }
    651  1.1    kardel 
    652  1.1    kardel /*
    653  1.1    kardel  * attempt to re-rebind interface if necessary
    654  1.1    kardel  */
    655  1.1    kardel static void
    656  1.1    kardel peer_refresh_interface(
    657  1.4  christos 	struct peer *p
    658  1.1    kardel 	)
    659  1.1    kardel {
    660  1.3    kardel 	endpt *	niface;
    661  1.3    kardel 	endpt *	piface;
    662  1.1    kardel 
    663  1.4  christos 	niface = select_peerinterface(p, &p->srcadr, NULL);
    664  1.1    kardel 
    665  1.3    kardel 	DPRINTF(4, (
    666  1.4  christos 	    "peer_refresh_interface: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %u key %08x: new interface: ",
    667  1.4  christos 	    p->dstadr == NULL ? "<null>" :
    668  1.4  christos 	    stoa(&p->dstadr->sin), stoa(&p->srcadr), p->hmode,
    669  1.4  christos 	    p->version, p->minpoll, p->maxpoll, p->flags, p->cast_flags,
    670  1.4  christos 	    p->ttl, p->keyid));
    671  1.3    kardel 	if (niface != NULL) {
    672  1.3    kardel 		DPRINTF(4, (
    673  1.3    kardel 		    "fd=%d, bfd=%d, name=%.16s, flags=0x%x, ifindex=%u, sin=%s",
    674  1.3    kardel 		    niface->fd,  niface->bfd, niface->name,
    675  1.3    kardel 		    niface->flags, niface->ifindex,
    676  1.3    kardel 		    stoa(&niface->sin)));
    677  1.3    kardel 		if (niface->flags & INT_BROADCAST)
    678  1.3    kardel 			DPRINTF(4, (", bcast=%s",
    679  1.3    kardel 				stoa(&niface->bcast)));
    680  1.3    kardel 		DPRINTF(4, (", mask=%s\n", stoa(&niface->mask)));
    681  1.3    kardel 	} else {
    682  1.3    kardel 		DPRINTF(4, ("<NONE>\n"));
    683  1.1    kardel 	}
    684  1.1    kardel 
    685  1.4  christos 	piface = p->dstadr;
    686  1.4  christos 	set_peerdstadr(p, niface);
    687  1.4  christos 	if (p->dstadr != NULL) {
    688  1.1    kardel 		/*
    689  1.1    kardel 		 * clear crypto if we change the local address
    690  1.1    kardel 		 */
    691  1.4  christos 		if (p->dstadr != piface && !(MDF_ACAST & p->cast_flags)
    692  1.4  christos 		    && MODE_BROADCAST != p->pmode)
    693  1.4  christos 			peer_clear(p, "XFAC");
    694  1.1    kardel 
    695  1.1    kardel 		/*
    696  1.1    kardel 	 	 * Broadcast needs the socket enabled for broadcast
    697  1.1    kardel 	 	 */
    698  1.4  christos 		if (MDF_BCAST & p->cast_flags)
    699  1.4  christos 			enable_broadcast(p->dstadr, &p->srcadr);
    700  1.1    kardel 
    701  1.1    kardel 		/*
    702  1.1    kardel 	 	 * Multicast needs the socket interface enabled for
    703  1.1    kardel 		 * multicast
    704  1.1    kardel 	 	 */
    705  1.4  christos 		if (MDF_MCAST & p->cast_flags)
    706  1.4  christos 			enable_multicast_if(p->dstadr, &p->srcadr);
    707  1.1    kardel 	}
    708  1.1    kardel }
    709  1.1    kardel 
    710  1.4  christos 
    711  1.1    kardel /*
    712  1.1    kardel  * refresh_all_peerinterfaces - see that all interface bindings are up
    713  1.1    kardel  * to date
    714  1.1    kardel  */
    715  1.1    kardel void
    716  1.1    kardel refresh_all_peerinterfaces(void)
    717  1.1    kardel {
    718  1.4  christos 	struct peer *p;
    719  1.1    kardel 
    720  1.1    kardel 	/*
    721  1.1    kardel 	 * this is called when the interface list has changed
    722  1.1    kardel 	 * give all peers a chance to find a better interface
    723  1.1    kardel 	 */
    724  1.4  christos 	for (p = peer_list; p != NULL; p = p->p_link)
    725  1.4  christos 		peer_refresh_interface(p);
    726  1.1    kardel }
    727  1.1    kardel 
    728  1.1    kardel 
    729  1.1    kardel /*
    730  1.1    kardel  * newpeer - initialize a new peer association
    731  1.1    kardel  */
    732  1.1    kardel struct peer *
    733  1.1    kardel newpeer(
    734  1.4  christos 	sockaddr_u *	srcadr,
    735  1.4  christos 	const char *	hostname,
    736  1.4  christos 	endpt *		dstadr,
    737  1.4  christos 	u_char		hmode,
    738  1.4  christos 	u_char		version,
    739  1.4  christos 	u_char		minpoll,
    740  1.4  christos 	u_char		maxpoll,
    741  1.4  christos 	u_int		flags,
    742  1.4  christos 	u_char		cast_flags,
    743  1.4  christos 	u_int32		ttl,
    744  1.4  christos 	keyid_t		key,
    745  1.4  christos 	const char *	ident
    746  1.1    kardel 	)
    747  1.1    kardel {
    748  1.4  christos 	struct peer *	peer;
    749  1.4  christos 	u_int		hash;
    750  1.1    kardel 
    751  1.4  christos #ifdef AUTOKEY
    752  1.1    kardel 	/*
    753  1.1    kardel 	 * If Autokey is requested but not configured, complain loudly.
    754  1.1    kardel 	 */
    755  1.1    kardel 	if (!crypto_flags) {
    756  1.1    kardel 		if (key > NTP_MAXKEY) {
    757  1.1    kardel 			return (NULL);
    758  1.1    kardel 
    759  1.1    kardel 		} else if (flags & FLAG_SKEY) {
    760  1.1    kardel 			msyslog(LOG_ERR, "Autokey not configured");
    761  1.1    kardel 			return (NULL);
    762  1.1    kardel 		}
    763  1.1    kardel 	}
    764  1.4  christos #endif	/* AUTOKEY */
    765  1.4  christos 
    766  1.4  christos 	/*
    767  1.4  christos 	 * For now only pool associations have a hostname.
    768  1.4  christos 	 */
    769  1.4  christos 	NTP_INSIST(NULL == hostname || (MDF_POOL & cast_flags));
    770  1.1    kardel 
    771  1.1    kardel 	/*
    772  1.1    kardel 	 * First search from the beginning for an association with given
    773  1.1    kardel 	 * remote address and mode. If an interface is given, search
    774  1.1    kardel 	 * from there to find the association which matches that
    775  1.1    kardel 	 * destination. If the given interface is "any", track down the
    776  1.1    kardel 	 * actual interface, because that's what gets put into the peer
    777  1.1    kardel 	 * structure.
    778  1.1    kardel 	 */
    779  1.1    kardel 	if (dstadr != NULL) {
    780  1.4  christos 		peer = findexistingpeer(srcadr, hostname, NULL, hmode,
    781  1.4  christos 					cast_flags);
    782  1.1    kardel 		while (peer != NULL) {
    783  1.3    kardel 			if (peer->dstadr == dstadr ||
    784  1.3    kardel 			    ((MDF_BCLNT & cast_flags) &&
    785  1.3    kardel 			     (MDF_BCLNT & peer->cast_flags)))
    786  1.1    kardel 				break;
    787  1.1    kardel 
    788  1.1    kardel 			if (dstadr == ANY_INTERFACE_CHOOSE(srcadr) &&
    789  1.1    kardel 			    peer->dstadr == findinterface(srcadr))
    790  1.1    kardel 				break;
    791  1.1    kardel 
    792  1.4  christos 			peer = findexistingpeer(srcadr, hostname, peer,
    793  1.4  christos 						hmode, cast_flags);
    794  1.1    kardel 		}
    795  1.3    kardel 	} else {
    796  1.3    kardel 		/* no endpt address given */
    797  1.4  christos 		peer = findexistingpeer(srcadr, hostname, NULL, hmode,
    798  1.4  christos 					cast_flags);
    799  1.1    kardel 	}
    800  1.1    kardel 
    801  1.1    kardel 	/*
    802  1.1    kardel 	 * If a peer is found, this would be a duplicate and we don't
    803  1.3    kardel 	 * allow that. This avoids duplicate ephemeral (broadcast/
    804  1.3    kardel 	 * multicast) and preemptible (manycast and pool) client
    805  1.1    kardel 	 * associations.
    806  1.1    kardel 	 */
    807  1.4  christos 	if (peer != NULL) {
    808  1.4  christos 		DPRINTF(2, ("newpeer(%s) found existing association\n",
    809  1.4  christos 			(hostname)
    810  1.4  christos 			    ? hostname
    811  1.4  christos 			    : stoa(srcadr)));
    812  1.4  christos 		return NULL;
    813  1.4  christos 	}
    814  1.1    kardel 
    815  1.1    kardel 	/*
    816  1.1    kardel 	 * Allocate a new peer structure. Some dirt here, since some of
    817  1.1    kardel 	 * the initialization requires knowlege of our system state.
    818  1.1    kardel 	 */
    819  1.1    kardel 	if (peer_free_count == 0)
    820  1.1    kardel 		getmorepeermem();
    821  1.4  christos 	UNLINK_HEAD_SLIST(peer, peer_free, p_link);
    822  1.1    kardel 	peer_free_count--;
    823  1.1    kardel 	peer_associations++;
    824  1.4  christos 	if (FLAG_PREEMPT & flags)
    825  1.1    kardel 		peer_preempt++;
    826  1.1    kardel 
    827  1.1    kardel 	/*
    828  1.1    kardel 	 * Assign an association ID and increment the system variable.
    829  1.1    kardel 	 */
    830  1.1    kardel 	peer->associd = current_association_ID;
    831  1.1    kardel 	if (++current_association_ID == 0)
    832  1.1    kardel 		++current_association_ID;
    833  1.1    kardel 
    834  1.1    kardel 	peer->srcadr = *srcadr;
    835  1.4  christos 	if (hostname != NULL)
    836  1.4  christos 		peer->hostname = estrdup(hostname);
    837  1.4  christos 	peer->hmode = hmode;
    838  1.4  christos 	peer->version = version;
    839  1.1    kardel 	peer->flags = flags;
    840  1.4  christos 	peer->cast_flags = cast_flags;
    841  1.4  christos 	set_peerdstadr(peer,
    842  1.4  christos 		       select_peerinterface(peer, srcadr, dstadr));
    843  1.1    kardel 
    844  1.1    kardel 	/*
    845  1.1    kardel 	 * It is an error to set minpoll less than NTP_MINPOLL or to
    846  1.1    kardel 	 * set maxpoll greater than NTP_MAXPOLL. However, minpoll is
    847  1.1    kardel 	 * clamped not greater than NTP_MAXPOLL and maxpoll is clamped
    848  1.1    kardel 	 * not less than NTP_MINPOLL without complaint. Finally,
    849  1.1    kardel 	 * minpoll is clamped not greater than maxpoll.
    850  1.1    kardel 	 */
    851  1.1    kardel 	if (minpoll == 0)
    852  1.1    kardel 		peer->minpoll = NTP_MINDPOLL;
    853  1.1    kardel 	else
    854  1.4  christos 		peer->minpoll = min(minpoll, NTP_MAXPOLL);
    855  1.1    kardel 	if (maxpoll == 0)
    856  1.1    kardel 		peer->maxpoll = NTP_MAXDPOLL;
    857  1.1    kardel 	else
    858  1.4  christos 		peer->maxpoll = max(maxpoll, NTP_MINPOLL);
    859  1.1    kardel 	if (peer->minpoll > peer->maxpoll)
    860  1.1    kardel 		peer->minpoll = peer->maxpoll;
    861  1.1    kardel 
    862  1.4  christos 	if (peer->dstadr != NULL)
    863  1.4  christos 		DPRINTF(3, ("newpeer(%s): using fd %d and our addr %s\n",
    864  1.4  christos 			stoa(srcadr), peer->dstadr->fd,
    865  1.4  christos 			stoa(&peer->dstadr->sin)));
    866  1.1    kardel 	else
    867  1.4  christos 		DPRINTF(3, ("newpeer(%s): local interface currently not bound\n",
    868  1.4  christos 			stoa(srcadr)));
    869  1.1    kardel 
    870  1.1    kardel 	/*
    871  1.1    kardel 	 * Broadcast needs the socket enabled for broadcast
    872  1.1    kardel 	 */
    873  1.4  christos 	if ((MDF_BCAST & cast_flags) && peer->dstadr != NULL)
    874  1.1    kardel 		enable_broadcast(peer->dstadr, srcadr);
    875  1.1    kardel 
    876  1.1    kardel 	/*
    877  1.1    kardel 	 * Multicast needs the socket interface enabled for multicast
    878  1.1    kardel 	 */
    879  1.4  christos 	if ((MDF_MCAST & cast_flags) && peer->dstadr != NULL)
    880  1.1    kardel 		enable_multicast_if(peer->dstadr, srcadr);
    881  1.1    kardel 
    882  1.4  christos #ifdef AUTOKEY
    883  1.1    kardel 	if (key > NTP_MAXKEY)
    884  1.1    kardel 		peer->flags |= FLAG_SKEY;
    885  1.4  christos #endif	/* AUTOKEY */
    886  1.4  christos 	peer->ttl = ttl;
    887  1.1    kardel 	peer->keyid = key;
    888  1.4  christos 	if (ident != NULL)
    889  1.4  christos 		peer->ident = estrdup(ident);
    890  1.1    kardel 	peer->precision = sys_precision;
    891  1.1    kardel 	peer->hpoll = peer->minpoll;
    892  1.1    kardel 	if (cast_flags & MDF_ACAST)
    893  1.1    kardel 		peer_clear(peer, "ACST");
    894  1.4  christos 	else if (cast_flags & MDF_POOL)
    895  1.4  christos 		peer_clear(peer, "POOL");
    896  1.1    kardel 	else if (cast_flags & MDF_MCAST)
    897  1.1    kardel 		peer_clear(peer, "MCST");
    898  1.1    kardel 	else if (cast_flags & MDF_BCAST)
    899  1.1    kardel 		peer_clear(peer, "BCST");
    900  1.1    kardel 	else
    901  1.1    kardel 		peer_clear(peer, "INIT");
    902  1.1    kardel 	if (mode_ntpdate)
    903  1.1    kardel 		peer_ntpdate++;
    904  1.1    kardel 
    905  1.1    kardel 	/*
    906  1.1    kardel 	 * Note time on statistics timers.
    907  1.1    kardel 	 */
    908  1.1    kardel 	peer->timereset = current_time;
    909  1.1    kardel 	peer->timereachable = current_time;
    910  1.1    kardel 	peer->timereceived = current_time;
    911  1.1    kardel 
    912  1.4  christos 	if (ISREFCLOCKADR(&peer->srcadr)) {
    913  1.1    kardel #ifdef REFCLOCK
    914  1.1    kardel 		/*
    915  1.1    kardel 		 * We let the reference clock support do clock
    916  1.1    kardel 		 * dependent initialization.  This includes setting
    917  1.1    kardel 		 * the peer timer, since the clock may have requirements
    918  1.1    kardel 		 * for this.
    919  1.1    kardel 		 */
    920  1.1    kardel 		if (maxpoll == 0)
    921  1.1    kardel 			peer->maxpoll = peer->minpoll;
    922  1.1    kardel 		if (!refclock_newpeer(peer)) {
    923  1.1    kardel 			/*
    924  1.1    kardel 			 * Dump it, something screwed up
    925  1.1    kardel 			 */
    926  1.1    kardel 			set_peerdstadr(peer, NULL);
    927  1.4  christos 			free_peer(peer, 0);
    928  1.4  christos 			return NULL;
    929  1.1    kardel 		}
    930  1.4  christos #else /* REFCLOCK */
    931  1.4  christos 		msyslog(LOG_ERR, "refclock %s isn't supported. ntpd was compiled without refclock support.",
    932  1.4  christos 			stoa(&peer->srcadr));
    933  1.4  christos 		set_peerdstadr(peer, NULL);
    934  1.4  christos 		free_peer(peer, 0);
    935  1.4  christos 		return NULL;
    936  1.4  christos #endif /* REFCLOCK */
    937  1.1    kardel 	}
    938  1.1    kardel 
    939  1.1    kardel 	/*
    940  1.1    kardel 	 * Put the new peer in the hash tables.
    941  1.1    kardel 	 */
    942  1.1    kardel 	hash = NTP_HASH_ADDR(&peer->srcadr);
    943  1.4  christos 	LINK_SLIST(peer_hash[hash], peer, adr_link);
    944  1.1    kardel 	peer_hash_count[hash]++;
    945  1.1    kardel 	hash = peer->associd & NTP_HASH_MASK;
    946  1.4  christos 	LINK_SLIST(assoc_hash[hash], peer, aid_link);
    947  1.1    kardel 	assoc_hash_count[hash]++;
    948  1.4  christos 	LINK_SLIST(peer_list, peer, p_link);
    949  1.4  christos 
    950  1.4  christos 	restrict_source(&peer->srcadr, 0, 0);
    951  1.4  christos 	mprintf_event(PEVNT_MOBIL, peer, "assoc %d", peer->associd);
    952  1.4  christos 	DPRINTF(1, ("newpeer: %s->%s mode %u vers %u poll %u %u flags 0x%x 0x%x ttl %u key %08x\n",
    953  1.4  christos 	    latoa(peer->dstadr), stoa(&peer->srcadr), peer->hmode,
    954  1.4  christos 	    peer->version, peer->minpoll, peer->maxpoll, peer->flags,
    955  1.4  christos 	    peer->cast_flags, peer->ttl, peer->keyid));
    956  1.4  christos 	return peer;
    957  1.1    kardel }
    958  1.1    kardel 
    959  1.1    kardel 
    960  1.1    kardel /*
    961  1.4  christos  * peer_clr_stats - clear peer module statistics counters
    962  1.1    kardel  */
    963  1.1    kardel void
    964  1.1    kardel peer_clr_stats(void)
    965  1.1    kardel {
    966  1.1    kardel 	findpeer_calls = 0;
    967  1.1    kardel 	assocpeer_calls = 0;
    968  1.1    kardel 	peer_allocations = 0;
    969  1.1    kardel 	peer_demobilizations = 0;
    970  1.1    kardel 	peer_timereset = current_time;
    971  1.1    kardel }
    972  1.1    kardel 
    973  1.4  christos 
    974  1.1    kardel /*
    975  1.1    kardel  * peer_reset - reset statistics counters
    976  1.1    kardel  */
    977  1.1    kardel void
    978  1.1    kardel peer_reset(
    979  1.1    kardel 	struct peer *peer
    980  1.1    kardel 	)
    981  1.1    kardel {
    982  1.1    kardel 	if (peer == NULL)
    983  1.3    kardel 		return;
    984  1.1    kardel 
    985  1.1    kardel 	peer->timereset = current_time;
    986  1.1    kardel 	peer->sent = 0;
    987  1.1    kardel 	peer->received = 0;
    988  1.1    kardel 	peer->processed = 0;
    989  1.1    kardel 	peer->badauth = 0;
    990  1.1    kardel 	peer->bogusorg = 0;
    991  1.1    kardel 	peer->oldpkt = 0;
    992  1.1    kardel 	peer->seldisptoolarge = 0;
    993  1.1    kardel 	peer->selbroken = 0;
    994  1.1    kardel }
    995  1.1    kardel 
    996  1.1    kardel 
    997  1.1    kardel /*
    998  1.1    kardel  * peer_all_reset - reset all peer statistics counters
    999  1.1    kardel  */
   1000  1.1    kardel void
   1001  1.1    kardel peer_all_reset(void)
   1002  1.1    kardel {
   1003  1.1    kardel 	struct peer *peer;
   1004  1.1    kardel 
   1005  1.4  christos 	for (peer = peer_list; peer != NULL; peer = peer->p_link)
   1006  1.1    kardel 		peer_reset(peer);
   1007  1.1    kardel }
   1008  1.1    kardel 
   1009  1.1    kardel 
   1010  1.1    kardel /*
   1011  1.4  christos  * findmanycastpeer - find and return a manycastclient or pool
   1012  1.4  christos  *		      association matching a received response.
   1013  1.1    kardel  */
   1014  1.1    kardel struct peer *
   1015  1.1    kardel findmanycastpeer(
   1016  1.1    kardel 	struct recvbuf *rbufp	/* receive buffer pointer */
   1017  1.1    kardel 	)
   1018  1.1    kardel {
   1019  1.4  christos 	struct peer *peer;
   1020  1.1    kardel 	struct pkt *pkt;
   1021  1.1    kardel 	l_fp p_org;
   1022  1.1    kardel 
   1023  1.1    kardel  	/*
   1024  1.4  christos  	 * This routine is called upon arrival of a server-mode response
   1025  1.4  christos 	 * to a manycastclient multicast solicitation, or to a pool
   1026  1.4  christos 	 * server unicast solicitation.  Search the peer list for a
   1027  1.4  christos 	 * manycastclient association where the last transmit timestamp
   1028  1.4  christos 	 * matches the response packet's originate timestamp.  There can
   1029  1.4  christos 	 * be multiple manycastclient associations, or multiple pool
   1030  1.4  christos 	 * solicitation assocations, so this assumes the transmit
   1031  1.4  christos 	 * timestamps are unique for such.
   1032  1.1    kardel 	 */
   1033  1.1    kardel 	pkt = &rbufp->recv_pkt;
   1034  1.4  christos 	for (peer = peer_list; peer != NULL; peer = peer->p_link)
   1035  1.4  christos 		if (MDF_SOLICIT_MASK & peer->cast_flags) {
   1036  1.4  christos 			NTOHL_FP(&pkt->org, &p_org);
   1037  1.4  christos 			if (L_ISEQU(&p_org, &peer->aorg))
   1038  1.4  christos 				break;
   1039  1.1    kardel 		}
   1040  1.4  christos 
   1041  1.4  christos 	return peer;
   1042  1.1    kardel }
   1043  1.6  christos 
   1044  1.6  christos /* peer_cleanup - clean peer list prior to shutdown */
   1045  1.6  christos void peer_cleanup(void)
   1046  1.6  christos {
   1047  1.6  christos         struct peer *peer;
   1048  1.6  christos         associd_t assoc;
   1049  1.6  christos 
   1050  1.6  christos         for (assoc = initial_association_ID; assoc != current_association_ID; assoc++) {
   1051  1.6  christos             if (assoc != 0U) {
   1052  1.6  christos                 peer = findpeerbyassoc(assoc);
   1053  1.6  christos                 if (peer != NULL)
   1054  1.6  christos                     unpeer(peer);
   1055  1.6  christos             }
   1056  1.6  christos         }
   1057  1.6  christos         peer = findpeerbyassoc(current_association_ID);
   1058  1.6  christos         if (peer != NULL)
   1059  1.6  christos             unpeer(peer);
   1060  1.6  christos }
   1061