⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ntp_io.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * ntp_io.c - input/output routines for ntpd.	The socket-opening code *		   was shamelessly stolen from ntpd. */#ifdef HAVE_CONFIG_H# include <config.h>#endif#include "ntp_machine.h"#include "ntpd.h"#include "ntp_io.h"#include "iosignal.h"#include "ntp_refclock.h"#include "ntp_stdlib.h"#include "ntp.h"/* Don't include ISC's version of IPv6 variables and structures */#define ISC_IPV6_H 1#include <isc/interfaceiter.h>#include <isc/list.h>#include <isc/result.h>#ifdef SIM#include "ntpsim.h"#endif#include <stdio.h>#include <signal.h>#ifdef HAVE_SYS_PARAM_H# include <sys/param.h>#endif /* HAVE_SYS_PARAM_H */#ifdef HAVE_SYS_IOCTL_H# include <sys/ioctl.h>#endif#ifdef HAVE_SYS_SOCKIO_H	/* UXPV: SIOC* #defines (Frank Vance <fvance@waii.com>) */# include <sys/sockio.h>#endif/*  * Set up some macros to look for IPv6 and IPv6 multicast */#if defined(ISC_PLATFORM_HAVEIPV6) && !defined(DISABLE_IPV6)#define INCLUDE_IPV6_SUPPORT#if defined(INCLUDE_IPV6_SUPPORT) && defined(IPV6_JOIN_GROUP) && defined(IPV6_LEAVE_GROUP)#define INCLUDE_IPV6_MULTICAST_SUPPORT#endif	/* IPV6 Multicast Support */#endif  /* IPv6 Support */extern int listen_to_virtual_ips;extern const char *specific_interface;#if defined(SYS_WINNT)#include <transmitbuff.h>#include <isc/win32os.h>/* * Define this macro to control the behavior of connection * resets on UDP sockets.  See Microsoft KnowledgeBase Article Q263823 * for details. * NOTE: This requires that Windows 2000 systems install Service Pack 2 * or later. */#ifndef SIO_UDP_CONNRESET #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12) #endif#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. *//* * Other statistics of possible interest */volatile u_long packets_dropped;	/* total number of packets dropped on reception */volatile u_long packets_ignored;	/* packets received on wild card interface */volatile u_long packets_received;	/* total number of packets received */u_long packets_sent;	/* total number of packets sent */u_long packets_notsent; /* total number of packets which couldn't be sent */volatile u_long handler_calls;	/* number of calls to interrupt handler */volatile u_long handler_pkts;	/* number of pkts received by handler */u_long io_timereset;		/* time counters were reset *//* * Interface stuff */struct interface *any_interface;	/* default ipv4 interface */struct interface *any6_interface;	/* default ipv6 interface */struct interface *loopback_interface;	/* loopback ipv4 interface */struct interface *loopback6_interface;	/* loopback ipv6 interface */struct interface inter_list[MAXINTERFACES]; /* Interface list */int ninterfaces;			/* Total number of interfaces */int nwilds;				/* Total number of wildcard intefaces */int wildipv4 = -1;			/* Index into inter_list for IPv4 wildcard */int wildipv6 = -1;			/* Index into inter_list for IPv6 wildcard */#ifdef REFCLOCK/* * 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 *//* * Define what the possible "soft" errors can be.  These are non-fatal returns * of various network related functions, like recv() and so on. * * For some reason, BSDI (and perhaps others) will sometimes return <0 * from recv() but will have errno==0.  This is broken, but we have to * work around it here. */#define SOFT_ERROR(e)	((e) == EAGAIN || \			 (e) == EWOULDBLOCK || \			 (e) == EINTR || \			 (e) == 0)/* * File descriptor masks etc. for call to select * Not needed for I/O Completion Ports */fd_set activefds;int maxactivefd;static	int create_sockets	P((u_short));static	SOCKET	open_socket	P((struct sockaddr_storage *, int, int, struct interface *, int));static	void	close_socket	P((SOCKET));#ifdef REFCLOCKstatic	void	close_file	P((SOCKET));#endifstatic	char *	fdbits		P((int, fd_set *));static	void	set_reuseaddr	P((int));static	isc_boolean_t	socket_broadcast_enable	 P((struct interface *, SOCKET, struct sockaddr_storage *));static	isc_boolean_t	socket_broadcast_disable P((struct interface *, int, struct sockaddr_storage *));/* * Multicast functions */static	isc_boolean_t	addr_ismulticast	 P((struct sockaddr_storage *));/* * Not all platforms support multicast */#ifdef MCASTstatic	isc_boolean_t	socket_multicast_enable	 P((struct interface *, int, int, struct sockaddr_storage *));static	isc_boolean_t	socket_multicast_disable P((struct interface *, int, struct sockaddr_storage *));#endif#ifdef DEBUGstatic void print_interface	P((int));#endiftypedef struct vsock vsock_t;struct vsock {	SOCKET				fd;	ISC_LINK(vsock_t)		link;};ISC_LIST(vsock_t)	sockets_list;typedef struct remaddr remaddr_t;struct remaddr {      struct sockaddr_storage	addr;      int			if_index;      int			flags;      ISC_LINK(remaddr_t)	link;};ISC_LIST(remaddr_t)       remoteaddr_list;void	add_socket_to_list	P((SOCKET));void	delete_socket_from_list	P((SOCKET));void	add_addr_to_list	P((struct sockaddr_storage *, int, int));int     modify_addr_in_list	P((struct sockaddr_storage *, int));void	delete_addr_from_list	P((struct sockaddr_storage *));int     find_addr_in_list	P((struct sockaddr_storage *));int     find_flagged_addr_in_list P((struct sockaddr_storage *, int));int	create_wildcards	P((u_short));isc_boolean_t address_okay	P((isc_interface_t *));void	convert_isc_if		P((isc_interface_t *, struct interface *, u_short));int	findlocalinterface	P((struct sockaddr_storage *));int	findlocalcastinterface	P((struct sockaddr_storage *, int));/* * Routines to read the ntp packets */#if !defined(HAVE_IO_COMPLETION_PORT)static inline int     read_network_packet	P((SOCKET, struct interface *, l_fp));static inline int     read_refclock_packet	P((SOCKET, struct refclockio *, l_fp));#endif#ifdef SYS_WINNT/* * Windows 2000 systems incorrectly cause UDP sockets using WASRecvFrom * to not work correctly, returning a WSACONNRESET error when a WSASendTo * fails with an "ICMP port unreachable" response and preventing the * socket from using the WSARecvFrom in subsequent operations. * The function below fixes this, but requires that Windows 2000 * Service Pack 2 or later be installed on the system.  NT 4.0 * systems are not affected by this and work correctly. * See Microsoft Knowledge Base Article Q263823 for details of this. */isc_result_tconnection_reset_fix(SOCKET fd) {	DWORD dwBytesReturned = 0;	BOOL  bNewBehavior = FALSE;	DWORD status;	if(isc_win32os_majorversion() < 5)		return (ISC_R_SUCCESS); /*  NT 4.0 has no problem */	/* disable bad behavior using IOCTL: SIO_UDP_CONNRESET */	status = WSAIoctl(fd, SIO_UDP_CONNRESET, &bNewBehavior,			  sizeof(bNewBehavior), NULL, 0,			  &dwBytesReturned, NULL, NULL);	if (status != SOCKET_ERROR)		return (ISC_R_SUCCESS);	else		return (ISC_R_UNEXPECTED);}#endif/* * init_io - initialize I/O data structures and call socket creation routine */voidinit_io(void){#ifdef SYS_WINNT	if (!Win32InitSockets())	{		netsyslog(LOG_ERR, "No useable winsock.dll: %m");		exit(1);	}	init_transmitbuff();#endif /* SYS_WINNT */	/*	 * Init buffer free list and stat counters	 */	init_recvbuff(RECV_INIT);	packets_dropped = packets_received = 0;	packets_ignored = 0;	packets_sent = packets_notsent = 0;	handler_calls = handler_pkts = 0;	io_timereset = 0;	loopback_interface = NULL;	loopback6_interface = NULL;	any_interface = NULL;	any6_interface = NULL;#ifdef REFCLOCK	refio = 0;#endif#if defined(HAVE_SIGNALED_IO)	(void) set_signal();#endif	ISC_LIST_INIT(sockets_list);        ISC_LIST_INIT(remoteaddr_list);	/*	 * Create the sockets	 */	BLOCKIO();	(void) create_sockets(htons(NTP_PORT));	UNBLOCKIO();#ifdef DEBUG	if (debug)	    printf("init_io: maxactivefd %d\n", maxactivefd);#endif}/* * Function to dump the contents of the interface structure * For debugging use only. */#ifdef DEBUGvoidinterface_dump(struct interface *itf){	u_char* cp;	int i;	/* Limit the size of the sockaddr_storage hex dump */	int maxsize = min(32, sizeof(struct sockaddr_storage));	printf("Dumping interface: %p\n", itf);	printf("fd = %d\n", itf->fd);	printf("bfd = %d\n", itf->bfd);	printf("sin = %s,\n", stoa(&(itf->sin)));	cp = (u_char*) &(itf->sin);	for(i = 0; i < maxsize; i++)	{		printf("%02x", *cp++);		if((i+1)%4 == 0)			printf(" ");	}	printf("\n");	printf("bcast = %s,\n", stoa(&(itf->bcast)));	cp = (u_char*) &(itf->bcast);	for(i = 0; i < maxsize; i++)	{		printf("%02x", *cp++);		if((i+1)%4 == 0)			printf(" ");	}	printf("\n");	printf("mask = %s,\n", stoa(&(itf->mask)));	cp = (u_char*) &(itf->mask);	for(i = 0; i < maxsize; i++)	{		printf("%02x", *cp++);		if((i+1)%4 == 0)			printf(" ");	}	printf("\n");	printf("name = %s\n", itf->name);	printf("flags = 0x%08x\n", itf->flags);	printf("last_ttl = %d\n", itf->last_ttl);	printf("addr_refid = %08x\n", itf->addr_refid);	printf("num_mcast = %d\n", itf->num_mcast);	printf("received = %ld\n", itf->received);	printf("sent = %ld\n", itf->sent);	printf("notsent = %ld\n", itf->notsent);	printf("ifindex = %u\n", itf->ifindex);	printf("scopeid = %u\n", itf->scopeid);}static voidprint_interface(int ind) {	printf("interface %d:  fd=%d,  bfd=%d,  name=%s,  flags=0x%x,  scope=%d\n",	       ind,	       inter_list[ind].fd,	       inter_list[ind].bfd,	       inter_list[ind].name,	       inter_list[ind].flags,	       inter_list[ind].scopeid);	/* Leave these as three printf calls. */	printf("              sin=%s", stoa((&inter_list[ind].sin)));	if (inter_list[ind].flags & INT_BROADCAST)	    printf("  bcast=%s", stoa((&inter_list[ind].bcast)));	/* Only IPv4 has a network mask */	if(inter_list[ind].family == AF_INET)		printf(",  mask=%s", stoa((&inter_list[ind].mask)));	printf(" %s\n", inter_list[ind].ignore_packets == ISC_FALSE ? "Enabled": "Disabled");	if (debug > 4)	/* in-depth debugging only */		interface_dump(&inter_list[ind]);}#endifintcreate_wildcards(u_short port) {	int idx = 0;	isc_boolean_t okipv4 = ISC_TRUE;	/*	 * create pseudo-interface with wildcard IPv4 address	 */#ifdef IPV6_V6ONLY	if(isc_net_probeipv4() != ISC_R_SUCCESS)		okipv4 = ISC_FALSE;#endif	if(okipv4 == ISC_TRUE) {		inter_list[idx].family = AF_INET;		inter_list[idx].sin.ss_family = AF_INET;		((struct sockaddr_in*)&inter_list[idx].sin)->sin_addr.s_addr = htonl(INADDR_ANY);		((struct sockaddr_in*)&inter_list[idx].sin)->sin_port = port;		(void) strncpy(inter_list[idx].name, "wildcard", sizeof(inter_list[idx].name));		inter_list[idx].mask.ss_family = AF_INET;		((struct sockaddr_in*)&inter_list[idx].mask)->sin_addr.s_addr = htonl(~(u_int32)0);		inter_list[idx].bfd = INVALID_SOCKET;		inter_list[idx].num_mcast = 0;		inter_list[idx].received = 0;		inter_list[idx].sent = 0;		inter_list[idx].notsent = 0;		inter_list[idx].flags = INT_BROADCAST | INT_UP;		inter_list[idx].ignore_packets = ISC_TRUE;#if defined(MCAST)	/*	 * enable possible multicast reception on the broadcast socket	 */		inter_list[idx].bcast.ss_family = AF_INET;		((struct sockaddr_in*)&inter_list[idx].bcast)->sin_port = port;		((struct sockaddr_in*)&inter_list[idx].bcast)->sin_addr.s_addr = htonl(INADDR_ANY);#endif /* MCAST */		any_interface = &inter_list[idx];		wildipv4 = idx;		idx++;	}#ifdef INCLUDE_IPV6_SUPPORT	/*	 * create pseudo-interface with wildcard IPv6 address	 */	if (isc_net_probeipv6() == ISC_R_SUCCESS) {		inter_list[idx].family = AF_INET6;		inter_list[idx].sin.ss_family = AF_INET6;		((struct sockaddr_in6*)&inter_list[idx].sin)->sin6_addr = in6addr_any;		((struct sockaddr_in6*)&inter_list[idx].sin)->sin6_port = port;# ifdef ISC_PLATFORM_HAVESCOPEID		((struct sockaddr_in6*)&inter_list[idx].sin)->sin6_scope_id = 0;# endif		(void) strncpy(inter_list[idx].name, "wildcard", sizeof(inter_list[idx].name));		inter_list[idx].mask.ss_family = AF_INET6;		memset(&((struct sockaddr_in6*)&inter_list[idx].mask)->sin6_addr.s6_addr, 0xff, sizeof(struct in6_addr));		inter_list[idx].bfd = INVALID_SOCKET;		inter_list[idx].num_mcast = 0;		inter_list[idx].received = 0;		inter_list[idx].sent = 0;		inter_list[idx].notsent = 0;		inter_list[idx].flags = INT_UP;		inter_list[idx].ignore_packets = ISC_TRUE;		any6_interface = &inter_list[idx];		wildipv6 = idx;		idx++;	}#endif	return (idx);}isc_boolean_taddress_okay(isc_interface_t *isc_if) {#ifdef DEBUG	if (debug > 2)	    printf("address_okay: listen Virtual: %d, IF name: %s, Up Flag: %d\n", 		    listen_to_virtual_ips, isc_if->name, (isc_if->flags & INTERFACE_F_UP));#endif	/*	 * Always allow the loopback	 */	if((isc_if->flags & INTERFACE_F_LOOPBACK) != 0)		return (ISC_TRUE);	/*	 * Check if the interface is specified	 */	if (specific_interface != NULL) {		if (strcasecmp(isc_if->name, specific_interface) == 0)			return (ISC_TRUE);		else			return (ISC_FALSE);	}	else {		if (listen_to_virtual_ips == 0  && 		   (strchr(isc_if->name, (int)':') != NULL))			return (ISC_FALSE);	}	/* XXXPDM This should be fixed later, but since we may not have set	 * the UP flag, we at least get to use the interface.	 * The UP flag is not always set so we don't do this right now.	 *//*	if ((isc_if->flags & INTERFACE_F_UP) == 0)		return (ISC_FALSE);*/	return (ISC_TRUE);}voidconvert_isc_if(isc_interface_t *isc_if, struct interface *itf, u_short port) {	itf->scopeid = 0;	itf->family = (short) isc_if->af;	if(isc_if->af == AF_INET) {		itf->sin.ss_family = (u_short) isc_if->af;		strcpy(itf->name, isc_if->name);		memcpy(&(((struct sockaddr_in*)&itf->sin)->sin_addr),		       &(isc_if->address.type.in),		       sizeof(struct in_addr));		((struct sockaddr_in*)&itf->sin)->sin_port = port;		if((isc_if->flags & INTERFACE_F_BROADCAST) != 0) {			itf->flags |= INT_BROADCAST;			itf->bcast.ss_family = itf->sin.ss_family;			memcpy(&(((struct sockaddr_in*)&itf->bcast)->sin_addr),			       &(isc_if->broadcast.type.in),				 sizeof(struct in_addr));			((struct sockaddr_in*)&itf->bcast)->sin_port = port;		}		itf->mask.ss_family = itf->sin.ss_family;		memcpy(&(((struct sockaddr_in*)&itf->mask)->sin_addr),		       &(isc_if->netmask.type.in),		       sizeof(struct in_addr));		((struct sockaddr_in*)&itf->mask)->sin_port = port;		if (((isc_if->flags & INTERFACE_F_LOOPBACK) != 0) && (loopback_interface == NULL))		{			loopback_interface = itf;		}	}#ifdef INCLUDE_IPV6_SUPPORT	else if (isc_if->af == AF_INET6) {		itf->sin.ss_family = (u_short) isc_if->af;		strcpy(itf->name, isc_if->name);		memcpy(&(((struct sockaddr_in6 *)&itf->sin)->sin6_addr),		       &(isc_if->address.type.in6),

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -