From: Dave Hart Date: Fri, 29 May 2009 04:29:18 +0000 (+0000) Subject: [Bug 1200] Enable IPv6 in Windows port X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=242aa745eeff44221cabde8b78c89b2900e678a6;p=thirdparty%2Fntp.git [Bug 1200] Enable IPv6 in Windows port bk: 4a1f649eLs2kHr7eu3Hey_bkYqsMWQ --- diff --git a/ChangeLog b/ChangeLog index d9818af098..6693922aa7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ +* [Bug 1200] Enable IPv6 in Windows port (4.2.5p179) 2009/05/23 Released by Harlan Stenn * [Bug 1041] xmt -> aorg timestamp cleanup from Dave Mills, reported by Dave Hart. diff --git a/include/isc/interfaceiter.h b/include/isc/interfaceiter.h index f2d11ba8a4..3d5eef6e56 100644 --- a/include/isc/interfaceiter.h +++ b/include/isc/interfaceiter.h @@ -59,14 +59,12 @@ struct isc_interface { isc_netaddr_t dstaddress; /* Destination address (point-to-point only). */ isc_uint32_t flags; /* Flags; see below. */ - unsigned int ifindex; /* Interface Index */ - unsigned int scopeid; /* Scope id for Multicasting */ }; /* Interface flags. */ #define INTERFACE_F_UP 0x00000001U /* Interface is up */ -#define INTERFACE_F_POINTTOPOINT 0x00000002U /*this is point-to-point interface*/ +#define INTERFACE_F_POINTTOPOINT 0x00000002U /* this is point-to-point interface*/ #define INTERFACE_F_LOOPBACK 0x00000004U /* this is loopback interface */ #define INTERFACE_F_BROADCAST 0x00000008U /* Broadcast is supported */ #define INTERFACE_F_MULTICAST 0x00000010U /* multicast is supported */ diff --git a/include/ntp.h b/include/ntp.h index 333a1d2163..fb509b4ec8 100644 --- a/include/ntp.h +++ b/include/ntp.h @@ -180,23 +180,22 @@ struct interface { struct sockaddr_storage bcast; /* broadcast address */ struct sockaddr_storage mask; /* interface mask */ char name[32]; /* name of interface */ - short family; /* Address family */ + u_short family; /* Address family */ + u_short phase; /* phase in update cycle */ int flags; /* interface flags */ int last_ttl; /* last TTL specified */ u_int32 addr_refid; /* IPv4 addr or IPv6 hash */ int num_mcast; /* No. of IP addresses in multicast socket */ - u_long starttime; /* current_time as of creation of interface structure */ + u_long starttime; /* current_time as of creation of interface structure */ volatile long received; /* number of incoming packets */ long sent; /* number of outgoing packets */ long notsent; /* number of send failures */ u_int scopeid; /* Scope used for Multicasting */ - u_int ifindex; /* interface index */ - u_int ifnum; /* sequential interface instance count */ - u_char phase; /* phase in update cycle */ + u_int ifnum; /* sequential interface instance count */ isc_boolean_t ignore_packets; /* Specify whether the packet should be ignored */ - ISC_LIST(struct peer) peers; /* list of peers for the interface */ - u_int peercnt; /* number of peers referencinf this interface - informational only */ - ISC_LINK(struct interface) link; /* interface list */ + ISC_LIST(struct peer) peers; /* list of peers for the interface */ + u_int peercnt; /* number of peers referencinf this interface - informational only */ + ISC_LINK(struct interface) link;/* interface list */ }; /* diff --git a/include/recvbuff.h b/include/recvbuff.h index 590bba7762..fb07e39909 100644 --- a/include/recvbuff.h +++ b/include/recvbuff.h @@ -60,12 +60,11 @@ struct recvbuf { #define recv_srcadr X_from_where.X_recv_srcadr #define recv_srcclock X_from_where.X_recv_srcclock #define recv_peer X_from_where.X_recv_peer -#if defined HAVE_IO_COMPLETION_PORT - WSABUF wsabuff; -#else +#ifndef HAVE_IO_COMPLETION_PORT struct sockaddr_storage srcadr; /* where packet came from */ +#else + int recv_srcadr_len; /* filled in on completion */ #endif - int src_addr_len; /* source address length */ struct interface *dstadr; /* interface datagram arrived thru */ SOCKET fd; /* fd on which it was received */ int msg_flags; /* Flags received about the packet */ @@ -76,9 +75,9 @@ struct recvbuf { struct pkt X_recv_pkt; u_char X_recv_buffer[RX_BUFF_SIZE]; } recv_space; - int used; #define recv_pkt recv_space.X_recv_pkt #define recv_buffer recv_space.X_recv_buffer + int used; /* reference count */ }; extern void init_recvbuff (int); diff --git a/libntp/recvbuff.c b/libntp/recvbuff.c index a12d647162..71581b5e01 100644 --- a/libntp/recvbuff.c +++ b/libntp/recvbuff.c @@ -69,11 +69,6 @@ static void initialise_buffer(recvbuf_t *buff) { memset((char *) buff, 0, sizeof(recvbuf_t)); - -#if defined SYS_WINNT - buff->wsabuff.len = RX_BUFF_SIZE; - buff->wsabuff.buf = (char *) buff->recv_buffer; -#endif } static void diff --git a/ntpd/ntp_io.c b/ntpd/ntp_io.c index 08c912b164..0cd03b9f0a 100644 --- a/ntpd/ntp_io.c +++ b/ntpd/ntp_io.c @@ -107,17 +107,6 @@ ISC_LIST(limit_address_t) limit_address_list; #if defined(SYS_WINNT) #include #include -/* - * Define this macro to control the behavior of connection - * resets on UDP sockets. See Microsoft KnowledgeBase Article Q263823 - * for details. - * NOTE: This requires that Windows 2000 systems install Service Pack 2 - * or later. - */ -#ifndef SIO_UDP_CONNRESET -#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12) -#endif - /* * Windows C runtime ioctl() can't deal properly with sockets, * map to ioctlsocket for this source file. @@ -530,7 +519,6 @@ init_io(void) netsyslog(LOG_ERR, "No useable winsock.dll: %m"); exit(1); } - init_transmitbuff(); #endif /* SYS_WINNT */ /* @@ -628,7 +616,6 @@ interface_dump(struct interface *itf) printf("received = %ld\n", itf->received); printf("sent = %ld\n", itf->sent); printf("notsent = %ld\n", itf->notsent); - printf("ifindex = %u\n", itf->ifindex); printf("scopeid = %u\n", itf->scopeid); printf("peercnt = %u\n", itf->peercnt); printf("phase = %u\n", itf->phase); @@ -640,16 +627,14 @@ interface_dump(struct interface *itf) static void print_interface(struct interface *iface, char *pfx, char *sfx) { - printf("%sinterface #%d: fd=%d, bfd=%d, name=%s, flags=0x%x, scope=%d, ifindex=%d", + printf("%sinterface #%d: fd=%d, bfd=%d, name=%s, flags=0x%x, scope=%d", pfx, iface->ifnum, iface->fd, iface->bfd, iface->name, iface->flags, - iface->scopeid, - iface->ifindex); - /* Leave these as three printf calls (stoa() static buffer). */ + iface->scopeid); printf(", sin=%s", stoa((&iface->sin))); if (iface->flags & INT_BROADCAST) @@ -993,7 +978,7 @@ create_wildcards(u_short port) { #endif if(okipv4 == ISC_TRUE) { - struct interface *interface = new_interface(NULL); + struct interface *interface = new_interface(NULL); interface->family = AF_INET; interface->sin.ss_family = AF_INET; @@ -1035,7 +1020,7 @@ create_wildcards(u_short port) { * create pseudo-interface with wildcard IPv6 address */ if (isc_net_probeipv6() == ISC_R_SUCCESS) { - struct interface *interface = new_interface(NULL); + struct interface *interface = new_interface(NULL); interface->family = AF_INET6; interface->sin.ss_family = AF_INET6; @@ -1171,8 +1156,6 @@ convert_isc_if(isc_interface_t *isc_if, struct interface *itf, u_short port) { &(isc_if->netmask.type.in6), sizeof(struct in6_addr)); ((struct sockaddr_in6 *)&itf->mask)->sin6_port = port; - /* Copy the interface index */ - itf->ifindex = isc_if->ifindex; } #endif /* INCLUDE_IPV6_SUPPORT */ diff --git a/ntpd/ntp_request.c b/ntpd/ntp_request.c index a287363d5c..168b01863b 100644 --- a/ntpd/ntp_request.c +++ b/ntpd/ntp_request.c @@ -2876,7 +2876,8 @@ fill_info_if_stats(void *data, interface_info_t *interface_info) ifs->sent = htonl(interface->sent); ifs->notsent = htonl(interface->notsent); ifs->scopeid = htonl(interface->scopeid); - ifs->ifindex = htonl(interface->ifindex); + /* ifindex was always zero, now no longer in struct interface */ + ifs->ifindex = 0; ifs->ifnum = htonl(interface->ifnum); ifs->uptime = htonl(current_time - interface->starttime); ifs->ignore_packets = interface->ignore_packets; diff --git a/ntpdc/ntpdc.c b/ntpdc/ntpdc.c index 6e9950f57b..68c344ae62 100644 --- a/ntpdc/ntpdc.c +++ b/ntpdc/ntpdc.c @@ -159,10 +159,18 @@ static struct xcmd builtins[] = { /* * Default values we use. */ +#ifndef SYS_WINNT +#define DEFHOST "localhost" /* default host name */ +#else +/* Using "localhost" with AF 0 gives a garbage response, + * force the IPv4 localhost numeric address works. + * Using 'ntpdc ::' also does not work on Windows yet. + */ +#define DEFHOST "127.0.0.1" +#endif #define DEFTIMEOUT (5) /* 5 second time out */ #define DEFSTIMEOUT (2) /* 2 second time out after first */ #define DEFDELAY 0x51EB852 /* 20 milliseconds, l_fp fraction */ -#define DEFHOST "localhost" /* default host name */ #define LENHOSTNAME 256 /* host name is 256 characters long */ #define MAXCMDS 100 /* maximum commands on cmd line */ #define MAXHOSTS 200 /* maximum hosts on cmd line */ diff --git a/ntpdc/ntpdc_ops.c b/ntpdc/ntpdc_ops.c index 723749abce..7bec0842a8 100644 --- a/ntpdc/ntpdc_ops.c +++ b/ntpdc/ntpdc_ops.c @@ -3080,11 +3080,11 @@ again: (u_long)ntohl(ik->errcnt)); } -#define IF_LIST_FMT "%2d %c %48s %c %c %12.12s %03x %3d %2d %5d %5d %5d %2d %2d %3d %7d\n" -#define IF_LIST_FMT_STR "%2s %c %48s %c %c %12.12s %3s %3s %2s %5s %5s %5s %2s %2s %3s %7s\n" +#define IF_LIST_FMT "%2d %c %48s %c %c %12.12s %03x %3d %2d %5d %5d %5d %2d %3d %7d\n" +#define IF_LIST_FMT_STR "%2s %c %48s %c %c %12.12s %3s %3s %2s %5s %5s %5s %2s %3s %7s\n" #define IF_LIST_AFMT_STR " %48s %c\n" -#define IF_LIST_LABELS "#", 'A', "Address/Mask/Broadcast", 'T', 'E', "IF name", "Flg", "TL", "#M", "recv", "sent", "drop", "S", "IX", "PC", "uptime" -#define IF_LIST_LINE "=====================================================================================================================\n" +#define IF_LIST_LABELS "#", 'A', "Address/Mask/Broadcast", 'T', 'E', "IF name", "Flg", "TL", "#M", "recv", "sent", "drop", "S", "PC", "uptime" +#define IF_LIST_LINE "==================================================================================================================\n" static void iflist( @@ -3134,7 +3134,6 @@ iflist( ntohl(ifs->sent), ntohl(ifs->notsent), ntohl(ifs->scopeid), - ntohl(ifs->ifindex), ntohl(ifs->peercnt), ntohl(ifs->uptime)); diff --git a/ntpq/ntpq.c b/ntpq/ntpq.c index 428f4dc11a..2c3b2ae8b7 100644 --- a/ntpq/ntpq.c +++ b/ntpq/ntpq.c @@ -366,10 +366,18 @@ struct xcmd builtins[] = { /* * Default values we use. */ +#ifndef SYS_WINNT +#define DEFHOST "localhost" /* default host name */ +#else +/* Using "localhost" with AF 0 gives a garbage response, + * force the IPv4 localhost numeric address works. + * Using 'ntpq ::' also does not work on Windows yet. + */ +#define DEFHOST "127.0.0.1" +#endif #define DEFTIMEOUT (5) /* 5 second time out */ #define DEFSTIMEOUT (2) /* 2 second time out after first */ #define DEFDELAY 0x51EB852 /* 20 milliseconds, l_fp fraction */ -#define DEFHOST "localhost" /* default host name */ #define LENHOSTNAME 256 /* host name is 256 characters long */ #define MAXCMDS 100 /* maximum commands on cmd line */ #define MAXHOSTS 200 /* maximum hosts on cmd line */ @@ -529,10 +537,9 @@ ntpqmain( } #endif /* SYS_WINNT */ - /* Check to see if we have IPv6. Otherwise force the -4 flag */ - if (isc_net_probeipv6() != ISC_R_SUCCESS) { + /* Check to see if we have IPv6. Otherwise default to IPv4 */ + if (isc_net_probeipv6() != ISC_R_SUCCESS) ai_fam_default = AF_INET; - } progname = argv[0]; @@ -709,11 +716,13 @@ openhost( #endif a_info = getaddrinfo(hname, service, &hints, &ai); } +#ifdef AI_ADDRCONFIG /* Some older implementations don't like AI_ADDRCONFIG. */ if (a_info == EAI_BADFLAGS) { hints.ai_flags = AI_CANONNAME; a_info = getaddrinfo(hname, service, &hints, &ai); } +#endif if (a_info != 0) { (void) fprintf(stderr, "%s\n", gai_strerror(a_info)); return 0; diff --git a/ports/winnt/include/config.h b/ports/winnt/include/config.h index ce72b5a3ef..6fa18753b0 100644 --- a/ports/winnt/include/config.h +++ b/ports/winnt/include/config.h @@ -1,7 +1,7 @@ /* config.h for Windows NT */ -#ifndef __CONFIG_H -#define __CONFIG_H +#ifndef CONFIG_H +#define CONFIG_H /* * For newer compilers we may we want newer prototypes from Windows @@ -115,24 +115,36 @@ struct timeval { }; /* - * IPv6 requirements + * ntp_rfc2553.h has cruft under #ifdef SYS_WINNT which is + * appropriate for older Microsoft IPv6 definitions, such + * as in_addr6 being the struct type. We can differentiate + * the RFC2553-compliant newer headers because they have + * #define in_addr6 in6_addr + * for backward compatibility. With the newer headers, + * we define ISC_PLATFORM_HAVEIPV6 and disable the cruft. */ -/* - * For VS.NET most of the IPv6 types and structures are defined. - * This should depend on the contrents of the available headers, - * not on the compiler version. - */ -#if defined _MSC_VER && _MSC_VER > 1200 -#define HAVE_STRUCT_SOCKADDR_STORAGE +#ifdef in_addr6 +#define WANT_IPV6 #define ISC_PLATFORM_HAVEIPV6 +#define INCLUDE_IPV6_SUPPORT +#define INCLUDE_IPV6_MULTICAST_SUPPORT +#define ISC_PLATFORM_HAVESCOPEID +#define HAVE_STRUCT_SOCKADDR_STORAGE #define ISC_PLATFORM_HAVEIN6PKTINFO #define NO_OPTION_NAME_WARNINGS -#endif +#endif /* in_addr6 / RFC2553-compliant IPv6 headers */ -#ifndef _W64 +#if !defined( _W64 ) + /* + * if ULONG_PTR needs to be defined then the build environment + * is pure 32 bit Windows. Since ULONG_PTR and DWORD have + * the same size in 32 bit Windows we can safely define + * a replacement. + */ +typedef DWORD ULONG_PTR; /* VC6 doesn't know about socklen_t, except if the SDK is installed */ typedef int socklen_t; -#endif +#endif /* _W64 */ #define ISC_PLATFORM_NEEDIN6ADDRANY #define HAVE_SOCKADDR_IN6 @@ -150,6 +162,19 @@ typedef int socklen_t; #define SO_EXCLUSIVEADDRUSE ((int)(~SO_REUSEADDR)) #endif +/* + * Define this macro to control the behavior of connection + * resets on UDP sockets. See Microsoft KnowledgeBase Article Q263823 + * for details. + * Based on that article, it is surprising that a much newer winsock2.h + * does not define SIO_UDP_CONNRESET (the one that comes with VS 2008). + * NOTE: This requires that Windows 2000 systems install Service Pack 2 + * or later. + */ +#ifndef SIO_UDP_CONNRESET +#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12) +#endif + #if defined _MSC_VER && _MSC_VER < 1400 /* * Use 32-bit time definitions for versions prior to VS 2005 @@ -394,4 +419,4 @@ typedef unsigned long uintptr_t; */ #include -#endif /* __CONFIG_H */ +#endif /* CONFIG_H */ diff --git a/ports/winnt/include/transmitbuff.h b/ports/winnt/include/transmitbuff.h index 84afd72a45..aef37fa32a 100644 --- a/ports/winnt/include/transmitbuff.h +++ b/ports/winnt/include/transmitbuff.h @@ -1,10 +1,7 @@ -#if !defined __transmitbuff_h -#define __transmitbuff_h +#ifndef TRANSMITBUFF_H +#define TRANSMITBUFF_H #include "ntp.h" -#if defined HAVE_IO_COMPLETION_PORT -# include "ntp_iocompletionport.h" -#endif #include /* @@ -17,7 +14,6 @@ typedef struct transmitbuf transmitbuf_t; typedef struct transmitbuf { ISC_LINK(transmitbuf_t) link; - WSABUF wsabuf; time_t ts; /* Time stamp for the request */ /* @@ -46,5 +42,5 @@ extern void free_transmit_buffer (transmitbuf_t *); */ extern transmitbuf_t *get_free_transmit_buffer (void); -#endif /* defined __transmitbuff_h */ +#endif /* TRANSMITBUFF_H */ diff --git a/ports/winnt/include/win32_io.h b/ports/winnt/include/win32_io.h index b1249dd4eb..8c241436f2 100644 --- a/ports/winnt/include/win32_io.h +++ b/ports/winnt/include/win32_io.h @@ -7,7 +7,7 @@ #include -#define NCCS 4 +#define NCCS 18 /* refclock_arc.c uses VTIME (17) */ #define VEOL 3 typedef unsigned char cc_t; typedef unsigned int speed_t; @@ -176,6 +176,8 @@ struct termios #define TCSANOW 0 #define TCSADRAIN 1 #define TCSAFLUSH 2 +#define VMIN 16 +#define VTIME 17 /* modem lines */ #define TIOCM_LE 0x001 diff --git a/ports/winnt/libisc/interfaceiter.c b/ports/winnt/libisc/interfaceiter.c index 212122fb65..048f86bd63 100644 --- a/ports/winnt/libisc/interfaceiter.c +++ b/ports/winnt/libisc/interfaceiter.c @@ -1,26 +1,21 @@ /* + * Copyright (C) 2004, 2007-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * - * Permission to use, copy, modify, and distribute this software for any + * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM - * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL - * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: interfaceiter.c,v 1.7 2001/11/27 01:56:21 gson Exp $ */ - -/* - * Note that this code will need to be revisited to support IPv6 Interfaces. - * For now we just iterate through IPv4 interfaces. - */ +/* $Id: interfaceiter.c,v 1.13.110.2 2009/01/18 23:47:41 tbox Exp $ */ #include #include @@ -39,12 +34,14 @@ #include #include +void InitSockets(void); + /* Common utility functions */ /* * Extract the network address part from a "struct sockaddr". * - * The address family is given explicity + * The address family is given explicitly * instead of using src->sa_family, because the latter does not work * for copying a network mask obtained by SIOCGIFNETMASK (it does * not have a valid address family). @@ -60,11 +57,13 @@ struct isc_interfaceiter { int socket; INTERFACE_INFO IFData; /* Current Interface Info */ int numIF; /* Current Interface count */ - int totalIF; /* Total Number - of Interfaces */ - INTERFACE_INFO *buf; /* Buffer for WSAIoctl data. */ - unsigned int bufsize; /* Bytes allocated. */ - INTERFACE_INFO *pos; /* Current offset in IF List */ + int v4IF; /* Number of IPv4 Interfaces */ + INTERFACE_INFO *buf4; /* Buffer for WSAIoctl data. */ + unsigned int buf4size; /* Bytes allocated. */ + INTERFACE_INFO *pos4; /* Current offset in IF List */ + SOCKET_ADDRESS_LIST *buf6; + unsigned int buf6size; /* Bytes allocated. */ + unsigned int pos6; isc_interface_t current; /* Current interface data. */ isc_result_t result; /* Last result code. */ }; @@ -92,6 +91,7 @@ get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src) { memcpy(&dst->type.in6, &((struct sockaddr_in6 *) src)->sin6_addr, sizeof(struct in6_addr)); + dst->zone = ((struct sockaddr_in6 *) src)->sin6_scope_id; break; default: INSIST(0); @@ -121,7 +121,7 @@ get_broadcastaddr(isc_netaddr_t *bcastaddr, isc_netaddr_t *addr, isc_netaddr_t * isc_result_t isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { - char strbuf[ISC_STRERRORSIZE]; + char strbuf[ISC_STRERRORSIZE]; isc_interfaceiter_t *iter; isc_result_t result; int error; @@ -134,8 +134,18 @@ isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { if (iter == NULL) return (ISC_R_NOMEMORY); + InitSockets(); + iter->mctx = mctx; - iter->buf = NULL; + iter->buf4 = NULL; + iter->buf6 = NULL; + iter->pos4 = NULL; + iter->pos6 = 0; + iter->buf6size = 0; + iter->buf4size = 0; + iter->result = ISC_R_FAILURE; + iter->numIF = 0; + iter->v4IF = 0; /* * Create an unbound datagram socket to do the @@ -143,6 +153,8 @@ isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { */ if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { error = WSAGetLastError(); + if (error == WSAEAFNOSUPPORT) + goto inet6_only; isc__strerror(error, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "making interface scan socket: %s", @@ -155,17 +167,17 @@ isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { * Get the interface configuration, allocating more memory if * necessary. */ - iter->bufsize = IFCONF_SIZE_INITIAL*sizeof(INTERFACE_INFO); + iter->buf4size = IFCONF_SIZE_INITIAL*sizeof(INTERFACE_INFO); for (;;) { - iter->buf = isc_mem_get(mctx, iter->bufsize); - if (iter->buf == NULL) { + iter->buf4 = isc_mem_get(mctx, iter->buf4size); + if (iter->buf4 == NULL) { result = ISC_R_NOMEMORY; goto alloc_failure; } if (WSAIoctl(iter->socket, SIO_GET_INTERFACE_LIST, - 0, 0, iter->buf, iter->bufsize, + 0, 0, iter->buf4, iter->buf4size, &bytesReturned, 0, 0) == SOCKET_ERROR) { error = WSAGetLastError(); @@ -189,19 +201,19 @@ isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { * case and retry. */ if (bytesReturned > 0 && - (bytesReturned < iter->bufsize)) + (bytesReturned < iter->buf4size)) break; } - if (iter->bufsize >= IFCONF_SIZE_MAX*sizeof(INTERFACE_INFO)) { + if (iter->buf4size >= IFCONF_SIZE_MAX*sizeof(INTERFACE_INFO)) { UNEXPECTED_ERROR(__FILE__, __LINE__, "get interface configuration: " "maximum buffer size exceeded"); result = ISC_R_UNEXPECTED; goto ioctl_failure; } - isc_mem_put(mctx, iter->buf, iter->bufsize); + isc_mem_put(mctx, iter->buf4, iter->buf4size); - iter->bufsize += IFCONF_SIZE_INCREMENT * + iter->buf4size += IFCONF_SIZE_INCREMENT * sizeof(INTERFACE_INFO); } @@ -209,23 +221,92 @@ isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { * A newly created iterator has an undefined position * until isc_interfaceiter_first() is called. */ - iter->pos = NULL; - iter->result = ISC_R_FAILURE; - iter->numIF = 0; - iter->totalIF = bytesReturned/sizeof(INTERFACE_INFO); + iter->v4IF = bytesReturned/sizeof(INTERFACE_INFO); + /* We don't need the socket any more, so close it */ + closesocket(iter->socket); + inet6_only: + /* + * Create an unbound datagram socket to do the + * SIO_ADDRESS_LIST_QUERY WSAIoctl on. + */ + if ((iter->socket = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { + error = WSAGetLastError(); + if (error == WSAEAFNOSUPPORT) + goto inet_only; + isc__strerror(error, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "making interface scan socket: %s", + strbuf); + result = ISC_R_UNEXPECTED; + goto ioctl_failure; + } + + /* + * Get the interface configuration, allocating more memory if + * necessary. + */ + iter->buf6size = sizeof(SOCKET_ADDRESS_LIST) + + IFCONF_SIZE_INITIAL*sizeof(SOCKET_ADDRESS); + + for (;;) { + iter->buf6 = isc_mem_get(mctx, iter->buf6size); + if (iter->buf6 == NULL) { + result = ISC_R_NOMEMORY; + goto ioctl_failure; + } + + if (WSAIoctl(iter->socket, SIO_ADDRESS_LIST_QUERY, + 0, 0, iter->buf6, iter->buf6size, + &bytesReturned, 0, 0) == SOCKET_ERROR) + { + error = WSAGetLastError(); + if (error != WSAEFAULT && error != WSAENOBUFS) { + errno = error; + isc__strerror(error, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "sio address list query: %s", + strbuf); + result = ISC_R_UNEXPECTED; + goto ioctl6_failure; + } + /* + * EINVAL. Retry with a bigger buffer. + */ + } else + break; + + if (iter->buf6size >= IFCONF_SIZE_MAX*sizeof(SOCKET_ADDRESS)) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "get interface configuration: " + "maximum buffer size exceeded"); + result = ISC_R_UNEXPECTED; + goto ioctl6_failure; + } + isc_mem_put(mctx, iter->buf6, iter->buf6size); + + iter->buf6size += IFCONF_SIZE_INCREMENT * + sizeof(SOCKET_ADDRESS); + } + + closesocket(iter->socket); + + inet_only: iter->magic = IFITER_MAGIC; *iterp = iter; - /* We don't need the socket any more, so close it */ - closesocket(iter->socket); return (ISC_R_SUCCESS); + ioctl6_failure: + isc_mem_put(mctx, iter->buf6, iter->buf6size); + ioctl_failure: - isc_mem_put(mctx, iter->buf, iter->bufsize); + if (iter->buf4 != NULL) + isc_mem_put(mctx, iter->buf4, iter->buf4size); alloc_failure: - (void) closesocket(iter->socket); + if (iter->socket >= 0) + (void) closesocket(iter->socket); socket_failure: isc_mem_put(mctx, iter, sizeof(*iter)); @@ -241,7 +322,7 @@ isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { */ static isc_result_t -internal_current(isc_interfaceiter_t *iter, int family) { +internal_current(isc_interfaceiter_t *iter) { BOOL ifNamed = FALSE; unsigned long flags; @@ -249,16 +330,11 @@ internal_current(isc_interfaceiter_t *iter, int family) { REQUIRE(iter->numIF >= 0); memset(&iter->current, 0, sizeof(iter->current)); - iter->current.af = family; + iter->current.af = AF_INET; - get_addr(family, &iter->current.address, + get_addr(AF_INET, &iter->current.address, (struct sockaddr *)&(iter->IFData.iiAddress)); - /* XXXPDM This will need to be revisited */ - iter->current.ifindex = 0; /* Set to zero for now */ - iter->current.scopeid = 0; /* Set to zero for now */ - - /* * Get interface flags. */ @@ -269,6 +345,14 @@ internal_current(isc_interfaceiter_t *iter, int family) { if ((flags & IFF_UP) != 0) iter->current.flags |= INTERFACE_F_UP; + if ((flags & IFF_BROADCAST) != 0) { + iter->current.flags |= INTERFACE_F_BROADCAST; + } + + if ((flags & IFF_MULTICAST) != 0) { + iter->current.flags |= INTERFACE_F_MULTICAST; + } + if ((flags & IFF_POINTTOPOINT) != 0) { iter->current.flags |= INTERFACE_F_POINTTOPOINT; sprintf(iter->current.name, "PPP Interface %d", iter->numIF); @@ -282,38 +366,19 @@ internal_current(isc_interfaceiter_t *iter, int family) { ifNamed = TRUE; } - if ((flags & IFF_BROADCAST) != 0) { - iter->current.flags |= INTERFACE_F_BROADCAST; - } - - if ((flags & IFF_MULTICAST) != 0) { - iter->current.flags |= INTERFACE_F_MULTICAST; - } - - /* - * Get the network mask. - */ - switch (family) { - case AF_INET: - get_addr(family, &iter->current.netmask, - (struct sockaddr *)&(iter->IFData.iiNetmask)); - break; - case AF_INET6: - break; - } - /* * If the interface is point-to-point, get the destination address. */ if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) { - get_addr(family, &iter->current.dstaddress, + get_addr(AF_INET, &iter->current.dstaddress, (struct sockaddr *)&(iter->IFData.iiBroadcastAddress)); } + /* * If the interface is broadcast, get the broadcast address. */ if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) { - get_addr(family, &iter->current.broadcast, + get_addr(AF_INET, &iter->current.broadcast, (struct sockaddr *)&(iter->IFData.iiBroadcastAddress)); get_broadcastaddr(&iter->current.broadcast, &iter->current.address, &iter->current.netmask); @@ -321,11 +386,48 @@ internal_current(isc_interfaceiter_t *iter, int family) { if (ifNamed == FALSE) sprintf(iter->current.name, - "IP Interface %d", iter->numIF); + "TCP/IP Interface %d", iter->numIF); + + /* + * Get the network mask. + */ + get_addr(AF_INET, &iter->current.netmask, + (struct sockaddr *)&(iter->IFData.iiNetmask)); return (ISC_R_SUCCESS); } +static isc_result_t +internal_current6(isc_interfaceiter_t *iter) { + BOOL ifNamed = FALSE; + int i; + + REQUIRE(VALID_IFITER(iter)); + REQUIRE(iter->pos6 >= 0); + REQUIRE(iter->buf6 != 0); + + memset(&iter->current, 0, sizeof(iter->current)); + iter->current.af = AF_INET6; + + get_addr(AF_INET6, &iter->current.address, + iter->buf6->Address[iter->pos6].lpSockaddr); + + /* + * Get interface flags. + */ + + iter->current.flags = INTERFACE_F_UP | INTERFACE_F_MULTICAST; + + if (ifNamed == FALSE) + sprintf(iter->current.name, + "TCP/IPv6 Interface %d", iter->pos6 + 1); + + for (i = 0; i< 16; i++) + iter->current.netmask.type.in6.s6_addr[i] = 0xff; + iter->current.netmask.family = AF_INET6; + return (ISC_R_SUCCESS); +} + /* * Step the iterator to the next interface. Unlike * isc_interfaceiter_next(), this may leave the iterator @@ -335,7 +437,7 @@ internal_current(isc_interfaceiter_t *iter, int family) { */ static isc_result_t internal_next(isc_interfaceiter_t *iter) { - if (iter->numIF >= iter->totalIF) + if (iter->numIF >= iter->v4IF) return (ISC_R_NOMORE); /* @@ -344,21 +446,29 @@ internal_next(isc_interfaceiter_t *iter) { * Microsoft's implementation is peculiar for returning * the list in reverse order */ - + if (iter->numIF == 0) - iter->pos = (INTERFACE_INFO *)(iter->buf + (iter->totalIF)); + iter->pos4 = (INTERFACE_INFO *)(iter->buf4 + (iter->v4IF)); - iter->pos--; - if (&(iter->pos) < &(iter->buf)) + iter->pos4--; + if (&(iter->pos4) < &(iter->buf4)) return (ISC_R_NOMORE); memset(&(iter->IFData), 0, sizeof(INTERFACE_INFO)); - memcpy(&(iter->IFData), iter->pos, sizeof(INTERFACE_INFO)); + memcpy(&(iter->IFData), iter->pos4, sizeof(INTERFACE_INFO)); iter->numIF++; return (ISC_R_SUCCESS); } +static isc_result_t +internal_next6(isc_interfaceiter_t *iter) { + if (iter->pos6 == 0) + return (ISC_R_NOMORE); + iter->pos6--; + return (ISC_R_SUCCESS); +} + isc_result_t isc_interfaceiter_current(isc_interfaceiter_t *iter, isc_interface_t *ifdata) { @@ -369,21 +479,13 @@ isc_interfaceiter_current(isc_interfaceiter_t *iter, isc_result_t isc_interfaceiter_first(isc_interfaceiter_t *iter) { - isc_result_t result; REQUIRE(VALID_IFITER(iter)); - iter->numIF = 0; - for (;;) { - result = internal_next(iter); - if (result != ISC_R_SUCCESS) - break; - result = internal_current(iter, AF_INET); - if (result != ISC_R_IGNORE) - break; - } - iter->result = result; - return (result); + if (iter->buf6 != NULL) + iter->pos6 = iter->buf6->iAddressCount; + iter->result = ISC_R_SUCCESS; + return (isc_interfaceiter_next(iter)); } isc_result_t @@ -395,9 +497,16 @@ isc_interfaceiter_next(isc_interfaceiter_t *iter) { for (;;) { result = internal_next(iter); - if (result != ISC_R_SUCCESS) + if (result == ISC_R_NOMORE) { + result = internal_next6(iter); + if (result != ISC_R_SUCCESS) + break; + result = internal_current6(iter); + if (result != ISC_R_IGNORE) + break; + } else if (result != ISC_R_SUCCESS) break; - result = internal_current(iter,AF_INET); + result = internal_current(iter); if (result != ISC_R_IGNORE) break; } @@ -412,10 +521,12 @@ isc_interfaceiter_destroy(isc_interfaceiter_t **iterp) { iter = *iterp; REQUIRE(VALID_IFITER(iter)); - isc_mem_put(iter->mctx, iter->buf, iter->bufsize); + if (iter->buf4 != NULL) + isc_mem_put(iter->mctx, iter->buf4, iter->buf4size); + if (iter->buf6 != NULL) + isc_mem_put(iter->mctx, iter->buf6, iter->buf6size); iter->magic = 0; isc_mem_put(iter->mctx, iter, sizeof(*iter)); *iterp = NULL; } - diff --git a/ports/winnt/libisc/net.c b/ports/winnt/libisc/net.c index 60375b5300..db2b83ac9f 100644 --- a/ports/winnt/libisc/net.c +++ b/ports/winnt/libisc/net.c @@ -69,6 +69,7 @@ try_proto(int domain) { #ifdef ISC_PLATFORM_HAVEIPV6 #ifdef WANT_IPV6 #ifdef ISC_PLATFORM_HAVEIN6PKTINFO +#ifndef SYS_WINNT /* code below fails, needs bind() before getsockname() */ if (domain == PF_INET6) { struct sockaddr_in6 sin6; unsigned int len; @@ -90,6 +91,7 @@ try_proto(int domain) { } #endif #endif +#endif #endif closesocket(s); @@ -154,18 +156,14 @@ try_ipv6only(void) { if (s == INVALID_SOCKET) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, - "socket() %s: %s", - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, - "failed"), + "socket() failed: %s", strbuf); ipv6only_result = ISC_R_UNEXPECTED; return; } on = 1; - if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) { + if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)) < 0) { ipv6only_result = ISC_R_NOTFOUND; goto close; } @@ -177,18 +175,14 @@ try_ipv6only(void) { if (s == INVALID_SOCKET) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, - "socket() %s: %s", - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, - "failed"), + "socket() failed: %s", strbuf); ipv6only_result = ISC_R_UNEXPECTED; return; } on = 1; - if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) { + if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)) < 0) { ipv6only_result = ISC_R_NOTFOUND; goto close; } @@ -227,11 +221,7 @@ try_ipv6pktinfo(void) { if (s == -1) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, - "socket() %s: %s", - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, - "failed"), + "socket() failed: %s", strbuf); ipv6pktinfo_result = ISC_R_UNEXPECTED; return; @@ -243,7 +233,7 @@ try_ipv6pktinfo(void) { optname = IPV6_PKTINFO; #endif on = 1; - if (setsockopt(s, IPPROTO_IPV6, optname, &on, sizeof(on)) < 0) { + if (setsockopt(s, IPPROTO_IPV6, optname, (char *)&on, sizeof(on)) < 0) { ipv6pktinfo_result = ISC_R_NOTFOUND; goto close; } diff --git a/ports/winnt/libntp/interfaceiter.c b/ports/winnt/libntp/interfaceiter.c index cfea7ec8d3..a69b702694 100644 --- a/ports/winnt/libntp/interfaceiter.c +++ b/ports/winnt/libntp/interfaceiter.c @@ -1,21 +1,21 @@ /* + * Copyright (C) 2004, 2007-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * - * Permission to use, copy, modify, and distribute this software for any + * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM - * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL - * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: interfaceiter.c,v 1.7 2001/11/27 01:56:21 gson Exp $ */ +/* $Id: interfaceiter.c,v 1.13.110.2 2009/01/18 23:47:41 tbox Exp $ */ /* * Note that this code will need to be revisited to support IPv6 Interfaces. @@ -39,12 +39,14 @@ #include #include +void InitSockets(void); + /* Common utility functions */ /* * Extract the network address part from a "struct sockaddr". * - * The address family is given explicity + * The address family is given explicitly * instead of using src->sa_family, because the latter does not work * for copying a network mask obtained by SIOCGIFNETMASK (it does * not have a valid address family). @@ -60,11 +62,13 @@ struct isc_interfaceiter { int socket; INTERFACE_INFO IFData; /* Current Interface Info */ int numIF; /* Current Interface count */ - int totalIF; /* Total Number - of Interfaces */ - INTERFACE_INFO *buf; /* Buffer for WSAIoctl data. */ - unsigned int bufsize; /* Bytes allocated. */ - INTERFACE_INFO *pos; /* Current offset in IF List */ + int v4IF; /* Number of IPv4 Interfaces */ + INTERFACE_INFO *buf4; /* Buffer for WSAIoctl data. */ + unsigned int buf4size; /* Bytes allocated. */ + INTERFACE_INFO *pos4; /* Current offset in IF List */ + SOCKET_ADDRESS_LIST *buf6; + unsigned int buf6size; /* Bytes allocated. */ + unsigned int pos6; isc_interface_t current; /* Current interface data. */ isc_result_t result; /* Last result code. */ }; @@ -92,6 +96,7 @@ get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src) { memcpy(&dst->type.in6, &((struct sockaddr_in6 *) src)->sin6_addr, sizeof(struct in6_addr)); + dst->zone = ((struct sockaddr_in6 *) src)->sin6_scope_id; break; default: INSIST(0); @@ -101,7 +106,7 @@ get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src) { isc_result_t isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { - char strbuf[ISC_STRERRORSIZE]; + char strbuf[ISC_STRERRORSIZE]; isc_interfaceiter_t *iter; isc_result_t result; int error; @@ -115,8 +120,18 @@ isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { if (iter == NULL) return (ISC_R_NOMEMORY); + InitSockets(); + iter->mctx = mctx; - iter->buf = NULL; + iter->buf4 = NULL; + iter->buf6 = NULL; + iter->pos4 = NULL; + iter->pos6 = 0; + iter->buf6size = 0; + iter->buf4size = 0; + iter->result = ISC_R_FAILURE; + iter->numIF = 0; + iter->v4IF = 0; /* * Create an unbound datagram socket to do the @@ -124,6 +139,8 @@ isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { */ if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { error = WSAGetLastError(); + if (error == WSAEAFNOSUPPORT) + goto inet6_only; isc__strerror(error, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "making interface scan socket: %s", @@ -136,17 +153,17 @@ isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { * Get the interface configuration, allocating more memory if * necessary. */ - iter->bufsize = IFCONF_SIZE_INITIAL*sizeof(INTERFACE_INFO); + iter->buf4size = IFCONF_SIZE_INITIAL*sizeof(INTERFACE_INFO); for (;;) { - iter->buf = isc_mem_get(mctx, iter->bufsize); - if (iter->buf == NULL) { + iter->buf4 = isc_mem_get(mctx, iter->buf4size); + if (iter->buf4 == NULL) { result = ISC_R_NOMEMORY; goto alloc_failure; } if (WSAIoctl(iter->socket, SIO_GET_INTERFACE_LIST, - 0, 0, iter->buf, iter->bufsize, + 0, 0, iter->buf4, iter->buf4size, &bytesReturned, 0, 0) == SOCKET_ERROR) { error = WSAGetLastError(); @@ -170,19 +187,19 @@ isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { * case and retry. */ if (bytesReturned > 0 && - (bytesReturned < iter->bufsize)) + (bytesReturned < iter->buf4size)) break; } - if (iter->bufsize >= IFCONF_SIZE_MAX*sizeof(INTERFACE_INFO)) { + if (iter->buf4size >= IFCONF_SIZE_MAX*sizeof(INTERFACE_INFO)) { UNEXPECTED_ERROR(__FILE__, __LINE__, "get interface configuration: " "maximum buffer size exceeded"); result = ISC_R_UNEXPECTED; goto ioctl_failure; } - isc_mem_put(mctx, iter->buf, iter->bufsize); + isc_mem_put(mctx, iter->buf4, iter->buf4size); - iter->bufsize += IFCONF_SIZE_INCREMENT * + iter->buf4size += IFCONF_SIZE_INCREMENT * sizeof(INTERFACE_INFO); } @@ -190,23 +207,92 @@ isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { * A newly created iterator has an undefined position * until isc_interfaceiter_first() is called. */ - iter->pos = NULL; - iter->result = ISC_R_FAILURE; - iter->numIF = 0; - iter->totalIF = bytesReturned/sizeof(INTERFACE_INFO); + iter->v4IF = bytesReturned/sizeof(INTERFACE_INFO); + + /* We don't need the socket any more, so close it */ + closesocket(iter->socket); + + inet6_only: + /* + * Create an unbound datagram socket to do the + * SIO_ADDRESS_LIST_QUERY WSAIoctl on. + */ + if ((iter->socket = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { + error = WSAGetLastError(); + if (error == WSAEAFNOSUPPORT) + goto inet_only; + isc__strerror(error, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "making interface scan socket: %s", + strbuf); + result = ISC_R_UNEXPECTED; + goto ioctl_failure; + } + + /* + * Get the interface configuration, allocating more memory if + * necessary. + */ + iter->buf6size = sizeof(SOCKET_ADDRESS_LIST) + + IFCONF_SIZE_INITIAL*sizeof(SOCKET_ADDRESS); + for (;;) { + iter->buf6 = isc_mem_get(mctx, iter->buf6size); + if (iter->buf6 == NULL) { + result = ISC_R_NOMEMORY; + goto ioctl_failure; + } + if (WSAIoctl(iter->socket, SIO_ADDRESS_LIST_QUERY, + 0, 0, iter->buf6, iter->buf6size, + &bytesReturned, 0, 0) == SOCKET_ERROR) + { + error = WSAGetLastError(); + if (error != WSAEFAULT && error != WSAENOBUFS) { + errno = error; + isc__strerror(error, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "sio address list query: %s", + strbuf); + result = ISC_R_UNEXPECTED; + goto ioctl6_failure; + } + /* + * EINVAL. Retry with a bigger buffer. + */ + } else + break; + + if (iter->buf6size >= IFCONF_SIZE_MAX*sizeof(SOCKET_ADDRESS)) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "get interface configuration: " + "maximum buffer size exceeded"); + result = ISC_R_UNEXPECTED; + goto ioctl6_failure; + } + isc_mem_put(mctx, iter->buf6, iter->buf6size); + + iter->buf6size += IFCONF_SIZE_INCREMENT * + sizeof(SOCKET_ADDRESS); + } + + closesocket(iter->socket); + + inet_only: iter->magic = IFITER_MAGIC; *iterp = iter; - /* We don't need the socket any more, so close it */ - closesocket(iter->socket); return (ISC_R_SUCCESS); + ioctl6_failure: + isc_mem_put(mctx, iter->buf6, iter->buf6size); + ioctl_failure: - isc_mem_put(mctx, iter->buf, iter->bufsize); + if (iter->buf4 != NULL) + isc_mem_put(mctx, iter->buf4, iter->buf4size); alloc_failure: - (void) closesocket(iter->socket); + if (iter->socket >= 0) + (void) closesocket(iter->socket); socket_failure: isc_mem_put(mctx, iter, sizeof(*iter)); @@ -222,7 +308,7 @@ isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { */ static isc_result_t -internal_current(isc_interfaceiter_t *iter, int family) { +internal_current(isc_interfaceiter_t *iter) { BOOL ifNamed = FALSE; unsigned long flags; @@ -230,9 +316,9 @@ internal_current(isc_interfaceiter_t *iter, int family) { REQUIRE(iter->numIF >= 0); memset(&iter->current, 0, sizeof(iter->current)); - iter->current.af = family; + iter->current.af = AF_INET; - get_addr(family, &iter->current.address, + get_addr(AF_INET, &iter->current.address, (struct sockaddr *)&(iter->IFData.iiAddress)); /* @@ -262,7 +348,7 @@ internal_current(isc_interfaceiter_t *iter, int family) { * If the interface is point-to-point, get the destination address. */ if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) { - get_addr(family, &iter->current.dstaddress, + get_addr(AF_INET, &iter->current.dstaddress, (struct sockaddr *)&(iter->IFData.iiBroadcastAddress)); } @@ -273,18 +359,43 @@ internal_current(isc_interfaceiter_t *iter, int family) { /* * Get the network mask. */ - switch (family) { - case AF_INET: - get_addr(family, &iter->current.netmask, - (struct sockaddr *)&(iter->IFData.iiNetmask)); - break; - case AF_INET6: - break; - } + get_addr(AF_INET, &iter->current.netmask, + (struct sockaddr *)&(iter->IFData.iiNetmask)); return (ISC_R_SUCCESS); } +static isc_result_t +internal_current6(isc_interfaceiter_t *iter) { + BOOL ifNamed = FALSE; + int i; + + REQUIRE(VALID_IFITER(iter)); + REQUIRE(iter->pos6 >= 0); + REQUIRE(iter->buf6 != 0); + + memset(&iter->current, 0, sizeof(iter->current)); + iter->current.af = AF_INET6; + + get_addr(AF_INET6, &iter->current.address, + iter->buf6->Address[iter->pos6].lpSockaddr); + + /* + * Get interface flags. + */ + + iter->current.flags = INTERFACE_F_UP; + + if (ifNamed == FALSE) + sprintf(iter->current.name, + "TCP/IPv6 Interface %d", iter->pos6 + 1); + + for (i = 0; i< 16; i++) + iter->current.netmask.type.in6.s6_addr[i] = 0xff; + iter->current.netmask.family = AF_INET6; + return (ISC_R_SUCCESS); +} + /* * Step the iterator to the next interface. Unlike * isc_interfaceiter_next(), this may leave the iterator @@ -294,7 +405,7 @@ internal_current(isc_interfaceiter_t *iter, int family) { */ static isc_result_t internal_next(isc_interfaceiter_t *iter) { - if (iter->numIF >= iter->totalIF) + if (iter->numIF >= iter->v4IF) return (ISC_R_NOMORE); /* @@ -303,21 +414,29 @@ internal_next(isc_interfaceiter_t *iter) { * Microsoft's implementation is peculiar for returning * the list in reverse order */ - + if (iter->numIF == 0) - iter->pos = (INTERFACE_INFO *)(iter->buf + (iter->totalIF)); + iter->pos4 = (INTERFACE_INFO *)(iter->buf4 + (iter->v4IF)); - iter->pos--; - if (&(iter->pos) < &(iter->buf)) + iter->pos4--; + if (&(iter->pos4) < &(iter->buf4)) return (ISC_R_NOMORE); memset(&(iter->IFData), 0, sizeof(INTERFACE_INFO)); - memcpy(&(iter->IFData), iter->pos, sizeof(INTERFACE_INFO)); + memcpy(&(iter->IFData), iter->pos4, sizeof(INTERFACE_INFO)); iter->numIF++; return (ISC_R_SUCCESS); } +static isc_result_t +internal_next6(isc_interfaceiter_t *iter) { + if (iter->pos6 == 0) + return (ISC_R_NOMORE); + iter->pos6--; + return (ISC_R_SUCCESS); +} + isc_result_t isc_interfaceiter_current(isc_interfaceiter_t *iter, isc_interface_t *ifdata) { @@ -328,21 +447,13 @@ isc_interfaceiter_current(isc_interfaceiter_t *iter, isc_result_t isc_interfaceiter_first(isc_interfaceiter_t *iter) { - isc_result_t result; REQUIRE(VALID_IFITER(iter)); - iter->numIF = 0; - for (;;) { - result = internal_next(iter); - if (result != ISC_R_SUCCESS) - break; - result = internal_current(iter, AF_INET); - if (result != ISC_R_IGNORE) - break; - } - iter->result = result; - return (result); + if (iter->buf6 != NULL) + iter->pos6 = iter->buf6->iAddressCount; + iter->result = ISC_R_SUCCESS; + return (isc_interfaceiter_next(iter)); } isc_result_t @@ -354,9 +465,16 @@ isc_interfaceiter_next(isc_interfaceiter_t *iter) { for (;;) { result = internal_next(iter); - if (result != ISC_R_SUCCESS) + if (result == ISC_R_NOMORE) { + result = internal_next6(iter); + if (result != ISC_R_SUCCESS) + break; + result = internal_current6(iter); + if (result != ISC_R_IGNORE) + break; + } else if (result != ISC_R_SUCCESS) break; - result = internal_current(iter,AF_INET); + result = internal_current(iter); if (result != ISC_R_IGNORE) break; } @@ -371,10 +489,12 @@ isc_interfaceiter_destroy(isc_interfaceiter_t **iterp) { iter = *iterp; REQUIRE(VALID_IFITER(iter)); - isc_mem_put(iter->mctx, iter->buf, iter->bufsize); + if (iter->buf4 != NULL) + isc_mem_put(iter->mctx, iter->buf4, iter->buf4size); + if (iter->buf6 != NULL) + isc_mem_put(iter->mctx, iter->buf6, iter->buf6size); iter->magic = 0; isc_mem_put(iter->mctx, iter, sizeof(*iter)); *iterp = NULL; } - diff --git a/ports/winnt/libntp/libntp.vcproj b/ports/winnt/libntp/libntp.vcproj index 97bfbe52a6..219983e794 100644 --- a/ports/winnt/libntp/libntp.vcproj +++ b/ports/winnt/libntp/libntp.vcproj @@ -2024,6 +2024,10 @@ RelativePath="..\..\..\include\ntp_malloc.h" > + + diff --git a/ports/winnt/libntp/transmitbuff.c b/ports/winnt/libntp/transmitbuff.c index 5d2679cc93..8fcd302cb0 100644 --- a/ports/winnt/libntp/transmitbuff.c +++ b/ports/winnt/libntp/transmitbuff.c @@ -1,3 +1,10 @@ +/* + * DEAD CODE ALERT -- for whatever reason all this wonderful stuff is + * unused. The initialization was the only code + * exercised as of May 2009 when that was nipped. + */ + + #ifdef HAVE_CONFIG_H # include #endif @@ -35,13 +42,10 @@ static CRITICAL_SECTION TransmitLock; # define LOCK(lock) EnterCriticalSection(lock) # define UNLOCK(lock) LeaveCriticalSection(lock) -static void +static inline void initialise_buffer(transmitbuf *buff) { - memset((char *) buff, 0, sizeof(transmitbuf)); - - buff->wsabuf.len = 0; - buff->wsabuf.buf = (char *) &buff->pkt; + memset(buff, 0, sizeof(*buff)); } static void @@ -57,7 +61,7 @@ create_buffers(int nbufs) transmitbuf_t *buf; int i; - buf = (transmitbuf_t *) emalloc(nbufs*sizeof(transmitbuf_t)); + buf = emalloc(nbufs * sizeof(*buf)); for (i = 0; i < nbufs; i++) { initialise_buffer(buf); diff --git a/ports/winnt/ntpd/nt_clockstuff.c b/ports/winnt/ntpd/nt_clockstuff.c index 920acc2020..66710de2de 100644 --- a/ports/winnt/ntpd/nt_clockstuff.c +++ b/ports/winnt/ntpd/nt_clockstuff.c @@ -503,9 +503,24 @@ init_winnt_time(void) } /* Initialize random file before OpenSSL checks */ - if(!init_randfile()) + if (!init_randfile()) msyslog(LOG_ERR, "Unable to initialize .rnd file\n"); +#pragma warning(push) +#pragma warning(disable: 4127) /* conditional expression is constant */ + +#ifdef DEBUG + if (SIZEOF_TIME_T != sizeof(time_t) + || SIZEOF_INT != sizeof(int) + || SIZEOF_SIGNED_CHAR != sizeof(char)) { + + msyslog(LOG_ERR, "config.h SIZEOF_* macros wrong, fatal"); + exit(1); + } +#endif + +#pragma warning(pop) + /* * Get privileges needed for fiddling with the clock */ diff --git a/ports/winnt/ntpd/ntp_iocompletionport.c b/ports/winnt/ntpd/ntp_iocompletionport.c index 3822e344b0..5be1071694 100644 --- a/ports/winnt/ntpd/ntp_iocompletionport.c +++ b/ports/winnt/ntpd/ntp_iocompletionport.c @@ -7,8 +7,9 @@ #include #include #include +#include + #include "ntp_stdlib.h" -#include "syslog.h" #include "ntp_machine.h" #include "ntp_fp.h" #include "ntp.h" @@ -17,6 +18,7 @@ #include "ntp_iocompletionport.h" #include "transmitbuff.h" #include "ntp_request.h" +#include "ntp_assert.h" #include "clockstuff.h" #include "ntp_io.h" #include "clockstuff.h" @@ -46,16 +48,6 @@ typedef struct IoCompletionInfo { #define trans_buf buff_space.tbuf -#if !defined( _W64 ) - /* - * if ULONG_PTR needs to be defined then the build environment - * is pure 32 bit Windows. Since ULONG_PTR and DWORD have - * the same size in 32 bit Windows we can safely define - * a replacement. - */ - typedef DWORD ULONG_PTR; -#endif - /* * local function definitions */ @@ -118,9 +110,7 @@ FreeHeap(IoCompletionInfo *lpo, char *fromfunc) transmitbuf_t * get_trans_buf() { - transmitbuf_t *tb = (transmitbuf_t *) emalloc(sizeof(transmitbuf_t)); - tb->wsabuf.len = 0; - tb->wsabuf.buf = (char *) &tb->pkt; + transmitbuf_t *tb = emalloc(sizeof(*tb)); return (tb); } @@ -259,7 +249,7 @@ iocompletionthread(void *NotUsed) /* Create/initialise the I/O creation port */ -extern void +void init_io_completion_port( void ) @@ -279,6 +269,10 @@ init_io_completion_port( } #endif +#if 0 /* transmitbuff.c unused, no need to initialize it */ + init_transmitbuff(); +#endif + /* Create the event used to signal an IO event */ WaitableIoEventHandle = CreateEvent(NULL, FALSE, FALSE, WAITABLEIOEVENTHANDLE); @@ -326,7 +320,7 @@ init_io_completion_port( } -extern void +void uninit_io_completion_port( void ) @@ -339,6 +333,18 @@ uninit_io_completion_port( } +/* + * libisc/interfaceiter.c calls InitSockets(), to minimize deltas + * from the upstream source, we provide a no-op implementation. + */ +void +InitSockets( + void + ) +{ +} + + static int QueueSerialWait(struct refclockio *rio, recvbuf_t *buff, IoCompletionInfo *lpo, BOOL clear_timestamp) { lpo->request_type = SERIAL_WAIT; @@ -436,10 +442,10 @@ OnSerialWaitComplete(ULONG_PTR i, IoCompletionInfo *lpo, DWORD Bytes, int errsta rc = ReadFile( (HANDLE)buff->fd, - buff->wsabuff.buf, - buff->wsabuff.len, - &buff->wsabuff.len, - (LPOVERLAPPED) lpo); + buff->recv_buffer, + sizeof(buff->recv_buffer), + NULL, + (LPOVERLAPPED)lpo); if (!rc && ERROR_IO_PENDING != GetLastError()) { msyslog(LOG_ERR, "Can't read from Refclock: %m"); @@ -502,14 +508,17 @@ io_completion_port_add_clock_io( IoCompletionInfo *lpo; recvbuf_t *buff; - if (NULL == CreateIoCompletionPort((HANDLE)_get_osfhandle(rio->fd), hIoCompletionPort, (ULONG_PTR) rio, 0)) { + if (NULL == CreateIoCompletionPort( + (HANDLE)_get_osfhandle(rio->fd), + hIoCompletionPort, + (ULONG_PTR)rio, + 0)) { msyslog(LOG_ERR, "Can't add COM port to i/o completion port: %m"); return 1; } - lpo = (IoCompletionInfo *) GetHeapAlloc("io_completion_port_add_clock_io"); - if (lpo == NULL) - { + lpo = GetHeapAlloc("io_completion_port_add_clock_io"); + if (NULL == lpo) { msyslog(LOG_ERR, "Can't allocate heap for completion port: %m"); return 1; } @@ -523,41 +532,49 @@ io_completion_port_add_clock_io( * Queue a receiver on a socket. Returns 0 if no buffer can be queued * * Note: As per the winsock documentation, we use WSARecvFrom. Using - * ReadFile() is less efficient. + * ReadFile() is less efficient. */ -static unsigned long QueueSocketRecv(SOCKET s, recvbuf_t *buff, IoCompletionInfo *lpo) { - - int AddrLen; +static unsigned long +QueueSocketRecv( + SOCKET s, + recvbuf_t *buff, + IoCompletionInfo *lpo + ) +{ + WSABUF wsabuf; + DWORD Flags; + DWORD Result; lpo->request_type = SOCK_RECV; lpo->recv_buf = buff; if (buff != NULL) { - DWORD BytesReceived = 0; - DWORD Flags = 0; + Flags = 0; buff->fd = s; - AddrLen = sizeof(struct sockaddr_in); - buff->src_addr_len = sizeof(struct sockaddr); - - if (SOCKET_ERROR == WSARecvFrom(buff->fd, &buff->wsabuff, 1, - &BytesReceived, &Flags, - (struct sockaddr *) &buff->recv_srcadr, (LPINT) &buff->src_addr_len, - (LPOVERLAPPED) lpo, NULL)) { - DWORD Result = WSAGetLastError(); + buff->recv_srcadr_len = sizeof(buff->recv_srcadr); + wsabuf.buf = (char *)buff->recv_buffer; + wsabuf.len = sizeof(buff->recv_buffer); + + if (SOCKET_ERROR == WSARecvFrom(buff->fd, &wsabuf, 1, + NULL, &Flags, + (struct sockaddr *)&buff->recv_srcadr, + &buff->recv_srcadr_len, + (LPOVERLAPPED)lpo, NULL)) { + Result = GetLastError(); switch (Result) { case NO_ERROR : case WSA_IO_PENDING : break ; case WSAENOTSOCK : - netsyslog(LOG_ERR, "Can't read from socket, because it isn't a socket: %m"); + msyslog(LOG_ERR, "Can't read from non-socket fd %d: %m", (int)buff->fd); /* return the buffer */ freerecvbuf(buff); return 0; break; case WSAEFAULT : - netsyslog(LOG_ERR, "The buffers parameter is incorrect: %m"); + msyslog(LOG_ERR, "The buffers parameter is incorrect: %m"); /* return the buffer */ freerecvbuf(buff); return 0; @@ -586,22 +603,13 @@ OnSocketRecv(ULONG_PTR i, IoCompletionInfo *lpo, DWORD Bytes, int errstatus) get_systime(&arrival_time); - /* Convert the overlapped pointer back to a recvbuf pointer. - */ - - /* - * Check returned structures - */ - if (lpo == NULL) - return (1); /* Nothing to do */ + NTP_REQUIRE(NULL != lpo); + NTP_REQUIRE(NULL != lpo->recv_buf); - buff = lpo->recv_buf; /* - * Make sure we have a buffer + * Convert the overlapped pointer back to a recvbuf pointer. */ - if (buff == NULL) { - return (1); - } + buff = lpo->recv_buf; /* * If the socket is closed we get an Operation Aborted error @@ -614,34 +622,31 @@ OnSocketRecv(ULONG_PTR i, IoCompletionInfo *lpo, DWORD Bytes, int errstatus) return (1); } - /* * Get a new recv buffer for the replacement socket receive */ newbuff = get_free_recv_buffer_alloc(); QueueSocketRecv(inter->fd, newbuff, lpo); -#ifdef DEBUG - if(debug > 3 && get_packet_mode(buff) == MODE_BROADCAST) - printf("****Accepting Broadcast packet on fd %d from %s\n", buff->fd, stoa(&buff->recv_srcadr)); -#endif - ignore_this = inter->ignore_packets; -#ifdef DEBUG - if (debug > 3) - printf(" Packet mode is %d\n", get_packet_mode(buff)); -#endif + DPRINTF(4, ("%sfd %d %s recv packet mode is %d\n", + (MODE_BROADCAST == get_packet_mode(buff)) + ? " **** Broadcast " + : "", + (int)buff->fd, stoa(&buff->recv_srcadr), + get_packet_mode(buff))); + /* * If we keep it add some info to the structure */ - if (Bytes > 0 && ignore_this == ISC_FALSE) { + if (Bytes && !inter->ignore_packets) { memcpy(&buff->recv_time, &arrival_time, sizeof buff->recv_time); buff->recv_length = (int) Bytes; buff->receiver = receive; buff->dstadr = inter; -#ifdef DEBUG - if (debug > 1) - printf("Received %d bytes of fd %d in buffer %x from %s\n", Bytes, buff->fd, buff, stoa(&buff->recv_srcadr)); -#endif + + DPRINTF(2, ("Received %d bytes fd %d in buffer %p from %s\n", + Bytes, (int)buff->fd, buff, stoa(&buff->recv_srcadr))); + packets_received++; inter->received++; add_full_recv_buffer(buff); @@ -667,8 +672,8 @@ io_completion_port_add_socket(SOCKET fd, struct interface *inter) int n; if (fd != INVALID_SOCKET) { - if (NULL == CreateIoCompletionPort((HANDLE) fd, hIoCompletionPort, - (DWORD) inter, 0)) { + if (NULL == CreateIoCompletionPort((HANDLE)fd, + hIoCompletionPort, (ULONG_PTR)inter, 0)) { msyslog(LOG_ERR, "Can't add socket to i/o completion port: %m"); return 1; } @@ -745,15 +750,15 @@ io_completion_port_sendto( struct interface *inter, struct pkt *pkt, int len, - struct sockaddr_storage* dest) + struct sockaddr_storage *dest) { - transmitbuf_t *buff = NULL; + WSABUF wsabuf; + transmitbuf_t *buff; DWORD Result = ERROR_SUCCESS; int errval; int AddrLen; IoCompletionInfo *lpo; - DWORD BytesSent = 0; - DWORD Flags = 0; + DWORD Flags; lpo = (IoCompletionInfo *) GetHeapAlloc("io_completion_port_sendto"); @@ -770,16 +775,18 @@ io_completion_port_sendto( } - memcpy(&buff->pkt, pkt, len); - buff->wsabuf.buf = buff->pkt; - buff->wsabuf.len = len; + wsabuf.buf = buff->pkt; + wsabuf.len = len; - AddrLen = sizeof(struct sockaddr_in); + AddrLen = SOCKLEN(dest); lpo->request_type = SOCK_SEND; lpo->trans_buf = buff; + Flags = 0; - Result = WSASendTo(inter->fd, &buff->wsabuf, 1, &BytesSent, Flags, (struct sockaddr *) dest, AddrLen, (LPOVERLAPPED) lpo, NULL); + Result = WSASendTo(inter->fd, &wsabuf, 1, NULL, Flags, + (struct sockaddr *)dest, AddrLen, + (LPOVERLAPPED)lpo, NULL); if(Result == SOCKET_ERROR) { diff --git a/ports/winnt/ntpd/ntpd.vcproj b/ports/winnt/ntpd/ntpd.vcproj index 671c00c197..5644da73ea 100644 --- a/ports/winnt/ntpd/ntpd.vcproj +++ b/ports/winnt/ntpd/ntpd.vcproj @@ -578,6 +578,10 @@ RelativePath="..\..\..\ntpd\ntp_scanner.c" > + + @@ -851,6 +855,10 @@ RelativePath="..\..\..\include\ntp_malloc.h" > + + @@ -1134,7 +1142,6 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +