[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
---
+
+* [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.
#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 */
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 */
l_fp fudgetime1;
l_fp fudgetime2;
int32 fudgeval1;
- int32 fudgeval2;
+ u_int32 fudgeval2;
};
u_int32 clockadr;
u_int32 which;
l_fp fudgetime;
- int32 fudgeval_flags;
+ u_int32 fudgeval_flags;
};
#define FUDGE_TIME1 1
#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);
/* 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);
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)
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 *);
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);
}
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:
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:
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:
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;
}
+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 */
*/
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;
/*
* 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)];
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(
*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;
}
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) {
* 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)
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 *);
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 */
}
#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.
*/
* 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 */
* 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 */
}
* 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;
* 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))
#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
*
* 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 */
/*
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;
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;
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)
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)));
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)
peer = NULL;
while (!found) {
- peer = findexistingpeer(&peeraddr, peer, -1);
+ peer = findexistingpeer(&peeraddr, peer, -1, 0);
if (!peer)
break;
if (peer->flags & FLAG_CONFIG)
#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 +
#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));
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;
}
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);
#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;
}
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;
}
extern char * chosts[];
extern char currenthost[];
+extern int currenthostisnum;
extern int numhosts;
int maxhostlen;
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;
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;
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;
}
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);
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 &&
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 */
* 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;
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';
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;
}
}
+/*
+ * 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
*/
#include "ntp_control.h"
#include "ntp_string.h"
#include "ntp_malloc.h"
+#include "lib_strbuf.h"
/*
* Maximum number of arguments
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 **);
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);