ntpclient.c修改了官方文件:
/*
* 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/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/utsname.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <errno.h>
#ifdef _PRECISION_SIOCGSTAMP
#include <sys/ioctl.h>
#endif
#define ENABLE_DEBUG
extern char *optarg;
/* XXXX fixme - non-automatic build configuration */
#ifdef linux
typedef u_int32_t __u32;
#include <sys/timex.h>
#else
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);
void rfc1305print(char *data, struct ntptime *arrival);
void 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=1; /* non-zero presumably needs root privs */
#ifdef ENABLE_DEBUG
int debug=0;
#define DEBUG_OPTION "d"
#else
#define debug 0
#define DEBUG_OPTION
#endif
int 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
}
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(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 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