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

📄 ntp_intres.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 2 页
字号:
openntp(void){	struct addrinfo hints;	struct addrinfo *addrResult;	const char *localhost = "127.0.0.1";	/* Use IPv6 loopback */	if (sockfd >= 0)	    return;	memset(&hints, 0, sizeof(hints));	/*	 * For now only bother with IPv4	 */	hints.ai_family = AF_INET;	hints.ai_socktype = SOCK_DGRAM;	if (getaddrinfo(localhost, "ntp", &hints, &addrResult)!=0) {		msyslog(LOG_ERR, "getaddrinfo failed: %m");		resolver_exit(1);	}	sockfd = socket(addrResult->ai_family, addrResult->ai_socktype, 0);	if (sockfd == -1) {		msyslog(LOG_ERR, "socket() failed: %m");		resolver_exit(1);	}	/*	 * Make the socket non-blocking.  We'll wait with select()	 */#ifndef SYS_WINNT#if defined(O_NONBLOCK)	if (fcntl(sockfd, F_SETFL, O_NONBLOCK) == -1) {		msyslog(LOG_ERR, "fcntl(O_NONBLOCK) failed: %m");		resolver_exit(1);	}#else#if defined(FNDELAY)	if (fcntl(sockfd, F_SETFL, FNDELAY) == -1) {		msyslog(LOG_ERR, "fcntl(FNDELAY) failed: %m");		resolver_exit(1);	}#else# include "Bletch: NEED NON BLOCKING IO"#endif /* FNDDELAY */#endif /* O_NONBLOCK */#else  /* SYS_WINNT */	{		int on = 1;		if (ioctlsocket(sockfd,FIONBIO,(u_long *) &on) == SOCKET_ERROR) {			msyslog(LOG_ERR, "ioctlsocket(FIONBIO) fails: %m");			resolver_exit(1); /* Windows NT - set socket in non-blocking mode */		}	}#endif /* SYS_WINNT */	if (connect(sockfd, addrResult->ai_addr, addrResult->ai_addrlen) == -1) {		msyslog(LOG_ERR, "openntp: connect() failed: %m");		resolver_exit(1);	}	freeaddrinfo(addrResult);}/* * request - send a configuration request to the server, wait for a response */static intrequest(	struct conf_peer *conf	){	fd_set fdset;	struct timeval tvout;	struct req_pkt reqpkt;	l_fp ts;	int n;#ifdef SYS_WINNT	HANDLE hReadWriteEvent = NULL;	BOOL ret;	DWORD NumberOfBytesWritten, NumberOfBytesRead, dwWait;	OVERLAPPED overlap;#endif /* SYS_WINNT */	checkparent();		/* make sure our guy is still running */	if (sockfd == INVALID_SOCKET)	    openntp();	#ifdef SYS_WINNT	hReadWriteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);#endif /* SYS_WINNT */	/*	 * Try to clear out any previously received traffic so it	 * doesn't fool us.  Note the socket is nonblocking.	 */	tvout.tv_sec =  0;	tvout.tv_usec = 0;	FD_ZERO(&fdset);	FD_SET(sockfd, &fdset);	while (select(sockfd + 1, &fdset, (fd_set *)0, (fd_set *)0, &tvout) >	       0) {		recv(sockfd, (char *)&reqpkt, REQ_LEN_MAC, 0);		FD_ZERO(&fdset);		FD_SET(sockfd, &fdset);	}	/*	 * Make up a request packet with the configuration info	 */	memset((char *)&reqpkt, 0, sizeof(reqpkt));	reqpkt.rm_vn_mode = RM_VN_MODE(0, 0, 0);	reqpkt.auth_seq = AUTH_SEQ(1, 0);	/* authenticated, no seq */	reqpkt.implementation = IMPL_XNTPD;	/* local implementation */	reqpkt.request = REQ_CONFIG;		/* configure a new peer */	reqpkt.err_nitems = ERR_NITEMS(0, 1);	/* one item */	reqpkt.mbz_itemsize = MBZ_ITEMSIZE(sizeof(struct conf_peer));	/* Make sure mbz_itemsize <= sizeof reqpkt.data */	if (sizeof(struct conf_peer) > sizeof (reqpkt.data)) {		msyslog(LOG_ERR, "Bletch: conf_peer is too big for reqpkt.data!");		resolver_exit(1);	}	memmove(reqpkt.data, (char *)conf, sizeof(struct conf_peer));	reqpkt.keyid = htonl(req_keyid);	get_systime(&ts);	L_ADDUF(&ts, SKEWTIME);	HTONL_FP(&ts, &reqpkt.tstamp);	n = 0;	if (sys_authenticate)		n = authencrypt(req_keyid, (u_int32 *)&reqpkt, REQ_LEN_NOMAC);	/*	 * Done.  Send it.	 */#ifndef SYS_WINNT	n = send(sockfd, (char *)&reqpkt, (unsigned)(REQ_LEN_NOMAC + n), 0);	if (n < 0) {		msyslog(LOG_ERR, "send to NTP server failed: %m");		return 0;	/* maybe should exit */	}#else	/* In the NT world, documentation seems to indicate that there	 * exist _write and _read routines that can be used to do blocking	 * I/O on sockets. Problem is these routines require a socket	 * handle obtained through the _open_osf_handle C run-time API	 * of which there is no explanation in the documentation. We need	 * nonblocking write's and read's anyway for our purpose here.	 * We're therefore forced to deviate a little bit from the Unix	 * model here and use the ReadFile and WriteFile Win32 I/O API's	 * on the socket	 */	overlap.Offset = overlap.OffsetHigh = (DWORD)0;	overlap.hEvent = hReadWriteEvent;	ret = WriteFile((HANDLE)sockfd, (char *)&reqpkt, REQ_LEN_NOMAC + n,			NULL, (LPOVERLAPPED)&overlap);	if ((ret == FALSE) && (GetLastError() != ERROR_IO_PENDING)) {		msyslog(LOG_ERR, "send to NTP server failed: %m");		return 0;	}	dwWait = WaitForSingleObject(hReadWriteEvent, (DWORD) TIMEOUT_SEC * 1000);	if ((dwWait == WAIT_FAILED) || (dwWait == WAIT_TIMEOUT)) {		if (dwWait == WAIT_FAILED)		    msyslog(LOG_ERR, "WaitForSingleObject failed: %m");		return 0;	}	if (!GetOverlappedResult((HANDLE)sockfd, (LPOVERLAPPED)&overlap,				(LPDWORD)&NumberOfBytesWritten, FALSE)) {		msyslog(LOG_ERR, "GetOverlappedResult for WriteFile fails: %m");		return 0;	}#endif /* SYS_WINNT */    	/*	 * Wait for a response.  A weakness of the mode 7 protocol used	 * is that there is no way to associate a response with a	 * particular request, i.e. the response to this configuration	 * request is indistinguishable from that to any other.  I should	 * fix this some day.  In any event, the time out is fairly	 * pessimistic to make sure that if an answer is coming back	 * at all, we get it.	 */	for (;;) {		FD_ZERO(&fdset);		FD_SET(sockfd, &fdset);		tvout.tv_sec = TIMEOUT_SEC;		tvout.tv_usec = TIMEOUT_USEC;		n = select(sockfd + 1, &fdset, (fd_set *)0,			   (fd_set *)0, &tvout);		if (n < 0)		{			if (errno != EINTR)			    msyslog(LOG_ERR, "select() fails: %m");			return 0;		}		else if (n == 0)		{			if (debug)			    msyslog(LOG_INFO, "select() returned 0.");			return 0;		}#ifndef SYS_WINNT		n = recv(sockfd, (char *)&reqpkt, REQ_LEN_MAC, 0);		if (n <= 0) {			if (n < 0) {				msyslog(LOG_ERR, "recv() fails: %m");				return 0;			}			continue;		}#else /* Overlapped I/O used on non-blocking sockets on Windows NT */		ret = ReadFile((HANDLE)sockfd, (char *)&reqpkt, (DWORD)REQ_LEN_MAC,			       NULL, (LPOVERLAPPED)&overlap);		if ((ret == FALSE) && (GetLastError() != ERROR_IO_PENDING)) {			msyslog(LOG_ERR, "ReadFile() fails: %m");			return 0;		}		dwWait = WaitForSingleObject(hReadWriteEvent, (DWORD) TIMEOUT_SEC * 1000);		if ((dwWait == WAIT_FAILED) || (dwWait == WAIT_TIMEOUT)) {			if (dwWait == WAIT_FAILED) {				msyslog(LOG_ERR, "WaitForSingleObject for ReadFile fails: %m");				return 0;			}			continue;		}		if (!GetOverlappedResult((HANDLE)sockfd, (LPOVERLAPPED)&overlap,					(LPDWORD)&NumberOfBytesRead, FALSE)) {			msyslog(LOG_ERR, "GetOverlappedResult fails: %m");			return 0;		}		n = NumberOfBytesRead;#endif /* SYS_WINNT */		/*		 * Got one.  Check through to make sure it is what		 * we expect.		 */		if (n < RESP_HEADER_SIZE) {			msyslog(LOG_ERR, "received runt response (%d octets)",				n);			continue;		}		if (!ISRESPONSE(reqpkt.rm_vn_mode)) {#ifdef DEBUG			if (debug > 1)			    msyslog(LOG_INFO, "received non-response packet");#endif			continue;		}		if (ISMORE(reqpkt.rm_vn_mode)) {#ifdef DEBUG			if (debug > 1)			    msyslog(LOG_INFO, "received fragmented packet");#endif			continue;		}		if ( ( (INFO_VERSION(reqpkt.rm_vn_mode) < 2)		       || (INFO_VERSION(reqpkt.rm_vn_mode) > NTP_VERSION))		     || INFO_MODE(reqpkt.rm_vn_mode) != MODE_PRIVATE) {#ifdef DEBUG			if (debug > 1)			    msyslog(LOG_INFO,				    "version (%d/%d) or mode (%d/%d) incorrect",				    INFO_VERSION(reqpkt.rm_vn_mode),				    NTP_VERSION,				    INFO_MODE(reqpkt.rm_vn_mode),				    MODE_PRIVATE);#endif			continue;		}		if (INFO_SEQ(reqpkt.auth_seq) != 0) {#ifdef DEBUG			if (debug > 1)			    msyslog(LOG_INFO,				    "nonzero sequence number (%d)",				    INFO_SEQ(reqpkt.auth_seq));#endif			continue;		}		if (reqpkt.implementation != IMPL_XNTPD ||		    reqpkt.request != REQ_CONFIG) {#ifdef DEBUG			if (debug > 1)			    msyslog(LOG_INFO,				    "implementation (%d) or request (%d) incorrect",				    reqpkt.implementation, reqpkt.request);#endif			continue;		}		if (INFO_NITEMS(reqpkt.err_nitems) != 0 ||		    INFO_MBZ(reqpkt.mbz_itemsize) != 0 ||		    INFO_ITEMSIZE(reqpkt.mbz_itemsize) != 0) {#ifdef DEBUG			if (debug > 1)			    msyslog(LOG_INFO,				    "nitems (%d) mbz (%d) or itemsize (%d) nonzero",				    INFO_NITEMS(reqpkt.err_nitems),				    INFO_MBZ(reqpkt.mbz_itemsize),				    INFO_ITEMSIZE(reqpkt.mbz_itemsize));#endif			continue;		}		n = INFO_ERR(reqpkt.err_nitems);		switch (n) {		    case INFO_OKAY:			/* success */			return 1;				    case INFO_ERR_IMPL:			msyslog(LOG_ERR,				"ntpd reports implementation mismatch!");			return 0;				    case INFO_ERR_REQ:			msyslog(LOG_ERR,				"ntpd says configuration request is unknown!");			return 0;				    case INFO_ERR_FMT:			msyslog(LOG_ERR,				"ntpd indicates a format error occurred!");			return 0;		    case INFO_ERR_NODATA:			msyslog(LOG_ERR,				"ntpd indicates no data available!");			return 0;				    case INFO_ERR_AUTH:			msyslog(LOG_ERR,				"ntpd returns a permission denied error!");			return 0;		    default:			msyslog(LOG_ERR,				"ntpd returns unknown error code %d!", n);			return 0;		}	}}/* * nexttoken - return the next token from a line */static char *nexttoken(	char **lptr	){	register char *cp;	register char *tstart;	cp = *lptr;	/*	 * Skip leading white space	 */	while (*cp == ' ' || *cp == '\t')	    cp++;		/*	 * If this is the end of the line, return nothing.	 */	if (*cp == '\n' || *cp == '\0') {		*lptr = cp;		return NULL;	}		/*	 * Must be the start of a token.  Record the pointer and look	 * for the end.	 */	tstart = cp++;	while (*cp != ' ' && *cp != '\t' && *cp != '\n' && *cp != '\0')	    cp++;		/*	 * Terminate the token with a \0.  If this isn't the end of the	 * line, space to the next character.	 */	if (*cp == '\n' || *cp == '\0')	    *cp = '\0';	else	    *cp++ = '\0';	*lptr = cp;	return tstart;}/* * readconf - read the configuration information out of the file we *	      were passed.  Note that since the file is supposed to be *	      machine generated, we bail out at the first sign of trouble. */static voidreadconf(	FILE *fp,	char *name	){	register int i;	char *token[NUMTOK];	u_long intval[NUMTOK];	u_int flags;	char buf[MAXLINESIZE];	char *bp;	while (fgets(buf, MAXLINESIZE, fp) != NULL) {		bp = buf;		for (i = 0; i < NUMTOK; i++) {			if ((token[i] = nexttoken(&bp)) == NULL) {				msyslog(LOG_ERR,					"tokenizing error in file `%s', quitting",					name);				resolver_exit(1);			}		}		for (i = 1; i < NUMTOK - 1; i++) {			if (!atouint(token[i], &intval[i])) {				msyslog(LOG_ERR,					"format error for integer token `%s', file `%s', quitting",					token[i], name);				resolver_exit(1);			}		}		if (intval[TOK_HMODE] != MODE_ACTIVE &&		    intval[TOK_HMODE] != MODE_CLIENT &&		    intval[TOK_HMODE] != MODE_BROADCAST) {			msyslog(LOG_ERR, "invalid mode (%ld) in file %s",				intval[TOK_HMODE], name);			resolver_exit(1);		}		if (intval[TOK_VERSION] > NTP_VERSION ||		    intval[TOK_VERSION] < NTP_OLDVERSION) {			msyslog(LOG_ERR, "invalid version (%ld) in file %s",				intval[TOK_VERSION], name);			resolver_exit(1);		}		if (intval[TOK_MINPOLL] < NTP_MINPOLL ||		    intval[TOK_MINPOLL] > NTP_MAXPOLL) {			msyslog(LOG_ERR, "invalid MINPOLL value (%ld) in file %s",				intval[TOK_MINPOLL], name);			resolver_exit(1);		}		if (intval[TOK_MAXPOLL] < NTP_MINPOLL ||		    intval[TOK_MAXPOLL] > NTP_MAXPOLL) {			msyslog(LOG_ERR, "invalid MAXPOLL value (%ld) in file %s",				intval[TOK_MAXPOLL], name);			resolver_exit(1);		}		if ((intval[TOK_FLAGS] & ~(FLAG_AUTHENABLE | FLAG_PREFER |		    FLAG_NOSELECT | FLAG_BURST | FLAG_IBURST | FLAG_SKEY))		    != 0) {			msyslog(LOG_ERR, "invalid flags (%ld) in file %s",				intval[TOK_FLAGS], name);			resolver_exit(1);		}		flags = 0;		if (intval[TOK_FLAGS] & FLAG_AUTHENABLE)		    flags |= CONF_FLAG_AUTHENABLE;		if (intval[TOK_FLAGS] & FLAG_PREFER)		    flags |= CONF_FLAG_PREFER;		if (intval[TOK_FLAGS] & FLAG_NOSELECT)		    flags |= CONF_FLAG_NOSELECT;		if (intval[TOK_FLAGS] & FLAG_BURST)		    flags |= CONF_FLAG_BURST;		if (intval[TOK_FLAGS] & FLAG_IBURST)		    flags |= CONF_FLAG_IBURST;		if (intval[TOK_FLAGS] & FLAG_SKEY)		    flags |= CONF_FLAG_SKEY;		/*		 * This is as good as we can check it.  Add it in.		 */		addentry(token[TOK_HOSTNAME], (int)intval[TOK_HMODE],			 (int)intval[TOK_VERSION], (int)intval[TOK_MINPOLL],			 (int)intval[TOK_MAXPOLL], flags, (int)intval[TOK_TTL],			 intval[TOK_KEYID], token[TOK_KEYSTR]);	}}/* * doconfigure - attempt to resolve names and configure the server */static voiddoconfigure(	int dores	){	register struct conf_entry *ce;	register struct conf_entry *ceremove;	ce = confentries;	while (ce != NULL) {#ifdef DEBUG		if (debug > 1)			msyslog(LOG_INFO,			    "doconfigure: <%s> has peeraddr %s",			    ce->ce_name, stoa(&ce->peer_store));#endif		if (dores && SOCKNUL(&(ce->peer_store))) {			if (!findhostaddr(ce)) {				msyslog(LOG_ERR,					"couldn't resolve `%s', giving up on it",					ce->ce_name);				ceremove = ce;				ce = ceremove->ce_next;				removeentry(ceremove);				continue;			}		}		if (!SOCKNUL(&ce->peer_store)) {			if (request(&ce->ce_config)) {				ceremove = ce;				ce = ceremove->ce_next;				removeentry(ceremove);				continue;			}#ifdef DEBUG			if (debug > 1) {				msyslog(LOG_INFO,				    "doconfigure: request() FAILED, maybe next time.");			}#endif		}		ce = ce->ce_next;	}}

⌨️ 快捷键说明

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