diff options
Diffstat (limited to 'ntpd/ntp_proto.c')
-rw-r--r-- | ntpd/ntp_proto.c | 334 |
1 files changed, 209 insertions, 125 deletions
diff --git a/ntpd/ntp_proto.c b/ntpd/ntp_proto.c index f2c59238432a..170294c68bb6 100644 --- a/ntpd/ntp_proto.c +++ b/ntpd/ntp_proto.c @@ -17,7 +17,6 @@ #include "ntp_leapsec.h" #include "ntp_psl.h" #include "refidsmear.h" -#include "lib_strbuf.h" #include <stdio.h> #ifdef HAVE_LIBSCF_H @@ -35,9 +34,9 @@ #define SRVFUZ_SHIFT 6 /* 64 seconds */ #define SRVRSP_FUZZ(x) \ do { \ - x.l_uf &= 0; \ + x.l_uf = 0; \ x.l_ui &= ~((1 << SRVFUZ_SHIFT) - 1U); \ - } while(0) + } while (FALSE) /* * This macro defines the authentication state. If x is 1 authentication @@ -472,7 +471,16 @@ transmit( return; } - /* + /* [Bug 3851] drop pool servers which can no longer be reached. */ + if (MDF_PCLNT & peer->cast_flags) { + if ( (IS_IPV6(&peer->srcadr) && !nonlocal_v6_addr_up) + || !nonlocal_v4_addr_up) { + unpeer(peer); + return; + } + } + + /* * In unicast modes the dance is much more intricate. It is * designed to back off whenever possible to minimize network * traffic. @@ -584,6 +592,7 @@ transmit( } +#ifdef DEBUG const char * amtoa( int am @@ -607,6 +616,7 @@ amtoa( return bp; } } +#endif /* DEBUG */ /* @@ -626,7 +636,6 @@ receive( r4addr r4a; /* address restrictions */ u_short restrict_mask; /* restrict bits */ const char *hm_str; /* hismode string */ - const char *am_str; /* association match string */ int kissCode = NOKISS; /* Kiss Code */ int has_mac; /* length of MAC field */ int authlen; /* offset of MAC field */ @@ -636,11 +645,15 @@ receive( keyid_t skeyid = 0; /* key IDs */ u_int32 opcode = 0; /* extension field opcode */ sockaddr_u *dstadr_sin; /* active runway */ + u_char cast_flags; /* MDF_* flags for newpeer() */ struct peer *peer2; /* aux peer structure pointer */ endpt *match_ep; /* newpeer() local address */ l_fp p_org; /* origin timestamp */ l_fp p_rec; /* receive timestamp */ l_fp p_xmt; /* transmit timestamp */ +#ifdef DEBUG + const char *am_str; /* association match string */ +#endif #ifdef AUTOKEY char hostname[NTP_MAXSTRLEN + 1]; char *groupname = NULL; @@ -689,12 +702,11 @@ receive( } if (hismode == MODE_PRIVATE) { if (!ntp_mode7 || (restrict_mask & RES_NOQUERY)) { - DPRINTF(2, ("receive: drop: RES_NOQUERY\n")); + DPRINTF(2, ("receive: drop: !mode7 or RES_NOQUERY\n")); sys_restricted++; return; /* no query private */ } - process_private(rbufp, ((restrict_mask & - RES_NOMODIFY) == 0)); + process_private(rbufp, !(RES_NOMODIFY & restrict_mask)); return; } if (hismode == MODE_CONTROL) { @@ -725,14 +737,14 @@ receive( hisleap = PKT_LEAP(pkt->li_vn_mode); hisstratum = PKT_TO_STRATUM(pkt->stratum); - INSIST(0 != hisstratum); /* paranoia check PKT_TO_STRATUM result */ - + DEBUG_INSIST(0 != hisstratum); /* paranoia check PKT_TO_STRATUM result */ + /* TODO: this should be in a unit test */ DPRINTF(1, ("receive: at %ld %s<-%s ippeerlimit %d mode %d iflags %s " - "restrict %s org %#010x.%08x xmt %#010x.%08x\n", + "restrict %s org 0x%x.%08x xmt 0x%x.%08x\n", current_time, stoa(&rbufp->dstadr->sin), stoa(&rbufp->recv_srcadr), r4a.ippeerlimit, hismode, - build_iflags(rbufp->dstadr->flags), - build_rflags(restrict_mask), + iflags_str(rbufp->dstadr->flags), + rflags_str(restrict_mask), ntohl(pkt->org.l_ui), ntohl(pkt->org.l_uf), ntohl(pkt->xmt.l_ui), ntohl(pkt->xmt.l_uf))); @@ -807,10 +819,15 @@ receive( || (NTP_MAXPOLL < pkt->ppoll) ) ) { +#ifdef BUG3870 DPRINTF(2, ("receive: drop: Invalid ppoll (%d) from %s\n", pkt->ppoll, stoa(&rbufp->recv_srcadr))); sys_badlength++; return; /* invalid packet poll */ +#else + DPRINTF(2, ("receive: info: Invalid ppoll (%d) from %s\n", + pkt->ppoll, stoa(&rbufp->recv_srcadr))); +#endif } /* @@ -987,7 +1004,9 @@ receive( NTOHL_FP(&pkt->rec, &p_rec); NTOHL_FP(&pkt->xmt, &p_xmt); hm_str = modetoa(hismode); +#ifdef DEBUG am_str = amtoa(retcode); +#endif /* * Authentication is conditioned by three switches: @@ -1030,7 +1049,7 @@ receive( if (has_mac == 0) { restrict_mask &= ~RES_MSSNTP; is_authentic = AUTH_NONE; /* not required */ - DPRINTF(1, ("receive: at %ld %s<-%s mode %d/%s:%s len %d org %#010x.%08x xmt %#010x.%08x NOMAC\n", + DPRINTF(1, ("receive: at %ld %s<-%s mode %d/%s:%s len %d org 0x%x.%08x xmt 0x%x.%08x NOMAC\n", current_time, stoa(dstadr_sin), stoa(&rbufp->recv_srcadr), hismode, hm_str, am_str, authlen, @@ -1039,7 +1058,7 @@ receive( } else if (crypto_nak_test == VALIDNAK) { restrict_mask &= ~RES_MSSNTP; is_authentic = AUTH_CRYPTO; /* crypto-NAK */ - DPRINTF(1, ("receive: at %ld %s<-%s mode %d/%s:%s keyid %08x len %d auth %d org %#010x.%08x xmt %#010x.%08x CRYPTONAK\n", + DPRINTF(1, ("receive: at %ld %s<-%s mode %d/%s:%s keyid %08x len %d auth %d org 0x%x.%08x xmt 0x%x.%08x CRYPTONAK\n", current_time, stoa(dstadr_sin), stoa(&rbufp->recv_srcadr), hismode, hm_str, am_str, skeyid, authlen + has_mac, is_authentic, @@ -1062,7 +1081,7 @@ receive( && (memcmp(zero_key, (char *)pkt + authlen + 4, MAX_MD5_LEN - 4) == 0)) { is_authentic = AUTH_NONE; - DPRINTF(1, ("receive: at %ld %s<-%s mode %d/%s:%s len %d org %#010x.%08x xmt %#010x.%08x SIGND\n", + DPRINTF(1, ("receive: at %ld %s<-%s mode %d/%s:%s len %d org %x.%08x xmt %x.%08x SIGND\n", current_time, stoa(dstadr_sin), stoa(&rbufp->recv_srcadr), hismode, hm_str, am_str, authlen, @@ -1185,7 +1204,7 @@ receive( if (crypto_flags && skeyid > NTP_MAXKEY) authtrust(skeyid, 0); #endif /* AUTOKEY */ - DPRINTF(1, ("receive: at %ld %s<-%s mode %d/%s:%s keyid %08x len %d auth %d org %#010x.%08x xmt %#010x.%08x MAC\n", + DPRINTF(1, ("receive: at %ld %s<-%s mode %d/%s:%s keyid %08x len %d auth %d org 0x%x.%08x xmt 0x%x.%08x MAC\n", current_time, stoa(dstadr_sin), stoa(&rbufp->recv_srcadr), hismode, hm_str, am_str, skeyid, authlen + has_mac, is_authentic, @@ -1358,7 +1377,12 @@ receive( if ( sys_leap == LEAP_NOTINSYNC || sys_stratum >= hisstratum || (!sys_cohort && sys_stratum == hisstratum + 1) - || rbufp->dstadr->addr_refid == pkt->refid) { + || rbufp->dstadr->addr_refid == pkt->refid +# ifdef WORDS_BIGENDIAN /* see local_refid() comment */ + || ( IS_IPV6(&rbufp->dstadr->sin) + &&rbufp->dstadr->old_refid == pkt->refid) +# endif + ) { DPRINTF(2, ("receive: sys leap: %0x, sys_stratum %d > hisstratum+1 %d, !sys_cohort %d && sys_stratum == hisstratum+1, loop refid %#x == pkt refid %#x\n", sys_leap, sys_stratum, hisstratum + 1, !sys_cohort, rbufp->dstadr->addr_refid, pkt->refid)); DPRINTF(2, ("receive: AM_FXMIT drop: LEAP_NOTINSYNC || stratum || loop\n")); sys_declined++; @@ -1366,6 +1390,17 @@ receive( } /* + * Do not respond if the packet came into an IPv6 link-local + * address on an interface where we also have a usable + * global address, to avoid duplicate associations. + */ + if (INT_LL_OF_GLOB & rbufp->dstadr->flags) { + DPRINTF(2, ("receive: declining manycast solicitation on link-local IPv6\n")); + sys_declined++; + return; + } + + /* * Respond only if authentication succeeds. Don't do a * crypto-NAK, as that would not be useful. */ @@ -1423,6 +1458,12 @@ receive( return; } #endif /* AUTOKEY */ + /* Do not spin up duplicate manycast associations */ + if (INT_LL_OF_GLOB & rbufp->dstadr->flags) { + DPRINTF(2, ("receive: AM_MANYCAST drop: link-local server\n")); + sys_declined++; + return; + } if ((peer2 = findmanycastpeer(rbufp)) == NULL) { DPRINTF(2, ("receive: AM_MANYCAST drop: No manycast peer\n")); sys_restricted++; @@ -1450,11 +1491,15 @@ receive( sys_declined++; return; /* no help */ } + cast_flags = MDF_UCAST; + if (MDF_POOL & peer2->cast_flags) { + cast_flags |= MDF_PCLNT; + } peer = newpeer(&rbufp->recv_srcadr, NULL, rbufp->dstadr, r4a.ippeerlimit, MODE_CLIENT, hisversion, peer2->minpoll, peer2->maxpoll, (FLAG_PREEMPT | (POOL_FLAG_PMASK & peer2->flags)), - (MDF_UCAST | MDF_UCLNT), 0, skeyid, sys_ident); + cast_flags, 0, skeyid, sys_ident); if (NULL == peer) { DPRINTF(2, ("receive: AM_MANYCAST drop: duplicate\n")); sys_declined++; @@ -1840,7 +1885,7 @@ receive( if ( tdiff.l_i < 0 && (current_time - peer->timereceived) < deadband) { - msyslog(LOG_INFO, "receive: broadcast packet from %s contains non-monotonic timestamp: %#010x.%08x -> %#010x.%08x", + msyslog(LOG_INFO, "receive: broadcast packet from %s contains non-monotonic timestamp: 0x%x.%08x -> 0x%x.%08x", stoa(&rbufp->recv_srcadr), peer->bxmt.l_ui, peer->bxmt.l_uf, p_xmt.l_ui, p_xmt.l_uf @@ -1991,7 +2036,7 @@ receive( if (peer->flip == 0 && !L_ISEQU(&p_org, &peer->aorg)) { peer->bogusorg++; msyslog(LOG_INFO, - "receive: flip 0 KoD origin timestamp %#010x.%08x from %s does not match %#010x.%08x - ignoring.", + "receive: flip 0 KoD origin timestamp 0x%x.%08x from %s does not match 0x%x.%08x - ignoring.", p_org.l_ui, p_org.l_uf, ntoa(&peer->srcadr), peer->aorg.l_ui, peer->aorg.l_uf); @@ -1999,7 +2044,7 @@ receive( } else if (peer->flip == 1 && !L_ISEQU(&p_org, &peer->borg)) { peer->bogusorg++; msyslog(LOG_INFO, - "receive: flip 1 KoD origin timestamp %#010x.%08x from %s does not match interleave %#010x.%08x - ignoring.", + "receive: flip 1 KoD origin timestamp 0x%x.%08x from %s does not match interleave 0x%x.%08x - ignoring.", p_org.l_ui, p_org.l_uf, ntoa(&peer->srcadr), peer->borg.l_ui, peer->borg.l_uf); @@ -2033,9 +2078,14 @@ receive( /* XXX: FLAG_LOOPNONCE */ DEBUG_INSIST(0 == (FLAG_LOOPNONCE & peer->flags)); - msyslog(LOG_INFO, - "receive: Got KoD %s from %s", - refid_str(pkt->refid, hisstratum), ntoa(&peer->srcadr)); + if (RATEKISS == kissCode) { + msyslog(LOG_INFO, "RATE KoD from %s poll %u", + ntoa(&peer->srcadr), 1u << pkt->ppoll); + } else { + msyslog(LOG_INFO, "KoD %s from %s", + refid_str(pkt->refid, -1), + ntoa(&peer->srcadr)); + } } else if (peer->flip == 0) { if (0) { } else if (L_ISZERO(&p_org)) { @@ -2049,11 +2099,11 @@ receive( #endif /**/ switch (hismode) { - /* We allow 0org for: */ + /* We allow 0org for: */ case UCHAR_MAX: action = "Allow"; break; - /* We disallow 0org for: */ + /* We disallow 0org for: */ case MODE_UNSPEC: case MODE_ACTIVE: case MODE_PASSIVE: @@ -2071,20 +2121,22 @@ receive( } /**/ msyslog(LOG_INFO, - "receive: %s 0 origin timestamp from %s@%s xmt %#010x.%08x", + "receive: %s 0 origin timestamp from %s@%s xmt 0x%x.%08x", action, hm_str, ntoa(&peer->srcadr), ntohl(pkt->xmt.l_ui), ntohl(pkt->xmt.l_uf)); + } else if ( L_ISZERO(&peer->aorg) && MODE_CLIENT != hismode + && !memcmp("STEP", &peer->refid, 4)) { + /* response came in just after we stepped clock, normal */ } else if (!L_ISEQU(&p_org, &peer->aorg)) { /* are there cases here where we should bail? */ /* Should we set TEST2 if we decide to try xleave? */ peer->bogusorg++; peer->flash |= TEST2; /* bogus */ - msyslog(LOG_INFO, - "receive: Unexpected origin timestamp %#010x.%08x does not match aorg %#010x.%08x from %s@%s xmt %#010x.%08x", + msyslog(LOG_INFO, + "duplicate or replay: org 0x%x.%08x does not match 0x%x.%08x from %s@%s", ntohl(pkt->org.l_ui), ntohl(pkt->org.l_uf), peer->aorg.l_ui, peer->aorg.l_uf, - hm_str, ntoa(&peer->srcadr), - ntohl(pkt->xmt.l_ui), ntohl(pkt->xmt.l_uf)); + hm_str, ntoa(&peer->srcadr)); if ( !L_ISZERO(&peer->dst) && L_ISEQU(&p_org, &peer->dst)) { /* Might be the start of an interleave */ @@ -2474,8 +2526,10 @@ receive( * more flashers. Leave if the packet is not good. */ process_packet(peer, pkt, rbufp->recv_length); - if (peer->flash & PKT_TEST_MASK) + /* Bug 2734: TEST3 prevents initial interleave sync */ + if ((~TEST3 & peer->flash) & PKT_TEST_MASK) { return; + } /* [bug 3592] Update poll. Ideally this should not happen in a * receive branch, but too much is going on here... at least we @@ -2516,7 +2570,6 @@ process_packet( double p_offset, p_del, p_disp; l_fp p_rec, p_xmt, p_org, p_reftime, ci; u_char pmode, pleap, pversion, pstratum; - char statstr[NTP_MAXSTRLEN]; #ifdef ASSYM int itemp; double etemp, ftemp, td; @@ -2652,9 +2705,8 @@ process_packet( p_del = t21 - t34; p_offset = (t21 + t34) / 2.; if (p_del < 0 || p_del > 1.) { - snprintf(statstr, sizeof(statstr), - "t21 %.6f t34 %.6f", t21, t34); - report_event(PEVNT_XERR, peer, statstr); + mprintf_event(PEVNT_XERR, peer, + "t21 %.9f t34 %.9f", t21, t34); return; } @@ -2680,9 +2732,9 @@ process_packet( /* drop all if in the initial volley */ if (FLAG_BC_VOL & peer->flags) goto bcc_init_volley_fail; - snprintf(statstr, sizeof(statstr), - "offset %.6f delay %.6f", t21, t34); - report_event(PEVNT_XERR, peer, statstr); + mprintf_event(PEVNT_XERR, peer, + "offset %.9f delay %.9f", + t21, t34); return; } p_offset = t21; @@ -2981,20 +3033,6 @@ clock_update( if (crypto_flags) crypto_update(); #endif /* AUTOKEY */ - /* - * If our parent process is waiting for the - * first clock sync, send them home satisfied. - */ -#ifdef HAVE_WORKING_FORK - if (daemon_pipe[1] != -1) { - if (2 != write(daemon_pipe[1], "S\n", 2)) { - msyslog(LOG_ERR, "daemon failed to notify parent ntpd (--wait-sync)"); - } - close(daemon_pipe[1]); - daemon_pipe[1] = -1; - DPRINTF(1, ("notified parent --wait-sync is done\n")); - } -#endif /* HAVE_WORKING_FORK */ } @@ -3150,7 +3188,7 @@ poll_update( if ( 0 != sub || 0 != qty) { - do { + do { val = ntp_random() & msk; } while (val > qty); @@ -3193,8 +3231,9 @@ peer_clear( const char *ident /* tally lights */ ) { - u_char u; - l_fp bxmt = peer->bxmt; /* bcast clients retain this! */ + static u_long earliest; + u_char u; + l_fp bxmt = peer->bxmt; /* bcast clients retain this! */ #ifdef AUTOKEY /* @@ -3271,6 +3310,11 @@ peer_clear( peer->nextdate += peer_associations; } else if (!(FLAG_CONFIG & peer->flags)) { peer->nextdate += ntp_minpkt + 1; + /* space out manycastclient first polls */ + if (peer->nextdate < earliest) { + peer->nextdate = earliest; + } + earliest = peer->nextdate + 1; } else { peer->nextdate += ntp_random() % (1 << peer->minpoll); } @@ -3296,10 +3340,10 @@ clock_filter( ) { double dst[NTP_SHIFT]; /* distance vector */ - int ord[NTP_SHIFT]; /* index vector */ - int i, j, k, m; + u_char ord[NTP_SHIFT]; /* index vector */ + short i, j; + u_char k, m; double dtemp, etemp; - char tbuf[80]; /* * A sample consists of the offset, delay, dispersion and epoch @@ -3316,7 +3360,7 @@ clock_filter( peer->filter_disp[j] = sample_disp; peer->filter_epoch[j] = current_time; j = (j + 1) % NTP_SHIFT; - peer->filter_nextpt = j; + peer->filter_nextpt = (u_char)j; /* * Update dispersions since the last update and at the same @@ -3344,7 +3388,7 @@ clock_filter( } else { dst[i] = peer->filter_delay[j]; } - ord[i] = j; + ord[i] = (u_char)j; j = (j + 1) % NTP_SHIFT; } @@ -3377,7 +3421,7 @@ clock_filter( */ m = 0; for (i = 0; i < NTP_SHIFT; i++) { - peer->filter_order[i] = (u_char) ord[i]; + peer->filter_order[i] = ord[i]; if ( dst[i] >= MAXDISPERSE || (m >= 2 && dst[i] >= sys_maxdist)) continue; @@ -3394,11 +3438,12 @@ clock_filter( k = ord[0]; for (i = NTP_SHIFT - 1; i >= 0; i--) { j = ord[i]; - peer->disp = NTP_FWEIGHT * (peer->disp + - peer->filter_disp[j]); - if (i < m) + peer->disp = NTP_FWEIGHT * ( peer->disp + + peer->filter_disp[j]); + if (i < m) { peer->jitter += DIFF(peer->filter_offset[j], - peer->filter_offset[k]); + peer->filter_offset[k]); + } } /* @@ -3407,15 +3452,16 @@ clock_filter( * save the offset, delay and jitter. Note the jitter must not * be less than the precision. */ - if (m == 0) { + if (0 == m) { clock_select(); return; } etemp = fabs(peer->offset - peer->filter_offset[k]); peer->offset = peer->filter_offset[k]; peer->delay = peer->filter_delay[k]; - if (m > 1) + if (m > 1) { peer->jitter /= m - 1; + } peer->jitter = max(SQRT(peer->jitter), LOGTOD(sys_precision)); /* @@ -3428,23 +3474,22 @@ clock_filter( if ( peer->disp < sys_maxdist && peer->filter_disp[k] < sys_maxdist && etemp > CLOCK_SGATE * peer->jitter - && peer->filter_epoch[k] - peer->epoch + && peer->filter_epoch[k] - peer->epoch < 2. * ULOGTOD(peer->hpoll)) { - snprintf(tbuf, sizeof(tbuf), "%.6f s", etemp); - report_event(PEVNT_POPCORN, peer, tbuf); + mprintf_event(PEVNT_POPCORN, peer, "%.9f s", etemp); return; } /* * A new minimum sample is useful only if it is later than the * last one used. In this design the maximum lifetime of any - * sample is not greater than eight times the poll interval, so - * the maximum interval between minimum samples is eight - * packets. + * sample is not greater than NTP_SHIFT (8) times the poll + * interval, so the maximum interval between minimum samples is + * NTP_SHIFT packets. */ if (peer->filter_epoch[k] <= peer->epoch) { - DPRINTF(2, ("clock_filter: old sample %lu\n", current_time - - peer->filter_epoch[k])); + DPRINTF(2, ("clock_filter: old sample %lu s\n", + current_time - peer->filter_epoch[k])); return; } peer->epoch = peer->filter_epoch[k]; @@ -3454,13 +3499,14 @@ clock_filter( * processing. If not synchronized or not in a burst, tickle the * clock select algorithm. */ - record_peer_stats(&peer->srcadr, ctlpeerstatus(peer), - peer->offset, peer->delay, peer->disp, peer->jitter); - DPRINTF(1, ("clock_filter: n %d off %.6f del %.6f dsp %.6f jit %.6f\n", - m, peer->offset, peer->delay, peer->disp, + record_peer_stats(&peer->srcadr, ctlpeerstatus(peer), peer->offset, + peer->delay, peer->disp, peer->jitter); + DPRINTF(1, ("clock_filter: n %hu off %.9f del %.9f dsp %.9f jit %.9f\n", + (u_short)m, peer->offset, peer->delay, peer->disp, peer->jitter)); - if (peer->burst == 0 || sys_leap == LEAP_NOTINSYNC) + if (0 == peer->burst || LEAP_NOTINSYNC == sys_leap) { clock_select(); + } } @@ -3854,7 +3900,7 @@ clock_select(void) || ((FLAG_TRUE | FLAG_PREFER) & peers[k].peer->flags)) break; - DPRINTF(3, ("select: drop %s seljit %.6f jit %.6f\n", + DPRINTF(3, ("select: drop %s seljit %.9f jit %.9f\n", ntoa(&peers[k].peer->srcadr), g, d)); if (nlist > sys_maxclock) peers[k].peer->new_status = CTL_PST_SEL_EXCESS; @@ -3933,13 +3979,13 @@ clock_select(void) sys_clockhop = 0; } else if ((x = fabs(typesystem->offset - osys_peer->offset)) < sys_mindisp) { - if (sys_clockhop == 0) + if (0 == sys_clockhop) sys_clockhop = sys_mindisp; else sys_clockhop *= .5; - DPRINTF(1, ("select: clockhop %d %.6f %.6f\n", + DPRINTF(1, ("select: clockhop %d %.9f %.9f\n", j, x, sys_clockhop)); - if (fabs(x) < sys_clockhop) + if (x < sys_clockhop) typesystem = osys_peer; else sys_clockhop = 0; @@ -4108,9 +4154,9 @@ peer_xmit( keyid_t xkeyid = 0; /* transmit key ID */ l_fp xmt_tx, xmt_ty; - if (!peer->dstadr) /* drop peers without interface */ + if (!peer->dstadr) { /* can't send */ return; - + } xpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap, peer->version, peer->hmode); xpkt.stratum = STRATUM_TO_PKT(sys_stratum); @@ -4188,9 +4234,8 @@ peer_xmit( } L_SUB(&xmt_ty, &xmt_tx); LFPTOD(&xmt_ty, peer->xleave); - DPRINTF(1, ("peer_xmit: at %ld %s->%s mode %d len %zu xmt %#010x.%08x\n", - current_time, - peer->dstadr ? stoa(&peer->dstadr->sin) : "-", + DPRINTF(1, ("peer_xmit: at %ld %s->%s mode %d len %zu xmt 0x%x.%08x\n", + current_time, latoa(peer->dstadr), stoa(&peer->srcadr), peer->hmode, sendlen, xmt_tx.l_ui, xmt_tx.l_uf)); return; @@ -4477,8 +4522,8 @@ peer_xmit( authtrust(xkeyid, 0); #endif /* AUTOKEY */ if (sendlen > sizeof(xpkt)) { - msyslog(LOG_ERR, "peer_xmit: buffer overflow %zu", sendlen); - exit (-1); + msyslog(LOG_ERR, "peer_xmit: buffer overflow %u", (u_int)sendlen); + exit(EX_SOFTWARE); } peer->t21_bytes = sendlen; sendpkt(&peer->srcadr, peer->dstadr, @@ -4502,9 +4547,8 @@ peer_xmit( LFPTOD(&xmt_ty, peer->xleave); #ifdef AUTOKEY DPRINTF(1, ("peer_xmit: at %ld %s->%s mode %d keyid %08x len %zu index %d\n", - current_time, latoa(peer->dstadr), - ntoa(&peer->srcadr), peer->hmode, xkeyid, sendlen, - peer->keynumber)); + current_time, latoa(peer->dstadr), stoa(&peer->srcadr), + peer->hmode, xkeyid, sendlen, peer->keynumber)); #else /* !AUTOKEY follows */ DPRINTF(1, ("peer_xmit: at %ld %s->%s mode %d keyid %08x len %zu\n", current_time, peer->dstadr ? @@ -4543,14 +4587,14 @@ leap_smear_add_offs( */ static void fast_xmit( - struct recvbuf *rbufp, /* receive packet pointer */ + struct recvbuf* rbufp, /* receive packet pointer */ int xmode, /* receive mode */ /* XXX: HMS: really? */ keyid_t xkeyid, /* transmit key ID */ int flags /* restrict mask */ - ) +) { struct pkt xpkt; /* transmit packet structure */ - struct pkt *rpkt; /* receive packet structure */ + struct pkt* rpkt; /* receive packet structure */ l_fp xmt_tx, xmt_ty; size_t sendlen; #ifdef AUTOKEY @@ -4564,13 +4608,26 @@ fast_xmit( * the system minimum poll (ntp_minpoll). This is for KoD rate * control and not strictly specification compliant, but doesn't * break anything. - * - * If the gazinta was from a multicast address, the gazoutta - * must go out another way. */ rpkt = &rbufp->recv_pkt; - if (rbufp->dstadr->flags & INT_MCASTOPEN) + /* + * If the packet was received on an endpoint open only on + * a multicast address, the response needs to go out from + * a unicast endpoint. + */ +#ifndef MULTICAST_NONEWSOCKET + if (rbufp->dstadr->flags & INT_MCASTOPEN) { rbufp->dstadr = findinterface(&rbufp->recv_srcadr); + if (NULL == rbufp->dstadr || + ANY_INTERFACE_CHOOSE(&rbufp->recv_srcadr) /* wildcard */ + == rbufp->dstadr) { + DPRINTF(2, ("No unicast local address found for" + " reply to %s mcast.", + stoa(&rbufp->recv_srcadr))); + return; + } + } +#endif /* * If this is a kiss-o'-death (KoD) packet, show leap @@ -4802,15 +4859,14 @@ pool_xmit( ) { #ifdef WORKER - struct pkt xpkt; /* transmit packet structure */ - struct addrinfo hints; - int rc; - struct interface * lcladr; - sockaddr_u * rmtadr; - r4addr r4a; - u_short restrict_mask; - struct peer * p; - l_fp xmt_tx; + struct pkt xpkt; /* transmit packet structure */ + struct addrinfo hints; + int rc; + endpt * lcladr; + sockaddr_u * rmtadr; + u_short af; + struct peer * p; + l_fp xmt_tx; DEBUG_REQUIRE(pool); if (NULL == pool->ai) { @@ -4819,6 +4875,16 @@ pool_xmit( free(pool->addrs); pool->addrs = NULL; } + af = AF(&pool->srcadr); + if ( (AF_INET == af && !nonlocal_v4_addr_up) + || (AF_INET6 == af && !nonlocal_v6_addr_up) + || ( AF_UNSPEC == af + && !nonlocal_v4_addr_up + && !nonlocal_v6_addr_up)) { + + /* POOL DNS query would be useless [Bug 3845] */ + return; + } ZERO(hints); hints.ai_family = AF(&pool->srcadr); hints.ai_socktype = SOCK_DGRAM; @@ -4845,15 +4911,17 @@ pool_xmit( /* copy_addrinfo_list ai_addr points to a sockaddr_u */ rmtadr = (sockaddr_u *)(void *)pool->ai->ai_addr; pool->ai = pool->ai->ai_next; + /* do not solicit when hopeless [Bug 3845] */ + if ( (IS_IPV4(rmtadr) && !nonlocal_v4_addr_up) + || (IS_IPV6(rmtadr) && !nonlocal_v6_addr_up)) { + continue; + } p = findexistingpeer(rmtadr, NULL, NULL, MODE_CLIENT, 0, NULL); } while (p != NULL && pool->ai != NULL); - if (p != NULL) + if (p != NULL) { return; /* out of addresses, re-query DNS next poll */ - restrictions(rmtadr, &r4a); - restrict_mask = r4a.rflags; - if (RES_FLAGS & restrict_mask) - restrict_source(rmtadr, 0, - current_time + POOL_SOLICIT_WINDOW + 1); + } + restrict_source(rmtadr, FALSE, 1 + POOL_SOLICIT_WINDOW); lcladr = findinterface(rmtadr); memset(&xpkt, 0, sizeof(xpkt)); xpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap, pool->version, @@ -4867,7 +4935,6 @@ pool_xmit( /* Bug 3596: What are the pros/cons of using sys_reftime here? */ HTONL_FP(&sys_reftime, &xpkt.reftime); - /* HMS: the following is better done after the ntp_random() calls */ get_systime(&xmt_tx); pool->aorg = xmt_tx; @@ -4886,14 +4953,14 @@ pool_xmit( L_CLR(&pool->nonce); HTONL_FP(&xmt_tx, &xpkt.xmt); } - sendpkt(rmtadr, lcladr, - sys_ttl[(pool->ttl >= sys_ttlmax) ? sys_ttlmax : pool->ttl], - &xpkt, LEN_PKT_NOMAC); pool->sent++; pool->throttle += (1 << pool->minpoll) - 2; DPRINTF(1, ("pool_xmit: at %ld %s->%s pool\n", current_time, latoa(lcladr), stoa(rmtadr))); msyslog(LOG_INFO, "Soliciting pool server %s", stoa(rmtadr)); + sendpkt(rmtadr, lcladr, + sys_ttl[(pool->ttl >= sys_ttlmax) ? sys_ttlmax : pool->ttl], + &xpkt, LEN_PKT_NOMAC); #endif /* WORKER */ } @@ -4999,8 +5066,18 @@ key_expire( /* - * local_refid(peer) - check peer refid to avoid selecting peers + * local_refid(peer) - Check peer refid to avoid selecting peers * currently synced to this ntpd. + * Note that until 4.2.8p18 and 4.3.1XX ntpd calculated the IPv6 + * refid differently on different-endian systems. It now calculates + * the refid the same on both, the same way it did on little-endian + * in the past. On big-endian systems, ntpd also calculates a + * byte-swapped version of each of its IPv6 local addresses' refids, + * as endpt.old_refid and also detects a loop when seeing it. This + * ensures new BE ntpd will detect loops interoperating with older + * BE ntpd, and keeps the more-common LE old ntpd code detecting + * loops with IPv6 refids correctly. Thanks to Hal Murray for + * the byte-swapping idea. */ static int local_refid( @@ -5014,10 +5091,17 @@ local_refid( else unicast_ep = findinterface(&p->srcadr); - if (unicast_ep != NULL && p->refid == unicast_ep->addr_refid) + if (unicast_ep != NULL + && ( p->refid == unicast_ep->addr_refid +#ifdef WORDS_BIGENDIAN + || ( IS_IPV6(&unicast_ep->sin) + && p->refid == unicast_ep->old_refid) +#endif + )) { return TRUE; - else + } else { return FALSE; + } } |