ntp_io.c revision 54359
154359Sroberto/* 254359Sroberto * ntp_io.c - input/output routines for ntpd. The socket-opening code 354359Sroberto * was shamelessly stolen from ntpd. 454359Sroberto */ 554359Sroberto 654359Sroberto#ifdef HAVE_CONFIG_H 754359Sroberto# include <config.h> 854359Sroberto#endif 954359Sroberto 1054359Sroberto#include <stdio.h> 1154359Sroberto#include <signal.h> 1254359Sroberto#include <sys/types.h> 1354359Sroberto#ifdef HAVE_SYS_PARAM_H 1454359Sroberto# include <sys/param.h> 1554359Sroberto#endif /* HAVE_SYS_PARAM_H */ 1654359Sroberto#ifdef HAVE_SYS_TIME_H 1754359Sroberto# include <sys/time.h> 1854359Sroberto#endif 1954359Sroberto#ifdef HAVE_NETINET_IN_H 2054359Sroberto# include <netinet/in.h> 2154359Sroberto#endif 2254359Sroberto#ifdef HAVE_SYS_IOCTL_H 2354359Sroberto# include <sys/ioctl.h> 2454359Sroberto#endif 2554359Sroberto#ifdef HAVE_SYS_SOCKIO_H /* UXPV: SIOC* #defines (Frank Vance <fvance@waii.com>) */ 2654359Sroberto# include <sys/sockio.h> 2754359Sroberto#endif 2854359Sroberto#include <arpa/inet.h> 2954359Sroberto 3054359Sroberto#if _BSDI_VERSION >= 199510 3154359Sroberto# include <ifaddrs.h> 3254359Sroberto#endif 3354359Sroberto 3454359Sroberto#include "ntp_machine.h" 3554359Sroberto#include "ntpd.h" 3654359Sroberto#include "ntp_io.h" 3754359Sroberto#include "iosignal.h" 3854359Sroberto#include "ntp_refclock.h" 3954359Sroberto#include "ntp_if.h" 4054359Sroberto#include "ntp_stdlib.h" 4154359Sroberto 4254359Sroberto#if defined(VMS) /* most likely UCX-specific */ 4354359Sroberto 4454359Sroberto#include <UCX$INETDEF.H> 4554359Sroberto 4654359Sroberto/* "un*x"-compatible names for some items in UCX$INETDEF.H */ 4754359Sroberto#define ifreq IFREQDEF 4854359Sroberto#define ifr_name IFR$T_NAME 4954359Sroberto#define ifr_addr IFR$R_DUMMY.IFR$T_ADDR 5054359Sroberto#define ifr_broadaddr IFR$R_DUMMY.IFR$T_BROADADDR 5154359Sroberto#define ifr_flags IFR$R_DUMMY.IFR$R_DUMMY_1_OVRL.IFR$W_FLAGS 5254359Sroberto#define IFF_UP IFR$M_IFF_UP 5354359Sroberto#define IFF_BROADCAST IFR$M_IFF_BROADCAST 5454359Sroberto#define IFF_LOOPBACK IFR$M_IFF_LOOPBACK 5554359Sroberto 5654359Sroberto#endif /* VMS */ 5754359Sroberto 5854359Sroberto 5954359Sroberto#if defined(VMS) || defined(SYS_WINNT) 6054359Sroberto/* structure used in SIOCGIFCONF request (after [KSR] OSF/1) */ 6154359Srobertostruct ifconf { 6254359Sroberto int ifc_len; /* size of buffer */ 6354359Sroberto union { 6454359Sroberto caddr_t ifcu_buf; 6554359Sroberto struct ifreq *ifcu_req; 6654359Sroberto } ifc_ifcu; 6754359Sroberto}; 6854359Sroberto#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ 6954359Sroberto#define ifc_req ifc_ifcu.ifcu_req /* array of structures returned */ 7054359Sroberto 7154359Sroberto#endif /* VMS */ 7254359Sroberto 7354359Sroberto#if defined(USE_TTY_SIGPOLL) || defined(USE_UDP_SIGPOLL) 7454359Sroberto# if defined(SYS_AIX) && defined(_IO) /* XXX Identify AIX some other way */ 7554359Sroberto# undef _IO 7654359Sroberto# endif 7754359Sroberto# include <stropts.h> 7854359Sroberto#endif 7954359Sroberto 8054359Sroberto/* 8154359Sroberto * We do asynchronous input using the SIGIO facility. A number of 8254359Sroberto * recvbuf buffers are preallocated for input. In the signal 8354359Sroberto * handler we poll to see which sockets are ready and read the 8454359Sroberto * packets from them into the recvbuf's along with a time stamp and 8554359Sroberto * an indication of the source host and the interface it was received 8654359Sroberto * through. This allows us to get as accurate receive time stamps 8754359Sroberto * as possible independent of other processing going on. 8854359Sroberto * 8954359Sroberto * We watch the number of recvbufs available to the signal handler 9054359Sroberto * and allocate more when this number drops below the low water 9154359Sroberto * mark. If the signal handler should run out of buffers in the 9254359Sroberto * interim it will drop incoming frames, the idea being that it is 9354359Sroberto * better to drop a packet than to be inaccurate. 9454359Sroberto */ 9554359Sroberto 9654359Sroberto 9754359Sroberto/* 9854359Sroberto * Other statistics of possible interest 9954359Sroberto */ 10054359Srobertovolatile u_long packets_dropped; /* total number of packets dropped on reception */ 10154359Srobertovolatile u_long packets_ignored; /* packets received on wild card interface */ 10254359Srobertovolatile u_long packets_received; /* total number of packets received */ 10354359Srobertou_long packets_sent; /* total number of packets sent */ 10454359Srobertou_long packets_notsent; /* total number of packets which couldn't be sent */ 10554359Sroberto 10654359Srobertovolatile u_long handler_calls; /* number of calls to interrupt handler */ 10754359Srobertovolatile u_long handler_pkts; /* number of pkts received by handler */ 10854359Srobertou_long io_timereset; /* time counters were reset */ 10954359Sroberto 11054359Sroberto/* 11154359Sroberto * Interface stuff 11254359Sroberto */ 11354359Srobertostruct interface *any_interface; /* pointer to default interface */ 11454359Srobertostruct interface *loopback_interface; /* point to loopback interface */ 11554359Srobertostatic struct interface inter_list[MAXINTERFACES]; 11654359Srobertostatic int ninterfaces; 11754359Sroberto 11854359Sroberto#ifdef REFCLOCK 11954359Sroberto/* 12054359Sroberto * Refclock stuff. We keep a chain of structures with data concerning 12154359Sroberto * the guys we are doing I/O for. 12254359Sroberto */ 12354359Srobertostatic struct refclockio *refio; 12454359Sroberto#endif /* REFCLOCK */ 12554359Sroberto 12654359Sroberto/* 12754359Sroberto * File descriptor masks etc. for call to select 12854359Sroberto */ 12954359Srobertofd_set activefds; 13054359Srobertoint maxactivefd; 13154359Sroberto 13254359Srobertostatic int create_sockets P((u_int)); 13354359Srobertostatic int open_socket P((struct sockaddr_in *, int, int)); 13454359Srobertostatic void close_socket P((int)); 13554359Srobertostatic void close_file P((int)); 13654359Srobertostatic char * fdbits P((int, fd_set *)); 13754359Sroberto 13854359Sroberto/* 13954359Sroberto * init_io - initialize I/O data structures and call socket creation routine 14054359Sroberto */ 14154359Srobertovoid 14254359Srobertoinit_io(void) 14354359Sroberto{ 14454359Sroberto#ifdef SYS_WINNT 14554359Sroberto WORD wVersionRequested; 14654359Sroberto WSADATA wsaData; 14754359Sroberto init_transmitbuff(); 14854359Sroberto#endif /* SYS_WINNT */ 14954359Sroberto 15054359Sroberto /* 15154359Sroberto * Init buffer free list and stat counters 15254359Sroberto */ 15354359Sroberto init_recvbuff(RECV_INIT); 15454359Sroberto 15554359Sroberto packets_dropped = packets_received = 0; 15654359Sroberto packets_ignored = 0; 15754359Sroberto packets_sent = packets_notsent = 0; 15854359Sroberto handler_calls = handler_pkts = 0; 15954359Sroberto io_timereset = 0; 16054359Sroberto loopback_interface = 0; 16154359Sroberto 16254359Sroberto#ifdef REFCLOCK 16354359Sroberto refio = 0; 16454359Sroberto#endif 16554359Sroberto 16654359Sroberto#if defined(HAVE_SIGNALED_IO) 16754359Sroberto (void) set_signal(); 16854359Sroberto#endif 16954359Sroberto 17054359Sroberto#ifdef SYS_WINNT 17154359Sroberto wVersionRequested = MAKEWORD(1,1); 17254359Sroberto if (WSAStartup(wVersionRequested, &wsaData)) 17354359Sroberto { 17454359Sroberto msyslog(LOG_ERR, "No useable winsock.dll: %m"); 17554359Sroberto exit(1); 17654359Sroberto } 17754359Sroberto#endif /* SYS_WINNT */ 17854359Sroberto 17954359Sroberto /* 18054359Sroberto * Create the sockets 18154359Sroberto */ 18254359Sroberto BLOCKIO(); 18354359Sroberto (void) create_sockets(htons(NTP_PORT)); 18454359Sroberto UNBLOCKIO(); 18554359Sroberto 18654359Sroberto#ifdef DEBUG 18754359Sroberto if (debug) 18854359Sroberto printf("init_io: maxactivefd %d\n", maxactivefd); 18954359Sroberto#endif 19054359Sroberto} 19154359Sroberto 19254359Sroberto/* 19354359Sroberto * create_sockets - create a socket for each interface plus a default 19454359Sroberto * socket for when we don't know where to send 19554359Sroberto */ 19654359Srobertostatic int 19754359Srobertocreate_sockets( 19854359Sroberto u_int port 19954359Sroberto ) 20054359Sroberto{ 20154359Sroberto#if _BSDI_VERSION >= 199510 20254359Sroberto int i, j; 20354359Sroberto struct ifaddrs *ifaddrs, *ifap; 20454359Sroberto struct sockaddr_in resmask; 20554359Sroberto#if _BSDI_VERSION < 199701 20654359Sroberto struct ifaddrs *lp; 20754359Sroberto int num_if; 20854359Sroberto#endif 20954359Sroberto#else /* _BSDI_VERSION >= 199510 */ 21054359Sroberto# ifdef STREAMS_TLI 21154359Sroberto struct strioctl ioc; 21254359Sroberto# endif /* STREAMS_TLI */ 21354359Sroberto char buf[MAXINTERFACES*sizeof(struct ifreq)]; 21454359Sroberto struct ifconf ifc; 21554359Sroberto struct ifreq ifreq, *ifr; 21654359Sroberto int n, i, j, vs, size = 0; 21754359Sroberto struct sockaddr_in resmask; 21854359Sroberto#endif /* _BSDI_VERSION >= 199510 */ 21954359Sroberto 22054359Sroberto#ifdef DEBUG 22154359Sroberto if (debug) 22254359Sroberto printf("create_sockets(%d)\n", ntohs( (u_short) port)); 22354359Sroberto#endif 22454359Sroberto 22554359Sroberto /* 22654359Sroberto * create pseudo-interface with wildcard address 22754359Sroberto */ 22854359Sroberto inter_list[0].sin.sin_family = AF_INET; 22954359Sroberto inter_list[0].sin.sin_port = port; 23054359Sroberto inter_list[0].sin.sin_addr.s_addr = htonl(INADDR_ANY); 23154359Sroberto (void) strncpy(inter_list[0].name, "wildcard", 23254359Sroberto sizeof(inter_list[0].name)); 23354359Sroberto inter_list[0].mask.sin_addr.s_addr = htonl(~ (u_int32)0); 23454359Sroberto inter_list[0].received = 0; 23554359Sroberto inter_list[0].sent = 0; 23654359Sroberto inter_list[0].notsent = 0; 23754359Sroberto inter_list[0].flags = INT_BROADCAST; 23854359Sroberto 23954359Sroberto#if _BSDI_VERSION >= 199510 24054359Sroberto#if _BSDI_VERSION >= 199701 24154359Sroberto if (getifaddrs(&ifaddrs) < 0) 24254359Sroberto { 24354359Sroberto msyslog(LOG_ERR, "getifaddrs: %m"); 24454359Sroberto exit(1); 24554359Sroberto } 24654359Sroberto i = 1; 24754359Sroberto for (ifap = ifaddrs; ifap != NULL; ifap = ifap->ifa_next) 24854359Sroberto#else 24954359Sroberto if (getifaddrs(&ifaddrs, &num_if) < 0) 25054359Sroberto { 25154359Sroberto msyslog(LOG_ERR, "create_sockets: getifaddrs() failed: %m"); 25254359Sroberto exit(1); 25354359Sroberto } 25454359Sroberto 25554359Sroberto i = 1; 25654359Sroberto 25754359Sroberto for (ifap = ifaddrs, lp = ifap + num_if; ifap < lp; ifap++) 25854359Sroberto#endif 25954359Sroberto { 26054359Sroberto struct sockaddr_in *sin; 26154359Sroberto 26254359Sroberto if (!ifap->ifa_addr) 26354359Sroberto continue; 26454359Sroberto 26554359Sroberto if (ifap->ifa_addr->sa_family != AF_INET) 26654359Sroberto continue; 26754359Sroberto 26854359Sroberto if ((ifap->ifa_flags & IFF_UP) == 0) 26954359Sroberto continue; 27054359Sroberto 27154359Sroberto if (ifap->ifa_flags & IFF_LOOPBACK) 27254359Sroberto { 27354359Sroberto sin = (struct sockaddr_in *)ifap->ifa_addr; 27454359Sroberto if (ntohl(sin->sin_addr.s_addr) != 0x7f000001) 27554359Sroberto { 27654359Sroberto continue; 27754359Sroberto } 27854359Sroberto } 27954359Sroberto 28054359Sroberto inter_list[i].flags = 0; 28154359Sroberto if (ifap->ifa_flags & IFF_BROADCAST) 28254359Sroberto inter_list[i].flags |= INT_BROADCAST; 28354359Sroberto 28454359Sroberto (void)strcpy(inter_list[i].name, ifap->ifa_name); 28554359Sroberto 28654359Sroberto sin = (struct sockaddr_in *)ifap->ifa_addr; 28754359Sroberto inter_list[i].sin = *sin; 28854359Sroberto inter_list[i].sin.sin_port = port; 28954359Sroberto 29054359Sroberto if (ifap->ifa_flags & IFF_LOOPBACK) 29154359Sroberto { 29254359Sroberto inter_list[i].flags = INT_LOOPBACK; 29354359Sroberto if (loopback_interface == NULL 29454359Sroberto || ntohl(sin->sin_addr.s_addr) != 0x7f000001) 29554359Sroberto loopback_interface = &inter_list[i]; 29654359Sroberto } 29754359Sroberto 29854359Sroberto if (inter_list[i].flags & INT_BROADCAST) 29954359Sroberto { 30054359Sroberto sin = (struct sockaddr_in *)ifap->ifa_broadaddr; 30154359Sroberto inter_list[i].bcast = *sin; 30254359Sroberto inter_list[i].bcast.sin_port = port; 30354359Sroberto } 30454359Sroberto 30554359Sroberto if (ifap->ifa_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) 30654359Sroberto { 30754359Sroberto inter_list[i].mask.sin_addr.s_addr = 0xffffffff; 30854359Sroberto } 30954359Sroberto else 31054359Sroberto { 31154359Sroberto sin = (struct sockaddr_in *)ifap->ifa_netmask; 31254359Sroberto inter_list[i].mask = *sin; 31354359Sroberto } 31454359Sroberto inter_list[i].mask.sin_family = AF_INET; 31554359Sroberto inter_list[i].mask.sin_len = sizeof *sin; 31654359Sroberto 31754359Sroberto /* 31854359Sroberto * look for an already existing source interface address. If 31954359Sroberto * the machine has multiple point to point interfaces, then 32054359Sroberto * the local address may appear more than once. 32154359Sroberto * 32254359Sroberto * A second problem exists if we have two addresses on 32354359Sroberto * the same network (via "ifconfig alias ..."). Don't 32454359Sroberto * make two xntp interfaces for the two aliases on the 32554359Sroberto * one physical interface. -wsr 32654359Sroberto */ 32754359Sroberto for (j=0; j < i; j++) 32854359Sroberto if (inter_list[j].sin.sin_addr.s_addr & 32954359Sroberto inter_list[j].mask.sin_addr.s_addr == 33054359Sroberto inter_list[i].sin.sin_addr.s_addr & 33154359Sroberto inter_list[i].mask.sin_addr.s_addr) 33254359Sroberto { 33354359Sroberto if (inter_list[j].flags & INT_LOOPBACK) 33454359Sroberto inter_list[j] = inter_list[i]; 33554359Sroberto break; 33654359Sroberto } 33754359Sroberto if (j == i) 33854359Sroberto i++; 33954359Sroberto if (i > MAXINTERFACES) 34054359Sroberto break; 34154359Sroberto } 34254359Sroberto free(ifaddrs); 34354359Sroberto#else /* _BSDI_VERSION >= 199510 */ 34454359Sroberto# ifdef USE_STREAMS_DEVICE_FOR_IF_CONFIG 34554359Sroberto if ((vs = open("/dev/ip", O_RDONLY)) < 0) 34654359Sroberto { 34754359Sroberto msyslog(LOG_ERR, "create_sockets: open(/dev/ip) failed: %m"); 34854359Sroberto exit(1); 34954359Sroberto } 35054359Sroberto# else /* not USE_STREAMS_DEVICE_FOR_IF_CONFIG */ 35154359Sroberto if ( 35254359Sroberto (vs = socket(AF_INET, SOCK_DGRAM, 0)) 35354359Sroberto# ifndef SYS_WINNT 35454359Sroberto < 0 35554359Sroberto# else /* SYS_WINNT */ 35654359Sroberto == INVALID_SOCKET 35754359Sroberto# endif /* SYS_WINNT */ 35854359Sroberto ) { 35954359Sroberto msyslog(LOG_ERR, "create_sockets: socket(AF_INET, SOCK_DGRAM) failed: %m"); 36054359Sroberto exit(1); 36154359Sroberto } 36254359Sroberto# endif /* not USE_STREAMS_DEVICE_FOR_IF_CONFIG */ 36354359Sroberto 36454359Sroberto i = 1; 36554359Sroberto# if !defined(SYS_WINNT) 36654359Sroberto ifc.ifc_len = sizeof(buf); 36754359Sroberto# endif 36854359Sroberto# ifdef STREAMS_TLI 36954359Sroberto ioc.ic_cmd = SIOCGIFCONF; 37054359Sroberto ioc.ic_timout = 0; 37154359Sroberto ioc.ic_dp = (caddr_t)buf; 37254359Sroberto ioc.ic_len = sizeof(buf); 37354359Sroberto if(ioctl(vs, I_STR, &ioc) < 0 || 37454359Sroberto ioc.ic_len < sizeof(struct ifreq)) 37554359Sroberto { 37654359Sroberto msyslog(LOG_ERR, "create_sockets: ioctl(I_STR:SIOCGIFCONF) failed: %m - exiting"); 37754359Sroberto exit(1); 37854359Sroberto } 37954359Sroberto# ifdef SIZE_RETURNED_IN_BUFFER 38054359Sroberto ifc.ifc_len = ioc.ic_len - sizeof(int); 38154359Sroberto ifc.ifc_buf = buf + sizeof(int); 38254359Sroberto# else /* not SIZE_RETURNED_IN_BUFFER */ 38354359Sroberto ifc.ifc_len = ioc.ic_len; 38454359Sroberto ifc.ifc_buf = buf; 38554359Sroberto# endif /* not SIZE_RETURNED_IN_BUFFER */ 38654359Sroberto 38754359Sroberto# else /* not STREAMS_TLI */ 38854359Sroberto ifc.ifc_len = sizeof(buf); 38954359Sroberto ifc.ifc_buf = buf; 39054359Sroberto# ifndef SYS_WINNT 39154359Sroberto if (ioctl(vs, SIOCGIFCONF, (char *)&ifc) < 0) 39254359Sroberto# else 39354359Sroberto if (WSAIoctl(vs, SIO_GET_INTERFACE_LIST, 0, 0, ifc.ifc_buf, ifc.ifc_len, &ifc.ifc_len, 0, 0) == SOCKET_ERROR) 39454359Sroberto# endif /* SYS_WINNT */ 39554359Sroberto{ 39654359Sroberto msyslog(LOG_ERR, "create_sockets: ioctl(SIOCGIFCONF) failed: %m - exiting"); 39754359Sroberto exit(1); 39854359Sroberto} 39954359Sroberto 40054359Sroberto# endif /* not STREAMS_TLI */ 40154359Sroberto 40254359Sroberto for(n = ifc.ifc_len, ifr = ifc.ifc_req; n > 0; 40354359Sroberto ifr = (struct ifreq *)((char *)ifr + size)) 40454359Sroberto { 40554359Sroberto extern int listen_to_virtual_ips; 40654359Sroberto 40754359Sroberto size = sizeof(*ifr); 40854359Sroberto 40954359Sroberto# ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 41054359Sroberto if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_addr)) 41154359Sroberto size += ifr->ifr_addr.sa_len - sizeof(struct sockaddr); 41254359Sroberto# endif 41354359Sroberto n -= size; 41454359Sroberto 41554359Sroberto# if !defined(SYS_WINNT) 41654359Sroberto /* Exclude logical interfaces (indicated by ':' in the interface name) */ 41754359Sroberto if (debug) 41854359Sroberto printf("interface <%s> ", ifr->ifr_name); 41954359Sroberto if ((listen_to_virtual_ips == 0) 42054359Sroberto && (strchr(ifr->ifr_name, (int)':') != NULL)) { 42154359Sroberto if (debug) 42254359Sroberto printf("ignored\n"); 42354359Sroberto continue; 42454359Sroberto } 42554359Sroberto if (debug) 42654359Sroberto printf("OK\n"); 42754359Sroberto 42854359Sroberto if ( 42954359Sroberto# ifdef VMS /* VMS+UCX */ 43054359Sroberto (((struct sockaddr *)&(ifr->ifr_addr))->sa_family != AF_INET) 43154359Sroberto# else 43254359Sroberto (ifr->ifr_addr.sa_family != AF_INET) 43354359Sroberto# endif /* VMS+UCX */ 43454359Sroberto ) { 43554359Sroberto if (debug) 43654359Sroberto printf("ignoring %s - not AF_INET\n", 43754359Sroberto ifr->ifr_name); 43854359Sroberto continue; 43954359Sroberto } 44054359Sroberto# endif /* SYS_WINNT */ 44154359Sroberto ifreq = *ifr; 44254359Sroberto inter_list[i].flags = 0; 44354359Sroberto /* is it broadcast capable? */ 44454359Sroberto# ifndef SYS_WINNT 44554359Sroberto# ifdef STREAMS_TLI 44654359Sroberto ioc.ic_cmd = SIOCGIFFLAGS; 44754359Sroberto ioc.ic_timout = 0; 44854359Sroberto ioc.ic_dp = (caddr_t)&ifreq; 44954359Sroberto ioc.ic_len = sizeof(struct ifreq); 45054359Sroberto if(ioctl(vs, I_STR, &ioc)) { 45154359Sroberto msyslog(LOG_ERR, "create_sockets: ioctl(I_STR:SIOCGIFFLAGS) failed: %m"); 45254359Sroberto continue; 45354359Sroberto } 45454359Sroberto# else /* not STREAMS_TLI */ 45554359Sroberto if (ioctl(vs, SIOCGIFFLAGS, (char *)&ifreq) < 0) { 45654359Sroberto if (errno != ENXIO) 45754359Sroberto msyslog(LOG_ERR, "create_sockets: ioctl(SIOCGIFFLAGS) failed: %m"); 45854359Sroberto continue; 45954359Sroberto } 46054359Sroberto# endif /* not STREAMS_TLI */ 46154359Sroberto if ((ifreq.ifr_flags & IFF_UP) == 0) { 46254359Sroberto if (debug) 46354359Sroberto printf("ignoring %s - interface not UP\n", 46454359Sroberto ifr->ifr_name); 46554359Sroberto continue; 46654359Sroberto } 46754359Sroberto inter_list[i].flags = 0; 46854359Sroberto if (ifreq.ifr_flags & IFF_BROADCAST) 46954359Sroberto inter_list[i].flags |= INT_BROADCAST; 47054359Sroberto# endif /* not SYS_WINNT */ 47154359Sroberto# if !defined(SUN_3_3_STINKS) 47254359Sroberto if ( 47354359Sroberto# if defined(IFF_LOCAL_LOOPBACK) /* defined(SYS_HPUX) && (SYS_HPUX < 8) */ 47454359Sroberto (ifreq.ifr_flags & IFF_LOCAL_LOOPBACK) 47554359Sroberto# elif defined(IFF_LOOPBACK) 47654359Sroberto (ifreq.ifr_flags & IFF_LOOPBACK) 47754359Sroberto# else /* not IFF_LOCAL_LOOPBACK and not IFF_LOOPBACK */ 47854359Sroberto /* test against 127.0.0.1 (yuck!!) */ 47954359Sroberto (inter_list[i].sin.sin_addr.s_addr == inet_addr("127.0.0.1")) 48054359Sroberto# endif /* not IFF_LOCAL_LOOPBACK and not IFF_LOOPBACK */ 48154359Sroberto ) 48254359Sroberto { 48354359Sroberto# ifndef SYS_WINNT 48454359Sroberto inter_list[i].flags |= INT_LOOPBACK; 48554359Sroberto# endif /* not SYS_WINNT */ 48654359Sroberto if (loopback_interface == 0) 48754359Sroberto { 48854359Sroberto loopback_interface = &inter_list[i]; 48954359Sroberto } 49054359Sroberto } 49154359Sroberto# endif /* not SUN_3_3_STINKS */ 49254359Sroberto 49354359Sroberto#if 0 49454359Sroberto# ifndef SYS_WINNT 49554359Sroberto# ifdef STREAMS_TLI 49654359Sroberto ioc.ic_cmd = SIOCGIFADDR; 49754359Sroberto ioc.ic_timout = 0; 49854359Sroberto ioc.ic_dp = (caddr_t)&ifreq; 49954359Sroberto ioc.ic_len = sizeof(struct ifreq); 50054359Sroberto if (ioctl(vs, I_STR, &ioc)) 50154359Sroberto { 50254359Sroberto msyslog(LOG_ERR, "create_sockets: ioctl(I_STR:SIOCGIFADDR) failed: %m"); 50354359Sroberto continue; 50454359Sroberto } 50554359Sroberto# else /* not STREAMS_TLI */ 50654359Sroberto if (ioctl(vs, SIOCGIFADDR, (char *)&ifreq) < 0) 50754359Sroberto { 50854359Sroberto if (errno != ENXIO) 50954359Sroberto msyslog(LOG_ERR, "create_sockets: ioctl(SIOCGIFADDR) failed: %m"); 51054359Sroberto continue; 51154359Sroberto } 51254359Sroberto# endif /* not STREAMS_TLI */ 51354359Sroberto# endif /* not SYS_WINNT */ 51454359Sroberto#endif /* 0 */ 51554359Sroberto# if defined(SYS_WINNT) 51654359Sroberto {int TODO_FillInTheNameWithSomeThingReasonble;} 51754359Sroberto# else 51854359Sroberto (void)strncpy(inter_list[i].name, ifreq.ifr_name, 51954359Sroberto sizeof(inter_list[i].name)); 52054359Sroberto# endif 52154359Sroberto inter_list[i].sin = *(struct sockaddr_in *)&ifr->ifr_addr; 52254359Sroberto inter_list[i].sin.sin_family = AF_INET; 52354359Sroberto inter_list[i].sin.sin_port = port; 52454359Sroberto 52554359Sroberto# if defined(SUN_3_3_STINKS) 52654359Sroberto /* 52754359Sroberto * Oh, barf! I'm too disgusted to even explain this 52854359Sroberto */ 52954359Sroberto if (SRCADR(&inter_list[i].sin) == 0x7f000001) 53054359Sroberto { 53154359Sroberto inter_list[i].flags |= INT_LOOPBACK; 53254359Sroberto if (loopback_interface == 0) 53354359Sroberto loopback_interface = &inter_list[i]; 53454359Sroberto } 53554359Sroberto# endif /* SUN_3_3_STINKS */ 53654359Sroberto# if !defined SYS_WINNT && !defined SYS_CYGWIN32 /* no interface flags on NT */ 53754359Sroberto if (inter_list[i].flags & INT_BROADCAST) { 53854359Sroberto# ifdef STREAMS_TLI 53954359Sroberto ioc.ic_cmd = SIOCGIFBRDADDR; 54054359Sroberto ioc.ic_timout = 0; 54154359Sroberto ioc.ic_dp = (caddr_t)&ifreq; 54254359Sroberto ioc.ic_len = sizeof(struct ifreq); 54354359Sroberto if(ioctl(vs, I_STR, &ioc)) { 54454359Sroberto msyslog(LOG_ERR, "create_sockets: ioctl(I_STR:SIOCGIFBRDADDR) failed: %m"); 54554359Sroberto exit(1); 54654359Sroberto } 54754359Sroberto# else /* not STREAMS_TLI */ 54854359Sroberto if (ioctl(vs, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { 54954359Sroberto msyslog(LOG_ERR, "create_sockets: ioctl(SIOCGIFBRDADDR) failed: %m"); 55054359Sroberto exit(1); 55154359Sroberto } 55254359Sroberto# endif /* not STREAMS_TLI */ 55354359Sroberto 55454359Sroberto# ifndef ifr_broadaddr 55554359Sroberto inter_list[i].bcast = 55654359Sroberto *(struct sockaddr_in *)&ifreq.ifr_addr; 55754359Sroberto# else 55854359Sroberto inter_list[i].bcast = 55954359Sroberto *(struct sockaddr_in *)&ifreq.ifr_broadaddr; 56054359Sroberto# endif /* ifr_broadaddr */ 56154359Sroberto inter_list[i].bcast.sin_family = AF_INET; 56254359Sroberto inter_list[i].bcast.sin_port = port; 56354359Sroberto } 56454359Sroberto 56554359Sroberto# ifdef STREAMS_TLI 56654359Sroberto ioc.ic_cmd = SIOCGIFNETMASK; 56754359Sroberto ioc.ic_timout = 0; 56854359Sroberto ioc.ic_dp = (caddr_t)&ifreq; 56954359Sroberto ioc.ic_len = sizeof(struct ifreq); 57054359Sroberto if(ioctl(vs, I_STR, &ioc)) { 57154359Sroberto msyslog(LOG_ERR, "create_sockets: ioctl(I_STR:SIOCGIFNETMASK) failed: %m"); 57254359Sroberto exit(1); 57354359Sroberto } 57454359Sroberto# else /* not STREAMS_TLI */ 57554359Sroberto if (ioctl(vs, SIOCGIFNETMASK, (char *)&ifreq) < 0) { 57654359Sroberto msyslog(LOG_ERR, "create_sockets: ioctl(SIOCGIFNETMASK) failed: %m"); 57754359Sroberto exit(1); 57854359Sroberto } 57954359Sroberto# endif /* not STREAMS_TLI */ 58054359Sroberto inter_list[i].mask = *(struct sockaddr_in *)&ifreq.ifr_addr; 58154359Sroberto# else 58254359Sroberto /* winnt here */ 58354359Sroberto inter_list[i].bcast = ifreq.ifr_broadaddr; 58454359Sroberto inter_list[i].bcast.sin_family = AF_INET; 58554359Sroberto inter_list[i].bcast.sin_port = port; 58654359Sroberto inter_list[i].mask = ifreq.ifr_mask; 58754359Sroberto# endif /* not SYS_WINNT */ 58854359Sroberto 58954359Sroberto /* 59054359Sroberto * look for an already existing source interface address. If 59154359Sroberto * the machine has multiple point to point interfaces, then 59254359Sroberto * the local address may appear more than once. 59354359Sroberto */ 59454359Sroberto for (j=0; j < i; j++) 59554359Sroberto if (inter_list[j].sin.sin_addr.s_addr == 59654359Sroberto inter_list[i].sin.sin_addr.s_addr) { 59754359Sroberto break; 59854359Sroberto } 59954359Sroberto if (j == i) 60054359Sroberto i++; 60154359Sroberto if (i > MAXINTERFACES) 60254359Sroberto break; 60354359Sroberto } 60454359Sroberto closesocket(vs); 60554359Sroberto#endif /* _BSDI_VERSION >= 199510 */ 60654359Sroberto 60754359Sroberto ninterfaces = i; 60854359Sroberto maxactivefd = 0; 60954359Sroberto FD_ZERO(&activefds); 61054359Sroberto for (i = 0; i < ninterfaces; i++) { 61154359Sroberto inter_list[i].fd = 61254359Sroberto open_socket(&inter_list[i].sin, 61354359Sroberto inter_list[i].flags & INT_BROADCAST, 0); 61454359Sroberto } 61554359Sroberto 61654359Sroberto /* 61754359Sroberto * Now that we have opened all the sockets, turn off the reuse flag for 61854359Sroberto * security. 61954359Sroberto */ 62054359Sroberto for (i = 0; i < ninterfaces; i++) { 62154359Sroberto int off = 0; 62254359Sroberto 62354359Sroberto /* 62454359Sroberto * if inter_list[ n ].fd is -1, we might have a adapter 62554359Sroberto * configured but not present 62654359Sroberto */ 62754359Sroberto if ( inter_list[ i ].fd != -1 ) { 62854359Sroberto if (setsockopt(inter_list[i].fd, SOL_SOCKET, 62954359Sroberto SO_REUSEADDR, (char *)&off, 63054359Sroberto sizeof(off))) { 63154359Sroberto msyslog(LOG_ERR, "create_sockets: setsockopt(SO_REUSEADDR,off) failed: %m"); 63254359Sroberto } 63354359Sroberto } 63454359Sroberto } 63554359Sroberto 63654359Sroberto#if defined(MCAST) 63754359Sroberto /* 63854359Sroberto * enable possible multicast reception on the broadcast socket 63954359Sroberto */ 64054359Sroberto inter_list[0].bcast.sin_addr.s_addr = htonl(INADDR_ANY); 64154359Sroberto inter_list[0].bcast.sin_family = AF_INET; 64254359Sroberto inter_list[0].bcast.sin_port = port; 64354359Sroberto#endif /* MCAST */ 64454359Sroberto 64554359Sroberto /* 64654359Sroberto * Blacklist all bound interface addresses 64754359Sroberto */ 64854359Sroberto resmask.sin_addr.s_addr = ~ (u_int32)0; 64954359Sroberto for (i = 1; i < ninterfaces; i++) 65054359Sroberto hack_restrict(RESTRICT_FLAGS, &inter_list[i].sin, &resmask, 65154359Sroberto RESM_NTPONLY|RESM_INTERFACE, RES_IGNORE); 65254359Sroberto 65354359Sroberto any_interface = &inter_list[0]; 65454359Sroberto#ifdef DEBUG 65554359Sroberto if (debug > 2) { 65654359Sroberto printf("create_sockets: ninterfaces=%d\n", ninterfaces); 65754359Sroberto for (i = 0; i < ninterfaces; i++) { 65854359Sroberto printf("interface %d: fd=%d, bfd=%d, name=%.8s, flags=0x%x\n", 65954359Sroberto i, 66054359Sroberto inter_list[i].fd, 66154359Sroberto inter_list[i].bfd, 66254359Sroberto inter_list[i].name, 66354359Sroberto inter_list[i].flags); 66454359Sroberto /* Leave these as three printf calls. */ 66554359Sroberto printf(" sin=%s", 66654359Sroberto inet_ntoa((inter_list[i].sin.sin_addr))); 66754359Sroberto if (inter_list[i].flags & INT_BROADCAST) 66854359Sroberto printf(" bcast=%s,", 66954359Sroberto inet_ntoa((inter_list[i].bcast.sin_addr))); 67054359Sroberto printf(" mask=%s\n", 67154359Sroberto inet_ntoa((inter_list[i].mask.sin_addr))); 67254359Sroberto } 67354359Sroberto } 67454359Sroberto#endif 67554359Sroberto#if defined (HAVE_IO_COMPLETION_PORT) 67654359Sroberto for (i = 0; i < ninterfaces; i++) { 67754359Sroberto io_completion_port_add_socket(&inter_list[i]); 67854359Sroberto } 67954359Sroberto#endif 68054359Sroberto return ninterfaces; 68154359Sroberto} 68254359Sroberto 68354359Sroberto/* 68454359Sroberto * io_setbclient - open the broadcast client sockets 68554359Sroberto */ 68654359Srobertovoid 68754359Srobertoio_setbclient(void) 68854359Sroberto{ 68954359Sroberto int i; 69054359Sroberto 69154359Sroberto for (i = 1; i < ninterfaces; i++) 69254359Sroberto { 69354359Sroberto if (!(inter_list[i].flags & INT_BROADCAST)) 69454359Sroberto continue; 69554359Sroberto if (inter_list[i].flags & INT_BCASTOPEN) 69654359Sroberto continue; 69754359Sroberto#ifdef SYS_SOLARIS 69854359Sroberto inter_list[i].bcast.sin_addr.s_addr = htonl(INADDR_ANY); 69954359Sroberto#endif 70054359Sroberto#ifdef OPEN_BCAST_SOCKET /* Was: !SYS_DOMAINOS && !SYS_LINUX */ 70154359Sroberto inter_list[i].bfd = open_socket(&inter_list[i].bcast, INT_BROADCAST, 1); 70254359Sroberto inter_list[i].flags |= INT_BCASTOPEN; 70354359Sroberto#endif 70454359Sroberto } 70554359Sroberto} 70654359Sroberto 70754359Sroberto 70854359Sroberto/* 70954359Sroberto * io_multicast_add() - add multicast group address 71054359Sroberto */ 71154359Srobertovoid 71254359Srobertoio_multicast_add( 71354359Sroberto u_int32 addr 71454359Sroberto ) 71554359Sroberto{ 71654359Sroberto#ifdef MCAST 71754359Sroberto struct ip_mreq mreq; 71854359Sroberto int i = ninterfaces; /* Use the next interface */ 71954359Sroberto u_int32 haddr = ntohl(addr); 72054359Sroberto struct in_addr iaddr; 72154359Sroberto int s; 72254359Sroberto struct sockaddr_in *sinp; 72354359Sroberto 72454359Sroberto iaddr.s_addr = addr; 72554359Sroberto 72654359Sroberto if (!IN_CLASSD(haddr)) 72754359Sroberto { 72854359Sroberto msyslog(LOG_ERR, 72954359Sroberto "cannot add multicast address %s as it is not class D", 73054359Sroberto inet_ntoa(iaddr)); 73154359Sroberto return; 73254359Sroberto } 73354359Sroberto 73454359Sroberto for (i = 0; i < ninterfaces; i++) 73554359Sroberto { 73654359Sroberto /* Already have this address */ 73754359Sroberto if (inter_list[i].sin.sin_addr.s_addr == addr) return; 73854359Sroberto /* found a free slot */ 73954359Sroberto if (inter_list[i].sin.sin_addr.s_addr == 0 && 74054359Sroberto inter_list[i].fd <= 0 && inter_list[i].bfd <= 0 && 74154359Sroberto inter_list[i].flags == 0) break; 74254359Sroberto } 74354359Sroberto sinp = &(inter_list[i].sin); 74454359Sroberto 74554359Sroberto memset((char *)&mreq, 0, sizeof(mreq)); 74654359Sroberto memset((char *)&inter_list[i], 0, sizeof inter_list[0]); 74754359Sroberto sinp->sin_family = AF_INET; 74854359Sroberto sinp->sin_addr = iaddr; 74954359Sroberto sinp->sin_port = htons(123); 75054359Sroberto 75154359Sroberto s = open_socket(sinp, 0, 1); 75254359Sroberto /* Try opening a socket for the specified class D address */ 75354359Sroberto /* This works under SunOS 4.x, but not OSF1 .. :-( */ 75454359Sroberto if (s < 0) 75554359Sroberto { 75654359Sroberto memset((char *)&inter_list[i], 0, sizeof inter_list[0]); 75754359Sroberto i = 0; 75854359Sroberto /* HACK ! -- stuff in an address */ 75954359Sroberto inter_list[i].bcast.sin_addr.s_addr = addr; 76054359Sroberto msyslog(LOG_ERR, "...multicast address %s using wildcard socket", 76154359Sroberto inet_ntoa(iaddr)); 76254359Sroberto } 76354359Sroberto else 76454359Sroberto { 76554359Sroberto inter_list[i].fd = s; 76654359Sroberto inter_list[i].bfd = -1; 76754359Sroberto (void) strncpy(inter_list[i].name, "multicast", 76854359Sroberto sizeof(inter_list[i].name)); 76954359Sroberto inter_list[i].mask.sin_addr.s_addr = htonl(~(u_int32)0); 77054359Sroberto } 77154359Sroberto 77254359Sroberto /* 77354359Sroberto * enable reception of multicast packets 77454359Sroberto */ 77554359Sroberto mreq.imr_multiaddr = iaddr; 77654359Sroberto mreq.imr_interface.s_addr = htonl(INADDR_ANY); 77754359Sroberto if (setsockopt(inter_list[i].fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, 77854359Sroberto (char *)&mreq, sizeof(mreq)) == -1) 77954359Sroberto msyslog(LOG_ERR, 78054359Sroberto "setsockopt IP_ADD_MEMBERSHIP fails: %m for %x / %x (%s)", 78154359Sroberto mreq.imr_multiaddr.s_addr, mreq.imr_interface.s_addr, 78254359Sroberto inet_ntoa(iaddr)); 78354359Sroberto inter_list[i].flags |= INT_MULTICAST; 78454359Sroberto if (i >= ninterfaces) ninterfaces = i+1; 78554359Sroberto#else /* MCAST */ 78654359Sroberto struct in_addr iaddr; 78754359Sroberto 78854359Sroberto iaddr.s_addr = addr; 78954359Sroberto msyslog(LOG_ERR, "cannot add multicast address %s as no MCAST support", 79054359Sroberto inet_ntoa(iaddr)); 79154359Sroberto#endif /* MCAST */ 79254359Sroberto} 79354359Sroberto 79454359Sroberto/* 79554359Sroberto * io_unsetbclient - close the broadcast client sockets 79654359Sroberto */ 79754359Srobertovoid 79854359Srobertoio_unsetbclient(void) 79954359Sroberto{ 80054359Sroberto int i; 80154359Sroberto 80254359Sroberto for (i = 1; i < ninterfaces; i++) 80354359Sroberto { 80454359Sroberto if (!(inter_list[i].flags & INT_BCASTOPEN)) 80554359Sroberto continue; 80654359Sroberto close_socket(inter_list[i].bfd); 80754359Sroberto inter_list[i].bfd = -1; 80854359Sroberto inter_list[i].flags &= ~INT_BCASTOPEN; 80954359Sroberto } 81054359Sroberto} 81154359Sroberto 81254359Sroberto 81354359Sroberto/* 81454359Sroberto * io_multicast_del() - delete multicast group address 81554359Sroberto */ 81654359Srobertovoid 81754359Srobertoio_multicast_del( 81854359Sroberto u_int32 addr 81954359Sroberto ) 82054359Sroberto{ 82154359Sroberto#ifdef MCAST 82254359Sroberto int i; 82354359Sroberto struct ip_mreq mreq; 82454359Sroberto u_int32 haddr = ntohl(addr); 82554359Sroberto struct sockaddr_in sinaddr; 82654359Sroberto 82754359Sroberto if (!IN_CLASSD(haddr)) 82854359Sroberto { 82954359Sroberto sinaddr.sin_addr.s_addr = addr; 83054359Sroberto msyslog(LOG_ERR, 83154359Sroberto "invalid multicast address %s", ntoa(&sinaddr)); 83254359Sroberto return; 83354359Sroberto } 83454359Sroberto 83554359Sroberto /* 83654359Sroberto * Disable reception of multicast packets 83754359Sroberto */ 83854359Sroberto mreq.imr_multiaddr.s_addr = addr; 83954359Sroberto mreq.imr_interface.s_addr = htonl(INADDR_ANY); 84054359Sroberto for (i = 0; i < ninterfaces; i++) 84154359Sroberto { 84254359Sroberto if (!(inter_list[i].flags & INT_MULTICAST)) 84354359Sroberto continue; 84454359Sroberto if (!(inter_list[i].fd < 0)) 84554359Sroberto continue; 84654359Sroberto if (addr != inter_list[i].sin.sin_addr.s_addr) 84754359Sroberto continue; 84854359Sroberto if (i != 0) 84954359Sroberto { 85054359Sroberto /* we have an explicit fd, so we can close it */ 85154359Sroberto close_socket(inter_list[i].fd); 85254359Sroberto memset((char *)&inter_list[i], 0, sizeof inter_list[0]); 85354359Sroberto inter_list[i].fd = -1; 85454359Sroberto inter_list[i].bfd = -1; 85554359Sroberto } 85654359Sroberto else 85754359Sroberto { 85854359Sroberto /* We are sharing "any address" port :-( Don't close it! */ 85954359Sroberto if (setsockopt(inter_list[i].fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, 86054359Sroberto (char *)&mreq, sizeof(mreq)) == -1) 86154359Sroberto msyslog(LOG_ERR, "setsockopt IP_DROP_MEMBERSHIP fails: %m"); 86254359Sroberto /* This is **WRONG** -- there may be others ! */ 86354359Sroberto /* There should be a count of users ... */ 86454359Sroberto inter_list[i].flags &= ~INT_MULTICAST; 86554359Sroberto } 86654359Sroberto } 86754359Sroberto#else /* not MCAST */ 86854359Sroberto msyslog(LOG_ERR, "this function requires multicast kernel"); 86954359Sroberto#endif /* not MCAST */ 87054359Sroberto} 87154359Sroberto 87254359Sroberto 87354359Sroberto/* 87454359Sroberto * open_socket - open a socket, returning the file descriptor 87554359Sroberto */ 87654359Srobertostatic int 87754359Srobertoopen_socket( 87854359Sroberto struct sockaddr_in *addr, 87954359Sroberto int flags, 88054359Sroberto int turn_off_reuse 88154359Sroberto ) 88254359Sroberto{ 88354359Sroberto int fd; 88454359Sroberto int on = 1, off = 0; 88554359Sroberto 88654359Sroberto /* create a datagram (UDP) socket */ 88754359Sroberto if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) 88854359Sroberto#ifndef SYS_WINNT 88954359Sroberto < 0 89054359Sroberto#else 89154359Sroberto == INVALID_SOCKET 89254359Sroberto#endif /* SYS_WINNT */ 89354359Sroberto ) 89454359Sroberto { 89554359Sroberto msyslog(LOG_ERR, "socket(AF_INET, SOCK_DGRAM, 0) failed: %m"); 89654359Sroberto exit(1); 89754359Sroberto /*NOTREACHED*/ 89854359Sroberto } 89954359Sroberto 90054359Sroberto /* set SO_REUSEADDR since we will be binding the same port 90154359Sroberto number on each interface */ 90254359Sroberto if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 90354359Sroberto (char *)&on, sizeof(on))) 90454359Sroberto { 90554359Sroberto msyslog(LOG_ERR, "setsockopt SO_REUSEADDR on fails: %m"); 90654359Sroberto } 90754359Sroberto 90854359Sroberto /* 90954359Sroberto * bind the local address. 91054359Sroberto */ 91154359Sroberto if (bind(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0) { 91254359Sroberto char buff[160]; 91354359Sroberto sprintf(buff, 91454359Sroberto "bind() fd %d, family %d, port %d, addr %s, in_classd=%d flags=%d fails: %%m", 91554359Sroberto fd, addr->sin_family, (int)ntohs(addr->sin_port), 91654359Sroberto ntoa(addr), 91754359Sroberto IN_CLASSD(ntohl(addr->sin_addr.s_addr)), flags); 91854359Sroberto msyslog(LOG_ERR, buff); 91954359Sroberto closesocket(fd); 92054359Sroberto 92154359Sroberto /* 92254359Sroberto * soft fail if opening a class D address 92354359Sroberto */ 92454359Sroberto if (IN_CLASSD(ntohl(addr->sin_addr.s_addr))) 92554359Sroberto return -1; 92654359Sroberto#if 0 92754359Sroberto exit(1); 92854359Sroberto#else 92954359Sroberto return -1; 93054359Sroberto#endif 93154359Sroberto } 93254359Sroberto#ifdef DEBUG 93354359Sroberto if (debug) 93454359Sroberto printf("bind() fd %d, family %d, port %d, addr %s, flags=%d\n", 93554359Sroberto fd, 93654359Sroberto addr->sin_family, 93754359Sroberto (int)ntohs(addr->sin_port), 93854359Sroberto ntoa(addr), 93954359Sroberto flags); 94054359Sroberto#endif 94154359Sroberto if (fd > maxactivefd) 94254359Sroberto maxactivefd = fd; 94354359Sroberto FD_SET(fd, &activefds); 94454359Sroberto 94554359Sroberto /* 94654359Sroberto * set non-blocking, 94754359Sroberto */ 94854359Sroberto 94954359Sroberto#ifdef USE_FIONBIO 95054359Sroberto /* in vxWorks we use FIONBIO, but the others are defined for old systems, so 95154359Sroberto * all hell breaks loose if we leave them defined 95254359Sroberto */ 95354359Sroberto#undef O_NONBLOCK 95454359Sroberto#undef FNDELAY 95554359Sroberto#undef O_NDELAY 95654359Sroberto#endif 95754359Sroberto 95854359Sroberto#if defined(O_NONBLOCK) /* POSIX */ 95954359Sroberto if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) 96054359Sroberto { 96154359Sroberto msyslog(LOG_ERR, "fcntl(O_NONBLOCK) fails: %m"); 96254359Sroberto exit(1); 96354359Sroberto /*NOTREACHED*/ 96454359Sroberto } 96554359Sroberto#elif defined(FNDELAY) 96654359Sroberto if (fcntl(fd, F_SETFL, FNDELAY) < 0) 96754359Sroberto { 96854359Sroberto msyslog(LOG_ERR, "fcntl(FNDELAY) fails: %m"); 96954359Sroberto exit(1); 97054359Sroberto /*NOTREACHED*/ 97154359Sroberto } 97254359Sroberto#elif defined(O_NDELAY) /* generally the same as FNDELAY */ 97354359Sroberto if (fcntl(fd, F_SETFL, O_NDELAY) < 0) 97454359Sroberto { 97554359Sroberto msyslog(LOG_ERR, "fcntl(O_NDELAY) fails: %m"); 97654359Sroberto exit(1); 97754359Sroberto /*NOTREACHED*/ 97854359Sroberto } 97954359Sroberto#elif defined(FIONBIO) 98054359Sroberto if ( 98154359Sroberto# if defined(VMS) 98254359Sroberto (ioctl(fd,FIONBIO,&1) < 0) 98354359Sroberto# elif defined(SYS_WINNT) 98454359Sroberto (ioctlsocket(fd,FIONBIO,(u_long *) &on) == SOCKET_ERROR) 98554359Sroberto# else 98654359Sroberto (ioctl(fd,FIONBIO,&on) < 0) 98754359Sroberto# endif 98854359Sroberto ) 98954359Sroberto { 99054359Sroberto msyslog(LOG_ERR, "ioctl(FIONBIO) fails: %m"); 99154359Sroberto exit(1); 99254359Sroberto /*NOTREACHED*/ 99354359Sroberto } 99454359Sroberto#elif defined(FIOSNBIO) 99554359Sroberto if (ioctl(fd,FIOSNBIO,&on) < 0) 99654359Sroberto { 99754359Sroberto msyslog(LOG_ERR, "ioctl(FIOSNBIO) fails: %m"); 99854359Sroberto exit(1); 99954359Sroberto /*NOTREACHED*/ 100054359Sroberto } 100154359Sroberto#else 100254359Sroberto# include "Bletch: Need non-blocking I/O!" 100354359Sroberto#endif 100454359Sroberto 100554359Sroberto#ifdef HAVE_SIGNALED_IO 100654359Sroberto init_socket_sig(fd); 100754359Sroberto#endif /* not HAVE_SIGNALED_IO */ 100854359Sroberto 100954359Sroberto /* 101054359Sroberto * Turn off the SO_REUSEADDR socket option. It apparently 101154359Sroberto * causes heartburn on systems with multicast IP installed. 101254359Sroberto * On normal systems it only gets looked at when the address 101354359Sroberto * is being bound anyway.. 101454359Sroberto */ 101554359Sroberto if (turn_off_reuse) 101654359Sroberto if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 101754359Sroberto (char *)&off, sizeof(off))) 101854359Sroberto { 101954359Sroberto msyslog(LOG_ERR, "setsockopt SO_REUSEADDR off fails: %m"); 102054359Sroberto } 102154359Sroberto 102254359Sroberto#ifdef SO_BROADCAST 102354359Sroberto /* if this interface can support broadcast, set SO_BROADCAST */ 102454359Sroberto if (flags & INT_BROADCAST) 102554359Sroberto { 102654359Sroberto if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, 102754359Sroberto (char *)&on, sizeof(on))) 102854359Sroberto { 102954359Sroberto msyslog(LOG_ERR, "setsockopt(SO_BROADCAST): %m"); 103054359Sroberto } 103154359Sroberto } 103254359Sroberto#endif /* SO_BROADCAST */ 103354359Sroberto 103454359Sroberto#if !defined(SYS_WINNT) && !defined(VMS) 103554359Sroberto# ifdef DEBUG 103654359Sroberto if (debug > 1) 103754359Sroberto printf("flags for fd %d: 0%o\n", fd, 103854359Sroberto fcntl(fd, F_GETFL, 0)); 103954359Sroberto# endif 104054359Sroberto#endif /* SYS_WINNT || VMS */ 104154359Sroberto 104254359Sroberto return fd; 104354359Sroberto} 104454359Sroberto 104554359Sroberto 104654359Sroberto/* 104754359Sroberto * close_socket - close a socket and remove from the activefd list 104854359Sroberto */ 104954359Srobertostatic void 105054359Srobertoclose_socket( 105154359Sroberto int fd 105254359Sroberto ) 105354359Sroberto{ 105454359Sroberto int i, newmax; 105554359Sroberto 105654359Sroberto (void) closesocket(fd); 105754359Sroberto FD_CLR( (u_int) fd, &activefds); 105854359Sroberto 105954359Sroberto if (fd >= maxactivefd) 106054359Sroberto { 106154359Sroberto newmax = 0; 106254359Sroberto for (i = 0; i < maxactivefd; i++) 106354359Sroberto if (FD_ISSET(i, &activefds)) 106454359Sroberto newmax = i; 106554359Sroberto maxactivefd = newmax; 106654359Sroberto } 106754359Sroberto} 106854359Sroberto 106954359Sroberto 107054359Sroberto/* 107154359Sroberto * close_file - close a file and remove from the activefd list 107254359Sroberto * added 1/31/1997 Greg Schueman for Windows NT portability 107354359Sroberto */ 107454359Srobertostatic void 107554359Srobertoclose_file( 107654359Sroberto int fd 107754359Sroberto ) 107854359Sroberto{ 107954359Sroberto int i, newmax; 108054359Sroberto 108154359Sroberto (void) close(fd); 108254359Sroberto FD_CLR( (u_int) fd, &activefds); 108354359Sroberto 108454359Sroberto if (fd >= maxactivefd) 108554359Sroberto { 108654359Sroberto newmax = 0; 108754359Sroberto for (i = 0; i < maxactivefd; i++) 108854359Sroberto if (FD_ISSET(i, &activefds)) 108954359Sroberto newmax = i; 109054359Sroberto maxactivefd = newmax; 109154359Sroberto } 109254359Sroberto} 109354359Sroberto 109454359Sroberto 109554359Sroberto/* 109654359Sroberto * findbcastinter - find broadcast interface corresponding to address 109754359Sroberto */ 109854359Srobertostruct interface * 109954359Srobertofindbcastinter( 110054359Sroberto struct sockaddr_in *addr 110154359Sroberto ) 110254359Sroberto{ 110354359Sroberto#if defined(SIOCGIFCONF) || defined(SYS_WINNT) 110454359Sroberto register int i; 110554359Sroberto register u_int32 netnum; 110654359Sroberto 110754359Sroberto netnum = NSRCADR(addr); 110854359Sroberto for (i = 1; i < ninterfaces; i++) 110954359Sroberto { 111054359Sroberto if (!(inter_list[i].flags & INT_BROADCAST)) 111154359Sroberto continue; 111254359Sroberto if (NSRCADR(&inter_list[i].bcast) == netnum) 111354359Sroberto return &inter_list[i]; 111454359Sroberto if ((NSRCADR(&inter_list[i].sin) & NSRCADR(&inter_list[i].mask)) 111554359Sroberto == (netnum & NSRCADR(&inter_list[i].mask))) 111654359Sroberto return &inter_list[i]; 111754359Sroberto } 111854359Sroberto#endif /* SIOCGIFCONF */ 111954359Sroberto return any_interface; 112054359Sroberto} 112154359Sroberto 112254359Sroberto 112354359Sroberto/* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */ 112454359Sroberto/* 112554359Sroberto * sendpkt - send a packet to the specified destination. Maintain a 112654359Sroberto * send error cache so that only the first consecutive error for a 112754359Sroberto * destination is logged. 112854359Sroberto */ 112954359Srobertovoid 113054359Srobertosendpkt( 113154359Sroberto struct sockaddr_in *dest, 113254359Sroberto struct interface *inter, 113354359Sroberto int ttl, 113454359Sroberto struct pkt *pkt, 113554359Sroberto int len 113654359Sroberto ) 113754359Sroberto{ 113854359Sroberto int cc, slot; 113954359Sroberto#ifdef SYS_WINNT 114054359Sroberto DWORD err; 114154359Sroberto#endif /* SYS_WINNT */ 114254359Sroberto 114354359Sroberto /* 114454359Sroberto * Send error cache. Empty slots have port == 0 114554359Sroberto * Set ERRORCACHESIZE to 0 to disable 114654359Sroberto */ 114754359Sroberto struct cache { 114854359Sroberto u_short port; 114954359Sroberto struct in_addr addr; 115054359Sroberto }; 115154359Sroberto 115254359Sroberto#ifndef ERRORCACHESIZE 115354359Sroberto#define ERRORCACHESIZE 8 115454359Sroberto#endif 115554359Sroberto#if ERRORCACHESIZE > 0 115654359Sroberto static struct cache badaddrs[ERRORCACHESIZE]; 115754359Sroberto#else 115854359Sroberto#define badaddrs ((struct cache *)0) /* Only used in empty loops! */ 115954359Sroberto#endif 116054359Sroberto 116154359Sroberto /* 116254359Sroberto * check if the source address is a multicast address - replace 116354359Sroberto * interface with any-interface if so. 116454359Sroberto */ 116554359Sroberto if (IN_MULTICAST(ntohl(inter->sin.sin_addr.s_addr))) 116654359Sroberto inter = any_interface; 116754359Sroberto#ifdef DEBUG 116854359Sroberto if (debug > 1) 116954359Sroberto printf("%ssendpkt(fd=%d dst=%s, src=%s, ttl=%d, len=%d)\n", 117054359Sroberto (ttl >= 0) ? "\tMCAST\t*****" : "", 117154359Sroberto inter->fd, ntoa(dest), 117254359Sroberto ntoa(&inter->sin), ttl, len); 117354359Sroberto#endif 117454359Sroberto 117554359Sroberto#ifdef MCAST 117654359Sroberto /* for the moment we use the bcast option to set multicast ttl */ 117754359Sroberto if (ttl >= 0 && ttl != inter->last_ttl) 117854359Sroberto { 117954359Sroberto char mttl = ttl; 118054359Sroberto 118154359Sroberto /* set the multicast ttl for outgoing packets */ 118254359Sroberto if (setsockopt(inter->fd, IPPROTO_IP, IP_MULTICAST_TTL, 118354359Sroberto &mttl, sizeof(mttl)) == -1) 118454359Sroberto { 118554359Sroberto msyslog(LOG_ERR, "setsockopt IP_MULTICAST_TTL fails: %m"); 118654359Sroberto } 118754359Sroberto else inter->last_ttl = ttl; 118854359Sroberto } 118954359Sroberto#endif /* MCAST */ 119054359Sroberto 119154359Sroberto for (slot = ERRORCACHESIZE; --slot >= 0; ) 119254359Sroberto if (badaddrs[slot].port == dest->sin_port && 119354359Sroberto badaddrs[slot].addr.s_addr == dest->sin_addr.s_addr) 119454359Sroberto break; 119554359Sroberto 119654359Sroberto#if defined(HAVE_IO_COMPLETION_PORT) 119754359Sroberto err = io_completion_port_sendto(inter, pkt, len, dest); 119854359Sroberto if (err != ERROR_SUCCESS) 119954359Sroberto#else 120054359Sroberto cc = sendto(inter->fd, (char *)pkt, len, 0, (struct sockaddr *)dest, 120154359Sroberto sizeof(struct sockaddr_in)); 120254359Sroberto if (cc == -1) 120354359Sroberto#endif 120454359Sroberto { 120554359Sroberto inter->notsent++; 120654359Sroberto packets_notsent++; 120754359Sroberto#if defined(HAVE_IO_COMPLETION_PORT) 120854359Sroberto if (err != WSAEWOULDBLOCK && err != WSAENOBUFS && slot < 0) 120954359Sroberto#else 121054359Sroberto if (errno != EWOULDBLOCK && errno != ENOBUFS && slot < 0) 121154359Sroberto#endif 121254359Sroberto { 121354359Sroberto /* 121454359Sroberto * Remember this, if there's an empty slot 121554359Sroberto */ 121654359Sroberto for (slot = ERRORCACHESIZE; --slot >= 0; ) 121754359Sroberto if (badaddrs[slot].port == 0) 121854359Sroberto { 121954359Sroberto badaddrs[slot].port = dest->sin_port; 122054359Sroberto badaddrs[slot].addr = dest->sin_addr; 122154359Sroberto break; 122254359Sroberto } 122354359Sroberto msyslog(LOG_ERR, "sendto(%s): %m", ntoa(dest)); 122454359Sroberto } 122554359Sroberto } 122654359Sroberto else 122754359Sroberto { 122854359Sroberto inter->sent++; 122954359Sroberto packets_sent++; 123054359Sroberto /* 123154359Sroberto * He's not bad any more 123254359Sroberto */ 123354359Sroberto if (slot >= 0) 123454359Sroberto { 123554359Sroberto msyslog(LOG_INFO, "Connection re-established to %s", ntoa(dest)); 123654359Sroberto badaddrs[slot].port = 0; 123754359Sroberto } 123854359Sroberto } 123954359Sroberto} 124054359Sroberto 124154359Sroberto#if !defined(HAVE_IO_COMPLETION_PORT) 124254359Sroberto/* 124354359Sroberto * fdbits - generate ascii representation of fd_set (FAU debug support) 124454359Sroberto * HFDF format - highest fd first. 124554359Sroberto */ 124654359Srobertostatic char * 124754359Srobertofdbits( 124854359Sroberto int count, 124954359Sroberto fd_set *set 125054359Sroberto ) 125154359Sroberto{ 125254359Sroberto static char buffer[256]; 125354359Sroberto char * buf = buffer; 125454359Sroberto 125554359Sroberto count = (count < 256) ? count : 255; 125654359Sroberto 125754359Sroberto while (count >= 0) 125854359Sroberto { 125954359Sroberto *buf++ = FD_ISSET(count, set) ? '#' : '-'; 126054359Sroberto count--; 126154359Sroberto } 126254359Sroberto *buf = '\0'; 126354359Sroberto 126454359Sroberto return buffer; 126554359Sroberto} 126654359Sroberto 126754359Sroberto/* 126854359Sroberto * input_handler - receive packets asynchronously 126954359Sroberto */ 127054359Srobertoextern void 127154359Srobertoinput_handler( 127254359Sroberto l_fp *cts 127354359Sroberto ) 127454359Sroberto{ 127554359Sroberto register int i, n; 127654359Sroberto register struct recvbuf *rb; 127754359Sroberto register int doing; 127854359Sroberto register int fd; 127954359Sroberto struct timeval tvzero; 128054359Sroberto int fromlen; 128154359Sroberto l_fp ts; /* Timestamp at BOselect() gob */ 128254359Sroberto l_fp ts_e; /* Timestamp at EOselect() gob */ 128354359Sroberto fd_set fds; 128454359Sroberto int select_count = 0; 128554359Sroberto static int handler_count = 0; 128654359Sroberto 128754359Sroberto ++handler_count; 128854359Sroberto if (handler_count != 1) 128954359Sroberto msyslog(LOG_ERR, "input_handler: handler_count is %d!", handler_count); 129054359Sroberto handler_calls++; 129154359Sroberto ts = *cts; 129254359Sroberto 129354359Sroberto for (;;) 129454359Sroberto { 129554359Sroberto /* 129654359Sroberto * Do a poll to see who has data 129754359Sroberto */ 129854359Sroberto 129954359Sroberto fds = activefds; 130054359Sroberto tvzero.tv_sec = tvzero.tv_usec = 0; 130154359Sroberto 130254359Sroberto /* 130354359Sroberto * If we have something to do, freeze a timestamp. 130454359Sroberto * See below for the other cases (nothing (left) to do or error) 130554359Sroberto */ 130654359Sroberto while (0 < (n = select(maxactivefd+1, &fds, (fd_set *)0, (fd_set *)0, &tvzero))) 130754359Sroberto { 130854359Sroberto ++select_count; 130954359Sroberto ++handler_pkts; 131054359Sroberto 131154359Sroberto#ifdef REFCLOCK 131254359Sroberto /* 131354359Sroberto * Check out the reference clocks first, if any 131454359Sroberto */ 131554359Sroberto if (refio != 0) 131654359Sroberto { 131754359Sroberto register struct refclockio *rp; 131854359Sroberto 131954359Sroberto for (rp = refio; rp != 0 && n > 0; rp = rp->next) 132054359Sroberto { 132154359Sroberto fd = rp->fd; 132254359Sroberto if (FD_ISSET(fd, &fds)) 132354359Sroberto { 132454359Sroberto n--; 132554359Sroberto if (free_recvbuffs() == 0) 132654359Sroberto { 132754359Sroberto char buf[RX_BUFF_SIZE]; 132854359Sroberto 132954359Sroberto#ifndef SYS_WINNT 133054359Sroberto (void) read(fd, buf, sizeof buf); 133154359Sroberto#else 133254359Sroberto (void) ReadFile((HANDLE)fd, buf, (DWORD)sizeof buf, NULL, NULL); 133354359Sroberto#endif /* SYS_WINNT */ 133454359Sroberto packets_dropped++; 133554359Sroberto goto select_again; 133654359Sroberto } 133754359Sroberto 133854359Sroberto rb = get_free_recv_buffer(); 133954359Sroberto 134054359Sroberto i = (rp->datalen == 0 134154359Sroberto || rp->datalen > sizeof(rb->recv_space)) 134254359Sroberto ? sizeof(rb->recv_space) : rp->datalen; 134354359Sroberto#ifndef SYS_WINNT 134454359Sroberto rb->recv_length = 134554359Sroberto read(fd, (char *)&rb->recv_space, (unsigned)i) 134654359Sroberto#else /* SYS_WINNT */ 134754359Sroberto ReadFile((HANDLE)fd, (char *)&rb->recv_space, (DWORD)i, 134854359Sroberto (LPDWORD)&(rb->recv_length), NULL) 134954359Sroberto#endif /* SYS_WINNT */ 135054359Sroberto ; 135154359Sroberto 135254359Sroberto if (rb->recv_length == -1) 135354359Sroberto { 135454359Sroberto msyslog(LOG_ERR, "clock read fd %d: %m", fd); 135554359Sroberto freerecvbuf(rb); 135654359Sroberto goto select_again; 135754359Sroberto } 135854359Sroberto 135954359Sroberto /* 136054359Sroberto * Got one. Mark how and when it got here, 136154359Sroberto * put it on the full list and do bookkeeping. 136254359Sroberto */ 136354359Sroberto rb->recv_srcclock = rp->srcclock; 136454359Sroberto rb->dstadr = 0; 136554359Sroberto rb->fd = fd; 136654359Sroberto rb->recv_time = ts; 136754359Sroberto rb->receiver = rp->clock_recv; 136854359Sroberto 136954359Sroberto if (rp->io_input) 137054359Sroberto { 137154359Sroberto /* 137254359Sroberto * have direct input routine for refclocks 137354359Sroberto */ 137454359Sroberto if (rp->io_input(rb) == 0) 137554359Sroberto { 137654359Sroberto /* 137754359Sroberto * data was consumed - nothing to pass up 137854359Sroberto * into block input machine 137954359Sroberto */ 138054359Sroberto freerecvbuf(rb); 138154359Sroberto#if 1 138254359Sroberto goto select_again; 138354359Sroberto#else 138454359Sroberto continue; 138554359Sroberto#endif 138654359Sroberto } 138754359Sroberto } 138854359Sroberto 138954359Sroberto add_full_recv_buffer(rb); 139054359Sroberto 139154359Sroberto rp->recvcount++; 139254359Sroberto packets_received++; 139354359Sroberto } 139454359Sroberto } 139554359Sroberto } 139654359Sroberto#endif /* REFCLOCK */ 139754359Sroberto 139854359Sroberto /* 139954359Sroberto * Loop through the interfaces looking for data to read. 140054359Sroberto */ 140154359Sroberto for (i = ninterfaces - 1; (i >= 0) && (n > 0); i--) 140254359Sroberto { 140354359Sroberto for (doing = 0; (doing < 2) && (n > 0); doing++) 140454359Sroberto { 140554359Sroberto if (doing == 0) 140654359Sroberto { 140754359Sroberto fd = inter_list[i].fd; 140854359Sroberto } 140954359Sroberto else 141054359Sroberto { 141154359Sroberto if (!(inter_list[i].flags & INT_BCASTOPEN)) 141254359Sroberto break; 141354359Sroberto fd = inter_list[i].bfd; 141454359Sroberto } 141554359Sroberto if (fd < 0) continue; 141654359Sroberto if (FD_ISSET(fd, &fds)) 141754359Sroberto { 141854359Sroberto n--; 141954359Sroberto 142054359Sroberto /* 142154359Sroberto * Get a buffer and read the frame. If we 142254359Sroberto * haven't got a buffer, or this is received 142354359Sroberto * on the wild card socket, just dump the 142454359Sroberto * packet. 142554359Sroberto */ 142654359Sroberto if ( 142754359Sroberto#ifdef UDP_WILDCARD_DELIVERY 142854359Sroberto /* 142954359Sroberto * these guys manage to put properly addressed 143054359Sroberto * packets into the wildcard queue 143154359Sroberto */ 143254359Sroberto (free_recvbuffs() == 0) 143354359Sroberto#else 143454359Sroberto ((i == 0) || (free_recvbuffs() == 0)) 143554359Sroberto#endif 143654359Sroberto ) 143754359Sroberto { 143854359Sroberto char buf[RX_BUFF_SIZE]; 143954359Sroberto struct sockaddr from; 144054359Sroberto 144154359Sroberto fromlen = sizeof from; 144254359Sroberto (void) recvfrom(fd, buf, sizeof(buf), 0, &from, &fromlen); 144354359Sroberto#ifdef DEBUG 144454359Sroberto if (debug) 144554359Sroberto printf("%s on %d(%lu) fd=%d from %s\n", 144654359Sroberto (i) ? "drop" : "ignore", 144754359Sroberto i, free_recvbuffs(), fd, 144854359Sroberto inet_ntoa(((struct sockaddr_in *) &from)->sin_addr)); 144954359Sroberto#endif 145054359Sroberto if (i == 0) 145154359Sroberto packets_ignored++; 145254359Sroberto else 145354359Sroberto packets_dropped++; 145454359Sroberto goto select_again; 145554359Sroberto } 145654359Sroberto 145754359Sroberto rb = get_free_recv_buffer(); 145854359Sroberto 145954359Sroberto fromlen = sizeof(struct sockaddr_in); 146054359Sroberto rb->recv_length = recvfrom(fd, 146154359Sroberto (char *)&rb->recv_space, 146254359Sroberto sizeof(rb->recv_space), 0, 146354359Sroberto (struct sockaddr *)&rb->recv_srcadr, 146454359Sroberto &fromlen); 146554359Sroberto if (rb->recv_length == 0 146654359Sroberto#ifdef EWOULDBLOCK 146754359Sroberto || errno==EWOULDBLOCK 146854359Sroberto#endif 146954359Sroberto#ifdef EAGAIN 147054359Sroberto || errno==EAGAIN 147154359Sroberto#endif 147254359Sroberto ) { 147354359Sroberto freerecvbuf(rb); 147454359Sroberto continue; 147554359Sroberto } 147654359Sroberto else if (rb->recv_length < 0) 147754359Sroberto { 147854359Sroberto msyslog(LOG_ERR, "recvfrom() fd=%d: %m", fd); 147954359Sroberto#ifdef DEBUG 148054359Sroberto if (debug) 148154359Sroberto printf("input_handler: fd=%d dropped (bad recvfrom)\n", fd); 148254359Sroberto#endif 148354359Sroberto freerecvbuf(rb); 148454359Sroberto continue; 148554359Sroberto } 148654359Sroberto#ifdef DEBUG 148754359Sroberto if (debug > 2) 148854359Sroberto printf("input_handler: fd=%d length %d from %08lx %s\n", 148954359Sroberto fd, rb->recv_length, 149054359Sroberto (u_long)ntohl(rb->recv_srcadr.sin_addr.s_addr) & 149154359Sroberto 0x00000000ffffffff, 149254359Sroberto inet_ntoa(rb->recv_srcadr.sin_addr)); 149354359Sroberto#endif 149454359Sroberto 149554359Sroberto /* 149654359Sroberto * Got one. Mark how and when it got here, 149754359Sroberto * put it on the full list and do bookkeeping. 149854359Sroberto */ 149954359Sroberto rb->dstadr = &inter_list[i]; 150054359Sroberto rb->fd = fd; 150154359Sroberto rb->recv_time = ts; 150254359Sroberto rb->receiver = receive; 150354359Sroberto 150454359Sroberto add_full_recv_buffer(rb); 150554359Sroberto 150654359Sroberto inter_list[i].received++; 150754359Sroberto packets_received++; 150854359Sroberto goto select_again; 150954359Sroberto } 151054359Sroberto /* Check more interfaces */ 151154359Sroberto } 151254359Sroberto } 151354359Sroberto select_again:; 151454359Sroberto /* 151554359Sroberto * Done everything from that select. Poll again. 151654359Sroberto */ 151754359Sroberto } 151854359Sroberto 151954359Sroberto /* 152054359Sroberto * If nothing more to do, try again. 152154359Sroberto * If nothing to do, just return. 152254359Sroberto * If an error occurred, complain and return. 152354359Sroberto */ 152454359Sroberto if (n == 0) 152554359Sroberto { 152654359Sroberto if (select_count == 0) /* We really had nothing to do */ 152754359Sroberto { 152854359Sroberto if (debug) 152954359Sroberto msyslog(LOG_DEBUG, "input_handler: select() returned 0"); 153054359Sroberto --handler_count; 153154359Sroberto return; 153254359Sroberto } 153354359Sroberto /* We've done our work */ 153454359Sroberto get_systime(&ts_e); 153554359Sroberto /* 153654359Sroberto * (ts_e - ts) is the amount of time we spent processing 153754359Sroberto * this gob of file descriptors. Log it. 153854359Sroberto */ 153954359Sroberto L_SUB(&ts_e, &ts); 154054359Sroberto if (debug > 3) 154154359Sroberto msyslog(LOG_INFO, "input_handler: Processed a gob of fd's in %s msec", lfptoms(&ts_e, 6)); 154254359Sroberto 154354359Sroberto /* just bail. */ 154454359Sroberto --handler_count; 154554359Sroberto return; 154654359Sroberto } 154754359Sroberto else if (n == -1) 154854359Sroberto { 154954359Sroberto#ifndef SYS_WINNT 155054359Sroberto int err = errno; 155154359Sroberto#else 155254359Sroberto DWORD err = WSAGetLastError(); 155354359Sroberto#endif /* SYS_WINNT */ 155454359Sroberto 155554359Sroberto /* 155654359Sroberto * extended FAU debugging output 155754359Sroberto */ 155854359Sroberto msyslog(LOG_ERR, "select(%d, %s, 0L, 0L, &0.000000) error: %m", 155954359Sroberto maxactivefd+1, fdbits(maxactivefd, &activefds)); 156054359Sroberto if ( 156154359Sroberto#ifndef SYS_WINNT 156254359Sroberto (err == EBADF) 156354359Sroberto#else 156454359Sroberto (err == WSAEBADF) 156554359Sroberto#endif /* SYS_WINNT */ 156654359Sroberto ) 156754359Sroberto { 156854359Sroberto int j, b; 156954359Sroberto 157054359Sroberto fds = activefds; 157154359Sroberto for (j = 0; j <= maxactivefd; j++) 157254359Sroberto if ( 157354359Sroberto#ifndef SYS_WINNT 157454359Sroberto (FD_ISSET(j, &fds) && (read(j, &b, 0) == -1)) 157554359Sroberto#else 157654359Sroberto (FD_ISSET(j, &fds) && (!ReadFile((HANDLE)j, &b, 0, NULL, NULL))) 157754359Sroberto#endif /* SYS_WINNT */ 157854359Sroberto ) 157954359Sroberto msyslog(LOG_ERR, "Bad file descriptor %d", j); 158054359Sroberto } 158154359Sroberto --handler_count; 158254359Sroberto return; 158354359Sroberto } 158454359Sroberto } 158554359Sroberto msyslog(LOG_ERR, "input_handler: fell out of infinite for(;;) loop!"); 158654359Sroberto --handler_count; 158754359Sroberto return; 158854359Sroberto} 158954359Sroberto 159054359Sroberto#endif 159154359Sroberto 159254359Sroberto/* 159354359Sroberto * findinterface - utility used by other modules to find an interface 159454359Sroberto * given an address. 159554359Sroberto */ 159654359Srobertostruct interface * 159754359Srobertofindinterface( 159854359Sroberto struct sockaddr_in *addr 159954359Sroberto ) 160054359Sroberto{ 160154359Sroberto register int i; 160254359Sroberto register u_int32 saddr; 160354359Sroberto 160454359Sroberto /* 160554359Sroberto * Just match the address portion. 160654359Sroberto */ 160754359Sroberto saddr = addr->sin_addr.s_addr; 160854359Sroberto for (i = 0; i < ninterfaces; i++) 160954359Sroberto { 161054359Sroberto if (inter_list[i].sin.sin_addr.s_addr == saddr) 161154359Sroberto return &inter_list[i]; 161254359Sroberto } 161354359Sroberto return (struct interface *)0; 161454359Sroberto} 161554359Sroberto 161654359Sroberto 161754359Sroberto/* 161854359Sroberto * io_clr_stats - clear I/O module statistics 161954359Sroberto */ 162054359Srobertovoid 162154359Srobertoio_clr_stats(void) 162254359Sroberto{ 162354359Sroberto packets_dropped = 0; 162454359Sroberto packets_ignored = 0; 162554359Sroberto packets_received = 0; 162654359Sroberto packets_sent = 0; 162754359Sroberto packets_notsent = 0; 162854359Sroberto 162954359Sroberto handler_calls = 0; 163054359Sroberto handler_pkts = 0; 163154359Sroberto io_timereset = current_time; 163254359Sroberto} 163354359Sroberto 163454359Sroberto 163554359Sroberto#ifdef REFCLOCK 163654359Sroberto/* 163754359Sroberto * This is a hack so that I don't have to fool with these ioctls in the 163854359Sroberto * pps driver ... we are already non-blocking and turn on SIGIO thru 163954359Sroberto * another mechanisim 164054359Sroberto */ 164154359Srobertoint 164254359Srobertoio_addclock_simple( 164354359Sroberto struct refclockio *rio 164454359Sroberto ) 164554359Sroberto{ 164654359Sroberto BLOCKIO(); 164754359Sroberto /* 164854359Sroberto * Stuff the I/O structure in the list and mark the descriptor 164954359Sroberto * in use. There is a harmless (I hope) race condition here. 165054359Sroberto */ 165154359Sroberto rio->next = refio; 165254359Sroberto refio = rio; 165354359Sroberto 165454359Sroberto if (rio->fd > maxactivefd) 165554359Sroberto maxactivefd = rio->fd; 165654359Sroberto FD_SET(rio->fd, &activefds); 165754359Sroberto UNBLOCKIO(); 165854359Sroberto return 1; 165954359Sroberto} 166054359Sroberto 166154359Sroberto/* 166254359Sroberto * io_addclock - add a reference clock to the list and arrange that we 166354359Sroberto * get SIGIO interrupts from it. 166454359Sroberto */ 166554359Srobertoint 166654359Srobertoio_addclock( 166754359Sroberto struct refclockio *rio 166854359Sroberto ) 166954359Sroberto{ 167054359Sroberto BLOCKIO(); 167154359Sroberto /* 167254359Sroberto * Stuff the I/O structure in the list and mark the descriptor 167354359Sroberto * in use. There is a harmless (I hope) race condition here. 167454359Sroberto */ 167554359Sroberto rio->next = refio; 167654359Sroberto refio = rio; 167754359Sroberto 167854359Sroberto# ifdef HAVE_SIGNALED_IO 167954359Sroberto if (init_clock_sig(rio)) 168054359Sroberto { 168154359Sroberto refio = rio->next; 168254359Sroberto UNBLOCKIO(); 168354359Sroberto return 0; 168454359Sroberto } 168554359Sroberto# elif defined(HAVE_IO_COMPLETION_PORT) 168654359Sroberto if (io_completion_port_add_clock_io(rio)) 168754359Sroberto { 168854359Sroberto refio = rio->next; 168954359Sroberto UNBLOCKIO(); 169054359Sroberto return 0; 169154359Sroberto } 169254359Sroberto# endif 169354359Sroberto 169454359Sroberto if (rio->fd > maxactivefd) 169554359Sroberto maxactivefd = rio->fd; 169654359Sroberto FD_SET(rio->fd, &activefds); 169754359Sroberto 169854359Sroberto UNBLOCKIO(); 169954359Sroberto return 1; 170054359Sroberto} 170154359Sroberto 170254359Sroberto/* 170354359Sroberto * io_closeclock - close the clock in the I/O structure given 170454359Sroberto */ 170554359Srobertovoid 170654359Srobertoio_closeclock( 170754359Sroberto struct refclockio *rio 170854359Sroberto ) 170954359Sroberto{ 171054359Sroberto /* 171154359Sroberto * Remove structure from the list 171254359Sroberto */ 171354359Sroberto if (refio == rio) 171454359Sroberto { 171554359Sroberto refio = rio->next; 171654359Sroberto } 171754359Sroberto else 171854359Sroberto { 171954359Sroberto register struct refclockio *rp; 172054359Sroberto 172154359Sroberto for (rp = refio; rp != 0; rp = rp->next) 172254359Sroberto if (rp->next == rio) 172354359Sroberto { 172454359Sroberto rp->next = rio->next; 172554359Sroberto break; 172654359Sroberto } 172754359Sroberto 172854359Sroberto if (rp == 0) 172954359Sroberto { 173054359Sroberto /* 173154359Sroberto * Internal error. Report it. 173254359Sroberto */ 173354359Sroberto msyslog(LOG_ERR, 173454359Sroberto "internal error: refclockio structure not found"); 173554359Sroberto return; 173654359Sroberto } 173754359Sroberto } 173854359Sroberto 173954359Sroberto /* 174054359Sroberto * Close the descriptor. 174154359Sroberto */ 174254359Sroberto close_file(rio->fd); 174354359Sroberto} 174454359Sroberto#endif /* REFCLOCK */ 174554359Sroberto 174654359Srobertovoid 174754359Srobertokill_asyncio(void) 174854359Sroberto{ 174954359Sroberto int i; 175054359Sroberto 175154359Sroberto BLOCKIO(); 175254359Sroberto for (i = 0; i <= maxactivefd; i++) 175354359Sroberto (void)close_socket(i); 175454359Sroberto} 1755