]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 1978] Ignore tentative IP addresses on Linux.
authorDave Hart <hart@ntp.org>
Wed, 27 Jul 2011 21:41:02 +0000 (21:41 +0000)
committerDave Hart <hart@ntp.org>
Wed, 27 Jul 2011 21:41:02 +0000 (21:41 +0000)
Backport several fixes for Coverity warnings from ntp-dev.

bk: 4e3085eekVdLxvStZswxGqUcK3dIyQ

ChangeLog
configure.ac
include/ntp_rfc2553.h
lib/isc/unix/interfaceiter.c
libntp/audio.c
libntp/decodenetnum.c
libntp/icom.c
ntpd/refclock_arc.c
ntpdc/ntpdc.c
ntpq/ntpq.c

index ea64e6ff6d39b430ad79fcea291b7379f161feb9..b6fb0fb4cbe4e18e9921ccd0e3b7d4c876eef1a6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,6 +5,8 @@
 * [Bug 1970] UNLINK_EXPR_SLIST() causes crash if list is empty.
 * [Bug 1972] checking for struct rtattr fails.
 * [Bug 1975] libntp/mktime.c won't work with 64-bit time_t
+* [Bug 1978] Ignore tentative IP addresses on Linux.
+* Backport several fixes for Coverity warnings from ntp-dev.
 
 ---
 (4.2.6p4-RC1) 2011/07/10 Released by Harlan Stenn <stenn@ntp.org>
