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" 17285612Sdelphij#include "timevalops.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" 23285612Sdelphij#include <ssl_applink.c> 2482498Sroberto 25182007Sroberto#include "isc/net.h" 26182007Sroberto#include "isc/result.h" 27182007Sroberto#include "isc/sockaddr.h" 28182007Sroberto 2954359Sroberto#ifdef HAVE_UNISTD_H 3054359Sroberto# include <unistd.h> 3154359Sroberto#endif 3254359Sroberto 3354359Sroberto#include <stdio.h> 3454359Sroberto#include <signal.h> 3554359Sroberto#include <ctype.h> 3654359Sroberto#ifdef HAVE_POLL_H 3782498Sroberto# include <poll.h> 3854359Sroberto#endif 39285612Sdelphij#ifdef HAVE_SYS_SIGNAL_H 40285612Sdelphij# include <sys/signal.h> 41285612Sdelphij#endif 42285612Sdelphij#ifdef HAVE_SYS_IOCTL_H 43285612Sdelphij# include <sys/ioctl.h> 44285612Sdelphij#endif 4554359Sroberto#ifdef HAVE_SYS_RESOURCE_H 4654359Sroberto# include <sys/resource.h> 47285612Sdelphij#endif 4854359Sroberto 49132451Sroberto#include <arpa/inet.h> 50132451Sroberto 5154359Sroberto#ifdef SYS_VXWORKS 5254359Sroberto# include "ioLib.h" 5354359Sroberto# include "sockLib.h" 5454359Sroberto# include "timers.h" 5554359Sroberto 5654359Sroberto/* select wants a zero structure ... */ 5754359Srobertostruct timeval timeout = {0,0}; 58182007Sroberto#elif defined(SYS_WINNT) 59182007Sroberto/* 60182007Sroberto * Windows does not abort a select select call if SIGALRM goes off 61285612Sdelphij * so a 200 ms timeout is needed (TIMER_HZ is 5). 62182007Sroberto */ 63285612Sdelphijstruct sock_timeval timeout = {0,1000000/TIMER_HZ}; 6454359Sroberto#else 6554359Srobertostruct timeval timeout = {60,0}; 6654359Sroberto#endif 6754359Sroberto 68132451Sroberto#ifdef HAVE_NETINFO 69132451Sroberto#include <netinfo/ni.h> 70132451Sroberto#endif 71132451Sroberto 7254359Sroberto#include "recvbuff.h" 7354359Sroberto 7454359Sroberto#ifdef SYS_WINNT 75132451Sroberto#define TARGET_RESOLUTION 1 /* Try for 1-millisecond accuracy 7654359Sroberto on Windows NT timers. */ 7754359Sroberto#pragma comment(lib, "winmm") 78182007Srobertoisc_boolean_t ntp_port_inuse(int af, u_short port); 79182007SrobertoUINT wTimerRes; 8054359Sroberto#endif /* SYS_WINNT */ 8154359Sroberto 8254359Sroberto/* 8354359Sroberto * Scheduling priority we run at 8454359Sroberto */ 8554359Sroberto#ifndef SYS_VXWORKS 8654359Sroberto# define NTPDATE_PRIO (-12) 8754359Sroberto#else 8854359Sroberto# define NTPDATE_PRIO (100) 8954359Sroberto#endif 9054359Sroberto 91285612Sdelphij#ifdef HAVE_TIMER_CREATE 9254359Sroberto/* POSIX TIMERS - vxWorks doesn't have itimer - casey */ 9354359Srobertostatic timer_t ntpdate_timerid; 9454359Sroberto#endif 9554359Sroberto 9654359Sroberto/* 9754359Sroberto * Compatibility stuff for Version 2 9854359Sroberto */ 9954359Sroberto#define NTP_MAXSKW 0x28f /* 0.01 sec in fp format */ 100182007Sroberto#define NTP_MINDIST 0x51f /* 0.02 sec in fp format */ 10154359Sroberto#define PEER_MAXDISP (64*FP_SECOND) /* maximum dispersion (fp 64) */ 10254359Sroberto#define NTP_INFIN 15 /* max stratum, infinity a la Bellman-Ford */ 10354359Sroberto#define NTP_MAXWGT (8*FP_SECOND) /* maximum select weight 8 seconds */ 104182007Sroberto#define NTP_MAXLIST 5 /* maximum select list size */ 10554359Sroberto#define PEER_SHIFT 8 /* 8 suitable for crystal time base */ 10654359Sroberto 10754359Sroberto/* 108182007Sroberto * for get_systime() 109182007Sroberto */ 110182007Srobertos_char sys_precision; /* local clock precision (log2 s) */ 111182007Sroberto 112182007Sroberto/* 11354359Sroberto * File descriptor masks etc. for call to select 11454359Sroberto */ 115132451Sroberto 116132451Srobertoint ai_fam_templ; 117285612Sdelphijint nbsock; /* the number of sockets used */ 118182007SrobertoSOCKET fd[MAX_AF]; 119285612Sdelphijint fd_family[MAX_AF]; /* to remember the socket family */ 12054359Sroberto#ifdef HAVE_POLL_H 121132451Srobertostruct pollfd fdmask[MAX_AF]; 12254359Sroberto#else 12354359Srobertofd_set fdmask; 124182007SrobertoSOCKET maxfd; 12554359Sroberto#endif 126132451Srobertoint polltest = 0; 12754359Sroberto 12854359Sroberto/* 12954359Sroberto * Initializing flag. All async routines watch this and only do their 13054359Sroberto * thing when it is clear. 13154359Sroberto */ 13254359Srobertoint initializing = 1; 13354359Sroberto 13454359Sroberto/* 13554359Sroberto * Alarm flag. Set when an alarm occurs 13654359Sroberto */ 13754359Srobertovolatile int alarm_flag = 0; 13854359Sroberto 13954359Sroberto/* 14054359Sroberto * Simple query flag. 14154359Sroberto */ 14254359Srobertoint simple_query = 0; 14354359Sroberto 14454359Sroberto/* 145182007Sroberto * Unprivileged port flag. 14654359Sroberto */ 14754359Srobertoint unpriv_port = 0; 14854359Sroberto 14954359Sroberto/* 15054359Sroberto * Program name. 15154359Sroberto */ 152289997Sglebiuschar const *progname; 15354359Sroberto 15454359Sroberto/* 15554359Sroberto * Systemwide parameters and flags 15654359Sroberto */ 15754359Srobertoint sys_samples = DEFSAMPLES; /* number of samples/server */ 15854359Srobertou_long sys_timeout = DEFTIMEOUT; /* timeout time, in TIMER_HZ units */ 15956746Srobertostruct server *sys_servers; /* the server list */ 16054359Srobertoint sys_numservers = 0; /* number of servers to poll */ 16154359Srobertoint sys_authenticate = 0; /* true when authenticating */ 16254359Srobertou_int32 sys_authkey = 0; /* set to authentication key in use */ 16354359Srobertou_long sys_authdelay = 0; /* authentication delay */ 16454359Srobertoint sys_version = NTP_VERSION; /* version to poll with */ 16554359Sroberto 16654359Sroberto/* 16754359Sroberto * The current internal time 16854359Sroberto */ 16954359Srobertou_long current_time = 0; 17054359Sroberto 17154359Sroberto/* 17254359Sroberto * Counter for keeping track of completed servers 17354359Sroberto */ 17454359Srobertoint complete_servers = 0; 17554359Sroberto 17654359Sroberto/* 17754359Sroberto * File of encryption keys 17854359Sroberto */ 17954359Sroberto 18054359Sroberto#ifndef KEYFILE 18154359Sroberto# ifndef SYS_WINNT 18254359Sroberto#define KEYFILE "/etc/ntp.keys" 18354359Sroberto# else 18454359Sroberto#define KEYFILE "%windir%\\ntp.keys" 18554359Sroberto# endif /* SYS_WINNT */ 18654359Sroberto#endif /* KEYFILE */ 18754359Sroberto 18854359Sroberto#ifndef SYS_WINNT 18954359Srobertoconst char *key_file = KEYFILE; 19054359Sroberto#else 19154359Srobertochar key_file_storage[MAX_PATH+1], *key_file ; 19254359Sroberto#endif /* SYS_WINNT */ 19354359Sroberto 19454359Sroberto/* 19554359Sroberto * Miscellaneous flags 19654359Sroberto */ 19754359Srobertoint verbose = 0; 19854359Srobertoint always_step = 0; 19954359Srobertoint never_step = 0; 20054359Sroberto 201285612Sdelphijint ntpdatemain (int, char **); 202132451Sroberto 203285612Sdelphijstatic void transmit (struct server *); 204285612Sdelphijstatic void receive (struct recvbuf *); 205285612Sdelphijstatic void server_data (struct server *, s_fp, l_fp *, u_fp); 206285612Sdelphijstatic void clock_filter (struct server *); 207285612Sdelphijstatic struct server *clock_select (void); 208285612Sdelphijstatic int clock_adjust (void); 209285612Sdelphijstatic void addserver (char *); 210285612Sdelphijstatic struct server *findserver (sockaddr_u *); 211285612Sdelphij void timer (void); 212285612Sdelphijstatic void init_alarm (void); 21354359Sroberto#ifndef SYS_WINNT 214285612Sdelphijstatic RETSIGTYPE alarming (int); 21554359Sroberto#endif /* SYS_WINNT */ 216285612Sdelphijstatic void init_io (void); 217285612Sdelphijstatic void sendpkt (sockaddr_u *, struct pkt *, int); 218285612Sdelphijvoid input_handler (void); 21954359Sroberto 220285612Sdelphijstatic int l_adj_systime (l_fp *); 221285612Sdelphijstatic int l_step_systime (l_fp *); 22254359Sroberto 223285612Sdelphijstatic void printserver (struct server *, FILE *); 22454359Sroberto 22554359Sroberto#ifdef SYS_WINNT 22654359Srobertoint on = 1; 22754359SrobertoWORD wVersionRequested; 228182007SrobertoWSADATA wsaData; 22954359Sroberto#endif /* SYS_WINNT */ 23054359Sroberto 23154359Sroberto#ifdef NO_MAIN_ALLOWED 23254359SrobertoCALL(ntpdate,"ntpdate",ntpdatemain); 23354359Sroberto 23454359Srobertovoid clear_globals() 23554359Sroberto{ 23654359Sroberto /* 23754359Sroberto * Debugging flag 23854359Sroberto */ 23954359Sroberto debug = 0; 24054359Sroberto 24154359Sroberto ntp_optind = 0; 24254359Sroberto /* 24354359Sroberto * Initializing flag. All async routines watch this and only do their 24454359Sroberto * thing when it is clear. 24554359Sroberto */ 24654359Sroberto initializing = 1; 24754359Sroberto 24854359Sroberto /* 24954359Sroberto * Alarm flag. Set when an alarm occurs 25054359Sroberto */ 25154359Sroberto alarm_flag = 0; 25254359Sroberto 25354359Sroberto /* 25454359Sroberto * Simple query flag. 25554359Sroberto */ 25654359Sroberto simple_query = 0; 25754359Sroberto 25854359Sroberto /* 259182007Sroberto * Unprivileged port flag. 26054359Sroberto */ 26154359Sroberto unpriv_port = 0; 26254359Sroberto 26354359Sroberto /* 26454359Sroberto * Systemwide parameters and flags 26554359Sroberto */ 26654359Sroberto sys_numservers = 0; /* number of servers to poll */ 26754359Sroberto sys_authenticate = 0; /* true when authenticating */ 26854359Sroberto sys_authkey = 0; /* set to authentication key in use */ 26954359Sroberto sys_authdelay = 0; /* authentication delay */ 27054359Sroberto sys_version = NTP_VERSION; /* version to poll with */ 27154359Sroberto 27254359Sroberto /* 27354359Sroberto * The current internal time 27454359Sroberto */ 27554359Sroberto current_time = 0; 27654359Sroberto 27754359Sroberto /* 27854359Sroberto * Counter for keeping track of completed servers 27954359Sroberto */ 28054359Sroberto complete_servers = 0; 28154359Sroberto verbose = 0; 28254359Sroberto always_step = 0; 28354359Sroberto never_step = 0; 28454359Sroberto} 28554359Sroberto#endif 28654359Sroberto 28754359Sroberto#ifdef HAVE_NETINFO 288285612Sdelphijstatic ni_namelist *getnetinfoservers (void); 28954359Sroberto#endif 29054359Sroberto 29154359Sroberto/* 29254359Sroberto * Main program. Initialize us and loop waiting for I/O and/or 29354359Sroberto * timer expiries. 29454359Sroberto */ 29554359Sroberto#ifndef NO_MAIN_ALLOWED 29654359Srobertoint 29754359Srobertomain( 29854359Sroberto int argc, 29954359Sroberto char *argv[] 30054359Sroberto ) 30154359Sroberto{ 30254359Sroberto return ntpdatemain (argc, argv); 30354359Sroberto} 30454359Sroberto#endif /* NO_MAIN_ALLOWED */ 30554359Sroberto 30654359Srobertoint 30754359Srobertontpdatemain ( 30854359Sroberto int argc, 30954359Sroberto char *argv[] 31054359Sroberto ) 31154359Sroberto{ 31254359Sroberto int was_alarmed; 313182007Sroberto int tot_recvbufs; 31454359Sroberto struct recvbuf *rbuf; 31554359Sroberto l_fp tmp; 31654359Sroberto int errflg; 31754359Sroberto int c; 318182007Sroberto int nfound; 319132451Sroberto 32054359Sroberto#ifdef HAVE_NETINFO 32154359Sroberto ni_namelist *netinfoservers; 32254359Sroberto#endif 32354359Sroberto#ifdef SYS_WINNT 32454359Sroberto key_file = key_file_storage; 32554359Sroberto 32654359Sroberto if (!ExpandEnvironmentStrings(KEYFILE, key_file, MAX_PATH)) 327285612Sdelphij msyslog(LOG_ERR, "ExpandEnvironmentStrings(KEYFILE) failed: %m"); 328285612Sdelphij 329285612Sdelphij ssl_applink(); 33054359Sroberto#endif /* SYS_WINNT */ 33154359Sroberto 33254359Sroberto#ifdef NO_MAIN_ALLOWED 33354359Sroberto clear_globals(); 33454359Sroberto#endif 33554359Sroberto 336285612Sdelphij init_lib(); /* sets up ipv4_works, ipv6_works */ 337182007Sroberto 338285612Sdelphij /* Check to see if we have IPv6. Otherwise default to IPv4 */ 339285612Sdelphij if (!ipv6_works) 340182007Sroberto ai_fam_templ = AF_INET; 341182007Sroberto 34254359Sroberto errflg = 0; 34354359Sroberto progname = argv[0]; 34454359Sroberto syslogit = 0; 34554359Sroberto 34654359Sroberto /* 34754359Sroberto * Decode argument list 34854359Sroberto */ 349182007Sroberto while ((c = ntp_getopt(argc, argv, "46a:bBde:k:o:p:qst:uv")) != EOF) 35054359Sroberto switch (c) 35154359Sroberto { 352132451Sroberto case '4': 353132451Sroberto ai_fam_templ = AF_INET; 354132451Sroberto break; 355132451Sroberto case '6': 356132451Sroberto ai_fam_templ = AF_INET6; 357132451Sroberto break; 35854359Sroberto case 'a': 35954359Sroberto c = atoi(ntp_optarg); 36054359Sroberto sys_authenticate = 1; 36154359Sroberto sys_authkey = c; 36254359Sroberto break; 36354359Sroberto case 'b': 36454359Sroberto always_step++; 36554359Sroberto never_step = 0; 36654359Sroberto break; 36754359Sroberto case 'B': 36854359Sroberto never_step++; 36954359Sroberto always_step = 0; 37054359Sroberto break; 37154359Sroberto case 'd': 37254359Sroberto ++debug; 37354359Sroberto break; 37454359Sroberto case 'e': 37554359Sroberto if (!atolfp(ntp_optarg, &tmp) 37654359Sroberto || tmp.l_ui != 0) { 37754359Sroberto (void) fprintf(stderr, 37854359Sroberto "%s: encryption delay %s is unlikely\n", 37954359Sroberto progname, ntp_optarg); 38054359Sroberto errflg++; 38154359Sroberto } else { 38254359Sroberto sys_authdelay = tmp.l_uf; 38354359Sroberto } 38454359Sroberto break; 38554359Sroberto case 'k': 38654359Sroberto key_file = ntp_optarg; 38754359Sroberto break; 38854359Sroberto case 'o': 38954359Sroberto sys_version = atoi(ntp_optarg); 39054359Sroberto break; 39154359Sroberto case 'p': 39254359Sroberto c = atoi(ntp_optarg); 39354359Sroberto if (c <= 0 || c > NTP_SHIFT) { 39454359Sroberto (void) fprintf(stderr, 39554359Sroberto "%s: number of samples (%d) is invalid\n", 39654359Sroberto progname, c); 39754359Sroberto errflg++; 39854359Sroberto } else { 39954359Sroberto sys_samples = c; 40054359Sroberto } 40154359Sroberto break; 40254359Sroberto case 'q': 40354359Sroberto simple_query = 1; 40454359Sroberto break; 40554359Sroberto case 's': 40654359Sroberto syslogit = 1; 40754359Sroberto break; 40854359Sroberto case 't': 40954359Sroberto if (!atolfp(ntp_optarg, &tmp)) { 41054359Sroberto (void) fprintf(stderr, 41154359Sroberto "%s: timeout %s is undecodeable\n", 41254359Sroberto progname, ntp_optarg); 41354359Sroberto errflg++; 41454359Sroberto } else { 41554359Sroberto sys_timeout = ((LFPTOFP(&tmp) * TIMER_HZ) 41654359Sroberto + 0x8000) >> 16; 417285612Sdelphij sys_timeout = max(sys_timeout, MINTIMEOUT); 41854359Sroberto } 41954359Sroberto break; 42054359Sroberto case 'v': 42154359Sroberto verbose = 1; 42254359Sroberto break; 42354359Sroberto case 'u': 42454359Sroberto unpriv_port = 1; 42554359Sroberto break; 42654359Sroberto case '?': 42754359Sroberto ++errflg; 42854359Sroberto break; 42954359Sroberto default: 43054359Sroberto break; 43154359Sroberto } 43254359Sroberto 43354359Sroberto if (errflg) { 43454359Sroberto (void) fprintf(stderr, 435182007Sroberto "usage: %s [-46bBdqsuv] [-a key#] [-e delay] [-k file] [-p samples] [-o version#] [-t timeo] server ...\n", 436132451Sroberto progname); 43754359Sroberto exit(2); 43854359Sroberto } 43954359Sroberto 44054359Sroberto if (debug || simple_query) { 44154359Sroberto#ifdef HAVE_SETVBUF 44254359Sroberto static char buf[BUFSIZ]; 44354359Sroberto setvbuf(stdout, buf, _IOLBF, BUFSIZ); 44454359Sroberto#else 44554359Sroberto setlinebuf(stdout); 44654359Sroberto#endif 44754359Sroberto } 44854359Sroberto 44954359Sroberto /* 45054359Sroberto * Logging. Open the syslog if we have to 45154359Sroberto */ 45254359Sroberto if (syslogit) { 45354359Sroberto#if !defined (SYS_WINNT) && !defined (SYS_VXWORKS) && !defined SYS_CYGWIN32 45454359Sroberto# ifndef LOG_DAEMON 45554359Sroberto openlog("ntpdate", LOG_PID); 45654359Sroberto# else 45754359Sroberto 45854359Sroberto# ifndef LOG_NTP 45954359Sroberto# define LOG_NTP LOG_DAEMON 46054359Sroberto# endif 46154359Sroberto openlog("ntpdate", LOG_PID | LOG_NDELAY, LOG_NTP); 46254359Sroberto if (debug) 46354359Sroberto setlogmask(LOG_UPTO(LOG_DEBUG)); 46454359Sroberto else 46554359Sroberto setlogmask(LOG_UPTO(LOG_INFO)); 46654359Sroberto# endif /* LOG_DAEMON */ 46754359Sroberto#endif /* SYS_WINNT */ 46854359Sroberto } 46954359Sroberto 47054359Sroberto if (debug || verbose) 47154359Sroberto msyslog(LOG_NOTICE, "%s", Version); 47254359Sroberto 47354359Sroberto /* 47454359Sroberto * Add servers we are going to be polling 47554359Sroberto */ 47654359Sroberto#ifdef HAVE_NETINFO 47782498Sroberto netinfoservers = getnetinfoservers(); 47854359Sroberto#endif 47954359Sroberto 48054359Sroberto for ( ; ntp_optind < argc; ntp_optind++) 48154359Sroberto addserver(argv[ntp_optind]); 48254359Sroberto 48354359Sroberto#ifdef HAVE_NETINFO 48454359Sroberto if (netinfoservers) { 48554359Sroberto if ( netinfoservers->ni_namelist_len && 48654359Sroberto *netinfoservers->ni_namelist_val ) { 48754359Sroberto u_int servercount = 0; 48854359Sroberto while (servercount < netinfoservers->ni_namelist_len) { 48954359Sroberto if (debug) msyslog(LOG_DEBUG, 49054359Sroberto "Adding time server %s from NetInfo configuration.", 49154359Sroberto netinfoservers->ni_namelist_val[servercount]); 49254359Sroberto addserver(netinfoservers->ni_namelist_val[servercount++]); 49354359Sroberto } 49454359Sroberto } 49554359Sroberto ni_namelist_free(netinfoservers); 49654359Sroberto free(netinfoservers); 49754359Sroberto } 49854359Sroberto#endif 49954359Sroberto 50054359Sroberto if (sys_numservers == 0) { 50154359Sroberto msyslog(LOG_ERR, "no servers can be used, exiting"); 50254359Sroberto exit(1); 50354359Sroberto } 50454359Sroberto 50554359Sroberto /* 50654359Sroberto * Initialize the time of day routines and the I/O subsystem 50754359Sroberto */ 50854359Sroberto if (sys_authenticate) { 50954359Sroberto init_auth(); 51054359Sroberto if (!authreadkeys(key_file)) { 51182498Sroberto msyslog(LOG_ERR, "no key file <%s>, exiting", key_file); 51254359Sroberto exit(1); 51354359Sroberto } 51482498Sroberto authtrust(sys_authkey, 1); 51554359Sroberto if (!authistrusted(sys_authkey)) { 516182007Sroberto msyslog(LOG_ERR, "authentication key %lu unknown", 517182007Sroberto (unsigned long) sys_authkey); 51854359Sroberto exit(1); 51954359Sroberto } 52054359Sroberto } 52154359Sroberto init_io(); 52254359Sroberto init_alarm(); 52354359Sroberto 52454359Sroberto /* 52554359Sroberto * Set the priority. 52654359Sroberto */ 52754359Sroberto#ifdef SYS_VXWORKS 52854359Sroberto taskPrioritySet( taskIdSelf(), NTPDATE_PRIO); 52954359Sroberto#endif 53054359Sroberto#if defined(HAVE_ATT_NICE) 53154359Sroberto nice (NTPDATE_PRIO); 53254359Sroberto#endif 53354359Sroberto#if defined(HAVE_BSD_NICE) 53454359Sroberto (void) setpriority(PRIO_PROCESS, 0, NTPDATE_PRIO); 53554359Sroberto#endif 53654359Sroberto 537132451Sroberto 53854359Sroberto initializing = 0; 53954359Sroberto was_alarmed = 0; 540132451Sroberto 54154359Sroberto while (complete_servers < sys_numservers) { 54254359Sroberto#ifdef HAVE_POLL_H 543182007Sroberto struct pollfd* rdfdes; 544182007Sroberto rdfdes = fdmask; 54554359Sroberto#else 54654359Sroberto fd_set rdfdes; 547182007Sroberto rdfdes = fdmask; 54854359Sroberto#endif 54954359Sroberto 55054359Sroberto if (alarm_flag) { /* alarmed? */ 55154359Sroberto was_alarmed = 1; 55254359Sroberto alarm_flag = 0; 55354359Sroberto } 554182007Sroberto tot_recvbufs = full_recvbuffs(); /* get received buffers */ 55554359Sroberto 556182007Sroberto if (!was_alarmed && tot_recvbufs == 0) { 55754359Sroberto /* 55854359Sroberto * Nothing to do. Wait for something. 55954359Sroberto */ 56054359Sroberto#ifdef HAVE_POLL_H 561182007Sroberto nfound = poll(rdfdes, (unsigned int)nbsock, timeout.tv_sec * 1000); 562132451Sroberto 56354359Sroberto#else 564293650Sglebius nfound = select(maxfd, &rdfdes, NULL, NULL, 565293650Sglebius &timeout); 56654359Sroberto#endif 56754359Sroberto if (nfound > 0) 56854359Sroberto input_handler(); 569182007Sroberto else if (nfound == SOCKET_ERROR) 570182007Sroberto { 57154359Sroberto#ifndef SYS_WINNT 572182007Sroberto if (errno != EINTR) 57354359Sroberto#else 574182007Sroberto if (WSAGetLastError() != WSAEINTR) 57554359Sroberto#endif 576285612Sdelphij msyslog(LOG_ERR, 57754359Sroberto#ifdef HAVE_POLL_H 57854359Sroberto "poll() error: %m" 57954359Sroberto#else 58054359Sroberto "select() error: %m" 58154359Sroberto#endif 58254359Sroberto ); 583182007Sroberto } else if (errno != 0) { 58454359Sroberto#ifndef SYS_VXWORKS 585285612Sdelphij msyslog(LOG_DEBUG, 58654359Sroberto#ifdef HAVE_POLL_H 58754359Sroberto "poll(): nfound = %d, error: %m", 58854359Sroberto#else 58954359Sroberto "select(): nfound = %d, error: %m", 59054359Sroberto#endif 59154359Sroberto nfound); 59254359Sroberto#endif 59354359Sroberto } 59454359Sroberto if (alarm_flag) { /* alarmed? */ 59554359Sroberto was_alarmed = 1; 59654359Sroberto alarm_flag = 0; 59754359Sroberto } 598182007Sroberto tot_recvbufs = full_recvbuffs(); /* get received buffers */ 59954359Sroberto } 60054359Sroberto 60154359Sroberto /* 60254359Sroberto * Out here, signals are unblocked. Call receive 60354359Sroberto * procedure for each incoming packet. 60454359Sroberto */ 605182007Sroberto rbuf = get_full_recv_buffer(); 606182007Sroberto while (rbuf != NULL) 607182007Sroberto { 60854359Sroberto receive(rbuf); 60954359Sroberto freerecvbuf(rbuf); 610182007Sroberto rbuf = get_full_recv_buffer(); 61154359Sroberto } 61254359Sroberto 61354359Sroberto /* 61454359Sroberto * Call timer to process any timeouts 61554359Sroberto */ 61654359Sroberto if (was_alarmed) { 61754359Sroberto timer(); 61854359Sroberto was_alarmed = 0; 61954359Sroberto } 62054359Sroberto 62154359Sroberto /* 62254359Sroberto * Go around again 62354359Sroberto */ 62454359Sroberto } 62554359Sroberto 62654359Sroberto /* 62754359Sroberto * When we get here we've completed the polling of all servers. 62854359Sroberto * Adjust the clock, then exit. 62954359Sroberto */ 63054359Sroberto#ifdef SYS_WINNT 63154359Sroberto WSACleanup(); 63254359Sroberto#endif 63354359Sroberto#ifdef SYS_VXWORKS 63454359Sroberto close (fd); 63554359Sroberto timer_delete(ntpdate_timerid); 63654359Sroberto#endif 637132451Sroberto 63854359Sroberto return clock_adjust(); 63954359Sroberto} 64054359Sroberto 64154359Sroberto 64254359Sroberto/* 64354359Sroberto * transmit - transmit a packet to the given server, or mark it completed. 644182007Sroberto * This is called by the timeout routine and by the receive 645182007Sroberto * procedure. 64654359Sroberto */ 64754359Srobertostatic void 64854359Srobertotransmit( 64954359Sroberto register struct server *server 65054359Sroberto ) 65154359Sroberto{ 65254359Sroberto struct pkt xpkt; 65354359Sroberto 65454359Sroberto if (debug) 655285612Sdelphij printf("transmit(%s)\n", stoa(&server->srcadr)); 65654359Sroberto 65754359Sroberto if (server->filter_nextpt < server->xmtcnt) { 65854359Sroberto l_fp ts; 65954359Sroberto /* 66054359Sroberto * Last message to this server timed out. Shift 66154359Sroberto * zeros into the filter. 66254359Sroberto */ 66354359Sroberto L_CLR(&ts); 66454359Sroberto server_data(server, 0, &ts, 0); 66554359Sroberto } 66654359Sroberto 66754359Sroberto if ((int)server->filter_nextpt >= sys_samples) { 66854359Sroberto /* 66954359Sroberto * Got all the data we need. Mark this guy 67054359Sroberto * completed and return. 67154359Sroberto */ 67254359Sroberto server->event_time = 0; 67354359Sroberto complete_servers++; 67454359Sroberto return; 67554359Sroberto } 67654359Sroberto 67754359Sroberto /* 678182007Sroberto * If we're here, send another message to the server. Fill in 67954359Sroberto * the packet and let 'er rip. 68054359Sroberto */ 68154359Sroberto xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC, 68254359Sroberto sys_version, MODE_CLIENT); 68354359Sroberto xpkt.stratum = STRATUM_TO_PKT(STRATUM_UNSPEC); 68454359Sroberto xpkt.ppoll = NTP_MINPOLL; 68554359Sroberto xpkt.precision = NTPDATE_PRECISION; 68654359Sroberto xpkt.rootdelay = htonl(NTPDATE_DISTANCE); 687285612Sdelphij xpkt.rootdisp = htonl(NTPDATE_DISP); 68854359Sroberto xpkt.refid = htonl(NTPDATE_REFID); 68954359Sroberto L_CLR(&xpkt.reftime); 69054359Sroberto L_CLR(&xpkt.org); 69154359Sroberto L_CLR(&xpkt.rec); 69254359Sroberto 69354359Sroberto /* 69454359Sroberto * Determine whether to authenticate or not. If so, 69554359Sroberto * fill in the extended part of the packet and do it. 69654359Sroberto * If not, just timestamp it and send it away. 69754359Sroberto */ 69854359Sroberto if (sys_authenticate) { 699293650Sglebius size_t len; 70054359Sroberto 70182498Sroberto xpkt.exten[0] = htonl(sys_authkey); 70254359Sroberto get_systime(&server->xmt); 70354359Sroberto L_ADDUF(&server->xmt, sys_authdelay); 70454359Sroberto HTONL_FP(&server->xmt, &xpkt.xmt); 70554359Sroberto len = authencrypt(sys_authkey, (u_int32 *)&xpkt, LEN_PKT_NOMAC); 706285612Sdelphij sendpkt(&server->srcadr, &xpkt, (int)(LEN_PKT_NOMAC + len)); 70754359Sroberto 70854359Sroberto if (debug > 1) 70954359Sroberto printf("transmit auth to %s\n", 710285612Sdelphij stoa(&server->srcadr)); 71154359Sroberto } else { 71254359Sroberto get_systime(&(server->xmt)); 71354359Sroberto HTONL_FP(&server->xmt, &xpkt.xmt); 714285612Sdelphij sendpkt(&server->srcadr, &xpkt, LEN_PKT_NOMAC); 71554359Sroberto 71654359Sroberto if (debug > 1) 717285612Sdelphij printf("transmit to %s\n", stoa(&server->srcadr)); 71854359Sroberto } 71954359Sroberto 72054359Sroberto /* 72154359Sroberto * Update the server timeout and transmit count 72254359Sroberto */ 72354359Sroberto server->event_time = current_time + sys_timeout; 72454359Sroberto server->xmtcnt++; 72554359Sroberto} 72654359Sroberto 72754359Sroberto 72854359Sroberto/* 72954359Sroberto * receive - receive and process an incoming frame 73054359Sroberto */ 73154359Srobertostatic void 73254359Srobertoreceive( 73354359Sroberto struct recvbuf *rbufp 73454359Sroberto ) 73554359Sroberto{ 73654359Sroberto register struct pkt *rpkt; 73754359Sroberto register struct server *server; 73854359Sroberto register s_fp di; 739106163Sroberto l_fp t10, t23, tmp; 74054359Sroberto l_fp org; 74154359Sroberto l_fp rec; 74254359Sroberto l_fp ci; 74354359Sroberto int has_mac; 74454359Sroberto int is_authentic; 74554359Sroberto 74654359Sroberto if (debug) 747182007Sroberto printf("receive(%s)\n", stoa(&rbufp->recv_srcadr)); 74854359Sroberto /* 74954359Sroberto * Check to see if the packet basically looks like something 75054359Sroberto * intended for us. 75154359Sroberto */ 75254359Sroberto if (rbufp->recv_length == LEN_PKT_NOMAC) 75354359Sroberto has_mac = 0; 754285612Sdelphij else if (rbufp->recv_length >= (int)LEN_PKT_NOMAC) 75554359Sroberto has_mac = 1; 75654359Sroberto else { 75754359Sroberto if (debug) 75854359Sroberto printf("receive: packet length %d\n", 75954359Sroberto rbufp->recv_length); 76054359Sroberto return; /* funny length packet */ 76154359Sroberto } 76254359Sroberto 76354359Sroberto rpkt = &(rbufp->recv_pkt); 76454359Sroberto if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION || 76554359Sroberto PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) { 76654359Sroberto return; 76754359Sroberto } 76854359Sroberto 76954359Sroberto if ((PKT_MODE(rpkt->li_vn_mode) != MODE_SERVER 77054359Sroberto && PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE) 77182498Sroberto || rpkt->stratum >= STRATUM_UNSPEC) { 77254359Sroberto if (debug) 77354359Sroberto printf("receive: mode %d stratum %d\n", 77454359Sroberto PKT_MODE(rpkt->li_vn_mode), rpkt->stratum); 77554359Sroberto return; 77654359Sroberto } 77754359Sroberto 77854359Sroberto /* 77954359Sroberto * So far, so good. See if this is from a server we know. 78054359Sroberto */ 78154359Sroberto server = findserver(&(rbufp->recv_srcadr)); 78254359Sroberto if (server == NULL) { 78354359Sroberto if (debug) 78454359Sroberto printf("receive: server not found\n"); 78554359Sroberto return; 78654359Sroberto } 78754359Sroberto 78854359Sroberto /* 78954359Sroberto * Decode the org timestamp and make sure we're getting a response 79054359Sroberto * to our last request. 79154359Sroberto */ 79254359Sroberto NTOHL_FP(&rpkt->org, &org); 79354359Sroberto if (!L_ISEQU(&org, &server->xmt)) { 79454359Sroberto if (debug) 79554359Sroberto printf("receive: pkt.org and peer.xmt differ\n"); 79654359Sroberto return; 79754359Sroberto } 79854359Sroberto 79954359Sroberto /* 80054359Sroberto * Check out the authenticity if we're doing that. 80154359Sroberto */ 80254359Sroberto if (!sys_authenticate) 80354359Sroberto is_authentic = 1; 80454359Sroberto else { 80554359Sroberto is_authentic = 0; 80654359Sroberto 80754359Sroberto if (debug > 3) 80854359Sroberto printf("receive: rpkt keyid=%ld sys_authkey=%ld decrypt=%ld\n", 80982498Sroberto (long int)ntohl(rpkt->exten[0]), (long int)sys_authkey, 81054359Sroberto (long int)authdecrypt(sys_authkey, (u_int32 *)rpkt, 811293650Sglebius LEN_PKT_NOMAC, (size_t)(rbufp->recv_length - LEN_PKT_NOMAC))); 81254359Sroberto 81382498Sroberto if (has_mac && ntohl(rpkt->exten[0]) == sys_authkey && 81454359Sroberto authdecrypt(sys_authkey, (u_int32 *)rpkt, LEN_PKT_NOMAC, 815293650Sglebius (size_t)(rbufp->recv_length - LEN_PKT_NOMAC))) 81654359Sroberto is_authentic = 1; 81754359Sroberto if (debug) 81854359Sroberto printf("receive: authentication %s\n", 81954359Sroberto is_authentic ? "passed" : "failed"); 82054359Sroberto } 82154359Sroberto server->trust <<= 1; 82254359Sroberto if (!is_authentic) 82354359Sroberto server->trust |= 1; 82454359Sroberto 82554359Sroberto /* 826285612Sdelphij * Check for a KoD (rate limiting) response, cease and decist. 827285612Sdelphij */ 828285612Sdelphij if (LEAP_NOTINSYNC == PKT_LEAP(rpkt->li_vn_mode) && 829285612Sdelphij STRATUM_PKT_UNSPEC == rpkt->stratum && 830285612Sdelphij !memcmp("RATE", &rpkt->refid, 4)) { 831285612Sdelphij msyslog(LOG_ERR, "%s rate limit response from server.", 832285612Sdelphij stoa(&rbufp->recv_srcadr)); 833285612Sdelphij server->event_time = 0; 834285612Sdelphij complete_servers++; 835285612Sdelphij return; 836285612Sdelphij } 837285612Sdelphij 838285612Sdelphij /* 83954359Sroberto * Looks good. Record info from the packet. 84054359Sroberto */ 84154359Sroberto server->leap = PKT_LEAP(rpkt->li_vn_mode); 84254359Sroberto server->stratum = PKT_TO_STRATUM(rpkt->stratum); 84354359Sroberto server->precision = rpkt->precision; 84454359Sroberto server->rootdelay = ntohl(rpkt->rootdelay); 845285612Sdelphij server->rootdisp = ntohl(rpkt->rootdisp); 84654359Sroberto server->refid = rpkt->refid; 84754359Sroberto NTOHL_FP(&rpkt->reftime, &server->reftime); 84854359Sroberto NTOHL_FP(&rpkt->rec, &rec); 84954359Sroberto NTOHL_FP(&rpkt->xmt, &server->org); 85054359Sroberto 85154359Sroberto /* 85254359Sroberto * Make sure the server is at least somewhat sane. If not, try 85354359Sroberto * again. 85454359Sroberto */ 85554359Sroberto if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)) { 856285612Sdelphij server->event_time = current_time + sys_timeout; 85754359Sroberto return; 85854359Sroberto } 85954359Sroberto 86054359Sroberto /* 86154359Sroberto * Calculate the round trip delay (di) and the clock offset (ci). 86254359Sroberto * We use the equations (reordered from those in the spec): 86354359Sroberto * 86454359Sroberto * d = (t2 - t3) - (t1 - t0) 86554359Sroberto * c = ((t2 - t3) + (t1 - t0)) / 2 86654359Sroberto */ 86754359Sroberto t10 = server->org; /* pkt.xmt == t1 */ 86854359Sroberto L_SUB(&t10, &rbufp->recv_time); /* recv_time == t0*/ 86954359Sroberto 87054359Sroberto t23 = rec; /* pkt.rec == t2 */ 87154359Sroberto L_SUB(&t23, &org); /* pkt->org == t3 */ 87254359Sroberto 87354359Sroberto /* now have (t2 - t3) and (t0 - t1). Calculate (ci) and (di) */ 874106163Sroberto /* 875106163Sroberto * Calculate (ci) = ((t1 - t0) / 2) + ((t2 - t3) / 2) 876106163Sroberto * For large offsets this may prevent an overflow on '+' 877106163Sroberto */ 87854359Sroberto ci = t10; 87954359Sroberto L_RSHIFT(&ci); 880106163Sroberto tmp = t23; 881106163Sroberto L_RSHIFT(&tmp); 882106163Sroberto L_ADD(&ci, &tmp); 88354359Sroberto 88454359Sroberto /* 88554359Sroberto * Calculate di in t23 in full precision, then truncate 88654359Sroberto * to an s_fp. 88754359Sroberto */ 88854359Sroberto L_SUB(&t23, &t10); 88954359Sroberto di = LFPTOFP(&t23); 89054359Sroberto 89154359Sroberto if (debug > 3) 89254359Sroberto printf("offset: %s, delay %s\n", lfptoa(&ci, 6), fptoa(di, 5)); 89354359Sroberto 89454359Sroberto di += (FP_SECOND >> (-(int)NTPDATE_PRECISION)) 89554359Sroberto + (FP_SECOND >> (-(int)server->precision)) + NTP_MAXSKW; 89654359Sroberto 89754359Sroberto if (di <= 0) { /* value still too raunchy to use? */ 89854359Sroberto L_CLR(&ci); 89954359Sroberto di = 0; 90054359Sroberto } else { 90154359Sroberto di = max(di, NTP_MINDIST); 90254359Sroberto } 90354359Sroberto 90454359Sroberto /* 905285612Sdelphij * Shift this data in, then schedule another transmit. 90654359Sroberto */ 90754359Sroberto server_data(server, (s_fp) di, &ci, 0); 908285612Sdelphij 909285612Sdelphij if ((int)server->filter_nextpt >= sys_samples) { 910285612Sdelphij /* 911285612Sdelphij * Got all the data we need. Mark this guy 912285612Sdelphij * completed and return. 913285612Sdelphij */ 914285612Sdelphij server->event_time = 0; 915285612Sdelphij complete_servers++; 916285612Sdelphij return; 917285612Sdelphij } 918285612Sdelphij 919285612Sdelphij server->event_time = current_time + sys_timeout; 92054359Sroberto} 92154359Sroberto 92254359Sroberto 92354359Sroberto/* 92454359Sroberto * server_data - add a sample to the server's filter registers 92554359Sroberto */ 92654359Srobertostatic void 92754359Srobertoserver_data( 92854359Sroberto register struct server *server, 92954359Sroberto s_fp d, 93054359Sroberto l_fp *c, 93154359Sroberto u_fp e 93254359Sroberto ) 93354359Sroberto{ 934132451Sroberto u_short i; 93554359Sroberto 93654359Sroberto i = server->filter_nextpt; 93754359Sroberto if (i < NTP_SHIFT) { 93854359Sroberto server->filter_delay[i] = d; 93954359Sroberto server->filter_offset[i] = *c; 94054359Sroberto server->filter_soffset[i] = LFPTOFP(c); 94154359Sroberto server->filter_error[i] = e; 942132451Sroberto server->filter_nextpt = (u_short)(i + 1); 94354359Sroberto } 94454359Sroberto} 94554359Sroberto 94654359Sroberto 94754359Sroberto/* 94854359Sroberto * clock_filter - determine a server's delay, dispersion and offset 94954359Sroberto */ 95054359Srobertostatic void 95154359Srobertoclock_filter( 95254359Sroberto register struct server *server 95354359Sroberto ) 95454359Sroberto{ 95554359Sroberto register int i, j; 95654359Sroberto int ord[NTP_SHIFT]; 95754359Sroberto 958316722Sdelphij INSIST((0 < sys_samples) && (sys_samples <= NTP_SHIFT)); 959316722Sdelphij 96054359Sroberto /* 96154359Sroberto * Sort indices into increasing delay order 96254359Sroberto */ 96354359Sroberto for (i = 0; i < sys_samples; i++) 96454359Sroberto ord[i] = i; 96554359Sroberto 96654359Sroberto for (i = 0; i < (sys_samples-1); i++) { 96754359Sroberto for (j = i+1; j < sys_samples; j++) { 96854359Sroberto if (server->filter_delay[ord[j]] == 0) 96954359Sroberto continue; 97054359Sroberto if (server->filter_delay[ord[i]] == 0 97154359Sroberto || (server->filter_delay[ord[i]] 97254359Sroberto > server->filter_delay[ord[j]])) { 97354359Sroberto register int tmp; 97454359Sroberto 97554359Sroberto tmp = ord[i]; 97654359Sroberto ord[i] = ord[j]; 97754359Sroberto ord[j] = tmp; 97854359Sroberto } 97954359Sroberto } 98054359Sroberto } 98154359Sroberto 98254359Sroberto /* 98354359Sroberto * Now compute the dispersion, and assign values to delay and 98454359Sroberto * offset. If there are no samples in the register, delay and 98554359Sroberto * offset go to zero and dispersion is set to the maximum. 98654359Sroberto */ 98754359Sroberto if (server->filter_delay[ord[0]] == 0) { 98854359Sroberto server->delay = 0; 98954359Sroberto L_CLR(&server->offset); 99054359Sroberto server->soffset = 0; 99154359Sroberto server->dispersion = PEER_MAXDISP; 99254359Sroberto } else { 99354359Sroberto register s_fp d; 99454359Sroberto 99554359Sroberto server->delay = server->filter_delay[ord[0]]; 99654359Sroberto server->offset = server->filter_offset[ord[0]]; 99754359Sroberto server->soffset = LFPTOFP(&server->offset); 99854359Sroberto server->dispersion = 0; 99954359Sroberto for (i = 1; i < sys_samples; i++) { 100054359Sroberto if (server->filter_delay[ord[i]] == 0) 100154359Sroberto d = PEER_MAXDISP; 100254359Sroberto else { 100354359Sroberto d = server->filter_soffset[ord[i]] 100454359Sroberto - server->filter_soffset[ord[0]]; 100554359Sroberto if (d < 0) 100654359Sroberto d = -d; 100754359Sroberto if (d > PEER_MAXDISP) 100854359Sroberto d = PEER_MAXDISP; 100954359Sroberto } 101054359Sroberto /* 101154359Sroberto * XXX This *knows* PEER_FILTER is 1/2 101254359Sroberto */ 101354359Sroberto server->dispersion += (u_fp)(d) >> i; 101454359Sroberto } 101554359Sroberto } 101654359Sroberto /* 101754359Sroberto * We're done 101854359Sroberto */ 101954359Sroberto} 102054359Sroberto 102154359Sroberto 102254359Sroberto/* 102354359Sroberto * clock_select - select the pick-of-the-litter clock from the samples 102454359Sroberto * we've got. 102554359Sroberto */ 102654359Srobertostatic struct server * 102754359Srobertoclock_select(void) 102854359Sroberto{ 1029285612Sdelphij struct server *server; 1030285612Sdelphij u_int nlist; 1031285612Sdelphij s_fp d; 1032285612Sdelphij u_int count; 1033285612Sdelphij u_int i; 1034285612Sdelphij u_int j; 1035285612Sdelphij u_int k; 1036285612Sdelphij int n; 103754359Sroberto s_fp local_threshold; 103854359Sroberto struct server *server_list[NTP_MAXCLOCK]; 103954359Sroberto u_fp server_badness[NTP_MAXCLOCK]; 104054359Sroberto struct server *sys_server; 104154359Sroberto 104254359Sroberto /* 104354359Sroberto * This first chunk of code is supposed to go through all 104454359Sroberto * servers we know about to find the NTP_MAXLIST servers which 104554359Sroberto * are most likely to succeed. We run through the list 104654359Sroberto * doing the sanity checks and trying to insert anyone who 104754359Sroberto * looks okay. We are at all times aware that we should 104854359Sroberto * only keep samples from the top two strata and we only need 104954359Sroberto * NTP_MAXLIST of them. 105054359Sroberto */ 105154359Sroberto nlist = 0; /* none yet */ 105256746Sroberto for (server = sys_servers; server != NULL; server = server->next_server) { 1053106163Sroberto if (server->delay == 0) { 1054106163Sroberto if (debug) 1055106163Sroberto printf("%s: Server dropped: no data\n", ntoa(&server->srcadr)); 1056182007Sroberto continue; /* no data */ 1057106163Sroberto } 1058106163Sroberto if (server->stratum > NTP_INFIN) { 1059106163Sroberto if (debug) 1060106163Sroberto printf("%s: Server dropped: strata too high\n", ntoa(&server->srcadr)); 1061182007Sroberto continue; /* stratum no good */ 1062106163Sroberto } 106354359Sroberto if (server->delay > NTP_MAXWGT) { 1064106163Sroberto if (debug) 1065106163Sroberto printf("%s: Server dropped: server too far away\n", 1066182007Sroberto ntoa(&server->srcadr)); 1067182007Sroberto continue; /* too far away */ 106854359Sroberto } 1069106163Sroberto if (server->leap == LEAP_NOTINSYNC) { 1070106163Sroberto if (debug) 1071106163Sroberto printf("%s: Server dropped: Leap not in sync\n", ntoa(&server->srcadr)); 1072182007Sroberto continue; /* he's in trouble */ 1073106163Sroberto } 107454359Sroberto if (!L_ISHIS(&server->org, &server->reftime)) { 1075106163Sroberto if (debug) 1076106163Sroberto printf("%s: Server dropped: server is very broken\n", 1077106163Sroberto ntoa(&server->srcadr)); 1078182007Sroberto continue; /* very broken host */ 107954359Sroberto } 108054359Sroberto if ((server->org.l_ui - server->reftime.l_ui) 1081106163Sroberto >= NTP_MAXAGE) { 1082106163Sroberto if (debug) 1083106163Sroberto printf("%s: Server dropped: Server has gone too long without sync\n", 1084106163Sroberto ntoa(&server->srcadr)); 108554359Sroberto continue; /* too long without sync */ 108654359Sroberto } 108754359Sroberto if (server->trust != 0) { 1088106163Sroberto if (debug) 1089106163Sroberto printf("%s: Server dropped: Server is untrusted\n", 1090106163Sroberto ntoa(&server->srcadr)); 109154359Sroberto continue; 109254359Sroberto } 109354359Sroberto 109454359Sroberto /* 109554359Sroberto * This one seems sane. Find where he belongs 109654359Sroberto * on the list. 109754359Sroberto */ 109854359Sroberto d = server->dispersion + server->dispersion; 109954359Sroberto for (i = 0; i < nlist; i++) 110054359Sroberto if (server->stratum <= server_list[i]->stratum) 110154359Sroberto break; 110254359Sroberto for ( ; i < nlist; i++) { 110354359Sroberto if (server->stratum < server_list[i]->stratum) 110454359Sroberto break; 110554359Sroberto if (d < (s_fp) server_badness[i]) 110654359Sroberto break; 110754359Sroberto } 110854359Sroberto 110954359Sroberto /* 111054359Sroberto * If i points past the end of the list, this 111154359Sroberto * guy is a loser, else stick him in. 111254359Sroberto */ 111354359Sroberto if (i >= NTP_MAXLIST) 111454359Sroberto continue; 111554359Sroberto for (j = nlist; j > i; j--) 111654359Sroberto if (j < NTP_MAXLIST) { 111754359Sroberto server_list[j] = server_list[j-1]; 111854359Sroberto server_badness[j] 111954359Sroberto = server_badness[j-1]; 112054359Sroberto } 112154359Sroberto 112254359Sroberto server_list[i] = server; 112354359Sroberto server_badness[i] = d; 112454359Sroberto if (nlist < NTP_MAXLIST) 112554359Sroberto nlist++; 112654359Sroberto } 112754359Sroberto 112854359Sroberto /* 112954359Sroberto * Got the five-or-less best. Cut the list where the number of 113054359Sroberto * strata exceeds two. 113154359Sroberto */ 1132285612Sdelphij count = 0; 113354359Sroberto for (i = 1; i < nlist; i++) 1134285612Sdelphij if (server_list[i]->stratum > server_list[i-1]->stratum) { 1135285612Sdelphij count++; 1136285612Sdelphij if (2 == count) { 1137285612Sdelphij nlist = i; 1138285612Sdelphij break; 1139285612Sdelphij } 114054359Sroberto } 114154359Sroberto 114254359Sroberto /* 114354359Sroberto * Whew! What we should have by now is 0 to 5 candidates for 114454359Sroberto * the job of syncing us. If we have none, we're out of luck. 114554359Sroberto * If we have one, he's a winner. If we have more, do falseticker 114654359Sroberto * detection. 114754359Sroberto */ 114854359Sroberto 1149285612Sdelphij if (0 == nlist) 1150285612Sdelphij sys_server = NULL; 1151285612Sdelphij else if (1 == nlist) { 115254359Sroberto sys_server = server_list[0]; 115354359Sroberto } else { 115454359Sroberto /* 115554359Sroberto * Re-sort by stratum, bdelay estimate quality and 115654359Sroberto * server.delay. 115754359Sroberto */ 115854359Sroberto for (i = 0; i < nlist-1; i++) 115954359Sroberto for (j = i+1; j < nlist; j++) { 1160285612Sdelphij if (server_list[i]->stratum < 1161285612Sdelphij server_list[j]->stratum) 1162285612Sdelphij /* already sorted by stratum */ 1163285612Sdelphij break; 1164285612Sdelphij if (server_list[i]->delay < 1165285612Sdelphij server_list[j]->delay) 1166285612Sdelphij continue; 116754359Sroberto server = server_list[i]; 116854359Sroberto server_list[i] = server_list[j]; 116954359Sroberto server_list[j] = server; 117054359Sroberto } 117154359Sroberto 117254359Sroberto /* 117354359Sroberto * Calculate the fixed part of the dispersion limit 117454359Sroberto */ 117554359Sroberto local_threshold = (FP_SECOND >> (-(int)NTPDATE_PRECISION)) 117654359Sroberto + NTP_MAXSKW; 117754359Sroberto 117854359Sroberto /* 117954359Sroberto * Now drop samples until we're down to one. 118054359Sroberto */ 118154359Sroberto while (nlist > 1) { 1182285612Sdelphij for (k = 0; k < nlist; k++) { 1183285612Sdelphij server_badness[k] = 0; 118454359Sroberto for (j = 0; j < nlist; j++) { 1185285612Sdelphij if (j == k) /* with self? */ 118654359Sroberto continue; 1187285612Sdelphij d = server_list[j]->soffset - 1188285612Sdelphij server_list[k]->soffset; 1189285612Sdelphij if (d < 0) /* abs value */ 119054359Sroberto d = -d; 119154359Sroberto /* 119254359Sroberto * XXX This code *knows* that 119354359Sroberto * NTP_SELECT is 3/4 119454359Sroberto */ 119554359Sroberto for (i = 0; i < j; i++) 119654359Sroberto d = (d>>1) + (d>>2); 1197285612Sdelphij server_badness[k] += d; 119854359Sroberto } 119954359Sroberto } 120054359Sroberto 120154359Sroberto /* 120254359Sroberto * We now have an array of nlist badness 120354359Sroberto * coefficients. Find the badest. Find 120454359Sroberto * the minimum precision while we're at 120554359Sroberto * it. 120654359Sroberto */ 120754359Sroberto i = 0; 120854359Sroberto n = server_list[0]->precision;; 120954359Sroberto for (j = 1; j < nlist; j++) { 121054359Sroberto if (server_badness[j] >= server_badness[i]) 121154359Sroberto i = j; 121254359Sroberto if (n > server_list[j]->precision) 121354359Sroberto n = server_list[j]->precision; 121454359Sroberto } 121554359Sroberto 121654359Sroberto /* 121754359Sroberto * i is the index of the server with the worst 121854359Sroberto * dispersion. If his dispersion is less than 121954359Sroberto * the threshold, stop now, else delete him and 122054359Sroberto * continue around again. 122154359Sroberto */ 122254359Sroberto if ( (s_fp) server_badness[i] < (local_threshold 122354359Sroberto + (FP_SECOND >> (-n)))) 122454359Sroberto break; 122554359Sroberto for (j = i + 1; j < nlist; j++) 122654359Sroberto server_list[j-1] = server_list[j]; 122754359Sroberto nlist--; 122854359Sroberto } 122954359Sroberto 123054359Sroberto /* 123154359Sroberto * What remains is a list of less than 5 servers. Take 123254359Sroberto * the best. 123354359Sroberto */ 123454359Sroberto sys_server = server_list[0]; 123554359Sroberto } 123654359Sroberto 123754359Sroberto /* 1238182007Sroberto * That's it. Return our server. 123954359Sroberto */ 124054359Sroberto return sys_server; 124154359Sroberto} 124254359Sroberto 124354359Sroberto 124454359Sroberto/* 124554359Sroberto * clock_adjust - process what we've received, and adjust the time 124654359Sroberto * if we got anything decent. 124754359Sroberto */ 124854359Srobertostatic int 124954359Srobertoclock_adjust(void) 125054359Sroberto{ 125156746Sroberto register struct server *sp, *server; 125254359Sroberto int dostep; 125354359Sroberto 125456746Sroberto for (sp = sys_servers; sp != NULL; sp = sp->next_server) 125556746Sroberto clock_filter(sp); 125654359Sroberto server = clock_select(); 125754359Sroberto 125854359Sroberto if (debug || simple_query) { 125956746Sroberto for (sp = sys_servers; sp != NULL; sp = sp->next_server) 126056746Sroberto printserver(sp, stdout); 126154359Sroberto } 126254359Sroberto 126354359Sroberto if (server == 0) { 126454359Sroberto msyslog(LOG_ERR, 126554359Sroberto "no server suitable for synchronization found"); 126654359Sroberto return(1); 126754359Sroberto } 126854359Sroberto 126954359Sroberto if (always_step) { 127054359Sroberto dostep = 1; 127154359Sroberto } else if (never_step) { 127254359Sroberto dostep = 0; 127354359Sroberto } else { 1274298770Sdelphij /* [Bug 3023] get absolute difference, avoiding signed 1275298770Sdelphij * integer overflow like hell. 1276298770Sdelphij */ 1277298770Sdelphij u_fp absoffset; 1278298770Sdelphij if (server->soffset < 0) 1279298770Sdelphij absoffset = 1u + (u_fp)(-(server->soffset + 1)); 1280298770Sdelphij else 1281298770Sdelphij absoffset = (u_fp)server->soffset; 1282298770Sdelphij dostep = (absoffset >= NTPDATE_THRESHOLD); 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 { 1292285612Sdelphij#ifndef SYS_WINNT 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 1321285612Sdelphijis_reachable (sockaddr_u *dst) 1322182007Sroberto{ 1323182007Sroberto SOCKET sockfd; 1324182007Sroberto 1325285612Sdelphij sockfd = socket(AF(dst), SOCK_DGRAM, 0); 1326182007Sroberto if (sockfd == -1) { 1327182007Sroberto return 0; 1328182007Sroberto } 1329182007Sroberto 1330285612Sdelphij if (connect(sockfd, &dst->sa, 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]; 1359285612Sdelphij sockaddr_u addr; 136054359Sroberto 1361285612Sdelphij strlcpy(service, "ntp", sizeof(service)); 1362285612Sdelphij 1363182007Sroberto /* Get host address. Looking for UDP datagram connection. */ 1364285612Sdelphij ZERO(hints); 1365182007Sroberto hints.ai_family = ai_fam_templ; 1366182007Sroberto hints.ai_socktype = SOCK_DGRAM; 1367132451Sroberto 1368138451Sroberto#ifdef DEBUG 1369182007Sroberto if (debug) 1370182007Sroberto printf("Looking for host %s and service %s\n", serv, service); 1371138451Sroberto#endif 1372132451Sroberto 1373182007Sroberto error = getaddrinfo(serv, service, &hints, &addrResult); 1374182007Sroberto if (error != 0) { 1375182007Sroberto /* Conduct more refined error analysis */ 1376182007Sroberto if (error == EAI_FAIL || error == EAI_AGAIN){ 1377182007Sroberto /* Name server is unusable. Exit after failing on the 1378182007Sroberto first server, in order to shorten the timeout caused 1379182007Sroberto by waiting for resolution of several servers */ 1380285612Sdelphij fprintf(stderr, "Exiting, name server cannot be used: %s (%d)", 1381285612Sdelphij gai_strerror(error), error); 1382285612Sdelphij msyslog(LOG_ERR, "name server cannot be used: %s (%d)", 1383285612Sdelphij gai_strerror(error), error); 1384182007Sroberto exit(1); 1385182007Sroberto } 1386285612Sdelphij fprintf(stderr, "Error resolving %s: %s (%d)\n", serv, 1387285612Sdelphij gai_strerror(error), error); 1388285612Sdelphij msyslog(LOG_ERR, "Can't find host %s: %s (%d)", serv, 1389285612Sdelphij gai_strerror(error), error); 139054359Sroberto return; 139154359Sroberto } 1392138451Sroberto#ifdef DEBUG 1393285612Sdelphij if (debug) { 1394285612Sdelphij ZERO(addr); 1395285612Sdelphij INSIST(addrResult->ai_addrlen <= sizeof(addr)); 1396285612Sdelphij memcpy(&addr, addrResult->ai_addr, addrResult->ai_addrlen); 1397285612Sdelphij fprintf(stderr, "host found : %s\n", stohost(&addr)); 1398182007Sroberto } 1399138451Sroberto#endif 140054359Sroberto 1401182007Sroberto /* We must get all returned server in case the first one fails */ 1402182007Sroberto for (ptr = addrResult; ptr != NULL; ptr = ptr->ai_next) { 1403285612Sdelphij ZERO(addr); 1404285612Sdelphij INSIST(ptr->ai_addrlen <= sizeof(addr)); 1405285612Sdelphij memcpy(&addr, ptr->ai_addr, ptr->ai_addrlen); 1406285612Sdelphij if (is_reachable(&addr)) { 1407285612Sdelphij server = emalloc_zero(sizeof(*server)); 1408285612Sdelphij memcpy(&server->srcadr, ptr->ai_addr, ptr->ai_addrlen); 1409182007Sroberto server->event_time = ++sys_numservers; 1410182007Sroberto if (sys_servers == NULL) 1411182007Sroberto sys_servers = server; 1412182007Sroberto else { 1413182007Sroberto struct server *sp; 141456746Sroberto 1415182007Sroberto for (sp = sys_servers; sp->next_server != NULL; 1416285612Sdelphij sp = sp->next_server) 1417285612Sdelphij /* empty */; 1418182007Sroberto sp->next_server = server; 1419182007Sroberto } 1420182007Sroberto } 142156746Sroberto } 1422182007Sroberto 1423182007Sroberto freeaddrinfo(addrResult); 142454359Sroberto} 142554359Sroberto 142654359Sroberto 142754359Sroberto/* 142854359Sroberto * findserver - find a server in the list given its address 1429132451Sroberto * ***(For now it isn't totally AF-Independant, to check later..) 143054359Sroberto */ 143154359Srobertostatic struct server * 143254359Srobertofindserver( 1433285612Sdelphij sockaddr_u *addr 143454359Sroberto ) 143554359Sroberto{ 143656746Sroberto struct server *server; 143756746Sroberto struct server *mc_server; 143854359Sroberto 143956746Sroberto mc_server = NULL; 1440285612Sdelphij if (SRCPORT(addr) != NTP_PORT) 144154359Sroberto return 0; 144254359Sroberto 144356746Sroberto for (server = sys_servers; server != NULL; 144456746Sroberto server = server->next_server) { 1445285612Sdelphij if (SOCK_EQ(addr, &server->srcadr)) 144656746Sroberto return server; 1447182007Sroberto 1448285612Sdelphij if (AF(addr) == AF(&server->srcadr)) { 1449285612Sdelphij if (IS_MCAST(&server->srcadr)) 1450182007Sroberto mc_server = server; 1451182007Sroberto } 145254359Sroberto } 145356746Sroberto 145456746Sroberto if (mc_server != NULL) { 1455132451Sroberto 145656746Sroberto struct server *sp; 145756746Sroberto 145856746Sroberto if (mc_server->event_time != 0) { 145956746Sroberto mc_server->event_time = 0; 146056746Sroberto complete_servers++; 146156746Sroberto } 1462132451Sroberto 1463285612Sdelphij server = emalloc_zero(sizeof(*server)); 146456746Sroberto 1465285612Sdelphij server->srcadr = *addr; 146656746Sroberto 146756746Sroberto server->event_time = ++sys_numservers; 1468132451Sroberto 146956746Sroberto for (sp = sys_servers; sp->next_server != NULL; 1470285612Sdelphij sp = sp->next_server) 1471285612Sdelphij /* empty */; 147256746Sroberto sp->next_server = server; 147356746Sroberto transmit(server); 147456746Sroberto } 147556746Sroberto return NULL; 147654359Sroberto} 147754359Sroberto 147854359Sroberto 147954359Sroberto/* 148054359Sroberto * timer - process a timer interrupt 148154359Sroberto */ 148254359Srobertovoid 148354359Srobertotimer(void) 148454359Sroberto{ 148556746Sroberto struct server *server; 148654359Sroberto 148754359Sroberto /* 148854359Sroberto * Bump the current idea of the time 148954359Sroberto */ 149054359Sroberto current_time++; 149154359Sroberto 149254359Sroberto /* 149354359Sroberto * Search through the server list looking for guys 149454359Sroberto * who's event timers have expired. Give these to 149554359Sroberto * the transmit routine. 149654359Sroberto */ 149756746Sroberto for (server = sys_servers; server != NULL; 149856746Sroberto server = server->next_server) { 149956746Sroberto if (server->event_time != 0 150056746Sroberto && server->event_time <= current_time) 150156746Sroberto transmit(server); 150254359Sroberto } 150354359Sroberto} 150454359Sroberto 150554359Sroberto 150682498Sroberto/* 150782498Sroberto * The code duplication in the following subroutine sucks, but 150882498Sroberto * we need to appease ansi2knr. 150982498Sroberto */ 151082498Sroberto 151154359Sroberto#ifndef SYS_WINNT 151254359Sroberto/* 151354359Sroberto * alarming - record the occurance of an alarm interrupt 151454359Sroberto */ 151554359Srobertostatic RETSIGTYPE 151654359Srobertoalarming( 151754359Sroberto int sig 151854359Sroberto ) 151982498Sroberto{ 152082498Sroberto alarm_flag++; 152182498Sroberto} 1522285612Sdelphij#else /* SYS_WINNT follows */ 152354359Srobertovoid CALLBACK 152454359Srobertoalarming(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) 152554359Sroberto{ 1526285612Sdelphij UNUSED_ARG(uTimerID); UNUSED_ARG(uMsg); UNUSED_ARG(dwUser); 1527285612Sdelphij UNUSED_ARG(dw1); UNUSED_ARG(dw2); 1528285612Sdelphij 152954359Sroberto alarm_flag++; 153054359Sroberto} 153154359Sroberto 1532182007Srobertostatic void 1533182007SrobertocallTimeEndPeriod(void) 1534182007Sroberto{ 1535182007Sroberto timeEndPeriod( wTimerRes ); 1536182007Sroberto wTimerRes = 0; 1537182007Sroberto} 1538182007Sroberto#endif /* SYS_WINNT */ 1539182007Sroberto 1540182007Sroberto 154154359Sroberto/* 154254359Sroberto * init_alarm - set up the timer interrupt 154354359Sroberto */ 154454359Srobertostatic void 154554359Srobertoinit_alarm(void) 154654359Sroberto{ 154754359Sroberto#ifndef SYS_WINNT 1548285612Sdelphij# ifdef HAVE_TIMER_CREATE 1549285612Sdelphij struct itimerspec its; 155054359Sroberto# else 1551285612Sdelphij struct itimerval itv; 155254359Sroberto# endif 1553285612Sdelphij#else /* SYS_WINNT follows */ 155454359Sroberto TIMECAPS tc; 1555182007Sroberto UINT wTimerID; 155654359Sroberto HANDLE hToken; 155754359Sroberto TOKEN_PRIVILEGES tkp; 155854359Sroberto DWORD dwUser = 0; 155954359Sroberto#endif /* SYS_WINNT */ 156054359Sroberto 156154359Sroberto alarm_flag = 0; 156254359Sroberto 156354359Sroberto#ifndef SYS_WINNT 1564285612Sdelphij# ifdef HAVE_TIMER_CREATE 156554359Sroberto alarm_flag = 0; 156654359Sroberto /* this code was put in as setitimer() is non existant this us the 156754359Sroberto * POSIX "equivalents" setup - casey 156854359Sroberto */ 156954359Sroberto /* ntpdate_timerid is global - so we can kill timer later */ 157054359Sroberto if (timer_create (CLOCK_REALTIME, NULL, &ntpdate_timerid) == 157154359Sroberto# ifdef SYS_VXWORKS 157254359Sroberto ERROR 157354359Sroberto# else 157454359Sroberto -1 157554359Sroberto# endif 157654359Sroberto ) 157754359Sroberto { 157854359Sroberto fprintf (stderr, "init_alarm(): timer_create (...) FAILED\n"); 157954359Sroberto return; 158054359Sroberto } 158154359Sroberto 158254359Sroberto /* TIMER_HZ = (5) 158354359Sroberto * Set up the alarm interrupt. The first comes 1/(2*TIMER_HZ) 158454359Sroberto * seconds from now and they continue on every 1/TIMER_HZ seconds. 158554359Sroberto */ 1586285612Sdelphij signal_no_reset(SIGALRM, alarming); 1587285612Sdelphij its.it_interval.tv_sec = 0; 1588285612Sdelphij its.it_value.tv_sec = 0; 1589285612Sdelphij its.it_interval.tv_nsec = 1000000000/TIMER_HZ; 1590285612Sdelphij its.it_value.tv_nsec = 1000000000/(TIMER_HZ<<1); 1591285612Sdelphij timer_settime(ntpdate_timerid, 0 /* !TIMER_ABSTIME */, &its, NULL); 1592285612Sdelphij# else /* !HAVE_TIMER_CREATE follows */ 159354359Sroberto /* 159454359Sroberto * Set up the alarm interrupt. The first comes 1/(2*TIMER_HZ) 159554359Sroberto * seconds from now and they continue on every 1/TIMER_HZ seconds. 159654359Sroberto */ 1597285612Sdelphij signal_no_reset(SIGALRM, alarming); 1598285612Sdelphij itv.it_interval.tv_sec = 0; 1599285612Sdelphij itv.it_value.tv_sec = 0; 1600285612Sdelphij itv.it_interval.tv_usec = 1000000/TIMER_HZ; 1601285612Sdelphij itv.it_value.tv_usec = 1000000/(TIMER_HZ<<1); 1602132451Sroberto 1603285612Sdelphij setitimer(ITIMER_REAL, &itv, NULL); 1604285612Sdelphij# endif /* !HAVE_TIMER_CREATE */ 1605285612Sdelphij#else /* SYS_WINNT follows */ 160654359Sroberto _tzset(); 160754359Sroberto 160854359Sroberto /* 1609182007Sroberto * Get privileges needed for fiddling with the clock 161054359Sroberto */ 161154359Sroberto 161254359Sroberto /* get the current process token handle */ 161354359Sroberto if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { 161454359Sroberto msyslog(LOG_ERR, "OpenProcessToken failed: %m"); 161554359Sroberto exit(1); 161654359Sroberto } 161754359Sroberto /* get the LUID for system-time privilege. */ 161854359Sroberto LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid); 1619182007Sroberto tkp.PrivilegeCount = 1; /* one privilege to set */ 162054359Sroberto tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 162154359Sroberto /* get set-time privilege for this process. */ 162254359Sroberto AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0); 162354359Sroberto /* cannot test return value of AdjustTokenPrivileges. */ 162454359Sroberto if (GetLastError() != ERROR_SUCCESS) 162554359Sroberto msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m"); 162654359Sroberto 162754359Sroberto /* 162854359Sroberto * Set up timer interrupts for every 2**EVENT_TIMEOUT seconds 162954359Sroberto * Under Win/NT, expiry of timer interval leads to invocation 163054359Sroberto * of a callback function (on a different thread) rather than 163154359Sroberto * generating an alarm signal 163254359Sroberto */ 163354359Sroberto 163454359Sroberto /* determine max and min resolution supported */ 163554359Sroberto if(timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) { 163654359Sroberto msyslog(LOG_ERR, "timeGetDevCaps failed: %m"); 163754359Sroberto exit(1); 163854359Sroberto } 163954359Sroberto wTimerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax); 164054359Sroberto /* establish the minimum timer resolution that we'll use */ 164154359Sroberto timeBeginPeriod(wTimerRes); 1642182007Sroberto atexit(callTimeEndPeriod); 164354359Sroberto 164454359Sroberto /* start the timer event */ 164554359Sroberto wTimerID = timeSetEvent( 1646182007Sroberto (UINT) (1000/TIMER_HZ), /* Delay */ 1647182007Sroberto wTimerRes, /* Resolution */ 1648182007Sroberto (LPTIMECALLBACK) alarming, /* Callback function */ 1649182007Sroberto (DWORD) dwUser, /* User data */ 1650182007Sroberto TIME_PERIODIC); /* Event type (periodic) */ 165154359Sroberto if (wTimerID == 0) { 165254359Sroberto msyslog(LOG_ERR, "timeSetEvent failed: %m"); 165354359Sroberto exit(1); 165454359Sroberto } 165554359Sroberto#endif /* SYS_WINNT */ 165654359Sroberto} 165754359Sroberto 165854359Sroberto 165954359Sroberto 166054359Sroberto 166154359Sroberto/* 166254359Sroberto * We do asynchronous input using the SIGIO facility. A number of 166354359Sroberto * recvbuf buffers are preallocated for input. In the signal 166454359Sroberto * handler we poll to see if the socket is ready and read the 166554359Sroberto * packets from it into the recvbuf's along with a time stamp and 166654359Sroberto * an indication of the source host and the interface it was received 166754359Sroberto * through. This allows us to get as accurate receive time stamps 166854359Sroberto * as possible independent of other processing going on. 166954359Sroberto * 167054359Sroberto * We allocate a number of recvbufs equal to the number of servers 167154359Sroberto * plus 2. This should be plenty. 167254359Sroberto */ 167354359Sroberto 167454359Sroberto 167554359Sroberto/* 167654359Sroberto * init_io - initialize I/O data and open socket 167754359Sroberto */ 167854359Srobertostatic void 167954359Srobertoinit_io(void) 168054359Sroberto{ 1681182007Sroberto struct addrinfo *res, *ressave; 1682182007Sroberto struct addrinfo hints; 1683285612Sdelphij sockaddr_u addr; 1684132451Sroberto char service[5]; 1685285612Sdelphij int rc; 1686182007Sroberto int optval = 1; 1687182007Sroberto int check_ntp_port_in_use = !debug && !simple_query && !unpriv_port; 1688132451Sroberto 168954359Sroberto /* 169054359Sroberto * Init buffer free list and stat counters 169154359Sroberto */ 169254359Sroberto init_recvbuff(sys_numservers + 2); 1693132451Sroberto 169454359Sroberto /* 169554359Sroberto * Open the socket 169654359Sroberto */ 169754359Sroberto 1698285612Sdelphij strlcpy(service, "ntp", sizeof(service)); 1699132451Sroberto 1700182007Sroberto /* 1701182007Sroberto * Init hints addrinfo structure 1702182007Sroberto */ 1703285612Sdelphij ZERO(hints); 1704182007Sroberto hints.ai_family = ai_fam_templ; 1705182007Sroberto hints.ai_flags = AI_PASSIVE; 1706182007Sroberto hints.ai_socktype = SOCK_DGRAM; 1707132451Sroberto 1708285612Sdelphij if (getaddrinfo(NULL, service, &hints, &res) != 0) { 1709285612Sdelphij msyslog(LOG_ERR, "getaddrinfo() failed: %m"); 1710285612Sdelphij exit(1); 1711285612Sdelphij /*NOTREACHED*/ 1712182007Sroberto } 1713132451Sroberto 1714182007Sroberto#ifdef SYS_WINNT 1715182007Sroberto if (check_ntp_port_in_use && ntp_port_inuse(AF_INET, NTP_PORT)){ 1716285612Sdelphij msyslog(LOG_ERR, "the NTP socket is in use, exiting: %m"); 1717182007Sroberto exit(1); 1718182007Sroberto } 1719182007Sroberto#endif 1720132451Sroberto 1721182007Sroberto /* Remember the address of the addrinfo structure chain */ 1722182007Sroberto ressave = res; 1723182007Sroberto 1724182007Sroberto /* 1725182007Sroberto * For each structure returned, open and bind socket 1726182007Sroberto */ 1727182007Sroberto for(nbsock = 0; (nbsock < MAX_AF) && res ; res = res->ai_next) { 172854359Sroberto /* create a datagram (UDP) socket */ 1729182007Sroberto fd[nbsock] = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 1730182007Sroberto if (fd[nbsock] == SOCKET_ERROR) { 1731182007Sroberto#ifndef SYS_WINNT 1732132451Sroberto if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT || 1733132451Sroberto errno == EPFNOSUPPORT) 1734182007Sroberto#else 1735182007Sroberto int err = WSAGetLastError(); 1736182007Sroberto if (err == WSAEPROTONOSUPPORT || err == WSAEAFNOSUPPORT || 1737182007Sroberto err == WSAEPFNOSUPPORT) 1738182007Sroberto#endif 1739132451Sroberto continue; 1740285612Sdelphij msyslog(LOG_ERR, "socket() failed: %m"); 174154359Sroberto exit(1); 174254359Sroberto /*NOTREACHED*/ 1743182007Sroberto } 1744182007Sroberto /* set socket to reuse address */ 1745182007Sroberto if (setsockopt(fd[nbsock], SOL_SOCKET, SO_REUSEADDR, (void*) &optval, sizeof(optval)) < 0) { 1746285612Sdelphij msyslog(LOG_ERR, "setsockopt() SO_REUSEADDR failed: %m"); 1747182007Sroberto exit(1); 1748182007Sroberto /*NOTREACHED*/ 1749182007Sroberto } 1750132451Sroberto#ifdef IPV6_V6ONLY 1751182007Sroberto /* Restricts AF_INET6 socket to IPv6 communications (see RFC 2553bis-03) */ 1752182007Sroberto if (res->ai_family == AF_INET6) 1753182007Sroberto if (setsockopt(fd[nbsock], IPPROTO_IPV6, IPV6_V6ONLY, (void*) &optval, sizeof(optval)) < 0) { 1754285612Sdelphij msyslog(LOG_ERR, "setsockopt() IPV6_V6ONLY failed: %m"); 1755182007Sroberto exit(1); 1756182007Sroberto /*NOTREACHED*/ 1757182007Sroberto } 1758132451Sroberto#endif 175954359Sroberto 1760182007Sroberto /* Remember the socket family in fd_family structure */ 1761182007Sroberto fd_family[nbsock] = res->ai_family; 1762132451Sroberto 1763182007Sroberto /* 1764182007Sroberto * bind the socket to the NTP port 1765182007Sroberto */ 1766182007Sroberto if (check_ntp_port_in_use) { 1767285612Sdelphij ZERO(addr); 1768285612Sdelphij INSIST(res->ai_addrlen <= sizeof(addr)); 1769285612Sdelphij memcpy(&addr, res->ai_addr, res->ai_addrlen); 1770285612Sdelphij rc = bind(fd[nbsock], &addr.sa, SOCKLEN(&addr)); 1771285612Sdelphij if (rc < 0) { 1772285612Sdelphij if (EADDRINUSE == socket_errno()) 1773285612Sdelphij msyslog(LOG_ERR, "the NTP socket is in use, exiting"); 177454359Sroberto else 1775285612Sdelphij msyslog(LOG_ERR, "bind() fails: %m"); 1776182007Sroberto exit(1); 1777182007Sroberto } 177854359Sroberto } 177954359Sroberto 178054359Sroberto#ifdef HAVE_POLL_H 1781182007Sroberto fdmask[nbsock].fd = fd[nbsock]; 1782182007Sroberto fdmask[nbsock].events = POLLIN; 178354359Sroberto#else 1784182007Sroberto FD_SET(fd[nbsock], &fdmask); 1785182007Sroberto if (maxfd < fd[nbsock]+1) { 1786182007Sroberto maxfd = fd[nbsock]+1; 1787182007Sroberto } 178854359Sroberto#endif 178954359Sroberto 1790182007Sroberto /* 1791182007Sroberto * set non-blocking, 1792182007Sroberto */ 179354359Sroberto#ifndef SYS_WINNT 179454359Sroberto# ifdef SYS_VXWORKS 1795182007Sroberto { 1796285612Sdelphij int on = TRUE; 179754359Sroberto 1798285612Sdelphij if (ioctl(fd[nbsock],FIONBIO, &on) == ERROR) { 1799285612Sdelphij msyslog(LOG_ERR, "ioctl(FIONBIO) fails: %m"); 1800285612Sdelphij exit(1); 1801285612Sdelphij } 1802182007Sroberto } 180354359Sroberto# else /* not SYS_VXWORKS */ 180454359Sroberto# if defined(O_NONBLOCK) 1805182007Sroberto if (fcntl(fd[nbsock], F_SETFL, O_NONBLOCK) < 0) { 1806285612Sdelphij msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m"); 1807182007Sroberto exit(1); 1808182007Sroberto /*NOTREACHED*/ 1809182007Sroberto } 181054359Sroberto# else /* not O_NONBLOCK */ 181154359Sroberto# if defined(FNDELAY) 1812182007Sroberto if (fcntl(fd[nbsock], F_SETFL, FNDELAY) < 0) { 1813285612Sdelphij msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m"); 1814182007Sroberto exit(1); 1815182007Sroberto /*NOTREACHED*/ 1816182007Sroberto } 181754359Sroberto# else /* FNDELAY */ 181854359Sroberto# include "Bletch: Need non blocking I/O" 181954359Sroberto# endif /* FNDELAY */ 182054359Sroberto# endif /* not O_NONBLOCK */ 182154359Sroberto# endif /* SYS_VXWORKS */ 182254359Sroberto#else /* SYS_WINNT */ 1823182007Sroberto if (ioctlsocket(fd[nbsock], FIONBIO, (u_long *) &on) == SOCKET_ERROR) { 1824285612Sdelphij msyslog(LOG_ERR, "ioctlsocket(FIONBIO) fails: %m"); 1825182007Sroberto exit(1); 1826182007Sroberto } 1827182007Sroberto#endif /* SYS_WINNT */ 1828182007Sroberto nbsock++; 182954359Sroberto } 1830182007Sroberto freeaddrinfo(ressave); 183154359Sroberto} 183254359Sroberto 183354359Sroberto/* 183454359Sroberto * sendpkt - send a packet to the specified destination 183554359Sroberto */ 183654359Srobertostatic void 183754359Srobertosendpkt( 1838285612Sdelphij sockaddr_u *dest, 183954359Sroberto struct pkt *pkt, 184054359Sroberto int len 184154359Sroberto ) 184254359Sroberto{ 1843182007Sroberto int i; 184454359Sroberto int cc; 1845182007Sroberto SOCKET sock = INVALID_SOCKET; 184654359Sroberto 184754359Sroberto#ifdef SYS_WINNT 184854359Sroberto DWORD err; 184954359Sroberto#endif /* SYS_WINNT */ 185054359Sroberto 1851182007Sroberto /* Find a local family compatible socket to send ntp packet to ntp server */ 1852182007Sroberto for(i = 0; (i < MAX_AF); i++) { 1853285612Sdelphij if(AF(dest) == fd_family[i]) { 1854182007Sroberto sock = fd[i]; 1855182007Sroberto break; 1856182007Sroberto } 1857182007Sroberto } 1858132451Sroberto 1859285612Sdelphij if (INVALID_SOCKET == sock) { 1860285612Sdelphij msyslog(LOG_ERR, "cannot find family compatible socket to send ntp packet"); 1861182007Sroberto exit(1); 1862182007Sroberto /*NOTREACHED*/ 1863182007Sroberto } 1864132451Sroberto 1865132451Sroberto cc = sendto(sock, (char *)pkt, len, 0, (struct sockaddr *)dest, 1866132451Sroberto SOCKLEN(dest)); 1867132451Sroberto 1868285612Sdelphij if (SOCKET_ERROR == cc) { 186954359Sroberto#ifndef SYS_WINNT 187054359Sroberto if (errno != EWOULDBLOCK && errno != ENOBUFS) 187154359Sroberto#else 187254359Sroberto err = WSAGetLastError(); 187354359Sroberto if (err != WSAEWOULDBLOCK && err != WSAENOBUFS) 187454359Sroberto#endif /* SYS_WINNT */ 1875285612Sdelphij msyslog(LOG_ERR, "sendto(%s): %m", stohost(dest)); 187654359Sroberto } 187754359Sroberto} 187854359Sroberto 187954359Sroberto 188054359Sroberto/* 188154359Sroberto * input_handler - receive packets asynchronously 188254359Sroberto */ 188354359Srobertovoid 188454359Srobertoinput_handler(void) 188554359Sroberto{ 188654359Sroberto register int n; 188754359Sroberto register struct recvbuf *rb; 1888285612Sdelphij struct sock_timeval tvzero; 1889285612Sdelphij GETSOCKNAME_SOCKLEN_TYPE fromlen; 189054359Sroberto l_fp ts; 1891182007Sroberto int i; 189254359Sroberto#ifdef HAVE_POLL_H 1893132451Sroberto struct pollfd fds[MAX_AF]; 189454359Sroberto#else 189554359Sroberto fd_set fds; 189654359Sroberto#endif 1897293650Sglebius SOCKET fdc = 0; 189854359Sroberto 189954359Sroberto /* 190054359Sroberto * Do a poll to see if we have data 190154359Sroberto */ 190254359Sroberto for (;;) { 190354359Sroberto tvzero.tv_sec = tvzero.tv_usec = 0; 190454359Sroberto#ifdef HAVE_POLL_H 1905132451Sroberto memcpy(fds, fdmask, sizeof(fdmask)); 1906182007Sroberto n = poll(fds, (unsigned int)nbsock, tvzero.tv_sec * 1000); 1907132451Sroberto 1908182007Sroberto /* 1909182007Sroberto * Determine which socket received data 1910182007Sroberto */ 1911132451Sroberto 1912182007Sroberto for(i=0; i < nbsock; i++) { 1913182007Sroberto if(fds[i].revents & POLLIN) { 1914182007Sroberto fdc = fd[i]; 1915182007Sroberto break; 1916182007Sroberto } 1917182007Sroberto } 1918132451Sroberto 191954359Sroberto#else 1920132451Sroberto fds = fdmask; 1921293650Sglebius n = select(maxfd, &fds, NULL, NULL, &tvzero); 1922132451Sroberto 1923182007Sroberto /* 1924182007Sroberto * Determine which socket received data 1925182007Sroberto */ 1926132451Sroberto 1927182007Sroberto for(i=0; i < nbsock; i++) { 1928182007Sroberto if(FD_ISSET(fd[i], &fds)) { 1929182007Sroberto fdc = fd[i]; 1930182007Sroberto break; 1931182007Sroberto } 1932182007Sroberto } 1933132451Sroberto 193454359Sroberto#endif 193554359Sroberto 193654359Sroberto /* 193754359Sroberto * If nothing to do, just return. If an error occurred, 193854359Sroberto * complain and return. If we've got some, freeze a 193954359Sroberto * timestamp. 194054359Sroberto */ 194154359Sroberto if (n == 0) 194254359Sroberto return; 194354359Sroberto else if (n == -1) { 194454359Sroberto if (errno != EINTR) 1945285612Sdelphij msyslog(LOG_ERR, 194654359Sroberto#ifdef HAVE_POLL_H 194754359Sroberto "poll() error: %m" 194854359Sroberto#else 194954359Sroberto "select() error: %m" 195054359Sroberto#endif 195154359Sroberto ); 195254359Sroberto return; 195354359Sroberto } 195454359Sroberto get_systime(&ts); 195554359Sroberto 195654359Sroberto /* 195754359Sroberto * Get a buffer and read the frame. If we 195854359Sroberto * haven't got a buffer, or this is received 195954359Sroberto * on the wild card socket, just dump the packet. 196054359Sroberto */ 196154359Sroberto if (initializing || free_recvbuffs() == 0) { 196254359Sroberto char buf[100]; 196354359Sroberto 1964132451Sroberto 196554359Sroberto#ifndef SYS_WINNT 1966132451Sroberto (void) read(fdc, buf, sizeof buf); 196754359Sroberto#else 196854359Sroberto /* NT's _read does not operate on nonblocking sockets 196954359Sroberto * either recvfrom or ReadFile() has to be used here. 197054359Sroberto * ReadFile is used in [ntpd]ntp_intres() and ntpdc, 197154359Sroberto * just to be different use recvfrom() here 197254359Sroberto */ 1973132451Sroberto recvfrom(fdc, buf, sizeof(buf), 0, (struct sockaddr *)0, NULL); 197454359Sroberto#endif /* SYS_WINNT */ 197554359Sroberto continue; 197654359Sroberto } 197754359Sroberto 197854359Sroberto rb = get_free_recv_buffer(); 197954359Sroberto 1980285612Sdelphij fromlen = sizeof(rb->recv_srcadr); 1981132451Sroberto rb->recv_length = recvfrom(fdc, (char *)&rb->recv_pkt, 198254359Sroberto sizeof(rb->recv_pkt), 0, 198354359Sroberto (struct sockaddr *)&rb->recv_srcadr, &fromlen); 198454359Sroberto if (rb->recv_length == -1) { 198554359Sroberto freerecvbuf(rb); 198654359Sroberto continue; 198754359Sroberto } 198854359Sroberto 198954359Sroberto /* 199054359Sroberto * Got one. Mark how and when it got here, 199154359Sroberto * put it on the full list. 199254359Sroberto */ 199354359Sroberto rb->recv_time = ts; 199454359Sroberto add_full_recv_buffer(rb); 199554359Sroberto } 199654359Sroberto} 199754359Sroberto 199854359Sroberto 199954359Sroberto#if !defined SYS_WINNT && !defined SYS_CYGWIN32 200054359Sroberto/* 200154359Sroberto * adj_systime - do a big long slew of the system time 200254359Sroberto */ 200354359Srobertostatic int 200454359Srobertol_adj_systime( 200554359Sroberto l_fp *ts 200654359Sroberto ) 200754359Sroberto{ 200854359Sroberto struct timeval adjtv, oadjtv; 200954359Sroberto int isneg = 0; 201054359Sroberto l_fp offset; 201154359Sroberto#ifndef STEP_SLEW 201254359Sroberto l_fp overshoot; 201354359Sroberto#endif 201454359Sroberto 201554359Sroberto /* 201654359Sroberto * Take the absolute value of the offset 201754359Sroberto */ 201854359Sroberto offset = *ts; 201954359Sroberto if (L_ISNEG(&offset)) { 202054359Sroberto isneg = 1; 202154359Sroberto L_NEG(&offset); 202254359Sroberto } 202354359Sroberto 202454359Sroberto#ifndef STEP_SLEW 202554359Sroberto /* 202654359Sroberto * Calculate the overshoot. XXX N.B. This code *knows* 202754359Sroberto * ADJ_OVERSHOOT is 1/2. 202854359Sroberto */ 202954359Sroberto overshoot = offset; 203054359Sroberto L_RSHIFTU(&overshoot); 203154359Sroberto if (overshoot.l_ui != 0 || (overshoot.l_uf > ADJ_MAXOVERSHOOT)) { 203254359Sroberto overshoot.l_ui = 0; 203354359Sroberto overshoot.l_uf = ADJ_MAXOVERSHOOT; 203454359Sroberto } 203554359Sroberto L_ADD(&offset, &overshoot); 203654359Sroberto#endif 203754359Sroberto TSTOTV(&offset, &adjtv); 203854359Sroberto 203954359Sroberto if (isneg) { 204054359Sroberto adjtv.tv_sec = -adjtv.tv_sec; 204154359Sroberto adjtv.tv_usec = -adjtv.tv_usec; 204254359Sroberto } 204354359Sroberto 204454359Sroberto if (adjtv.tv_usec != 0 && !debug) { 204554359Sroberto if (adjtime(&adjtv, &oadjtv) < 0) { 204654359Sroberto msyslog(LOG_ERR, "Can't adjust the time of day: %m"); 2047285612Sdelphij exit(1); 204854359Sroberto } 204954359Sroberto } 205054359Sroberto return 1; 205154359Sroberto} 205254359Sroberto#endif /* SYS_WINNT */ 205354359Sroberto 205454359Sroberto 205554359Sroberto/* 205654359Sroberto * This fuction is not the same as lib/systime step_systime!!! 205754359Sroberto */ 205854359Srobertostatic int 205954359Srobertol_step_systime( 206054359Sroberto l_fp *ts 206154359Sroberto ) 206254359Sroberto{ 206354359Sroberto double dtemp; 206454359Sroberto 206554359Sroberto#ifdef SLEWALWAYS 206654359Sroberto#ifdef STEP_SLEW 206754359Sroberto l_fp ftmp; 206854359Sroberto int isneg; 206954359Sroberto int n; 207054359Sroberto 207154359Sroberto if (debug) return 1; 207254359Sroberto /* 207354359Sroberto * Take the absolute value of the offset 207454359Sroberto */ 207554359Sroberto ftmp = *ts; 207654359Sroberto if (L_ISNEG(&ftmp)) { 207754359Sroberto L_NEG(&ftmp); 207854359Sroberto isneg = 1; 207954359Sroberto } else 208054359Sroberto isneg = 0; 208154359Sroberto 208254359Sroberto if (ftmp.l_ui >= 3) { /* Step it and slew - we might win */ 208356746Sroberto LFPTOD(ts, dtemp); 208456746Sroberto n = step_systime(dtemp); 208554359Sroberto if (!n) 208654359Sroberto return n; 208754359Sroberto if (isneg) 208854359Sroberto ts->l_ui = ~0; 208954359Sroberto else 209054359Sroberto ts->l_ui = ~0; 209154359Sroberto } 209254359Sroberto /* 209354359Sroberto * Just add adjustment into the current offset. The update 209454359Sroberto * routine will take care of bringing the system clock into 209554359Sroberto * line. 209654359Sroberto */ 209754359Sroberto#endif 209854359Sroberto if (debug) 209954359Sroberto return 1; 210054359Sroberto#ifdef FORCE_NTPDATE_STEP 210154359Sroberto LFPTOD(ts, dtemp); 210254359Sroberto return step_systime(dtemp); 210354359Sroberto#else 210454359Sroberto l_adj_systime(ts); 210554359Sroberto return 1; 210654359Sroberto#endif 2107182007Sroberto#else /* SLEWALWAYS */ 210854359Sroberto if (debug) 210954359Sroberto return 1; 211054359Sroberto LFPTOD(ts, dtemp); 211154359Sroberto return step_systime(dtemp); 211254359Sroberto#endif /* SLEWALWAYS */ 211354359Sroberto} 211454359Sroberto 211554359Sroberto 211654359Sroberto/* XXX ELIMINATE printserver similar in ntptrace.c, ntpdate.c */ 211754359Sroberto/* 211854359Sroberto * printserver - print detail information for a server 211954359Sroberto */ 212054359Srobertostatic void 212154359Srobertoprintserver( 212254359Sroberto register struct server *pp, 212354359Sroberto FILE *fp 212454359Sroberto ) 212554359Sroberto{ 212654359Sroberto register int i; 212754359Sroberto char junk[5]; 2128285612Sdelphij const char *str; 212954359Sroberto 213054359Sroberto if (!debug) { 213154359Sroberto (void) fprintf(fp, "server %s, stratum %d, offset %s, delay %s\n", 2132132451Sroberto stoa(&pp->srcadr), pp->stratum, 213354359Sroberto lfptoa(&pp->offset, 6), fptoa((s_fp)pp->delay, 5)); 213454359Sroberto return; 213554359Sroberto } 213654359Sroberto 213754359Sroberto (void) fprintf(fp, "server %s, port %d\n", 2138132451Sroberto stoa(&pp->srcadr), ntohs(((struct sockaddr_in*)&(pp->srcadr))->sin_port)); 213954359Sroberto 214054359Sroberto (void) fprintf(fp, "stratum %d, precision %d, leap %c%c, trust %03o\n", 214154359Sroberto pp->stratum, pp->precision, 214254359Sroberto pp->leap & 0x2 ? '1' : '0', 214354359Sroberto pp->leap & 0x1 ? '1' : '0', 214454359Sroberto pp->trust); 214554359Sroberto 214654359Sroberto if (pp->stratum == 1) { 214754359Sroberto junk[4] = 0; 214854359Sroberto memmove(junk, (char *)&pp->refid, 4); 214954359Sroberto str = junk; 215054359Sroberto } else { 2151132451Sroberto str = stoa(&pp->srcadr); 215254359Sroberto } 215354359Sroberto (void) fprintf(fp, 215454359Sroberto "refid [%s], delay %s, dispersion %s\n", 215554359Sroberto str, fptoa((s_fp)pp->delay, 5), 215654359Sroberto ufptoa(pp->dispersion, 5)); 215754359Sroberto 215854359Sroberto (void) fprintf(fp, "transmitted %d, in filter %d\n", 215954359Sroberto pp->xmtcnt, pp->filter_nextpt); 216054359Sroberto 216154359Sroberto (void) fprintf(fp, "reference time: %s\n", 216254359Sroberto prettydate(&pp->reftime)); 216354359Sroberto (void) fprintf(fp, "originate timestamp: %s\n", 216454359Sroberto prettydate(&pp->org)); 216554359Sroberto (void) fprintf(fp, "transmit timestamp: %s\n", 216654359Sroberto prettydate(&pp->xmt)); 216754359Sroberto 216854359Sroberto (void) fprintf(fp, "filter delay: "); 216954359Sroberto for (i = 0; i < NTP_SHIFT; i++) { 217054359Sroberto (void) fprintf(fp, " %-8.8s", fptoa(pp->filter_delay[i], 5)); 217154359Sroberto if (i == (NTP_SHIFT>>1)-1) 217254359Sroberto (void) fprintf(fp, "\n "); 217354359Sroberto } 217454359Sroberto (void) fprintf(fp, "\n"); 217554359Sroberto 217654359Sroberto (void) fprintf(fp, "filter offset:"); 217754359Sroberto for (i = 0; i < PEER_SHIFT; i++) { 217854359Sroberto (void) fprintf(fp, " %-8.8s", lfptoa(&pp->filter_offset[i], 6)); 217954359Sroberto if (i == (PEER_SHIFT>>1)-1) 218054359Sroberto (void) fprintf(fp, "\n "); 218154359Sroberto } 218254359Sroberto (void) fprintf(fp, "\n"); 218354359Sroberto 218454359Sroberto (void) fprintf(fp, "delay %s, dispersion %s\n", 218554359Sroberto fptoa((s_fp)pp->delay, 5), ufptoa(pp->dispersion, 5)); 218654359Sroberto 218754359Sroberto (void) fprintf(fp, "offset %s\n\n", 218854359Sroberto lfptoa(&pp->offset, 6)); 218954359Sroberto} 219054359Sroberto 219154359Sroberto 219254359Sroberto#ifdef HAVE_NETINFO 219354359Srobertostatic ni_namelist * 219454359Srobertogetnetinfoservers(void) 219554359Sroberto{ 219654359Sroberto ni_status status; 219754359Sroberto void *domain; 219854359Sroberto ni_id confdir; 2199285612Sdelphij ni_namelist *namelist = emalloc(sizeof(ni_namelist)); 220054359Sroberto 220154359Sroberto /* Find a time server in NetInfo */ 220254359Sroberto if ((status = ni_open(NULL, ".", &domain)) != NI_OK) return NULL; 220354359Sroberto 220454359Sroberto while (status = ni_pathsearch(domain, &confdir, NETINFO_CONFIG_DIR) == NI_NODIR) { 220554359Sroberto void *next_domain; 220654359Sroberto if (ni_open(domain, "..", &next_domain) != NI_OK) break; 220754359Sroberto ni_free(domain); 220854359Sroberto domain = next_domain; 220954359Sroberto } 221054359Sroberto if (status != NI_OK) return NULL; 221154359Sroberto 221254359Sroberto NI_INIT(namelist); 221354359Sroberto if (ni_lookupprop(domain, &confdir, "server", namelist) != NI_OK) { 221454359Sroberto ni_namelist_free(namelist); 221554359Sroberto free(namelist); 221654359Sroberto return NULL; 221754359Sroberto } 221854359Sroberto 221954359Sroberto return(namelist); 222054359Sroberto} 222154359Sroberto#endif 2222182007Sroberto 2223182007Sroberto#ifdef SYS_WINNT 2224182007Srobertoisc_boolean_t ntp_port_inuse(int af, u_short port) 2225182007Sroberto{ 2226182007Sroberto /* 2227182007Sroberto * Check if NTP socket is already in use on this system 2228182007Sroberto * This is only for Windows Systems, as they tend not to fail on the real bind() below 2229182007Sroberto */ 2230182007Sroberto 2231182007Sroberto SOCKET checksocket; 2232182007Sroberto struct sockaddr_in checkservice; 2233182007Sroberto checksocket = socket(af, SOCK_DGRAM, 0); 2234182007Sroberto if (checksocket == INVALID_SOCKET) { 2235182007Sroberto return (ISC_TRUE); 2236182007Sroberto } 2237182007Sroberto 2238182007Sroberto checkservice.sin_family = (short) AF_INET; 2239182007Sroberto checkservice.sin_addr.s_addr = INADDR_LOOPBACK; 2240182007Sroberto checkservice.sin_port = htons(port); 2241182007Sroberto 2242182007Sroberto if (bind(checksocket, (struct sockaddr *)&checkservice, 2243182007Sroberto sizeof(checkservice)) == SOCKET_ERROR) { 2244182007Sroberto if ( WSAGetLastError() == WSAEADDRINUSE ){ 2245182007Sroberto closesocket(checksocket); 2246182007Sroberto return (ISC_TRUE); 2247182007Sroberto } 2248182007Sroberto } 2249182007Sroberto closesocket(checksocket); 2250182007Sroberto return (ISC_FALSE); 2251182007Sroberto} 2252182007Sroberto#endif 2253