ntp_io.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* Copyright 1996, 1999-2002 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* was shamelessly stolen from ntpd.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef SYS_SOLARIS
# define FD_SETSIZE 65536
#endif
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#ifdef HAVE_SYS_PARAM_H
#endif /* HAVE_SYS_PARAM_H */
#ifdef HAVE_SYS_TIME_H
#endif
#ifdef HAVE_NETINET_IN_H
#endif
#ifdef HAVE_SYS_IOCTL_H
#endif
#ifdef HAVE_SYS_SOCKIO_H /* UXPV: SIOC* #defines (Frank Vance <fvance@waii.com>) */
#endif
#if _BSDI_VERSION >= 199510
# include <ifaddrs.h>
#endif
#include "ntpd.h"
#include "ntp_select.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_if.h"
#include "ntp_stdlib.h"
#if defined (SYS_SOLARIS)
# include <sys/resource.h>
# define HAVE_RLIMIT
#endif
#if defined (SIOCGIFNUM) && defined (SYS_SOLARIS)
# include <assert.h>
#endif
#if defined(VMS) /* most likely UCX-specific */
/* "un*x"-compatible names for some items in UCX$INETDEF.H */
/* structure used in SIOCGIFCONF request (after [KSR] OSF/1) */
struct ifconf {
int ifc_len; /* size of buffer */
union {
} ifc_ifcu;
};
#endif /* VMS */
#if defined(USE_TTY_SIGPOLL) || defined(USE_UDP_SIGPOLL)
# endif
# include <stropts.h>
#endif
/*
* We do asynchronous input using the SIGIO facility. A number of
* recvbuf buffers are preallocated for input. In the signal
* handler we poll to see which sockets are ready and read the
* packets from them into the recvbuf's along with a time stamp and
* an indication of the source host and the interface it was received
* through. This allows us to get as accurate receive time stamps
* as possible independent of other processing going on.
*
* We watch the number of recvbufs available to the signal handler
* and allocate more when this number drops below the low water
* mark. If the signal handler should run out of buffers in the
* interim it will drop incoming frames, the idea being that it is
* better to drop a packet than to be inaccurate.
*/
/*
* Block the interrupt, for critical sections.
*/
#if defined(HAVE_SIGNALED_IO)
static int sigio_block_count = 0;
# define BLOCKIO() ((void) block_sigio())
# define UNBLOCKIO() ((void) unblock_sigio())
#else
# define BLOCKIO()
# define UNBLOCKIO()
#endif
/*
* recvbuf memory management
*/
/*
* Memory allocation
*/
/*
* Other statistics of possible interest
*/
/*
* Interface stuff
*/
#define DYN_IFLIST \
(defined (SIOCGIFNUM) && !defined (STREAMS_TLI))
#if DYN_IFLIST && defined (DEBUG)
#else
#define DYN_IFL_ASSERT(IGNORED)
#endif
#if DYN_IFLIST
static struct interface *inter_list;
static int ninter_alloc = 0; /* # of if slots allocated */
#else
#endif
static int ninterfaces;
#ifdef REFCLOCK
/*
* Refclock stuff. We keep a chain of structures with data concerning
* the guys we are doing I/O for.
*/
static struct refclockio *refio;
#endif /* REFCLOCK */
/*
* File descriptor masks etc. for call to select
*/
int maxactivefd;
/*
* Imported from ntp_timer.c
*/
extern u_long current_time;
#ifndef SYS_WINNT
extern int errno;
#endif /* SYS_WINNT */
extern int debug;
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));
#ifdef HAVE_SIGNALED_IO
static int init_clock_sig P((struct refclockio *));
static void init_socket_sig P((int));
static RETSIGTYPE sigio_handler P((int));
static void block_sigio P((void));
static void unblock_sigio P((void));
static void set_signal P((void));
#endif /* HAVE_SIGNALED_IO */
#ifndef STREAMS_TLI
# ifndef SYS_WINNT
# endif /* SYS_WINNT */
#endif /* STREAMS_TLI */
#ifdef HAVE_RLIMIT
/*
* Raise the fd limit to its maximum
*/
static void
{
struct rlimit r;
return;
}
}
#endif
/*
* init_io - initialize I/O data structures and call socket creation routine
*/
void
init_io()
{
register int i;
#ifdef SYS_WINNT
#endif /* SYS_WINNT */
/*
* Init buffer free list and stat counters
*/
freelist = 0;
for (i = 0; i < RECV_INIT; i++)
{
freelist = &initial_bufs[i];
}
fulllist = 0;
full_recvbufs = lowater_additions = 0;
packets_dropped = packets_received = 0;
packets_ignored = 0;
packets_sent = packets_notsent = 0;
handler_calls = handler_pkts = 0;
io_timereset = 0;
loopback_interface = 0;
#ifdef REFCLOCK
refio = 0;
#endif
#if defined(HAVE_SIGNALED_IO)
(void) set_signal();
#endif
#ifdef SYS_WINNT
{
exit(1);
}
#endif /* SYS_WINNT */
#ifdef HAVE_RLIMIT
/* Up the soft file descriptor limit to the system maximum */
max_fdlimit();
#endif
/*
* Create the sockets
*/
#ifdef DEBUG
if (debug)
#endif
}
/*
* create_sockets - create a socket for each interface plus a default
* socket for when we don't know where to send
*/
static int
{
#if _BSDI_VERSION >= 199510
int i, j;
struct sockaddr_in resmask;
#if _BSDI_VERSION < 199701
int num_if;
#endif
#else /* _BSDI_VERSION >= 199510 */
# ifdef STREAMS_TLI
# endif /* STREAMS_TLI */
# if DYN_IFLIST
char *buf;
int ifnum;
# else
# endif
struct sockaddr_in resmask;
#endif /* _BSDI_VERSION >= 199510 */
#ifdef DEBUG
if (debug)
#endif
exit(1);
}
#if DYN_IFLIST
exit(1);
}
/*
* One entry is later added to the table for each mcast net, and there
* is a catch-all entry in inter_list[0]. So add a few extra entries
* up front. In the general case (one mcast net) later extension of
* the table won't be necessary.
*/
#ifdef DEBUG
if (debug > 2)
sizeof (*inter_list) * ninter_alloc);
#endif
exit (1);
}
#endif
/*
* create pseudo-interface with wildcard address
*/
sizeof(inter_list[0].name));
inter_list[0].received = 0;
inter_list[0].sent = 0;
inter_list[0].notsent = 0;
#if _BSDI_VERSION >= 199510
#if _BSDI_VERSION >= 199701
if (getifaddrs(&ifaddrs) < 0)
{
exit(1);
}
i = 1;
#else
{
exit(1);
}
i = 1;
#endif
{
struct sockaddr_in *sin;
continue;
continue;
continue;
inter_list[i].flags = 0;
{
if (loopback_interface == NULL
loopback_interface = &inter_list[i];
}
{
}
{
}
else
{
}
/*
* 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++)
{
inter_list[j] = inter_list[i];
break;
}
if (j == i)
i++;
}
#else /* _BSDI_VERSION >= 199510 */
i = 1;
# ifdef STREAMS_TLI
{
exit(1);
}
# ifdef SIZE_RETURNED_IN_BUFFER
# else /* not SIZE_RETURNED_IN_BUFFER */
# endif /* not SIZE_RETURNED_IN_BUFFER */
# else /* not STREAMS_TLI */
# if DYN_IFLIST
exit(1);
}
# else /* ! DYN_IFLIST */
# endif /* DYN_IFLIST */
# ifndef SYS_WINNT
# else
if (get_winnt_interfaces(&ifc) < 0)
# endif /* SYS_WINNT */
{
exit(1);
}
# endif /* not STREAMS_TLI */
{
# ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
# endif
n -= size;
if
# ifdef VMS /* VMS+UCX */
# else
# endif /* VMS+UCX */
continue;
# ifndef SYS_WINNT /* no interface flags on NT */
# ifdef STREAMS_TLI
{
continue;
}
# else /* not STREAMS_TLI */
{
continue;
}
# endif /* not STREAMS_TLI */
continue;
inter_list[i].flags = 0;
# endif /* not SYS_WINNT */
# if !defined(SUN_3_3_STINKS)
if (
# if defined(IFF_LOCAL_LOOPBACK) /* defined(SYS_HPUX) && (SYS_HPUX < 8) */
# elif defined(IFF_LOOPBACK)
# else /* not IFF_LOCAL_LOOPBACK and not IFF_LOOPBACK */
/* test against 127.0.0.1 (yuck!!) */
# endif /* not IFF_LOCAL_LOOPBACK and not IFF_LOOPBACK */
)
{
# ifndef SYS_WINNT
# 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
{
continue;
}
# else /* not STREAMS_TLI */
{
continue;
}
# endif /* not STREAMS_TLI */
# endif /* not SYS_WINNT */
#endif /* 0 */
sizeof(inter_list[i].name));
# if defined(SUN_3_3_STINKS)
/*
* Oh, barf! I'm too disgusted to even explain this
*/
{
if (loopback_interface == 0)
loopback_interface = &inter_list[i];
}
# endif /* SUN_3_3_STINKS */
# ifndef SYS_WINNT /* no interface flags on NT */
{
# ifdef STREAMS_TLI
{
exit(1);
}
# else /* not STREAMS_TLI */
{
exit(1);
}
# endif /* not STREAMS_TLI */
# ifndef ifr_broadaddr
inter_list[i].bcast =
# else
inter_list[i].bcast =
# endif /* ifr_broadaddr */
}
# ifdef STREAMS_TLI
{
exit(1);
}
# else /* not STREAMS_TLI */
{
exit(1);
}
# endif /* not STREAMS_TLI */
# 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++)
{
break;
}
if (j == i)
i++;
}
#endif /* _BSDI_VERSION >= 199510 */
ninterfaces = i;
maxactivefd = 0;
for (i = 0; i < ninterfaces; i++)
{
inter_list[i].fd =
}
/*
* 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 defined(MCAST)
/*
* enable possible multicast reception on the broadcast socket
*/
#endif /* MCAST */
/*
* Blacklist all bound interface addresses
*/
for (i = 1; i < ninterfaces; i++)
any_interface = &inter_list[0];
#ifdef DEBUG
if (debug > 2)
{
for (i = 0; i < ninterfaces; i++)
{
printf("interface %d: fd=%d, bfd=%d, name=%.8s, flags=0x%x\n",
i,
inter_list[i].fd,
inter_list[i].bfd,
inter_list[i].name,
inter_list[i].flags);
/* Leave these as three printf calls. */
printf(" sin=%s",
printf(" bcast=%s,",
printf(" mask=%s\n",
}
}
#endif
#if DYN_IFLIST
#endif
return ninterfaces;
}
/*
* io_setbclient - open the broadcast client sockets
*/
void
{
int i;
for (i = 1; i < ninterfaces; i++)
{
continue;
continue;
#ifdef SYS_SOLARIS
#endif
#ifdef OPEN_BCAST_SOCKET /* Was: !SYS_DOMAINOS && !SYS_LINUX */
#endif
}
}
/* Make sure there is at least N+1 elements in if list */
static void
extend_iflist(int n)
{
#if DYN_IFLIST
if (n >= ninter_alloc) {
int old_n = ninter_alloc;
/*
* Only called to add a few extra entries, so keep
* the extensions fairly small.
*/
ninter_alloc = n + 32;
# ifdef DEBUG
if (debug > 2)
printf("realloc inter_list[%d], %d bytes\n",
# endif
if (inter_list == NULL) {
exit (1);
}
/* Zero the part added */
(ninter_alloc - old_n));
}
#endif /* DYN_IFLIST */
}
/*
* io_multicast_add() - add multicast group address
*/
void
{
#ifdef MCAST
int i = ninterfaces; /* Use the next interface */
int s;
struct sockaddr_in *sinp;
{
"cannot add multicast address %s as it is not class D",
return;
}
for (i = 0; i < ninterfaces; i++)
{
/* Already have this address */
/* found a free slot */
inter_list[i].flags == 0) break;
}
extend_iflist(i);
/* Try opening a socket for the specified class D address */
/* This works under SunOS 4.x, but not OSF1 .. :-( */
if (s < 0)
{
i = 0;
/* HACK ! -- stuff in an address */
}
else
{
inter_list[i].fd = s;
sizeof(inter_list[i].name));
}
/*
* enable reception of multicast packets
*/
"setsockopt IP_ADD_MEMBERSHIP fails: %m for %x / %x (%s)",
#else /* MCAST */
#endif /* MCAST */
}
/*
* io_unsetbclient - close the broadcast client sockets
*/
void
{
int i;
for (i = 1; i < ninterfaces; i++)
{
continue;
}
}
/*
* io_multicast_del() - delete multicast group address
*/
void
{
#ifdef MCAST
int i;
struct sockaddr_in sinaddr;
{
return;
}
/*
* Disable reception of multicast packets
*/
for (i = 0; i < ninterfaces; i++)
{
continue;
if (!(inter_list[i].fd < 0))
continue;
continue;
if (i != 0)
{
/* we have an explicit fd, so we can close it */
}
else
{
/* We are sharing "any address" port :-( Don't close it! */
/* This is **WRONG** -- there may be others ! */
/* There should be a count of users ... */
}
}
#else /* not MCAST */
#endif /* not MCAST */
}
/*
* open_socket - open a socket, returning the file descriptor
*/
static int
struct sockaddr_in *addr;
int flags;
int turn_off_reuse;
{
int fd;
/* create a datagram (UDP) socket */
#ifndef SYS_WINNT
< 0
#else
#endif /* SYS_WINNT */
)
{
exit(1);
/*NOTREACHED*/
}
/* set SO_REUSEADDR since we will be binding the same port
number on each interface */
{
}
/*
* bind the local address.
*/
{
char buff[160];
"bind() fd %d, family %d, port %d, addr %08lx, in_classd=%d flags=%d fails: %%m",
/*
* soft fail if opening a class D address
*/
return -1;
exit(1);
}
#ifdef DEBUG
if (debug)
printf("bind() fd %d, family %d, port %d, addr %08lx, flags=%d\n",
fd,
flags);
#endif
if (fd > maxactivefd)
maxactivefd = fd;
/*
* set non-blocking,
*/
#ifdef USE_FIONBIO
/* in vxWorks we use FIONBIO, but the others are defined for old systems, so
* all hell breaks loose if we leave them defined
*/
#endif
#if defined(O_NONBLOCK) /* POSIX */
{
exit(1);
/*NOTREACHED*/
}
{
exit(1);
/*NOTREACHED*/
}
{
exit(1);
/*NOTREACHED*/
}
# if defined(VMS)
# else
# endif
{
exit(1);
/*NOTREACHED*/
}
{
exit(1);
/*NOTREACHED*/
}
#else
# include "Bletch: Need non blocking I/O!"
#endif
#ifdef HAVE_SIGNALED_IO
#endif /* not HAVE_SIGNALED_IO */
/*
* Turn off the SO_REUSEADDR socket option. It apparently
* causes heartburn on systems with multicast IP installed.
* On normal systems it only gets looked at when the address
* is being bound anyway..
*/
if (turn_off_reuse)
{
}
#ifdef SO_BROADCAST
/* if this interface can support broadcast, set SO_BROADCAST */
if (flags & INT_BROADCAST)
{
{
}
}
#endif /* SO_BROADCAST */
# ifdef DEBUG
if (debug > 1)
# endif
#endif /* SYS_WINNT || VMS */
return fd;
}
/*
* close_socket - close a socket and remove from the activefd list
*/
static void
int fd;
{
int i, newmax;
(void) closesocket(fd);
if (fd >= maxactivefd)
{
newmax = 0;
for (i = 0; i < maxactivefd; i++)
newmax = i;
}
}
/*
* close_file - close a file and remove from the activefd list
* added 1/31/1997 Greg Schueman for Windows NT portability
*/
static void
int fd;
{
int i, newmax;
if (fd >= maxactivefd)
{
newmax = 0;
for (i = 0; i < maxactivefd; i++)
newmax = i;
}
}
/*
* findbcastinter - find broadcast interface corresponding to address
*/
struct interface *
struct sockaddr_in *addr;
{
#ifdef SIOCGIFCONF
register int i;
for (i = 1; i < ninterfaces; i++)
{
continue;
return &inter_list[i];
return &inter_list[i];
}
#endif /* SIOCGIFCONF */
return any_interface;
}
/* XXX ELIMINATE getrecvbufs (almost) identical to ntpdate.c, ntptrace.c, ntp_io.c */
/*
* getrecvbufs - get receive buffers which have data in them
*
* ***N.B. must be called with SIGIO blocked***
*/
struct recvbuf *
{
static struct timeval timelogged = {0, 0};
#ifdef DEBUG
if (debug > 4)
printf("getrecvbufs: %ld handler interrupts, %ld frames\n",
#endif
if (full_recvbufs == 0)
{
#ifdef DEBUG
if (debug > 4)
printf("getrecvbufs called, no action here\n");
#endif
return (struct recvbuf *)0; /* nothing has arrived */
}
/*
* Get the fulllist chain and mark it empty
*/
#ifdef DEBUG
if (debug > 4)
#endif
fulllist = 0;
full_recvbufs = 0;
/*
* Check to see if we're below the low water mark.
*/
if (free_recvbufs <= RECV_LOWAT)
{
register int i;
if (total_recvbufs >= RECV_TOOMANY)
{
{
" multicast packets than expected: is network OK?");
}
}
else
{
for (i = 0; i < RECV_INC; i++)
{
buf++;
}
}
}
/*
* Return the chain
*/
return rb;
}
/* XXX ELIMINATE freerecvbuf (almost) identical to ntpdate.c, ntptrace.c, ntp_io.c */
/*
* freerecvbuf - make a single recvbuf available for reuse
*/
void
{
BLOCKIO();
UNBLOCKIO();
}
/* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */
/*
* sendpkt - send a packet to the specified destination. Maintain a
* send error cache so that only the first consecutive error for a
* destination is logged.
*/
void
struct sockaddr_in *dest;
int ttl;
int len;
{
#ifdef SYS_WINNT
#endif /* SYS_WINNT */
/*
* Send error cache. Empty slots have port == 0
* Set ERRORCACHESIZE to 0 to disable
*/
struct cache {
};
#ifndef ERRORCACHESIZE
#define ERRORCACHESIZE 8
#endif
#if ERRORCACHESIZE > 0
#else
#endif
#ifdef DEBUG
if (debug)
printf("%ssendpkt(fd=%d %s, %s, ttl=%d, %d)\n",
#endif
#ifdef MCAST
/* for the moment we use the bcast option to set multicast ttl */
{
/* set the multicast ttl for outgoing packets */
{
}
}
#endif /* MCAST */
break;
sizeof(struct sockaddr_in));
if (cc == -1)
{
#ifndef SYS_WINNT
#else
err = WSAGetLastError();
#endif /* SYS_WINNT */
{
/*
* Remember this, if there's an empty slot
*/
{
break;
}
}
}
else
{
packets_sent++;
/*
* He's not bad any more
*/
if (slot >= 0)
{
}
}
}
/*
* fdbits - generate ascii representation of fd_set (FAU debug support)
* HFDF format - highest fd first.
*/
static char *
int count;
{
static int buflen = 0;
char *buf;
exit (1);
}
}
while (count >= 0)
{
count--;
}
*buf = '\0';
return buffer;
}
/*
* input_handler - receive packets asynchronously
*/
void
{
register int i, n;
register int doing;
register int fd;
int select_count = 0;
#if 0
int first = 1;
#endif
static int handler_count = 0;
if (handler_count != 1)
for (;;)
{
/*
* Do a poll to see who has data
*/
/*
* If we have something to do, freeze a timestamp.
* See below for the other cases (nothing (left) to do or error)
*/
{
#if 0
first = 0;
#endif
++select_count;
#if 1
++handler_pkts;
#else
handler_pkts += n;
#endif
#ifdef REFCLOCK
/*
* Check out the reference clocks first, if any
*/
if (refio != 0)
{
register struct refclockio *rp;
{
{
n--;
if (free_recvbufs == 0)
{
char buf[RX_BUFF_SIZE];
#ifndef SYS_WINNT
#else
#endif /* SYS_WINNT */
#if 1
goto select_again;
#else
continue;
#endif
}
#ifndef SYS_WINNT
rb->recv_length =
#else /* SYS_WINNT */
#endif /* SYS_WINNT */
;
{
#if 1
goto select_again;
#else
continue;
#endif
}
/*
* Got one. Mark how and when it got here,
* put it on the full list and do bookkeeping.
*/
if (fulllist == 0)
{
}
else
{
}
}
}
}
#endif /* REFCLOCK */
/*
* Loop through the interfaces looking for data to read.
*/
for (i = ninterfaces - 1; (i >= 0) && (n > 0); i--)
{
{
if (doing == 0)
{
}
else
{
break;
}
if (fd < 0) continue;
{
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
* packet.
*/
if (
#ifndef SYS_WINNT
(!(free_recvbufs && (i == 0) &&
#else
* i is 0, and INT_MULTICAST flag is not set.
*/
#endif /* SYS_WINNT */
)
{
if (
#ifdef UDP_WILDCARD_DELIVERY
/*
* these guys manage to put properly addressed
* packets into the wildcard queue
*/
(free_recvbufs == 0)
#else
((i == 0) || (free_recvbufs == 0))
#endif
)
{
char buf[RX_BUFF_SIZE];
sizeof(buf), 0,
#ifdef DEBUG
if (debug)
printf("%s on %d(%lu) fd=%d from %s\n",
(i) ? "drop" : "ignore",
i, free_recvbufs, fd,
#endif
if (i == 0)
else
#if 1
goto select_again;
#else
continue;
#endif
}
}
fromlen = sizeof(struct sockaddr_in);
(char *)&rb->recv_space,
sizeof(rb->recv_space), 0,
&fromlen);
if (rb->recv_length > 0)
{
}
else if (rb->recv_length == 0
#ifdef EWOULDBLOCK
|| errno==EWOULDBLOCK
#endif
#ifdef EAGAIN
#endif
)
continue;
else
{
#ifdef DEBUG
if (debug)
printf("input_handler: fd=%d dropped (bad recvfrom): %s\n",
#endif
continue;
}
#ifdef DEBUG
if (debug)
printf("input_handler: fd=%d length %d from %08lx %s\n",
0x00000000ffffffff,
#endif
/*
* Got one. Mark how and when it got here,
* put it on the full list and do bookkeeping.
*/
if (fulllist == 0)
{
}
else
{
}
inter_list[i].received++;
goto select_again;
}
/* Check more interfaces */
}
}
/*
* Done everything from that select. Poll again.
*/
}
/*
* If nothing more to do, try again.
* If nothing to do, just return.
* If an error occurred, complain and return.
*/
if (n == 0)
{
if (select_count == 0) /* We really had nothing to do */
{
if (debug)
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.
*/
if (debug > 3)
#if 0
/*
* We'll re-start the for(;;) loop now.
* Use the ending timestamp as the received timestamp
*/
#else
/* No, for now just bail. */
return;
#endif
}
else if (n == -1)
{
#ifndef SYS_WINNT
#else
#endif /* SYS_WINNT */
/*
* extended FAU debugging output
*/
if (
#ifndef SYS_WINNT
#else
#endif /* SYS_WINNT */
)
{
int i, b;
for (i = 0; i <= maxactivefd; i++)
if (
#ifndef SYS_WINNT
#else
#endif /* SYS_WINNT */
)
}
return;
}
}
#ifndef SYS_SOLARIS
return;
#endif
}
/*
* findinterface - utility used by other modules to find an interface
* given an address.
*/
struct interface *
struct sockaddr_in *addr;
{
register int i;
/*
* Just match the address portion.
*/
for (i = 0; i < ninterfaces; i++)
{
return &inter_list[i];
}
return (struct interface *)0;
}
/*
* io_clr_stats - clear I/O module statistics
*/
void
{
packets_dropped = 0;
packets_ignored = 0;
packets_received = 0;
packets_sent = 0;
packets_notsent = 0;
handler_calls = 0;
handler_pkts = 0;
}
#ifdef REFCLOCK
/*
* This is a hack so that I don't have to fool with these ioctls in the
* pps driver ... we are already non-blocking and turn on SIGIO thru
* another mechanisim
*/
int
struct refclockio *rio;
{
BLOCKIO();
/*
* Stuff the I/O structure in the list and mark the descriptor
* in use. There is a harmless (I hope) race condition here.
*/
UNBLOCKIO();
return 1;
}
/*
* io_addclock - add a reference clock to the list and arrange that we
* get SIGIO interrupts from it.
*/
int
struct refclockio *rio;
{
BLOCKIO();
/*
* Stuff the I/O structure in the list and mark the descriptor
* in use. There is a harmless (I hope) race condition here.
*/
# ifdef HAVE_SIGNALED_IO
if (init_clock_sig(rio))
{
UNBLOCKIO();
return 0;
}
# endif
UNBLOCKIO();
return 1;
}
/*
* io_closeclock - close the clock in the I/O structure given
*/
void
struct refclockio *rio;
{
/*
* Remove structure from the list
*/
{
}
else
{
register struct refclockio *rp;
{
break;
}
if (rp == 0)
{
/*
* Internal error. Report it.
*/
"internal error: refclockio structure not found");
return;
}
}
/*
* Close the descriptor.
*/
}
#endif /* REFCLOCK */
/*
* SIGPOLL and SIGIO ROUTINES.
*/
#ifdef HAVE_SIGNALED_IO
/*
* Some systems (MOST) define SIGPOLL == SIGIO, others SIGIO == SIGPOLL, and
* a few have separate SIGIO and SIGPOLL signals. This code checks for the
* SIGIO == SIGPOLL case at compile time.
* Do not defined USE_SIGPOLL or USE_SIGIO.
* these are interal only to ntp_io.c!
*/
# if defined(USE_SIGPOLL)
# endif
# if defined(USE_SIGIO)
# endif
# if defined(USE_TTY_SIGPOLL) || defined(USE_UDP_SIGPOLL)
# define USE_SIGPOLL
# endif
# if !defined(USE_TTY_SIGPOLL) || !defined(USE_UDP_SIGPOLL)
# define USE_SIGIO
# endif
# if defined(USE_SIGIO) && defined(USE_SIGPOLL)
# define USE_SIGIO
# endif /* SIGIO == SIGPOLL */
# endif /* USE_SIGIO && USE_SIGIO */
/*
* TTY initialization routines.
*/
static int
struct refclockio *rio;
# ifdef USE_TTY_SIGPOLL
{
/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
{
"init_clock_sig: ioctl(I_SETSIG, S_INPUT) failed: %m");
return 1;
}
return 0;
}
# else
/*
* Special cases first!
*/
/* Was: defined(SYS_HPUX) */
#define CLOCK_DONE
{
/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
{
exit(1);
/*NOTREACHED*/
}
/*
* set non-blocking, async I/O on the descriptor
*/
{
exit(1);
/*NOTREACHED*/
}
{
exit(1);
/*NOTREACHED*/
}
return 0;
}
# endif /* SYS_HPUX: FIOSSAIOOWN && FIOSNBIO && FIOSSAIOSTAT */
/* Was: defined(SYS_AIX) && !defined(_BSD) */
/*
* SYSV compatibility mode under AIX.
*/
#define CLOCK_DONE
{
/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
{
return 1;
}
{
return 1;
}
{
return 1;
}
return 0;
}
# endif /* AIX && !BSD: !_BSD && FIOASYNC && FIOSETOWN */
# ifndef CLOCK_DONE
{
/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
# if defined(TIOCSCTTY) && defined(USE_FSETOWNCTTY)
/*
* there are, however, always exceptions to the rules
* one is, that OSF accepts SETOWN on TTY fd's only, iff they are
* CTTYs. SunOS and HPUX do not semm to have this restriction.
* another question is: how can you do multiple SIGIO from several
* ttys (as they all should be CTTYs), wondering...
*
* kd 95-07-16
*/
{
return 1;
}
# endif /* TIOCSCTTY && USE_FSETOWNCTTY */
{
return 1;
}
{
"fcntl(FNDELAY|FASYNC) fails for clock I/O: %m");
return 1;
}
return 0;
}
# endif /* CLOCK_DONE */
# endif /* !USE_TTY_SIGPOLL */
static void
int fd;
# ifdef USE_UDP_SIGPOLL
{
{
"init_socket_sig: ioctl(I_SETSIG, S_INPUT) failed: %m");
exit(1);
}
}
# else /* USE_UDP_SIGPOLL */
{
int pgrp;
# ifdef FIOASYNC
int on = 1;
# endif
# if defined(FIOASYNC)
{
exit(1);
/*NOTREACHED*/
}
{
int flags;
{
exit(1);
/*NOTREACHED*/
}
{
exit(1);
/*NOTREACHED*/
}
}
# else
# include "Bletch: Need asynchronous I/O!"
# endif
# ifdef UDP_BACKWARDS_SETOWN
# else
# endif
# if defined(SIOCSPGRP)
{
exit(1);
/*NOTREACHED*/
}
{
exit(1);
/*NOTREACHED*/
}
{
exit(1);
/*NOTREACHED*/
}
# else
# include "Bletch: Need to set process(group) to receive SIG(IO|POLL)"
# endif
}
# endif /* USE_UDP_SIGPOLL */
static RETSIGTYPE
int sig;
{
int saved_errno = errno;
get_systime(&ts);
(void)input_handler(&ts);
errno = saved_errno;
}
/*
* Signal support routines.
*/
# ifdef HAVE_SIGACTION
static void
{
# ifdef USE_SIGIO
# endif
# ifdef USE_SIGPOLL
# endif
}
void
{
if (sigemptyset(&set))
# if defined(USE_SIGIO)
# endif
# if defined(USE_SIGPOLL)
# endif
}
static void
{
if (sigio_block_count > 1)
if (sigio_block_count < 1)
if (sigemptyset(&set))
# if defined(USE_SIGIO)
# endif
# if defined(USE_SIGPOLL)
# endif
}
void
{
if (sigemptyset(&unset))
# if defined(USE_SIGIO)
# endif
# if defined(USE_SIGPOLL)
# endif
}
static
void
{
if (sigio_block_count > 0)
if (sigio_block_count < 0)
if (sigemptyset(&unset))
# if defined(USE_SIGIO)
# endif
# if defined(USE_SIGPOLL)
# endif
}
void
{
# if defined(USE_SIGIO)
# endif
# if defined(USE_SIGPOLL)
# endif
}
# else /* !HAVE_SIGACTION */
/*
* Must be an old bsd system.
* We assume there is no SIGPOLL.
*/
void
{
int mask;
}
static void
{
int mask;
if (sigio_block_count > 1)
if (sigio_block_count < 1)
}
static void
{
}
void
{
(void) sigsetmask(omask);
}
static void
{
if (sigio_block_count > 0)
if (sigio_block_count < 0)
(void) sigsetmask(omask);
}
void
{
}
# endif /* HAVE_SIGACTION */
#endif /* HAVE_SIGNALED_IO */
void
{
int i;
BLOCKIO();
#ifdef N_FD_RESERVE
for (i = N_FD_RESERVE; i <= maxactivefd; i++)
(void)close_socket(i);
#else
for (i = 4; i <= maxactivefd; i++)
(void)close_socket(i);
#endif
}
#ifdef SYS_WINNT
/* ------------------------------------------------------------------------------------------------------------------ */
/* modified with suggestions from Kevin Dunlap so we only pick out netcards bound to tcpip */
int
{
int maxsize = sizeof(ifc_buffer);
char newkey[200];
char servicename[50];
int Done = 0;
/*
* these need to be big as they are multi_sz in type and hold all
* ip addresses and subnet mask for a given interface
*/
char IpAddresses[10000];
char *ipptr = IpAddresses;
char SubNetMasks[10000];
char *subptr = SubNetMasks;
char bindservicenames[1000];
char oneIpAddress[16];
char oneSubNetMask[16];
int count = 0;
char *onenetcard;
/* now get all the netcard values which are bound to tcpip */
if(bSuccess != ERROR_SUCCESS)
{
#ifdef DEBUG
if (debug)
#endif
return -1;
}
/* now get the bind value */
sizeofbindnames = 1000;
"Bind", /* value name */
NULL, /* must be zero */
NULL, /* value type not required */
&sizeofbindnames); /* length of value data */
if(bSuccess != ERROR_SUCCESS)
{
return -1;
}
/* now loop through and get all the values which are bound to tcpip */
/* we can also close the key here as we have the values now */
while(1)
{
{
}
else { /* no more */
break;
}
/*
* skip services that are NDISWAN... since these are temporary
* interfaces like ras and if we bind to these we would have to
* check if the socket is still ok everytime before using it as
* when the link goes down and comes back up the socket is no
* longer any good... and the server eventually crashes if we
* don't check this.. and to check it entails a lot of overhead...
* shouldn't be a problem with machines with only a RAS
* interface anyway as we can bind to the loopback or 0.0.0.0
*/
{
/* skip it */
#ifdef DEBUG
if (debug)
#endif
}
else {
/* if opening this key fails we can assume it is not a network card ie digiboard and go on.. */
/* ok now that we have the service name parameter close the key and go get the ipaddress and subnet mask */
if(bSuccess != ERROR_SUCCESS)
{
#ifdef DEBUG
if (debug)
#endif
}
else
{ /* ok it is a network card */
/* ok now get the ipaddress and subnetmask */
sizeofipaddresses = 10000;
bSuccess =
"IpAddress", /* value name */
NULL, /* must be zero */
NULL, /* value type not required */
&sizeofipaddresses); /* length of value data */
if(bSuccess != ERROR_SUCCESS)
{
return -1;
}
/* ok now get the ipaddress and subnetmask */
sizeofsubnetmasks = 10000;
bSuccess =
"SubNetMask", /* value name */
NULL, /* must be zero */
NULL, /* value type not required */
&sizeofsubnetmasks); /* length of value data */
if(bSuccess != ERROR_SUCCESS)
{
return -1;
}
/* ok now that we have some addresses and subnet masks go through each one and add to our structure... */
/* multi_sz strings are terminated by two \0 in a row */
ipptr = IpAddresses;
Done = 0;
while (!Done)
{
else Done = 1;
else Done = 1;
/* now add to interface structure */
if (!Done)
{
/* now increment pointer */
++count;
Done = 1;
}
}
} /* it is a network card */
} /* end of loop */
/* now reset the length */
return 0;
}
#endif /* SYS_WINNT */