index c215bccfeabe3338f3c81a68380101ebc596ebbb..99b009183a7aac1b1cc52c5af1f6c75a6e0a762e 100644 (file)
@@ -516,6 +516,15 @@ typedef union mpinfou {            /* For lint */
     ;;
 esac
 
+case "$host" in
+ *-linux*)
+    AC_CHECK_HEADERS([linux/if_addr.h], [], [], [
+       #ifdef HAVE_SYS_SOCKET_H
+       # include <sys/socket.h>
+       #endif
+    ])
+esac
+
 AC_CHECK_HEADERS([net/if.h], [], [],
 [#ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
index 4ed1b657cbe4f0f46338f100098e05dabf6c1ba4..8e824f4a240b1f5ccb45ff139f81c1f3a8789e2a 100644 (file)
@@ -79,7 +79,7 @@
 #include "ntp_types.h"
 
 
- /*
+/*
  * If various macros are not defined we need to define them
  */
 
@@ -146,7 +146,15 @@ struct sockaddr_storage {
 #endif /* !AI_PASSIVE */
 
 #ifndef AI_NUMERICHOST         /* such as AIX 4.3 */
-#define AI_NUMERICHOST 0
+# define Z_AI_NUMERICHOST      0
+#else
+# define Z_AI_NUMERICHOST      AI_NUMERICHOST
+#endif
+
+#ifndef AI_NUMERICSERV         /* not in RFC 2553 */
+# define Z_AI_NUMERICSERV      0
+#else
+# define Z_AI_NUMERICSERV      AI_NUMERICSERV
 #endif
 
 #ifndef ISC_PLATFORM_HAVEIPV6
index 5f5ee981120491b393b6dcd9785222cbca57c9a0..996669fc91e0917af17274044c3707b5a089531b 100644 (file)
@@ -51,7 +51,7 @@
 #endif
 #include <net/if.h>
 
-#ifdef __linux
+#ifdef HAVE_LINUX_IF_ADDR_H
 # include <linux/if_addr.h>
 #endif
 
@@ -84,11 +84,11 @@ get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src,
        switch (family) {
        case AF_INET:
                memcpy(&dst->type.in,
-                      &((struct sockaddr_in *) src)->sin_addr,
+                      &((struct sockaddr_in *)(void *)src)->sin_addr,
                       sizeof(struct in_addr));
                break;
        case AF_INET6:
-               sa6 = (struct sockaddr_in6 *)src;
+               sa6 = (struct sockaddr_in6 *)(void *)src;
                memcpy(&dst->type.in6, &sa6->sin6_addr,
                       sizeof(struct in6_addr));
 #ifdef ISC_PLATFORM_HAVESCOPEID
@@ -225,8 +225,10 @@ linux_if_inet6_current(isc_interfaceiter_t *iter) {
        ** Ignore DAD addresses --
        ** we can't bind to them until they are resolved
        */
+#ifdef IFA_F_TENTATIVE
        if (flags & IFA_F_TENTATIVE)
                return (ISC_R_IGNORE);
+#endif
 
        for (i = 0; i < 16; i++) {
                unsigned char byte;
index a685fe9521ada1516fcbfb94cc93c791b7cfec21..d9af6b51f3bc873cd1a4e8696109f5e5d84f045c 100644 (file)
@@ -174,21 +174,21 @@ audio_config_read(
                for (; *ca && isascii((int)*ca) && (isspace((int)*ca) || (*ca == '=')); ca++)
                        continue;
 
-               if (!strncmp(cc, "IDEV", (size_t) 4)) {
-                       sscanf(ca, "%s", ab);
-                       strcpy(cf_i_dev, ab);
+               if (!strncmp(cc, "IDEV", 4) &&
+                   1 == sscanf(ca, "%99s", ab)) {
+                       strncpy(cf_i_dev, ab, sizeof(cf_i_dev));
                        printf("idev <%s>\n", ab);
-               } else if (!strncmp(cc, "CDEV", (size_t) 4)) {
-                       sscanf(ca, "%s", ab);
-                       strcpy(cf_c_dev, ab);
+               } else if (!strncmp(cc, "CDEV", 4) &&
+                          1 == sscanf(ca, "%99s", ab)) {
+                       strncpy(cf_c_dev, ab, sizeof(cf_c_dev));
                        printf("cdev <%s>\n", ab);
-               } else if (!strncmp(cc, "AGC", (size_t) 3)) {
-                       sscanf(ca, "%s", ab);
-                       strcpy(cf_agc, ab);
+               } else if (!strncmp(cc, "AGC", 3) &&
+                          1 == sscanf(ca, "%99s", ab)) {
+                       strncpy(cf_agc, ab, sizeof(cf_agc));
                        printf("agc <%s> %d\n", ab, i);
-               } else if (!strncmp(cc, "MONITOR", (size_t) 7)) {
-                       sscanf(ca, "%s", ab);
-                       strcpy(cf_monitor, ab);
+               } else if (!strncmp(cc, "MONITOR", 7) &&
+                          1 == sscanf(ca, "%99s", ab)) {
+                       strncpy(cf_monitor, ab, sizeof(cf_monitor));
                        printf("monitor <%s> %d\n", ab, mixer_name(ab, -1));
                }
        }
@@ -316,7 +316,7 @@ audio_init(
            printf("SOUND_MIXER_READ_RECMASK: %s\n", strerror(errno));
 
        /* validate and set any specified config file stuff */
-       if (*cf_agc) {
+       if (cf_agc[0] != '\0') {
                int i;
 
                i = mixer_name(cf_agc, devmask);
@@ -327,7 +327,7 @@ audio_init(
                               cf_agc, recmask);
        }
 
-       if (*cf_monitor) {
+       if (cf_monitor[0] != '\0') {
                int i;
 
                /* devmask */
@@ -388,17 +388,16 @@ audio_gain(
        r = 0 ; /* setting to zero nicely mutes the channel */
 #endif
        l |= r << 8;
-        if ( cf_agc )
-          rval = ioctl(ctl_fd, agc, &l);
-        else
-         if (port == 2) {
-           rval = ioctl(ctl_fd, SOUND_MIXER_WRITE_LINE, &l);
-         } else {
-           rval = ioctl(ctl_fd, SOUND_MIXER_WRITE_MIC, &l);
-         }
-       if (rval == -1) {
+       if (cf_agc[0] != '\0')
+               rval = ioctl(ctl_fd, agc, &l);
+       else
+               if (2 == port)
+                       rval = ioctl(ctl_fd, SOUND_MIXER_WRITE_LINE, &l);
+               else
+                       rval = ioctl(ctl_fd, SOUND_MIXER_WRITE_MIC, &l);
+       if (-1 == rval) {
                printf("audio_gain: agc write: %s\n", strerror(errno));
-               return (rval);
+               return rval;
        }
 
        if (o_mongain != mongain) {
@@ -408,11 +407,12 @@ audio_gain(
                        printf("audio_gain: mongain %d/%d\n", mongain, l);
 # endif
                l |= r << 8;
-                if ( cf_monitor )
-                  rval = ioctl(ctl_fd, monitor, &l );
-                else 
-                 rval = ioctl(ctl_fd, SOUND_MIXER_WRITE_VOLUME, &l);
-               if (rval == -1) {
+               if (cf_monitor[0] != '\0')
+                       rval = ioctl(ctl_fd, monitor, &l );
+               else 
+                       rval = ioctl(ctl_fd, SOUND_MIXER_WRITE_VOLUME,
+                                    &l);
+               if (-1 == rval) {
                        printf("audio_gain: mongain write: %s\n",
                               strerror(errno));
                        return (rval);
index 1ce98ae891bf54fbc8e84227890066a0b85f7119..f265daebf9c66c0a754ef5780f84b3e324f907aa 100644 (file)
 #include <netinet/in.h>
 #endif
 
+#include "ntp.h"
 #include "ntp_stdlib.h"
 #include "ntp_assert.h"
 
+/*
+ * decodenetnum                convert text IP address and port to sockaddr_u
+ *
+ * Returns 0 for failure, 1 for success.
+ */
 int
 decodenetnum(
        const char *num,
@@ -21,30 +27,57 @@ decodenetnum(
        )
 {
        struct addrinfo hints, *ai = NULL;
-       register int err;
-       register const char *cp;
-       char name[80];
+       int err;
+       u_short port;
+       const char *cp;
+       const char *port_str;
+       char *pp;
        char *np;
+       char name[80];
 
        NTP_REQUIRE(num != NULL);
        NTP_REQUIRE(strlen(num) < sizeof(name));
 
-       if ('[' != num[0]) 
-               cp = num;
-       else {
+       port_str = NULL;
+       if ('[' != num[0]) {
+               /*
+                * to distinguish IPv6 embedded colons from a port
+                * specification on an IPv4 address, assume all 
+                * legal IPv6 addresses have at least two colons.
+                */
+               pp = strchr(num, ':');
+               if (NULL == pp)
+                       cp = num;       /* no colons */
+               else if (NULL != strchr(pp + 1, ':'))
+                       cp = num;       /* two or more colons */
+               else {                  /* one colon */
+                       strncpy(name, num, sizeof(name));
+                       name[sizeof(name) - 1] = '\0';
+                       cp = name;
+                       pp = strchr(cp, ':');
+                       *pp = '\0';
+                       port_str = pp + 1;
+               }
+       } else {
                cp = num + 1;
                np = name; 
                while (*cp && ']' != *cp)
                        *np++ = *cp++;
                *np = 0;
+               if (']' == cp[0] && ':' == cp[1] && '\0' != cp[2])
+                       port_str = &cp[2];
                cp = name; 
        }
-       memset(&hints, 0, sizeof(hints));
-       hints.ai_flags = AI_NUMERICHOST;
-       err = getaddrinfo(cp, NULL, &hints, &ai);
+       ZERO(hints);
+       hints.ai_flags = Z_AI_NUMERICHOST;
+       err = getaddrinfo(cp, "ntp", &hints, &ai);
        if (err != 0)
                return 0;
-       memcpy(netnum, ai->ai_addr, ai->ai_addrlen); 
+       NTP_INSIST(ai->ai_addrlen <= sizeof(*netnum));
+       memcpy(netnum, ai->ai_addr, ai->ai_addrlen);
        freeaddrinfo(ai);
+       if (NULL == port_str || 1 != sscanf(port_str, "%hu", &port))
+               port = NTP_PORT;
+       SET_PORT(netnum, port);
        return 1;
 }
index 557fc06ae87921c90b9eecf7261bb376a0781236..c981d8548418bd6615c786e65300f22e4a0bfd8a 100644 (file)
@@ -5,6 +5,7 @@
  * distribution. The only function provided is to load the radio
  * frequency. All other parameters must be manually set before use.
  */
+#include <config.h>
 #include "icom.h"
 #include <unistd.h>
 #include <stdio.h>
 #include "ntp_tty.h"
 #include "l_stdlib.h"
 
+#ifdef SYS_WINNT
+#undef write   /* ports/winnt/include/config.h: #define write _write */
+extern int async_write(int, const void *, unsigned int);
+#define write(fd, data, octets)        async_write(fd, data, octets)
+#endif
+
 /*
  * Packet routines
  *
@@ -64,13 +71,15 @@ icom_freq(                  /* returns 0 (ok), EIO (error) */
        u_char cmd[] = {PAD, PR, PR, 0, TX, V_SFREQ, 0, 0, 0, 0, FI,
            FI};
        int temp;
-       cmd[3] = ident;
+
+       cmd[3] = (char)ident;
        if (ident == IC735)
                temp = 4;
        else
                temp = 5;
        doublefreq(freq * 1e6, &cmd[6], temp);
        temp = write(fd, cmd, temp + 7);
+
        return (0);
 }
 
@@ -86,10 +95,10 @@ doublefreq(                 /* returns void */
        )
 {
        int i;
-       char s1[11];
+       char s1[16];
        char *y;
 
-       sprintf(s1, " %10.0f", freq);
+       snprintf(s1, sizeof(s1), " %10.0f", freq);
        y = s1 + 10;
        i = 0;
        while (*y != ' ') {
@@ -97,13 +106,13 @@ doublefreq(                        /* returns void */
                x[i] = x[i] | ((*y-- & 0x0f) << 4);
                i++;
        }
-       for (; i < len; i++)
+       for ( ; i < len; i++)
                x[i] = 0;
        x[i] = FI;
 }
 
 /*
- * icom_open() - open and initialize serial interface
+ * icom_init() - open and initialize serial interface
  *
  * This routine opens the serial interface for raw transmission; that
  * is, character-at-a-time, no stripping, checking or monkeying with the
@@ -117,14 +126,23 @@ icom_init(
        int trace               /* trace flags */       )
 {
        TTY ttyb;
-       int fd, flags;
+       int fd;
+       int flags;
+       int rc;
+       int saved_errno;
 
        flags = trace;
-       fd = open(device, O_RDWR, 0777);
+       fd = tty_open(device, O_RDWR, 0777);
        if (fd < 0)
-               return (fd);
+               return -1;
 
-       tcgetattr(fd, &ttyb);
+       rc = tcgetattr(fd, &ttyb);
+       if (rc < 0) {
+               saved_errno = errno;
+               close(fd);
+               errno = saved_errno;
+               return -1;
+       }
        ttyb.c_iflag = 0;       /* input modes */
        ttyb.c_oflag = 0;       /* output modes */
        ttyb.c_cflag = IBAUD|CS8|CLOCAL; /* control modes  (no read) */
@@ -133,7 +151,13 @@ icom_init(
        ttyb.c_cc[VTIME] = 5;   /* receive timeout */
        cfsetispeed(&ttyb, (u_int)speed);
        cfsetospeed(&ttyb, (u_int)speed);
-       tcsetattr(fd, TCSANOW, &ttyb);
+       rc = tcsetattr(fd, TCSANOW, &ttyb);
+       if (rc < 0) {
+               saved_errno = errno;
+               close(fd);
+               errno = saved_errno;
+               return -1;
+       }
        return (fd);
 }
 
index e0a2afeb48409e19fb8703c2fa0c1103147fdce6..c6ac8c7ee74bb92fd707b9121faf6d4d39216d05 100644 (file)
@@ -591,7 +591,7 @@ arc_event_handler(
        )
 {
        struct refclockproc *pp = peer->procptr;
-       register struct arcunit *up = (struct arcunit *)pp->unitptr;
+       register struct arcunit *up = pp->unitptr;
        int i;
        char c;
 #ifdef DEBUG
@@ -627,50 +627,49 @@ arc_start(
 {
        register struct arcunit *up;
        struct refclockproc *pp;
+       int temp_fd;
        int fd;
        char device[20];
 #ifdef HAVE_TERMIOS
        struct termios arg;
 #endif
 
-       msyslog(LOG_NOTICE, "ARCRON: %s: opening unit %d", arc_version, unit);
-#ifdef DEBUG
-       if(debug) {
-               printf("arc: %s: attempt to open unit %d.\n", arc_version, unit);
-       }
-#endif
-
-       /* Prevent a ridiculous device number causing overflow of device[]. */
-       if((unit < 0) || (unit > 255)) { return(0); }
+       msyslog(LOG_NOTICE, "MSF_ARCRON %s: opening unit %d",
+               arc_version, unit);
+       DPRINTF(1, ("arc: %s: attempt to open unit %d.\n", arc_version,
+               unit));
 
        /*
         * Open serial port. Use CLK line discipline, if available.
         */
        snprintf(device, sizeof(device), DEVICE, unit);
-       if (!(fd = refclock_open(device, SPEED, LDISC_CLK)))
-               return(0);
-#ifdef DEBUG
-       if(debug) { printf("arc: unit %d using open().\n", unit); }
-#endif
+       temp_fd = refclock_open(device, SPEED, LDISC_CLK);
+       if (temp_fd <= 0)
+               return 0;
+       DPRINTF(1, ("arc: unit %d using tty_open().\n", unit));
        fd = tty_open(device, OPEN_FLAGS, 0777);
-       if(fd < 0) {
-#ifdef DEBUG
-               if(debug) { printf("arc: failed [tty_open()] to open %s.\n", device); }
-#endif
-               return(0);
+       if (fd < 0) {
+               msyslog(LOG_ERR, "MSF_ARCRON(%d): failed second open(%s, 0777): %m.\n",
+                       unit, device);
+               close(temp_fd);
+               return 0;
        }
+       close(temp_fd);
+       temp_fd = -1;
 
 #ifndef SYS_WINNT
        fcntl(fd, F_SETFL, 0); /* clear the descriptor flags */
 #endif
-#ifdef DEBUG
-       if(debug)
-       { printf("arc: opened RS232 port with file descriptor %d.\n", fd); }
-#endif
+       DPRINTF(1, ("arc: opened RS232 port with file descriptor %d.\n", fd));
 
 #ifdef HAVE_TERMIOS
 
-       tcgetattr(fd, &arg);
+       if (tcgetattr(fd, &arg) < 0) {
+               msyslog(LOG_ERR, "MSF_ARCRON(%d): tcgetattr(%s): %m.\n",
+                       unit, device);
+               close(fd);
+               return 0;
+       }
 
        arg.c_iflag = IGNBRK | ISTRIP;
        arg.c_oflag = 0;
@@ -679,20 +678,24 @@ arc_start(
        arg.c_cc[VMIN] = 1;
        arg.c_cc[VTIME] = 0;
 
-       tcsetattr(fd, TCSANOW, &arg);
+       if (tcsetattr(fd, TCSANOW, &arg) < 0) {
+               msyslog(LOG_ERR, "MSF_ARCRON(%d): tcsetattr(%s): %m.\n",
+                       unit, device);
+               close(fd);
+               return 0;
+       }
 
 #else
 
-       msyslog(LOG_ERR, "ARCRON: termios not supported in this driver");
+       msyslog(LOG_ERR, "ARCRON: termios required by this driver");
        (void)close(fd);
 
        return 0;
 
 #endif
 
-       up = emalloc(sizeof(*up));
        /* Set structure to all zeros... */
-       memset(up, 0, sizeof(*up));
+       up = emalloc_zero(sizeof(*up));
        pp = peer->procptr;
        pp->io.clock_recv = arc_receive;
        pp->io.srcclock = (caddr_t)peer;
@@ -704,7 +707,7 @@ arc_start(
                free(up); 
                return(0); 
        }
-       pp->unitptr = (caddr_t)up;
+       pp->unitptr = up;
 
        /*
         * Initialize miscellaneous variables
@@ -775,7 +778,7 @@ arc_shutdown(
        peer->action = dummy_event_handler;
 
        pp = peer->procptr;
-       up = (struct arcunit *)pp->unitptr;
+       up = pp->unitptr;
        if (-1 != pp->io.fd)
                io_closeclock(&pp->io);
        if (NULL != up)
@@ -877,7 +880,7 @@ arc_receive(
         */
        peer = (struct peer *)rbufp->recv_srcclock;
        pp = peer->procptr;
-       up = (struct arcunit *)pp->unitptr;
+       up = pp->unitptr;
 
 
        /*
@@ -1454,7 +1457,7 @@ request_time(
        )
 {
        struct refclockproc *pp = peer->procptr;
-       register struct arcunit *up = (struct arcunit *)pp->unitptr;
+       register struct arcunit *up = pp->unitptr;
 #ifdef DEBUG
        if(debug) { printf("arc: unit %d: requesting time.\n", unit); }
 #endif
@@ -1485,7 +1488,7 @@ arc_poll(
        int resync_needed;              /* Should we start a resync? */
 
        pp = peer->procptr;
-       up = (struct arcunit *)pp->unitptr;
+       up = pp->unitptr;
 #if 0
        pp->lencode = 0;
        memset(pp->a_lastcode, 0, sizeof(pp->a_lastcode));
index 1ec269ef0ac4b67cb9190cc0ff9e450e9827bfd4..bffaf09a02c1f4956dca93eb73ebd5cd5e94ef44 100644 (file)
@@ -481,7 +481,7 @@ openhost(
        hints.ai_family = ai_fam_templ;
        hints.ai_protocol = IPPROTO_UDP;
        hints.ai_socktype = SOCK_DGRAM;
-       hints.ai_flags = AI_NUMERICHOST;
+       hints.ai_flags = Z_AI_NUMERICHOST;
 
        a_info = getaddrinfo(hname, service, &hints, &ai);
        if (a_info == EAI_NONAME
@@ -1475,34 +1475,42 @@ getnetnum(
        int af
        )
 {
-       int sockaddr_len;
        struct addrinfo hints, *ai = NULL;
 
-       sockaddr_len = SIZEOF_SOCKADDR(af);
-       memset((char *)&hints, 0, sizeof(struct addrinfo));
+       ZERO(hints);
        hints.ai_flags = AI_CANONNAME;
 #ifdef AI_ADDRCONFIG
        hints.ai_flags |= AI_ADDRCONFIG;
 #endif
        
-       /* decodenetnum only works with addresses */
+       /*
+        * decodenetnum only works with addresses, but handles syntax
+        * that getaddrinfo doesn't:  [2001::1]:1234
+        */
        if (decodenetnum(hname, num)) {
-               if (fullhost != 0) {
-                       getnameinfo(&num->sa, sockaddr_len, 
-                                   fullhost, sizeof(fullhost), NULL, 0, 
-                                   NI_NUMERICHOST); 
-               }
+               if (fullhost != NULL)
+                       getnameinfo(&num->sa, SOCKLEN(num), fullhost,
+                                   LENHOSTNAME, NULL, 0, 0);
                return 1;
        } else if (getaddrinfo(hname, "ntp", &hints, &ai) == 0) {
-               memmove((char *)num, ai->ai_addr, ai->ai_addrlen);
-               if (fullhost != 0)
-                       (void) strcpy(fullhost, ai->ai_canonname);
+               NTP_INSIST(sizeof(*num) >= ai->ai_addrlen);
+               memcpy(num, ai->ai_addr, ai->ai_addrlen);
+               if (fullhost != NULL) {
+                       if (ai->ai_canonname != NULL) {
+                               strncpy(fullhost, ai->ai_canonname,
+                                       LENHOSTNAME);
+                               fullhost[LENHOSTNAME - 1] = '\0';
+                       } else {
+                               getnameinfo(&num->sa, SOCKLEN(num),
+                                           fullhost, LENHOSTNAME, NULL,
+                                           0, 0);
+                       }
+               }
                return 1;
-       } else {
-               (void) fprintf(stderr, "***Can't find host %s\n", hname);
-               return 0;
        }
-       /*NOTREACHED*/
+       fprintf(stderr, "***Can't find host %s\n", hname);
+
+       return 0;
 }
 
 /*
index c8d26a5d4ddb3ff7e8a86d4ce901f004e286336d..9ba3925dae1af7cf734f77889092a8b4c9a472cf 100644 (file)
@@ -661,7 +661,7 @@ openhost(
        hints.ai_family = ai_fam_templ;
        hints.ai_protocol = IPPROTO_UDP;
        hints.ai_socktype = SOCK_DGRAM;
-       hints.ai_flags = AI_NUMERICHOST;
+       hints.ai_flags = Z_AI_NUMERICHOST;
 
        a_info = getaddrinfo(hname, service, &hints, &ai);
        if (a_info == EAI_NONAME
@@ -1832,34 +1832,42 @@ getnetnum(
        int af
        )
 {
-       int sockaddr_len;
        struct addrinfo hints, *ai = NULL;
 
-       sockaddr_len = SIZEOF_SOCKADDR(af);
-       memset(&hints, 0, sizeof(hints));
+       ZERO(hints);
        hints.ai_flags = AI_CANONNAME;
 #ifdef AI_ADDRCONFIG
        hints.ai_flags |= AI_ADDRCONFIG;
 #endif
        
-       /* decodenetnum works with addresses only */
+       /*
+        * decodenetnum only works with addresses, but handles syntax
+        * that getaddrinfo doesn't:  [2001::1]:1234
+        */
        if (decodenetnum(hname, num)) {
-               if (fullhost != 0) {
-                       getnameinfo((struct sockaddr *)num, sockaddr_len,
-                                       fullhost, sizeof(fullhost), NULL, 0,
-                                       NI_NUMERICHOST);
-               }
+               if (fullhost != NULL)
+                       getnameinfo(&num->sa, SOCKLEN(num), fullhost,
+                                   LENHOSTNAME, NULL, 0, 0);
                return 1;
        } else if (getaddrinfo(hname, "ntp", &hints, &ai) == 0) {
-               memmove((char *)num, ai->ai_addr, ai->ai_addrlen);
-               if (ai->ai_canonname != 0)
-                   (void) strcpy(fullhost, ai->ai_canonname);
+               NTP_INSIST(sizeof(*num) >= ai->ai_addrlen);
+               memcpy(num, ai->ai_addr, ai->ai_addrlen);
+               if (fullhost != NULL) {
+                       if (ai->ai_canonname != NULL) {
+                               strncpy(fullhost, ai->ai_canonname,
+                                       LENHOSTNAME);
+                               fullhost[LENHOSTNAME - 1] = '\0';
+                       } else {
+                               getnameinfo(&num->sa, SOCKLEN(num),
+                                           fullhost, LENHOSTNAME, NULL,
+                                           0, 0);
+                       }
+               }
                return 1;
-       } else {
-               (void) fprintf(stderr, "***Can't find host %s\n", hname);
-               return 0;
        }
-       /*NOTREACHED*/
+       fprintf(stderr, "***Can't find host %s\n", hname);
+
+       return 0;
 }
 
 /*