]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 2059] optional billboard column "server" does not honor -n.
authorDave Hart <hart@ntp.org>
Fri, 25 Nov 2011 10:23:58 +0000 (10:23 +0000)
committerDave Hart <hart@ntp.org>
Fri, 25 Nov 2011 10:23:58 +0000 (10:23 +0000)
[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

15 files changed:
ChangeLog
include/ntp.h
include/ntp_refclock.h
include/ntp_request.h
include/ntpd.h
ntpd/ntp_config.c
ntpd/ntp_control.c
ntpd/ntp_io.c
ntpd/ntp_peer.c
ntpd/ntp_proto.c
ntpd/ntp_refclock.c
ntpd/ntp_request.c
ntpq/ntpq-subs.c
ntpq/ntpq.c
ntpq/ntpq.h

index b79cdd102cc0413b41cfeb779e712fb714ad42d0..338873b2973ce089e68f68def6e9c9ea95b98b45 100644 (file)
--- 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 <stenn@ntp.org>
 
 * [Bug 2034] Listening address configuration with prefix misapplied.
index b719803e49898e8b804096688f95460403f12b54..d7e87582d708cef3dd44a3c425487904f5e0b7ae 100644 (file)
@@ -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 */
index 9fa4a7bce23aca30d3174baf565631865e222eb9..9d803e4cc4d5b033b2e8cd6fc8af28cda98346b9 100644 (file)
@@ -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 */
index 8b6dbf3b63b93461b7e53174cb54d065d338395e..7f68894479dd7578ad496a5492912efd9ebaa21e 100644 (file)
@@ -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
index 1ee0e52bdab17783e75287b817cf8e2aa963096a..75e87de97a4168f8e346402c094dc54e9af4fc77 100644 (file)
@@ -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);
index 4bd0e73a553bd478f666dba6933fd1e3c7bd08d4..db9682a74cbd04b7277dab6dcce7136a6d303016 100644 (file)
@@ -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)
index faef3c5fb635e6c3bafb82033d8f238b722ad7ac..a6904697693a6194b89e80176451607ad3ad23b8 100644 (file)
@@ -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;
 
index ab25b6e0acc580c59e38779958d6e6762f9c5864..f5584462732f4945e9e1ef071d4627ce1bb20606 100644 (file)
@@ -4366,6 +4366,17 @@ find_flagged_addr_in_list(
 }
 
 
+const char *
+localaddrtoa(
+       endpt *la
+       )
+{
+       return (NULL == la)
+                  ? "<null>"
+                  : stoa(&la->sin);
+}
+
+
 #ifdef HAS_ROUTING_SOCKET
 # ifndef UPDATE_GRACE
 #  define UPDATE_GRACE 2       /* wait UPDATE_GRACE seconds before scanning */
index d592d0c00e2b48187521f22187bc77c7d6ef37cc..619e389f03394c09c10d058f4400fb06e8fee09e 100644 (file)
@@ -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)
index 9651fc050516f22631c4964be01fecac702d84a1..d5c645504412de56daab11f7145c8526d1aac7b4 100644 (file)
@@ -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 */
 
        /*
index 08c0e40a9c1d491b0c4cfec27361f7f080d6c818..a4d30e80b118f7ff24d22e741c18547f957fd2fd 100644 (file)
@@ -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;
index bc490fae80b5f20f7b2b74ed8f0cfec9753905ae..a3c17e2267e84886347a9c2056d67ba17cc24309 100644 (file)
@@ -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, &ltmp);
                HTONL_FP(&ltmp, &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;
                }
index 8a53612814c3814c05d82191bd20e43c77655c1c..ba235f1575e91ef21dc89ce20f3d9d068ef7e302 100644 (file)
@@ -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 &&
index 9ba3925dae1af7cf734f77889092a8b4c9a472cf..bc1acc61ed7bdf16ff4ba410794853d06ac56760 100644 (file)
@@ -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
  */
index 4abc0aaefbadf0fe472aebf0b041dcc934085dca..77d5ce7f9afb33e6d1e6c0b1b690bcf9cfea02d7 100644 (file)
@@ -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);