From: Dave Hart Date: Wed, 27 Jul 2011 21:41:02 +0000 (+0000) Subject: [Bug 1978] Ignore tentative IP addresses on Linux. X-Git-Tag: NTP_4_2_6P4_RC2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=de52f2bad407c11e00d8f89c983ef96f7a572bd7;p=thirdparty%2Fntp.git [Bug 1978] Ignore tentative IP addresses on Linux. Backport several fixes for Coverity warnings from ntp-dev. bk: 4e3085eekVdLxvStZswxGqUcK3dIyQ --- diff --git a/ChangeLog b/ChangeLog index ea64e6ff6..b6fb0fb4c 100644 --- 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 diff --git a/configure.ac b/configure.ac index c215bccfe..99b009183 100644 --- a/configure.ac +++ b/configure.ac @@ -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 + #endif + ]) +esac + AC_CHECK_HEADERS([net/if.h], [], [], [#ifdef HAVE_SYS_SOCKET_H #include diff --git a/include/ntp_rfc2553.h b/include/ntp_rfc2553.h index 4ed1b657c..8e824f4a2 100644 --- a/include/ntp_rfc2553.h +++ b/include/ntp_rfc2553.h @@ -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 diff --git a/lib/isc/unix/interfaceiter.c b/lib/isc/unix/interfaceiter.c index 5f5ee9811..996669fc9 100644 --- a/lib/isc/unix/interfaceiter.c +++ b/lib/isc/unix/interfaceiter.c @@ -51,7 +51,7 @@ #endif #include -#ifdef __linux +#ifdef HAVE_LINUX_IF_ADDR_H # include #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; diff --git a/libntp/audio.c b/libntp/audio.c index a685fe952..d9af6b51f 100644 --- a/libntp/audio.c +++ b/libntp/audio.c @@ -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); diff --git a/libntp/decodenetnum.c b/libntp/decodenetnum.c index 1ce98ae89..f265daebf 100644 --- a/libntp/decodenetnum.c +++ b/libntp/decodenetnum.c @@ -11,9 +11,15 @@ #include #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; } diff --git a/libntp/icom.c b/libntp/icom.c index 557fc06ae..c981d8548 100644 --- a/libntp/icom.c +++ b/libntp/icom.c @@ -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 #include "icom.h" #include #include @@ -14,6 +15,12 @@ #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); } diff --git a/ntpd/refclock_arc.c b/ntpd/refclock_arc.c index e0a2afeb4..c6ac8c7ee 100644 --- a/ntpd/refclock_arc.c +++ b/ntpd/refclock_arc.c @@ -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)); diff --git a/ntpdc/ntpdc.c b/ntpdc/ntpdc.c index 1ec269ef0..bffaf09a0 100644 --- a/ntpdc/ntpdc.c +++ b/ntpdc/ntpdc.c @@ -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; } /* diff --git a/ntpq/ntpq.c b/ntpq/ntpq.c index c8d26a5d4..9ba3925da 100644 --- a/ntpq/ntpq.c +++ b/ntpq/ntpq.c @@ -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; } /*