static struct peer * findexistingpeer_addr( sockaddr_u * addr, struct peer * start_peer, int mode, u_char cast_flags ) { struct peer *peer; DPRINTF(2, ("findexistingpeer_addr(%s, %s, %d, 0x%x)\n", sptoa(addr), (start_peer) ? sptoa(&start_peer->srcadr) : "NULL", mode, (u_int)cast_flags)); /* * start_peer is included so we can locate instances of the * same peer through different interfaces in the hash table. * Without MDF_BCLNT, a match requires the same mode and remote * address. MDF_BCLNT associations start out as MODE_CLIENT * if broadcastdelay is not specified, and switch to * MODE_BCLIENT after estimating the one-way delay. Duplicate * associations are expanded in definition to match any other * MDF_BCLNT with the same srcadr (remote, unicast address). */ if (NULL == start_peer) peer = peer_hash[NTP_HASH_ADDR(addr)]; else peer = start_peer->adr_link; while (peer != NULL) { DPRINTF(3, ("%s %s %d %d 0x%x 0x%x ", sptoa(addr), sptoa(&peer->srcadr), mode, peer->hmode, (u_int)cast_flags, (u_int)peer->cast_flags)); if ((-1 == mode || peer->hmode == mode || ((MDF_BCLNT & peer->cast_flags) && (MDF_BCLNT & cast_flags))) && ADDR_PORT_EQ(addr, &peer->srcadr)) { DPRINTF(3, ("found.\n")); break; } DPRINTF(3, ("\n")); peer = peer->adr_link; } return peer; }
/* ** queue_xmt */ void queue_xmt( SOCKET sock, struct dns_ctx * dctx, sent_pkt * spkt, u_int xmt_delay ) { sockaddr_u * dest; sent_pkt ** pkt_listp; sent_pkt * match; xmt_ctx * xctx; struct timeval start_cb; struct timeval delay; dest = &spkt->addr; if (IS_IPV6(dest)) pkt_listp = &v6_pkts_list; else pkt_listp = &v4_pkts_list; /* reject attempts to add address already listed */ for (match = *pkt_listp; match != NULL; match = match->link) { if (ADDR_PORT_EQ(&spkt->addr, &match->addr)) { if (strcasecmp(spkt->dctx->name, match->dctx->name)) printf("%s %s duplicate address from %s ignored.\n", sptoa(&match->addr), match->dctx->name, spkt->dctx->name); else printf("%s %s, duplicate address ignored.\n", sptoa(&match->addr), match->dctx->name); dec_pending_ntp(spkt->dctx->name, &spkt->addr); free(spkt); return; } } LINK_SLIST(*pkt_listp, spkt, link); xctx = emalloc_zero(sizeof(*xctx)); xctx->sock = sock; xctx->spkt = spkt; gettimeofday_cached(base, &start_cb); xctx->sched = start_cb.tv_sec + (2 * xmt_delay); LINK_SORT_SLIST(xmt_q, xctx, (xctx->sched < L_S_S_CUR()->sched), link, xmt_ctx); if (xmt_q == xctx) { /* * The new entry is the first scheduled. The timer is * either not active or is set for the second xmt * context in xmt_q. */ if (NULL == ev_xmt_timer) ev_xmt_timer = event_new(base, INVALID_SOCKET, EV_TIMEOUT, &xmt_timer_cb, NULL); if (NULL == ev_xmt_timer) { msyslog(LOG_ERR, "queue_xmt: event_new(base, -1, EV_TIMEOUT) failed!"); exit(1); } ZERO(delay); if (xctx->sched > start_cb.tv_sec) delay.tv_sec = xctx->sched - start_cb.tv_sec; event_add(ev_xmt_timer, &delay); TRACE(2, ("queue_xmt: xmt timer for %u usec\n", (u_int)delay.tv_usec)); } }
/* * 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; }