From: Dave Hart Date: Fri, 25 Nov 2011 10:23:58 +0000 (+0000) Subject: [Bug 2059] optional billboard column "server" does not honor -n. X-Git-Tag: NTP_4_2_6P5_RC2~6^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ac67b33d4ee42b7e8a1eb95cf507da534c7a63a7;p=thirdparty%2Fntp.git [Bug 2059] optional billboard column "server" does not honor -n. [Bug 2066] ntpq lopeers ipv6 "local" column overrun. [Bug 2068] ntpd sends nonprintable stratum 16 refid to ntpq. [Bug 2069] broadcastclient, multicastclient spin up duplicate ephemeral associations without broadcastdelay. Exclude not-yet-determined sys_refid from use in loopback TEST12 (from David Mills). bk: 4ecf6cbePfJMvvlmYZy5T53uBJM6hg --- diff --git a/ChangeLog b/ChangeLog index b79cdd102..338873b29 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,13 @@ --- + +* [Bug 2059] optional billboard column "server" does not honor -n. +* [Bug 2066] ntpq lopeers ipv6 "local" column overrun. +* [Bug 2068] ntpd sends nonprintable stratum 16 refid to ntpq. +* [Bug 2069] broadcastclient, multicastclient spin up duplicate + ephemeral associations without broadcastdelay. +* Exclude not-yet-determined sys_refid from use in loopback TEST12 + (from David Mills). +--- (4.2.6p5-RC1) 2011/10/18 Released by Harlan Stenn * [Bug 2034] Listening address configuration with prefix misapplied. diff --git a/include/ntp.h b/include/ntp.h index b719803e4..d7e87582d 100644 --- a/include/ntp.h +++ b/include/ntp.h @@ -445,6 +445,7 @@ struct peer { #define FLAG_PREEMPT 0x0002 /* preemptable association */ #define FLAG_AUTHENTIC 0x0004 /* last message was authentic */ #define FLAG_REFCLOCK 0x0008 /* this is actually a reference clock */ +#define FLAG_BC_VOL 0x0010 /* broadcast client volleying */ #define FLAG_PREFER 0x0020 /* prefer peer */ #define FLAG_BURST 0x0040 /* burst mode */ #define FLAG_PPS 0x0080 /* steered by PPS */ diff --git a/include/ntp_refclock.h b/include/ntp_refclock.h index 9fa4a7bce..9d803e4cc 100644 --- a/include/ntp_refclock.h +++ b/include/ntp_refclock.h @@ -110,7 +110,7 @@ struct refclockstat { double fudgetime1; /* configure fudge time1 */ double fudgetime2; /* configure fudge time2 */ int32 fudgeval1; /* configure fudge value1 */ - int32 fudgeval2; /* configure fudge value2 */ + u_int32 fudgeval2; /* configure fudge value2 */ u_char currentstatus; /* clock status */ u_char lastevent; /* last exception event */ u_char leap; /* leap bits */ diff --git a/include/ntp_request.h b/include/ntp_request.h index 8b6dbf3b6..7f6889447 100644 --- a/include/ntp_request.h +++ b/include/ntp_request.h @@ -823,7 +823,7 @@ struct info_clock { l_fp fudgetime1; l_fp fudgetime2; int32 fudgeval1; - int32 fudgeval2; + u_int32 fudgeval2; }; @@ -834,7 +834,7 @@ struct conf_fudge { u_int32 clockadr; u_int32 which; l_fp fudgetime; - int32 fudgeval_flags; + u_int32 fudgeval_flags; }; #define FUDGE_TIME1 1 diff --git a/include/ntpd.h b/include/ntpd.h index 1ee0e52bd..75e87de97 100644 --- a/include/ntpd.h +++ b/include/ntpd.h @@ -107,6 +107,8 @@ extern void block_io_and_alarm (void); #define UNBLOCK_IO_AND_ALARM() #define BLOCK_IO_AND_ALARM() #endif +#define latoa(pif) localaddrtoa(pif) +extern const char * localaddrtoa(endpt *); /* ntp_loopfilter.c */ extern void init_loopfilter(void); @@ -126,7 +128,7 @@ extern void ntp_monclearinterface (struct interface *interface); /* ntp_peer.c */ extern void init_peer (void); -extern struct peer *findexistingpeer (sockaddr_u *, struct peer *, int); +extern struct peer *findexistingpeer (sockaddr_u *, struct peer *, int, u_char); extern struct peer *findpeer (struct recvbuf *, int, int *); extern struct peer *findpeerbyassoc (u_int); extern void set_peerdstadr (struct peer *peer, struct interface *interface); diff --git a/ntpd/ntp_config.c b/ntpd/ntp_config.c index 4bd0e73a5..db9682a74 100644 --- a/ntpd/ntp_config.c +++ b/ntpd/ntp_config.c @@ -3589,7 +3589,7 @@ config_unpeers( DPRINTF(1, ("searching for %s\n", stoa(&peeraddr))); while (!found) { - peer = findexistingpeer(&peeraddr, peer, -1); + peer = findexistingpeer(&peeraddr, peer, -1, 0); if (!peer) break; if (peer->flags & FLAG_CONFIG) diff --git a/ntpd/ntp_control.c b/ntpd/ntp_control.c index faef3c5fb..a69046976 100644 --- a/ntpd/ntp_control.c +++ b/ntpd/ntp_control.c @@ -59,7 +59,7 @@ static void ctl_putint (const char *, long); static void ctl_putts (const char *, l_fp *); static void ctl_putadr (const char *, u_int32, sockaddr_u *); -static void ctl_putid (const char *, char *); +static void ctl_putrefid (const char *, u_int32); static void ctl_putarray (const char *, double *, int); static void ctl_putsys (int); static void ctl_putpeer (int, struct peer *); @@ -1254,29 +1254,43 @@ ctl_putadr( ctl_putdata(buffer, (unsigned)(cp - buffer), 0); } + /* - * ctl_putid - write a tagged clock ID into the response + * ctl_putrefid - send a u_int32 refid as printable text */ static void -ctl_putid( - const char *tag, - char *id +ctl_putrefid( + const char * tag, + u_int32 refid ) { - register char *cp; - register const char *cq; - char buffer[200]; - - cp = buffer; - cq = tag; - while (*cq != '\0') - *cp++ = *cq++; - - *cp++ = '='; - NTP_INSIST((cp - buffer) < sizeof(buffer)); - snprintf(cp, sizeof(buffer) - (cp - buffer), "%.4s", id); - cp += strlen(cp); - ctl_putdata(buffer, (unsigned)( cp - buffer ), 0); + char output[16]; + char * optr; + char * oplim; + char * iptr; + char * iplim; + char * past_eq; + + optr = output; + oplim = output + sizeof(output); + while (optr < oplim && '\0' != *tag) + *optr++ = *tag++; + if (optr < oplim) { + *optr++ = '='; + past_eq = optr; + } + if (!(optr < oplim)) + return; + iptr = (char *)&refid; + iplim = iptr + sizeof(refid); + for (; optr < oplim && iptr < iplim; iptr++, optr++) + if (isprint(*iptr)) + *optr = *iptr; + else + *optr = '.'; + if (!(optr <= oplim)) + optr = past_eq; + ctl_putdata(output, (u_int)(optr - output), FALSE); } @@ -1353,10 +1367,9 @@ ctl_putsys( case CS_REFID: if (sys_stratum > 1 && sys_stratum < STRATUM_UNSPEC) - ctl_putadr(sys_var[CS_REFID].text, sys_refid, NULL); + ctl_putadr(sys_var[varid].text, sys_refid, NULL); else - ctl_putid(sys_var[CS_REFID].text, - (char *)&sys_refid); + ctl_putrefid(sys_var[varid].text, sys_refid); break; case CS_REFTIME: @@ -1678,18 +1691,17 @@ ctl_putpeer( break; case CP_REFID: +#ifdef REFCLOCK if (peer->flags & FLAG_REFCLOCK) { - ctl_putid(peer_var[CP_REFID].text, - (char *)&peer->refid); - } else { - if (peer->stratum > 1 && peer->stratum < - STRATUM_UNSPEC) - ctl_putadr(peer_var[CP_REFID].text, - peer->refid, NULL); - else - ctl_putid(peer_var[CP_REFID].text, - (char *)&peer->refid); + ctl_putrefid(peer_var[varid].text, peer->refid); + break; } +#endif + if (peer->stratum > 1 && peer->stratum < STRATUM_UNSPEC) + ctl_putadr(peer_var[varid].text, peer->refid, + NULL); + else + ctl_putrefid(peer_var[varid].text, peer->refid); break; case CP_REFTIME: @@ -1923,8 +1935,9 @@ ctl_putclock( break; case CC_FUDGETIME2: - if (mustput || (clock_stat->haveflags & CLK_HAVETIME2)) ctl_putdbl(clock_var[CC_FUDGETIME2].text, - clock_stat->fudgetime2 * 1e3); + if (mustput || (clock_stat->haveflags & CLK_HAVETIME2)) + ctl_putdbl(clock_var[CC_FUDGETIME2].text, + clock_stat->fudgetime2 * 1e3); break; case CC_FUDGEVAL1: @@ -1937,10 +1950,10 @@ ctl_putclock( if (mustput || (clock_stat->haveflags & CLK_HAVEVAL2)) { if (clock_stat->fudgeval1 > 1) ctl_putadr(clock_var[CC_FUDGEVAL2].text, - (u_int32)clock_stat->fudgeval2, NULL); + clock_stat->fudgeval2, NULL); else - ctl_putid(clock_var[CC_FUDGEVAL2].text, - (char *)&clock_stat->fudgeval2); + ctl_putrefid(clock_var[CC_FUDGEVAL2].text, + clock_stat->fudgeval2); } break; diff --git a/ntpd/ntp_io.c b/ntpd/ntp_io.c index ab25b6e0a..f55844627 100644 --- a/ntpd/ntp_io.c +++ b/ntpd/ntp_io.c @@ -4366,6 +4366,17 @@ find_flagged_addr_in_list( } +const char * +localaddrtoa( + endpt *la + ) +{ + return (NULL == la) + ? "" + : stoa(&la->sin); +} + + #ifdef HAS_ROUTING_SOCKET # ifndef UPDATE_GRACE # define UPDATE_GRACE 2 /* wait UPDATE_GRACE seconds before scanning */ diff --git a/ntpd/ntp_peer.c b/ntpd/ntp_peer.c index d592d0c00..619e389f0 100644 --- a/ntpd/ntp_peer.c +++ b/ntpd/ntp_peer.c @@ -183,9 +183,10 @@ getmorepeermem(void) */ struct peer * findexistingpeer( - sockaddr_u *addr, - struct peer *start_peer, - int mode + sockaddr_u * addr, + struct peer * start_peer, + int mode, + u_char cast_flags ) { register struct peer *peer; @@ -193,6 +194,12 @@ findexistingpeer( /* * 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)]; @@ -200,18 +207,21 @@ findexistingpeer( peer = start_peer->next; while (peer != NULL) { - if (SOCK_EQ(addr, &peer->srcadr) - && NSRCPORT(addr) == NSRCPORT(&peer->srcadr) - && (-1 == mode || peer->hmode == mode)) + if (ADDR_PORT_EQ(addr, &peer->srcadr) + && (-1 == mode || peer->hmode == mode || + ((MDF_BCLNT & peer->cast_flags) && + (MDF_BCLNT & cast_flags)))) break; peer = peer->next; } - return (peer); + + return peer; } /* - * findpeer - find and return a peer in the hash table. + * findpeer - find and return a peer match for a received datagram in + * the peer_hash table. */ struct peer * findpeer( @@ -280,8 +290,11 @@ findpeer( *action = MATCH_ASSOC(NO_PEER, pkt_mode); } else if (p->dstadr != rbufp->dstadr) { set_peerdstadr(p, rbufp->dstadr); - DPRINTF(1, ("changed %s local address to match response", - stoa(&p->srcadr))); + 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; } @@ -538,13 +551,12 @@ set_peerdstadr( if (p->dstadr == dstadr) return; - if (dstadr != NULL && (MDF_BCLNT & p->cast_flags) && - (dstadr->flags & INT_MCASTIF) && p->burst) { - /* - * don't accept updates to a true multicast - * reception interface while a BCLNT peer is - * running it's unicast protocol - */ + /* + * Don't accept updates to a separate multicast receive-only + * endpt while a BCLNT peer is running its unicast protocol. + */ + if (dstadr != NULL && (FLAG_BC_VOL & p->flags) && + (INT_MCASTIF & dstadr->flags) && MODE_CLIENT == p->hmode) { return; } if (p->dstadr != NULL) { @@ -754,23 +766,30 @@ newpeer( * actual interface, because that's what gets put into the peer * structure. */ - peer = findexistingpeer(srcadr, NULL, hmode); if (dstadr != NULL) { + peer = findexistingpeer(srcadr, NULL, hmode, cast_flags); while (peer != NULL) { - if (peer->dstadr == dstadr) + if (peer->dstadr == dstadr || + ((MDF_BCLNT & cast_flags) && + (MDF_BCLNT & peer->cast_flags))) break; if (dstadr == ANY_INTERFACE_CHOOSE(srcadr) && peer->dstadr == findinterface(srcadr)) break; - peer = findexistingpeer(srcadr, peer, hmode); + peer = findexistingpeer(srcadr, peer, hmode, + cast_flags); } + } else { + /* no endpt address given */ + peer = findexistingpeer(srcadr, NULL, hmode, cast_flags); } /* * If a peer is found, this would be a duplicate and we don't - * allow that. This is mostly to avoid duplicate pool + * allow that. This avoids duplicate ephemeral (broadcast/ + * multicast) and preemptible (manycast and pool) client * associations. */ if (peer != NULL) diff --git a/ntpd/ntp_proto.c b/ntpd/ntp_proto.c index 9651fc050..d5c645504 100644 --- a/ntpd/ntp_proto.c +++ b/ntpd/ntp_proto.c @@ -125,6 +125,7 @@ static void fast_xmit (struct recvbuf *, int, keyid_t, int); static void clock_update (struct peer *); static int default_get_precision (void); +static int local_refid (struct peer *); static int peer_unfit (struct peer *); @@ -309,6 +310,7 @@ receive( u_int32 opcode = 0; /* extension field opcode */ sockaddr_u *dstadr_sin; /* active runway */ 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 */ @@ -848,6 +850,20 @@ receive( } #endif /* OPENSSL */ + /* + * Broadcasts received via a multicast address may + * arrive after a unicast volley has begun + * with the same remote address. newpeer() will not + * find duplicate associations on other local endpoints + * if a non-NULL endpoint is supplied. multicastclient + * ephemeral associations are unique across all local + * endpoints. + */ + if (!(INT_MCASTOPEN & rbufp->dstadr->flags)) + match_ep = rbufp->dstadr; + else + match_ep = NULL; + /* * Determine whether to execute the initial volley. */ @@ -867,10 +883,11 @@ receive( * Do not execute the volley. Start out in * broadcast client mode. */ - if ((peer = newpeer(&rbufp->recv_srcadr, - rbufp->dstadr, MODE_BCLIENT, hisversion, - pkt->ppoll, pkt->ppoll, 0, 0, 0, - skeyid)) == NULL) { + peer = newpeer(&rbufp->recv_srcadr, match_ep, + MODE_BCLIENT, hisversion, pkt->ppoll, + pkt->ppoll, FLAG_PREEMPT, MDF_BCLNT, 0, + skeyid); + if (NULL == peer) { sys_restricted++; return; /* ignore duplicate */ @@ -889,10 +906,11 @@ receive( * packet, normally 6 (64 s) and that the poll interval * is fixed at this value. */ - if ((peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr, + peer = newpeer(&rbufp->recv_srcadr, match_ep, MODE_CLIENT, hisversion, pkt->ppoll, pkt->ppoll, - FLAG_IBURST | FLAG_PREEMPT, MDF_BCLNT, 0, - skeyid)) == NULL) { + FLAG_BC_VOL | FLAG_IBURST | FLAG_PREEMPT, MDF_BCLNT, + 0, skeyid); + if (NULL == peer) { sys_restricted++; return; /* ignore duplicate */ } @@ -1495,8 +1513,8 @@ process_packet( * timestamp. This works for both basic and interleaved * modes. */ - if (peer->cast_flags & MDF_BCLNT) { - peer->cast_flags &= ~MDF_BCLNT; + if (FLAG_BC_VOL & peer->flags) { + peer->flags &= ~FLAG_BC_VOL; peer->delay = (peer->offset - p_offset) * 2; } p_del = peer->delay; @@ -1602,8 +1620,8 @@ process_packet( * client mode when the client is fit and the autokey dance is * complete. */ - if ((peer->cast_flags & MDF_BCLNT) && !(peer_unfit(peer) & - TEST11)) { + if ((FLAG_BC_VOL & peer->flags) && MODE_CLIENT == peer->hmode && + !(TEST11 & peer_unfit(peer))) { /* distance exceeded */ #ifdef OPENSSL if (peer->flags & FLAG_SKEY) { if (!(~peer->crypto & CRYPTO_FLAG_ALL)) @@ -3389,6 +3407,29 @@ key_expire( #endif /* OPENSSL */ +/* + * local_refid(peer) - check peer refid to avoid selecting peers + * currently synced to this ntpd. + */ +static int +local_refid( + struct peer * p + ) +{ + endpt * unicast_ep; + + if (!(INT_MCASTIF & p->dstadr->flags)) + unicast_ep = p->dstadr; + else + unicast_ep = findinterface(&p->srcadr); + + if (unicast_ep != NULL && p->refid == unicast_ep->addr_refid) + return TRUE; + else + return FALSE; +} + + /* * Determine if the peer is unfit for synchronization * @@ -3429,9 +3470,7 @@ peer_unfit( * server as the local peer but only if the remote peer is * neither a reference clock nor an orphan. */ - if (peer->stratum > 1 && peer->refid != htonl(LOOPBACKADR) && - (peer->refid == (peer->dstadr ? peer->dstadr->addr_refid : - 0) || peer->refid == sys_refid)) + if (peer->stratum > 1 && local_refid(peer)) rval |= TEST12; /* synchronization loop */ /* diff --git a/ntpd/ntp_refclock.c b/ntpd/ntp_refclock.c index 08c0e40a9..a4d30e80b 100644 --- a/ntpd/ntp_refclock.c +++ b/ntpd/ntp_refclock.c @@ -1041,7 +1041,7 @@ refclock_control( clktype = (u_char)REFCLOCKTYPE(srcadr); unit = REFCLOCKUNIT(srcadr); - peer = findexistingpeer(srcadr, NULL, -1); + peer = findexistingpeer(srcadr, NULL, -1, 0); if (NULL == peer || NULL == peer->procptr) return; @@ -1140,7 +1140,7 @@ refclock_buginfo( clktype = (u_char) REFCLOCKTYPE(srcadr); unit = REFCLOCKUNIT(srcadr); - peer = findexistingpeer(srcadr, NULL, -1); + peer = findexistingpeer(srcadr, NULL, -1, 0); if (NULL == peer || NULL == peer->procptr) return; diff --git a/ntpd/ntp_request.c b/ntpd/ntp_request.c index bc490fae8..a3c17e226 100644 --- a/ntpd/ntp_request.c +++ b/ntpd/ntp_request.c @@ -852,7 +852,8 @@ peer_info ( addr.sa.sa_len = SOCKLEN(&addr); #endif ipl++; - if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0) + pp = findexistingpeer(&addr, NULL, -1, 0); + if (NULL == pp) continue; if (IS_IPV6(srcadr)) { if (pp->dstadr) @@ -990,7 +991,8 @@ peer_stats ( ipl = (struct info_peer_list *)((char *)ipl + INFO_ITEMSIZE(inpkt->mbz_itemsize)); - if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == NULL) + pp = findexistingpeer(&addr, NULL, -1, 0); + if (NULL == pp) continue; DPRINTF(1, ("peer_stats: found %s\n", stoa(&addr))); @@ -1575,7 +1577,7 @@ do_unconf( DPRINTF(1, ("searching for %s\n", stoa(&peeraddr))); while (!found) { - peer = findexistingpeer(&peeraddr, peer, -1); + peer = findexistingpeer(&peeraddr, peer, -1, 0); if (!peer) break; if (peer->flags & FLAG_CONFIG) @@ -1618,7 +1620,7 @@ do_unconf( peer = NULL; while (!found) { - peer = findexistingpeer(&peeraddr, peer, -1); + peer = findexistingpeer(&peeraddr, peer, -1, 0); if (!peer) break; if (peer->flags & FLAG_CONFIG) @@ -2135,7 +2137,7 @@ reset_peer( #ifdef ISC_PLATFORM_HAVESALEN peeraddr.sa.sa_len = SOCKLEN(&peeraddr); #endif - peer = findexistingpeer(&peeraddr, NULL, -1); + peer = findexistingpeer(&peeraddr, NULL, -1, 0); if (NULL == peer) bad++; cp = (struct conf_unpeer *)((char *)cp + @@ -2166,10 +2168,10 @@ reset_peer( #ifdef ISC_PLATFORM_HAVESALEN peeraddr.sa.sa_len = SOCKLEN(&peeraddr); #endif - peer = findexistingpeer(&peeraddr, NULL, -1); + peer = findexistingpeer(&peeraddr, NULL, -1, 0); while (peer != NULL) { peer_reset(peer); - peer = findexistingpeer(&peeraddr, peer, -1); + peer = findexistingpeer(&peeraddr, peer, -1, 0); } cp = (struct conf_unpeer *)((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize)); @@ -2682,7 +2684,7 @@ get_clock_info( while (items-- > 0) { NSRCADR(&addr) = *clkaddr++; if (!ISREFCLOCKADR(&addr) || - findexistingpeer(&addr, NULL, -1) == NULL) { + findexistingpeer(&addr, NULL, -1, 0) == NULL) { req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); return; } @@ -2706,7 +2708,7 @@ get_clock_info( DTOLFP(clock_stat.fudgetime2, <mp); HTONL_FP(<mp, &ic->fudgetime2); ic->fudgeval1 = htonl((u_int32)clock_stat.fudgeval1); - ic->fudgeval2 = htonl((u_int32)clock_stat.fudgeval2); + ic->fudgeval2 = htonl(clock_stat.fudgeval2); free_varlist(clock_stat.kv_list); @@ -2746,7 +2748,7 @@ set_clock_fudge( #endif SET_PORT(&addr, NTP_PORT); if (!ISREFCLOCKADR(&addr) || - findexistingpeer(&addr, NULL, -1) == 0) { + findexistingpeer(&addr, NULL, -1, 0) == 0) { req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); return; } @@ -2821,7 +2823,7 @@ get_clkbug_info( while (items-- > 0) { NSRCADR(&addr) = *clkaddr++; if (!ISREFCLOCKADR(&addr) || - findexistingpeer(&addr, NULL, -1) == 0) { + findexistingpeer(&addr, NULL, -1, 0) == 0) { req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); return; } diff --git a/ntpq/ntpq-subs.c b/ntpq/ntpq-subs.c index 8a5361281..ba235f157 100644 --- a/ntpq/ntpq-subs.c +++ b/ntpq/ntpq-subs.c @@ -13,6 +13,7 @@ extern char * chosts[]; extern char currenthost[]; +extern int currenthostisnum; extern int numhosts; int maxhostlen; @@ -1442,8 +1443,10 @@ doprintpeers( sockaddr_u srcadr; sockaddr_u dstadr; + sockaddr_u refidadr; u_long srcport = 0; char *dstadr_refid = "0.0.0.0"; + char *serverlocal; size_t drlen; u_long stratum = 0; long ppoll = 0; @@ -1490,10 +1493,10 @@ doprintpeers( case CP_DSTADR: if (decodenetnum(value, &dum_store)) { type = decodeaddrtype(&dum_store); + havevar[HAVE_DSTADR] = 1; + dstadr = dum_store; if (pvl == opeervarlist) { - havevar[HAVE_DSTADR] = 1; - dstadr = dum_store; - dstadr_refid = stoa(&dstadr); + dstadr_refid = trunc_left(stoa(&dstadr), 15); } } break; @@ -1509,15 +1512,15 @@ doprintpeers( refid_string[i] = '.'; refid_string[i+1] = '\0'; dstadr_refid = refid_string; - } else if (decodenetnum(value, &dstadr)) { - if (SOCK_UNSPEC(&dstadr)) + } else if (decodenetnum(value, &refidadr)) { + if (SOCK_UNSPEC(&refidadr)) dstadr_refid = "0.0.0.0"; - else if (ISREFCLOCKADR(&dstadr)) + else if (ISREFCLOCKADR(&refidadr)) dstadr_refid = - refnumtoa(&dstadr); + refnumtoa(&refidadr); else dstadr_refid = - stoa(&dstadr); + stoa(&refidadr); } else { havevar[HAVE_REFID] = 0; } @@ -1595,8 +1598,20 @@ doprintpeers( c = flash3[CTL_PEER_STATVAL(rstatus) & 0x7]; else c = flash2[CTL_PEER_STATVAL(rstatus) & 0x3]; - if (numhosts > 1) - fprintf(fp, "%-*s ", maxhostlen, currenthost); + if (numhosts > 1) { + if (peervarlist == pvl && havevar[HAVE_DSTADR]) { + serverlocal = nntohost_col(&dstadr, + (size_t)min(LIB_BUFLENGTH - 1, maxhostlen), + TRUE); + } else { + if (currenthostisnum) + serverlocal = trunc_left(currenthost, + maxhostlen); + else + serverlocal = currenthost; + } + fprintf(fp, "%-*s ", maxhostlen, serverlocal); + } if (AF_UNSPEC == af || AF(&srcadr) == af) { strncpy(clock_name, nntohost(&srcadr), sizeof(clock_name)); fprintf(fp, "%c%-15.15s ", c, clock_name); @@ -1694,27 +1709,32 @@ dopeers( int af ) { - register int i; - char fullname[LENHOSTNAME]; - sockaddr_u netnum; + int i; + char fullname[LENHOSTNAME]; + sockaddr_u netnum; + char * name_or_num; + size_t sl; if (!dogetassoc(fp)) return; for (i = 0; i < numhosts; ++i) { - if (getnetnum(chosts[i], &netnum, fullname, af)) - if ((int)strlen(fullname) > maxhostlen) - maxhostlen = strlen(fullname); + if (getnetnum(chosts[i], &netnum, fullname, af)) { + name_or_num = nntohost(&netnum); + sl = strlen(name_or_num); + maxhostlen = max(maxhostlen, (int)sl); + } } if (numhosts > 1) - (void) fprintf(fp, "%-*.*s ", maxhostlen, maxhostlen, "server"); - (void) fprintf(fp, - " remote refid st t when poll reach delay offset jitter\n"); + fprintf(fp, "%-*.*s ", maxhostlen, maxhostlen, + "server (local)"); + fprintf(fp, + " remote refid st t when poll reach delay offset jitter\n"); if (numhosts > 1) for (i = 0; i <= maxhostlen; ++i) - (void) fprintf(fp, "="); - (void) fprintf(fp, - "==============================================================================\n"); + fprintf(fp, "="); + fprintf(fp, + "==============================================================================\n"); for (i = 0; i < numassoc; i++) { if (!showall && diff --git a/ntpq/ntpq.c b/ntpq/ntpq.c index 9ba3925da..bc1acc61e 100644 --- a/ntpq/ntpq.c +++ b/ntpq/ntpq.c @@ -379,6 +379,7 @@ struct sock_timeval tvout = { DEFTIMEOUT, 0 }; /* time out for reads */ struct sock_timeval tvsout = { DEFSTIMEOUT, 0 };/* secondary time out */ l_fp delay_time; /* delay time */ char currenthost[LENHOSTNAME]; /* current host name */ +int currenthostisnum; /* is prior text from IP? */ struct sockaddr_in hostaddr = { 0 }; /* host address */ int showhostnames = 1; /* show host names by default */ @@ -657,7 +658,7 @@ openhost( * give it an IPv4 address to lookup. */ strcpy(service, "ntp"); - memset((char *)&hints, 0, sizeof(struct addrinfo)); + ZERO(hints); hints.ai_family = ai_fam_templ; hints.ai_protocol = IPPROTO_UDP; hints.ai_socktype = SOCK_DGRAM; @@ -687,13 +688,14 @@ openhost( return 0; } - if (ai->ai_canonname == NULL) { + if (!showhostnames || ai->ai_canonname == NULL) { strncpy(temphost, stoa((sockaddr_u *)ai->ai_addr), LENHOSTNAME); - + currenthostisnum = TRUE; } else { strncpy(temphost, ai->ai_canonname, LENHOSTNAME); + currenthostisnum = FALSE; } temphost[LENHOSTNAME-1] = '\0'; @@ -1879,12 +1881,39 @@ nntohost( sockaddr_u *netnum ) { - if (!showhostnames) - return stoa(netnum); - else if (ISREFCLOCKADR(netnum)) - return refnumtoa(netnum); - else - return socktohost(netnum); + return nntohost_col(netnum, LIB_BUFLENGTH - 1, FALSE); +} + + +/* + * nntohost_col - convert network number to host name in fixed width. + * This routine enforces the showhostnames setting. + * When displaying hostnames longer than the width, + * the first part of the hostname is displayed. When + * displaying numeric addresses longer than the width, + * Such as IPv6 addresses, the caller decides whether + * the first or last of the numeric address is used. + */ +char * +nntohost_col( + sockaddr_u * addr, + size_t width, + int preserve_lowaddrbits + ) +{ + const char * out; + + if (!showhostnames) { + if (preserve_lowaddrbits) + out = trunc_left(stoa(addr), width); + else + out = trunc_right(stoa(addr), width); + } else if (ISREFCLOCKADR(addr)) { + out = refnumtoa(addr); + } else { + out = trunc_right(socktohost(addr), width); + } + return out; } @@ -2818,6 +2847,62 @@ asciize( } +/* + * truncate string to fit clipping excess at end. + * "too long" -> "too l" + * Used for hostnames. + */ +char * +trunc_right( + const char * src, + size_t width + ) +{ + size_t sl; + char * out; + + + sl = strlen(src); + if (sl > width && LIB_BUFLENGTH - 1 > width && width > 0) { + LIB_GETBUF(out); + memcpy(out, src, width); + out[width] = '\0'; + + return out; + } + + return src; +} + + +/* + * truncate string to fit by preserving right side and using '_' to hint + * "too long" -> "_long" + * Used for local IPv6 addresses, where low bits differentiate. + */ +char * +trunc_left( + const char * src, + size_t width + ) +{ + size_t sl; + char * out; + + + sl = strlen(src); + if (sl > width && LIB_BUFLENGTH - 1 > width && width > 1) { + LIB_GETBUF(out); + out[0] = '_'; + memcpy(&out[1], &src[sl + 1 - width], width); + + return out; + } + + return src; +} + + /* * Some circular buffer space */ diff --git a/ntpq/ntpq.h b/ntpq/ntpq.h index 4abc0aaef..77d5ce7f9 100644 --- a/ntpq/ntpq.h +++ b/ntpq/ntpq.h @@ -6,6 +6,7 @@ #include "ntp_control.h" #include "ntp_string.h" #include "ntp_malloc.h" +#include "lib_strbuf.h" /* * Maximum number of arguments @@ -91,6 +92,7 @@ extern int doquery (int, associd_t, int, int, char *, extern int doqueryex (int, associd_t, int, int, char *, u_short *, int *, const char **, int); extern char * nntohost (sockaddr_u *); +extern char * nntohost_col (sockaddr_u *, size_t, int); extern int decodets (char *, l_fp *); extern int decodeuint (char *, u_long *); extern int nextvar (int *, const char **, char **, char **); @@ -99,3 +101,5 @@ extern void printvars (int, const char *, int, int, int, FILE *); extern int decodeint (char *, long *); extern int findvar (char *, struct ctl_var *, int code); extern void makeascii (int, const char *, FILE *); +extern char * trunc_left (const char *, size_t); +extern char * trunc_right (const char *, size_t);