xref: /freebsd/contrib/ntp/ntpd/ntp_peer.c (revision b52b9d56d4e96089873a75f9e29062eec19fabba)
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_stdlib.h"
13 #ifdef AUTOKEY
14 #include "ntp_crypto.h"
15 #endif /* AUTOKEY */
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       e       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       1
28  * SERVER          |   e       0       0       0       0       0
29  * BCAST	   |   e       0       0       0       0       0
30  * CONTROL	   |   e       0       0       0       0       0
31  * PRIVATE	   |   e       0       0       0       0       0
32  * BCLIENT         |   e       0       0       0       e       1
33  *
34  * One point to note here: a packet in BCAST mode can potentially match
35  * a peer in CLIENT mode, but we that is a special case and we check for
36  * that early in the decision process.  This avoids having to keep track
37  * of what kind of associations are possible etc...  We actually
38  * circumvent that problem by requiring that the first b(m)roadcast
39  * received after the change back to BCLIENT mode sets the clock.
40  */
41 
42 int AM[AM_MODES][AM_MODES] = {
43 /*	{ UNSPEC,   ACTIVE,     PASSIVE,    CLIENT,     SERVER,     BCAST } */
44 
45 /*NONE*/{ AM_ERR, AM_NEWPASS, AM_ERR,     AM_FXMIT,   AM_MANYCAST, AM_NEWBCL},
46 
47 /*A*/	{ AM_ERR, AM_PROCPKT, AM_PROCPKT, AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},
48 
49 /*P*/	{ AM_ERR, AM_PROCPKT, AM_ERR,     AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},
50 
51 /*C*/	{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_PROCPKT,  AM_POSSBCL},
52 
53 /*S*/	{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},
54 
55 /*BCST*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},
56 
57 /*CNTL*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},
58 
59 /*PRIV*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},
60 
61 /*BCL*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_ERR,      AM_PROCPKT},
62 };
63 
64 #define MATCH_ASSOC(x,y)	AM[(x)][(y)]
65 
66 /*
67  * These routines manage the allocation of memory to peer structures
68  * and the maintenance of the peer hash table. The two main entry
69  * points are findpeer(), which looks for matching peer sturctures in
70  * the peer list, newpeer(), which allocates a new peer structure and
71  * adds it to the list, and unpeer(), which demobilizes the association
72  * and deallocates the structure.
73  */
74 /*
75  * Peer hash tables
76  */
77 struct peer *peer_hash[HASH_SIZE];	/* peer hash table */
78 int peer_hash_count[HASH_SIZE];		/* peers in each bucket */
79 struct peer *assoc_hash[HASH_SIZE];	/* association ID hash table */
80 int assoc_hash_count[HASH_SIZE];	/* peers in each bucket */
81 static struct peer *peer_free;		/* peer structures free list */
82 int peer_free_count;			/* count of free structures */
83 
84 /*
85  * Association ID.  We initialize this value randomly, then assign a new
86  * value every time the peer structure is incremented.
87  */
88 static associd_t current_association_ID; /* association ID */
89 
90 /*
91  * Memory allocation watermarks.
92  */
93 #define	INIT_PEER_ALLOC		15	/* initialize for 15 peers */
94 #define	INC_PEER_ALLOC		5	/* when run out, add 5 more */
95 
96 /*
97  * Miscellaneous statistic counters which may be queried.
98  */
99 u_long peer_timereset;			/* time stat counters zeroed */
100 u_long findpeer_calls;			/* calls to findpeer */
101 u_long assocpeer_calls;			/* calls to findpeerbyassoc */
102 u_long peer_allocations;		/* allocations from free list */
103 u_long peer_demobilizations;		/* structs freed to free list */
104 int total_peer_structs;			/* peer structs */
105 int peer_associations;			/* active associations */
106 static struct peer init_peer_alloc[INIT_PEER_ALLOC]; /* init alloc */
107 
108 static	void	getmorepeermem	P((void));
109 
110 /*
111  * init_peer - initialize peer data structures and counters
112  *
113  * N.B. We use the random number routine in here. It had better be
114  * initialized prior to getting here.
115  */
116 void
117 init_peer(void)
118 {
119 	register int i;
120 
121 	/*
122 	 * Clear hash table and counters.
123 	 */
124 	for (i = 0; i < HASH_SIZE; i++) {
125 		peer_hash[i] = 0;
126 		peer_hash_count[i] = 0;
127 		assoc_hash[i] = 0;
128 		assoc_hash_count[i] = 0;
129 	}
130 
131 	/*
132 	 * Clear stat counters
133 	 */
134 	findpeer_calls = peer_allocations = 0;
135 	assocpeer_calls = peer_demobilizations = 0;
136 
137 	/*
138 	 * Initialize peer memory.
139 	 */
140 	peer_free = 0;
141 	for (i = 0; i < INIT_PEER_ALLOC; i++) {
142 		init_peer_alloc[i].next = peer_free;
143 		peer_free = &init_peer_alloc[i];
144 	}
145 	total_peer_structs = INIT_PEER_ALLOC;
146 	peer_free_count = INIT_PEER_ALLOC;
147 
148 	/*
149 	 * Initialize our first association ID
150 	 */
151 	current_association_ID = (associd_t)ranp2(16);
152 	if (current_association_ID == 0)
153 	    current_association_ID = 1;
154 }
155 
156 
157 /*
158  * getmorepeermem - add more peer structures to the free list
159  */
160 static void
161 getmorepeermem(void)
162 {
163 	register int i;
164 	register struct peer *peer;
165 
166 	peer = (struct peer *)emalloc(INC_PEER_ALLOC *
167 	    sizeof(struct peer));
168 	for (i = 0; i < INC_PEER_ALLOC; i++) {
169 		peer->next = peer_free;
170 		peer_free = peer;
171 		peer++;
172 	}
173 
174 	total_peer_structs += INC_PEER_ALLOC;
175 	peer_free_count += INC_PEER_ALLOC;
176 }
177 
178 
179 /*
180  * findexistingpeer - return a pointer to a peer in the hash table
181  */
182 struct peer *
183 findexistingpeer(
184 	struct sockaddr_in *addr,
185 	struct peer *start_peer,
186 	int mode
187 	)
188 {
189 	register struct peer *peer;
190 
191 	/*
192 	 * start_peer is included so we can locate instances of the
193 	 * same peer through different interfaces in the hash table.
194 	 */
195 	if (start_peer == 0)
196 		peer = peer_hash[HASH_ADDR(addr)];
197 	else
198 		peer = start_peer->next;
199 
200 	while (peer != 0) {
201 		if (NSRCADR(addr) == NSRCADR(&peer->srcadr)
202 		    && NSRCPORT(addr) == NSRCPORT(&peer->srcadr)) {
203 			if (mode == -1)
204 				return (peer);
205 			else if (peer->hmode == mode)
206 				break;
207 		}
208 		peer = peer->next;
209 	}
210 	return (peer);
211 }
212 
213 
214 /*
215  * findpeer - find and return a peer in the hash table.
216  */
217 struct peer *
218 findpeer(
219 	struct sockaddr_in *srcadr,
220 	struct interface *dstadr,
221 	int fd,
222 	int pkt_mode,
223 	int *action
224 	)
225 {
226 	register struct peer *peer;
227 	int hash;
228 
229 	findpeer_calls++;
230 	hash = HASH_ADDR(srcadr);
231 	for (peer = peer_hash[hash]; peer != 0; peer = peer->next) {
232 		if (NSRCADR(srcadr) == NSRCADR(&peer->srcadr)
233 		    && NSRCPORT(srcadr) == NSRCPORT(&peer->srcadr)) {
234 
235 			/*
236 			 * if the association matching rules determine
237 			 * that this is not a valid combination, then
238 			 * look for the next valid peer association.
239 			 */
240 			*action = MATCH_ASSOC(peer->hmode, pkt_mode);
241 
242 			/*
243 			 * Sigh!  Check if BCLIENT peer in client
244 			 * server mode, else return error.
245 			 */
246 			if ((*action == AM_POSSBCL) && !(peer->flags &
247 			    FLAG_MCAST))
248 				*action = AM_ERR;
249 
250 			/*
251 			 * if an error was returned, exit back right
252 			 * here.
253 			 */
254 			if (*action == AM_ERR)
255 				return ((struct peer *)0);
256 
257 			/*
258 			 * if a match is found, we stop our search.
259 			 */
260 			if (*action != AM_NOMATCH)
261 				break;
262 		}
263 	}
264 
265 	/*
266 	 * If no matching association is found
267 	 */
268 	if (peer == 0) {
269 		*action = MATCH_ASSOC(NO_PEER, pkt_mode);
270 		return ((struct peer *)0);
271 	}
272 	peer->dstadr = dstadr;
273 	return (peer);
274 }
275 
276 /*
277  * findpeerbyassocid - find and return a peer using his association ID
278  */
279 struct peer *
280 findpeerbyassoc(
281 	u_int assoc
282 	)
283 {
284 	register struct peer *peer;
285 	int hash;
286 
287 	assocpeer_calls++;
288 
289 	hash = assoc & HASH_MASK;
290 	for (peer = assoc_hash[hash]; peer != 0; peer =
291 	    peer->ass_next) {
292 		if (assoc == peer->associd)
293 		    return (peer);
294 	}
295 	return (NULL);
296 }
297 
298 
299 /*
300  * clear_all - flush all time values for all associations
301  */
302 void
303 clear_all(void)
304 {
305 	struct peer *peer, *next_peer;
306 	int n;
307 
308 	/*
309 	 * This routine is called when the clock is stepped, and so all
310 	 * previously saved time values are untrusted.
311 	 */
312 	for (n = 0; n < HASH_SIZE; n++) {
313 		for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
314 			next_peer = peer->next;
315 			peer_clear(peer);
316 		}
317 	}
318 #ifdef DEBUG
319 	if (debug)
320 		printf("clear_all: at %lu\n", current_time);
321 #endif
322 }
323 
324 
325 /*
326  * unpeer - remove peer structure from hash table and free structure
327  */
328 void
329 unpeer(
330 	struct peer *peer_to_remove
331 	)
332 {
333 	int hash;
334 
335 	peer_associations--;
336 #ifdef DEBUG
337 	if (debug)
338 		printf("demobilize %u %d\n", peer_to_remove->associd,
339 		    peer_associations);
340 #endif
341 	peer_clear(peer_to_remove);
342 	hash = HASH_ADDR(&peer_to_remove->srcadr);
343 	peer_hash_count[hash]--;
344 	peer_demobilizations++;
345 #ifdef REFCLOCK
346 	/*
347 	 * If this peer is actually a clock, shut it down first
348 	 */
349 	if (peer_to_remove->flags & FLAG_REFCLOCK)
350 		refclock_unpeer(peer_to_remove);
351 #endif
352 	peer_to_remove->action = 0;	/* disable timeout actions */
353 	if (peer_hash[hash] == peer_to_remove)
354 		peer_hash[hash] = peer_to_remove->next;
355 	else {
356 		register struct peer *peer;
357 
358 		peer = peer_hash[hash];
359 		while (peer != 0 && peer->next != peer_to_remove)
360 		    peer = peer->next;
361 
362 		if (peer == 0) {
363 			peer_hash_count[hash]++;
364 			msyslog(LOG_ERR, "peer struct for %s not in table!",
365 				ntoa(&peer->srcadr));
366 		} else {
367 			peer->next = peer_to_remove->next;
368 		}
369 	}
370 
371 	/*
372 	 * Remove him from the association hash as well.
373 	 */
374 	hash = peer_to_remove->associd & HASH_MASK;
375 	assoc_hash_count[hash]--;
376 	if (assoc_hash[hash] == peer_to_remove)
377 		assoc_hash[hash] = peer_to_remove->ass_next;
378 	else {
379 		register struct peer *peer;
380 
381 		peer = assoc_hash[hash];
382 		while (peer != 0 && peer->ass_next != peer_to_remove)
383 		    peer = peer->ass_next;
384 
385 		if (peer == 0) {
386 			assoc_hash_count[hash]++;
387 			msyslog(LOG_ERR,
388 				"peer struct for %s not in association table!",
389 				ntoa(&peer->srcadr));
390 		} else {
391 			peer->ass_next = peer_to_remove->ass_next;
392 		}
393 	}
394 	peer_to_remove->next = peer_free;
395 	peer_free = peer_to_remove;
396 	peer_free_count++;
397 }
398 
399 
400 /*
401  * peer_config - configure a new association
402  */
403 struct peer *
404 peer_config(
405 	struct sockaddr_in *srcadr,
406 	struct interface *dstadr,
407 	int hmode,
408 	int version,
409 	int minpoll,
410 	int maxpoll,
411 	u_int flags,
412 	int ttl,
413 	keyid_t key,
414 	u_char *keystr
415 	)
416 {
417 	register struct peer *peer;
418 	u_int cast_flags;
419 
420 	/*
421 	 * First search from the beginning for an association with given
422 	 * remote address and mode. If an interface is given, search
423 	 * from there to find the association which matches that
424 	 * destination.
425 	 */
426 	peer = findexistingpeer(srcadr, (struct peer *)0, hmode);
427 	if (dstadr != 0) {
428 		while (peer != 0) {
429 			if (peer->dstadr == dstadr)
430 				break;
431 			peer = findexistingpeer(srcadr, peer, hmode);
432 		}
433 	}
434 
435 	/*
436 	 * We do a dirty little jig to figure the cast flags. This is
437 	 * probably not the best place to do this, at least until the
438 	 * configure code is rebuilt. Note only one flag can be set.
439 	 */
440 	switch (hmode) {
441 
442 	case MODE_BROADCAST:
443 		if (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr)))
444 			cast_flags = MDF_MCAST;
445 		else
446 			cast_flags = MDF_BCAST;
447 		break;
448 
449 	case MODE_CLIENT:
450 		if (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr)))
451 			cast_flags = MDF_ACAST;
452 		else
453 			cast_flags = MDF_UCAST;
454 		break;
455 
456 	default:
457 		cast_flags = MDF_UCAST;
458 		break;
459 	}
460 
461 	/*
462 	 * If the peer is already configured, some dope has a duplicate
463 	 * configureation entry or another dope is wiggling from afar.
464 	 */
465 	if (peer != 0) {
466 		peer->hmode = (u_char)hmode;
467 		peer->version = (u_char)version;
468 		peer->minpoll = (u_char)minpoll;
469 		peer->maxpoll = (u_char)maxpoll;
470 		peer->hpoll = peer->kpoll = peer->minpoll;
471 		peer->ppoll = peer->maxpoll;
472 		peer->flags = flags | FLAG_CONFIG |
473 			(peer->flags & FLAG_REFCLOCK);
474 		peer->cast_flags = cast_flags;
475 		peer->ttlmax = ttl;
476 		peer->keyid = key;
477 		return (peer);
478 	}
479 
480 	/*
481 	 * Here no match has been found, so presumably this is a new
482 	 * persistent association. Mobilize the thing and initialize its
483 	 * variables.
484 	 */
485 	peer = newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll,
486 	    flags | FLAG_CONFIG, cast_flags, ttl, key);
487 	return (peer);
488 }
489 
490 
491 /*
492  * newpeer - initialize a new peer association
493  */
494 struct peer *
495 newpeer(
496 	struct sockaddr_in *srcadr,
497 	struct interface *dstadr,
498 	int hmode,
499 	int version,
500 	int minpoll,
501 	int maxpoll,
502 	u_int flags,
503 	u_int cast_flags,
504 	int ttl,
505 	keyid_t key
506 	)
507 {
508 	register struct peer *peer;
509 	register int i;
510 
511 	/*
512 	 * Allocate a new peer structure. Some dirt here, since some of
513 	 * the initialization requires knowlege of our system state.
514 	 */
515 	if (peer_free_count == 0)
516 		getmorepeermem();
517 	peer = peer_free;
518 	peer_free = peer->next;
519 	peer_free_count--;
520 	peer_associations++;
521 	memset((char *)peer, 0, sizeof(struct peer));
522 
523 	/*
524 	 * Initialize the peer structure and dance the interface jig.
525 	 * Reference clocks step the loopback waltz, the others
526 	 * squaredance around the interface list looking for a buddy. If
527 	 * the dance peters out, there is always the wildcard interface.
528 	 * This might happen in some systems and would preclude proper
529 	 * operation with public key cryptography.
530 	 */
531 	if (ISREFCLOCKADR(srcadr))
532 		peer->dstadr = loopback_interface;
533 	else if (cast_flags & MDF_BCLNT)
534 		peer->dstadr = findbcastinter(srcadr);
535 	else if (dstadr != any_interface)
536 		peer->dstadr = dstadr;
537 	else
538 		peer->dstadr = findinterface(srcadr);
539 	peer->srcadr = *srcadr;
540 	peer->hmode = (u_char)hmode;
541 	peer->version = (u_char)version;
542 	peer->minpoll = (u_char)max(NTP_MINPOLL, minpoll);
543 	peer->maxpoll = (u_char)min(NTP_MAXPOLL, maxpoll);
544 	peer->flags = flags | (key > NTP_MAXKEY ? FLAG_SKEY : 0);
545 	peer->cast_flags = cast_flags;
546 	peer->ttlmax = ttl;
547 	peer->keyid = key;
548 	peer->precision = sys_precision;
549 	peer_clear(peer);
550 	if (mode_ntpdate)
551 		peer_ntpdate++;
552 
553 	/*
554 	 * Assign an association ID and increment the system variable.
555 	 */
556 	peer->associd = current_association_ID;
557 	if (++current_association_ID == 0)
558 		++current_association_ID;
559 
560 	/*
561 	 * Note time on statistics timers.
562 	 */
563 	peer->timereset = current_time;
564 	peer->timereachable = current_time;
565 	peer->timereceived = current_time;
566 #ifdef REFCLOCK
567 	if (ISREFCLOCKADR(&peer->srcadr)) {
568 		/*
569 		 * We let the reference clock support do clock
570 		 * dependent initialization.  This includes setting
571 		 * the peer timer, since the clock may have requirements
572 		 * for this.
573 		 */
574 		if (!refclock_newpeer(peer)) {
575 			/*
576 			 * Dump it, something screwed up
577 			 */
578 			peer->next = peer_free;
579 			peer_free = peer;
580 			peer_free_count++;
581 			return (NULL);
582 		}
583 	}
584 #endif
585 
586 	/*
587 	 * Put the new peer in the hash tables.
588 	 */
589 	i = HASH_ADDR(&peer->srcadr);
590 	peer->next = peer_hash[i];
591 	peer_hash[i] = peer;
592 	peer_hash_count[i]++;
593 	i = peer->associd & HASH_MASK;
594 	peer->ass_next = assoc_hash[i];
595 	assoc_hash[i] = peer;
596 	assoc_hash_count[i]++;
597 #ifdef DEBUG
598 	if (debug)
599 		printf(
600 		    "newpeer: %s->%s mode %d vers %d poll %d %d flags %x %x ttl %d key %08x\n",
601 		    ntoa(&peer->dstadr->sin), ntoa(&peer->srcadr),
602 		    peer->hmode, peer->version, peer->minpoll,
603 		    peer->maxpoll, peer->flags, peer->cast_flags,
604 		    peer->ttlmax, peer->keyid);
605 #endif
606 	return (peer);
607 }
608 
609 
610 /*
611  * peer_unconfig - remove the configuration bit from a peer
612  */
613 int
614 peer_unconfig(
615 	struct sockaddr_in *srcadr,
616 	struct interface *dstadr,
617 	int mode
618 	)
619 {
620 	register struct peer *peer;
621 	int num_found;
622 
623 	num_found = 0;
624 	peer = findexistingpeer(srcadr, (struct peer *)0, mode);
625 	while (peer != 0) {
626 		if (peer->flags & FLAG_CONFIG
627 		    && (dstadr == 0 || peer->dstadr == dstadr)) {
628 			num_found++;
629 
630 			/*
631 			 * Tricky stuff here. If the peer is polling us
632 			 * in active mode, turn off the configuration
633 			 * bit and make the mode passive. This allows us
634 			 * to avoid dumping a lot of history for peers
635 			 * we might choose to keep track of in passive
636 			 * mode. The protocol will eventually terminate
637 			 * undesirables on its own.
638 			 */
639 			if (peer->hmode == MODE_ACTIVE
640 			    && peer->pmode == MODE_ACTIVE) {
641 				peer->hmode = MODE_PASSIVE;
642 				peer->flags &= ~FLAG_CONFIG;
643 			} else {
644 				unpeer(peer);
645 				peer = 0;
646 			}
647 		}
648 		peer = findexistingpeer(srcadr, peer, mode);
649 	}
650 	return (num_found);
651 }
652 
653 /*
654  * peer_clr_stats - clear peer module stat counters
655  */
656 void
657 peer_clr_stats(void)
658 {
659 	findpeer_calls = 0;
660 	assocpeer_calls = 0;
661 	peer_allocations = 0;
662 	peer_demobilizations = 0;
663 	peer_timereset = current_time;
664 }
665 
666 /*
667  * peer_reset - reset stat counters in a peer structure
668  */
669 void
670 peer_reset(
671 	struct peer *peer
672 	)
673 {
674 	if (peer == 0)
675 	    return;
676 	peer->sent = 0;
677 	peer->received = 0;
678 	peer->processed = 0;
679 	peer->badauth = 0;
680 	peer->bogusorg = 0;
681 	peer->oldpkt = 0;
682 	peer->seldisptoolarge = 0;
683 	peer->selbroken = 0;
684 	peer->timereset = current_time;
685 }
686 
687 
688 /*
689  * peer_all_reset - reset all peer stat counters
690  */
691 void
692 peer_all_reset(void)
693 {
694 	struct peer *peer;
695 	int hash;
696 
697 	for (hash = 0; hash < HASH_SIZE; hash++)
698 	    for (peer = peer_hash[hash]; peer != 0; peer = peer->next)
699 		peer_reset(peer);
700 }
701 
702 
703 #ifdef AUTOKEY
704 /*
705  * expire_all - flush all crypto data and update timestamps.
706  */
707 void
708 expire_all(void)
709 {
710 	struct peer *peer, *next_peer;
711 	int n;
712 
713 	/*
714 	 * This routine is called about once per day from the timer
715 	 * routine and when the client is first synchronized. Search the
716 	 * peer list for all associations and flush only the key list
717 	 * and cookie. If a manycast client association, flush
718 	 * everything. Then, recompute and sign the agreement public
719 	 * value, if present.
720 	 */
721 	for (n = 0; n < HASH_SIZE; n++) {
722 		for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
723 			next_peer = peer->next;
724 			if (peer->cast_flags & MDF_ACAST) {
725 				peer_clear(peer);
726 #ifdef AUTOKEY
727 			} else {
728 				key_expire(peer);
729 				peer->pcookie.tstamp = 0;
730 #endif /* AUTOKEY */
731 			}
732 
733 		}
734 	}
735 	sys_private = (u_int32)RANDOM & 0xffffffff;
736 #ifdef PUBKEY
737 	crypto_agree();
738 #endif /* PUBKEY */
739 #ifdef DEBUG
740 	if (debug)
741 		printf("expire_all: at %lu\n", current_time);
742 #endif
743 }
744 #endif /* AUTOKEY */
745 
746 
747 /*
748  * findmanycastpeer - find and return a manycast peer
749  */
750 struct peer *
751 findmanycastpeer(
752 	struct recvbuf *rbufp
753 	)
754 {
755 	register struct peer *peer;
756 	struct pkt *pkt;
757 	l_fp p_org;
758 	int i;
759 
760  	/*
761  	 * This routine is called upon arrival of a client-mode message
762 	 * from a manycast server. Search the peer list for a manycast
763 	 * client association where the last transmit timestamp matches
764 	 * the originate timestamp. This assumes the transmit timestamps
765 	 * for possibly more than one manycast association are unique.
766 	 */
767 	pkt = &rbufp->recv_pkt;
768 	for (i = 0; i < HASH_SIZE; i++) {
769 		if (peer_hash_count[i] == 0)
770 			continue;
771 
772 		for (peer = peer_hash[i]; peer != 0; peer =
773 		    peer->next) {
774 			if (peer->cast_flags & MDF_ACAST) {
775 				NTOHL_FP(&pkt->org, &p_org);
776 				if (L_ISEQU(&peer->xmt, &p_org))
777 					return (peer);
778 			}
779 		}
780 	}
781 	return (NULL);
782 }
783 
784 
785 /*
786  * resetmanycast - reset all manycast clients
787  */
788 void
789 resetmanycast(void)
790 {
791 	register struct peer *peer;
792 	int i;
793 
794 	/*
795 	 * This routine is called when the number of client associations
796 	 * falls below the minimum. Search the peer list for manycast
797 	 * client associations and reset the ttl and poll interval.
798 	 */
799 	for (i = 0; i < HASH_SIZE; i++) {
800 		if (peer_hash_count[i] == 0)
801 			continue;
802 
803 		for (peer = peer_hash[i]; peer != 0; peer =
804 		    peer->next) {
805 			if (peer->cast_flags & MDF_ACAST) {
806 				peer->ttl = 0;
807 				poll_update(peer, peer->hpoll);
808 			}
809 		}
810 	}
811 }
812