/* Send a packet */ int sendpkt ( SOCKET rsock, sockaddr_u *dest, struct pkt *pkt, int len ) { int cc; #ifdef DEBUG if (debug > 2) { printf("sntp sendpkt: Packet data:\n"); pkt_output(pkt, len, stdout); } #endif TRACE(1, ("sntp sendpkt: Sending packet to %s ...\n", sptoa(dest))); cc = sendto(rsock, (void *)pkt, len, 0, &dest->sa, SOCKLEN(dest)); if (cc == SOCKET_ERROR) { msyslog(LOG_ERR, "Send to %s failed, %m", sptoa(dest)); return FALSE; } TRACE(1, ("Packet sent.\n")); return TRUE; }
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; }
/* Receive raw data */ int recvdata( SOCKET rsock, sockaddr_u * sender, void * rdata, int rdata_length ) { GETSOCKNAME_SOCKLEN_TYPE slen; int recvc; slen = sizeof(*sender); recvc = recvfrom(rsock, rdata, rdata_length, 0, &sender->sa, &slen); if (recvc < 0) return recvc; #ifdef DEBUG if (debug > 2) { printf("Received %d bytes from %s:\n", recvc, sptoa(sender)); pkt_output((struct pkt *)rdata, recvc, stdout); } #endif return recvc; }
/* ** Socket readable/timeout Callback: ** Read in the packet ** Unicast: ** - close socket ** - decrement n_pending_ntp ** - If packet is good, set the time and "exit" ** Broadcast: ** - If packet is good, set the time and "exit" */ void sock_cb( evutil_socket_t fd, short what, void *ptr ) { sockaddr_u sender; sockaddr_u * psau; sent_pkt ** p_pktlist; sent_pkt * spkt; int rpktl; int rc; INSIST(sock4 == fd || sock6 == fd); TRACE(3, ("sock_cb: event on sock%s:%s%s%s%s\n", (fd == sock6) ? "6" : "4", (what & EV_TIMEOUT) ? " timeout" : "", (what & EV_READ) ? " read" : "", (what & EV_WRITE) ? " write" : "", (what & EV_SIGNAL) ? " signal" : "")); if (!(EV_READ & what)) { if (EV_TIMEOUT & what) timeout_queries(); return; } /* Read in the packet */ rpktl = recvdata(fd, &sender, &rbuf, sizeof(rbuf)); if (rpktl < 0) { msyslog(LOG_DEBUG, "recvfrom error %m"); return; } if (sock6 == fd) p_pktlist = &v6_pkts_list; else p_pktlist = &v4_pkts_list; for (spkt = *p_pktlist; spkt != NULL; spkt = spkt->link) { psau = &spkt->addr; if (SOCK_EQ(&sender, psau)) break; } if (NULL == spkt) { msyslog(LOG_WARNING, "Packet from unexpected source %s dropped", sptoa(&sender)); return; } TRACE(1, ("sock_cb: %s %s\n", spkt->dctx->name, sptoa(&sender))); rpktl = process_pkt(&r_pkt, &sender, rpktl, MODE_SERVER, &spkt->x_pkt, "sock_cb"); TRACE(2, ("sock_cb: process_pkt returned %d\n", rpktl)); /* If this is a Unicast packet, one down ... */ if (!spkt->done && (CTX_UCST & spkt->dctx->flags)) { dec_pending_ntp(spkt->dctx->name, &spkt->addr); spkt->done = TRUE; } /* If the packet is good, set the time and we're all done */ rc = handle_pkt(rpktl, &r_pkt, &spkt->addr, spkt->dctx->name); if (0 != rc) TRACE(1, ("sock_cb: handle_pkt() returned %d\n", rc)); check_exit_conditions(); }
/* ** 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)); } }