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.c112
1 files changed, 84 insertions, 28 deletions
diff --git a/contrib/ntp/ntpd/ntp_io.c b/contrib/ntp/ntpd/ntp_io.c
index ee52b1a..55f9ada 100644
--- a/contrib/ntp/ntpd/ntp_io.c
+++ b/contrib/ntp/ntpd/ntp_io.c
@@ -62,10 +62,6 @@
# endif
#endif
-#if defined(HAVE_SIGNALED_IO) && defined(DEBUG_TIMING)
-# undef DEBUG_TIMING
-#endif
-
/*
* setsockopt does not always have the same arg declaration
* across all platforms. If it's not defined we make it empty
@@ -778,6 +774,12 @@ new_interface(
iface->ifnum = sys_ifnum++;
iface->starttime = current_time;
+# ifdef HAVE_IO_COMPLETION_PORT
+ if (!io_completion_port_add_interface(iface)) {
+ msyslog(LOG_EMERG, "cannot register interface with IO engine -- will exit now");
+ exit(1);
+ }
+# endif
return iface;
}
@@ -785,11 +787,14 @@ new_interface(
/*
* return interface storage into free memory pool
*/
-static inline void
+static void
delete_interface(
endpt *ep
)
{
+# ifdef HAVE_IO_COMPLETION_PORT
+ io_completion_port_remove_interface(ep);
+# endif
free(ep);
}
@@ -1007,6 +1012,9 @@ remove_interface(
ep->sent,
ep->notsent,
current_time - ep->starttime);
+# ifdef HAVE_IO_COMPLETION_PORT
+ io_completion_port_remove_socket(ep->fd, ep);
+# endif
close_and_delete_fd_from_list(ep->fd);
ep->fd = INVALID_SOCKET;
}
@@ -1015,10 +1023,15 @@ remove_interface(
msyslog(LOG_INFO,
"stop listening for broadcasts to %s on interface #%d %s",
stoa(&ep->bcast), ep->ifnum, ep->name);
+# ifdef HAVE_IO_COMPLETION_PORT
+ io_completion_port_remove_socket(ep->bfd, ep);
+# endif
close_and_delete_fd_from_list(ep->bfd);
ep->bfd = INVALID_SOCKET;
- ep->flags &= ~INT_BCASTOPEN;
}
+# ifdef HAVE_IO_COMPLETION_PORT
+ io_completion_port_remove_interface(ep);
+# endif
ninterfaces--;
mon_clearinterface(ep);
@@ -2569,7 +2582,7 @@ io_setbclient(void)
continue;
/* Only IPv4 addresses are valid for broadcast */
- REQUIRE(IS_IPV4(&interf->sin));
+ REQUIRE(IS_IPV4(&interf->bcast));
/* Do we already have the broadcast address open? */
if (interf->flags & INT_BCASTOPEN) {
@@ -2597,13 +2610,31 @@ io_setbclient(void)
msyslog(LOG_INFO,
"Listen for broadcasts to %s on interface #%d %s",
stoa(&interf->bcast), interf->ifnum, interf->name);
- } else {
- /* silently ignore EADDRINUSE as we probably opened
- the socket already for an address in the same network */
- if (errno != EADDRINUSE)
- msyslog(LOG_INFO,
- "failed to listen for broadcasts to %s on interface #%d %s",
- stoa(&interf->bcast), interf->ifnum, interf->name);
+ } else switch (errno) {
+ /* Silently ignore EADDRINUSE as we probably
+ * opened the socket already for an address in
+ * the same network */
+ case EADDRINUSE:
+ /* Some systems cannot bind a socket to a broadcast
+ * address, as that is not a valid host address. */
+ case EADDRNOTAVAIL:
+# ifdef SYS_WINNT /*TODO: use for other systems, too? */
+ /* avoid recurrence here -- if we already have a
+ * regular socket, it's quite useless to try this
+ * again.
+ */
+ if (interf->fd != INVALID_SOCKET) {
+ interf->flags |= INT_BCASTOPEN;
+ nif++;
+ }
+# endif
+ break;
+
+ default:
+ msyslog(LOG_INFO,
+ "failed to listen for broadcasts to %s on interface #%d %s",
+ stoa(&interf->bcast), interf->ifnum, interf->name);
+ break;
}
}
set_reuseaddr(0);
@@ -2641,10 +2672,13 @@ io_unsetbclient(void)
msyslog(LOG_INFO,
"stop listening for broadcasts to %s on interface #%d %s",
stoa(&ep->bcast), ep->ifnum, ep->name);
+# ifdef HAVE_IO_COMPLETION_PORT
+ io_completion_port_remove_socket(ep->bfd, ep);
+# endif
close_and_delete_fd_from_list(ep->bfd);
ep->bfd = INVALID_SOCKET;
- ep->flags &= ~INT_BCASTOPEN;
}
+ ep->flags &= ~INT_BCASTOPEN;
}
broadcast_client_enabled = ISC_FALSE;
}
@@ -3020,11 +3054,11 @@ open_socket(
fcntl(fd, F_GETFL, 0)));
#endif /* SYS_WINNT || VMS */
-#if defined (HAVE_IO_COMPLETION_PORT)
+#if defined(HAVE_IO_COMPLETION_PORT)
/*
* Add the socket to the completion port
*/
- if (io_completion_port_add_socket(fd, interf)) {
+ if (!io_completion_port_add_socket(fd, interf, bcast)) {
msyslog(LOG_ERR, "unable to set up io completion port - EXITING");
exit(1);
}
@@ -3033,10 +3067,6 @@ open_socket(
}
-#ifdef SYS_WINNT
-#define sendto(fd, buf, len, flags, dest, destsz) \
- io_completion_port_sendto(fd, buf, len, (sockaddr_u *)(dest))
-#endif
/* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */
/*
@@ -3124,6 +3154,9 @@ sendpkt(
#ifdef SIM
cc = simulate_server(dest, src, pkt);
+#elif defined(HAVE_IO_COMPLETION_PORT)
+ cc = io_completion_port_sendto(src, src->fd, pkt,
+ (size_t)len, (sockaddr_u *)&dest->sa);
#else
cc = sendto(src->fd, (char *)pkt, (u_int)len, 0,
&dest->sa, SOCKLEN(dest));
@@ -3141,7 +3174,8 @@ sendpkt(
}
-#if !defined(HAVE_IO_COMPLETION_PORT) && !defined(HAVE_SIGNALED_IO)
+#if !defined(HAVE_IO_COMPLETION_PORT)
+#if !defined(HAVE_SIGNALED_IO)
/*
* fdbits - generate ascii representation of fd_set (FAU debug support)
* HFDF format - highest fd first.
@@ -3450,6 +3484,18 @@ read_network_packet(
DPRINTF(3, ("read_network_packet: fd=%d length %d from %s\n",
fd, buflen, stoa(&rb->recv_srcadr)));
+#ifdef ENABLE_BUG3020_FIX
+ if (ISREFCLOCKADR(&rb->recv_srcadr)) {
+ msyslog(LOG_ERR, "recvfrom(%s) fd=%d: refclock srcadr on a network interface!",
+ stoa(&rb->recv_srcadr), fd);
+ DPRINTF(1, ("read_network_packet: fd=%d dropped (refclock srcadr))\n",
+ fd));
+ packets_dropped++;
+ freerecvbuf(rb);
+ return (buflen);
+ }
+#endif
+
/*
** Bug 2672: Some OSes (MacOSX and Linux) don't block spoofed ::1
*/
@@ -3789,7 +3835,7 @@ input_handler_scan(
lfptoms(&ts_e, 6));
#endif /* DEBUG_TIMING */
}
-
+#endif /* !HAVE_IO_COMPLETION_PORT */
/*
* find an interface suitable for the src address
@@ -4279,7 +4325,7 @@ io_addclock(
return 0;
}
# elif defined(HAVE_IO_COMPLETION_PORT)
- if (io_completion_port_add_clock_io(rio)) {
+ if (!io_completion_port_add_clock_io(rio)) {
UNBLOCKIO();
return 0;
}
@@ -4318,13 +4364,23 @@ io_closeclock(
rio->active = FALSE;
UNLINK_SLIST(unlinked, refio, rio, next, struct refclockio);
if (NULL != unlinked) {
- purge_recv_buffers_for_fd(rio->fd);
- /*
- * Close the descriptor.
+ /* Close the descriptor. The order of operations is
+ * important here in case of async / overlapped IO:
+ * only after we have removed the clock from the
+ * IO completion port we can be sure no further
+ * input is queued. So...
+ * - we first disable feeding to the queu by removing
+ * the clock from the IO engine
+ * - close the file (which brings down any IO on it)
+ * - clear the buffer from results for this fd
*/
+# ifdef HAVE_IO_COMPLETION_PORT
+ io_completion_port_remove_clock_io(rio);
+# endif
close_and_delete_fd_from_list(rio->fd);
+ purge_recv_buffers_for_fd(rio->fd);
+ rio->fd = -1;
}
- rio->fd = -1;
UNBLOCKIO();
}
OpenPOWER on IntegriCloud