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