154359Sroberto/* 254359Sroberto * ntpdate - set the time of day by polling one or more NTP servers 354359Sroberto */ 454359Sroberto 554359Sroberto#ifdef HAVE_CONFIG_H 654359Sroberto# include <config.h> 754359Sroberto#endif 854359Sroberto 982498Sroberto#ifdef HAVE_NETINFO 1082498Sroberto#include <netinfo/ni.h> 1154359Sroberto#endif 1282498Sroberto 13106163Sroberto#include "ntp_machine.h" 1482498Sroberto#include "ntp_fp.h" 1582498Sroberto#include "ntp.h" 1682498Sroberto#include "ntp_io.h" 1782498Sroberto#include "ntp_unixtime.h" 1882498Sroberto#include "ntpdate.h" 1982498Sroberto#include "ntp_string.h" 2082498Sroberto#include "ntp_syslog.h" 2182498Sroberto#include "ntp_select.h" 2282498Sroberto#include "ntp_stdlib.h" 2382498Sroberto 24182007Sroberto/* Don't include ISC's version of IPv6 variables and structures */ 25182007Sroberto#define ISC_IPV6_H 1 26182007Sroberto#include "isc/net.h" 27182007Sroberto#include "isc/result.h" 28182007Sroberto#include "isc/sockaddr.h" 29182007Sroberto 3054359Sroberto#ifdef HAVE_UNISTD_H 3154359Sroberto# include <unistd.h> 3254359Sroberto#endif 3354359Sroberto 3454359Sroberto#include <stdio.h> 3554359Sroberto#include <signal.h> 3654359Sroberto#include <ctype.h> 3754359Sroberto#ifdef HAVE_POLL_H 3882498Sroberto# include <poll.h> 3954359Sroberto#endif 4054359Sroberto#ifndef SYS_WINNT 41106163Sroberto# ifdef HAVE_SYS_SIGNAL_H 42106163Sroberto# include <sys/signal.h> 43106163Sroberto# else 44106163Sroberto# include <signal.h> 45106163Sroberto# endif 4682498Sroberto# ifdef HAVE_SYS_IOCTL_H 4782498Sroberto# include <sys/ioctl.h> 4882498Sroberto# endif 4954359Sroberto#endif /* SYS_WINNT */ 5054359Sroberto#ifdef HAVE_SYS_RESOURCE_H 5154359Sroberto# include <sys/resource.h> 5254359Sroberto#endif /* HAVE_SYS_RESOURCE_H */ 5354359Sroberto 54132451Sroberto#include <arpa/inet.h> 55132451Sroberto 5654359Sroberto#ifdef SYS_VXWORKS 5754359Sroberto# include "ioLib.h" 5854359Sroberto# include "sockLib.h" 5954359Sroberto# include "timers.h" 6054359Sroberto 6154359Sroberto/* select wants a zero structure ... */ 6254359Srobertostruct timeval timeout = {0,0}; 63182007Sroberto#elif defined(SYS_WINNT) 64182007Sroberto/* 65182007Sroberto * Windows does not abort a select select call if SIGALRM goes off 66182007Sroberto * so a 200 ms timeout is needed 67182007Sroberto */ 68182007Srobertostruct timeval timeout = {0,1000000/TIMER_HZ}; 6954359Sroberto#else 7054359Srobertostruct timeval timeout = {60,0}; 7154359Sroberto#endif 7254359Sroberto 73132451Sroberto#ifdef HAVE_NETINFO 74132451Sroberto#include <netinfo/ni.h> 75132451Sroberto#endif 76132451Sroberto 7754359Sroberto#include "recvbuff.h" 7854359Sroberto 7954359Sroberto#ifdef SYS_WINNT 80132451Sroberto#define EPROTONOSUPPORT WSAEPROTONOSUPPORT 81182007Sroberto#define EAFNOSUPPORT WSAEAFNOSUPPORT 82182007Sroberto#define EPFNOSUPPORT WSAEPFNOSUPPORT 83132451Sroberto#define TARGET_RESOLUTION 1 /* Try for 1-millisecond accuracy 8454359Sroberto on Windows NT timers. */ 8554359Sroberto#pragma comment(lib, "winmm") 86182007Srobertoisc_boolean_t ntp_port_inuse(int af, u_short port); 87182007SrobertoUINT wTimerRes; 8854359Sroberto#endif /* SYS_WINNT */ 8954359Sroberto 9054359Sroberto/* 9154359Sroberto * Scheduling priority we run at 9254359Sroberto */ 9354359Sroberto#ifndef SYS_VXWORKS 9454359Sroberto# define NTPDATE_PRIO (-12) 9554359Sroberto#else 9654359Sroberto# define NTPDATE_PRIO (100) 9754359Sroberto#endif 9854359Sroberto 9954359Sroberto#if defined(HAVE_TIMER_SETTIME) || defined (HAVE_TIMER_CREATE) 10054359Sroberto/* POSIX TIMERS - vxWorks doesn't have itimer - casey */ 10154359Srobertostatic timer_t ntpdate_timerid; 10254359Sroberto#endif 10354359Sroberto 10454359Sroberto/* 10554359Sroberto * Compatibility stuff for Version 2 10654359Sroberto */ 10754359Sroberto#define NTP_MAXSKW 0x28f /* 0.01 sec in fp format */ 108182007Sroberto#define NTP_MINDIST 0x51f /* 0.02 sec in fp format */ 10954359Sroberto#define PEER_MAXDISP (64*FP_SECOND) /* maximum dispersion (fp 64) */ 11054359Sroberto#define NTP_INFIN 15 /* max stratum, infinity a la Bellman-Ford */ 11154359Sroberto#define NTP_MAXWGT (8*FP_SECOND) /* maximum select weight 8 seconds */ 112182007Sroberto#define NTP_MAXLIST 5 /* maximum select list size */ 11354359Sroberto#define PEER_SHIFT 8 /* 8 suitable for crystal time base */ 11454359Sroberto 11554359Sroberto/* 116182007Sroberto * for get_systime() 117182007Sroberto */ 118182007Srobertos_char sys_precision; /* local clock precision (log2 s) */ 119182007Sroberto 120182007Sroberto/* 12154359Sroberto * Debugging flag 12254359Sroberto */ 12354359Srobertovolatile int debug = 0; 12454359Sroberto 12554359Sroberto/* 12654359Sroberto * File descriptor masks etc. for call to select 12754359Sroberto */ 128132451Sroberto 129132451Srobertoint ai_fam_templ; 130182007Srobertoint nbsock; /* the number of sockets used */ 131182007SrobertoSOCKET fd[MAX_AF]; 132132451Srobertoint fd_family[MAX_AF]; /* to remember the socket family */ 13354359Sroberto#ifdef HAVE_POLL_H 134132451Srobertostruct pollfd fdmask[MAX_AF]; 13554359Sroberto#else 13654359Srobertofd_set fdmask; 137182007SrobertoSOCKET maxfd; 13854359Sroberto#endif 139132451Srobertoint polltest = 0; 14054359Sroberto 14154359Sroberto/* 14254359Sroberto * Initializing flag. All async routines watch this and only do their 14354359Sroberto * thing when it is clear. 14454359Sroberto */ 14554359Srobertoint initializing = 1; 14654359Sroberto 14754359Sroberto/* 14854359Sroberto * Alarm flag. Set when an alarm occurs 14954359Sroberto */ 15054359Srobertovolatile int alarm_flag = 0; 15154359Sroberto 15254359Sroberto/* 15354359Sroberto * Simple query flag. 15454359Sroberto */ 15554359Srobertoint simple_query = 0; 15654359Sroberto 15754359Sroberto/* 158182007Sroberto * Unprivileged port flag. 15954359Sroberto */ 16054359Srobertoint unpriv_port = 0; 16154359Sroberto 16254359Sroberto/* 16354359Sroberto * Program name. 16454359Sroberto */ 16554359Srobertochar *progname; 16654359Sroberto 16754359Sroberto/* 16854359Sroberto * Systemwide parameters and flags 16954359Sroberto */ 17054359Srobertoint sys_samples = DEFSAMPLES; /* number of samples/server */ 17154359Srobertou_long sys_timeout = DEFTIMEOUT; /* timeout time, in TIMER_HZ units */ 17256746Srobertostruct server *sys_servers; /* the server list */ 17354359Srobertoint sys_numservers = 0; /* number of servers to poll */ 17454359Srobertoint sys_authenticate = 0; /* true when authenticating */ 17554359Srobertou_int32 sys_authkey = 0; /* set to authentication key in use */ 17654359Srobertou_long sys_authdelay = 0; /* authentication delay */ 17754359Srobertoint sys_version = NTP_VERSION; /* version to poll with */ 17854359Sroberto 17954359Sroberto/* 18054359Sroberto * The current internal time 18154359Sroberto */ 18254359Srobertou_long current_time = 0; 18354359Sroberto 18454359Sroberto/* 18554359Sroberto * Counter for keeping track of completed servers 18654359Sroberto */ 18754359Srobertoint complete_servers = 0; 18854359Sroberto 18954359Sroberto/* 19054359Sroberto * File of encryption keys 19154359Sroberto */ 19254359Sroberto 19354359Sroberto#ifndef KEYFILE 19454359Sroberto# ifndef SYS_WINNT 19554359Sroberto#define KEYFILE "/etc/ntp.keys" 19654359Sroberto# else 19754359Sroberto#define KEYFILE "%windir%\\ntp.keys" 19854359Sroberto# endif /* SYS_WINNT */ 19954359Sroberto#endif /* KEYFILE */ 20054359Sroberto 20154359Sroberto#ifndef SYS_WINNT 20254359Srobertoconst char *key_file = KEYFILE; 20354359Sroberto#else 20454359Srobertochar key_file_storage[MAX_PATH+1], *key_file ; 20554359Sroberto#endif /* SYS_WINNT */ 20654359Sroberto 20754359Sroberto/* 20854359Sroberto * Miscellaneous flags 20954359Sroberto */ 21054359Srobertoint verbose = 0; 21154359Srobertoint always_step = 0; 21254359Srobertoint never_step = 0; 21354359Sroberto 214182007Srobertoint ntpdatemain P((int, char **)); 215132451Sroberto 21654359Srobertostatic void transmit P((struct server *)); 21754359Srobertostatic void receive P((struct recvbuf *)); 21854359Srobertostatic void server_data P((struct server *, s_fp, l_fp *, u_fp)); 21954359Srobertostatic void clock_filter P((struct server *)); 22054359Srobertostatic struct server *clock_select P((void)); 22154359Srobertostatic int clock_adjust P((void)); 22254359Srobertostatic void addserver P((char *)); 223132451Srobertostatic struct server *findserver P((struct sockaddr_storage *)); 224182007Srobertovoid timer P((void)); 22554359Srobertostatic void init_alarm P((void)); 22654359Sroberto#ifndef SYS_WINNT 22754359Srobertostatic RETSIGTYPE alarming P((int)); 22854359Sroberto#endif /* SYS_WINNT */ 22954359Srobertostatic void init_io P((void)); 230132451Srobertostatic void sendpkt P((struct sockaddr_storage *, struct pkt *, int)); 23154359Srobertovoid input_handler P((void)); 23254359Sroberto 23354359Srobertostatic int l_adj_systime P((l_fp *)); 23454359Srobertostatic int l_step_systime P((l_fp *)); 23554359Sroberto 23654359Srobertostatic void printserver P((struct server *, FILE *)); 23754359Sroberto 23854359Sroberto#ifdef SYS_WINNT 23954359Srobertoint on = 1; 24054359SrobertoWORD wVersionRequested; 241182007SrobertoWSADATA wsaData; 24254359SrobertoHANDLE TimerThreadHandle = NULL; 24354359Sroberto#endif /* SYS_WINNT */ 24454359Sroberto 24554359Sroberto#ifdef NO_MAIN_ALLOWED 24654359SrobertoCALL(ntpdate,"ntpdate",ntpdatemain); 24754359Sroberto 24854359Srobertovoid clear_globals() 24954359Sroberto{ 25054359Sroberto /* 25154359Sroberto * Debugging flag 25254359Sroberto */ 25354359Sroberto debug = 0; 25454359Sroberto 25554359Sroberto ntp_optind = 0; 25654359Sroberto /* 25754359Sroberto * Initializing flag. All async routines watch this and only do their 25854359Sroberto * thing when it is clear. 25954359Sroberto */ 26054359Sroberto initializing = 1; 26154359Sroberto 26254359Sroberto /* 26354359Sroberto * Alarm flag. Set when an alarm occurs 26454359Sroberto */ 26554359Sroberto alarm_flag = 0; 26654359Sroberto 26754359Sroberto /* 26854359Sroberto * Simple query flag. 26954359Sroberto */ 27054359Sroberto simple_query = 0; 27154359Sroberto 27254359Sroberto /* 273182007Sroberto * Unprivileged port flag. 27454359Sroberto */ 27554359Sroberto unpriv_port = 0; 27654359Sroberto 27754359Sroberto /* 27854359Sroberto * Systemwide parameters and flags 27954359Sroberto */ 28054359Sroberto sys_numservers = 0; /* number of servers to poll */ 28154359Sroberto sys_authenticate = 0; /* true when authenticating */ 28254359Sroberto sys_authkey = 0; /* set to authentication key in use */ 28354359Sroberto sys_authdelay = 0; /* authentication delay */ 28454359Sroberto sys_version = NTP_VERSION; /* version to poll with */ 28554359Sroberto 28654359Sroberto /* 28754359Sroberto * The current internal time 28854359Sroberto */ 28954359Sroberto current_time = 0; 29054359Sroberto 29154359Sroberto /* 29254359Sroberto * Counter for keeping track of completed servers 29354359Sroberto */ 29454359Sroberto complete_servers = 0; 29554359Sroberto verbose = 0; 29654359Sroberto always_step = 0; 29754359Sroberto never_step = 0; 29854359Sroberto} 29954359Sroberto#endif 30054359Sroberto 30154359Sroberto#ifdef HAVE_NETINFO 30254359Srobertostatic ni_namelist *getnetinfoservers P((void)); 30354359Sroberto#endif 30454359Sroberto 30554359Sroberto/* 30654359Sroberto * Main program. Initialize us and loop waiting for I/O and/or 30754359Sroberto * timer expiries. 30854359Sroberto */ 30954359Sroberto#ifndef NO_MAIN_ALLOWED 31054359Srobertoint 31154359Srobertomain( 31254359Sroberto int argc, 31354359Sroberto char *argv[] 31454359Sroberto ) 31554359Sroberto{ 31654359Sroberto return ntpdatemain (argc, argv); 31754359Sroberto} 31854359Sroberto#endif /* NO_MAIN_ALLOWED */ 31954359Sroberto 32054359Srobertoint 32154359Srobertontpdatemain ( 32254359Sroberto int argc, 32354359Sroberto char *argv[] 32454359Sroberto ) 32554359Sroberto{ 32654359Sroberto int was_alarmed; 327182007Sroberto int tot_recvbufs; 32854359Sroberto struct recvbuf *rbuf; 32954359Sroberto l_fp tmp; 33054359Sroberto int errflg; 33154359Sroberto int c; 332182007Sroberto int nfound; 333132451Sroberto 33454359Sroberto#ifdef HAVE_NETINFO 33554359Sroberto ni_namelist *netinfoservers; 33654359Sroberto#endif 33754359Sroberto#ifdef SYS_WINNT 33854359Sroberto HANDLE process_handle; 33954359Sroberto 34054359Sroberto wVersionRequested = MAKEWORD(1,1); 34154359Sroberto if (WSAStartup(wVersionRequested, &wsaData)) { 342132451Sroberto netsyslog(LOG_ERR, "No useable winsock.dll: %m"); 34354359Sroberto exit(1); 34454359Sroberto } 34554359Sroberto 34654359Sroberto key_file = key_file_storage; 34754359Sroberto 34854359Sroberto if (!ExpandEnvironmentStrings(KEYFILE, key_file, MAX_PATH)) 34954359Sroberto { 35054359Sroberto msyslog(LOG_ERR, "ExpandEnvironmentStrings(KEYFILE) failed: %m\n"); 35154359Sroberto } 35254359Sroberto#endif /* SYS_WINNT */ 35354359Sroberto 35454359Sroberto#ifdef NO_MAIN_ALLOWED 35554359Sroberto clear_globals(); 35654359Sroberto#endif 35754359Sroberto 358182007Sroberto 359182007Sroberto /* Check to see if we have IPv6. Otherwise force the -4 flag */ 360182007Sroberto if (isc_net_probeipv6() != ISC_R_SUCCESS) { 361182007Sroberto ai_fam_templ = AF_INET; 362182007Sroberto } 363182007Sroberto 36454359Sroberto errflg = 0; 36554359Sroberto progname = argv[0]; 36654359Sroberto syslogit = 0; 36754359Sroberto 36854359Sroberto /* 36954359Sroberto * Decode argument list 37054359Sroberto */ 371182007Sroberto while ((c = ntp_getopt(argc, argv, "46a:bBde:k:o:p:qst:uv")) != EOF) 37254359Sroberto switch (c) 37354359Sroberto { 374132451Sroberto case '4': 375132451Sroberto ai_fam_templ = AF_INET; 376132451Sroberto break; 377132451Sroberto case '6': 378132451Sroberto ai_fam_templ = AF_INET6; 379132451Sroberto break; 38054359Sroberto case 'a': 38154359Sroberto c = atoi(ntp_optarg); 38254359Sroberto sys_authenticate = 1; 38354359Sroberto sys_authkey = c; 38454359Sroberto break; 38554359Sroberto case 'b': 38654359Sroberto always_step++; 38754359Sroberto never_step = 0; 38854359Sroberto break; 38954359Sroberto case 'B': 39054359Sroberto never_step++; 39154359Sroberto always_step = 0; 39254359Sroberto break; 39354359Sroberto case 'd': 39454359Sroberto ++debug; 39554359Sroberto break; 39654359Sroberto case 'e': 39754359Sroberto if (!atolfp(ntp_optarg, &tmp) 39854359Sroberto || tmp.l_ui != 0) { 39954359Sroberto (void) fprintf(stderr, 40054359Sroberto "%s: encryption delay %s is unlikely\n", 40154359Sroberto progname, ntp_optarg); 40254359Sroberto errflg++; 40354359Sroberto } else { 40454359Sroberto sys_authdelay = tmp.l_uf; 40554359Sroberto } 40654359Sroberto break; 40754359Sroberto case 'k': 40854359Sroberto key_file = ntp_optarg; 40954359Sroberto break; 41054359Sroberto case 'o': 41154359Sroberto sys_version = atoi(ntp_optarg); 41254359Sroberto break; 41354359Sroberto case 'p': 41454359Sroberto c = atoi(ntp_optarg); 41554359Sroberto if (c <= 0 || c > NTP_SHIFT) { 41654359Sroberto (void) fprintf(stderr, 41754359Sroberto "%s: number of samples (%d) is invalid\n", 41854359Sroberto progname, c); 41954359Sroberto errflg++; 42054359Sroberto } else { 42154359Sroberto sys_samples = c; 42254359Sroberto } 42354359Sroberto break; 42454359Sroberto case 'q': 42554359Sroberto simple_query = 1; 42654359Sroberto break; 42754359Sroberto case 's': 42854359Sroberto syslogit = 1; 42954359Sroberto break; 43054359Sroberto case 't': 43154359Sroberto if (!atolfp(ntp_optarg, &tmp)) { 43254359Sroberto (void) fprintf(stderr, 43354359Sroberto "%s: timeout %s is undecodeable\n", 43454359Sroberto progname, ntp_optarg); 43554359Sroberto errflg++; 43654359Sroberto } else { 43754359Sroberto sys_timeout = ((LFPTOFP(&tmp) * TIMER_HZ) 43854359Sroberto + 0x8000) >> 16; 43954359Sroberto if (sys_timeout == 0) 44054359Sroberto sys_timeout = 1; 44154359Sroberto } 44254359Sroberto break; 44354359Sroberto case 'v': 44454359Sroberto verbose = 1; 44554359Sroberto break; 44654359Sroberto case 'u': 44754359Sroberto unpriv_port = 1; 44854359Sroberto break; 44954359Sroberto case '?': 45054359Sroberto ++errflg; 45154359Sroberto break; 45254359Sroberto default: 45354359Sroberto break; 45454359Sroberto } 45554359Sroberto 45654359Sroberto if (errflg) { 45754359Sroberto (void) fprintf(stderr, 458182007Sroberto "usage: %s [-46bBdqsuv] [-a key#] [-e delay] [-k file] [-p samples] [-o version#] [-t timeo] server ...\n", 459132451Sroberto progname); 46054359Sroberto exit(2); 46154359Sroberto } 46254359Sroberto 46354359Sroberto if (debug || simple_query) { 46454359Sroberto#ifdef HAVE_SETVBUF 46554359Sroberto static char buf[BUFSIZ]; 466182007Sroberto#ifdef SYS_WINNT 467182007Sroberto /* Win32 does not implement line buffering */ 468182007Sroberto setvbuf(stdout, NULL, _IONBF, BUFSIZ); 469182007Sroberto#else 47054359Sroberto setvbuf(stdout, buf, _IOLBF, BUFSIZ); 471182007Sroberto#endif /* SYS_WINNT */ 47254359Sroberto#else 47354359Sroberto setlinebuf(stdout); 47454359Sroberto#endif 47554359Sroberto } 47654359Sroberto 47754359Sroberto /* 47854359Sroberto * Logging. Open the syslog if we have to 47954359Sroberto */ 48054359Sroberto if (syslogit) { 48154359Sroberto#if !defined (SYS_WINNT) && !defined (SYS_VXWORKS) && !defined SYS_CYGWIN32 48254359Sroberto# ifndef LOG_DAEMON 48354359Sroberto openlog("ntpdate", LOG_PID); 48454359Sroberto# else 48554359Sroberto 48654359Sroberto# ifndef LOG_NTP 48754359Sroberto# define LOG_NTP LOG_DAEMON 48854359Sroberto# endif 48954359Sroberto openlog("ntpdate", LOG_PID | LOG_NDELAY, LOG_NTP); 49054359Sroberto if (debug) 49154359Sroberto setlogmask(LOG_UPTO(LOG_DEBUG)); 49254359Sroberto else 49354359Sroberto setlogmask(LOG_UPTO(LOG_INFO)); 49454359Sroberto# endif /* LOG_DAEMON */ 49554359Sroberto#endif /* SYS_WINNT */ 49654359Sroberto } 49754359Sroberto 49854359Sroberto if (debug || verbose) 49954359Sroberto msyslog(LOG_NOTICE, "%s", Version); 50054359Sroberto 50154359Sroberto /* 50254359Sroberto * Add servers we are going to be polling 50354359Sroberto */ 50454359Sroberto#ifdef HAVE_NETINFO 50582498Sroberto netinfoservers = getnetinfoservers(); 50654359Sroberto#endif 50754359Sroberto 50854359Sroberto for ( ; ntp_optind < argc; ntp_optind++) 50954359Sroberto addserver(argv[ntp_optind]); 51054359Sroberto 51154359Sroberto#ifdef HAVE_NETINFO 51254359Sroberto if (netinfoservers) { 51354359Sroberto if ( netinfoservers->ni_namelist_len && 51454359Sroberto *netinfoservers->ni_namelist_val ) { 51554359Sroberto u_int servercount = 0; 51654359Sroberto while (servercount < netinfoservers->ni_namelist_len) { 51754359Sroberto if (debug) msyslog(LOG_DEBUG, 51854359Sroberto "Adding time server %s from NetInfo configuration.", 51954359Sroberto netinfoservers->ni_namelist_val[servercount]); 52054359Sroberto addserver(netinfoservers->ni_namelist_val[servercount++]); 52154359Sroberto } 52254359Sroberto } 52354359Sroberto ni_namelist_free(netinfoservers); 52454359Sroberto free(netinfoservers); 52554359Sroberto } 52654359Sroberto#endif 52754359Sroberto 52854359Sroberto if (sys_numservers == 0) { 52954359Sroberto msyslog(LOG_ERR, "no servers can be used, exiting"); 53054359Sroberto exit(1); 53154359Sroberto } 53254359Sroberto 53354359Sroberto /* 53454359Sroberto * Initialize the time of day routines and the I/O subsystem 53554359Sroberto */ 53654359Sroberto if (sys_authenticate) { 53754359Sroberto init_auth(); 53854359Sroberto if (!authreadkeys(key_file)) { 53982498Sroberto msyslog(LOG_ERR, "no key file <%s>, exiting", key_file); 54054359Sroberto exit(1); 54154359Sroberto } 54282498Sroberto authtrust(sys_authkey, 1); 54354359Sroberto if (!authistrusted(sys_authkey)) { 544182007Sroberto msyslog(LOG_ERR, "authentication key %lu unknown", 545182007Sroberto (unsigned long) sys_authkey); 54654359Sroberto exit(1); 54754359Sroberto } 54854359Sroberto } 54954359Sroberto init_io(); 55054359Sroberto init_alarm(); 55154359Sroberto 55254359Sroberto /* 55354359Sroberto * Set the priority. 55454359Sroberto */ 55554359Sroberto#ifdef SYS_VXWORKS 55654359Sroberto taskPrioritySet( taskIdSelf(), NTPDATE_PRIO); 55754359Sroberto#endif 55854359Sroberto#if defined(HAVE_ATT_NICE) 55954359Sroberto nice (NTPDATE_PRIO); 56054359Sroberto#endif 56154359Sroberto#if defined(HAVE_BSD_NICE) 56254359Sroberto (void) setpriority(PRIO_PROCESS, 0, NTPDATE_PRIO); 56354359Sroberto#endif 56454359Sroberto#ifdef SYS_WINNT 56554359Sroberto process_handle = GetCurrentProcess(); 56654359Sroberto if (!SetPriorityClass(process_handle, (DWORD) REALTIME_PRIORITY_CLASS)) { 56754359Sroberto msyslog(LOG_ERR, "SetPriorityClass failed: %m"); 56854359Sroberto } 56954359Sroberto#endif /* SYS_WINNT */ 57054359Sroberto 571132451Sroberto 572132451Sroberto 57354359Sroberto initializing = 0; 57454359Sroberto was_alarmed = 0; 575132451Sroberto 57654359Sroberto while (complete_servers < sys_numservers) { 57754359Sroberto#ifdef HAVE_POLL_H 578182007Sroberto struct pollfd* rdfdes; 579182007Sroberto rdfdes = fdmask; 58054359Sroberto#else 58154359Sroberto fd_set rdfdes; 582182007Sroberto rdfdes = fdmask; 58354359Sroberto#endif 58454359Sroberto 58554359Sroberto if (alarm_flag) { /* alarmed? */ 58654359Sroberto was_alarmed = 1; 58754359Sroberto alarm_flag = 0; 58854359Sroberto } 589182007Sroberto tot_recvbufs = full_recvbuffs(); /* get received buffers */ 59054359Sroberto 591182007Sroberto if (!was_alarmed && tot_recvbufs == 0) { 59254359Sroberto /* 59354359Sroberto * Nothing to do. Wait for something. 59454359Sroberto */ 59554359Sroberto#ifdef HAVE_POLL_H 596182007Sroberto nfound = poll(rdfdes, (unsigned int)nbsock, timeout.tv_sec * 1000); 597132451Sroberto 59854359Sroberto#else 599182007Sroberto nfound = select(maxfd, &rdfdes, (fd_set *)0, 60054359Sroberto (fd_set *)0, &timeout); 60154359Sroberto#endif 60254359Sroberto if (nfound > 0) 60354359Sroberto input_handler(); 604182007Sroberto else if (nfound == SOCKET_ERROR) 605182007Sroberto { 60654359Sroberto#ifndef SYS_WINNT 607182007Sroberto if (errno != EINTR) 60854359Sroberto#else 609182007Sroberto if (WSAGetLastError() != WSAEINTR) 61054359Sroberto#endif 611132451Sroberto netsyslog(LOG_ERR, 61254359Sroberto#ifdef HAVE_POLL_H 61354359Sroberto "poll() error: %m" 61454359Sroberto#else 61554359Sroberto "select() error: %m" 61654359Sroberto#endif 61754359Sroberto ); 618182007Sroberto } else if (errno != 0) { 61954359Sroberto#ifndef SYS_VXWORKS 620132451Sroberto netsyslog(LOG_DEBUG, 62154359Sroberto#ifdef HAVE_POLL_H 62254359Sroberto "poll(): nfound = %d, error: %m", 62354359Sroberto#else 62454359Sroberto "select(): nfound = %d, error: %m", 62554359Sroberto#endif 62654359Sroberto nfound); 62754359Sroberto#endif 62854359Sroberto } 62954359Sroberto if (alarm_flag) { /* alarmed? */ 63054359Sroberto was_alarmed = 1; 63154359Sroberto alarm_flag = 0; 63254359Sroberto } 633182007Sroberto tot_recvbufs = full_recvbuffs(); /* get received buffers */ 63454359Sroberto } 63554359Sroberto 63654359Sroberto /* 63754359Sroberto * Out here, signals are unblocked. Call receive 63854359Sroberto * procedure for each incoming packet. 63954359Sroberto */ 640182007Sroberto rbuf = get_full_recv_buffer(); 641182007Sroberto while (rbuf != NULL) 642182007Sroberto { 64354359Sroberto receive(rbuf); 64454359Sroberto freerecvbuf(rbuf); 645182007Sroberto rbuf = get_full_recv_buffer(); 64654359Sroberto } 64754359Sroberto 64854359Sroberto /* 64954359Sroberto * Call timer to process any timeouts 65054359Sroberto */ 65154359Sroberto if (was_alarmed) { 65254359Sroberto timer(); 65354359Sroberto was_alarmed = 0; 65454359Sroberto } 65554359Sroberto 65654359Sroberto /* 65754359Sroberto * Go around again 65854359Sroberto */ 65954359Sroberto } 66054359Sroberto 66154359Sroberto /* 66254359Sroberto * When we get here we've completed the polling of all servers. 66354359Sroberto * Adjust the clock, then exit. 66454359Sroberto */ 66554359Sroberto#ifdef SYS_WINNT 66654359Sroberto WSACleanup(); 66754359Sroberto#endif 66854359Sroberto#ifdef SYS_VXWORKS 66954359Sroberto close (fd); 67054359Sroberto timer_delete(ntpdate_timerid); 67154359Sroberto#endif 672132451Sroberto 67354359Sroberto return clock_adjust(); 67454359Sroberto} 67554359Sroberto 67654359Sroberto 67754359Sroberto/* 67854359Sroberto * transmit - transmit a packet to the given server, or mark it completed. 679182007Sroberto * This is called by the timeout routine and by the receive 680182007Sroberto * procedure. 68154359Sroberto */ 68254359Srobertostatic void 68354359Srobertotransmit( 68454359Sroberto register struct server *server 68554359Sroberto ) 68654359Sroberto{ 68754359Sroberto struct pkt xpkt; 68854359Sroberto 68954359Sroberto if (debug) 690132451Sroberto printf("transmit(%s)\n", stoa(&(server->srcadr))); 69154359Sroberto 69254359Sroberto if (server->filter_nextpt < server->xmtcnt) { 69354359Sroberto l_fp ts; 69454359Sroberto /* 69554359Sroberto * Last message to this server timed out. Shift 69654359Sroberto * zeros into the filter. 69754359Sroberto */ 69854359Sroberto L_CLR(&ts); 69954359Sroberto server_data(server, 0, &ts, 0); 70054359Sroberto } 70154359Sroberto 70254359Sroberto if ((int)server->filter_nextpt >= sys_samples) { 70354359Sroberto /* 70454359Sroberto * Got all the data we need. Mark this guy 70554359Sroberto * completed and return. 70654359Sroberto */ 70754359Sroberto server->event_time = 0; 70854359Sroberto complete_servers++; 70954359Sroberto return; 71054359Sroberto } 71154359Sroberto 71254359Sroberto /* 713182007Sroberto * If we're here, send another message to the server. Fill in 71454359Sroberto * the packet and let 'er rip. 71554359Sroberto */ 71654359Sroberto xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC, 71754359Sroberto sys_version, MODE_CLIENT); 71854359Sroberto xpkt.stratum = STRATUM_TO_PKT(STRATUM_UNSPEC); 71954359Sroberto xpkt.ppoll = NTP_MINPOLL; 72054359Sroberto xpkt.precision = NTPDATE_PRECISION; 72154359Sroberto xpkt.rootdelay = htonl(NTPDATE_DISTANCE); 72254359Sroberto xpkt.rootdispersion = htonl(NTPDATE_DISP); 72354359Sroberto xpkt.refid = htonl(NTPDATE_REFID); 72454359Sroberto L_CLR(&xpkt.reftime); 72554359Sroberto L_CLR(&xpkt.org); 72654359Sroberto L_CLR(&xpkt.rec); 72754359Sroberto 72854359Sroberto /* 72954359Sroberto * Determine whether to authenticate or not. If so, 73054359Sroberto * fill in the extended part of the packet and do it. 73154359Sroberto * If not, just timestamp it and send it away. 73254359Sroberto */ 73354359Sroberto if (sys_authenticate) { 73454359Sroberto int len; 73554359Sroberto 73682498Sroberto xpkt.exten[0] = htonl(sys_authkey); 73754359Sroberto get_systime(&server->xmt); 73854359Sroberto L_ADDUF(&server->xmt, sys_authdelay); 73954359Sroberto HTONL_FP(&server->xmt, &xpkt.xmt); 74054359Sroberto len = authencrypt(sys_authkey, (u_int32 *)&xpkt, LEN_PKT_NOMAC); 74154359Sroberto sendpkt(&(server->srcadr), &xpkt, (int)(LEN_PKT_NOMAC + len)); 74254359Sroberto 74354359Sroberto if (debug > 1) 74454359Sroberto printf("transmit auth to %s\n", 745132451Sroberto stoa(&(server->srcadr))); 74654359Sroberto } else { 74754359Sroberto get_systime(&(server->xmt)); 74854359Sroberto HTONL_FP(&server->xmt, &xpkt.xmt); 74954359Sroberto sendpkt(&(server->srcadr), &xpkt, LEN_PKT_NOMAC); 75054359Sroberto 75154359Sroberto if (debug > 1) 752132451Sroberto printf("transmit to %s\n", stoa(&(server->srcadr))); 75354359Sroberto } 75454359Sroberto 75554359Sroberto /* 75654359Sroberto * Update the server timeout and transmit count 75754359Sroberto */ 75854359Sroberto server->event_time = current_time + sys_timeout; 75954359Sroberto server->xmtcnt++; 76054359Sroberto} 76154359Sroberto 76254359Sroberto 76354359Sroberto/* 76454359Sroberto * receive - receive and process an incoming frame 76554359Sroberto */ 76654359Srobertostatic void 76754359Srobertoreceive( 76854359Sroberto struct recvbuf *rbufp 76954359Sroberto ) 77054359Sroberto{ 77154359Sroberto register struct pkt *rpkt; 77254359Sroberto register struct server *server; 77354359Sroberto register s_fp di; 774106163Sroberto l_fp t10, t23, tmp; 77554359Sroberto l_fp org; 77654359Sroberto l_fp rec; 77754359Sroberto l_fp ci; 77854359Sroberto int has_mac; 77954359Sroberto int is_authentic; 78054359Sroberto 78154359Sroberto if (debug) 782182007Sroberto printf("receive(%s)\n", stoa(&rbufp->recv_srcadr)); 78354359Sroberto /* 78454359Sroberto * Check to see if the packet basically looks like something 78554359Sroberto * intended for us. 78654359Sroberto */ 78754359Sroberto if (rbufp->recv_length == LEN_PKT_NOMAC) 78854359Sroberto has_mac = 0; 78954359Sroberto else if (rbufp->recv_length >= LEN_PKT_NOMAC) 79054359Sroberto has_mac = 1; 79154359Sroberto else { 79254359Sroberto if (debug) 79354359Sroberto printf("receive: packet length %d\n", 79454359Sroberto rbufp->recv_length); 79554359Sroberto return; /* funny length packet */ 79654359Sroberto } 79754359Sroberto 79854359Sroberto rpkt = &(rbufp->recv_pkt); 79954359Sroberto if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION || 80054359Sroberto PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) { 80154359Sroberto return; 80254359Sroberto } 80354359Sroberto 80454359Sroberto if ((PKT_MODE(rpkt->li_vn_mode) != MODE_SERVER 80554359Sroberto && PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE) 80682498Sroberto || rpkt->stratum >= STRATUM_UNSPEC) { 80754359Sroberto if (debug) 80854359Sroberto printf("receive: mode %d stratum %d\n", 80954359Sroberto PKT_MODE(rpkt->li_vn_mode), rpkt->stratum); 81054359Sroberto return; 81154359Sroberto } 81254359Sroberto 81354359Sroberto /* 81454359Sroberto * So far, so good. See if this is from a server we know. 81554359Sroberto */ 81654359Sroberto server = findserver(&(rbufp->recv_srcadr)); 81754359Sroberto if (server == NULL) { 81854359Sroberto if (debug) 81954359Sroberto printf("receive: server not found\n"); 82054359Sroberto return; 82154359Sroberto } 82254359Sroberto 82354359Sroberto /* 82454359Sroberto * Decode the org timestamp and make sure we're getting a response 82554359Sroberto * to our last request. 82654359Sroberto */ 82754359Sroberto NTOHL_FP(&rpkt->org, &org); 82854359Sroberto if (!L_ISEQU(&org, &server->xmt)) { 82954359Sroberto if (debug) 83054359Sroberto printf("receive: pkt.org and peer.xmt differ\n"); 83154359Sroberto return; 83254359Sroberto } 83354359Sroberto 83454359Sroberto /* 83554359Sroberto * Check out the authenticity if we're doing that. 83654359Sroberto */ 83754359Sroberto if (!sys_authenticate) 83854359Sroberto is_authentic = 1; 83954359Sroberto else { 84054359Sroberto is_authentic = 0; 84154359Sroberto 84254359Sroberto if (debug > 3) 84354359Sroberto printf("receive: rpkt keyid=%ld sys_authkey=%ld decrypt=%ld\n", 84482498Sroberto (long int)ntohl(rpkt->exten[0]), (long int)sys_authkey, 84554359Sroberto (long int)authdecrypt(sys_authkey, (u_int32 *)rpkt, 84654359Sroberto LEN_PKT_NOMAC, (int)(rbufp->recv_length - LEN_PKT_NOMAC))); 84754359Sroberto 84882498Sroberto if (has_mac && ntohl(rpkt->exten[0]) == sys_authkey && 84954359Sroberto authdecrypt(sys_authkey, (u_int32 *)rpkt, LEN_PKT_NOMAC, 85054359Sroberto (int)(rbufp->recv_length - LEN_PKT_NOMAC))) 85154359Sroberto is_authentic = 1; 85254359Sroberto if (debug) 85354359Sroberto printf("receive: authentication %s\n", 85454359Sroberto is_authentic ? "passed" : "failed"); 85554359Sroberto } 85654359Sroberto server->trust <<= 1; 85754359Sroberto if (!is_authentic) 85854359Sroberto server->trust |= 1; 85954359Sroberto 86054359Sroberto /* 86154359Sroberto * Looks good. Record info from the packet. 86254359Sroberto */ 86354359Sroberto server->leap = PKT_LEAP(rpkt->li_vn_mode); 86454359Sroberto server->stratum = PKT_TO_STRATUM(rpkt->stratum); 86554359Sroberto server->precision = rpkt->precision; 86654359Sroberto server->rootdelay = ntohl(rpkt->rootdelay); 86754359Sroberto server->rootdispersion = ntohl(rpkt->rootdispersion); 86854359Sroberto server->refid = rpkt->refid; 86954359Sroberto NTOHL_FP(&rpkt->reftime, &server->reftime); 87054359Sroberto NTOHL_FP(&rpkt->rec, &rec); 87154359Sroberto NTOHL_FP(&rpkt->xmt, &server->org); 87254359Sroberto 87354359Sroberto /* 87454359Sroberto * Make sure the server is at least somewhat sane. If not, try 87554359Sroberto * again. 87654359Sroberto */ 87754359Sroberto if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)) { 87854359Sroberto transmit(server); 87954359Sroberto return; 88054359Sroberto } 88154359Sroberto 88254359Sroberto /* 88354359Sroberto * Calculate the round trip delay (di) and the clock offset (ci). 88454359Sroberto * We use the equations (reordered from those in the spec): 88554359Sroberto * 88654359Sroberto * d = (t2 - t3) - (t1 - t0) 88754359Sroberto * c = ((t2 - t3) + (t1 - t0)) / 2 88854359Sroberto */ 88954359Sroberto t10 = server->org; /* pkt.xmt == t1 */ 89054359Sroberto L_SUB(&t10, &rbufp->recv_time); /* recv_time == t0*/ 89154359Sroberto 89254359Sroberto t23 = rec; /* pkt.rec == t2 */ 89354359Sroberto L_SUB(&t23, &org); /* pkt->org == t3 */ 89454359Sroberto 89554359Sroberto /* now have (t2 - t3) and (t0 - t1). Calculate (ci) and (di) */ 896106163Sroberto /* 897106163Sroberto * Calculate (ci) = ((t1 - t0) / 2) + ((t2 - t3) / 2) 898106163Sroberto * For large offsets this may prevent an overflow on '+' 899106163Sroberto */ 90054359Sroberto ci = t10; 90154359Sroberto L_RSHIFT(&ci); 902106163Sroberto tmp = t23; 903106163Sroberto L_RSHIFT(&tmp); 904106163Sroberto L_ADD(&ci, &tmp); 90554359Sroberto 90654359Sroberto /* 90754359Sroberto * Calculate di in t23 in full precision, then truncate 90854359Sroberto * to an s_fp. 90954359Sroberto */ 91054359Sroberto L_SUB(&t23, &t10); 91154359Sroberto di = LFPTOFP(&t23); 91254359Sroberto 91354359Sroberto if (debug > 3) 91454359Sroberto printf("offset: %s, delay %s\n", lfptoa(&ci, 6), fptoa(di, 5)); 91554359Sroberto 91654359Sroberto di += (FP_SECOND >> (-(int)NTPDATE_PRECISION)) 91754359Sroberto + (FP_SECOND >> (-(int)server->precision)) + NTP_MAXSKW; 91854359Sroberto 91954359Sroberto if (di <= 0) { /* value still too raunchy to use? */ 92054359Sroberto L_CLR(&ci); 92154359Sroberto di = 0; 92254359Sroberto } else { 92354359Sroberto di = max(di, NTP_MINDIST); 92454359Sroberto } 92554359Sroberto 92654359Sroberto /* 92754359Sroberto * Shift this data in, then transmit again. 92854359Sroberto */ 92954359Sroberto server_data(server, (s_fp) di, &ci, 0); 93054359Sroberto transmit(server); 93154359Sroberto} 93254359Sroberto 93354359Sroberto 93454359Sroberto/* 93554359Sroberto * server_data - add a sample to the server's filter registers 93654359Sroberto */ 93754359Srobertostatic void 93854359Srobertoserver_data( 93954359Sroberto register struct server *server, 94054359Sroberto s_fp d, 94154359Sroberto l_fp *c, 94254359Sroberto u_fp e 94354359Sroberto ) 94454359Sroberto{ 945132451Sroberto u_short i; 94654359Sroberto 94754359Sroberto i = server->filter_nextpt; 94854359Sroberto if (i < NTP_SHIFT) { 94954359Sroberto server->filter_delay[i] = d; 95054359Sroberto server->filter_offset[i] = *c; 95154359Sroberto server->filter_soffset[i] = LFPTOFP(c); 95254359Sroberto server->filter_error[i] = e; 953132451Sroberto server->filter_nextpt = (u_short)(i + 1); 95454359Sroberto } 95554359Sroberto} 95654359Sroberto 95754359Sroberto 95854359Sroberto/* 95954359Sroberto * clock_filter - determine a server's delay, dispersion and offset 96054359Sroberto */ 96154359Srobertostatic void 96254359Srobertoclock_filter( 96354359Sroberto register struct server *server 96454359Sroberto ) 96554359Sroberto{ 96654359Sroberto register int i, j; 96754359Sroberto int ord[NTP_SHIFT]; 96854359Sroberto 96954359Sroberto /* 97054359Sroberto * Sort indices into increasing delay order 97154359Sroberto */ 97254359Sroberto for (i = 0; i < sys_samples; i++) 97354359Sroberto ord[i] = i; 97454359Sroberto 97554359Sroberto for (i = 0; i < (sys_samples-1); i++) { 97654359Sroberto for (j = i+1; j < sys_samples; j++) { 97754359Sroberto if (server->filter_delay[ord[j]] == 0) 97854359Sroberto continue; 97954359Sroberto if (server->filter_delay[ord[i]] == 0 98054359Sroberto || (server->filter_delay[ord[i]] 98154359Sroberto > server->filter_delay[ord[j]])) { 98254359Sroberto register int tmp; 98354359Sroberto 98454359Sroberto tmp = ord[i]; 98554359Sroberto ord[i] = ord[j]; 98654359Sroberto ord[j] = tmp; 98754359Sroberto } 98854359Sroberto } 98954359Sroberto } 99054359Sroberto 99154359Sroberto /* 99254359Sroberto * Now compute the dispersion, and assign values to delay and 99354359Sroberto * offset. If there are no samples in the register, delay and 99454359Sroberto * offset go to zero and dispersion is set to the maximum. 99554359Sroberto */ 99654359Sroberto if (server->filter_delay[ord[0]] == 0) { 99754359Sroberto server->delay = 0; 99854359Sroberto L_CLR(&server->offset); 99954359Sroberto server->soffset = 0; 100054359Sroberto server->dispersion = PEER_MAXDISP; 100154359Sroberto } else { 100254359Sroberto register s_fp d; 100354359Sroberto 100454359Sroberto server->delay = server->filter_delay[ord[0]]; 100554359Sroberto server->offset = server->filter_offset[ord[0]]; 100654359Sroberto server->soffset = LFPTOFP(&server->offset); 100754359Sroberto server->dispersion = 0; 100854359Sroberto for (i = 1; i < sys_samples; i++) { 100954359Sroberto if (server->filter_delay[ord[i]] == 0) 101054359Sroberto d = PEER_MAXDISP; 101154359Sroberto else { 101254359Sroberto d = server->filter_soffset[ord[i]] 101354359Sroberto - server->filter_soffset[ord[0]]; 101454359Sroberto if (d < 0) 101554359Sroberto d = -d; 101654359Sroberto if (d > PEER_MAXDISP) 101754359Sroberto d = PEER_MAXDISP; 101854359Sroberto } 101954359Sroberto /* 102054359Sroberto * XXX This *knows* PEER_FILTER is 1/2 102154359Sroberto */ 102254359Sroberto server->dispersion += (u_fp)(d) >> i; 102354359Sroberto } 102454359Sroberto } 102554359Sroberto /* 102654359Sroberto * We're done 102754359Sroberto */ 102854359Sroberto} 102954359Sroberto 103054359Sroberto 103154359Sroberto/* 103254359Sroberto * clock_select - select the pick-of-the-litter clock from the samples 103354359Sroberto * we've got. 103454359Sroberto */ 103554359Srobertostatic struct server * 103654359Srobertoclock_select(void) 103754359Sroberto{ 103854359Sroberto register struct server *server; 103954359Sroberto register int i; 104054359Sroberto register int nlist; 104154359Sroberto register s_fp d; 104254359Sroberto register int j; 104354359Sroberto register int n; 104454359Sroberto s_fp local_threshold; 104554359Sroberto struct server *server_list[NTP_MAXCLOCK]; 104654359Sroberto u_fp server_badness[NTP_MAXCLOCK]; 104754359Sroberto struct server *sys_server; 104854359Sroberto 104954359Sroberto /* 105054359Sroberto * This first chunk of code is supposed to go through all 105154359Sroberto * servers we know about to find the NTP_MAXLIST servers which 105254359Sroberto * are most likely to succeed. We run through the list 105354359Sroberto * doing the sanity checks and trying to insert anyone who 105454359Sroberto * looks okay. We are at all times aware that we should 105554359Sroberto * only keep samples from the top two strata and we only need 105654359Sroberto * NTP_MAXLIST of them. 105754359Sroberto */ 105854359Sroberto nlist = 0; /* none yet */ 105956746Sroberto for (server = sys_servers; server != NULL; server = server->next_server) { 1060106163Sroberto if (server->delay == 0) { 1061106163Sroberto if (debug) 1062106163Sroberto printf("%s: Server dropped: no data\n", ntoa(&server->srcadr)); 1063182007Sroberto continue; /* no data */ 1064106163Sroberto } 1065106163Sroberto if (server->stratum > NTP_INFIN) { 1066106163Sroberto if (debug) 1067106163Sroberto printf("%s: Server dropped: strata too high\n", ntoa(&server->srcadr)); 1068182007Sroberto continue; /* stratum no good */ 1069106163Sroberto } 107054359Sroberto if (server->delay > NTP_MAXWGT) { 1071106163Sroberto if (debug) 1072106163Sroberto printf("%s: Server dropped: server too far away\n", 1073182007Sroberto ntoa(&server->srcadr)); 1074182007Sroberto continue; /* too far away */ 107554359Sroberto } 1076106163Sroberto if (server->leap == LEAP_NOTINSYNC) { 1077106163Sroberto if (debug) 1078106163Sroberto printf("%s: Server dropped: Leap not in sync\n", ntoa(&server->srcadr)); 1079182007Sroberto continue; /* he's in trouble */ 1080106163Sroberto } 108154359Sroberto if (!L_ISHIS(&server->org, &server->reftime)) { 1082106163Sroberto if (debug) 1083106163Sroberto printf("%s: Server dropped: server is very broken\n", 1084106163Sroberto ntoa(&server->srcadr)); 1085182007Sroberto continue; /* very broken host */ 108654359Sroberto } 108754359Sroberto if ((server->org.l_ui - server->reftime.l_ui) 1088106163Sroberto >= NTP_MAXAGE) { 1089106163Sroberto if (debug) 1090106163Sroberto printf("%s: Server dropped: Server has gone too long without sync\n", 1091106163Sroberto ntoa(&server->srcadr)); 109254359Sroberto continue; /* too long without sync */ 109354359Sroberto } 109454359Sroberto if (server->trust != 0) { 1095106163Sroberto if (debug) 1096106163Sroberto printf("%s: Server dropped: Server is untrusted\n", 1097106163Sroberto ntoa(&server->srcadr)); 109854359Sroberto continue; 109954359Sroberto } 110054359Sroberto 110154359Sroberto /* 110254359Sroberto * This one seems sane. Find where he belongs 110354359Sroberto * on the list. 110454359Sroberto */ 110554359Sroberto d = server->dispersion + server->dispersion; 110654359Sroberto for (i = 0; i < nlist; i++) 110754359Sroberto if (server->stratum <= server_list[i]->stratum) 110854359Sroberto break; 110954359Sroberto for ( ; i < nlist; i++) { 111054359Sroberto if (server->stratum < server_list[i]->stratum) 111154359Sroberto break; 111254359Sroberto if (d < (s_fp) server_badness[i]) 111354359Sroberto break; 111454359Sroberto } 111554359Sroberto 111654359Sroberto /* 111754359Sroberto * If i points past the end of the list, this 111854359Sroberto * guy is a loser, else stick him in. 111954359Sroberto */ 112054359Sroberto if (i >= NTP_MAXLIST) 112154359Sroberto continue; 112254359Sroberto for (j = nlist; j > i; j--) 112354359Sroberto if (j < NTP_MAXLIST) { 112454359Sroberto server_list[j] = server_list[j-1]; 112554359Sroberto server_badness[j] 112654359Sroberto = server_badness[j-1]; 112754359Sroberto } 112854359Sroberto 112954359Sroberto server_list[i] = server; 113054359Sroberto server_badness[i] = d; 113154359Sroberto if (nlist < NTP_MAXLIST) 113254359Sroberto nlist++; 113354359Sroberto } 113454359Sroberto 113554359Sroberto /* 113654359Sroberto * Got the five-or-less best. Cut the list where the number of 113754359Sroberto * strata exceeds two. 113854359Sroberto */ 113954359Sroberto j = 0; 114054359Sroberto for (i = 1; i < nlist; i++) 114154359Sroberto if (server_list[i]->stratum > server_list[i-1]->stratum) 114254359Sroberto if (++j == 2) { 114354359Sroberto nlist = i; 114454359Sroberto break; 114554359Sroberto } 114654359Sroberto 114754359Sroberto /* 114854359Sroberto * Whew! What we should have by now is 0 to 5 candidates for 114954359Sroberto * the job of syncing us. If we have none, we're out of luck. 115054359Sroberto * If we have one, he's a winner. If we have more, do falseticker 115154359Sroberto * detection. 115254359Sroberto */ 115354359Sroberto 115454359Sroberto if (nlist == 0) 115554359Sroberto sys_server = 0; 115654359Sroberto else if (nlist == 1) { 115754359Sroberto sys_server = server_list[0]; 115854359Sroberto } else { 115954359Sroberto /* 116054359Sroberto * Re-sort by stratum, bdelay estimate quality and 116154359Sroberto * server.delay. 116254359Sroberto */ 116354359Sroberto for (i = 0; i < nlist-1; i++) 116454359Sroberto for (j = i+1; j < nlist; j++) { 116554359Sroberto if (server_list[i]->stratum 116654359Sroberto < server_list[j]->stratum) 116754359Sroberto break; /* already sorted by stratum */ 116854359Sroberto if (server_list[i]->delay 116954359Sroberto < server_list[j]->delay) 117054359Sroberto continue; 117154359Sroberto server = server_list[i]; 117254359Sroberto server_list[i] = server_list[j]; 117354359Sroberto server_list[j] = server; 117454359Sroberto } 117554359Sroberto 117654359Sroberto /* 117754359Sroberto * Calculate the fixed part of the dispersion limit 117854359Sroberto */ 117954359Sroberto local_threshold = (FP_SECOND >> (-(int)NTPDATE_PRECISION)) 118054359Sroberto + NTP_MAXSKW; 118154359Sroberto 118254359Sroberto /* 118354359Sroberto * Now drop samples until we're down to one. 118454359Sroberto */ 118554359Sroberto while (nlist > 1) { 118654359Sroberto for (n = 0; n < nlist; n++) { 118754359Sroberto server_badness[n] = 0; 118854359Sroberto for (j = 0; j < nlist; j++) { 118954359Sroberto if (j == n) /* with self? */ 119054359Sroberto continue; 119154359Sroberto d = server_list[j]->soffset 119254359Sroberto - server_list[n]->soffset; 119354359Sroberto if (d < 0) /* absolute value */ 119454359Sroberto d = -d; 119554359Sroberto /* 119654359Sroberto * XXX This code *knows* that 119754359Sroberto * NTP_SELECT is 3/4 119854359Sroberto */ 119954359Sroberto for (i = 0; i < j; i++) 120054359Sroberto d = (d>>1) + (d>>2); 120154359Sroberto server_badness[n] += d; 120254359Sroberto } 120354359Sroberto } 120454359Sroberto 120554359Sroberto /* 120654359Sroberto * We now have an array of nlist badness 120754359Sroberto * coefficients. Find the badest. Find 120854359Sroberto * the minimum precision while we're at 120954359Sroberto * it. 121054359Sroberto */ 121154359Sroberto i = 0; 121254359Sroberto n = server_list[0]->precision;; 121354359Sroberto for (j = 1; j < nlist; j++) { 121454359Sroberto if (server_badness[j] >= server_badness[i]) 121554359Sroberto i = j; 121654359Sroberto if (n > server_list[j]->precision) 121754359Sroberto n = server_list[j]->precision; 121854359Sroberto } 121954359Sroberto 122054359Sroberto /* 122154359Sroberto * i is the index of the server with the worst 122254359Sroberto * dispersion. If his dispersion is less than 122354359Sroberto * the threshold, stop now, else delete him and 122454359Sroberto * continue around again. 122554359Sroberto */ 122654359Sroberto if ( (s_fp) server_badness[i] < (local_threshold 122754359Sroberto + (FP_SECOND >> (-n)))) 122854359Sroberto break; 122954359Sroberto for (j = i + 1; j < nlist; j++) 123054359Sroberto server_list[j-1] = server_list[j]; 123154359Sroberto nlist--; 123254359Sroberto } 123354359Sroberto 123454359Sroberto /* 123554359Sroberto * What remains is a list of less than 5 servers. Take 123654359Sroberto * the best. 123754359Sroberto */ 123854359Sroberto sys_server = server_list[0]; 123954359Sroberto } 124054359Sroberto 124154359Sroberto /* 1242182007Sroberto * That's it. Return our server. 124354359Sroberto */ 124454359Sroberto return sys_server; 124554359Sroberto} 124654359Sroberto 124754359Sroberto 124854359Sroberto/* 124954359Sroberto * clock_adjust - process what we've received, and adjust the time 125054359Sroberto * if we got anything decent. 125154359Sroberto */ 125254359Srobertostatic int 125354359Srobertoclock_adjust(void) 125454359Sroberto{ 125556746Sroberto register struct server *sp, *server; 125654359Sroberto s_fp absoffset; 125754359Sroberto int dostep; 125854359Sroberto 125956746Sroberto for (sp = sys_servers; sp != NULL; sp = sp->next_server) 126056746Sroberto clock_filter(sp); 126154359Sroberto server = clock_select(); 126254359Sroberto 126354359Sroberto if (debug || simple_query) { 126456746Sroberto for (sp = sys_servers; sp != NULL; sp = sp->next_server) 126556746Sroberto printserver(sp, stdout); 126654359Sroberto } 126754359Sroberto 126854359Sroberto if (server == 0) { 126954359Sroberto msyslog(LOG_ERR, 127054359Sroberto "no server suitable for synchronization found"); 127154359Sroberto return(1); 127254359Sroberto } 127354359Sroberto 127454359Sroberto if (always_step) { 127554359Sroberto dostep = 1; 127654359Sroberto } else if (never_step) { 127754359Sroberto dostep = 0; 127854359Sroberto } else { 127954359Sroberto absoffset = server->soffset; 128054359Sroberto if (absoffset < 0) 128154359Sroberto absoffset = -absoffset; 1282106424Sroberto dostep = (absoffset >= NTPDATE_THRESHOLD || absoffset < 0); 128354359Sroberto } 128454359Sroberto 128554359Sroberto if (dostep) { 1286182007Sroberto if (simple_query || debug || l_step_systime(&server->offset)){ 128754359Sroberto msyslog(LOG_NOTICE, "step time server %s offset %s sec", 1288132451Sroberto stoa(&server->srcadr), 128954359Sroberto lfptoa(&server->offset, 6)); 129054359Sroberto } 129154359Sroberto } else { 129254359Sroberto#if !defined SYS_WINNT && !defined SYS_CYGWIN32 129354359Sroberto if (simple_query || l_adj_systime(&server->offset)) { 129454359Sroberto msyslog(LOG_NOTICE, "adjust time server %s offset %s sec", 1295132451Sroberto stoa(&server->srcadr), 129654359Sroberto lfptoa(&server->offset, 6)); 129754359Sroberto } 129854359Sroberto#else 129954359Sroberto /* The NT SetSystemTimeAdjustment() call achieves slewing by 130054359Sroberto * changing the clock frequency. This means that we cannot specify 130154359Sroberto * it to slew the clock by a definite amount and then stop like 130254359Sroberto * the Unix adjtime() routine. We can technically adjust the clock 130354359Sroberto * frequency, have ntpdate sleep for a while, and then wake 130454359Sroberto * up and reset the clock frequency, but this might cause some 130554359Sroberto * grief if the user attempts to run ntpd immediately after 130654359Sroberto * ntpdate and the socket is in use. 130754359Sroberto */ 130854359Sroberto printf("\nThe -b option is required by ntpdate on Windows NT platforms\n"); 130954359Sroberto exit(1); 131054359Sroberto#endif /* SYS_WINNT */ 131154359Sroberto } 131254359Sroberto return(0); 131354359Sroberto} 131454359Sroberto 131554359Sroberto 1316182007Sroberto/* 1317182007Sroberto * is_unreachable - check to see if we have a route to given destination 1318182007Sroberto * (non-blocking). 1319182007Sroberto */ 1320182007Srobertostatic int 1321182007Srobertois_reachable (struct sockaddr_storage *dst) 1322182007Sroberto{ 1323182007Sroberto SOCKET sockfd; 1324182007Sroberto 1325182007Sroberto sockfd = socket(dst->ss_family, SOCK_DGRAM, 0); 1326182007Sroberto if (sockfd == -1) { 1327182007Sroberto return 0; 1328182007Sroberto } 1329182007Sroberto 1330182007Sroberto if(connect(sockfd, (struct sockaddr *)dst, SOCKLEN(dst))) { 1331182007Sroberto closesocket(sockfd); 1332182007Sroberto return 0; 1333182007Sroberto } 1334182007Sroberto closesocket(sockfd); 1335182007Sroberto return 1; 1336182007Sroberto} 1337182007Sroberto 1338182007Sroberto 1339182007Sroberto 134054359Sroberto/* XXX ELIMINATE: merge BIG slew into adj_systime in lib/systime.c */ 134154359Sroberto/* 134254359Sroberto * addserver - determine a server's address and allocate a new structure 1343182007Sroberto * for it. 134454359Sroberto */ 134554359Srobertostatic void 134654359Srobertoaddserver( 134754359Sroberto char *serv 134854359Sroberto ) 134954359Sroberto{ 135054359Sroberto register struct server *server; 1351182007Sroberto /* Address infos structure to store result of getaddrinfo */ 1352182007Sroberto struct addrinfo *addrResult, *ptr; 1353182007Sroberto /* Address infos structure to store hints for getaddrinfo */ 1354182007Sroberto struct addrinfo hints; 1355182007Sroberto /* Error variable for getaddrinfo */ 1356182007Sroberto int error; 1357182007Sroberto /* Service name */ 1358182007Sroberto char service[5]; 1359132451Sroberto strcpy(service, "ntp"); 136054359Sroberto 1361182007Sroberto /* Get host address. Looking for UDP datagram connection. */ 1362182007Sroberto memset(&hints, 0, sizeof(hints)); 1363182007Sroberto hints.ai_family = ai_fam_templ; 1364182007Sroberto hints.ai_socktype = SOCK_DGRAM; 1365132451Sroberto 1366138451Sroberto#ifdef DEBUG 1367182007Sroberto if (debug) 1368182007Sroberto printf("Looking for host %s and service %s\n", serv, service); 1369138451Sroberto#endif 1370132451Sroberto 1371182007Sroberto error = getaddrinfo(serv, service, &hints, &addrResult); 1372182007Sroberto if (error != 0) { 1373182007Sroberto /* Conduct more refined error analysis */ 1374182007Sroberto if (error == EAI_FAIL || error == EAI_AGAIN){ 1375182007Sroberto /* Name server is unusable. Exit after failing on the 1376182007Sroberto first server, in order to shorten the timeout caused 1377182007Sroberto by waiting for resolution of several servers */ 1378182007Sroberto fprintf(stderr, "Name server cannot be used, exiting"); 1379182007Sroberto msyslog(LOG_ERR, "name server cannot be used, reason: %s\n", gai_strerror(error)); 1380182007Sroberto exit(1); 1381182007Sroberto } 1382182007Sroberto fprintf(stderr, "Error : %s\n", gai_strerror(error)); 138354359Sroberto msyslog(LOG_ERR, "can't find host %s\n", serv); 138454359Sroberto return; 138554359Sroberto } 1386138451Sroberto#ifdef DEBUG 1387182007Sroberto else if (debug) { 1388182007Sroberto fprintf(stderr, "host found : %s\n", stohost((struct sockaddr_storage*)addrResult->ai_addr)); 1389182007Sroberto } 1390138451Sroberto#endif 139154359Sroberto 1392182007Sroberto /* We must get all returned server in case the first one fails */ 1393182007Sroberto for (ptr = addrResult; ptr != NULL; ptr = ptr->ai_next) { 1394182007Sroberto if (is_reachable ((struct sockaddr_storage *)ptr->ai_addr)) { 1395182007Sroberto server = (struct server *)emalloc(sizeof(struct server)); 1396182007Sroberto memset((char *)server, 0, sizeof(struct server)); 139754359Sroberto 1398182007Sroberto memset(&(server->srcadr), 0, sizeof(struct sockaddr_storage)); 1399182007Sroberto memcpy(&(server->srcadr), ptr->ai_addr, ptr->ai_addrlen); 1400182007Sroberto server->event_time = ++sys_numservers; 1401182007Sroberto if (sys_servers == NULL) 1402182007Sroberto sys_servers = server; 1403182007Sroberto else { 1404182007Sroberto struct server *sp; 140556746Sroberto 1406182007Sroberto for (sp = sys_servers; sp->next_server != NULL; 1407182007Sroberto sp = sp->next_server) ; 1408182007Sroberto sp->next_server = server; 1409182007Sroberto } 1410182007Sroberto } 141156746Sroberto } 1412182007Sroberto 1413182007Sroberto freeaddrinfo(addrResult); 141454359Sroberto} 141554359Sroberto 141654359Sroberto 141754359Sroberto/* 141854359Sroberto * findserver - find a server in the list given its address 1419132451Sroberto * ***(For now it isn't totally AF-Independant, to check later..) 142054359Sroberto */ 142154359Srobertostatic struct server * 142254359Srobertofindserver( 1423132451Sroberto struct sockaddr_storage *addr 142454359Sroberto ) 142554359Sroberto{ 142656746Sroberto struct server *server; 142756746Sroberto struct server *mc_server; 1428182007Sroberto isc_sockaddr_t laddr; 1429182007Sroberto isc_sockaddr_t saddr; 143054359Sroberto 1431182007Sroberto if(addr->ss_family == AF_INET) { 1432182007Sroberto isc_sockaddr_fromin( &laddr, &((struct sockaddr_in*)addr)->sin_addr, 0); 1433182007Sroberto } 1434182007Sroberto else { 1435182007Sroberto isc_sockaddr_fromin6(&laddr, &((struct sockaddr_in6*)addr)->sin6_addr, 0); 1436182007Sroberto } 1437182007Sroberto 1438182007Sroberto 143956746Sroberto mc_server = NULL; 1440132451Sroberto if (htons(((struct sockaddr_in*)addr)->sin_port) != NTP_PORT) 144154359Sroberto return 0; 144254359Sroberto 144356746Sroberto for (server = sys_servers; server != NULL; 144456746Sroberto server = server->next_server) { 144556746Sroberto 1446182007Sroberto if(server->srcadr.ss_family == AF_INET) { 1447182007Sroberto isc_sockaddr_fromin(&saddr, &((struct sockaddr_in*)&server->srcadr)->sin_addr, 0); 1448182007Sroberto } 1449182007Sroberto else { 1450182007Sroberto isc_sockaddr_fromin6(&saddr, &((struct sockaddr_in6*)&server->srcadr)->sin6_addr, 0); 1451182007Sroberto } 1452182007Sroberto if (isc_sockaddr_eqaddr(&laddr, &saddr) == ISC_TRUE) 145356746Sroberto return server; 1454182007Sroberto 1455182007Sroberto if(addr->ss_family == server->srcadr.ss_family) { 1456182007Sroberto if (isc_sockaddr_ismulticast(&saddr) == ISC_TRUE) 1457182007Sroberto mc_server = server; 1458182007Sroberto } 145954359Sroberto } 146056746Sroberto 146156746Sroberto if (mc_server != NULL) { 1462132451Sroberto 146356746Sroberto struct server *sp; 146456746Sroberto 146556746Sroberto if (mc_server->event_time != 0) { 146656746Sroberto mc_server->event_time = 0; 146756746Sroberto complete_servers++; 146856746Sroberto } 1469132451Sroberto 147056746Sroberto server = (struct server *)emalloc(sizeof(struct server)); 147156746Sroberto memset((char *)server, 0, sizeof(struct server)); 147256746Sroberto 1473182007Sroberto memcpy(&server->srcadr, addr, sizeof(struct sockaddr_storage)); 147456746Sroberto 147556746Sroberto server->event_time = ++sys_numservers; 1476132451Sroberto 147756746Sroberto for (sp = sys_servers; sp->next_server != NULL; 147856746Sroberto sp = sp->next_server) ; 147956746Sroberto sp->next_server = server; 148056746Sroberto transmit(server); 148156746Sroberto } 148256746Sroberto return NULL; 148354359Sroberto} 148454359Sroberto 148554359Sroberto 148654359Sroberto/* 148754359Sroberto * timer - process a timer interrupt 148854359Sroberto */ 148954359Srobertovoid 149054359Srobertotimer(void) 149154359Sroberto{ 149256746Sroberto struct server *server; 149354359Sroberto 149454359Sroberto /* 149554359Sroberto * Bump the current idea of the time 149654359Sroberto */ 149754359Sroberto current_time++; 149854359Sroberto 149954359Sroberto /* 150054359Sroberto * Search through the server list looking for guys 150154359Sroberto * who's event timers have expired. Give these to 150254359Sroberto * the transmit routine. 150354359Sroberto */ 150456746Sroberto for (server = sys_servers; server != NULL; 150556746Sroberto server = server->next_server) { 150656746Sroberto if (server->event_time != 0 150756746Sroberto && server->event_time <= current_time) 150856746Sroberto transmit(server); 150954359Sroberto } 151054359Sroberto} 151154359Sroberto 151254359Sroberto 151382498Sroberto/* 151482498Sroberto * The code duplication in the following subroutine sucks, but 151582498Sroberto * we need to appease ansi2knr. 151682498Sroberto */ 151782498Sroberto 151854359Sroberto#ifndef SYS_WINNT 151954359Sroberto/* 152054359Sroberto * alarming - record the occurance of an alarm interrupt 152154359Sroberto */ 152254359Srobertostatic RETSIGTYPE 152354359Srobertoalarming( 152454359Sroberto int sig 152554359Sroberto ) 152682498Sroberto{ 152782498Sroberto alarm_flag++; 152882498Sroberto} 152954359Sroberto#else 153054359Srobertovoid CALLBACK 153154359Srobertoalarming(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) 153254359Sroberto{ 153354359Sroberto alarm_flag++; 153454359Sroberto} 153582498Sroberto#endif /* SYS_WINNT */ 153654359Sroberto 153754359Sroberto 1538182007Sroberto#ifdef SYS_WINNT 1539182007Srobertostatic void 1540182007SrobertocallTimeEndPeriod(void) 1541182007Sroberto{ 1542182007Sroberto timeEndPeriod( wTimerRes ); 1543182007Sroberto wTimerRes = 0; 1544182007Sroberto} 1545182007Sroberto#endif /* SYS_WINNT */ 1546182007Sroberto 1547182007Sroberto 154854359Sroberto/* 154954359Sroberto * init_alarm - set up the timer interrupt 155054359Sroberto */ 155154359Srobertostatic void 155254359Srobertoinit_alarm(void) 155354359Sroberto{ 155454359Sroberto#ifndef SYS_WINNT 155554359Sroberto# ifndef HAVE_TIMER_SETTIME 155654359Sroberto struct itimerval itimer; 155754359Sroberto# else 155854359Sroberto struct itimerspec ntpdate_itimer; 155954359Sroberto# endif 156054359Sroberto#else 156154359Sroberto TIMECAPS tc; 1562182007Sroberto UINT wTimerID; 156354359Sroberto# endif /* SYS_WINNT */ 156454359Sroberto#if defined SYS_CYGWIN32 || defined SYS_WINNT 156554359Sroberto HANDLE hToken; 156654359Sroberto TOKEN_PRIVILEGES tkp; 156754359Sroberto DWORD dwUser = 0; 156854359Sroberto#endif /* SYS_WINNT */ 156954359Sroberto 157054359Sroberto alarm_flag = 0; 157154359Sroberto 157254359Sroberto#ifndef SYS_WINNT 157354359Sroberto# if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME) 157454359Sroberto alarm_flag = 0; 157554359Sroberto /* this code was put in as setitimer() is non existant this us the 157654359Sroberto * POSIX "equivalents" setup - casey 157754359Sroberto */ 157854359Sroberto /* ntpdate_timerid is global - so we can kill timer later */ 157954359Sroberto if (timer_create (CLOCK_REALTIME, NULL, &ntpdate_timerid) == 158054359Sroberto# ifdef SYS_VXWORKS 158154359Sroberto ERROR 158254359Sroberto# else 158354359Sroberto -1 158454359Sroberto# endif 158554359Sroberto ) 158654359Sroberto { 158754359Sroberto fprintf (stderr, "init_alarm(): timer_create (...) FAILED\n"); 158854359Sroberto return; 158954359Sroberto } 159054359Sroberto 159154359Sroberto /* TIMER_HZ = (5) 159254359Sroberto * Set up the alarm interrupt. The first comes 1/(2*TIMER_HZ) 159354359Sroberto * seconds from now and they continue on every 1/TIMER_HZ seconds. 159454359Sroberto */ 159554359Sroberto (void) signal_no_reset(SIGALRM, alarming); 159654359Sroberto ntpdate_itimer.it_interval.tv_sec = ntpdate_itimer.it_value.tv_sec = 0; 159754359Sroberto ntpdate_itimer.it_interval.tv_nsec = 1000000000/TIMER_HZ; 159854359Sroberto ntpdate_itimer.it_value.tv_nsec = 1000000000/(TIMER_HZ<<1); 159954359Sroberto timer_settime(ntpdate_timerid, 0 /* !TIMER_ABSTIME */, &ntpdate_itimer, NULL); 160054359Sroberto# else 160154359Sroberto /* 160254359Sroberto * Set up the alarm interrupt. The first comes 1/(2*TIMER_HZ) 160354359Sroberto * seconds from now and they continue on every 1/TIMER_HZ seconds. 160454359Sroberto */ 160554359Sroberto (void) signal_no_reset(SIGALRM, alarming); 160654359Sroberto itimer.it_interval.tv_sec = itimer.it_value.tv_sec = 0; 160754359Sroberto itimer.it_interval.tv_usec = 1000000/TIMER_HZ; 160854359Sroberto itimer.it_value.tv_usec = 1000000/(TIMER_HZ<<1); 1609132451Sroberto 161054359Sroberto setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0); 161154359Sroberto# endif 161254359Sroberto#if defined SYS_CYGWIN32 161354359Sroberto /* 1614182007Sroberto * Get privileges needed for fiddling with the clock 161554359Sroberto */ 161654359Sroberto 161754359Sroberto /* get the current process token handle */ 161854359Sroberto if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { 161954359Sroberto msyslog(LOG_ERR, "OpenProcessToken failed: %m"); 162054359Sroberto exit(1); 162154359Sroberto } 162254359Sroberto /* get the LUID for system-time privilege. */ 162354359Sroberto LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid); 1624182007Sroberto tkp.PrivilegeCount = 1; /* one privilege to set */ 162554359Sroberto tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 162654359Sroberto /* get set-time privilege for this process. */ 162754359Sroberto AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0); 162854359Sroberto /* cannot test return value of AdjustTokenPrivileges. */ 162954359Sroberto if (GetLastError() != ERROR_SUCCESS) 163054359Sroberto msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m"); 163154359Sroberto#endif 163254359Sroberto#else /* SYS_WINNT */ 163354359Sroberto _tzset(); 163454359Sroberto 163554359Sroberto /* 1636182007Sroberto * Get privileges needed for fiddling with the clock 163754359Sroberto */ 163854359Sroberto 163954359Sroberto /* get the current process token handle */ 164054359Sroberto if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { 164154359Sroberto msyslog(LOG_ERR, "OpenProcessToken failed: %m"); 164254359Sroberto exit(1); 164354359Sroberto } 164454359Sroberto /* get the LUID for system-time privilege. */ 164554359Sroberto LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid); 1646182007Sroberto tkp.PrivilegeCount = 1; /* one privilege to set */ 164754359Sroberto tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 164854359Sroberto /* get set-time privilege for this process. */ 164954359Sroberto AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0); 165054359Sroberto /* cannot test return value of AdjustTokenPrivileges. */ 165154359Sroberto if (GetLastError() != ERROR_SUCCESS) 165254359Sroberto msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m"); 165354359Sroberto 165454359Sroberto /* 165554359Sroberto * Set up timer interrupts for every 2**EVENT_TIMEOUT seconds 165654359Sroberto * Under Win/NT, expiry of timer interval leads to invocation 165754359Sroberto * of a callback function (on a different thread) rather than 165854359Sroberto * generating an alarm signal 165954359Sroberto */ 166054359Sroberto 166154359Sroberto /* determine max and min resolution supported */ 166254359Sroberto if(timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) { 166354359Sroberto msyslog(LOG_ERR, "timeGetDevCaps failed: %m"); 166454359Sroberto exit(1); 166554359Sroberto } 166654359Sroberto wTimerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax); 166754359Sroberto /* establish the minimum timer resolution that we'll use */ 166854359Sroberto timeBeginPeriod(wTimerRes); 1669182007Sroberto atexit(callTimeEndPeriod); 167054359Sroberto 167154359Sroberto /* start the timer event */ 167254359Sroberto wTimerID = timeSetEvent( 1673182007Sroberto (UINT) (1000/TIMER_HZ), /* Delay */ 1674182007Sroberto wTimerRes, /* Resolution */ 1675182007Sroberto (LPTIMECALLBACK) alarming, /* Callback function */ 1676182007Sroberto (DWORD) dwUser, /* User data */ 1677182007Sroberto TIME_PERIODIC); /* Event type (periodic) */ 167854359Sroberto if (wTimerID == 0) { 167954359Sroberto msyslog(LOG_ERR, "timeSetEvent failed: %m"); 168054359Sroberto exit(1); 168154359Sroberto } 168254359Sroberto#endif /* SYS_WINNT */ 168354359Sroberto} 168454359Sroberto 168554359Sroberto 168654359Sroberto 168754359Sroberto 168854359Sroberto/* 168954359Sroberto * We do asynchronous input using the SIGIO facility. A number of 169054359Sroberto * recvbuf buffers are preallocated for input. In the signal 169154359Sroberto * handler we poll to see if the socket is ready and read the 169254359Sroberto * packets from it into the recvbuf's along with a time stamp and 169354359Sroberto * an indication of the source host and the interface it was received 169454359Sroberto * through. This allows us to get as accurate receive time stamps 169554359Sroberto * as possible independent of other processing going on. 169654359Sroberto * 169754359Sroberto * We allocate a number of recvbufs equal to the number of servers 169854359Sroberto * plus 2. This should be plenty. 169954359Sroberto */ 170054359Sroberto 170154359Sroberto 170254359Sroberto/* 170354359Sroberto * init_io - initialize I/O data and open socket 170454359Sroberto */ 170554359Srobertostatic void 170654359Srobertoinit_io(void) 170754359Sroberto{ 1708182007Sroberto struct addrinfo *res, *ressave; 1709182007Sroberto struct addrinfo hints; 1710132451Sroberto char service[5]; 1711182007Sroberto int optval = 1; 1712182007Sroberto int check_ntp_port_in_use = !debug && !simple_query && !unpriv_port; 1713132451Sroberto 171454359Sroberto /* 171554359Sroberto * Init buffer free list and stat counters 171654359Sroberto */ 171754359Sroberto init_recvbuff(sys_numservers + 2); 1718132451Sroberto 171954359Sroberto /* 172054359Sroberto * Open the socket 172154359Sroberto */ 172254359Sroberto 1723132451Sroberto strcpy(service, "ntp"); 1724132451Sroberto 1725182007Sroberto /* 1726182007Sroberto * Init hints addrinfo structure 1727182007Sroberto */ 1728182007Sroberto memset(&hints, 0, sizeof(hints)); 1729182007Sroberto hints.ai_family = ai_fam_templ; 1730182007Sroberto hints.ai_flags = AI_PASSIVE; 1731182007Sroberto hints.ai_socktype = SOCK_DGRAM; 1732132451Sroberto 1733182007Sroberto if(getaddrinfo(NULL, service, &hints, &res) != 0) { 1734182007Sroberto msyslog(LOG_ERR, "getaddrinfo() failed: %m"); 1735182007Sroberto exit(1); 1736182007Sroberto /*NOTREACHED*/ 1737182007Sroberto } 1738132451Sroberto 1739182007Sroberto#ifdef SYS_WINNT 1740182007Sroberto if (check_ntp_port_in_use && ntp_port_inuse(AF_INET, NTP_PORT)){ 1741182007Sroberto netsyslog(LOG_ERR, "the NTP socket is in use, exiting: %m"); 1742182007Sroberto exit(1); 1743182007Sroberto } 1744182007Sroberto#endif 1745132451Sroberto 1746182007Sroberto /* Remember the address of the addrinfo structure chain */ 1747182007Sroberto ressave = res; 1748182007Sroberto 1749182007Sroberto /* 1750182007Sroberto * For each structure returned, open and bind socket 1751182007Sroberto */ 1752182007Sroberto for(nbsock = 0; (nbsock < MAX_AF) && res ; res = res->ai_next) { 175354359Sroberto /* create a datagram (UDP) socket */ 1754182007Sroberto fd[nbsock] = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 1755182007Sroberto if (fd[nbsock] == SOCKET_ERROR) { 1756182007Sroberto#ifndef SYS_WINNT 1757132451Sroberto if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT || 1758132451Sroberto errno == EPFNOSUPPORT) 1759182007Sroberto#else 1760182007Sroberto int err = WSAGetLastError(); 1761182007Sroberto if (err == WSAEPROTONOSUPPORT || err == WSAEAFNOSUPPORT || 1762182007Sroberto err == WSAEPFNOSUPPORT) 1763182007Sroberto#endif 1764132451Sroberto continue; 1765132451Sroberto netsyslog(LOG_ERR, "socket() failed: %m"); 176654359Sroberto exit(1); 176754359Sroberto /*NOTREACHED*/ 1768182007Sroberto } 1769182007Sroberto /* set socket to reuse address */ 1770182007Sroberto if (setsockopt(fd[nbsock], SOL_SOCKET, SO_REUSEADDR, (void*) &optval, sizeof(optval)) < 0) { 1771182007Sroberto netsyslog(LOG_ERR, "setsockopt() SO_REUSEADDR failed: %m"); 1772182007Sroberto exit(1); 1773182007Sroberto /*NOTREACHED*/ 1774182007Sroberto } 1775132451Sroberto#ifdef IPV6_V6ONLY 1776182007Sroberto /* Restricts AF_INET6 socket to IPv6 communications (see RFC 2553bis-03) */ 1777182007Sroberto if (res->ai_family == AF_INET6) 1778182007Sroberto if (setsockopt(fd[nbsock], IPPROTO_IPV6, IPV6_V6ONLY, (void*) &optval, sizeof(optval)) < 0) { 1779182007Sroberto netsyslog(LOG_ERR, "setsockopt() IPV6_V6ONLY failed: %m"); 1780182007Sroberto exit(1); 1781182007Sroberto /*NOTREACHED*/ 1782182007Sroberto } 1783132451Sroberto#endif 178454359Sroberto 1785182007Sroberto /* Remember the socket family in fd_family structure */ 1786182007Sroberto fd_family[nbsock] = res->ai_family; 1787132451Sroberto 1788182007Sroberto /* 1789182007Sroberto * bind the socket to the NTP port 1790182007Sroberto */ 1791182007Sroberto if (check_ntp_port_in_use) { 1792182007Sroberto if (bind(fd[nbsock], res->ai_addr, SOCKLEN(res->ai_addr)) < 0) { 179354359Sroberto#ifndef SYS_WINNT 1794182007Sroberto if (errno == EADDRINUSE) 179554359Sroberto#else 179654359Sroberto if (WSAGetLastError() == WSAEADDRINUSE) 179754359Sroberto#endif /* SYS_WINNT */ 1798182007Sroberto netsyslog(LOG_ERR, "the NTP socket is in use, exiting"); 179954359Sroberto else 1800182007Sroberto netsyslog(LOG_ERR, "bind() fails: %m"); 1801182007Sroberto exit(1); 1802182007Sroberto } 180354359Sroberto } 180454359Sroberto 180554359Sroberto#ifdef HAVE_POLL_H 1806182007Sroberto fdmask[nbsock].fd = fd[nbsock]; 1807182007Sroberto fdmask[nbsock].events = POLLIN; 180854359Sroberto#else 1809182007Sroberto FD_SET(fd[nbsock], &fdmask); 1810182007Sroberto if (maxfd < fd[nbsock]+1) { 1811182007Sroberto maxfd = fd[nbsock]+1; 1812182007Sroberto } 181354359Sroberto#endif 181454359Sroberto 1815182007Sroberto /* 1816182007Sroberto * set non-blocking, 1817182007Sroberto */ 181854359Sroberto#ifndef SYS_WINNT 181954359Sroberto# ifdef SYS_VXWORKS 1820182007Sroberto { 1821182007Sroberto int on = TRUE; 182254359Sroberto 1823182007Sroberto if (ioctl(fd[nbsock],FIONBIO, &on) == ERROR) { 1824182007Sroberto netsyslog(LOG_ERR, "ioctl(FIONBIO) fails: %m"); 1825182007Sroberto exit(1); 1826182007Sroberto } 1827182007Sroberto } 182854359Sroberto# else /* not SYS_VXWORKS */ 182954359Sroberto# if defined(O_NONBLOCK) 1830182007Sroberto if (fcntl(fd[nbsock], F_SETFL, O_NONBLOCK) < 0) { 1831182007Sroberto netsyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m"); 1832182007Sroberto exit(1); 1833182007Sroberto /*NOTREACHED*/ 1834182007Sroberto } 183554359Sroberto# else /* not O_NONBLOCK */ 183654359Sroberto# if defined(FNDELAY) 1837182007Sroberto if (fcntl(fd[nbsock], F_SETFL, FNDELAY) < 0) { 1838182007Sroberto netsyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m"); 1839182007Sroberto exit(1); 1840182007Sroberto /*NOTREACHED*/ 1841182007Sroberto } 184254359Sroberto# else /* FNDELAY */ 184354359Sroberto# include "Bletch: Need non blocking I/O" 184454359Sroberto# endif /* FNDELAY */ 184554359Sroberto# endif /* not O_NONBLOCK */ 184654359Sroberto# endif /* SYS_VXWORKS */ 184754359Sroberto#else /* SYS_WINNT */ 1848182007Sroberto if (ioctlsocket(fd[nbsock], FIONBIO, (u_long *) &on) == SOCKET_ERROR) { 1849182007Sroberto netsyslog(LOG_ERR, "ioctlsocket(FIONBIO) fails: %m"); 1850182007Sroberto exit(1); 1851182007Sroberto } 1852182007Sroberto#endif /* SYS_WINNT */ 1853182007Sroberto nbsock++; 185454359Sroberto } 1855182007Sroberto freeaddrinfo(ressave); 185654359Sroberto} 185754359Sroberto 185854359Sroberto/* 185954359Sroberto * sendpkt - send a packet to the specified destination 186054359Sroberto */ 186154359Srobertostatic void 186254359Srobertosendpkt( 1863132451Sroberto struct sockaddr_storage *dest, 186454359Sroberto struct pkt *pkt, 186554359Sroberto int len 186654359Sroberto ) 186754359Sroberto{ 1868182007Sroberto int i; 186954359Sroberto int cc; 1870182007Sroberto SOCKET sock = INVALID_SOCKET; 187154359Sroberto 187254359Sroberto#ifdef SYS_WINNT 187354359Sroberto DWORD err; 187454359Sroberto#endif /* SYS_WINNT */ 187554359Sroberto 1876182007Sroberto /* Find a local family compatible socket to send ntp packet to ntp server */ 1877182007Sroberto for(i = 0; (i < MAX_AF); i++) { 1878182007Sroberto if(dest->ss_family == fd_family[i]) { 1879182007Sroberto sock = fd[i]; 1880182007Sroberto break; 1881182007Sroberto } 1882182007Sroberto } 1883132451Sroberto 1884182007Sroberto if ( sock == INVALID_SOCKET ) { 1885182007Sroberto netsyslog(LOG_ERR, "cannot find family compatible socket to send ntp packet"); 1886182007Sroberto exit(1); 1887182007Sroberto /*NOTREACHED*/ 1888182007Sroberto } 1889132451Sroberto 1890132451Sroberto cc = sendto(sock, (char *)pkt, len, 0, (struct sockaddr *)dest, 1891132451Sroberto SOCKLEN(dest)); 1892132451Sroberto 1893182007Sroberto if (cc == SOCKET_ERROR) { 189454359Sroberto#ifndef SYS_WINNT 189554359Sroberto if (errno != EWOULDBLOCK && errno != ENOBUFS) 189654359Sroberto#else 189754359Sroberto err = WSAGetLastError(); 189854359Sroberto if (err != WSAEWOULDBLOCK && err != WSAENOBUFS) 189954359Sroberto#endif /* SYS_WINNT */ 1900182007Sroberto netsyslog(LOG_ERR, "sendto(%s): %m", stohost(dest)); 190154359Sroberto } 190254359Sroberto} 190354359Sroberto 190454359Sroberto 190554359Sroberto/* 190654359Sroberto * input_handler - receive packets asynchronously 190754359Sroberto */ 190854359Srobertovoid 190954359Srobertoinput_handler(void) 191054359Sroberto{ 191154359Sroberto register int n; 191254359Sroberto register struct recvbuf *rb; 191354359Sroberto struct timeval tvzero; 191454359Sroberto int fromlen; 191554359Sroberto l_fp ts; 1916182007Sroberto int i; 191754359Sroberto#ifdef HAVE_POLL_H 1918132451Sroberto struct pollfd fds[MAX_AF]; 191954359Sroberto#else 192054359Sroberto fd_set fds; 192154359Sroberto#endif 1922182007Sroberto int fdc = 0; 192354359Sroberto 192454359Sroberto /* 192554359Sroberto * Do a poll to see if we have data 192654359Sroberto */ 192754359Sroberto for (;;) { 192854359Sroberto tvzero.tv_sec = tvzero.tv_usec = 0; 192954359Sroberto#ifdef HAVE_POLL_H 1930132451Sroberto memcpy(fds, fdmask, sizeof(fdmask)); 1931182007Sroberto n = poll(fds, (unsigned int)nbsock, tvzero.tv_sec * 1000); 1932132451Sroberto 1933182007Sroberto /* 1934182007Sroberto * Determine which socket received data 1935182007Sroberto */ 1936132451Sroberto 1937182007Sroberto for(i=0; i < nbsock; i++) { 1938182007Sroberto if(fds[i].revents & POLLIN) { 1939182007Sroberto fdc = fd[i]; 1940182007Sroberto break; 1941182007Sroberto } 1942182007Sroberto } 1943132451Sroberto 194454359Sroberto#else 1945132451Sroberto fds = fdmask; 1946182007Sroberto n = select(maxfd, &fds, (fd_set *)0, (fd_set *)0, &tvzero); 1947132451Sroberto 1948182007Sroberto /* 1949182007Sroberto * Determine which socket received data 1950182007Sroberto */ 1951132451Sroberto 1952182007Sroberto for(i=0; i < nbsock; i++) { 1953182007Sroberto if(FD_ISSET(fd[i], &fds)) { 1954182007Sroberto fdc = fd[i]; 1955182007Sroberto break; 1956182007Sroberto } 1957182007Sroberto } 1958132451Sroberto 195954359Sroberto#endif 196054359Sroberto 196154359Sroberto /* 196254359Sroberto * If nothing to do, just return. If an error occurred, 196354359Sroberto * complain and return. If we've got some, freeze a 196454359Sroberto * timestamp. 196554359Sroberto */ 196654359Sroberto if (n == 0) 196754359Sroberto return; 196854359Sroberto else if (n == -1) { 196954359Sroberto if (errno != EINTR) 1970132451Sroberto netsyslog(LOG_ERR, 197154359Sroberto#ifdef HAVE_POLL_H 197254359Sroberto "poll() error: %m" 197354359Sroberto#else 197454359Sroberto "select() error: %m" 197554359Sroberto#endif 197654359Sroberto ); 197754359Sroberto return; 197854359Sroberto } 197954359Sroberto get_systime(&ts); 198054359Sroberto 198154359Sroberto /* 198254359Sroberto * Get a buffer and read the frame. If we 198354359Sroberto * haven't got a buffer, or this is received 198454359Sroberto * on the wild card socket, just dump the packet. 198554359Sroberto */ 198654359Sroberto if (initializing || free_recvbuffs() == 0) { 198754359Sroberto char buf[100]; 198854359Sroberto 1989132451Sroberto 199054359Sroberto#ifndef SYS_WINNT 1991132451Sroberto (void) read(fdc, buf, sizeof buf); 199254359Sroberto#else 199354359Sroberto /* NT's _read does not operate on nonblocking sockets 199454359Sroberto * either recvfrom or ReadFile() has to be used here. 199554359Sroberto * ReadFile is used in [ntpd]ntp_intres() and ntpdc, 199654359Sroberto * just to be different use recvfrom() here 199754359Sroberto */ 1998132451Sroberto recvfrom(fdc, buf, sizeof(buf), 0, (struct sockaddr *)0, NULL); 199954359Sroberto#endif /* SYS_WINNT */ 200054359Sroberto continue; 200154359Sroberto } 200254359Sroberto 200354359Sroberto rb = get_free_recv_buffer(); 200454359Sroberto 2005132451Sroberto fromlen = sizeof(struct sockaddr_storage); 2006132451Sroberto rb->recv_length = recvfrom(fdc, (char *)&rb->recv_pkt, 200754359Sroberto sizeof(rb->recv_pkt), 0, 200854359Sroberto (struct sockaddr *)&rb->recv_srcadr, &fromlen); 200954359Sroberto if (rb->recv_length == -1) { 201054359Sroberto freerecvbuf(rb); 201154359Sroberto continue; 201254359Sroberto } 201354359Sroberto 201454359Sroberto /* 201554359Sroberto * Got one. Mark how and when it got here, 201654359Sroberto * put it on the full list. 201754359Sroberto */ 201854359Sroberto rb->recv_time = ts; 201954359Sroberto add_full_recv_buffer(rb); 202054359Sroberto } 202154359Sroberto} 202254359Sroberto 202354359Sroberto 202454359Sroberto#if !defined SYS_WINNT && !defined SYS_CYGWIN32 202554359Sroberto/* 202654359Sroberto * adj_systime - do a big long slew of the system time 202754359Sroberto */ 202854359Srobertostatic int 202954359Srobertol_adj_systime( 203054359Sroberto l_fp *ts 203154359Sroberto ) 203254359Sroberto{ 203354359Sroberto struct timeval adjtv, oadjtv; 203454359Sroberto int isneg = 0; 203554359Sroberto l_fp offset; 203654359Sroberto#ifndef STEP_SLEW 203754359Sroberto l_fp overshoot; 203854359Sroberto#endif 203954359Sroberto 204054359Sroberto /* 204154359Sroberto * Take the absolute value of the offset 204254359Sroberto */ 204354359Sroberto offset = *ts; 204454359Sroberto if (L_ISNEG(&offset)) { 204554359Sroberto isneg = 1; 204654359Sroberto L_NEG(&offset); 204754359Sroberto } 204854359Sroberto 204954359Sroberto#ifndef STEP_SLEW 205054359Sroberto /* 205154359Sroberto * Calculate the overshoot. XXX N.B. This code *knows* 205254359Sroberto * ADJ_OVERSHOOT is 1/2. 205354359Sroberto */ 205454359Sroberto overshoot = offset; 205554359Sroberto L_RSHIFTU(&overshoot); 205654359Sroberto if (overshoot.l_ui != 0 || (overshoot.l_uf > ADJ_MAXOVERSHOOT)) { 205754359Sroberto overshoot.l_ui = 0; 205854359Sroberto overshoot.l_uf = ADJ_MAXOVERSHOOT; 205954359Sroberto } 206054359Sroberto L_ADD(&offset, &overshoot); 206154359Sroberto#endif 206254359Sroberto TSTOTV(&offset, &adjtv); 206354359Sroberto 206454359Sroberto if (isneg) { 206554359Sroberto adjtv.tv_sec = -adjtv.tv_sec; 206654359Sroberto adjtv.tv_usec = -adjtv.tv_usec; 206754359Sroberto } 206854359Sroberto 206954359Sroberto if (adjtv.tv_usec != 0 && !debug) { 207054359Sroberto if (adjtime(&adjtv, &oadjtv) < 0) { 207154359Sroberto msyslog(LOG_ERR, "Can't adjust the time of day: %m"); 207254359Sroberto return 0; 207354359Sroberto } 207454359Sroberto } 207554359Sroberto return 1; 207654359Sroberto} 207754359Sroberto#endif /* SYS_WINNT */ 207854359Sroberto 207954359Sroberto 208054359Sroberto/* 208154359Sroberto * This fuction is not the same as lib/systime step_systime!!! 208254359Sroberto */ 208354359Srobertostatic int 208454359Srobertol_step_systime( 208554359Sroberto l_fp *ts 208654359Sroberto ) 208754359Sroberto{ 208854359Sroberto double dtemp; 208954359Sroberto 209054359Sroberto#ifdef SLEWALWAYS 209154359Sroberto#ifdef STEP_SLEW 209254359Sroberto l_fp ftmp; 209354359Sroberto int isneg; 209454359Sroberto int n; 209554359Sroberto 209654359Sroberto if (debug) return 1; 209754359Sroberto /* 209854359Sroberto * Take the absolute value of the offset 209954359Sroberto */ 210054359Sroberto ftmp = *ts; 210154359Sroberto if (L_ISNEG(&ftmp)) { 210254359Sroberto L_NEG(&ftmp); 210354359Sroberto isneg = 1; 210454359Sroberto } else 210554359Sroberto isneg = 0; 210654359Sroberto 210754359Sroberto if (ftmp.l_ui >= 3) { /* Step it and slew - we might win */ 210856746Sroberto LFPTOD(ts, dtemp); 210956746Sroberto n = step_systime(dtemp); 211054359Sroberto if (!n) 211154359Sroberto return n; 211254359Sroberto if (isneg) 211354359Sroberto ts->l_ui = ~0; 211454359Sroberto else 211554359Sroberto ts->l_ui = ~0; 211654359Sroberto } 211754359Sroberto /* 211854359Sroberto * Just add adjustment into the current offset. The update 211954359Sroberto * routine will take care of bringing the system clock into 212054359Sroberto * line. 212154359Sroberto */ 212254359Sroberto#endif 212354359Sroberto if (debug) 212454359Sroberto return 1; 212554359Sroberto#ifdef FORCE_NTPDATE_STEP 212654359Sroberto LFPTOD(ts, dtemp); 212754359Sroberto return step_systime(dtemp); 212854359Sroberto#else 212954359Sroberto l_adj_systime(ts); 213054359Sroberto return 1; 213154359Sroberto#endif 2132182007Sroberto#else /* SLEWALWAYS */ 213354359Sroberto if (debug) 213454359Sroberto return 1; 213554359Sroberto LFPTOD(ts, dtemp); 213654359Sroberto return step_systime(dtemp); 213754359Sroberto#endif /* SLEWALWAYS */ 213854359Sroberto} 213954359Sroberto 214054359Sroberto 214154359Sroberto/* XXX ELIMINATE printserver similar in ntptrace.c, ntpdate.c */ 214254359Sroberto/* 214354359Sroberto * printserver - print detail information for a server 214454359Sroberto */ 214554359Srobertostatic void 214654359Srobertoprintserver( 214754359Sroberto register struct server *pp, 214854359Sroberto FILE *fp 214954359Sroberto ) 215054359Sroberto{ 215154359Sroberto register int i; 215254359Sroberto char junk[5]; 215354359Sroberto char *str; 215454359Sroberto 215554359Sroberto if (!debug) { 215654359Sroberto (void) fprintf(fp, "server %s, stratum %d, offset %s, delay %s\n", 2157132451Sroberto stoa(&pp->srcadr), pp->stratum, 215854359Sroberto lfptoa(&pp->offset, 6), fptoa((s_fp)pp->delay, 5)); 215954359Sroberto return; 216054359Sroberto } 216154359Sroberto 216254359Sroberto (void) fprintf(fp, "server %s, port %d\n", 2163132451Sroberto stoa(&pp->srcadr), ntohs(((struct sockaddr_in*)&(pp->srcadr))->sin_port)); 216454359Sroberto 216554359Sroberto (void) fprintf(fp, "stratum %d, precision %d, leap %c%c, trust %03o\n", 216654359Sroberto pp->stratum, pp->precision, 216754359Sroberto pp->leap & 0x2 ? '1' : '0', 216854359Sroberto pp->leap & 0x1 ? '1' : '0', 216954359Sroberto pp->trust); 217054359Sroberto 217154359Sroberto if (pp->stratum == 1) { 217254359Sroberto junk[4] = 0; 217354359Sroberto memmove(junk, (char *)&pp->refid, 4); 217454359Sroberto str = junk; 217554359Sroberto } else { 2176132451Sroberto str = stoa(&pp->srcadr); 217754359Sroberto } 217854359Sroberto (void) fprintf(fp, 217954359Sroberto "refid [%s], delay %s, dispersion %s\n", 218054359Sroberto str, fptoa((s_fp)pp->delay, 5), 218154359Sroberto ufptoa(pp->dispersion, 5)); 218254359Sroberto 218354359Sroberto (void) fprintf(fp, "transmitted %d, in filter %d\n", 218454359Sroberto pp->xmtcnt, pp->filter_nextpt); 218554359Sroberto 218654359Sroberto (void) fprintf(fp, "reference time: %s\n", 218754359Sroberto prettydate(&pp->reftime)); 218854359Sroberto (void) fprintf(fp, "originate timestamp: %s\n", 218954359Sroberto prettydate(&pp->org)); 219054359Sroberto (void) fprintf(fp, "transmit timestamp: %s\n", 219154359Sroberto prettydate(&pp->xmt)); 219254359Sroberto 219354359Sroberto (void) fprintf(fp, "filter delay: "); 219454359Sroberto for (i = 0; i < NTP_SHIFT; i++) { 219554359Sroberto (void) fprintf(fp, " %-8.8s", fptoa(pp->filter_delay[i], 5)); 219654359Sroberto if (i == (NTP_SHIFT>>1)-1) 219754359Sroberto (void) fprintf(fp, "\n "); 219854359Sroberto } 219954359Sroberto (void) fprintf(fp, "\n"); 220054359Sroberto 220154359Sroberto (void) fprintf(fp, "filter offset:"); 220254359Sroberto for (i = 0; i < PEER_SHIFT; i++) { 220354359Sroberto (void) fprintf(fp, " %-8.8s", lfptoa(&pp->filter_offset[i], 6)); 220454359Sroberto if (i == (PEER_SHIFT>>1)-1) 220554359Sroberto (void) fprintf(fp, "\n "); 220654359Sroberto } 220754359Sroberto (void) fprintf(fp, "\n"); 220854359Sroberto 220954359Sroberto (void) fprintf(fp, "delay %s, dispersion %s\n", 221054359Sroberto fptoa((s_fp)pp->delay, 5), ufptoa(pp->dispersion, 5)); 221154359Sroberto 221254359Sroberto (void) fprintf(fp, "offset %s\n\n", 221354359Sroberto lfptoa(&pp->offset, 6)); 221454359Sroberto} 221554359Sroberto 221654359Sroberto#if !defined(HAVE_VSPRINTF) 221754359Srobertoint 221854359Srobertovsprintf( 221954359Sroberto char *str, 222054359Sroberto const char *fmt, 222154359Sroberto va_list ap 222254359Sroberto ) 222354359Sroberto{ 222454359Sroberto FILE f; 222554359Sroberto int len; 222654359Sroberto 222754359Sroberto f._flag = _IOWRT+_IOSTRG; 222854359Sroberto f._ptr = str; 222954359Sroberto f._cnt = 32767; 223054359Sroberto len = _doprnt(fmt, ap, &f); 223154359Sroberto *f._ptr = 0; 223254359Sroberto return (len); 223354359Sroberto} 223454359Sroberto#endif 223554359Sroberto 223654359Sroberto#if 0 223754359Sroberto/* override function in library since SA_RESTART makes ALL syscalls restart */ 223854359Sroberto#ifdef SA_RESTART 223954359Srobertovoid 224054359Srobertosignal_no_reset( 224154359Sroberto int sig, 224254359Sroberto void (*func)() 224354359Sroberto ) 224454359Sroberto{ 224554359Sroberto int n; 224654359Sroberto struct sigaction vec; 224754359Sroberto 224854359Sroberto vec.sa_handler = func; 224954359Sroberto sigemptyset(&vec.sa_mask); 225054359Sroberto vec.sa_flags = 0; 225154359Sroberto 225254359Sroberto while (1) 225354359Sroberto { 225454359Sroberto n = sigaction(sig, &vec, NULL); 225554359Sroberto if (n == -1 && errno == EINTR) 225654359Sroberto continue; 225754359Sroberto break; 225854359Sroberto } 225954359Sroberto if (n == -1) 226054359Sroberto { 226154359Sroberto perror("sigaction"); 226254359Sroberto exit(1); 226354359Sroberto } 226454359Sroberto} 226554359Sroberto#endif 226654359Sroberto#endif 226754359Sroberto 226854359Sroberto#ifdef HAVE_NETINFO 226954359Srobertostatic ni_namelist * 227054359Srobertogetnetinfoservers(void) 227154359Sroberto{ 227254359Sroberto ni_status status; 227354359Sroberto void *domain; 227454359Sroberto ni_id confdir; 227554359Sroberto ni_namelist *namelist = (ni_namelist*)malloc(sizeof(ni_namelist)); 227654359Sroberto 227754359Sroberto /* Find a time server in NetInfo */ 227854359Sroberto if ((status = ni_open(NULL, ".", &domain)) != NI_OK) return NULL; 227954359Sroberto 228054359Sroberto while (status = ni_pathsearch(domain, &confdir, NETINFO_CONFIG_DIR) == NI_NODIR) { 228154359Sroberto void *next_domain; 228254359Sroberto if (ni_open(domain, "..", &next_domain) != NI_OK) break; 228354359Sroberto ni_free(domain); 228454359Sroberto domain = next_domain; 228554359Sroberto } 228654359Sroberto if (status != NI_OK) return NULL; 228754359Sroberto 228854359Sroberto NI_INIT(namelist); 228954359Sroberto if (ni_lookupprop(domain, &confdir, "server", namelist) != NI_OK) { 229054359Sroberto ni_namelist_free(namelist); 229154359Sroberto free(namelist); 229254359Sroberto return NULL; 229354359Sroberto } 229454359Sroberto 229554359Sroberto return(namelist); 229654359Sroberto} 229754359Sroberto#endif 2298182007Sroberto 2299182007Sroberto#ifdef SYS_WINNT 2300182007Srobertoisc_boolean_t ntp_port_inuse(int af, u_short port) 2301182007Sroberto{ 2302182007Sroberto /* 2303182007Sroberto * Check if NTP socket is already in use on this system 2304182007Sroberto * This is only for Windows Systems, as they tend not to fail on the real bind() below 2305182007Sroberto */ 2306182007Sroberto 2307182007Sroberto SOCKET checksocket; 2308182007Sroberto struct sockaddr_in checkservice; 2309182007Sroberto checksocket = socket(af, SOCK_DGRAM, 0); 2310182007Sroberto if (checksocket == INVALID_SOCKET) { 2311182007Sroberto return (ISC_TRUE); 2312182007Sroberto } 2313182007Sroberto 2314182007Sroberto checkservice.sin_family = (short) AF_INET; 2315182007Sroberto checkservice.sin_addr.s_addr = INADDR_LOOPBACK; 2316182007Sroberto checkservice.sin_port = htons(port); 2317182007Sroberto 2318182007Sroberto if (bind(checksocket, (struct sockaddr *)&checkservice, 2319182007Sroberto sizeof(checkservice)) == SOCKET_ERROR) { 2320182007Sroberto if ( WSAGetLastError() == WSAEADDRINUSE ){ 2321182007Sroberto closesocket(checksocket); 2322182007Sroberto return (ISC_TRUE); 2323182007Sroberto } 2324182007Sroberto } 2325182007Sroberto closesocket(checksocket); 2326182007Sroberto return (ISC_FALSE); 2327182007Sroberto} 2328182007Sroberto#endif 2329