/* * findpeer - find and return a peer in the hash table. */ struct peer * findpeer( struct sockaddr_storage *srcadr, struct interface *dstadr, int pkt_mode, int *action ) { register struct peer *peer; int hash; findpeer_calls++; hash = NTP_HASH_ADDR(srcadr); for (peer = peer_hash[hash]; peer != NULL; peer = peer->next) { if (SOCKCMP(srcadr, &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. */ *action = MATCH_ASSOC(peer->hmode, pkt_mode); /* * if an error was returned, exit back right * here. */ if (*action == AM_ERR) return ((struct peer *)0); /* * if a match is found, we stop our search. */ if (*action != AM_NOMATCH) break; } } /* * If no matching association is found */ if (peer == 0) { *action = MATCH_ASSOC(NO_PEER, pkt_mode); return ((struct peer *)0); } set_peerdstadr(peer, dstadr); return (peer); }
/* * unpeer - remove peer structure from hash table and free structure */ void unpeer( struct peer *peer ) { mprintf_event(PEVNT_DEMOBIL, peer, "assoc %u", peer->associd); restrict_source(&peer->srcadr, 1, 0); set_peerdstadr(peer, NULL); peer_demobilizations++; peer_associations--; if (FLAG_PREEMPT & peer->flags) peer_preempt--; #ifdef REFCLOCK /* * If this peer is actually a clock, shut it down first */ if (FLAG_REFCLOCK & peer->flags) refclock_unpeer(peer); #endif free_peer(peer, TRUE); }
/* * unpeer - remove peer structure from hash table and free structure */ void unpeer( struct peer *peer_to_remove ) { int hash; #ifdef OPENSSL char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */ if (peer_to_remove->flags & FLAG_SKEY) { sprintf(statstr, "unpeer %d flash %x reach %03o flags %04x", peer_to_remove->associd, peer_to_remove->flash, peer_to_remove->reach, peer_to_remove->flags); record_crypto_stats(&peer_to_remove->srcadr, statstr); #ifdef DEBUG if (debug) printf("peer: %s\n", statstr); #endif } #endif /* OPENSSL */ #ifdef DEBUG if (debug) printf("demobilize %u %d %d\n", peer_to_remove->associd, peer_associations, peer_preempt); #endif set_peerdstadr(peer_to_remove, NULL); /* XXXMEMLEAK? peer_clear->crypto allocation */ hash = NTP_HASH_ADDR(&peer_to_remove->srcadr); peer_hash_count[hash]--; peer_demobilizations++; peer_associations--; if (peer_to_remove->flags & FLAG_PREEMPT) peer_preempt--; #ifdef REFCLOCK /* * If this peer is actually a clock, shut it down first */ if (peer_to_remove->flags & FLAG_REFCLOCK) refclock_unpeer(peer_to_remove); #endif peer_to_remove->action = 0; /* disable timeout actions */ if (peer_hash[hash] == peer_to_remove) peer_hash[hash] = peer_to_remove->next; else { register struct peer *peer; peer = peer_hash[hash]; while (peer != 0 && peer->next != peer_to_remove) peer = peer->next; if (peer == 0) { peer_hash_count[hash]++; msyslog(LOG_ERR, "peer struct for %s not in table!", stoa(&peer->srcadr)); } else { peer->next = peer_to_remove->next; } } /* * Remove him from the association hash as well. */ hash = peer_to_remove->associd & NTP_HASH_MASK; assoc_hash_count[hash]--; if (assoc_hash[hash] == peer_to_remove) assoc_hash[hash] = peer_to_remove->ass_next; else { register struct peer *peer; peer = assoc_hash[hash]; while (peer != 0 && peer->ass_next != peer_to_remove) peer = peer->ass_next; if (peer == 0) { assoc_hash_count[hash]++; msyslog(LOG_ERR, "peer struct for %s not in association table!", stoa(&peer->srcadr)); } else { peer->ass_next = peer_to_remove->ass_next; } } peer_to_remove->next = peer_free; peer_free = peer_to_remove; peer_free_count++; }
/* * findpeer - find and return a peer match for a received datagram in * the peer_hash table. */ struct peer * findpeer( struct recvbuf *rbufp, int pkt_mode, int * action ) { struct peer * p; sockaddr_u * srcadr; u_int hash; struct pkt * pkt; l_fp pkt_org; findpeer_calls++; srcadr = &rbufp->recv_srcadr; hash = NTP_HASH_ADDR(srcadr); for (p = peer_hash[hash]; p != NULL; p = p->adr_link) { if (ADDR_PORT_EQ(srcadr, &p->srcadr)) { /* * if the association matching rules determine * that this is not a valid combination, then * look for the next valid peer association. */ *action = MATCH_ASSOC(p->hmode, pkt_mode); /* * A response to our manycastclient solicitation * might be misassociated with an ephemeral peer * already spun for the server. If the packet's * org timestamp doesn't match the peer's, check * if it matches the ACST prototype peer's. If * so it is a redundant solicitation response, * return AM_ERR to discard it. [Bug 1762] */ if (MODE_SERVER == pkt_mode && AM_PROCPKT == *action) { pkt = &rbufp->recv_pkt; NTOHL_FP(&pkt->org, &pkt_org); if (!L_ISEQU(&p->aorg, &pkt_org) && findmanycastpeer(rbufp)) *action = AM_ERR; } /* * if an error was returned, exit back right * here. */ if (*action == AM_ERR) return NULL; /* * if a match is found, we stop our search. */ if (*action != AM_NOMATCH) break; } } /* * If no matching association is found */ if (NULL == p) { *action = MATCH_ASSOC(NO_PEER, pkt_mode); } else if (p->dstadr != rbufp->dstadr) { set_peerdstadr(p, rbufp->dstadr); if (p->dstadr == rbufp->dstadr) { DPRINTF(1, ("Changed %s local address to match response\n", stoa(&p->srcadr))); return findpeer(rbufp, pkt_mode, action); } } return p; }