Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / ntp / ntpd / ntp_peer.c
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 }