/* * 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); }
/* * 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; }