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

📄 ntpclient.c

📁 ntpclient是通过网络进行系统时间校准的client端程序。从而使多个终端能够保证时间同步性。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * ntpclient.c - NTP client * * Copyright 1997, 1999, 2000  Larry Doolittle  <larry@doolittle.boa.org> * Last hack: 2 December, 2000 * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License (Version 2, *  June 1991) as published by the Free Software Foundation.  At the *  time of writing, that license was published by the FSF with the URL *  http://www.gnu.org/copyleft/gpl.html, and is incorporated herein by *  reference. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  Possible future improvements: *      - Double check that the originate timestamp in the received packet *        corresponds to what we sent. *      - Verify that the return packet came from the host we think *        we're talking to.  Not necessarily useful since UDP packets *        are so easy to forge. *      - Complete phase locking code. *      - Write more documentation  :-( * *  Compile with -D_PRECISION_SIOCGSTAMP if your machine really has it. *  There are patches floating around to add this to Linux, but *  usually you only get an answer to the nearest jiffy. *  Hint for Linux hacker wannabes: look at the usage of get_fast_time() *  in net/core/dev.c, and its definition in kernel/time.c . * *  If the compile gives you any flak, check below in the section *  labelled "XXXX fixme - non-automatic build configuration". */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <arpa/inet.h>#include <time.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#ifdef _PRECISION_SIOCGSTAMP#include <sys/ioctl.h>#endif#define ENABLE_DEBUG#define HOSTNAME_MAX_LEN        64extern char *optarg;/* XXXX fixme - non-automatic build configuration */#ifdef linux#include <sys/utsname.h>#include <sys/time.h>typedef u_int32_t __u32;#include <sys/timex.h>#else#define main ntpclientextern struct hostent *gethostbyname(const char *name);extern int h_errno;#define herror(hostname) \	fprintf(stderr,"Error %d looking up hostname %s\n", h_errno,hostname)typedef uint32_t __u32;#endif#define JAN_1970        0x83aa7e80      /* 2208988800 1970 - 1900 in seconds */#define NTP_PORT "123"/* How to multiply by 4294.967296 quickly (and not quite exactly) * without using floating point or greater than 32-bit integers. * If you want to fix the last 12 microseconds of error, add in * (2911*(x))>>28) */#define NTPFRAC(x) ( 4294*(x) + ( (1981*(x))>>11 ) )/* The reverse of the above, needed if we want to set our microsecond * clock (via settimeofday) based on the incoming time in NTP format. * Basically exact. */#define USEC(x) ( ( (x) >> 12 ) - 759 * ( ( ( (x) >> 10 ) + 32768 ) >> 16 ) )/* Converts NTP delay and dispersion, apparently in seconds scaled * by 65536, to microseconds.  RFC1305 states this time is in seconds, * doesn't mention the scaling. * Should somehow be the same as 1000000 * x / 65536 */#define sec2u(x) ( (x) * 15.2587890625 )struct ntptime {	unsigned int coarse;	unsigned int fine;};void send_packet(int usd, int print_errors);int rfc1305print(char *data, struct ntptime *arrival);int udp_handle(int usd, char *data, int data_len, struct sockaddr *sa_source, int sa_len);/* global variables (I know, bad form, but this is a short program) */char incoming[1500];struct timeval time_of_send;int live=0;int set_clock=0;   /* non-zero presumably needs root privs */int host_count = 0;int current_host = 0;char *host_list[8];struct addrinfo *addr_list = NULL;struct addrinfo *current_addr = NULL;char **global_argv;#ifdef ENABLE_DEBUGint debug=0;#define DEBUG_OPTION "d"#else#define debug 0#define DEBUG_OPTION#endifint contemplate_data(unsigned int absolute, double skew, double errorbar, int freq);int get_current_freq(){	/* OS dependent routine to get the current value of clock frequency.	 */#ifdef linux	struct timex txc;	txc.modes=0;	if (adjtimex(&txc) < 0) {		perror("adjtimex"); exit(1);	}	return txc.freq;#else	return 0;#endif}int set_freq(int new_freq){	/* OS dependent routine to set a new value of clock frequency.	 */#ifdef linux	struct timex txc;	txc.modes = ADJ_FREQUENCY;	txc.freq = new_freq;	if (adjtimex(&txc) < 0) {		perror("adjtimex"); exit(1);	}	return txc.freq;#else	return 0;#endif}int resolv_conf_changed(void){	struct stat st;	static time_t last_mod;	static int last_mod_valid = 0;	int ret;	if (stat("/etc/resolv.conf", &st) < 0) {		last_mod_valid = 0;		return 0;	}	ret = !last_mod_valid || last_mod != st.st_mtime;	last_mod_valid = 1;	last_mod = st.st_mtime;	return ret;}char *make_addr(struct sockaddr *addr){	static char tmp[128];	int port;	switch (addr->sa_family) {	case AF_INET:		inet_ntop(AF_INET, &((struct sockaddr_in *)addr)->sin_addr,			tmp, sizeof(tmp));		port = ((struct sockaddr_in *)addr)->sin_port;		break;	case AF_INET6:		inet_ntop(AF_INET6, &((struct sockaddr_in6 *)addr)->sin6_addr,			tmp, sizeof(tmp));		port = ((struct sockaddr_in6 *)addr)->sin6_port;		break;	default:		tmp[0] = 0;		return tmp;	}	sprintf(tmp + strlen(tmp), ":%d", ntohs(port));	return tmp;}void server_failed(void){	if (current_addr)		current_addr = current_addr->ai_next;}void send_packet(int usd, int print_errors){	__u32 data[12];	struct timeval now;	struct addrinfo *addr;	int res;	struct addrinfo hints;	static int wrapped = 0;	if (!current_addr) {		if (current_host == host_count) {			if (wrapped) {				if (resolv_conf_changed()) {					/* glibc only reads resolv.conf once,					 * so we need to re-exec to pick up					 * the new nameservers */					if (debug)						printf("resolv.conf changed; "								"re-execing\n");					execvp(global_argv[0], global_argv);				}				/* skip this query, continue retrying */				wrapped = 0;				return;			}			wrapped = 1;			current_host = 0;		}		if (addr_list)			freeaddrinfo(addr_list);		memset(&hints, 0, sizeof(hints));		hints.ai_family = AF_INET;		hints.ai_socktype = SOCK_DGRAM;		res = getaddrinfo(host_list[current_host], NTP_PORT, &hints,					&addr_list);		if (res) {			if (print_errors)				fprintf(stderr, "%s: %s\n",						host_list[current_host],						gai_strerror(res));			++current_host;			send_packet(usd, print_errors);			return;		}		current_addr = addr_list;		if (debug)			for (addr = addr_list; addr; addr = addr->ai_next)				printf("adding %s\n", make_addr(addr->ai_addr));		++current_host;		send_packet(usd, print_errors);		return;	}	wrapped = 0;#define LI 0#define VN 3#define MODE 3#define STRATUM 0#define POLL 4 #define PREC -6	if (debug) fprintf(stderr,"Sending to %s...\n",			make_addr(current_addr->ai_addr));	if (sizeof(data) != 48) {		fprintf(stderr,"size error\n");		return;	}	bzero((char*)data,sizeof(data));	data[0] = htonl (		( LI << 30 ) | ( VN << 27 ) | ( MODE << 24 ) |		( STRATUM << 16) | ( POLL << 8 ) | ( PREC & 0xff ) );	data[1] = htonl(1<<16);  /* Root Delay (seconds) */	data[2] = htonl(1<<16);  /* Root Dispersion (seconds) */	gettimeofday(&now,NULL);	data[10] = htonl(now.tv_sec + JAN_1970); /* Transmit Timestamp coarse */	data[11] = htonl(NTPFRAC(now.tv_usec));  /* Transmit Timestamp fine   */	if (sendto(usd,data,48,0,current_addr->ai_addr,				current_addr->ai_addrlen) < 0)		server_failed();	time_of_send=now;}int udp_handle(int usd, char *data, int data_len, struct sockaddr *sa_source, int sa_len){	struct timeval udp_arrival;	struct ntptime udp_arrival_ntp;#ifdef _PRECISION_SIOCGSTAMP	if ( ioctl(usd, SIOCGSTAMP, &udp_arrival) < 0 ) {		perror("ioctl-SIOCGSTAMP");		gettimeofday(&udp_arrival,NULL);	}#else	gettimeofday(&udp_arrival,NULL);#endif	udp_arrival_ntp.coarse = udp_arrival.tv_sec + JAN_1970;	udp_arrival_ntp.fine   = NTPFRAC(udp_arrival.tv_usec);	if (debug) {		printf("packet of length %d received\n",data_len);		printf("Source: %s\n", make_addr(sa_source));	}	if (rfc1305print(data,&udp_arrival_ntp) < 0) {		if (debug)			printf("kiss of death!  removing %s...\n",					make_addr(sa_source));		return -1;	}	return 0;}double ntpdiff( struct ntptime *start, struct ntptime *stop){	int a;	unsigned int b;	a = stop->coarse - start->coarse;	if (stop->fine >= start->fine) {		b = stop->fine - start->fine;	} else {		b = start->fine - stop->fine;		b = ~b;		a -= 1;	}		return a*1.e6 + b * (1.e6/4294967296.0);}int rfc1305print(char *data, struct ntptime *arrival){/* straight out of RFC-1305 Appendix A */	int li, vn, mode, stratum, poll, prec;	int delay, disp, refid;	struct ntptime reftime, orgtime, rectime, xmttime;

⌨️ 快捷键说明

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