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

📄 ntpclient.c

📁 A NTP client is a program which user can synchronize the time with time server assigned. This prog
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * ntpclient.c - NTP client * * Copyright 1997, 1999, 2000, 2003  Larry Doolittle  <larry@doolittle.boa.org> * Last hack: July 5, 2003 * *  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. *      - 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/socket.h>#include <netinet/in.h>#include <netdb.h>     /* gethostbyname */#include <arpa/inet.h>#include <time.h>#include <unistd.h>#include <errno.h>#ifdef _PRECISION_SIOCGSTAMP#include <sys/ioctl.h>#endif#define ENABLE_DEBUGextern 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>#elseextern 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;};/* prototype for function defined in phaselock.c */int contemplate_data(unsigned int absolute, double skew, double errorbar, int freq);/* prototypes for some local routines */void send_packet(int usd);int rfc1305print(uint32_t *data, struct ntptime *arrival);void udp_handle(int usd, char *data, int data_len, struct sockaddr *sa_source, int sa_len);/* variables with file scope * (I know, bad form, but this is a short program) */static uint32_t incoming_word[325];#define incoming ((char *) incoming_word)#define sizeof_incoming (sizeof(incoming_word)*sizeof(uint32_t))static struct timeval time_of_send;static int live=0;static int set_clock=0;   /* non-zero presumably needs root privs *//* when present, debug is a true global, shared with phaselock.c */#ifdef ENABLE_DEBUGint debug=1;#define DEBUG_OPTION "d"#else#define debug 0#define DEBUG_OPTION#endifint get_current_freq(void){	/* 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}void send_packet(int usd){	__u32 data[12];	struct timeval now;#define LI 0#define VN 3#define MODE 3#define STRATUM 0#define POLL 4 #define PREC -6	if (debug) fprintf(stderr,"Sending ...\n");	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   */	send(usd,data,48,0);	time_of_send=now;}void get_packet_timestamp(int usd, struct ntptime *udp_arrival_ntp){	struct timeval udp_arrival;#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);}void check_source(int data_len, struct sockaddr *sa_source, int sa_len){	/* This is where one could check that the source is the server we expect */	if (debug) {		struct sockaddr_in *sa_in=(struct sockaddr_in *)sa_source;		printf("packet of length %d received\n",data_len);		if (sa_source->sa_family==AF_INET) {			printf("Source: INET Port %d host %s\n",				ntohs(sa_in->sin_port),inet_ntoa(sa_in->sin_addr));		} else {			printf("Source: Address family %d\n",sa_source->sa_family);		}	}}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);}typedef struct _TimeZoneInfo{	char* strTimeZone;	int	  iOffset;	}TimeZoneInfo;TimeZoneInfo g_tzinfo [] ={	{"GMT+1100",-39600},	{"GMT+1000",-36000},	{"GMT+0900",-32400},	{"GMT+0800",-28800},	{"GMT+0700",-25200},	{"GMT+0600",-21600},	{"GMT+0500",-18000},	{"GMT+0400",-14400},	{"GMT+0300",-10800},	{"GMT+0200",-7200},	{"GMT+0100",-3600},	{"GMT+0000",0},	{"GMT-0100",3600},	{"GMT-0200",7200},	{"GMT-0300",10800},	{"GMT-0400",14400},	{"GMT-0500",18000},	{"GMT-0600",21600},	{"GMT-0700",25200},	{"GMT-0800",28800},	{"GMT-0900",32400},	{"GMT-1000",36000},	{"GMT-1100",39600},	{"GMT-1200",43200},		{"0",0},};int SyncTimeZone(){		FILE 	*fp;	char  	strtmp[256];	int		iOffset = 0,i=0;		memset(strtmp,0,sizeof(strtmp));		if ( (fp=fopen("/etc/timezone", "r")) == NULL )		return;			fscanf(fp,"%s",strtmp);	fclose(fp);				for (i=0;strcmp(g_tzinfo[i].strTimeZone,"0");i++)	{		if (!strcmp(g_tzinfo[i].strTimeZone,strtmp))				return 	g_tzinfo[i].iOffset;			}	//setenv("TZ", strtmp, 1);	return iOffset;}/* Does more than print, so this name is bogus. * It also makes time adjustments, both sudden (-s) * and phase-locking (-l).  *//* return value is number of microseconds uncertainty in answer */int rfc1305print(uint32_t *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;	double el_time,st_time,skew1,skew2;	int freq;#define Data(i) ntohl(((uint32_t *)data)[i])	li      = Data(0) >> 30 & 0x03;	vn      = Data(0) >> 27 & 0x07;	mode    = Data(0) >> 24 & 0x07;	stratum = Data(0) >> 16 & 0xff;	poll    = Data(0) >>  8 & 0xff;

⌨️ 快捷键说明

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