2 * ntp_peer.c - management of data maintained for peer associations
12 #include "ntp_lists.h"
13 #include "ntp_stdlib.h"
14 #include "ntp_control.h"
15 #include <ntp_random.h>
18 * Table of valid association combinations
19 * ---------------------------------------
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
30 * BCLIENT | e 0 0 0 e 1
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.
39 #define AM_MODES 7 /* number of rows and columns */
40 #define NO_PEER 0 /* action when no peer is found */
42 int AM[AM_MODES][AM_MODES] = {
44 /* peer { UNSPEC, ACTIVE, PASSIVE, CLIENT, SERVER, BCAST } */
46 /*NONE*/{ AM_ERR, AM_NEWPASS, AM_NOMATCH, AM_FXMIT, AM_MANYCAST, AM_NEWBCL},
48 /*A*/ { AM_ERR, AM_PROCPKT, AM_PROCPKT, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
50 /*P*/ { AM_ERR, AM_PROCPKT, AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
52 /*C*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_PROCPKT, AM_NOMATCH},
54 /*S*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
56 /*BCST*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
58 /*BCL*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_PROCPKT},
61 #define MATCH_ASSOC(x, y) AM[(x)][(y)]
64 * These routines manage the allocation of memory to peer structures
65 * and the maintenance of three data structures involving all peers:
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.
72 * They also maintain a free list of peer structures, peer_free.
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.
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 */
91 * Association ID. We initialize this value randomly, then assign a new
92 * value every time an association is mobilized.
94 static associd_t current_association_ID; /* association ID */
95 static associd_t initial_association_ID; /* association ID */
98 * Memory allocation watermarks.
100 #define INIT_PEER_ALLOC 8 /* static preallocation */
101 #define INC_PEER_ALLOC 4 /* add N more when empty */
104 * Miscellaneous statistic counters which may be queried.
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 */
116 static struct peer * findexistingpeer_name(const char *, u_short,
118 static struct peer * findexistingpeer_addr(sockaddr_u *,
121 static void free_peer(struct peer *, int);
122 static void getmorepeermem(void);
123 static int score(struct peer *);
127 * init_peer - initialize peer data structures and counters
129 * N.B. We use the random number routine in here. It had better be
130 * initialized prior to getting here.
138 * Initialize peer free list from static allocation.
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);
146 * Initialize our first association ID
149 current_association_ID = ntp_random() & ASSOCID_MAX;
150 while (!current_association_ID);
151 initial_association_ID = current_association_ID;
156 * getmorepeermem - add more peer structures to the free list
164 peers = eallocarray(INC_PEER_ALLOC, sizeof(*peers));
166 for (i = INC_PEER_ALLOC - 1; i >= 0; i--)
167 LINK_SLIST(peer_free, &peers[i], p_link);
169 total_peer_structs += INC_PEER_ALLOC;
170 peer_free_count += INC_PEER_ALLOC;
175 findexistingpeer_name(
176 const char * hostname,
178 struct peer * start_peer,
184 if (NULL == start_peer)
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))
202 findexistingpeer_addr(
204 struct peer * start_peer,
211 DPRINTF(2, ("findexistingpeer_addr(%s, %s, %d, 0x%x)\n",
214 ? sptoa(&start_peer->srcadr)
216 mode, (u_int)cast_flags));
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).
228 if (NULL == start_peer)
229 peer = peer_hash[NTP_HASH_ADDR(addr)];
231 peer = start_peer->adr_link;
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"));
245 peer = peer->adr_link;
253 * findexistingpeer - search by address and return a pointer to a peer.
258 const char * hostname,
259 struct peer * start_peer,
264 if (hostname != NULL)
265 return findexistingpeer_name(hostname, AF(addr),
268 return findexistingpeer_addr(addr, start_peer, mode,
274 * findpeer - find and return a peer match for a received datagram in
275 * the peer_hash table.
277 * [Bug 3072] To faciliate a faster reorganisation after routing changes
278 * the original code re-assigned the peer address to be the destination
279 * of the received packet and initiated another round on a mismatch.
280 * Unfortunately this leaves us wide open for a DoS attack where the
281 * attacker directs a packet with forged destination address to us --
282 * this results in a wrong interface assignment, actually creating a DoS
285 * This condition would persist until the next update of the interface
286 * list, but a continued attack would put us out of business again soon
287 * enough. Authentication alone does not help here, since it does not
288 * protect the UDP layer and leaves us open for a replay attack.
290 * So we do not update the adresses and wait until the next interface
291 * list update does the right thing for us.
295 struct recvbuf *rbufp,
307 srcadr = &rbufp->recv_srcadr;
308 hash = NTP_HASH_ADDR(srcadr);
309 for (p = peer_hash[hash]; p != NULL; p = p->adr_link) {
311 /* [Bug 3072] ensure interface of peer matches */
312 /* [Bug 3356] ... if NOT a broadcast peer! */
313 if (p->hmode != MODE_BCLIENT && p->dstadr != rbufp->dstadr)
316 /* ensure peer source address matches */
317 if ( ! ADDR_PORT_EQ(srcadr, &p->srcadr))
320 /* If the association matching rules determine that this
321 * is not a valid combination, then look for the next
322 * valid peer association.
324 *action = MATCH_ASSOC(p->hmode, pkt_mode);
326 /* A response to our manycastclient solicitation might
327 * be misassociated with an ephemeral peer already spun
328 * for the server. If the packet's org timestamp
329 * doesn't match the peer's, check if it matches the
330 * ACST prototype peer's. If so it is a redundant
331 * solicitation response, return AM_ERR to discard it.
334 if (MODE_SERVER == pkt_mode && AM_PROCPKT == *action) {
335 pkt = &rbufp->recv_pkt;
336 NTOHL_FP(&pkt->org, &pkt_org);
337 if (!L_ISEQU(&p->aorg, &pkt_org) &&
338 findmanycastpeer(rbufp))
342 /* if an error was returned, exit back right here. */
343 if (*action == AM_ERR)
346 /* if a match is found, we stop our search. */
347 if (*action != AM_NOMATCH)
351 /* If no matching association is found... */
353 *action = MATCH_ASSOC(NO_PEER, pkt_mode);
359 * findpeerbyassoc - find and return a peer using his association ID
370 hash = assoc & NTP_HASH_MASK;
371 for (p = assoc_hash[hash]; p != NULL; p = p->aid_link)
372 if (assoc == p->associd)
379 * clear_all - flush all time values for all associations
387 * This routine is called when the clock is stepped, and so all
388 * previously saved time values are untrusted.
390 for (p = peer_list; p != NULL; p = p->p_link)
391 if (!(MDF_TXONLY_MASK & p->cast_flags))
392 peer_clear(p, "STEP");
394 DPRINTF(1, ("clear_all: at %lu\n", current_time));
399 * score_all() - determine if an association can be demobilized
403 struct peer *peer /* peer structure pointer */
411 * This routine finds the minimum score for all preemptible
412 * associations and returns > 0 if the association can be
417 for (speer = peer_list; speer != NULL; speer = speer->p_link)
418 if (speer->flags & FLAG_PREEMPT) {
423 DPRINTF(1, ("score_all: at %lu score %d min %d\n",
424 current_time, tamp, temp));
434 * score() - calculate preemption score
438 struct peer *peer /* peer structure pointer */
444 * This routine calculates the premption score from the peer
445 * error bits and status. Increasing values are more cherished.
448 if (!(peer->flash & TEST10))
449 temp++; /* 1 good synch and stratum */
450 if (!(peer->flash & TEST13))
451 temp++; /* 2 reachable */
452 if (!(peer->flash & TEST12))
453 temp++; /* 3 no loop */
454 if (!(peer->flash & TEST11))
455 temp++; /* 4 good distance */
456 if (peer->status >= CTL_PST_SEL_SELCAND)
457 temp++; /* 5 in the hunt */
458 if (peer->status != CTL_PST_SEL_EXCESS)
459 temp++; /* 6 not spare tire */
460 return (temp); /* selection status */
465 * free_peer - internal routine to free memory referred to by a struct
466 * peer and return it to the peer free list. If unlink is
467 * nonzero, unlink from the various lists.
475 struct peer * unlinked;
479 hash = NTP_HASH_ADDR(&p->srcadr);
480 peer_hash_count[hash]--;
482 UNLINK_SLIST(unlinked, peer_hash[hash], p, adr_link,
484 if (NULL == unlinked) {
485 peer_hash_count[hash]++;
486 msyslog(LOG_ERR, "peer %s not in address table!",
491 * Remove him from the association hash as well.
493 hash = p->associd & NTP_HASH_MASK;
494 assoc_hash_count[hash]--;
496 UNLINK_SLIST(unlinked, assoc_hash[hash], p, aid_link,
498 if (NULL == unlinked) {
499 assoc_hash_count[hash]++;
501 "peer %s not in association ID table!",
505 /* Remove him from the overall list. */
506 UNLINK_SLIST(unlinked, peer_list, p, p_link,
508 if (NULL == unlinked)
509 msyslog(LOG_ERR, "%s not in peer list!",
513 if (p->hostname != NULL)
516 if (p->ident != NULL)
519 if (p->addrs != NULL)
520 free(p->addrs); /* from copy_addrinfo_list() */
522 /* Add his corporeal form to peer free list */
524 LINK_SLIST(peer_free, p, p_link);
530 * unpeer - remove peer structure from hash table and free structure
537 mprintf_event(PEVNT_DEMOBIL, peer, "assoc %u", peer->associd);
538 restrict_source(&peer->srcadr, 1, 0);
539 set_peerdstadr(peer, NULL);
540 peer_demobilizations++;
542 if (FLAG_PREEMPT & peer->flags)
546 * If this peer is actually a clock, shut it down first
548 if (FLAG_REFCLOCK & peer->flags)
549 refclock_unpeer(peer);
552 free_peer(peer, TRUE);
557 * peer_config - configure a new association
562 const char * hostname,
571 const char * ident /* autokey group */
577 * We do a dirty little jig to figure the cast flags. This is
578 * probably not the best place to do this, at least until the
579 * configure code is rebuilt. Note only one flag can be set.
583 if (IS_MCAST(srcadr))
584 cast_flags = MDF_MCAST;
586 cast_flags = MDF_BCAST;
590 if (hostname != NULL && SOCK_UNSPEC(srcadr))
591 cast_flags = MDF_POOL;
592 else if (IS_MCAST(srcadr))
593 cast_flags = MDF_ACAST;
595 cast_flags = MDF_UCAST;
599 cast_flags = MDF_UCAST;
603 * Mobilize the association and initialize its variables. If
604 * emulating ntpdate, force iburst. For pool and manycastclient
605 * strip FLAG_PREEMPT as the prototype associations are not
606 * themselves preemptible, though the resulting associations
609 flags |= FLAG_CONFIG;
611 flags |= FLAG_IBURST;
612 if ((MDF_ACAST | MDF_POOL) & cast_flags)
613 flags &= ~FLAG_PREEMPT;
614 return newpeer(srcadr, hostname, dstadr, hmode, version,
615 minpoll, maxpoll, flags, cast_flags, ttl, key, ident);
619 * setup peer dstadr field keeping it in sync with the interface
628 struct peer * unlinked;
630 DEBUG_INSIST(p != NULL);
635 /* check for impossible or identical assignment */
636 if (p->dstadr == dstadr)
640 * Don't accept updates to a separate multicast receive-only
641 * endpt while a BCLNT peer is running its unicast protocol.
643 if (dstadr != NULL && (FLAG_BC_VOL & p->flags) &&
644 (INT_MCASTIF & dstadr->flags) && MODE_CLIENT == p->hmode) {
648 /* unlink from list if we have an address prior to assignment */
649 if (p->dstadr != NULL) {
650 p->dstadr->peercnt--;
651 UNLINK_SLIST(unlinked, p->dstadr->peers, p, ilink,
653 msyslog(LOG_INFO, "%s local addr %s -> %s",
654 stoa(&p->srcadr), latoa(p->dstadr),
660 /* link to list if we have an address after assignment */
661 if (p->dstadr != NULL) {
662 LINK_SLIST(dstadr->peers, p, ilink);
668 * attempt to re-rebind interface if necessary
671 peer_refresh_interface(
678 niface = select_peerinterface(p, &p->srcadr, NULL);
681 "peer_refresh_interface: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %u key %08x: new interface: ",
682 p->dstadr == NULL ? "<null>" :
683 stoa(&p->dstadr->sin), stoa(&p->srcadr), p->hmode,
684 p->version, p->minpoll, p->maxpoll, p->flags, p->cast_flags,
686 if (niface != NULL) {
688 "fd=%d, bfd=%d, name=%.16s, flags=0x%x, ifindex=%u, sin=%s",
689 niface->fd, niface->bfd, niface->name,
690 niface->flags, niface->ifindex,
691 stoa(&niface->sin)));
692 if (niface->flags & INT_BROADCAST)
693 DPRINTF(4, (", bcast=%s",
694 stoa(&niface->bcast)));
695 DPRINTF(4, (", mask=%s\n", stoa(&niface->mask)));
697 DPRINTF(4, ("<NONE>\n"));
701 set_peerdstadr(p, niface);
702 if (p->dstadr != NULL) {
704 * clear crypto if we change the local address
706 if (p->dstadr != piface && !(MDF_ACAST & p->cast_flags)
707 && MODE_BROADCAST != p->pmode)
708 peer_clear(p, "XFAC");
711 * Broadcast needs the socket enabled for broadcast
713 if (MDF_BCAST & p->cast_flags)
714 enable_broadcast(p->dstadr, &p->srcadr);
717 * Multicast needs the socket interface enabled for
720 if (MDF_MCAST & p->cast_flags)
721 enable_multicast_if(p->dstadr, &p->srcadr);
727 * refresh_all_peerinterfaces - see that all interface bindings are up
731 refresh_all_peerinterfaces(void)
736 * this is called when the interface list has changed
737 * give all peers a chance to find a better interface
738 * but only if either they don't have an address already
739 * or if the one they have hasn't worked for a while.
741 for (p = peer_list; p != NULL; p = p->p_link) {
742 if (!(p->dstadr && (p->reach & 0x3))) // Bug 2849 XOR 2043
743 peer_refresh_interface(p);
749 * newpeer - initialize a new peer association
754 const char * hostname,
770 DEBUG_REQUIRE(srcadr);
774 * If Autokey is requested but not configured, complain loudly.
777 if (key > NTP_MAXKEY) {
780 } else if (flags & FLAG_SKEY) {
781 msyslog(LOG_ERR, "Autokey not configured");
788 * For now only pool associations have a hostname.
790 INSIST(NULL == hostname || (MDF_POOL & cast_flags));
793 * First search from the beginning for an association with given
794 * remote address and mode. If an interface is given, search
795 * from there to find the association which matches that
796 * destination. If the given interface is "any", track down the
797 * actual interface, because that's what gets put into the peer
800 if (dstadr != NULL) {
801 peer = findexistingpeer(srcadr, hostname, NULL, hmode,
803 while (peer != NULL) {
804 if (peer->dstadr == dstadr ||
805 ((MDF_BCLNT & cast_flags) &&
806 (MDF_BCLNT & peer->cast_flags)))
809 if (dstadr == ANY_INTERFACE_CHOOSE(srcadr) &&
810 peer->dstadr == findinterface(srcadr))
813 peer = findexistingpeer(srcadr, hostname, peer,
817 /* no endpt address given */
818 peer = findexistingpeer(srcadr, hostname, NULL, hmode,
823 * If a peer is found, this would be a duplicate and we don't
824 * allow that. This avoids duplicate ephemeral (broadcast/
825 * multicast) and preemptible (manycast and pool) client
829 DPRINTF(2, ("newpeer(%s) found existing association\n",
837 * Allocate a new peer structure. Some dirt here, since some of
838 * the initialization requires knowlege of our system state.
840 if (peer_free_count == 0)
842 UNLINK_HEAD_SLIST(peer, peer_free, p_link);
843 INSIST(peer != NULL);
846 if (FLAG_PREEMPT & flags)
850 * Assign an association ID and increment the system variable.
852 peer->associd = current_association_ID;
853 if (++current_association_ID == 0)
854 ++current_association_ID;
856 peer->srcadr = *srcadr;
857 if (hostname != NULL)
858 peer->hostname = estrdup(hostname);
860 peer->version = version;
862 peer->cast_flags = cast_flags;
864 select_peerinterface(peer, srcadr, dstadr));
867 * It is an error to set minpoll less than NTP_MINPOLL or to
868 * set maxpoll greater than NTP_MAXPOLL. However, minpoll is
869 * clamped not greater than NTP_MAXPOLL and maxpoll is clamped
870 * not less than NTP_MINPOLL without complaint. Finally,
871 * minpoll is clamped not greater than maxpoll.
874 peer->minpoll = NTP_MINDPOLL;
876 peer->minpoll = min(minpoll, NTP_MAXPOLL);
878 peer->maxpoll = NTP_MAXDPOLL;
880 peer->maxpoll = max(maxpoll, NTP_MINPOLL);
881 if (peer->minpoll > peer->maxpoll)
882 peer->minpoll = peer->maxpoll;
884 if (peer->dstadr != NULL)
885 DPRINTF(3, ("newpeer(%s): using fd %d and our addr %s\n",
886 stoa(srcadr), peer->dstadr->fd,
887 stoa(&peer->dstadr->sin)));
889 DPRINTF(3, ("newpeer(%s): local interface currently not bound\n",
893 * Broadcast needs the socket enabled for broadcast
895 if ((MDF_BCAST & cast_flags) && peer->dstadr != NULL)
896 enable_broadcast(peer->dstadr, srcadr);
899 * Multicast needs the socket interface enabled for multicast
901 if ((MDF_MCAST & cast_flags) && peer->dstadr != NULL)
902 enable_multicast_if(peer->dstadr, srcadr);
905 if (key > NTP_MAXKEY)
906 peer->flags |= FLAG_SKEY;
911 peer->ident = estrdup(ident);
912 peer->precision = sys_precision;
913 peer->hpoll = peer->minpoll;
914 if (cast_flags & MDF_ACAST)
915 peer_clear(peer, "ACST");
916 else if (cast_flags & MDF_POOL)
917 peer_clear(peer, "POOL");
918 else if (cast_flags & MDF_MCAST)
919 peer_clear(peer, "MCST");
920 else if (cast_flags & MDF_BCAST)
921 peer_clear(peer, "BCST");
923 peer_clear(peer, "INIT");
928 * Note time on statistics timers.
930 peer->timereset = current_time;
931 peer->timereachable = current_time;
932 peer->timereceived = current_time;
934 if (ISREFCLOCKADR(&peer->srcadr)) {
937 * We let the reference clock support do clock
938 * dependent initialization. This includes setting
939 * the peer timer, since the clock may have requirements
943 peer->maxpoll = peer->minpoll;
944 if (!refclock_newpeer(peer)) {
946 * Dump it, something screwed up
948 set_peerdstadr(peer, NULL);
953 msyslog(LOG_ERR, "refclock %s isn't supported. ntpd was compiled without refclock support.",
954 stoa(&peer->srcadr));
955 set_peerdstadr(peer, NULL);
958 #endif /* REFCLOCK */
962 * Put the new peer in the hash tables.
964 hash = NTP_HASH_ADDR(&peer->srcadr);
965 LINK_SLIST(peer_hash[hash], peer, adr_link);
966 peer_hash_count[hash]++;
967 hash = peer->associd & NTP_HASH_MASK;
968 LINK_SLIST(assoc_hash[hash], peer, aid_link);
969 assoc_hash_count[hash]++;
970 LINK_SLIST(peer_list, peer, p_link);
972 restrict_source(&peer->srcadr, 0, 0);
973 mprintf_event(PEVNT_MOBIL, peer, "assoc %d", peer->associd);
974 DPRINTF(1, ("newpeer: %s->%s mode %u vers %u poll %u %u flags 0x%x 0x%x ttl %u key %08x\n",
975 latoa(peer->dstadr), stoa(&peer->srcadr), peer->hmode,
976 peer->version, peer->minpoll, peer->maxpoll, peer->flags,
977 peer->cast_flags, peer->ttl, peer->keyid));
983 * peer_clr_stats - clear peer module statistics counters
990 peer_allocations = 0;
991 peer_demobilizations = 0;
992 peer_timereset = current_time;
997 * peer_reset - reset statistics counters
1007 peer->timereset = current_time;
1010 peer->processed = 0;
1014 peer->seldisptoolarge = 0;
1015 peer->selbroken = 0;
1020 * peer_all_reset - reset all peer statistics counters
1023 peer_all_reset(void)
1027 for (peer = peer_list; peer != NULL; peer = peer->p_link)
1033 * findmanycastpeer - find and return a manycastclient or pool
1034 * association matching a received response.
1038 struct recvbuf *rbufp /* receive buffer pointer */
1046 * This routine is called upon arrival of a server-mode response
1047 * to a manycastclient multicast solicitation, or to a pool
1048 * server unicast solicitation. Search the peer list for a
1049 * manycastclient association where the last transmit timestamp
1050 * matches the response packet's originate timestamp. There can
1051 * be multiple manycastclient associations, or multiple pool
1052 * solicitation assocations, so this assumes the transmit
1053 * timestamps are unique for such.
1055 pkt = &rbufp->recv_pkt;
1056 for (peer = peer_list; peer != NULL; peer = peer->p_link)
1057 if (MDF_SOLICIT_MASK & peer->cast_flags) {
1058 NTOHL_FP(&pkt->org, &p_org);
1059 if (L_ISEQU(&p_org, &peer->aorg))
1066 /* peer_cleanup - clean peer list prior to shutdown */
1067 void peer_cleanup(void)
1072 for (assoc = initial_association_ID; assoc != current_association_ID; assoc++) {
1074 peer = findpeerbyassoc(assoc);
1079 peer = findpeerbyassoc(current_association_ID);