📄 ntpdate.c
字号:
/* * ntpdate - set the time of day by polling one or more NTP servers */#ifdef HAVE_CONFIG_H# include <config.h>#endif#ifdef HAVE_NETINFO#include <netinfo/ni.h>#endif#include "ntp_machine.h"#include "ntp_fp.h"#include "ntp.h"#include "ntp_io.h"#include "ntp_unixtime.h"#include "ntpdate.h"#include "ntp_string.h"#include "ntp_syslog.h"#include "ntp_select.h"#include "ntp_stdlib.h"/* Don't include ISC's version of IPv6 variables and structures */#define ISC_IPV6_H 1#include "isc/net.h"#include "isc/result.h"#include "isc/sockaddr.h"#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#include <stdio.h>#include <signal.h>#include <ctype.h>#ifdef HAVE_POLL_H# include <poll.h>#endif#ifndef SYS_WINNT# ifdef HAVE_SYS_SIGNAL_H# include <sys/signal.h># else# include <signal.h># endif# ifdef HAVE_SYS_IOCTL_H# include <sys/ioctl.h># endif#endif /* SYS_WINNT */#ifdef HAVE_SYS_RESOURCE_H# include <sys/resource.h>#endif /* HAVE_SYS_RESOURCE_H */#include <arpa/inet.h>#ifdef __QNXNTO__# include "adjtime.h"#endif#ifdef SYS_VXWORKS# include "ioLib.h"# include "sockLib.h"# include "timers.h"/* select wants a zero structure ... */struct timeval timeout = {0,0};#elif defined(SYS_WINNT)/* * Windows does not abort a select select call if SIGALRM goes off * so a 200 ms timeout is needed */struct timeval timeout = {0,1000000/TIMER_HZ};#elsestruct timeval timeout = {60,0};#endif#ifdef HAVE_NETINFO#include <netinfo/ni.h>#endif#include "recvbuff.h"#ifdef SYS_WINNT#define EPROTONOSUPPORT WSAEPROTONOSUPPORT#define EAFNOSUPPORT WSAEAFNOSUPPORT#define EPFNOSUPPORT WSAEPFNOSUPPORT#define TARGET_RESOLUTION 1 /* Try for 1-millisecond accuracy on Windows NT timers. */#pragma comment(lib, "winmm")isc_boolean_t ntp_port_inuse(int af, u_short port);#endif /* SYS_WINNT *//* * Scheduling priority we run at */#ifndef SYS_VXWORKS# define NTPDATE_PRIO (-12)#else# define NTPDATE_PRIO (100)#endif#if defined(HAVE_TIMER_SETTIME) || defined (HAVE_TIMER_CREATE)/* POSIX TIMERS - vxWorks doesn't have itimer - casey */static timer_t ntpdate_timerid;#endif/* * Compatibility stuff for Version 2 */#define NTP_MAXSKW 0x28f /* 0.01 sec in fp format */#define NTP_MINDIST 0x51f /* 0.02 sec in fp format */#define PEER_MAXDISP (64*FP_SECOND) /* maximum dispersion (fp 64) */#define NTP_INFIN 15 /* max stratum, infinity a la Bellman-Ford */#define NTP_MAXWGT (8*FP_SECOND) /* maximum select weight 8 seconds */#define NTP_MAXLIST 5 /* maximum select list size */#define PEER_SHIFT 8 /* 8 suitable for crystal time base *//* * Debugging flag */volatile int debug = 0;/* * File descriptor masks etc. for call to select */int ai_fam_templ;int nbsock;SOCKET fd[MAX_AF]; /* support up to 2 sockets */int fd_family[MAX_AF]; /* to remember the socket family */#ifdef HAVE_POLL_Hstruct pollfd fdmask[MAX_AF];#elsefd_set fdmask;SOCKET maxfd;#endifint polltest = 0;/* * Initializing flag. All async routines watch this and only do their * thing when it is clear. */int initializing = 1;/* * Alarm flag. Set when an alarm occurs */volatile int alarm_flag = 0;/* * Simple query flag. */int simple_query = 0;/* * Unpriviledged port flag. */int unpriv_port = 0;/* * Time to spend measuring drift rate */int rate = 0;/* * Program name. */char *progname;/* * Systemwide parameters and flags */int sys_samples = DEFSAMPLES; /* number of samples/server */u_long sys_timeout = DEFTIMEOUT; /* timeout time, in TIMER_HZ units */struct server *sys_servers; /* the server list */int sys_numservers = 0; /* number of servers to poll */int sys_authenticate = 0; /* true when authenticating */u_int32 sys_authkey = 0; /* set to authentication key in use */u_long sys_authdelay = 0; /* authentication delay */int sys_version = NTP_VERSION; /* version to poll with *//* * The current internal time */u_long current_time = 0;/* * Counter for keeping track of completed servers */int complete_servers = 0;/* * File of encryption keys */#ifndef KEYFILE# ifndef SYS_WINNT#define KEYFILE "/etc/ntp.keys"# else#define KEYFILE "%windir%\\ntp.keys"# endif /* SYS_WINNT */#endif /* KEYFILE */#ifndef SYS_WINNTconst char *key_file = KEYFILE;#elsechar key_file_storage[MAX_PATH+1], *key_file ;#endif /* SYS_WINNT *//* * Miscellaneous flags */int verbose = 0;int always_step = 0;int never_step = 0;int ntpdatemain P((int, char **));static void transmit P((struct server *));static void receive P((struct recvbuf *));static void server_data P((struct server *, s_fp, l_fp *, u_fp));static void clock_filter P((struct server *));static struct server *clock_select P((void));static int clock_adjust P((void));static void addserver P((char *));static struct server *findserver P((struct sockaddr_storage *)); void timer P((void));static void init_alarm P((void));#ifndef SYS_WINNTstatic RETSIGTYPE alarming P((int));#endif /* SYS_WINNT */static void init_io P((void));static void sendpkt P((struct sockaddr_storage *, struct pkt *, int));void input_handler P((void));static int l_adj_systime P((l_fp *));static int l_step_systime P((l_fp *));static void printserver P((struct server *, FILE *));#ifdef SYS_WINNTint on = 1;WORD wVersionRequested;WSADATA wsaData;HANDLE TimerThreadHandle = NULL;#endif /* SYS_WINNT */#ifdef NO_MAIN_ALLOWEDCALL(ntpdate,"ntpdate",ntpdatemain);void clear_globals(){ /* * Debugging flag */ debug = 0; ntp_optind = 0; /* * Initializing flag. All async routines watch this and only do their * thing when it is clear. */ initializing = 1; /* * Alarm flag. Set when an alarm occurs */ alarm_flag = 0; /* * Simple query flag. */ simple_query = 0; /* * Unpriviledged port flag. */ unpriv_port = 0; /* * Time to spend measuring drift rate */ rate = 0; /* * Systemwide parameters and flags */ sys_numservers = 0; /* number of servers to poll */ sys_authenticate = 0; /* true when authenticating */ sys_authkey = 0; /* set to authentication key in use */ sys_authdelay = 0; /* authentication delay */ sys_version = NTP_VERSION; /* version to poll with */ /* * The current internal time */ current_time = 0; /* * Counter for keeping track of completed servers */ complete_servers = 0; verbose = 0; always_step = 0; never_step = 0;}#endif#ifdef HAVE_NETINFOstatic ni_namelist *getnetinfoservers P((void));#endif/* * Main program. Initialize us and loop waiting for I/O and/or * timer expiries. */#ifndef NO_MAIN_ALLOWEDintmain( int argc, char *argv[] ){ return ntpdatemain (argc, argv);}#endif /* NO_MAIN_ALLOWED */intntpdatemain ( int argc, char *argv[] ){ int was_alarmed; struct recvbuf *rbuflist; struct recvbuf *rbuf; l_fp tmp; int errflg; int c; int nfound;#ifdef HAVE_NETINFO ni_namelist *netinfoservers;#endif#ifdef SYS_WINNT HANDLE process_handle; wVersionRequested = MAKEWORD(1,1); if (WSAStartup(wVersionRequested, &wsaData)) { netsyslog(LOG_ERR, "No useable winsock.dll: %m"); exit(1); } key_file = key_file_storage; if (!ExpandEnvironmentStrings(KEYFILE, key_file, MAX_PATH)) { msyslog(LOG_ERR, "ExpandEnvironmentStrings(KEYFILE) failed: %m\n"); }#endif /* SYS_WINNT */#ifdef NO_MAIN_ALLOWED clear_globals();#endif /* Check to see if we have IPv6. Otherwise force the -4 flag */ if (isc_net_probeipv6() != ISC_R_SUCCESS) { ai_fam_templ = AF_INET; } errflg = 0; progname = argv[0]; syslogit = 0; /* * Decode argument list */ while ((c = ntp_getopt(argc, argv, "46a:bBde:k:o:p:qr:st:uv")) != EOF) switch (c) { case '4': ai_fam_templ = AF_INET; break; case '6': ai_fam_templ = AF_INET6; break; case 'a': c = atoi(ntp_optarg); sys_authenticate = 1; sys_authkey = c; break; case 'b': always_step++; never_step = 0; break; case 'B': never_step++; always_step = 0; break; case 'd': ++debug; break; case 'e': if (!atolfp(ntp_optarg, &tmp) || tmp.l_ui != 0) { (void) fprintf(stderr, "%s: encryption delay %s is unlikely\n", progname, ntp_optarg); errflg++; } else { sys_authdelay = tmp.l_uf; } break; case 'k': key_file = ntp_optarg; break; case 'o': sys_version = atoi(ntp_optarg); break; case 'p': c = atoi(ntp_optarg); if (c <= 0 || c > NTP_SHIFT) { (void) fprintf(stderr, "%s: number of samples (%d) is invalid\n", progname, c); errflg++; } else { sys_samples = c; } break; case 'q': simple_query = 1; break; case 'r': c = atoi(ntp_optarg); if (c <= 0 || c > (60 * 60)) { (void) fprintf(stderr, "%s: rate (%d) is invalid: 0 - %d\n", progname, c, (60 * 60)); errflg++; } else { rate = c; } break; case 's': syslogit = 1; break; case 't': if (!atolfp(ntp_optarg, &tmp)) { (void) fprintf(stderr, "%s: timeout %s is undecodeable\n", progname, ntp_optarg); errflg++; } else { sys_timeout = ((LFPTOFP(&tmp) * TIMER_HZ) + 0x8000) >> 16; if (sys_timeout == 0) sys_timeout = 1; } break; case 'v': verbose = 1; break; case 'u': unpriv_port = 1; break; case '?': ++errflg; break; default: break; } if (errflg) { (void) fprintf(stderr, "usage: %s [-46bBdqsuv] [-a key#] [-e delay] [-k file] [-p samples] [-o version#] [-r rate] [-t timeo] server ...\n", progname); exit(2); } if (debug || simple_query) {#ifdef HAVE_SETVBUF static char buf[BUFSIZ];#ifdef SYS_WINNT /* Win32 does not implement line bufferibg */ setvbuf(stdout, NULL, _IONBF, BUFSIZ);#else setvbuf(stdout, buf, _IOLBF, BUFSIZ);#endif /* SYS_WINNT */#else setlinebuf(stdout);#endif } /* * Logging. Open the syslog if we have to */ if (syslogit) {#if !defined (SYS_WINNT) && !defined (SYS_VXWORKS) && !defined SYS_CYGWIN32# ifndef LOG_DAEMON openlog("ntpdate", LOG_PID);# else# ifndef LOG_NTP# define LOG_NTP LOG_DAEMON# endif openlog("ntpdate", LOG_PID | LOG_NDELAY, LOG_NTP); if (debug) setlogmask(LOG_UPTO(LOG_DEBUG)); else setlogmask(LOG_UPTO(LOG_INFO));# endif /* LOG_DAEMON */#endif /* SYS_WINNT */ } if (debug || verbose) msyslog(LOG_NOTICE, "%s", Version); /* * Add servers we are going to be polling */#ifdef HAVE_NETINFO netinfoservers = getnetinfoservers();#endif for ( ; ntp_optind < argc; ntp_optind++) addserver(argv[ntp_optind]);#ifdef HAVE_NETINFO if (netinfoservers) { if ( netinfoservers->ni_namelist_len && *netinfoservers->ni_namelist_val ) { u_int servercount = 0; while (servercount < netinfoservers->ni_namelist_len) { if (debug) msyslog(LOG_DEBUG, "Adding time server %s from NetInfo configuration.", netinfoservers->ni_namelist_val[servercount]); addserver(netinfoservers->ni_namelist_val[servercount++]); } } ni_namelist_free(netinfoservers); free(netinfoservers); }#endif if (sys_numservers == 0) { msyslog(LOG_ERR, "no servers can be used, exiting"); exit(1); } /* * Initialize the time of day routines and the I/O subsystem */ if (sys_authenticate) { init_auth(); if (!authreadkeys(key_file)) { msyslog(LOG_ERR, "no key file <%s>, exiting", key_file); exit(1); } authtrust(sys_authkey, 1); if (!authistrusted(sys_authkey)) { char buf[10]; (void) sprintf(buf, "%lu", (unsigned long)sys_authkey); msyslog(LOG_ERR, "authentication key %s unknown", buf); exit(1); } } init_io(); init_alarm(); /* * Set the priority. */#ifdef SYS_VXWORKS taskPrioritySet( taskIdSelf(), NTPDATE_PRIO);#endif#if defined(HAVE_ATT_NICE) nice (NTPDATE_PRIO);#endif#if defined(HAVE_BSD_NICE) (void) setpriority(PRIO_PROCESS, 0, NTPDATE_PRIO);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -