summaryrefslogtreecommitdiffstats
path: root/contrib/ntp/ntpd/ntp_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ntp/ntpd/ntp_io.c')
-rw-r--r--contrib/ntp/ntpd/ntp_io.c1933
1 files changed, 1214 insertions, 719 deletions
diff --git a/contrib/ntp/ntpd/ntp_io.c b/contrib/ntp/ntpd/ntp_io.c
index ef0c146..9f2acea 100644
--- a/contrib/ntp/ntpd/ntp_io.c
+++ b/contrib/ntp/ntpd/ntp_io.c
@@ -14,6 +14,17 @@
#include "ntp_refclock.h"
#include "ntp_if.h"
#include "ntp_stdlib.h"
+#include "ntp.h"
+
+/* Don't include ISC's version of IPv6 variables and structures */
+#define ISC_IPV6_H 1
+#include <isc/interfaceiter.h>
+#include <isc/list.h>
+#include <isc/result.h>
+
+#ifdef SIM
+#include "ntpsim.h"
+#endif
#include <stdio.h>
#include <signal.h>
@@ -43,46 +54,20 @@
extern int listen_to_virtual_ips;
-#if _BSDI_VERSION >= 199510
-# include <ifaddrs.h>
+#if defined(SYS_WINNT)
+#include <transmitbuff.h>
+#include <isc/win32os.h>
+/*
+ * 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
-#if defined(VMS) /* most likely UCX-specific */
-
-#include <UCX$INETDEF.H>
-
-/* "un*x"-compatible names for some items in UCX$INETDEF.H */
-#define ifreq IFREQDEF
-#define ifr_name IFR$T_NAME
-#define ifr_addr IFR$R_DUMMY.IFR$T_ADDR
-#define ifr_broadaddr IFR$R_DUMMY.IFR$T_BROADADDR
-#define ifr_flags IFR$R_DUMMY.IFR$R_DUMMY_1_OVRL.IFR$W_FLAGS
-#define IFF_UP IFR$M_IFF_UP
-#define IFF_BROADCAST IFR$M_IFF_BROADCAST
-#define IFF_LOOPBACK IFR$M_IFF_LOOPBACK
-
-#endif /* VMS */
-
-
-#if defined(VMS) || defined(SYS_WINNT)
-/* structure used in SIOCGIFCONF request (after [KSR] OSF/1) */
-struct ifconf {
- int ifc_len; /* size of buffer */
- union {
- caddr_t ifcu_buf;
- struct ifreq *ifcu_req;
- } ifc_ifcu;
-};
-#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */
-#define ifc_req ifc_ifcu.ifcu_req /* array of structures returned */
-
-#endif /* VMS */
-
-#if defined(USE_TTY_SIGPOLL) || defined(USE_UDP_SIGPOLL)
-# if defined(SYS_AIX) && defined(_IO) /* XXX Identify AIX some other way */
-# undef _IO
-# endif
-# include <stropts.h>
#endif
/*
@@ -118,10 +103,15 @@ u_long io_timereset; /* time counters were reset */
/*
* Interface stuff
*/
-struct interface *any_interface; /* default interface */
-struct interface *loopback_interface; /* loopback interface */
-struct interface inter_list[MAXINTERFACES];
-int ninterfaces;
+struct interface *any_interface; /* default ipv4 interface */
+struct interface *any6_interface; /* default ipv6 interface */
+struct interface *loopback_interface; /* loopback ipv4 interface */
+struct interface *loopback6_interface; /* loopback ipv6 interface */
+struct interface inter_list[MAXINTERFACES]; /* Interface list */
+int ninterfaces; /* Total number of interfaces */
+int nwilds; /* Total number of wildcard intefaces */
+int wildipv4 = -1; /* Index into inter_list for IPv4 wildcard */
+int wildipv6 = -1; /* Index into inter_list for IPv6 wildcard */
#ifdef REFCLOCK
/*
@@ -131,18 +121,94 @@ int ninterfaces;
static struct refclockio *refio;
#endif /* REFCLOCK */
+
+/*
+ * Define what the possible "soft" errors can be. These are non-fatal returns
+ * of various network related functions, like recv() and so on.
+ *
+ * For some reason, BSDI (and perhaps others) will sometimes return <0
+ * from recv() but will have errno==0. This is broken, but we have to
+ * work around it here.
+ */
+#define SOFT_ERROR(e) ((e) == EAGAIN || \
+ (e) == EWOULDBLOCK || \
+ (e) == EINTR || \
+ (e) == 0)
+
/*
* File descriptor masks etc. for call to select
+ * Not needed for I/O Completion Ports
*/
fd_set activefds;
int maxactivefd;
-static int create_sockets P((u_int));
-static int open_socket P((struct sockaddr_in *, int, int));
-static void close_socket P((int));
-static void close_file P((int));
+static int create_sockets P((u_short));
+static SOCKET open_socket P((struct sockaddr_storage *, int, int));
+static void close_socket P((SOCKET));
+#ifdef REFCLOCK
+static void close_file P((SOCKET));
+#endif
static char * fdbits P((int, fd_set *));
+static void set_reuseaddr P((int));
+
+typedef struct vsock vsock_t;
+
+struct vsock {
+ SOCKET fd;
+ ISC_LINK(vsock_t) link;
+};
+
+ISC_LIST(vsock_t) sockets_list;
+
+typedef struct remaddr remaddr_t;
+
+struct remaddr {
+ struct sockaddr_storage addr;
+ int if_index;
+ ISC_LINK(remaddr_t) link;
+};
+
+ISC_LIST(remaddr_t) remoteaddr_list;
+
+void add_socket_to_list P((SOCKET));
+void delete_socket_from_list P((SOCKET));
+void add_addr_to_list P((struct sockaddr_storage *, int));
+void delete_addr_from_list P((struct sockaddr_storage *));
+int find_addr_in_list P((struct sockaddr_storage *));
+int create_wildcards P((u_short));
+isc_boolean_t address_okay P((isc_interface_t *));
+void convert_isc_if P((isc_interface_t *, struct interface *, u_short));
+#ifdef SYS_WINNT
+/*
+ * Windows 2000 systems incorrectly cause UDP sockets using WASRecvFrom
+ * to not work correctly, returning a WSACONNRESET error when a WSASendTo
+ * fails with an "ICMP port unreachable" response and preventing the
+ * socket from using the WSARecvFrom in subsequent operations.
+ * The function below fixes this, but requires that Windows 2000
+ * Service Pack 2 or later be installed on the system. NT 4.0
+ * systems are not affected by this and work correctly.
+ * See Microsoft Knowledge Base Article Q263823 for details of this.
+ */
+isc_result_t
+connection_reset_fix(SOCKET fd) {
+ DWORD dwBytesReturned = 0;
+ BOOL bNewBehavior = FALSE;
+ DWORD status;
+
+ if(isc_win32os_majorversion() < 5)
+ return (ISC_R_SUCCESS); /* NT 4.0 has no problem */
+
+ /* disable bad behavior using IOCTL: SIO_UDP_CONNRESET */
+ status = WSAIoctl(fd, SIO_UDP_CONNRESET, &bNewBehavior,
+ sizeof(bNewBehavior), NULL, 0,
+ &dwBytesReturned, NULL, NULL);
+ if (status != SOCKET_ERROR)
+ return (ISC_R_SUCCESS);
+ else
+ return (ISC_R_UNEXPECTED);
+}
+#endif
/*
* init_io - initialize I/O data structures and call socket creation routine
*/
@@ -150,8 +216,6 @@ void
init_io(void)
{
#ifdef SYS_WINNT
- WORD wVersionRequested;
- WSADATA wsaData;
init_transmitbuff();
#endif /* SYS_WINNT */
@@ -165,7 +229,8 @@ init_io(void)
packets_sent = packets_notsent = 0;
handler_calls = handler_pkts = 0;
io_timereset = 0;
- loopback_interface = 0;
+ loopback_interface = NULL;
+ loopback6_interface = NULL;
#ifdef REFCLOCK
refio = 0;
@@ -176,14 +241,17 @@ init_io(void)
#endif
#ifdef SYS_WINNT
- wVersionRequested = MAKEWORD(1,1);
- if (WSAStartup(wVersionRequested, &wsaData))
+ if (!Win32InitSockets())
{
- msyslog(LOG_ERR, "No useable winsock.dll: %m");
+ netsyslog(LOG_ERR, "No useable winsock.dll: %m");
exit(1);
}
#endif /* SYS_WINNT */
+ ISC_LIST_INIT(sockets_list);
+
+ ISC_LIST_INIT(remoteaddr_list);
+
/*
* Create the sockets
*/
@@ -197,456 +265,274 @@ init_io(void)
#endif
}
-/*
- * create_sockets - create a socket for each interface plus a default
- * socket for when we don't know where to send
- */
-static int
-create_sockets(
- u_int port
- )
-{
-#if _BSDI_VERSION >= 199510
- int i, j;
- struct ifaddrs *ifaddrs, *ifap;
- struct sockaddr_in resmask;
-#if _BSDI_VERSION < 199701
- struct ifaddrs *lp;
- int num_if;
-#endif
-#else /* _BSDI_VERSION >= 199510 */
-# ifdef STREAMS_TLI
- struct strioctl ioc;
-# endif /* STREAMS_TLI */
- char buf[MAXINTERFACES*sizeof(struct ifreq)];
- struct ifconf ifc;
- struct ifreq ifreq, *ifr;
- int n, i, j, vs, size = 0;
- struct sockaddr_in resmask;
-#endif /* _BSDI_VERSION >= 199510 */
+int
+create_wildcards(u_short port) {
-#ifdef DEBUG
- if (debug)
- printf("create_sockets(%d)\n", ntohs( (u_short) port));
-#endif
+ int idx = 0;
+ /*
+ * create pseudo-interface with wildcard IPv4 address
+ */
+ inter_list[idx].sin.ss_family = AF_INET;
+ ((struct sockaddr_in*)&inter_list[idx].sin)->sin_addr.s_addr = htonl(INADDR_ANY);
+ ((struct sockaddr_in*)&inter_list[idx].sin)->sin_port = port;
+ (void) strncpy(inter_list[idx].name, "wildcard", sizeof(inter_list[idx].name));
+ inter_list[idx].mask.ss_family = AF_INET;
+ ((struct sockaddr_in*)&inter_list[idx].mask)->sin_addr.s_addr = htonl(~(u_int32)0);
+ inter_list[idx].bfd = INVALID_SOCKET;
+ inter_list[idx].num_mcast = 0;
+ inter_list[idx].received = 0;
+ inter_list[idx].sent = 0;
+ inter_list[idx].notsent = 0;
+ inter_list[idx].flags = INT_BROADCAST;
+ any_interface = &inter_list[idx];
+#if defined(MCAST)
+ /*
+ * enable possible multicast reception on the broadcast socket
+ */
+ inter_list[idx].bcast.ss_family = AF_INET;
+ ((struct sockaddr_in*)&inter_list[idx].bcast)->sin_port = port;
+ ((struct sockaddr_in*)&inter_list[idx].bcast)->sin_addr.s_addr = htonl(INADDR_ANY);
+#endif /* MCAST */
+ wildipv4 = idx;
+ idx++;
+#ifdef HAVE_IPV6
/*
- * create pseudo-interface with wildcard address
+ * create pseudo-interface with wildcard IPv6 address
*/
- inter_list[0].sin.sin_family = AF_INET;
- inter_list[0].sin.sin_port = port;
- inter_list[0].sin.sin_addr.s_addr = htonl(INADDR_ANY);
- (void) strncpy(inter_list[0].name, "wildcard",
- sizeof(inter_list[0].name));
- inter_list[0].mask.sin_addr.s_addr = htonl(~ (u_int32)0);
- inter_list[0].received = 0;
- inter_list[0].sent = 0;
- inter_list[0].notsent = 0;
- inter_list[0].flags = INT_BROADCAST;
- any_interface = &inter_list[0];
-
-#if _BSDI_VERSION >= 199510
-#if _BSDI_VERSION >= 199701
- if (getifaddrs(&ifaddrs) < 0)
- {
- msyslog(LOG_ERR, "getifaddrs: %m");
- exit(1);
+ if (isc_net_probeipv6() == ISC_R_SUCCESS) {
+ inter_list[idx].sin.ss_family = AF_INET6;
+ ((struct sockaddr_in6*)&inter_list[idx].sin)->sin6_addr = in6addr_any;
+ ((struct sockaddr_in6*)&inter_list[idx].sin)->sin6_port = port;
+ (void) strncpy(inter_list[idx].name, "wildcard", sizeof(inter_list[idx].name));
+ inter_list[idx].mask.ss_family = AF_INET6;
+ memset(&((struct sockaddr_in6*)&inter_list[idx].mask)->sin6_addr.s6_addr, 0xff, sizeof(struct in6_addr));
+ inter_list[idx].bfd = INVALID_SOCKET;
+ inter_list[idx].num_mcast = 0;
+ inter_list[idx].received = 0;
+ inter_list[idx].sent = 0;
+ inter_list[idx].notsent = 0;
+ inter_list[idx].flags = 0;
+ any6_interface = &inter_list[idx];
+ wildipv6 = idx;
+ idx++;
}
- i = 1;
- for (ifap = ifaddrs; ifap != NULL; ifap = ifap->ifa_next)
-#else
- if (getifaddrs(&ifaddrs, &num_if) < 0)
- {
- msyslog(LOG_ERR, "create_sockets: getifaddrs() failed: %m");
- exit(1);
- }
+#endif
+ return (idx);
+}
- i = 1;
+isc_boolean_t
+address_okay(isc_interface_t *isc_if) {
- for (ifap = ifaddrs, lp = ifap + num_if; ifap < lp; ifap++)
+#ifdef DEBUG
+ if (debug > 2)
+ printf("address_okay: listen Virtual: %d, IF name: %s, Up Flag: %d\n",
+ listen_to_virtual_ips, isc_if->name, (isc_if->flags & INTERFACE_F_UP));
#endif
- {
- struct sockaddr_in *sin;
- if (!ifap->ifa_addr)
- continue;
+ if (listen_to_virtual_ips == 0 && (strchr(isc_if->name, (int)':') != NULL))
+ return (ISC_FALSE);
- if (ifap->ifa_addr->sa_family != AF_INET)
- continue;
+ /* XXXPDM This should be fixed later, but since we may not have set
+ * the UP flag, we at least get to use the interface.
+ * The UP flag is not always set so we don't do this right now.
+ */
+/* if ((isc_if->flags & INTERFACE_F_UP) == 0)
+ return (ISC_FALSE);
+*/
+ return (ISC_TRUE);
+}
+void
+convert_isc_if(isc_interface_t *isc_if, struct interface *itf, u_short port) {
+
+ if(isc_if->af == AF_INET) {
+ itf->sin.ss_family = (u_short) isc_if->af;
+ strcpy(itf->name, isc_if->name);
+ memcpy(&(((struct sockaddr_in*)&itf->sin)->sin_addr),
+ &(isc_if->address.type.in),
+ sizeof(struct in_addr));
+ ((struct sockaddr_in*)&itf->sin)->sin_port = port;
+
+ if((isc_if->flags & INTERFACE_F_BROADCAST) != 0) {
+ itf->flags |= INT_BROADCAST;
+ itf->bcast.ss_family = itf->sin.ss_family;
+ memcpy(&(((struct sockaddr_in*)&itf->bcast)->sin_addr),
+ &(isc_if->broadcast.type.in),
+ sizeof(struct in_addr));
+ ((struct sockaddr_in*)&itf->bcast)->sin_port = port;
+ }
- if ((ifap->ifa_flags & IFF_UP) == 0)
- continue;
+ itf->mask.ss_family = itf->sin.ss_family;
+ memcpy(&(((struct sockaddr_in*)&itf->mask)->sin_addr),
+ &(isc_if->netmask.type.in),
+ sizeof(struct in_addr));
+ ((struct sockaddr_in*)&itf->mask)->sin_port = port;
- if (debug)
- printf("after getifaddrs(), considering %s (%s)\n",
- ifap->ifa_name,
- inet_ntoa(((struct sockaddr_in *)ifap->ifa_addr)->sin_addr));
-
- if (ifap->ifa_flags & IFF_LOOPBACK) {
- sin = (struct sockaddr_in *)ifap->ifa_addr;
- if (ntohl(sin->sin_addr.s_addr) != 0x7f000001 &&
- !listen_to_virtual_ips)
- continue;
- }
- inter_list[i].flags = 0;
- if (ifap->ifa_flags & IFF_BROADCAST)
- inter_list[i].flags |= INT_BROADCAST;
- strcpy(inter_list[i].name, ifap->ifa_name);
- sin = (struct sockaddr_in *)ifap->ifa_addr;
- inter_list[i].sin = *sin;
- inter_list[i].sin.sin_port = port;
- if (ifap->ifa_flags & IFF_LOOPBACK) {
- inter_list[i].flags = INT_LOOPBACK;
- if (loopback_interface == NULL
- || ntohl(sin->sin_addr.s_addr) != 0x7f000001)
- loopback_interface = &inter_list[i];
- }
- if (inter_list[i].flags & INT_BROADCAST) {
- sin = (struct sockaddr_in *)ifap->ifa_broadaddr;
- inter_list[i].bcast = *sin;
- inter_list[i].bcast.sin_port = port;
- }
- if (ifap->ifa_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) {
- inter_list[i].mask.sin_addr.s_addr = 0xffffffff;
- } else {
- sin = (struct sockaddr_in *)ifap->ifa_netmask;
- inter_list[i].mask = *sin;
+ if (((isc_if->flags & INTERFACE_F_LOOPBACK) != 0) && (loopback_interface == NULL))
+ {
+ loopback_interface = itf;
}
- inter_list[i].mask.sin_family = AF_INET;
- inter_list[i].mask.sin_len = sizeof *sin;
-
- /*
- * look for an already existing source interface address. If
- * the machine has multiple point to point interfaces, then
- * the local address may appear more than once.
- *
- * A second problem exists if we have two addresses on
- * the same network (via "ifconfig alias ..."). Don't
- * make two xntp interfaces for the two aliases on the
- * one physical interface. -wsr
- */
- for (j=0; j < i; j++)
- if ((inter_list[j].sin.sin_addr.s_addr &
- inter_list[j].mask.sin_addr.s_addr) ==
- (inter_list[i].sin.sin_addr.s_addr &
- inter_list[i].mask.sin_addr.s_addr))
- {
- if (inter_list[j].flags & INT_LOOPBACK)
- inter_list[j] = inter_list[i];
- break;
- }
- if (j == i)
- i++;
- if (i > MAXINTERFACES)
- break;
}
- free(ifaddrs);
-#else /* _BSDI_VERSION >= 199510 */
-# ifdef USE_STREAMS_DEVICE_FOR_IF_CONFIG
- if ((vs = open("/dev/ip", O_RDONLY)) < 0)
- {
- msyslog(LOG_ERR, "create_sockets: open(/dev/ip) failed: %m");
- exit(1);
- }
-# else /* not USE_STREAMS_DEVICE_FOR_IF_CONFIG */
- if (
- (vs = socket(AF_INET, SOCK_DGRAM, 0))
-# ifndef SYS_WINNT
- < 0
-# else /* SYS_WINNT */
- == INVALID_SOCKET
-# endif /* SYS_WINNT */
- ) {
- msyslog(LOG_ERR, "create_sockets: socket(AF_INET, SOCK_DGRAM) failed: %m");
- exit(1);
+#ifdef HAVE_IPV6
+ else if (isc_if->af == AF_INET6) {
+ itf->sin.ss_family = (u_short) isc_if->af;
+ strcpy(itf->name, isc_if->name);
+ memcpy(&(((struct sockaddr_in6 *)&itf->sin)->sin6_addr),
+ &(isc_if->address.type.in6),
+ sizeof(struct in6_addr));
+ ((struct sockaddr_in6 *)&itf->sin)->sin6_port = port;
+
+ itf->mask.ss_family = itf->sin.ss_family;
+ memcpy(&(((struct sockaddr_in6 *)&itf->mask)->sin6_addr),
+ &(isc_if->netmask.type.in6),
+ sizeof(struct in6_addr));
+ ((struct sockaddr_in6 *)&itf->mask)->sin6_port = port;
+
+ if (((isc_if->flags & INTERFACE_F_LOOPBACK) != 0) && (loopback6_interface == NULL))
+ {
+ loopback6_interface = itf;
+ }
}
-# endif /* not USE_STREAMS_DEVICE_FOR_IF_CONFIG */
+#endif /* HAVE_IPV6 */
- i = 1;
-# if !defined(SYS_WINNT)
- ifc.ifc_len = sizeof(buf);
-# endif
-# ifdef STREAMS_TLI
- ioc.ic_cmd = SIOCGIFCONF;
- ioc.ic_timout = 0;
- ioc.ic_dp = (caddr_t)buf;
- ioc.ic_len = sizeof(buf);
- if(ioctl(vs, I_STR, &ioc) < 0 ||
- ioc.ic_len < sizeof(struct ifreq))
- {
- msyslog(LOG_ERR, "create_sockets: ioctl(I_STR:SIOCGIFCONF) failed: %m - exiting");
- exit(1);
- }
-# ifdef SIZE_RETURNED_IN_BUFFER
- ifc.ifc_len = ioc.ic_len - sizeof(int);
- ifc.ifc_buf = buf + sizeof(int);
-# else /* not SIZE_RETURNED_IN_BUFFER */
- ifc.ifc_len = ioc.ic_len;
- ifc.ifc_buf = buf;
-# endif /* not SIZE_RETURNED_IN_BUFFER */
-
-# else /* not STREAMS_TLI */
- ifc.ifc_len = sizeof(buf);
- ifc.ifc_buf = buf;
-# ifndef SYS_WINNT
- if (ioctl(vs, SIOCGIFCONF, (char *)&ifc) < 0)
-# else
- if (WSAIoctl(vs, SIO_GET_INTERFACE_LIST, 0, 0, ifc.ifc_buf, ifc.ifc_len, &ifc.ifc_len, 0, 0) == SOCKET_ERROR)
-# endif /* SYS_WINNT */
-{
- msyslog(LOG_ERR, "create_sockets: ioctl(SIOCGIFCONF) failed: %m - exiting");
- exit(1);
+ /* Process the rest of the flags */
+
+ if((isc_if->flags & INTERFACE_F_UP) != 0)
+ itf->flags |= INT_UP;
+ if((isc_if->flags & INTERFACE_F_LOOPBACK) != 0)
+ itf->flags |= INT_LOOPBACK;
+ if((isc_if->flags & INTERFACE_F_POINTTOPOINT) != 0)
+ itf->flags |= INT_PPP;
}
+/*
+ * create_sockets - create a socket for each interface plus a default
+ * socket for when we don't know where to send
+ */
+static int
+create_sockets(
+ u_short port
+ )
+{
+ struct sockaddr_storage resmask;
+ int i;
+ isc_mem_t *mctx = NULL;
+ isc_interfaceiter_t *iter = NULL;
+ isc_boolean_t scan_ipv4 = ISC_FALSE;
+ isc_boolean_t scan_ipv6 = ISC_FALSE;
+ isc_result_t result;
+ int idx = 0;
-# endif /* not STREAMS_TLI */
+#ifdef DEBUG
+ if (debug)
+ printf("create_sockets(%d)\n", ntohs( (u_short) port));
+#endif
+
+ if (isc_net_probeipv6() == ISC_R_SUCCESS)
+ scan_ipv6 = ISC_TRUE;
+#ifdef HAVE_IPV6
+ else
+ netsyslog(LOG_ERR, "no IPv6 interfaces found");
+#endif
- for(n = ifc.ifc_len, ifr = ifc.ifc_req; n > 0;
- ifr = (struct ifreq *)((char *)ifr + size))
+ if (isc_net_probeipv4() == ISC_R_SUCCESS)
+ scan_ipv4 = ISC_TRUE;
+ else
+ netsyslog(LOG_ERR, "no IPv4 interfaces found");
+
+ nwilds = create_wildcards(port);
+ idx = nwilds;
+
+ result = isc_interfaceiter_create(mctx, &iter);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ for (result = isc_interfaceiter_first(iter);
+ result == ISC_R_SUCCESS;
+ result = isc_interfaceiter_next(iter))
{
- size = sizeof(*ifr);
+ isc_interface_t isc_if;
+ unsigned int family;
-# ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_addr))
- size += ifr->ifr_addr.sa_len - sizeof(struct sockaddr);
-# endif
- n -= size;
+ result = isc_interfaceiter_current(iter, &isc_if);
+ if (result != ISC_R_SUCCESS)
+ break;
-# if !defined(SYS_WINNT)
- /* Exclude logical interfaces (indicated by ':' in the interface name) */
- if (debug)
- printf("interface <%s> ", ifr->ifr_name);
- if ((listen_to_virtual_ips == 0)
- && (strchr(ifr->ifr_name, (int)':') != NULL)) {
- if (debug)
- printf("ignored\n");
+ /* See if we have a valid family to use */
+ family = isc_if.address.family;
+ if (family != AF_INET && family != AF_INET6)
continue;
- }
- if (debug)
- printf("OK\n");
-
- if (
-# ifdef VMS /* VMS+UCX */
- (((struct sockaddr *)&(ifr->ifr_addr))->sa_family != AF_INET)
-# else
- (ifr->ifr_addr.sa_family != AF_INET)
-# endif /* VMS+UCX */
- ) {
- if (debug)
- printf("ignoring %s - not AF_INET\n",
- ifr->ifr_name);
+ if (scan_ipv4 == ISC_FALSE && family == AF_INET)
continue;
- }
-# endif /* SYS_WINNT */
- ifreq = *ifr;
- inter_list[i].flags = 0;
- /* is it broadcast capable? */
-# ifndef SYS_WINNT
-# ifdef STREAMS_TLI
- ioc.ic_cmd = SIOCGIFFLAGS;
- ioc.ic_timout = 0;
- ioc.ic_dp = (caddr_t)&ifreq;
- ioc.ic_len = sizeof(struct ifreq);
- if(ioctl(vs, I_STR, &ioc)) {
- msyslog(LOG_ERR, "create_sockets: ioctl(I_STR:SIOCGIFFLAGS) failed: %m");
- continue;
- }
-# else /* not STREAMS_TLI */
- if (ioctl(vs, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
- if (errno != ENXIO)
- msyslog(LOG_ERR, "create_sockets: ioctl(SIOCGIFFLAGS) failed: %m");
+ if (scan_ipv6 == ISC_FALSE && family == AF_INET6)
continue;
- }
-# endif /* not STREAMS_TLI */
- if ((ifreq.ifr_flags & IFF_UP) == 0) {
- if (debug)
- printf("ignoring %s - interface not UP\n",
- ifr->ifr_name);
- continue;
- }
- inter_list[i].flags = 0;
- if (ifreq.ifr_flags & IFF_BROADCAST)
- inter_list[i].flags |= INT_BROADCAST;
-# endif /* not SYS_WINNT */
-# if !defined(SUN_3_3_STINKS)
- if (
-# if defined(IFF_LOCAL_LOOPBACK) /* defined(SYS_HPUX) && (SYS_HPUX < 8) */
- (ifreq.ifr_flags & IFF_LOCAL_LOOPBACK)
-# elif defined(IFF_LOOPBACK)
- (ifreq.ifr_flags & IFF_LOOPBACK)
-# else /* not IFF_LOCAL_LOOPBACK and not IFF_LOOPBACK */
- /* test against 127.0.0.1 (yuck!!) */
- ((*(struct sockaddr_in *)&ifr->ifr_addr).sin_addr.s_addr == inet_addr("127.0.0.1"))
-# endif /* not IFF_LOCAL_LOOPBACK and not IFF_LOOPBACK */
- )
- {
-# ifndef SYS_WINNT
- inter_list[i].flags |= INT_LOOPBACK;
-# endif /* not SYS_WINNT */
- if (loopback_interface == 0)
- {
- loopback_interface = &inter_list[i];
- }
- }
-# endif /* not SUN_3_3_STINKS */
-#if 0
-# ifndef SYS_WINNT
-# ifdef STREAMS_TLI
- ioc.ic_cmd = SIOCGIFADDR;
- ioc.ic_timout = 0;
- ioc.ic_dp = (caddr_t)&ifreq;
- ioc.ic_len = sizeof(struct ifreq);
- if (ioctl(vs, I_STR, &ioc))
- {
- msyslog(LOG_ERR, "create_sockets: ioctl(I_STR:SIOCGIFADDR) failed: %m");
- continue;
+ /* Check to see if we are going to use the interface */
+ if (address_okay(&isc_if) == ISC_TRUE) {
+ convert_isc_if(&isc_if, &inter_list[idx], port);
+ inter_list[idx].fd = INVALID_SOCKET;
+ inter_list[idx].bfd = INVALID_SOCKET;
+ inter_list[idx].num_mcast = 0;
+ inter_list[idx].received = 0;
+ inter_list[idx].sent = 0;
+ inter_list[idx].notsent = 0;
+ idx++;
}
-# else /* not STREAMS_TLI */
- if (ioctl(vs, SIOCGIFADDR, (char *)&ifreq) < 0)
- {
- if (errno != ENXIO)
- msyslog(LOG_ERR, "create_sockets: ioctl(SIOCGIFADDR) failed: %m");
- continue;
- }
-# endif /* not STREAMS_TLI */
-# endif /* not SYS_WINNT */
-#endif /* 0 */
-# if defined(SYS_WINNT)
- {int TODO_FillInTheNameWithSomeThingReasonble;}
-# else
- (void)strncpy(inter_list[i].name, ifreq.ifr_name,
- sizeof(inter_list[i].name));
-# endif
- inter_list[i].sin = *(struct sockaddr_in *)&ifr->ifr_addr;
- inter_list[i].sin.sin_family = AF_INET;
- inter_list[i].sin.sin_port = port;
-
-# if defined(SUN_3_3_STINKS)
- /*
- * Oh, barf! I'm too disgusted to even explain this
- */
- if (SRCADR(&inter_list[i].sin) == 0x7f000001)
- {
- inter_list[i].flags |= INT_LOOPBACK;
- if (loopback_interface == 0)
- loopback_interface = &inter_list[i];
- }
-# endif /* SUN_3_3_STINKS */
-# if !defined SYS_WINNT && !defined SYS_CYGWIN32 /* no interface flags on NT */
- if (inter_list[i].flags & INT_BROADCAST) {
-# ifdef STREAMS_TLI
- ioc.ic_cmd = SIOCGIFBRDADDR;
- ioc.ic_timout = 0;
- ioc.ic_dp = (caddr_t)&ifreq;
- ioc.ic_len = sizeof(struct ifreq);
- if(ioctl(vs, I_STR, &ioc)) {
- msyslog(LOG_ERR, "create_sockets: ioctl(I_STR:SIOCGIFBRDADDR) failed: %m");
- exit(1);
- }
-# else /* not STREAMS_TLI */
- if (ioctl(vs, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
- msyslog(LOG_ERR, "create_sockets: ioctl(SIOCGIFBRDADDR) failed: %m");
- exit(1);
- }
-# endif /* not STREAMS_TLI */
-
-# ifndef ifr_broadaddr
- inter_list[i].bcast =
- *(struct sockaddr_in *)&ifreq.ifr_addr;
-# else
- inter_list[i].bcast =
- *(struct sockaddr_in *)&ifreq.ifr_broadaddr;
-# endif /* ifr_broadaddr */
- inter_list[i].bcast.sin_family = AF_INET;
- inter_list[i].bcast.sin_port = port;
- }
-
-# ifdef STREAMS_TLI
- ioc.ic_cmd = SIOCGIFNETMASK;
- ioc.ic_timout = 0;
- ioc.ic_dp = (caddr_t)&ifreq;
- ioc.ic_len = sizeof(struct ifreq);
- if(ioctl(vs, I_STR, &ioc)) {
- msyslog(LOG_ERR, "create_sockets: ioctl(I_STR:SIOCGIFNETMASK) failed: %m");
- exit(1);
- }
-# else /* not STREAMS_TLI */
- if (ioctl(vs, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
- msyslog(LOG_ERR, "create_sockets: ioctl(SIOCGIFNETMASK) failed: %m");
- exit(1);
- }
-# endif /* not STREAMS_TLI */
- inter_list[i].mask = *(struct sockaddr_in *)&ifreq.ifr_addr;
-# else
- /* winnt here */
- inter_list[i].bcast = ifreq.ifr_broadaddr;
- inter_list[i].bcast.sin_family = AF_INET;
- inter_list[i].bcast.sin_port = port;
- inter_list[i].mask = ifreq.ifr_mask;
-# endif /* not SYS_WINNT */
-
- /*
- * look for an already existing source interface address. If
- * the machine has multiple point to point interfaces, then
- * the local address may appear more than once.
- */
- for (j=0; j < i; j++)
- if (inter_list[j].sin.sin_addr.s_addr ==
- inter_list[i].sin.sin_addr.s_addr) {
- break;
- }
- if (j == i)
- i++;
- if (i > MAXINTERFACES)
- break;
}
- closesocket(vs);
-#endif /* _BSDI_VERSION >= 199510 */
+ isc_interfaceiter_destroy(&iter);
- ninterfaces = i;
+ ninterfaces = idx;
+ /*
+ * I/O Completion Ports don't care about the select and FD_SET
+ */
+#ifndef HAVE_IO_COMPLETION_PORT
maxactivefd = 0;
FD_ZERO(&activefds);
+#endif
for (i = 0; i < ninterfaces; i++) {
inter_list[i].fd = open_socket(&inter_list[i].sin,
inter_list[i].flags & INT_BROADCAST, 0);
- }
-
- /*
- * Now that we have opened all the sockets, turn off the reuse flag for
- * security.
- */
- for (i = 0; i < ninterfaces; i++) {
- int off = 0;
-
- /*
- * if inter_list[ n ].fd is -1, we might have a adapter
- * configured but not present
- */
- if ( inter_list[ i ].fd != -1 ) {
- if (setsockopt(inter_list[i].fd, SOL_SOCKET,
- SO_REUSEADDR, (char *)&off,
- sizeof(off))) {
- msyslog(LOG_ERR, "create_sockets: setsockopt(SO_REUSEADDR,off) failed: %m");
- }
+ if (inter_list[i].bfd != INVALID_SOCKET)
+ msyslog(LOG_INFO, "Listening on interface %s, %s#%d",
+ inter_list[i].name,
+ stoa((&inter_list[i].sin)),
+ NTP_PORT);
+ if ((inter_list[i].flags & INT_BROADCAST) &&
+ inter_list[i].bfd != INVALID_SOCKET)
+ msyslog(LOG_INFO, "Listening on broadcast address %s#%d",
+ stoa((&inter_list[i].bcast)),
+ NTP_PORT);
+#if defined (HAVE_IO_COMPLETION_PORT)
+ if (inter_list[i].fd != INVALID_SOCKET) {
+ io_completion_port_add_socket(inter_list[i].fd, &inter_list[i]);
}
+#endif
}
-#if defined(MCAST)
/*
- * enable possible multicast reception on the broadcast socket
+ * Now that we have opened all the sockets, turn off the reuse
+ * flag for security.
*/
- inter_list[0].bcast.sin_addr.s_addr = htonl(INADDR_ANY);
- inter_list[0].bcast.sin_family = AF_INET;
- inter_list[0].bcast.sin_port = port;
-#endif /* MCAST */
+ set_reuseaddr(0);
/*
* Blacklist all bound interface addresses
+ * Wildcard interfaces are ignored.
*/
- resmask.sin_addr.s_addr = ~ (u_int32)0;
- for (i = 1; i < ninterfaces; i++)
+
+ for (i = nwilds; i < ninterfaces; i++) {
+ SET_HOSTMASK(&resmask, inter_list[i].sin.ss_family);
hack_restrict(RESTRICT_FLAGS, &inter_list[i].sin, &resmask,
RESM_NTPONLY|RESM_INTERFACE, RES_IGNORE);
+ }
+
+ /*
+ * Calculate the address hash for each interface address.
+ */
+ for (i = 0; i < ninterfaces; i++) {
+ inter_list[i].addr_refid = addr2refid(&inter_list[i].sin);
+ }
+
+
#ifdef DEBUG
if (debug > 1) {
printf("create_sockets: ninterfaces=%d\n", ninterfaces);
@@ -659,20 +545,15 @@ create_sockets(
inter_list[i].flags);
/* Leave these as three printf calls. */
printf(" sin=%s",
- inet_ntoa((inter_list[i].sin.sin_addr)));
+ stoa((&inter_list[i].sin)));
if (inter_list[i].flags & INT_BROADCAST)
printf(" bcast=%s,",
- inet_ntoa((inter_list[i].bcast.sin_addr)));
+ stoa((&inter_list[i].bcast)));
printf(" mask=%s\n",
- inet_ntoa((inter_list[i].mask.sin_addr)));
+ stoa((&inter_list[i].mask)));
}
}
#endif
-#if defined (HAVE_IO_COMPLETION_PORT)
- for (i = 0; i < ninterfaces; i++) {
- io_completion_port_add_socket(&inter_list[i]);
- }
-#endif
return ninterfaces;
}
@@ -684,10 +565,19 @@ io_setbclient(void)
{
int i;
- for (i = 1; i < ninterfaces; i++) {
+#ifdef OPEN_BCAST_SOCKET
+ set_reuseaddr(1);
+#endif
+ for (i = nwilds; i < ninterfaces; i++) {
+ /* Only IPv4 addresses are valid for broadcast */
+ if (inter_list[i].bcast.ss_family != AF_INET)
+ continue;
+
+ /* Is this a broadcast address? */
if (!(inter_list[i].flags & INT_BROADCAST))
continue;
+ /* Do we already have the broadcast address open? */
if (inter_list[i].flags & INT_BCASTOPEN)
continue;
@@ -697,8 +587,54 @@ io_setbclient(void)
#ifdef OPEN_BCAST_SOCKET /* Was: !SYS_DOMAINOS && !SYS_LINUX */
inter_list[i].bfd = open_socket(&inter_list[i].bcast,
INT_BROADCAST, 1);
- inter_list[i].flags |= INT_BCASTOPEN;
+ if (inter_list[i].bfd != INVALID_SOCKET) {
+ inter_list[i].flags |= INT_BCASTOPEN;
+#if defined (HAVE_IO_COMPLETION_PORT)
+ io_completion_port_add_socket(inter_list[i].bfd, &inter_list[i]);
+#endif
+ }
+#ifdef DEBUG
+ if (debug) {
+ if (inter_list[i].bfd != INVALID_SOCKET)
+ printf("io_setbclient: Opened broadcast client on interface %d, socket: %d\n",
+ i, inter_list[i].bfd);
+ else
+ printf("io_setbclient: Unable to Open broadcast client on interface %d\n",
+ i);
+ }
+#endif
+#endif
+ }
+#ifdef OPEN_BCAST_SOCKET
+ set_reuseaddr(0);
+#endif
+#ifdef DEBUG
+ if (debug)
+ printf("io_setbclient: Opened broadcast clients\n");
#endif
+}
+
+/*
+ * set_reuseaddr() - set/clear REUSEADDR on all sockets
+ * NB possible hole - should we be doing this on broadcast
+ * fd's also?
+ */
+static void
+set_reuseaddr(int flag) {
+ int i;
+
+ for (i=0; i < ninterfaces; i++) {
+ /*
+ * if inter_list[ n ].fd is -1, we might have a adapter
+ * configured but not present
+ */
+ if (inter_list[i].fd != INVALID_SOCKET) {
+ if (setsockopt(inter_list[i].fd, SOL_SOCKET,
+ SO_REUSEADDR, (char *)&flag,
+ sizeof(flag))) {
+ netsyslog(LOG_ERR, "set_reuseaddr: setsockopt(SO_REUSEADDR, %s) failed: %m", flag ? "on" : "off");
+ }
+ }
}
}
@@ -708,83 +644,196 @@ io_setbclient(void)
*/
void
io_multicast_add(
- u_int32 addr
+ struct sockaddr_storage addr
)
{
#ifdef MCAST
struct ip_mreq mreq;
int i = ninterfaces; /* Use the next interface */
- u_int32 haddr = ntohl(addr);
+ u_int32 haddr = ntohl(((struct sockaddr_in*)&addr)->sin_addr.s_addr);
struct in_addr iaddr;
- int s;
+ SOCKET s;
struct sockaddr_in *sinp;
- iaddr.s_addr = addr;
- if (!IN_CLASSD(haddr)) {
- msyslog(LOG_ERR,
- "multicast address %s not class D",
- inet_ntoa(iaddr));
- return;
- }
- for (i = 0; i < ninterfaces; i++) {
- /* Already have this address */
- if (inter_list[i].sin.sin_addr.s_addr == addr)
+#ifdef HAVE_IPV6
+ struct ipv6_mreq mreq6;
+ struct in6_addr iaddr6;
+ struct sockaddr_in6 *sin6p;
+#endif /* HAVE_IPV6 */
+
+ switch (addr.ss_family)
+ {
+ case AF_INET :
+ iaddr = (((struct sockaddr_in*)&addr)->sin_addr);
+ if (!IN_CLASSD(haddr)) {
+ netsyslog(LOG_ERR,
+ "multicast address %s not class D",
+ inet_ntoa(iaddr));
return;
- /* found a free slot */
- if (inter_list[i].sin.sin_addr.s_addr == 0 &&
- inter_list[i].fd <= 0 && inter_list[i].bfd <= 0 &&
- inter_list[i].flags == 0)
+ }
+ for (i = nwilds; i < ninterfaces; i++) {
+ /* Be sure it's the correct family */
+ if (inter_list[i].sin.ss_family != AF_INET)
+ continue;
+ /* Already have this address */
+ if (SOCKCMP(&inter_list[i].sin, &addr))
+ return;
+ /* found a free slot */
+ if (SOCKNUL(&inter_list[i].sin) &&
+ inter_list[i].fd <= 0 && inter_list[i].bfd <= 0 &&
+ inter_list[i].flags == 0)
+ break;
+ }
+ sinp = (struct sockaddr_in*)&(inter_list[i].sin);
+ memset((char *)&mreq, 0, sizeof(mreq));
+ memset((char *)&inter_list[i], 0, sizeof(struct interface));
+ sinp->sin_family = AF_INET;
+ sinp->sin_addr = iaddr;
+ sinp->sin_port = htons(NTP_PORT);
+
+ /*
+ * Try opening a socket for the specified class D address. This
+ * works under SunOS 4.x, but not OSF1 .. :-(
+ */
+ set_reuseaddr(1);
+ s = open_socket((struct sockaddr_storage*)sinp, 0, 1);
+ set_reuseaddr(0);
+ if (s == INVALID_SOCKET) {
+ memset((char *)&inter_list[i], 0, sizeof(struct interface));
+ if (wildipv4 >= 0) {
+ i = wildipv4;
+ /* HACK ! -- stuff in an address */
+ inter_list[i].bcast = addr;
+ netsyslog(LOG_ERR,
+ "...multicast address %s using wildcard socket",
+ inet_ntoa(iaddr));
+ } else {
+ netsyslog(LOG_ERR,
+ "No wildcard socket available to use for address %s",
+ inet_ntoa(iaddr));
+ return;
+ }
+ } else {
+ inter_list[i].fd = s;
+ inter_list[i].bfd = INVALID_SOCKET;
+ (void) strncpy(inter_list[i].name, "multicast",
+ sizeof(inter_list[i].name));
+ ((struct sockaddr_in*)&inter_list[i].mask)->sin_addr.s_addr = htonl(~(u_int32)0);
+#if defined (HAVE_IO_COMPLETION_PORT)
+ io_completion_port_add_socket(inter_list[i].fd, &inter_list[i]);
+#endif
+ }
+
+ /*
+ * enable reception of multicast packets
+ */
+ mreq.imr_multiaddr = iaddr;
+ mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+ if (setsockopt(inter_list[i].fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ (char *)&mreq, sizeof(mreq)) == -1)
+ netsyslog(LOG_ERR,
+ "setsockopt IP_ADD_MEMBERSHIP fails: %m for %x / %x (%s)",
+ mreq.imr_multiaddr.s_addr,
+ mreq.imr_interface.s_addr, inet_ntoa(iaddr));
+ inter_list[i].flags |= INT_MULTICAST;
+ inter_list[i].num_mcast++;
+ if (i >= ninterfaces)
+ ninterfaces = i+1;
+
+ add_addr_to_list(&addr, i);
break;
- }
- sinp = &(inter_list[i].sin);
- memset((char *)&mreq, 0, sizeof(mreq));
- memset((char *)&inter_list[i], 0, sizeof inter_list[0]);
- sinp->sin_family = AF_INET;
- sinp->sin_addr = iaddr;
- sinp->sin_port = htons(123);
- /*
- * Try opening a socket for the specified class D address. This
- * works under SunOS 4.x, but not OSF1 .. :-(
- */
- s = open_socket(sinp, 0, 1);
- if (s < 0) {
- memset((char *)&inter_list[i], 0, sizeof inter_list[0]);
- i = 0;
- /* HACK ! -- stuff in an address */
- inter_list[i].bcast.sin_addr.s_addr = addr;
- msyslog(LOG_ERR,
- "...multicast address %s using wildcard socket",
- inet_ntoa(iaddr));
- } else {
- inter_list[i].fd = s;
- inter_list[i].bfd = -1;
- (void) strncpy(inter_list[i].name, "multicast",
- sizeof(inter_list[i].name));
- inter_list[i].mask.sin_addr.s_addr = htonl(~(u_int32)0);
+#ifdef HAVE_IPV6
+ case AF_INET6 :
+
+ iaddr6 = ((struct sockaddr_in6*)&addr)->sin6_addr;
+ if (!IN6_IS_ADDR_MULTICAST(&iaddr6)) {
+ netsyslog(LOG_ERR,
+ "address %s not IPv6 multicast address",
+ stoa(&addr));
+ return;
+ }
+ for (i = nwilds; i < ninterfaces; i++) {
+ /* Be sure it's the correct family */
+ if(inter_list[i].sin.ss_family != AF_INET6)
+ continue;
+ /* Already have this address */
+ if (SOCKCMP(&inter_list[i].sin, &addr))
+ return;
+ /* found a free slot */
+ if (SOCKNUL(&inter_list[i].sin) &&
+ inter_list[i].fd <= 0 && inter_list[i].bfd <= 0 &&
+ inter_list[i].flags == 0)
+ break;
+ }
+ sin6p = (struct sockaddr_in6*)&inter_list[i].sin;
+ memset((char *)&mreq6, 0, sizeof(mreq6));
+ memset((char *)&inter_list[i], 0, sizeof(struct interface));
+ sin6p->sin6_family = AF_INET6;
+ sin6p->sin6_addr = iaddr6;
+ sin6p->sin6_port = htons(NTP_PORT);
+
+ /*
+ * Try opening a socket for the specified class D address. This
+ * works under SunOS 4.x, but not OSF1 .. :-(
+ */
+ set_reuseaddr(1);
+ s = open_socket((struct sockaddr_storage*)sin6p, 0, 1);
+ set_reuseaddr(0);
+ if(s == INVALID_SOCKET){
+ memset((char *)&inter_list[i], 0, sizeof(struct interface));
+ if (wildipv6 >= 0) {
+ i = wildipv6;
+ /* HACK ! -- stuff in an address */
+ inter_list[i].bcast = addr;
+ netsyslog(LOG_ERR,
+ "...multicast address %s using wildcard socket",
+ stoa(&addr));
+ } else {
+ netsyslog(LOG_ERR,
+ "No wildcard socket available to use for address %s",
+ stoa(&addr));
+ return;
+ }
+ } else {
+ inter_list[i].fd = s;
+ inter_list[i].bfd = INVALID_SOCKET;
+ (void)strncpy(inter_list[i].name, "multicast",
+ sizeof(inter_list[i].name));
+ memset(&(((struct sockaddr_in6*)&inter_list[i].mask)->sin6_addr), 1, sizeof(struct in6_addr));
+#if defined (HAVE_IO_COMPLETION_PORT)
+ io_completion_port_add_socket(inter_list[i].fd, &inter_list[i]);
+#endif
+ }
+
+ /*
+ * enable reception of multicast packets
+ */
+ mreq6.ipv6mr_multiaddr = iaddr6;
+ mreq6.ipv6mr_interface = 0;
+ if(setsockopt(inter_list[i].fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
+ (char *)&mreq6, sizeof(mreq6)) == -1)
+ netsyslog(LOG_ERR,
+ "setsockopt IPV6_JOIN_GROUP fails: %m on interface %d(%s)",
+ mreq6.ipv6mr_interface, stoa(&addr));
+ inter_list[i].flags |= INT_MULTICAST;
+ inter_list[i].num_mcast++;
+ if(i >= ninterfaces)
+ ninterfaces = i+1;
+
+ add_addr_to_list(&addr, i);
+ break;
+#endif /* HAVE_IPV6 */
}
- /*
- * enable reception of multicast packets
- */
- mreq.imr_multiaddr = iaddr;
- mreq.imr_interface.s_addr = htonl(INADDR_ANY);
- if (setsockopt(inter_list[i].fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- (char *)&mreq, sizeof(mreq)) == -1)
- msyslog(LOG_ERR,
- "setsockopt IP_ADD_MEMBERSHIP fails: %m for %x / %x (%s)",
- mreq.imr_multiaddr.s_addr,
- mreq.imr_interface.s_addr, inet_ntoa(iaddr));
- inter_list[i].flags |= INT_MULTICAST;
- if (i >= ninterfaces)
- ninterfaces = i+1;
+#ifdef DEBUG
+ if (debug)
+ printf("io_multicast_add %s\n", stoa(&addr));
+#endif
#else /* MCAST */
- struct in_addr iaddr;
-
- iaddr.s_addr = addr;
- msyslog(LOG_ERR,
+ netsyslog(LOG_ERR,
"cannot add multicast address %s as no MCAST support",
- inet_ntoa(iaddr));
+ stoa(&addr));
#endif /* MCAST */
}
@@ -796,12 +845,12 @@ io_unsetbclient(void)
{
int i;
- for (i = 1; i < ninterfaces; i++)
+ for (i = nwilds; i < ninterfaces; i++)
{
if (!(inter_list[i].flags & INT_BCASTOPEN))
continue;
close_socket(inter_list[i].bfd);
- inter_list[i].bfd = -1;
+ inter_list[i].bfd = INVALID_SOCKET;
inter_list[i].flags &= ~INT_BCASTOPEN;
}
}
@@ -812,57 +861,125 @@ io_unsetbclient(void)
*/
void
io_multicast_del(
- u_int32 addr
+ struct sockaddr_storage addr
)
{
#ifdef MCAST
int i;
struct ip_mreq mreq;
- u_int32 haddr = ntohl(addr);
- struct sockaddr_in sinaddr;
+ u_int32 haddr;
- if (!IN_CLASSD(haddr))
- {
- sinaddr.sin_addr.s_addr = addr;
- msyslog(LOG_ERR,
- "invalid multicast address %s", ntoa(&sinaddr));
- return;
- }
+#ifdef HAVE_IPV6
+ struct ipv6_mreq mreq6;
+ struct in6_addr haddr6;
+#endif /* HAVE_IPV6 */
- /*
- * Disable reception of multicast packets
- */
- mreq.imr_multiaddr.s_addr = addr;
- mreq.imr_interface.s_addr = htonl(INADDR_ANY);
- for (i = 0; i < ninterfaces; i++)
+ switch (addr.ss_family)
{
- if (!(inter_list[i].flags & INT_MULTICAST))
- continue;
- if (!(inter_list[i].fd < 0))
- continue;
- if (addr != inter_list[i].sin.sin_addr.s_addr)
- continue;
- if (i != 0)
+ case AF_INET :
+
+ haddr = ntohl(((struct sockaddr_in*)&addr)->sin_addr.s_addr);
+
+ if (!IN_CLASSD(haddr))
{
- /* we have an explicit fd, so we can close it */
- close_socket(inter_list[i].fd);
- memset((char *)&inter_list[i], 0, sizeof inter_list[0]);
- inter_list[i].fd = -1;
- inter_list[i].bfd = -1;
+ netsyslog(LOG_ERR,
+ "invalid multicast address %s", stoa(&addr));
+ return;
}
- else
+
+ /*
+ * Disable reception of multicast packets
+ */
+ mreq.imr_multiaddr = ((struct sockaddr_in*)&addr)->sin_addr;
+ mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+ for (i = 0; i < ninterfaces; i++)
{
- /* We are sharing "any address" port :-( Don't close it! */
- if (setsockopt(inter_list[i].fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
- (char *)&mreq, sizeof(mreq)) == -1)
- msyslog(LOG_ERR, "setsockopt IP_DROP_MEMBERSHIP fails: %m");
- /* This is **WRONG** -- there may be others ! */
- /* There should be a count of users ... */
- inter_list[i].flags &= ~INT_MULTICAST;
+ /* Be sure it's the correct family */
+ if (inter_list[i].sin.ss_family != AF_INET)
+ continue;
+ if (!(inter_list[i].flags & INT_MULTICAST))
+ continue;
+ if (!(inter_list[i].fd < 0))
+ continue;
+ if (!SOCKCMP(&addr, &inter_list[i].sin))
+ continue;
+ if (i != wildipv4)
+ {
+ /* we have an explicit fd, so we can close it */
+ close_socket(inter_list[i].fd);
+ memset((char *)&inter_list[i], 0, sizeof(struct interface));
+ inter_list[i].fd = INVALID_SOCKET;
+ inter_list[i].bfd = INVALID_SOCKET;
+ }
+ else
+ {
+ /* We are sharing "any address" port :-( Don't close it! */
+ if (setsockopt(inter_list[i].fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+ (char *)&mreq, sizeof(mreq)) == -1)
+ netsyslog(LOG_ERR, "setsockopt IP_DROP_MEMBERSHIP fails on address: %s %m",
+ stoa(&addr));
+ inter_list[i].num_mcast--;
+ /* If there are none left negate the Multicast flag */
+ if(inter_list[i].num_mcast == 0)
+ inter_list[i].flags &= ~INT_MULTICAST;
+ }
}
- }
+ break;
+
+#ifdef HAVE_IPV6
+ case AF_INET6 :
+ haddr6 = ((struct sockaddr_in6*)&addr)->sin6_addr;
+
+ if (!IN6_IS_ADDR_MULTICAST(&haddr6))
+ {
+ netsyslog(LOG_ERR,
+ "invalid multicast address %s", stoa(&addr));
+ return;
+ }
+
+ /*
+ * Disable reception of multicast packets
+ */
+ mreq6.ipv6mr_multiaddr = ((struct sockaddr_in6*)&addr)->sin6_addr;
+ mreq6.ipv6mr_interface = 0;
+ for (i = 0; i < ninterfaces; i++)
+ {
+ /* Be sure it's the correct family */
+ if (inter_list[i].sin.ss_family != AF_INET6)
+ continue;
+ if (!(inter_list[i].flags & INT_MULTICAST))
+ continue;
+ if (!(inter_list[i].fd < 0))
+ continue;
+ if (!SOCKCMP(&addr, &inter_list[i].sin))
+ continue;
+ if (i != wildipv6)
+ {
+ /* we have an explicit fd, so we can close it */
+ close_socket(inter_list[i].fd);
+ memset((char *)&inter_list[i], 0, sizeof(struct interface));
+ inter_list[i].fd = INVALID_SOCKET;
+ inter_list[i].bfd = INVALID_SOCKET;
+ }
+ else
+ {
+ /* We are sharing "any address" port :-( Don't close it! */
+ if (setsockopt(inter_list[i].fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
+ (char *)&mreq6, sizeof(mreq6)) == -1)
+ netsyslog(LOG_ERR, "setsockopt IP_DROP_MEMBERSHIP fails on address %s: %m",
+ stoa(&addr));
+ /* If there are none left negate the Multicast flag */
+ if(inter_list[i].num_mcast == 0)
+ inter_list[i].flags &= ~INT_MULTICAST;
+ }
+ }
+ break;
+#endif /* HAVE_IPV6 */
+ }/* switch */
+ delete_addr_from_list(&addr);
+
#else /* not MCAST */
- msyslog(LOG_ERR, "this function requires multicast kernel");
+ netsyslog(LOG_ERR, "this function requires multicast kernel");
#endif /* not MCAST */
}
@@ -870,87 +987,163 @@ io_multicast_del(
/*
* open_socket - open a socket, returning the file descriptor
*/
-static int
+
+static SOCKET
open_socket(
- struct sockaddr_in *addr,
+ struct sockaddr_storage *addr,
int flags,
int turn_off_reuse
)
{
- int fd;
+ int errval;
+ SOCKET fd;
int on = 1, off = 0;
#if defined(IPTOS_LOWDELAY) && defined(IPPROTO_IP) && defined(IP_TOS)
int tos;
#endif /* IPTOS_LOWDELAY && IPPROTO_IP && IP_TOS */
+ if ((addr->ss_family == AF_INET6) && (isc_net_probeipv6() != ISC_R_SUCCESS))
+ return (INVALID_SOCKET);
+
/* create a datagram (UDP) socket */
- if ( (fd = socket(AF_INET, SOCK_DGRAM, 0))
#ifndef SYS_WINNT
- < 0
+ if ( (fd = socket(addr->ss_family, SOCK_DGRAM, 0)) < 0) {
+ errval = errno;
+ if(addr->ss_family == AF_INET)
+ netsyslog(LOG_ERR, "socket(AF_INET, SOCK_DGRAM, 0) failed on address %s: %m",
+ stoa(addr));
+ else if(addr->ss_family == AF_INET6)
+ netsyslog(LOG_ERR, "socket(AF_INET6, SOCK_DGRAM, 0) failed on address %s: %m",
+ stoa(addr));
+ if (errval == EPROTONOSUPPORT || errval == EAFNOSUPPORT ||
+ errval == EPFNOSUPPORT)
+ return (INVALID_SOCKET);
+ exit(1);
+ /*NOTREACHED*/
+ }
#else
- == INVALID_SOCKET
-#endif /* SYS_WINNT */
- )
- {
- msyslog(LOG_ERR, "socket(AF_INET, SOCK_DGRAM, 0) failed: %m");
+ if ( (fd = socket(addr->ss_family, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
+ errval = WSAGetLastError();
+ if(addr->ss_family == AF_INET)
+ netsyslog(LOG_ERR, "socket(AF_INET, SOCK_DGRAM, 0) failed on address %s: %m",
+ stoa(addr));
+ else if(addr->ss_family == AF_INET6)
+ netsyslog(LOG_ERR, "socket(AF_INET6, SOCK_DGRAM, 0) failed on address %s: %m",
+ stoa(addr));
+ if (errval == WSAEPROTONOSUPPORT || errval == WSAEAFNOSUPPORT ||
+ errval == WSAEPFNOSUPPORT)
+ return (INVALID_SOCKET);
exit(1);
/*NOTREACHED*/
}
+ if (connection_reset_fix(fd) != ISC_R_SUCCESS) {
+ netsyslog(LOG_ERR, "connection_reset_fix(fd) failed on address %s: %m",
+ stoa(addr));
+ }
+
+#endif /* SYS_WINNT */
/* set SO_REUSEADDR since we will be binding the same port
number on each interface */
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
(char *)&on, sizeof(on)))
{
- msyslog(LOG_ERR, "setsockopt SO_REUSEADDR on fails: %m");
+ netsyslog(LOG_ERR, "setsockopt SO_REUSEADDR on fails on address %s: %m",
+ stoa(addr));
}
#if defined(IPTOS_LOWDELAY) && defined(IPPROTO_IP) && defined(IP_TOS)
/* set IP_TOS to minimize packet delay */
tos = IPTOS_LOWDELAY;
- if (setsockopt(fd, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(tos)) < 0)
- {
- msyslog(LOG_ERR, "setsockopt IPTOS_LOWDELAY on fails: %m");
- }
+ if (addr->ss_family == AF_INET)
+ if (setsockopt(fd, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(tos)) < 0)
+ {
+ netsyslog(LOG_ERR, "setsockopt IPTOS_LOWDELAY on fails on address %s: %m",
+ stoa(addr));
+ }
+
+#if defined(IPV6_V6ONLY)
+ if (addr->ss_family == AF_INET6)
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char*)&on, sizeof(on)))
+ {
+ netsyslog(LOG_ERR, "setsockopt IPV6_V6ONLY on fails on address %s: %m",
+ stoa(addr));
+ }
+#else /* IPV6_V6ONLY */
+#if defined(IPV6_BINDV6ONLY)
+ if (addr->ss_family == AF_INET6)
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_BINDV6ONLY,
+ (char*)&on, sizeof(on)))
+ {
+ netsyslog(LOG_ERR,
+ "setsockopt IPV6_BINDV6ONLY on fails on address %s: %m",
+ stoa(addr));
+ }
+#endif /* IPV6_BINDV6ONLY */
+#endif /* IPV6_V6ONLY */
+
#endif /* IPTOS_LOWDELAY && IPPROTO_IP && IP_TOS */
/*
* bind the local address.
*/
- if (bind(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0) {
+ if (bind(fd, (struct sockaddr *)addr, SOCKLEN(addr)) < 0) {
char buff[160];
- sprintf(buff,
- "bind() fd %d, family %d, port %d, addr %s, in_classd=%d flags=%d fails: %%m",
- fd, addr->sin_family, (int)ntohs(addr->sin_port),
- ntoa(addr),
- IN_CLASSD(ntohl(addr->sin_addr.s_addr)), flags);
- msyslog(LOG_ERR, buff);
+
+ if(addr->ss_family == AF_INET)
+ sprintf(buff,
+ "bind() fd %d, family %d, port %d, addr %s, in_classd=%d flags=%d fails: %%m",
+ fd, addr->ss_family, (int)ntohs(((struct sockaddr_in*)addr)->sin_port),
+ stoa(addr),
+ IN_CLASSD(ntohl(((struct sockaddr_in*)addr)->sin_addr.s_addr)), flags);
+ else if(addr->ss_family == AF_INET6)
+ sprintf(buff,
+ "bind() fd %d, family %d, port %d, addr %s, in6_is_addr_multicast=%d flags=%d fails: %%m",
+ fd, addr->ss_family, (int)ntohs(((struct sockaddr_in6*)addr)->sin6_port),
+ stoa(addr),
+ IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)addr)->sin6_addr), flags);
+ else return INVALID_SOCKET;
+
+ netsyslog(LOG_ERR, buff);
closesocket(fd);
/*
- * soft fail if opening a class D address
+ * soft fail if opening a multicast address
*/
- if (IN_CLASSD(ntohl(addr->sin_addr.s_addr)))
- return -1;
+ if(addr->ss_family == AF_INET){
+ if(IN_CLASSD(ntohl(((struct sockaddr_in*)addr)->sin_addr.s_addr)))
+ return (INVALID_SOCKET);
+ }
+ else {
+ if(IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)addr)->sin6_addr))
+ return (INVALID_SOCKET);
+ }
#if 0
exit(1);
#else
- return -1;
+ return INVALID_SOCKET;
#endif
}
#ifdef DEBUG
if (debug)
printf("bind() fd %d, family %d, port %d, addr %s, flags=%d\n",
fd,
- addr->sin_family,
- (int)ntohs(addr->sin_port),
- ntoa(addr),
+ addr->ss_family,
+ (int)ntohs(((struct sockaddr_in*)addr)->sin_port),
+ stoa(addr),
flags);
#endif
+
+ /*
+ * I/O Completion Ports don't care about the select and FD_SET
+ */
+#ifndef HAVE_IO_COMPLETION_PORT
if (fd > maxactivefd)
maxactivefd = fd;
FD_SET(fd, &activefds);
-
+#endif
+ add_socket_to_list(fd);
/*
* set non-blocking,
*/
@@ -967,43 +1160,46 @@ open_socket(
#if defined(O_NONBLOCK) /* POSIX */
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
{
- msyslog(LOG_ERR, "fcntl(O_NONBLOCK) fails: %m");
+ netsyslog(LOG_ERR, "fcntl(O_NONBLOCK) fails on address %s: %m",
+ stoa(addr));
exit(1);
/*NOTREACHED*/
}
#elif defined(FNDELAY)
if (fcntl(fd, F_SETFL, FNDELAY) < 0)
{
- msyslog(LOG_ERR, "fcntl(FNDELAY) fails: %m");
+ netsyslog(LOG_ERR, "fcntl(FNDELAY) fails on address %s: %m",
+ stoa(addr));
exit(1);
/*NOTREACHED*/
}
#elif defined(O_NDELAY) /* generally the same as FNDELAY */
if (fcntl(fd, F_SETFL, O_NDELAY) < 0)
{
- msyslog(LOG_ERR, "fcntl(O_NDELAY) fails: %m");
+ netsyslog(LOG_ERR, "fcntl(O_NDELAY) fails on address %s: %m",
+ stoa(addr));
exit(1);
/*NOTREACHED*/
}
#elif defined(FIONBIO)
- if (
# if defined(VMS)
- (ioctl(fd,FIONBIO,&1) < 0)
+ if (ioctl(fd,FIONBIO,&on) < 0)
# elif defined(SYS_WINNT)
- (ioctlsocket(fd,FIONBIO,(u_long *) &on) == SOCKET_ERROR)
+ if (ioctlsocket(fd,FIONBIO,(u_long *) &on) == SOCKET_ERROR)
# else
- (ioctl(fd,FIONBIO,&on) < 0)
+ if (ioctl(fd,FIONBIO,&on) < 0)
# endif
- )
{
- msyslog(LOG_ERR, "ioctl(FIONBIO) fails: %m");
+ netsyslog(LOG_ERR, "ioctl(FIONBIO) fails on address %s: %m",
+ stoa(addr));
exit(1);
/*NOTREACHED*/
}
#elif defined(FIOSNBIO)
if (ioctl(fd,FIOSNBIO,&on) < 0)
{
- msyslog(LOG_ERR, "ioctl(FIOSNBIO) fails: %m");
+ netsyslog(LOG_ERR, "ioctl(FIOSNBIO) fails on address %s: %m",
+ stoa(addr));
exit(1);
/*NOTREACHED*/
}
@@ -1025,7 +1221,8 @@ open_socket(
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
(char *)&off, sizeof(off)))
{
- msyslog(LOG_ERR, "setsockopt SO_REUSEADDR off fails: %m");
+ netsyslog(LOG_ERR, "setsockopt SO_REUSEADDR off fails on address %s: %m",
+ stoa(addr));
}
#ifdef SO_BROADCAST
@@ -1035,7 +1232,8 @@ open_socket(
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
(char *)&on, sizeof(on)))
{
- msyslog(LOG_ERR, "setsockopt(SO_BROADCAST): %m");
+ netsyslog(LOG_ERR, "setsockopt(SO_BROADCAST) on address %s: %m",
+ stoa(addr));
}
}
#endif /* SO_BROADCAST */
@@ -1057,21 +1255,29 @@ open_socket(
*/
static void
close_socket(
- int fd
+ SOCKET fd
)
{
- int i, newmax;
+ SOCKET i, newmax;
(void) closesocket(fd);
+
+ /*
+ * I/O Completion Ports don't care about select and fd_set
+ */
+#ifndef HAVE_IO_COMPLETION_PORT
FD_CLR( (u_int) fd, &activefds);
- if (fd >= maxactivefd) {
+ if (fd == maxactivefd) {
newmax = 0;
for (i = 0; i < maxactivefd; i++)
if (FD_ISSET(i, &activefds))
newmax = i;
maxactivefd = newmax;
}
+#endif
+ delete_socket_from_list(fd);
+
}
@@ -1079,24 +1285,33 @@ close_socket(
* close_file - close a file and remove from the activefd list
* added 1/31/1997 Greg Schueman for Windows NT portability
*/
+#ifdef REFCLOCK
static void
close_file(
- int fd
+ SOCKET fd
)
{
int i, newmax;
(void) close(fd);
+ /*
+ * I/O Completion Ports don't care about select and fd_set
+ */
+#ifndef HAVE_IO_COMPLETION_PORT
FD_CLR( (u_int) fd, &activefds);
- if (fd >= maxactivefd) {
+ if (fd == maxactivefd) {
newmax = 0;
for (i = 0; i < maxactivefd; i++)
if (FD_ISSET(i, &activefds))
newmax = i;
maxactivefd = newmax;
}
+#endif
+ delete_socket_from_list(fd);
+
}
+#endif
/* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */
@@ -1107,7 +1322,7 @@ close_file(
*/
void
sendpkt(
- struct sockaddr_in *dest,
+ struct sockaddr_storage *dest,
struct interface *inter,
int ttl,
struct pkt *pkt,
@@ -1120,7 +1335,7 @@ sendpkt(
#endif /* SYS_WINNT */
/*
- * Send error cache. Empty slots have port == 0
+ * Send error caches. Empty slots have port == 0
* Set ERRORCACHESIZE to 0 to disable
*/
struct cache {
@@ -1128,57 +1343,121 @@ sendpkt(
struct in_addr addr;
};
+#ifdef HAVE_IPV6
+ struct cache6 {
+ u_short port;
+ struct in6_addr addr;
+ };
+#endif /* HAVE_IPV6 */
+
#ifndef ERRORCACHESIZE
#define ERRORCACHESIZE 8
#endif
#if ERRORCACHESIZE > 0
static struct cache badaddrs[ERRORCACHESIZE];
+#ifdef HAVE_IPV6
+ static struct cache6 badaddrs6[ERRORCACHESIZE];
+#endif /* HAVE_IPV6 */
#else
#define badaddrs ((struct cache *)0) /* Only used in empty loops! */
+#ifdef HAVE_IPV6
+#define badaddrs6 ((struct cache6 *)0) /* Only used in empty loops! */
+#endif /* HAVE_IPV6 */
#endif
#ifdef DEBUG
if (debug > 1)
printf("%ssendpkt(fd=%d dst=%s, src=%s, ttl=%d, len=%d)\n",
(ttl >= 0) ? "\tMCAST\t*****" : "",
- inter->fd, ntoa(dest),
- ntoa(&inter->sin), ttl, len);
+ inter->fd, stoa(dest),
+ stoa(&inter->sin), ttl, len);
#endif
#ifdef MCAST
- /*
- * for the moment we use the bcast option to set multicast ttl
- */
- if (ttl > 0 && ttl != inter->last_ttl) {
- char mttl = ttl;
+
+ switch (inter->sin.ss_family) {
+
+ case AF_INET :
/*
- * set the multicast ttl for outgoing packets
+ * for the moment we use the bcast option to set multicast ttl
+ */
+ if (ttl > 0 && ttl != inter->last_ttl) {
+
+ /*
+ * set the multicast ttl for outgoing packets
+ */
+ if (setsockopt(inter->fd, IPPROTO_IP, IP_MULTICAST_TTL,
+ (char *) &ttl, sizeof(ttl)) != 0) {
+ netsyslog(LOG_ERR, "setsockopt IP_MULTICAST_TTL fails on address %s: %m",
+ stoa(&inter->sin));
+ }
+ else
+ inter->last_ttl = ttl;
+ }
+ break;
+
+#ifdef HAVE_IPV6
+ case AF_INET6 :
+
+ /*
+ * for the moment we use the bcast option to set
+ * multicast max hops
*/
- if (setsockopt(inter->fd, IPPROTO_IP, IP_MULTICAST_TTL,
- &mttl, sizeof(mttl)) == -1)
- msyslog(LOG_ERR, "setsockopt IP_MULTICAST_TTL fails: %m");
- else
- inter->last_ttl = ttl;
+ if (ttl > 0 && ttl != inter->last_ttl) {
+
+ /*
+ * set the multicast ttl for outgoing packets
+ */
+ if (setsockopt(inter->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+ &ttl, sizeof(ttl)) == -1)
+ netsyslog(LOG_ERR, "setsockopt IP_MULTICAST_TTL fails on address %s: %m",
+ stoa(&inter->sin));
+ else
+ inter->last_ttl = ttl;
+ }
+ break;
+#endif /* HAVE_IPV6 */
+
+ default :
+ exit(1);
+
}
+
+
#endif /* MCAST */
for (slot = ERRORCACHESIZE; --slot >= 0; )
- if (badaddrs[slot].port == dest->sin_port &&
- badaddrs[slot].addr.s_addr == dest->sin_addr.s_addr)
- break;
+ if(dest->ss_family == AF_INET) {
+ if (badaddrs[slot].port == ((struct sockaddr_in*)dest)->sin_port &&
+ badaddrs[slot].addr.s_addr == ((struct sockaddr_in*)dest)->sin_addr.s_addr)
+ break;
+ }
+#ifdef HAVE_IPV6
+ else if (dest->ss_family == AF_INET6) {
+ if (badaddrs6[slot].port == ((struct sockaddr_in6*)dest)->sin6_port &&
+ badaddrs6[slot].addr.s6_addr == ((struct sockaddr_in6*)dest)->sin6_addr.s6_addr)
+ break;
+ }
+#endif /* HAVE_IPV6 */
+ else exit(1); /* address family not supported yet */
#if defined(HAVE_IO_COMPLETION_PORT)
err = io_completion_port_sendto(inter, pkt, len, dest);
if (err != ERROR_SUCCESS)
#else
- cc = sendto(inter->fd, (char *)pkt, (size_t)len, 0, (struct sockaddr *)dest,
- sizeof(struct sockaddr_in));
+#ifdef SIM
+ cc = srvr_rply(&ntp_node, dest, inter, pkt);
+#else /* SIM */
+ cc = sendto(inter->fd, (char *)pkt, (unsigned int)len, 0, (struct sockaddr *)dest,
+ SOCKLEN(dest));
+#endif /* SIM */
if (cc == -1)
#endif
{
inter->notsent++;
packets_notsent++;
#if defined(HAVE_IO_COMPLETION_PORT)
+ err = WSAGetLastError();
if (err != WSAEWOULDBLOCK && err != WSAENOBUFS && slot < 0)
#else
if (errno != EWOULDBLOCK && errno != ENOBUFS && slot < 0)
@@ -1187,14 +1466,37 @@ sendpkt(
/*
* Remember this, if there's an empty slot
*/
- for (slot = ERRORCACHESIZE; --slot >= 0; )
- if (badaddrs[slot].port == 0)
- {
- badaddrs[slot].port = dest->sin_port;
- badaddrs[slot].addr = dest->sin_addr;
- break;
- }
- msyslog(LOG_ERR, "sendto(%s): %m", ntoa(dest));
+ switch (dest->ss_family) {
+
+ case AF_INET :
+
+ for (slot = ERRORCACHESIZE; --slot >= 0; )
+ if (badaddrs[slot].port == 0)
+ {
+ badaddrs[slot].port = SRCPORT(dest);
+ badaddrs[slot].addr = ((struct sockaddr_in*)dest)->sin_addr;
+ break;
+ }
+ break;
+
+#ifdef HAVE_IPV6
+ case AF_INET6 :
+
+ for (slot = ERRORCACHESIZE; --slot >= 0; )
+ if (badaddrs6[slot].port == 0)
+ {
+ badaddrs6[slot].port = SRCPORT(dest);
+ badaddrs6[slot].addr = ((struct sockaddr_in6*)dest)->sin6_addr;
+ break;
+ }
+ break;
+#endif /* HAVE_IPV6 */
+
+ default :
+ exit(1);
+ }
+
+ netsyslog(LOG_ERR, "sendto(%s): %m", stoa(dest));
}
}
else
@@ -1206,8 +1508,17 @@ sendpkt(
*/
if (slot >= 0)
{
- msyslog(LOG_INFO, "Connection re-established to %s", ntoa(dest));
- badaddrs[slot].port = 0;
+ netsyslog(LOG_INFO, "Connection re-established to %s", stoa(dest));
+ switch (dest->ss_family) {
+ case AF_INET :
+ badaddrs[slot].port = 0;
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6 :
+ badaddrs6[slot].port = 0;
+ break;
+#endif /* HAVE_IPV6 */
+ }
}
}
}
@@ -1249,7 +1560,7 @@ input_handler(
register int i, n;
register struct recvbuf *rb;
register int doing;
- register int fd;
+ register SOCKET fd;
struct timeval tvzero;
int fromlen;
l_fp ts; /* Timestamp at BOselect() gob */
@@ -1315,14 +1626,17 @@ input_handler(
if (rb->recv_length == -1)
{
- msyslog(LOG_ERR, "clock read fd %d: %m", fd);
+ netsyslog(LOG_ERR, "clock read fd %d: %m", fd);
freerecvbuf(rb);
goto select_again;
}
/*
- * Got one. Mark how and when it got here,
- * put it on the full list and do bookkeeping.
+ * Got one. Mark how
+ * and when it got here,
+ * put it on the full
+ * list and do
+ * bookkeeping.
*/
rb->recv_srcclock = rp->srcclock;
rb->dstadr = 0;
@@ -1333,13 +1647,25 @@ input_handler(
if (rp->io_input)
{
/*
- * have direct input routine for refclocks
+ * have direct
+ * input routine
+ * for refclocks
*/
if (rp->io_input(rb) == 0)
{
/*
- * data was consumed - nothing to pass up
- * into block input machine
+ * data
+ * was
+ * consumed
+ * -
+ * nothing
+ * to
+ * pass
+ * up
+ * into
+ * block
+ * input
+ * machine
*/
freerecvbuf(rb);
#if 1
@@ -1360,7 +1686,8 @@ input_handler(
#endif /* REFCLOCK */
/*
- * Loop through the interfaces looking for data to read.
+ * Loop through the interfaces looking for data
+ * to read.
*/
for (i = ninterfaces - 1; (i >= 0) && (n > 0); i--)
{
@@ -1382,9 +1709,12 @@ input_handler(
n--;
/*
- * Get a buffer and read the frame. If we
- * haven't got a buffer, or this is received
- * on the wild card socket, just dump the
+ * Get a buffer and read
+ * the frame. If we
+ * haven't got a buffer,
+ * or this is received
+ * on the wild card
+ * socket, just dump the
* packet.
*/
if (
@@ -1395,23 +1725,24 @@ input_handler(
*/
(free_recvbuffs() == 0)
#else
- ((i == 0) || (free_recvbuffs() == 0))
+ ((i == wildipv4) || (i == wildipv6)||
+ (free_recvbuffs() == 0))
#endif
)
{
char buf[RX_BUFF_SIZE];
- struct sockaddr from;
+ struct sockaddr_storage from;
fromlen = sizeof from;
- (void) recvfrom(fd, buf, sizeof(buf), 0, &from, &fromlen);
+ (void) recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr*)&from, &fromlen);
#ifdef DEBUG
if (debug)
printf("%s on %d(%lu) fd=%d from %s\n",
(i) ? "drop" : "ignore",
i, free_recvbuffs(), fd,
- inet_ntoa(((struct sockaddr_in *) &from)->sin_addr));
+ stoa(&from));
#endif
- if (i == 0)
+ if (i == wildipv4 || i == wildipv6)
packets_ignored++;
else
packets_dropped++;
@@ -1420,7 +1751,7 @@ input_handler(
rb = get_free_recv_buffer();
- fromlen = sizeof(struct sockaddr_in);
+ fromlen = sizeof(struct sockaddr_storage);
rb->recv_length = recvfrom(fd,
(char *)&rb->recv_space,
sizeof(rb->recv_space), 0,
@@ -1439,8 +1770,8 @@ input_handler(
}
else if (rb->recv_length < 0)
{
- msyslog(LOG_ERR, "recvfrom(%s) fd=%d: %m",
- inet_ntoa(rb->recv_srcadr.sin_addr), fd);
+ netsyslog(LOG_ERR, "recvfrom(%s) fd=%d: %m",
+ stoa(&rb->recv_srcadr), fd);
#ifdef DEBUG
if (debug)
printf("input_handler: fd=%d dropped (bad recvfrom)\n", fd);
@@ -1449,12 +1780,18 @@ input_handler(
continue;
}
#ifdef DEBUG
- if (debug > 2)
- printf("input_handler: if=%d fd=%d length %d from %08lx %s\n",
- i, fd, rb->recv_length,
- (u_long)ntohl(rb->recv_srcadr.sin_addr.s_addr) &
- 0x00000000ffffffff,
- inet_ntoa(rb->recv_srcadr.sin_addr));
+ if (debug > 2) {
+ if(rb->recv_srcadr.ss_family == AF_INET)
+ printf("input_handler: if=%d fd=%d length %d from %08lx %s\n",
+ i, fd, rb->recv_length,
+ (u_long)ntohl(((struct sockaddr_in*)&rb->recv_srcadr)->sin_addr.s_addr) &
+ 0x00000000ffffffff,
+ stoa(&rb->recv_srcadr));
+ else
+ printf("input_handler: if=%d fd=%d length %d from %s\n",
+ i, fd, rb->recv_length,
+ stoa(&rb->recv_srcadr));
+ }
#endif
/*
@@ -1467,7 +1804,7 @@ input_handler(
rb->receiver = receive;
add_full_recv_buffer(rb);
-
+
inter_list[i].received++;
packets_received++;
goto select_again;
@@ -1491,19 +1828,20 @@ input_handler(
if (select_count == 0) /* We really had nothing to do */
{
if (debug)
- msyslog(LOG_DEBUG, "input_handler: select() returned 0");
+ netsyslog(LOG_DEBUG, "input_handler: select() returned 0");
--handler_count;
return;
}
/* We've done our work */
get_systime(&ts_e);
/*
- * (ts_e - ts) is the amount of time we spent processing
- * this gob of file descriptors. Log it.
+ * (ts_e - ts) is the amount of time we spent
+ * processing this gob of file descriptors. Log
+ * it.
*/
L_SUB(&ts_e, &ts);
if (debug > 3)
- msyslog(LOG_INFO, "input_handler: Processed a gob of fd's in %s msec", lfptoms(&ts_e, 6));
+ netsyslog(LOG_INFO, "input_handler: Processed a gob of fd's in %s msec", lfptoms(&ts_e, 6));
/* just bail. */
--handler_count;
@@ -1516,8 +1854,11 @@ input_handler(
/*
* extended FAU debugging output
*/
- msyslog(LOG_ERR, "select(%d, %s, 0L, 0L, &0.000000) error: %m",
- maxactivefd+1, fdbits(maxactivefd, &activefds));
+ if (err != EINTR)
+ netsyslog(LOG_ERR,
+ "select(%d, %s, 0L, 0L, &0.0) error: %m",
+ maxactivefd+1,
+ fdbits(maxactivefd, &activefds));
if (err == EBADF) {
int j, b;
@@ -1526,7 +1867,7 @@ input_handler(
if (
(FD_ISSET(j, &fds) && (read(j, &b, 0) == -1))
)
- msyslog(LOG_ERR, "Bad file descriptor %d", j);
+ netsyslog(LOG_ERR, "Bad file descriptor %d", j);
}
--handler_count;
return;
@@ -1538,70 +1879,91 @@ input_handler(
}
#endif
-
/*
* findinterface - find interface corresponding to address
*/
struct interface *
findinterface(
- struct sockaddr_in *addr
+ struct sockaddr_storage *addr
)
{
- int s, rtn, i;
- struct sockaddr_in saddr;
- int saddrlen = sizeof(saddr);
- u_int32 xaddr;
-
+ SOCKET s;
+ int rtn, i;
+ struct sockaddr_storage saddr;
+ int saddrlen = SOCKLEN(addr);
/*
* This is considerably hoke. We open a socket, connect to it
* and slap a getsockname() on it. If anything breaks, as it
* probably will in some j-random knockoff, we just return the
* wildcard interface.
*/
- saddr.sin_family = AF_INET;
- saddr.sin_addr.s_addr = addr->sin_addr.s_addr;
- saddr.sin_port = htons(2000);
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0)
- return (any_interface);
-
- rtn = connect(s, (struct sockaddr *)&saddr, sizeof(saddr));
+ memset(&saddr, 0, sizeof(saddr));
+ saddr.ss_family = addr->ss_family;
+ if(addr->ss_family == AF_INET)
+ memcpy(&((struct sockaddr_in*)&saddr)->sin_addr, &((struct sockaddr_in*)addr)->sin_addr, sizeof(struct in_addr));
+ else if(addr->ss_family == AF_INET6)
+ memcpy(&((struct sockaddr_in6*)&saddr)->sin6_addr, &((struct sockaddr_in6*)addr)->sin6_addr, sizeof(struct in6_addr));
+ ((struct sockaddr_in*)&saddr)->sin_port = htons(2000);
+ s = socket(addr->ss_family, SOCK_DGRAM, 0);
+ if (s == INVALID_SOCKET)
+ return ANY_INTERFACE_CHOOSE(addr);
+
+ rtn = connect(s, (struct sockaddr *)&saddr, SOCKLEN(&saddr));
+#ifndef SYS_WINNT
if (rtn < 0)
- return (any_interface);
+#else
+ if (rtn == SOCKET_ERROR)
+#endif
+ {
+ closesocket(s);
+ return ANY_INTERFACE_CHOOSE(addr);
+ }
rtn = getsockname(s, (struct sockaddr *)&saddr, &saddrlen);
+ closesocket(s);
+#ifndef SYS_WINNT
if (rtn < 0)
- return (any_interface);
-
- close(s);
- xaddr = NSRCADR(&saddr);
- for (i = 1; i < ninterfaces; i++) {
+#else
+ if (rtn == SOCKET_ERROR)
+#endif
+ return ANY_INTERFACE_CHOOSE(addr);
+ for (i = 0; i < ninterfaces; i++) {
+ /*
+ * First look if is the the correct family
+ */
+ if(inter_list[i].sin.ss_family != saddr.ss_family)
+ continue;
/*
* We match the unicast address only.
*/
- if (NSRCADR(&inter_list[i].sin) == xaddr)
+ if (SOCKCMP(&inter_list[i].sin, &saddr))
return (&inter_list[i]);
}
- return (any_interface);
+ return ANY_INTERFACE_CHOOSE(addr);
}
-
/*
* findbcastinter - find broadcast interface corresponding to address
*/
struct interface *
findbcastinter(
- struct sockaddr_in *addr
+ struct sockaddr_storage *addr
)
{
#if !defined(MPE) && (defined(SIOCGIFCONF) || defined(SYS_WINNT))
register int i;
- register u_int32 xaddr;
-
- xaddr = NSRCADR(addr);
- for (i = 1; i < ninterfaces; i++) {
+
+ i = find_addr_in_list(addr);
+ if(i >= 0)
+ return (&inter_list[i]);
+ for (i = 0; i < ninterfaces; i++) {
+ /*
+ * First look if this is the correct family
+ */
+ if(inter_list[i].sin.ss_family != addr->ss_family)
+ continue;
/*
* We match only those interfaces marked as
* broadcastable and either the explicit broadcast
@@ -1610,15 +1972,23 @@ findbcastinter(
*/
if (!(inter_list[i].flags & INT_BROADCAST))
continue;
- if (NSRCADR(&inter_list[i].bcast) == xaddr)
- return (&inter_list[i]);
- if ((NSRCADR(&inter_list[i].sin) &
- NSRCADR(&inter_list[i].mask)) == (xaddr &
- NSRCADR(&inter_list[i].mask)))
- return (&inter_list[i]);
+ if(addr->ss_family == AF_INET) {
+ if (SOCKCMP(&inter_list[i].bcast, addr))
+ return (&inter_list[i]);
+ if ((NSRCADR(&inter_list[i].sin) &
+ NSRCADR(&inter_list[i].mask)) == (NSRCADR(addr) &
+ NSRCADR(&inter_list[i].mask)))
+ return (&inter_list[i]);
+ }
+ else if(addr->ss_family == AF_INET6) {
+ if (SOCKCMP(&inter_list[i].bcast, addr))
+ return (&inter_list[i]);
+ if (SOCKCMP(netof(&inter_list[i].sin), netof(addr)))
+ return (&inter_list[i]);
+ }
}
#endif /* SIOCGIFCONF */
- return (any_interface);
+ return ANY_INTERFACE_CHOOSE(addr);
}
@@ -1659,9 +2029,14 @@ io_addclock_simple(
rio->next = refio;
refio = rio;
+ /*
+ * I/O Completion Ports don't care about select and fd_set
+ */
+#ifndef HAVE_IO_COMPLETION_PORT
if (rio->fd > maxactivefd)
maxactivefd = rio->fd;
FD_SET(rio->fd, &activefds);
+#endif
UNBLOCKIO();
return 1;
}
@@ -1693,16 +2068,21 @@ io_addclock(
# elif defined(HAVE_IO_COMPLETION_PORT)
if (io_completion_port_add_clock_io(rio))
{
+ add_socket_to_list(rio->fd);
refio = rio->next;
UNBLOCKIO();
return 0;
}
# endif
+ /*
+ * I/O Completion Ports don't care about select and fd_set
+ */
+#ifndef HAVE_IO_COMPLETION_PORT
if (rio->fd > maxactivefd)
maxactivefd = rio->fd;
FD_SET(rio->fd, &activefds);
-
+#endif
UNBLOCKIO();
return 1;
}
@@ -1751,12 +2131,127 @@ io_closeclock(
}
#endif /* REFCLOCK */
+ /*
+ * I/O Completion Ports don't care about select and fd_set
+ */
+#ifndef HAVE_IO_COMPLETION_PORT
void
-kill_asyncio(void)
+kill_asyncio(
+ int startfd
+ )
{
- int i;
+ SOCKET i;
BLOCKIO();
- for (i = 0; i <= maxactivefd; i++)
+ for (i = startfd; i <= maxactivefd; i++)
(void)close_socket(i);
}
+#else
+/*
+ * On NT a SOCKET is an unsigned int so we cannot possibly keep it in
+ * an array. So we use one of the ISC_LIST functions to hold the
+ * socket value and use that when we want to enumerate it.
+ */
+void
+kill_asyncio(int startfd)
+{
+ vsock_t *lsock;
+ vsock_t *next;
+
+ BLOCKIO();
+
+ lsock = ISC_LIST_HEAD(sockets_list);
+ while (lsock != NULL) {
+ next = ISC_LIST_NEXT(lsock, link);
+ close_socket(lsock->fd);
+ lsock = next;
+ }
+
+}
+#endif
+/*
+ * Add and delete functions for the list of open sockets
+ */
+void
+add_socket_to_list(SOCKET fd){
+ vsock_t *lsock = malloc(sizeof(vsock_t));
+ lsock->fd = fd;
+
+ ISC_LIST_APPEND(sockets_list, lsock, link);
+}
+void
+delete_socket_from_list(SOCKET fd) {
+
+ vsock_t *next;
+ vsock_t *lsock = ISC_LIST_HEAD(sockets_list);
+
+ while(lsock != NULL) {
+ next = ISC_LIST_NEXT(lsock, link);
+ if(lsock->fd == fd) {
+ ISC_LIST_DEQUEUE(sockets_list, lsock, link);
+ free(lsock);
+ break;
+ }
+ else
+ lsock = next;
+ }
+}
+void
+add_addr_to_list(struct sockaddr_storage *addr, int if_index){
+ remaddr_t *laddr = malloc(sizeof(remaddr_t));
+ memcpy(&laddr->addr, addr, sizeof(addr));
+ laddr->if_index = if_index;
+
+ ISC_LIST_APPEND(remoteaddr_list, laddr, link);
+#ifdef DEBUG
+ if (debug)
+ printf("Added addr %s to list of addresses\n",
+ stoa(addr));
+#endif
+
+
+}
+void
+delete_addr_from_list(struct sockaddr_storage *addr) {
+
+ remaddr_t *next;
+ remaddr_t *laddr = ISC_LIST_HEAD(remoteaddr_list);
+
+ while(laddr != NULL) {
+ next = ISC_LIST_NEXT(laddr, link);
+ if(SOCKCMP(&laddr->addr, addr)) {
+ ISC_LIST_DEQUEUE(remoteaddr_list, laddr, link);
+ free(laddr);
+ break;
+ }
+ else
+ laddr = next;
+ }
+#ifdef DEBUG
+ if (debug)
+ printf("Deleted addr %s from list of addresses\n",
+ stoa(addr));
+#endif
+}
+int
+find_addr_in_list(struct sockaddr_storage *addr) {
+
+ remaddr_t *next;
+ remaddr_t *laddr = ISC_LIST_HEAD(remoteaddr_list);
+#ifdef DEBUG
+ if (debug)
+ printf("Finding addr %s in list of addresses\n",
+ stoa(addr));
+#endif
+
+ while(laddr != NULL) {
+ next = ISC_LIST_NEXT(laddr, link);
+ if(SOCKCMP(&laddr->addr, addr)) {
+ return (laddr->if_index);
+ break;
+ }
+ else
+ laddr = next;
+ }
+ return (-1); /* Not found */
+}
OpenPOWER on IntegriCloud