diff options
Diffstat (limited to 'contrib/ntp/ntpd/ntp_peer.c')
-rw-r--r-- | contrib/ntp/ntpd/ntp_peer.c | 566 |
1 files changed, 291 insertions, 275 deletions
diff --git a/contrib/ntp/ntpd/ntp_peer.c b/contrib/ntp/ntpd/ntp_peer.c index 90646ab..b164181 100644 --- a/contrib/ntp/ntpd/ntp_peer.c +++ b/contrib/ntp/ntpd/ntp_peer.c @@ -10,6 +10,9 @@ #include "ntpd.h" #include "ntp_stdlib.h" +#ifdef AUTOKEY +#include "ntp_crypto.h" +#endif /* AUTOKEY */ /* * Table of valid association combinations @@ -27,15 +30,13 @@ * CONTROL | e 0 0 0 0 0 * PRIVATE | e 0 0 0 0 0 * BCLIENT | e 0 0 0 e 1 - * MCLIENT | e 0 0 0 0 0 * - * One point to note here: - * a packet in BCAST mode can potentially match a peer in CLIENT - * mode, but we that is a special case and we check for that early - * in the decision process. This avoids having to keep track of - * what kind of associations are possible etc... We actually - * circumvent that problem by requiring that the first b(m)roadcast - * received after the change back to BCLIENT mode sets the clock. + * One point to note here: a packet in BCAST mode can potentially match + * a peer in CLIENT mode, but we that is a special case and we check for + * that early in the decision process. This avoids having to keep track + * of what kind of associations are possible etc... We actually + * circumvent that problem by requiring that the first b(m)roadcast + * received after the change back to BCLIENT mode sets the clock. */ int AM[AM_MODES][AM_MODES] = { @@ -58,82 +59,59 @@ int AM[AM_MODES][AM_MODES] = { /*PRIV*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH}, /*BCL*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_ERR, AM_PROCPKT}, - -/*MCL*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH} }; #define MATCH_ASSOC(x,y) AM[(x)][(y)] /* * These routines manage the allocation of memory to peer structures - * and the maintenance of the peer hash table. The two main entry - * points are findpeer(), which looks for corresponding peer data - * in the peer list, newpeer(), which allocates a new peer structure - * and adds it to the list, and unpeer(), which demobilizes the association + * and the maintenance of the peer hash table. The two main entry + * points are findpeer(), which looks for matching peer sturctures in + * the peer list, newpeer(), which allocates a new peer structure and + * adds it to the list, and unpeer(), which demobilizes the association * and deallocates the structure. */ - -/* - * The peer hash table (imported by the protocol module). - */ -struct peer *peer_hash[HASH_SIZE]; -int peer_hash_count[HASH_SIZE]; /* count of peers in each bucket */ - /* - * The association ID hash table. Used for lookups by association ID + * Peer hash tables */ -struct peer *assoc_hash[HASH_SIZE]; -int assoc_hash_count[HASH_SIZE]; +struct peer *peer_hash[HASH_SIZE]; /* peer hash table */ +int peer_hash_count[HASH_SIZE]; /* peers in each bucket */ +struct peer *assoc_hash[HASH_SIZE]; /* association ID hash table */ +int assoc_hash_count[HASH_SIZE]; /* peers in each bucket */ +static struct peer *peer_free; /* peer structures free list */ +int peer_free_count; /* count of free structures */ /* - * The free list. Clean structures only, please. - */ -static struct peer *peer_free; -int peer_free_count; - -/* - * Association ID. We initialize this value randomly, the assign a new + * Association ID. We initialize this value randomly, then assign a new * value every time the peer structure is incremented. */ -static u_short current_association_ID; +static associd_t current_association_ID; /* association ID */ /* * Memory allocation watermarks. */ -#define INIT_PEER_ALLOC 15 /* initialize space for 15 peers */ -#define INC_PEER_ALLOC 5 /* when we run out, add 5 more */ +#define INIT_PEER_ALLOC 15 /* initialize for 15 peers */ +#define INC_PEER_ALLOC 5 /* when run out, add 5 more */ /* * Miscellaneous statistic counters which may be queried. */ -u_long peer_timereset; /* time stat counters were zeroed */ -u_long findpeer_calls; /* number of calls to findpeer */ -u_long assocpeer_calls; /* number of calls to findpeerbyassoc */ -u_long peer_allocations; /* number of allocations from the free list */ -u_long peer_demobilizations; /* number of structs freed to free list */ -int total_peer_structs; /* number of peer structs in circulation */ -int peer_associations; /* number of active associations */ - -/* - * Our initial allocation of peer space - */ -static struct peer init_peer_alloc[INIT_PEER_ALLOC]; - -/* - * Initialization data. When configuring peers at initialization time, - * we try to get their poll update timers initialized to different values - * to prevent us from sending big clumps of data all at once. - */ -/* static u_long init_peer_starttime; */ +u_long peer_timereset; /* time stat counters zeroed */ +u_long findpeer_calls; /* calls to findpeer */ +u_long assocpeer_calls; /* calls to findpeerbyassoc */ +u_long peer_allocations; /* allocations from free list */ +u_long peer_demobilizations; /* structs freed to free list */ +int total_peer_structs; /* peer structs */ +int peer_associations; /* active associations */ +static struct peer init_peer_alloc[INIT_PEER_ALLOC]; /* init alloc */ static void getmorepeermem P((void)); -static void key_expire P((struct peer *)); /* * init_peer - initialize peer data structures and counters * - * N.B. We use the random number routine in here. It had better be - * initialized prior to getting here. + * N.B. We use the random number routine in here. It had better be + * initialized prior to getting here. */ void init_peer(void) @@ -157,11 +135,6 @@ init_peer(void) assocpeer_calls = peer_demobilizations = 0; /* - * Initialization counter. - */ - /* init_peer_starttime = 0; */ - - /* * Initialize peer memory. */ peer_free = 0; @@ -175,7 +148,7 @@ init_peer(void) /* * Initialize our first association ID */ - current_association_ID = (u_short)ranp2(16); + current_association_ID = (associd_t)ranp2(16); if (current_association_ID == 0) current_association_ID = 1; } @@ -190,7 +163,8 @@ getmorepeermem(void) register int i; register struct peer *peer; - peer = (struct peer *)emalloc(INC_PEER_ALLOC*sizeof(struct peer)); + peer = (struct peer *)emalloc(INC_PEER_ALLOC * + sizeof(struct peer)); for (i = 0; i < INC_PEER_ALLOC; i++) { peer->next = peer_free; peer_free = peer; @@ -202,7 +176,6 @@ getmorepeermem(void) } - /* * findexistingpeer - return a pointer to a peer in the hash table */ @@ -220,22 +193,21 @@ findexistingpeer( * same peer through different interfaces in the hash table. */ if (start_peer == 0) - peer = peer_hash[HASH_ADDR(addr)]; + peer = peer_hash[HASH_ADDR(addr)]; else - peer = start_peer->next; + peer = start_peer->next; while (peer != 0) { if (NSRCADR(addr) == NSRCADR(&peer->srcadr) && NSRCPORT(addr) == NSRCPORT(&peer->srcadr)) { if (mode == -1) - return peer; + return (peer); else if (peer->hmode == mode) break; } peer = peer->next; } - - return peer; + return (peer); } @@ -259,50 +231,46 @@ findpeer( for (peer = peer_hash[hash]; peer != 0; peer = peer->next) { if (NSRCADR(srcadr) == NSRCADR(&peer->srcadr) && NSRCPORT(srcadr) == NSRCPORT(&peer->srcadr)) { + /* - * if the association matching rules determine that - * this is not a valid combination, then look for - * the next valid peer association. + * if the association matching rules determine + * that this is not a valid combination, then + * look for the next valid peer association. */ *action = MATCH_ASSOC(peer->hmode, pkt_mode); /* * Sigh! Check if BCLIENT peer in client - * server mode, else return error + * server mode, else return error. */ - if ((*action == AM_POSSBCL) && - !(peer->cast_flags & FLAG_MCAST1)) { + if ((*action == AM_POSSBCL) && !(peer->flags & + FLAG_MCAST)) *action = AM_ERR; - } - /* if an error was returned, exit back right here */ + /* + * if an error was returned, exit back right + * here. + */ if (*action == AM_ERR) - return (struct peer *)0; + return ((struct peer *)0); - /* if a match is found, we stop our search */ + /* + * if a match is found, we stop our search. + */ if (*action != AM_NOMATCH) break; } } -#ifdef DEBUG - if (debug > 1) - printf("pkt_mode %d action %d\n", pkt_mode, *action); -#endif - /* if no matching association is found */ + /* + * If no matching association is found + */ if (peer == 0) { *action = MATCH_ASSOC(NO_PEER, pkt_mode); -#ifdef DEBUG - if (debug > 1) - printf("pkt_mode %d action %d\n", pkt_mode, *action); -#endif - return (struct peer *)0; + return ((struct peer *)0); } - - /* reset the default interface to something more meaningful */ - if ((peer->dstadr == any_interface)) - peer->dstadr = dstadr; - return peer; + peer->dstadr = dstadr; + return (peer); } /* @@ -310,7 +278,7 @@ findpeer( */ struct peer * findpeerbyassoc( - int assoc + u_int assoc ) { register struct peer *peer; @@ -319,101 +287,41 @@ findpeerbyassoc( assocpeer_calls++; hash = assoc & HASH_MASK; - for (peer = assoc_hash[hash]; peer != 0; peer = peer->ass_next) { - if ((u_short)assoc == peer->associd) - return peer; /* got it! */ + for (peer = assoc_hash[hash]; peer != 0; peer = + peer->ass_next) { + if (assoc == peer->associd) + return (peer); } - - /* - * Out of luck. Return 0. - */ - return (struct peer *)0; + return (NULL); } -/* - * findmanycastpeer - find and return an manycast peer if it exists - * - * - * the current implementation loops across all hash-buckets - * - * *** THERE IS AN URGENT NEED TO CHANGE THIS *** - */ -struct peer * -findmanycastpeer( - l_fp *p_org - ) -{ - register struct peer *peer; - register struct peer *manycast_peer = 0; - int i = 0; - - for (i = 0; i < HASH_SIZE; i++) { - if (peer_hash_count[i] == 0) - continue; - - for (peer = peer_hash[i]; peer != 0; peer = peer->next) { - if (peer->cast_flags & MDF_ACAST && - peer->flags & FLAG_CONFIG) { - if (L_ISEQU(&peer->xmt, p_org)) - return peer; /* got it */ - else - manycast_peer = peer; - } - } - } - - /* - * Out of luck. Return the manycastpeer for what it is worth. - */ - return manycast_peer; -} - -/* - * key_expire - garbage collect keys - */ -static void -key_expire( - struct peer *peer - ) -{ - int i; - - if (peer->keylist != 0) { - for (i = 0; i <= peer->keynumber; i++) - authtrust(peer->keylist[i], 0); - free(peer->keylist); - peer->keylist = 0; - } - if (peer->keyid > NTP_MAXKEY) { - authtrust(peer->keyid, 0); - peer->keyid = 0; - } -} /* - * key_rekey - expire all keys and roll a new private value. Note the - * 32-bit mask is necessary for 64-bit u_longs. + * clear_all - flush all time values for all associations */ void -key_expire_all( - ) +clear_all(void) { struct peer *peer, *next_peer; int n; + /* + * This routine is called when the clock is stepped, and so all + * previously saved time values are untrusted. + */ for (n = 0; n < HASH_SIZE; n++) { for (peer = peer_hash[n]; peer != 0; peer = next_peer) { next_peer = peer->next; - key_expire(peer); + peer_clear(peer); } } - sys_private = (u_long)RANDOM & 0xffffffff; #ifdef DEBUG if (debug) - printf("key_expire_all: at %lu private %08lx\n", - current_time, sys_private); + printf("clear_all: at %lu\n", current_time); #endif } + + /* * unpeer - remove peer structure from hash table and free structure */ @@ -424,16 +332,16 @@ unpeer( { int hash; + peer_associations--; #ifdef DEBUG - if (debug > 1) - printf("demobilize %u\n", peer_to_remove->associd); + if (debug) + printf("demobilize %u %d\n", peer_to_remove->associd, + peer_associations); #endif - key_expire(peer_to_remove); + peer_clear(peer_to_remove); hash = HASH_ADDR(&peer_to_remove->srcadr); peer_hash_count[hash]--; peer_demobilizations++; - peer_associations--; - #ifdef REFCLOCK /* * If this peer is actually a clock, shut it down first @@ -490,7 +398,7 @@ unpeer( /* - * peer_config - configure a new peer + * peer_config - configure a new association */ struct peer * peer_config( @@ -500,63 +408,83 @@ peer_config( int version, int minpoll, int maxpoll, - int flags, + u_int flags, int ttl, - u_long key + keyid_t key, + u_char *keystr ) { register struct peer *peer; + u_int cast_flags; /* - * See if we have this guy in the tables already. If - * so just mark him configured. + * First search from the beginning for an association with given + * remote address and mode. If an interface is given, search + * from there to find the association which matches that + * destination. */ peer = findexistingpeer(srcadr, (struct peer *)0, hmode); if (dstadr != 0) { while (peer != 0) { if (peer->dstadr == dstadr) - break; + break; peer = findexistingpeer(srcadr, peer, hmode); } } /* - * If we found one, just change his mode and mark him configured. + * We do a dirty little jig to figure the cast flags. This is + * probably not the best place to do this, at least until the + * configure code is rebuilt. Note only one flag can be set. + */ + switch (hmode) { + + case MODE_BROADCAST: + if (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr))) + cast_flags = MDF_MCAST; + else + cast_flags = MDF_BCAST; + break; + + case MODE_CLIENT: + if (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr))) + cast_flags = MDF_ACAST; + else + cast_flags = MDF_UCAST; + break; + + default: + cast_flags = MDF_UCAST; + break; + } + + /* + * If the peer is already configured, some dope has a duplicate + * configureation entry or another dope is wiggling from afar. */ if (peer != 0) { peer->hmode = (u_char)hmode; peer->version = (u_char)version; peer->minpoll = (u_char)minpoll; peer->maxpoll = (u_char)maxpoll; - peer->hpoll = peer->minpoll; - peer->ppoll = peer->minpoll; + peer->hpoll = peer->kpoll = peer->minpoll; + peer->ppoll = peer->maxpoll; peer->flags = flags | FLAG_CONFIG | (peer->flags & FLAG_REFCLOCK); - peer->cast_flags = (hmode == MODE_BROADCAST) ? - IN_CLASSD(ntohl(srcadr->sin_addr.s_addr)) ? MDF_MCAST : MDF_BCAST : MDF_UCAST; - peer->ttl = (u_char)ttl; + peer->cast_flags = cast_flags; + peer->ttlmax = ttl; peer->keyid = key; - peer->keynumber = 0; - return peer; + return (peer); } /* - * If we're here this guy is unknown to us. Make a new peer - * structure for him. + * Here no match has been found, so presumably this is a new + * persistent association. Mobilize the thing and initialize its + * variables. */ peer = newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll, - ttl, key); - if (peer != 0) { - peer->flags |= flags | FLAG_CONFIG; -#ifdef DEBUG - if (debug) - printf("peer_config: %s mode %d vers %d min %d max %d flags 0x%04x ttl %d key %lu\n", - ntoa(&peer->srcadr), peer->hmode, peer->version, - peer->minpoll, peer->maxpoll, peer->flags, - peer->ttl, peer->keyid); -#endif - } - return peer; + flags | FLAG_CONFIG, cast_flags, ttl, key); + return (peer); } @@ -571,74 +499,63 @@ newpeer( int version, int minpoll, int maxpoll, + u_int flags, + u_int cast_flags, int ttl, - u_long key + keyid_t key ) { register struct peer *peer; register int i; /* - * Some dirt here. Some of the initialization requires - * knowlege of our system state. + * Allocate a new peer structure. Some dirt here, since some of + * the initialization requires knowlege of our system state. */ if (peer_free_count == 0) - getmorepeermem(); - + getmorepeermem(); peer = peer_free; peer_free = peer->next; peer_free_count--; peer_associations++; + memset((char *)peer, 0, sizeof(struct peer)); /* - * Initialize the structure. This stuff is sort of part of - * the receive procedure and part of the clear procedure rolled - * into one. - * - * Zero the whole thing for now. We might be pickier later. + * Initialize the peer structure and dance the interface jig. + * Reference clocks step the loopback waltz, the others + * squaredance around the interface list looking for a buddy. If + * the dance peters out, there is always the wildcard interface. + * This might happen in some systems and would preclude proper + * operation with public key cryptography. */ - memset((char *)peer, 0, sizeof(struct peer)); - - peer->srcadr = *srcadr; - if (dstadr != 0) - peer->dstadr = dstadr; - else if (hmode == MODE_BROADCAST) + if (ISREFCLOCKADR(srcadr)) + peer->dstadr = loopback_interface; + else if (cast_flags & MDF_BCLNT) peer->dstadr = findbcastinter(srcadr); + else if (dstadr != any_interface) + peer->dstadr = dstadr; else - peer->dstadr = any_interface; - peer->cast_flags = (hmode == MODE_BROADCAST) ? - (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr))) ? MDF_MCAST : - MDF_BCAST : (hmode == MODE_BCLIENT || hmode == MODE_MCLIENT) ? - (peer->dstadr->flags & INT_MULTICAST) ? MDF_MCAST : MDF_BCAST : - MDF_UCAST; - /* Set manycast flags if appropriate */ - if (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr)) && hmode == MODE_CLIENT) - peer->cast_flags = MDF_ACAST; + peer->dstadr = findinterface(srcadr); + peer->srcadr = *srcadr; peer->hmode = (u_char)hmode; - peer->keyid = key; peer->version = (u_char)version; - peer->minpoll = (u_char)minpoll; - peer->maxpoll = (u_char)maxpoll; - peer->hpoll = peer->minpoll; - peer->ppoll = peer->minpoll; - peer->ttl = ttl; - peer->leap = LEAP_NOTINSYNC; + peer->minpoll = (u_char)max(NTP_MINPOLL, minpoll); + peer->maxpoll = (u_char)min(NTP_MAXPOLL, maxpoll); + peer->flags = flags | (key > NTP_MAXKEY ? FLAG_SKEY : 0); + peer->cast_flags = cast_flags; + peer->ttlmax = ttl; + peer->keyid = key; peer->precision = sys_precision; - peer->variance = MAXDISPERSE; - peer->epoch = current_time; - peer->stratum = STRATUM_UNSPEC; peer_clear(peer); - peer->update = peer->outdate = current_time; - peer->nextdate = peer->outdate + RANDPOLL(NTP_MINPOLL); - if (peer->flags & FLAG_BURST) - peer->burst = NTP_SHIFT; + if (mode_ntpdate) + peer_ntpdate++; /* - * Assign him an association ID and increment the system variable + * Assign an association ID and increment the system variable. */ peer->associd = current_association_ID; if (++current_association_ID == 0) - ++current_association_ID; + ++current_association_ID; /* * Note time on statistics timers. @@ -646,7 +563,6 @@ newpeer( peer->timereset = current_time; peer->timereachable = current_time; peer->timereceived = current_time; - #ifdef REFCLOCK if (ISREFCLOCKADR(&peer->srcadr)) { /* @@ -662,29 +578,32 @@ newpeer( peer->next = peer_free; peer_free = peer; peer_free_count++; - return 0; + return (NULL); } } #endif /* - * Put him in the hash tables. + * Put the new peer in the hash tables. */ i = HASH_ADDR(&peer->srcadr); peer->next = peer_hash[i]; peer_hash[i] = peer; peer_hash_count[i]++; - i = peer->associd & HASH_MASK; peer->ass_next = assoc_hash[i]; assoc_hash[i] = peer; assoc_hash_count[i]++; #ifdef DEBUG - if (debug > 1) - printf("mobilize %u next %lu\n", peer->associd, - peer->nextdate - peer->outdate); + if (debug) + printf( + "newpeer: %s->%s mode %d vers %d poll %d %d flags %x %x ttl %d key %08x\n", + ntoa(&peer->dstadr->sin), ntoa(&peer->srcadr), + peer->hmode, peer->version, peer->minpoll, + peer->maxpoll, peer->flags, peer->cast_flags, + peer->ttlmax, peer->keyid); #endif - return peer; + return (peer); } @@ -707,14 +626,15 @@ peer_unconfig( if (peer->flags & FLAG_CONFIG && (dstadr == 0 || peer->dstadr == dstadr)) { num_found++; + /* - * Tricky stuff here. If the peer is polling us - * in active mode, turn off the configuration bit - * and make the mode passive. This allows us to - * avoid dumping a lot of history for peers we - * might choose to keep track of in passive mode. - * The protocol will eventually terminate undesirables - * on its own. + * Tricky stuff here. If the peer is polling us + * in active mode, turn off the configuration + * bit and make the mode passive. This allows us + * to avoid dumping a lot of history for peers + * we might choose to keep track of in passive + * mode. The protocol will eventually terminate + * undesirables on its own. */ if (peer->hmode == MODE_ACTIVE && peer->pmode == MODE_ACTIVE) { @@ -727,21 +647,7 @@ peer_unconfig( } peer = findexistingpeer(srcadr, peer, mode); } - return num_found; -} - -/* - * peer_copy_manycast - copy manycast peer variables to new association - * (right now it simply copies the transmit timestamp) - */ -void -peer_config_manycast( - struct peer *peer1, - struct peer *peer2 - ) -{ - peer2->cast_flags = MDF_ACAST; - peer2->xmt = peer1->xmt; + return (num_found); } /* @@ -775,7 +681,6 @@ peer_reset( peer->oldpkt = 0; peer->seldisptoolarge = 0; peer->selbroken = 0; - peer->seltooold = 0; peer->timereset = current_time; } @@ -793,3 +698,114 @@ peer_all_reset(void) for (peer = peer_hash[hash]; peer != 0; peer = peer->next) peer_reset(peer); } + + +#ifdef AUTOKEY +/* + * expire_all - flush all crypto data and update timestamps. + */ +void +expire_all(void) +{ + struct peer *peer, *next_peer; + int n; + + /* + * This routine is called about once per day from the timer + * routine and when the client is first synchronized. Search the + * peer list for all associations and flush only the key list + * and cookie. If a manycast client association, flush + * everything. Then, recompute and sign the agreement public + * value, if present. + */ + for (n = 0; n < HASH_SIZE; n++) { + for (peer = peer_hash[n]; peer != 0; peer = next_peer) { + next_peer = peer->next; + if (peer->cast_flags & MDF_ACAST) { + peer_clear(peer); +#ifdef AUTOKEY + } else { + key_expire(peer); + peer->pcookie.tstamp = 0; +#endif /* AUTOKEY */ + } + + } + } + sys_private = (u_int32)RANDOM & 0xffffffff; +#ifdef PUBKEY + crypto_agree(); +#endif /* PUBKEY */ +#ifdef DEBUG + if (debug) + printf("expire_all: at %lu\n", current_time); +#endif +} +#endif /* AUTOKEY */ + + +/* + * findmanycastpeer - find and return a manycast peer + */ +struct peer * +findmanycastpeer( + struct recvbuf *rbufp + ) +{ + register struct peer *peer; + struct pkt *pkt; + l_fp p_org; + int i; + + /* + * This routine is called upon arrival of a client-mode message + * from a manycast server. Search the peer list for a manycast + * client association where the last transmit timestamp matches + * the originate timestamp. This assumes the transmit timestamps + * for possibly more than one manycast association are unique. + */ + pkt = &rbufp->recv_pkt; + for (i = 0; i < HASH_SIZE; i++) { + if (peer_hash_count[i] == 0) + continue; + + for (peer = peer_hash[i]; peer != 0; peer = + peer->next) { + if (peer->cast_flags & MDF_ACAST) { + NTOHL_FP(&pkt->org, &p_org); + if (L_ISEQU(&peer->xmt, &p_org)) + return (peer); + } + } + } + return (NULL); +} + + +/* + * resetmanycast - reset all manycast clients + */ +void +resetmanycast(void) +{ + register struct peer *peer; + int i; + + /* + * This routine is called when the number of client associations + * falls below the minimum. Search the peer list for manycast + * client associations and reset the ttl and poll interval. + */ + for (i = 0; i < HASH_SIZE; i++) { + if (peer_hash_count[i] == 0) + continue; + + for (peer = peer_hash[i]; peer != 0; peer = + peer->next) { + if (peer->cast_flags & MDF_ACAST) { + peer->ttl = 0; + poll_update(peer, peer->hpoll); + } + } + } +} |