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" 17290001Sglebius#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" 23290001Sglebius#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 39290001Sglebius#ifdef HAVE_SYS_SIGNAL_H 40290001Sglebius# include <sys/signal.h> 41290001Sglebius#endif 42290001Sglebius#ifdef HAVE_SYS_IOCTL_H 43290001Sglebius# include <sys/ioctl.h> 44290001Sglebius#endif 4554359Sroberto#ifdef HAVE_SYS_RESOURCE_H 4654359Sroberto# include <sys/resource.h> 47290001Sglebius#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 61290001Sglebius * so a 200 ms timeout is needed (TIMER_HZ is 5). 62182007Sroberto */ 63290001Sglebiusstruct 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 91290001Sglebius#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; 117290001Sglebiusint nbsock; /* the number of sockets used */ 118182007SrobertoSOCKET fd[MAX_AF]; 119290001Sglebiusint 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 */ 152290001Sglebiuschar 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 201290001Sglebiusint ntpdatemain (int, char **); 202132451Sroberto 203290001Sglebiusstatic void transmit (struct server *); 204290001Sglebiusstatic void receive (struct recvbuf *); 205290001Sglebiusstatic void server_data (struct server *, s_fp, l_fp *, u_fp); 206290001Sglebiusstatic void clock_filter (struct server *); 207290001Sglebiusstatic struct server *clock_select (void); 208290001Sglebiusstatic int clock_adjust (void); 209290001Sglebiusstatic void addserver (char *); 210290001Sglebiusstatic struct server *findserver (sockaddr_u *); 211290001Sglebius void timer (void); 212290001Sglebiusstatic void init_alarm (void); 21354359Sroberto#ifndef SYS_WINNT 214290001Sglebiusstatic RETSIGTYPE alarming (int); 21554359Sroberto#endif /* SYS_WINNT */ 216290001Sglebiusstatic void init_io (void); 217290001Sglebiusstatic void sendpkt (sockaddr_u *, struct pkt *, int); 218290001Sglebiusvoid input_handler (void); 21954359Sroberto 220290001Sglebiusstatic int l_adj_systime (l_fp *); 221290001Sglebiusstatic int l_step_systime (l_fp *); 22254359Sroberto 223290001Sglebiusstatic 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 288290001Sglebiusstatic 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)) 327290001Sglebius msyslog(LOG_ERR, "ExpandEnvironmentStrings(KEYFILE) failed: %m"); 328290001Sglebius 329290001Sglebius ssl_applink(); 33054359Sroberto#endif /* SYS_WINNT */ 33154359Sroberto 33254359Sroberto#ifdef NO_MAIN_ALLOWED 33354359Sroberto clear_globals(); 33454359Sroberto#endif 33554359Sroberto 336290001Sglebius init_lib(); /* sets up ipv4_works, ipv6_works */ 337182007Sroberto 338290001Sglebius /* Check to see if we have IPv6. Otherwise default to IPv4 */ 339290001Sglebius 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; 417290001Sglebius 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 564293896Sglebius nfound = select(maxfd, &rdfdes, NULL, NULL, 565293896Sglebius &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 576290001Sglebius 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 585290001Sglebius 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) 655290001Sglebius 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); 687290001Sglebius 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) { 699293896Sglebius 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); 706290001Sglebius sendpkt(&server->srcadr, &xpkt, (int)(LEN_PKT_NOMAC + len)); 70754359Sroberto 70854359Sroberto if (debug > 1) 70954359Sroberto printf("transmit auth to %s\n", 710290001Sglebius stoa(&server->srcadr)); 71154359Sroberto } else { 71254359Sroberto get_systime(&(server->xmt)); 71354359Sroberto HTONL_FP(&server->xmt, &xpkt.xmt); 714290001Sglebius sendpkt(&server->srcadr, &xpkt, LEN_PKT_NOMAC); 71554359Sroberto 71654359Sroberto if (debug > 1) 717290001Sglebius 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; 754290001Sglebius 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, 811293896Sglebius 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, 815293896Sglebius (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 /* 826290001Sglebius * Check for a KoD (rate limiting) response, cease and decist. 827290001Sglebius */ 828290001Sglebius if (LEAP_NOTINSYNC == PKT_LEAP(rpkt->li_vn_mode) && 829290001Sglebius STRATUM_PKT_UNSPEC == rpkt->stratum && 830290001Sglebius !memcmp("RATE", &rpkt->refid, 4)) { 831290001Sglebius msyslog(LOG_ERR, "%s rate limit response from server.", 832290001Sglebius stoa(&rbufp->recv_srcadr)); 833290001Sglebius server->event_time = 0; 834290001Sglebius complete_servers++; 835290001Sglebius return; 836290001Sglebius } 837290001Sglebius 838290001Sglebius /* 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); 845290001Sglebius 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)) { 856290001Sglebius 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 /* 905290001Sglebius * Shift this data in, then schedule another transmit. 90654359Sroberto */ 90754359Sroberto server_data(server, (s_fp) di, &ci, 0); 908290001Sglebius 909290001Sglebius if ((int)server->filter_nextpt >= sys_samples) { 910290001Sglebius /* 911290001Sglebius * Got all the data we need. Mark this guy 912290001Sglebius * completed and return. 913290001Sglebius */ 914290001Sglebius server->event_time = 0; 915290001Sglebius complete_servers++; 916290001Sglebius return; 917290001Sglebius } 918290001Sglebius 919290001Sglebius 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 95854359Sroberto /* 95954359Sroberto * Sort indices into increasing delay order 96054359Sroberto */ 96154359Sroberto for (i = 0; i < sys_samples; i++) 96254359Sroberto ord[i] = i; 96354359Sroberto 96454359Sroberto for (i = 0; i < (sys_samples-1); i++) { 96554359Sroberto for (j = i+1; j < sys_samples; j++) { 96654359Sroberto if (server->filter_delay[ord[j]] == 0) 96754359Sroberto continue; 96854359Sroberto if (server->filter_delay[ord[i]] == 0 96954359Sroberto || (server->filter_delay[ord[i]] 97054359Sroberto > server->filter_delay[ord[j]])) { 97154359Sroberto register int tmp; 97254359Sroberto 97354359Sroberto tmp = ord[i]; 97454359Sroberto ord[i] = ord[j]; 97554359Sroberto ord[j] = tmp; 97654359Sroberto } 97754359Sroberto } 97854359Sroberto } 97954359Sroberto 98054359Sroberto /* 98154359Sroberto * Now compute the dispersion, and assign values to delay and 98254359Sroberto * offset. If there are no samples in the register, delay and 98354359Sroberto * offset go to zero and dispersion is set to the maximum. 98454359Sroberto */ 98554359Sroberto if (server->filter_delay[ord[0]] == 0) { 98654359Sroberto server->delay = 0; 98754359Sroberto L_CLR(&server->offset); 98854359Sroberto server->soffset = 0; 98954359Sroberto server->dispersion = PEER_MAXDISP; 99054359Sroberto } else { 99154359Sroberto register s_fp d; 99254359Sroberto 99354359Sroberto server->delay = server->filter_delay[ord[0]]; 99454359Sroberto server->offset = server->filter_offset[ord[0]]; 99554359Sroberto server->soffset = LFPTOFP(&server->offset); 99654359Sroberto server->dispersion = 0; 99754359Sroberto for (i = 1; i < sys_samples; i++) { 99854359Sroberto if (server->filter_delay[ord[i]] == 0) 99954359Sroberto d = PEER_MAXDISP; 100054359Sroberto else { 100154359Sroberto d = server->filter_soffset[ord[i]] 100254359Sroberto - server->filter_soffset[ord[0]]; 100354359Sroberto if (d < 0) 100454359Sroberto d = -d; 100554359Sroberto if (d > PEER_MAXDISP) 100654359Sroberto d = PEER_MAXDISP; 100754359Sroberto } 100854359Sroberto /* 100954359Sroberto * XXX This *knows* PEER_FILTER is 1/2 101054359Sroberto */ 101154359Sroberto server->dispersion += (u_fp)(d) >> i; 101254359Sroberto } 101354359Sroberto } 101454359Sroberto /* 101554359Sroberto * We're done 101654359Sroberto */ 101754359Sroberto} 101854359Sroberto 101954359Sroberto 102054359Sroberto/* 102154359Sroberto * clock_select - select the pick-of-the-litter clock from the samples 102254359Sroberto * we've got. 102354359Sroberto */ 102454359Srobertostatic struct server * 102554359Srobertoclock_select(void) 102654359Sroberto{ 1027290001Sglebius struct server *server; 1028290001Sglebius u_int nlist; 1029290001Sglebius s_fp d; 1030290001Sglebius u_int count; 1031290001Sglebius u_int i; 1032290001Sglebius u_int j; 1033290001Sglebius u_int k; 1034290001Sglebius int n; 103554359Sroberto s_fp local_threshold; 103654359Sroberto struct server *server_list[NTP_MAXCLOCK]; 103754359Sroberto u_fp server_badness[NTP_MAXCLOCK]; 103854359Sroberto struct server *sys_server; 103954359Sroberto 104054359Sroberto /* 104154359Sroberto * This first chunk of code is supposed to go through all 104254359Sroberto * servers we know about to find the NTP_MAXLIST servers which 104354359Sroberto * are most likely to succeed. We run through the list 104454359Sroberto * doing the sanity checks and trying to insert anyone who 104554359Sroberto * looks okay. We are at all times aware that we should 104654359Sroberto * only keep samples from the top two strata and we only need 104754359Sroberto * NTP_MAXLIST of them. 104854359Sroberto */ 104954359Sroberto nlist = 0; /* none yet */ 105056746Sroberto for (server = sys_servers; server != NULL; server = server->next_server) { 1051106163Sroberto if (server->delay == 0) { 1052106163Sroberto if (debug) 1053106163Sroberto printf("%s: Server dropped: no data\n", ntoa(&server->srcadr)); 1054182007Sroberto continue; /* no data */ 1055106163Sroberto } 1056106163Sroberto if (server->stratum > NTP_INFIN) { 1057106163Sroberto if (debug) 1058106163Sroberto printf("%s: Server dropped: strata too high\n", ntoa(&server->srcadr)); 1059182007Sroberto continue; /* stratum no good */ 1060106163Sroberto } 106154359Sroberto if (server->delay > NTP_MAXWGT) { 1062106163Sroberto if (debug) 1063106163Sroberto printf("%s: Server dropped: server too far away\n", 1064182007Sroberto ntoa(&server->srcadr)); 1065182007Sroberto continue; /* too far away */ 106654359Sroberto } 1067106163Sroberto if (server->leap == LEAP_NOTINSYNC) { 1068106163Sroberto if (debug) 1069106163Sroberto printf("%s: Server dropped: Leap not in sync\n", ntoa(&server->srcadr)); 1070182007Sroberto continue; /* he's in trouble */ 1071106163Sroberto } 107254359Sroberto if (!L_ISHIS(&server->org, &server->reftime)) { 1073106163Sroberto if (debug) 1074106163Sroberto printf("%s: Server dropped: server is very broken\n", 1075106163Sroberto ntoa(&server->srcadr)); 1076182007Sroberto continue; /* very broken host */ 107754359Sroberto } 107854359Sroberto if ((server->org.l_ui - server->reftime.l_ui) 1079106163Sroberto >= NTP_MAXAGE) { 1080106163Sroberto if (debug) 1081106163Sroberto printf("%s: Server dropped: Server has gone too long without sync\n", 1082106163Sroberto ntoa(&server->srcadr)); 108354359Sroberto continue; /* too long without sync */ 108454359Sroberto } 108554359Sroberto if (server->trust != 0) { 1086106163Sroberto if (debug) 1087106163Sroberto printf("%s: Server dropped: Server is untrusted\n", 1088106163Sroberto ntoa(&server->srcadr)); 108954359Sroberto continue; 109054359Sroberto } 109154359Sroberto 109254359Sroberto /* 109354359Sroberto * This one seems sane. Find where he belongs 109454359Sroberto * on the list. 109554359Sroberto */ 109654359Sroberto d = server->dispersion + server->dispersion; 109754359Sroberto for (i = 0; i < nlist; i++) 109854359Sroberto if (server->stratum <= server_list[i]->stratum) 109954359Sroberto break; 110054359Sroberto for ( ; i < nlist; i++) { 110154359Sroberto if (server->stratum < server_list[i]->stratum) 110254359Sroberto break; 110354359Sroberto if (d < (s_fp) server_badness[i]) 110454359Sroberto break; 110554359Sroberto } 110654359Sroberto 110754359Sroberto /* 110854359Sroberto * If i points past the end of the list, this 110954359Sroberto * guy is a loser, else stick him in. 111054359Sroberto */ 111154359Sroberto if (i >= NTP_MAXLIST) 111254359Sroberto continue; 111354359Sroberto for (j = nlist; j > i; j--) 111454359Sroberto if (j < NTP_MAXLIST) { 111554359Sroberto server_list[j] = server_list[j-1]; 111654359Sroberto server_badness[j] 111754359Sroberto = server_badness[j-1]; 111854359Sroberto } 111954359Sroberto 112054359Sroberto server_list[i] = server; 112154359Sroberto server_badness[i] = d; 112254359Sroberto if (nlist < NTP_MAXLIST) 112354359Sroberto nlist++; 112454359Sroberto } 112554359Sroberto 112654359Sroberto /* 112754359Sroberto * Got the five-or-less best. Cut the list where the number of 112854359Sroberto * strata exceeds two. 112954359Sroberto */ 1130290001Sglebius count = 0; 113154359Sroberto for (i = 1; i < nlist; i++) 1132290001Sglebius if (server_list[i]->stratum > server_list[i-1]->stratum) { 1133290001Sglebius count++; 1134290001Sglebius if (2 == count) { 1135290001Sglebius nlist = i; 1136290001Sglebius break; 1137290001Sglebius } 113854359Sroberto } 113954359Sroberto 114054359Sroberto /* 114154359Sroberto * Whew! What we should have by now is 0 to 5 candidates for 114254359Sroberto * the job of syncing us. If we have none, we're out of luck. 114354359Sroberto * If we have one, he's a winner. If we have more, do falseticker 114454359Sroberto * detection. 114554359Sroberto */ 114654359Sroberto 1147290001Sglebius if (0 == nlist) 1148290001Sglebius sys_server = NULL; 1149290001Sglebius else if (1 == nlist) { 115054359Sroberto sys_server = server_list[0]; 115154359Sroberto } else { 115254359Sroberto /* 115354359Sroberto * Re-sort by stratum, bdelay estimate quality and 115454359Sroberto * server.delay. 115554359Sroberto */ 115654359Sroberto for (i = 0; i < nlist-1; i++) 115754359Sroberto for (j = i+1; j < nlist; j++) { 1158290001Sglebius if (server_list[i]->stratum < 1159290001Sglebius server_list[j]->stratum) 1160290001Sglebius /* already sorted by stratum */ 1161290001Sglebius break; 1162290001Sglebius if (server_list[i]->delay < 1163290001Sglebius server_list[j]->delay) 1164290001Sglebius continue; 116554359Sroberto server = server_list[i]; 116654359Sroberto server_list[i] = server_list[j]; 116754359Sroberto server_list[j] = server; 116854359Sroberto } 116954359Sroberto 117054359Sroberto /* 117154359Sroberto * Calculate the fixed part of the dispersion limit 117254359Sroberto */ 117354359Sroberto local_threshold = (FP_SECOND >> (-(int)NTPDATE_PRECISION)) 117454359Sroberto + NTP_MAXSKW; 117554359Sroberto 117654359Sroberto /* 117754359Sroberto * Now drop samples until we're down to one. 117854359Sroberto */ 117954359Sroberto while (nlist > 1) { 1180290001Sglebius for (k = 0; k < nlist; k++) { 1181290001Sglebius server_badness[k] = 0; 118254359Sroberto for (j = 0; j < nlist; j++) { 1183290001Sglebius if (j == k) /* with self? */ 118454359Sroberto continue; 1185290001Sglebius d = server_list[j]->soffset - 1186290001Sglebius server_list[k]->soffset; 1187290001Sglebius if (d < 0) /* abs value */ 118854359Sroberto d = -d; 118954359Sroberto /* 119054359Sroberto * XXX This code *knows* that 119154359Sroberto * NTP_SELECT is 3/4 119254359Sroberto */ 119354359Sroberto for (i = 0; i < j; i++) 119454359Sroberto d = (d>>1) + (d>>2); 1195290001Sglebius server_badness[k] += d; 119654359Sroberto } 119754359Sroberto } 119854359Sroberto 119954359Sroberto /* 120054359Sroberto * We now have an array of nlist badness 120154359Sroberto * coefficients. Find the badest. Find 120254359Sroberto * the minimum precision while we're at 120354359Sroberto * it. 120454359Sroberto */ 120554359Sroberto i = 0; 120654359Sroberto n = server_list[0]->precision;; 120754359Sroberto for (j = 1; j < nlist; j++) { 120854359Sroberto if (server_badness[j] >= server_badness[i]) 120954359Sroberto i = j; 121054359Sroberto if (n > server_list[j]->precision) 121154359Sroberto n = server_list[j]->precision; 121254359Sroberto } 121354359Sroberto 121454359Sroberto /* 121554359Sroberto * i is the index of the server with the worst 121654359Sroberto * dispersion. If his dispersion is less than 121754359Sroberto * the threshold, stop now, else delete him and 121854359Sroberto * continue around again. 121954359Sroberto */ 122054359Sroberto if ( (s_fp) server_badness[i] < (local_threshold 122154359Sroberto + (FP_SECOND >> (-n)))) 122254359Sroberto break; 122354359Sroberto for (j = i + 1; j < nlist; j++) 122454359Sroberto server_list[j-1] = server_list[j]; 122554359Sroberto nlist--; 122654359Sroberto } 122754359Sroberto 122854359Sroberto /* 122954359Sroberto * What remains is a list of less than 5 servers. Take 123054359Sroberto * the best. 123154359Sroberto */ 123254359Sroberto sys_server = server_list[0]; 123354359Sroberto } 123454359Sroberto 123554359Sroberto /* 1236182007Sroberto * That's it. Return our server. 123754359Sroberto */ 123854359Sroberto return sys_server; 123954359Sroberto} 124054359Sroberto 124154359Sroberto 124254359Sroberto/* 124354359Sroberto * clock_adjust - process what we've received, and adjust the time 124454359Sroberto * if we got anything decent. 124554359Sroberto */ 124654359Srobertostatic int 124754359Srobertoclock_adjust(void) 124854359Sroberto{ 124956746Sroberto register struct server *sp, *server; 125054359Sroberto int dostep; 125154359Sroberto 125256746Sroberto for (sp = sys_servers; sp != NULL; sp = sp->next_server) 125356746Sroberto clock_filter(sp); 125454359Sroberto server = clock_select(); 125554359Sroberto 125654359Sroberto if (debug || simple_query) { 125756746Sroberto for (sp = sys_servers; sp != NULL; sp = sp->next_server) 125856746Sroberto printserver(sp, stdout); 125954359Sroberto } 126054359Sroberto 126154359Sroberto if (server == 0) { 126254359Sroberto msyslog(LOG_ERR, 126354359Sroberto "no server suitable for synchronization found"); 126454359Sroberto return(1); 126554359Sroberto } 126654359Sroberto 126754359Sroberto if (always_step) { 126854359Sroberto dostep = 1; 126954359Sroberto } else if (never_step) { 127054359Sroberto dostep = 0; 127154359Sroberto } else { 1272298770Sdelphij /* [Bug 3023] get absolute difference, avoiding signed 1273298770Sdelphij * integer overflow like hell. 1274298770Sdelphij */ 1275298770Sdelphij u_fp absoffset; 1276298770Sdelphij if (server->soffset < 0) 1277298770Sdelphij absoffset = 1u + (u_fp)(-(server->soffset + 1)); 1278298770Sdelphij else 1279298770Sdelphij absoffset = (u_fp)server->soffset; 1280298770Sdelphij dostep = (absoffset >= NTPDATE_THRESHOLD); 128154359Sroberto } 128254359Sroberto 128354359Sroberto if (dostep) { 1284182007Sroberto if (simple_query || debug || l_step_systime(&server->offset)){ 128554359Sroberto msyslog(LOG_NOTICE, "step time server %s offset %s sec", 1286132451Sroberto stoa(&server->srcadr), 128754359Sroberto lfptoa(&server->offset, 6)); 128854359Sroberto } 128954359Sroberto } else { 1290290001Sglebius#ifndef SYS_WINNT 129154359Sroberto if (simple_query || l_adj_systime(&server->offset)) { 129254359Sroberto msyslog(LOG_NOTICE, "adjust time server %s offset %s sec", 1293132451Sroberto stoa(&server->srcadr), 129454359Sroberto lfptoa(&server->offset, 6)); 129554359Sroberto } 129654359Sroberto#else 129754359Sroberto /* The NT SetSystemTimeAdjustment() call achieves slewing by 129854359Sroberto * changing the clock frequency. This means that we cannot specify 129954359Sroberto * it to slew the clock by a definite amount and then stop like 130054359Sroberto * the Unix adjtime() routine. We can technically adjust the clock 130154359Sroberto * frequency, have ntpdate sleep for a while, and then wake 130254359Sroberto * up and reset the clock frequency, but this might cause some 130354359Sroberto * grief if the user attempts to run ntpd immediately after 130454359Sroberto * ntpdate and the socket is in use. 130554359Sroberto */ 130654359Sroberto printf("\nThe -b option is required by ntpdate on Windows NT platforms\n"); 130754359Sroberto exit(1); 130854359Sroberto#endif /* SYS_WINNT */ 130954359Sroberto } 131054359Sroberto return(0); 131154359Sroberto} 131254359Sroberto 131354359Sroberto 1314182007Sroberto/* 1315182007Sroberto * is_unreachable - check to see if we have a route to given destination 1316182007Sroberto * (non-blocking). 1317182007Sroberto */ 1318182007Srobertostatic int 1319290001Sglebiusis_reachable (sockaddr_u *dst) 1320182007Sroberto{ 1321182007Sroberto SOCKET sockfd; 1322182007Sroberto 1323290001Sglebius sockfd = socket(AF(dst), SOCK_DGRAM, 0); 1324182007Sroberto if (sockfd == -1) { 1325182007Sroberto return 0; 1326182007Sroberto } 1327182007Sroberto 1328290001Sglebius if (connect(sockfd, &dst->sa, SOCKLEN(dst))) { 1329182007Sroberto closesocket(sockfd); 1330182007Sroberto return 0; 1331182007Sroberto } 1332182007Sroberto closesocket(sockfd); 1333182007Sroberto return 1; 1334182007Sroberto} 1335182007Sroberto 1336182007Sroberto 1337182007Sroberto 133854359Sroberto/* XXX ELIMINATE: merge BIG slew into adj_systime in lib/systime.c */ 133954359Sroberto/* 134054359Sroberto * addserver - determine a server's address and allocate a new structure 1341182007Sroberto * for it. 134254359Sroberto */ 134354359Srobertostatic void 134454359Srobertoaddserver( 134554359Sroberto char *serv 134654359Sroberto ) 134754359Sroberto{ 134854359Sroberto register struct server *server; 1349182007Sroberto /* Address infos structure to store result of getaddrinfo */ 1350182007Sroberto struct addrinfo *addrResult, *ptr; 1351182007Sroberto /* Address infos structure to store hints for getaddrinfo */ 1352182007Sroberto struct addrinfo hints; 1353182007Sroberto /* Error variable for getaddrinfo */ 1354182007Sroberto int error; 1355182007Sroberto /* Service name */ 1356182007Sroberto char service[5]; 1357290001Sglebius sockaddr_u addr; 135854359Sroberto 1359290001Sglebius strlcpy(service, "ntp", sizeof(service)); 1360290001Sglebius 1361182007Sroberto /* Get host address. Looking for UDP datagram connection. */ 1362290001Sglebius ZERO(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 */ 1378290001Sglebius fprintf(stderr, "Exiting, name server cannot be used: %s (%d)", 1379290001Sglebius gai_strerror(error), error); 1380290001Sglebius msyslog(LOG_ERR, "name server cannot be used: %s (%d)", 1381290001Sglebius gai_strerror(error), error); 1382182007Sroberto exit(1); 1383182007Sroberto } 1384290001Sglebius fprintf(stderr, "Error resolving %s: %s (%d)\n", serv, 1385290001Sglebius gai_strerror(error), error); 1386290001Sglebius msyslog(LOG_ERR, "Can't find host %s: %s (%d)", serv, 1387290001Sglebius gai_strerror(error), error); 138854359Sroberto return; 138954359Sroberto } 1390138451Sroberto#ifdef DEBUG 1391290001Sglebius if (debug) { 1392290001Sglebius ZERO(addr); 1393290001Sglebius INSIST(addrResult->ai_addrlen <= sizeof(addr)); 1394290001Sglebius memcpy(&addr, addrResult->ai_addr, addrResult->ai_addrlen); 1395290001Sglebius fprintf(stderr, "host found : %s\n", stohost(&addr)); 1396182007Sroberto } 1397138451Sroberto#endif 139854359Sroberto 1399182007Sroberto /* We must get all returned server in case the first one fails */ 1400182007Sroberto for (ptr = addrResult; ptr != NULL; ptr = ptr->ai_next) { 1401290001Sglebius ZERO(addr); 1402290001Sglebius INSIST(ptr->ai_addrlen <= sizeof(addr)); 1403290001Sglebius memcpy(&addr, ptr->ai_addr, ptr->ai_addrlen); 1404290001Sglebius if (is_reachable(&addr)) { 1405290001Sglebius server = emalloc_zero(sizeof(*server)); 1406290001Sglebius memcpy(&server->srcadr, ptr->ai_addr, ptr->ai_addrlen); 1407182007Sroberto server->event_time = ++sys_numservers; 1408182007Sroberto if (sys_servers == NULL) 1409182007Sroberto sys_servers = server; 1410182007Sroberto else { 1411182007Sroberto struct server *sp; 141256746Sroberto 1413182007Sroberto for (sp = sys_servers; sp->next_server != NULL; 1414290001Sglebius sp = sp->next_server) 1415290001Sglebius /* empty */; 1416182007Sroberto sp->next_server = server; 1417182007Sroberto } 1418182007Sroberto } 141956746Sroberto } 1420182007Sroberto 1421182007Sroberto freeaddrinfo(addrResult); 142254359Sroberto} 142354359Sroberto 142454359Sroberto 142554359Sroberto/* 142654359Sroberto * findserver - find a server in the list given its address 1427132451Sroberto * ***(For now it isn't totally AF-Independant, to check later..) 142854359Sroberto */ 142954359Srobertostatic struct server * 143054359Srobertofindserver( 1431290001Sglebius sockaddr_u *addr 143254359Sroberto ) 143354359Sroberto{ 143456746Sroberto struct server *server; 143556746Sroberto struct server *mc_server; 143654359Sroberto 143756746Sroberto mc_server = NULL; 1438290001Sglebius if (SRCPORT(addr) != NTP_PORT) 143954359Sroberto return 0; 144054359Sroberto 144156746Sroberto for (server = sys_servers; server != NULL; 144256746Sroberto server = server->next_server) { 1443290001Sglebius if (SOCK_EQ(addr, &server->srcadr)) 144456746Sroberto return server; 1445182007Sroberto 1446290001Sglebius if (AF(addr) == AF(&server->srcadr)) { 1447290001Sglebius if (IS_MCAST(&server->srcadr)) 1448182007Sroberto mc_server = server; 1449182007Sroberto } 145054359Sroberto } 145156746Sroberto 145256746Sroberto if (mc_server != NULL) { 1453132451Sroberto 145456746Sroberto struct server *sp; 145556746Sroberto 145656746Sroberto if (mc_server->event_time != 0) { 145756746Sroberto mc_server->event_time = 0; 145856746Sroberto complete_servers++; 145956746Sroberto } 1460132451Sroberto 1461290001Sglebius server = emalloc_zero(sizeof(*server)); 146256746Sroberto 1463290001Sglebius server->srcadr = *addr; 146456746Sroberto 146556746Sroberto server->event_time = ++sys_numservers; 1466132451Sroberto 146756746Sroberto for (sp = sys_servers; sp->next_server != NULL; 1468290001Sglebius sp = sp->next_server) 1469290001Sglebius /* empty */; 147056746Sroberto sp->next_server = server; 147156746Sroberto transmit(server); 147256746Sroberto } 147356746Sroberto return NULL; 147454359Sroberto} 147554359Sroberto 147654359Sroberto 147754359Sroberto/* 147854359Sroberto * timer - process a timer interrupt 147954359Sroberto */ 148054359Srobertovoid 148154359Srobertotimer(void) 148254359Sroberto{ 148356746Sroberto struct server *server; 148454359Sroberto 148554359Sroberto /* 148654359Sroberto * Bump the current idea of the time 148754359Sroberto */ 148854359Sroberto current_time++; 148954359Sroberto 149054359Sroberto /* 149154359Sroberto * Search through the server list looking for guys 149254359Sroberto * who's event timers have expired. Give these to 149354359Sroberto * the transmit routine. 149454359Sroberto */ 149556746Sroberto for (server = sys_servers; server != NULL; 149656746Sroberto server = server->next_server) { 149756746Sroberto if (server->event_time != 0 149856746Sroberto && server->event_time <= current_time) 149956746Sroberto transmit(server); 150054359Sroberto } 150154359Sroberto} 150254359Sroberto 150354359Sroberto 150482498Sroberto/* 150582498Sroberto * The code duplication in the following subroutine sucks, but 150682498Sroberto * we need to appease ansi2knr. 150782498Sroberto */ 150882498Sroberto 150954359Sroberto#ifndef SYS_WINNT 151054359Sroberto/* 151154359Sroberto * alarming - record the occurance of an alarm interrupt 151254359Sroberto */ 151354359Srobertostatic RETSIGTYPE 151454359Srobertoalarming( 151554359Sroberto int sig 151654359Sroberto ) 151782498Sroberto{ 151882498Sroberto alarm_flag++; 151982498Sroberto} 1520290001Sglebius#else /* SYS_WINNT follows */ 152154359Srobertovoid CALLBACK 152254359Srobertoalarming(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) 152354359Sroberto{ 1524290001Sglebius UNUSED_ARG(uTimerID); UNUSED_ARG(uMsg); UNUSED_ARG(dwUser); 1525290001Sglebius UNUSED_ARG(dw1); UNUSED_ARG(dw2); 1526290001Sglebius 152754359Sroberto alarm_flag++; 152854359Sroberto} 152954359Sroberto 1530182007Srobertostatic void 1531182007SrobertocallTimeEndPeriod(void) 1532182007Sroberto{ 1533182007Sroberto timeEndPeriod( wTimerRes ); 1534182007Sroberto wTimerRes = 0; 1535182007Sroberto} 1536182007Sroberto#endif /* SYS_WINNT */ 1537182007Sroberto 1538182007Sroberto 153954359Sroberto/* 154054359Sroberto * init_alarm - set up the timer interrupt 154154359Sroberto */ 154254359Srobertostatic void 154354359Srobertoinit_alarm(void) 154454359Sroberto{ 154554359Sroberto#ifndef SYS_WINNT 1546290001Sglebius# ifdef HAVE_TIMER_CREATE 1547290001Sglebius struct itimerspec its; 154854359Sroberto# else 1549290001Sglebius struct itimerval itv; 155054359Sroberto# endif 1551290001Sglebius#else /* SYS_WINNT follows */ 155254359Sroberto TIMECAPS tc; 1553182007Sroberto UINT wTimerID; 155454359Sroberto HANDLE hToken; 155554359Sroberto TOKEN_PRIVILEGES tkp; 155654359Sroberto DWORD dwUser = 0; 155754359Sroberto#endif /* SYS_WINNT */ 155854359Sroberto 155954359Sroberto alarm_flag = 0; 156054359Sroberto 156154359Sroberto#ifndef SYS_WINNT 1562290001Sglebius# ifdef HAVE_TIMER_CREATE 156354359Sroberto alarm_flag = 0; 156454359Sroberto /* this code was put in as setitimer() is non existant this us the 156554359Sroberto * POSIX "equivalents" setup - casey 156654359Sroberto */ 156754359Sroberto /* ntpdate_timerid is global - so we can kill timer later */ 156854359Sroberto if (timer_create (CLOCK_REALTIME, NULL, &ntpdate_timerid) == 156954359Sroberto# ifdef SYS_VXWORKS 157054359Sroberto ERROR 157154359Sroberto# else 157254359Sroberto -1 157354359Sroberto# endif 157454359Sroberto ) 157554359Sroberto { 157654359Sroberto fprintf (stderr, "init_alarm(): timer_create (...) FAILED\n"); 157754359Sroberto return; 157854359Sroberto } 157954359Sroberto 158054359Sroberto /* TIMER_HZ = (5) 158154359Sroberto * Set up the alarm interrupt. The first comes 1/(2*TIMER_HZ) 158254359Sroberto * seconds from now and they continue on every 1/TIMER_HZ seconds. 158354359Sroberto */ 1584290001Sglebius signal_no_reset(SIGALRM, alarming); 1585290001Sglebius its.it_interval.tv_sec = 0; 1586290001Sglebius its.it_value.tv_sec = 0; 1587290001Sglebius its.it_interval.tv_nsec = 1000000000/TIMER_HZ; 1588290001Sglebius its.it_value.tv_nsec = 1000000000/(TIMER_HZ<<1); 1589290001Sglebius timer_settime(ntpdate_timerid, 0 /* !TIMER_ABSTIME */, &its, NULL); 1590290001Sglebius# else /* !HAVE_TIMER_CREATE follows */ 159154359Sroberto /* 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 */ 1595290001Sglebius signal_no_reset(SIGALRM, alarming); 1596290001Sglebius itv.it_interval.tv_sec = 0; 1597290001Sglebius itv.it_value.tv_sec = 0; 1598290001Sglebius itv.it_interval.tv_usec = 1000000/TIMER_HZ; 1599290001Sglebius itv.it_value.tv_usec = 1000000/(TIMER_HZ<<1); 1600132451Sroberto 1601290001Sglebius setitimer(ITIMER_REAL, &itv, NULL); 1602290001Sglebius# endif /* !HAVE_TIMER_CREATE */ 1603290001Sglebius#else /* SYS_WINNT follows */ 160454359Sroberto _tzset(); 160554359Sroberto 160654359Sroberto /* 1607182007Sroberto * Get privileges needed for fiddling with the clock 160854359Sroberto */ 160954359Sroberto 161054359Sroberto /* get the current process token handle */ 161154359Sroberto if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { 161254359Sroberto msyslog(LOG_ERR, "OpenProcessToken failed: %m"); 161354359Sroberto exit(1); 161454359Sroberto } 161554359Sroberto /* get the LUID for system-time privilege. */ 161654359Sroberto LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid); 1617182007Sroberto tkp.PrivilegeCount = 1; /* one privilege to set */ 161854359Sroberto tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 161954359Sroberto /* get set-time privilege for this process. */ 162054359Sroberto AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0); 162154359Sroberto /* cannot test return value of AdjustTokenPrivileges. */ 162254359Sroberto if (GetLastError() != ERROR_SUCCESS) 162354359Sroberto msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m"); 162454359Sroberto 162554359Sroberto /* 162654359Sroberto * Set up timer interrupts for every 2**EVENT_TIMEOUT seconds 162754359Sroberto * Under Win/NT, expiry of timer interval leads to invocation 162854359Sroberto * of a callback function (on a different thread) rather than 162954359Sroberto * generating an alarm signal 163054359Sroberto */ 163154359Sroberto 163254359Sroberto /* determine max and min resolution supported */ 163354359Sroberto if(timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) { 163454359Sroberto msyslog(LOG_ERR, "timeGetDevCaps failed: %m"); 163554359Sroberto exit(1); 163654359Sroberto } 163754359Sroberto wTimerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax); 163854359Sroberto /* establish the minimum timer resolution that we'll use */ 163954359Sroberto timeBeginPeriod(wTimerRes); 1640182007Sroberto atexit(callTimeEndPeriod); 164154359Sroberto 164254359Sroberto /* start the timer event */ 164354359Sroberto wTimerID = timeSetEvent( 1644182007Sroberto (UINT) (1000/TIMER_HZ), /* Delay */ 1645182007Sroberto wTimerRes, /* Resolution */ 1646182007Sroberto (LPTIMECALLBACK) alarming, /* Callback function */ 1647182007Sroberto (DWORD) dwUser, /* User data */ 1648182007Sroberto TIME_PERIODIC); /* Event type (periodic) */ 164954359Sroberto if (wTimerID == 0) { 165054359Sroberto msyslog(LOG_ERR, "timeSetEvent failed: %m"); 165154359Sroberto exit(1); 165254359Sroberto } 165354359Sroberto#endif /* SYS_WINNT */ 165454359Sroberto} 165554359Sroberto 165654359Sroberto 165754359Sroberto 165854359Sroberto 165954359Sroberto/* 166054359Sroberto * We do asynchronous input using the SIGIO facility. A number of 166154359Sroberto * recvbuf buffers are preallocated for input. In the signal 166254359Sroberto * handler we poll to see if the socket is ready and read the 166354359Sroberto * packets from it into the recvbuf's along with a time stamp and 166454359Sroberto * an indication of the source host and the interface it was received 166554359Sroberto * through. This allows us to get as accurate receive time stamps 166654359Sroberto * as possible independent of other processing going on. 166754359Sroberto * 166854359Sroberto * We allocate a number of recvbufs equal to the number of servers 166954359Sroberto * plus 2. This should be plenty. 167054359Sroberto */ 167154359Sroberto 167254359Sroberto 167354359Sroberto/* 167454359Sroberto * init_io - initialize I/O data and open socket 167554359Sroberto */ 167654359Srobertostatic void 167754359Srobertoinit_io(void) 167854359Sroberto{ 1679182007Sroberto struct addrinfo *res, *ressave; 1680182007Sroberto struct addrinfo hints; 1681290001Sglebius sockaddr_u addr; 1682132451Sroberto char service[5]; 1683290001Sglebius int rc; 1684182007Sroberto int optval = 1; 1685182007Sroberto int check_ntp_port_in_use = !debug && !simple_query && !unpriv_port; 1686132451Sroberto 168754359Sroberto /* 168854359Sroberto * Init buffer free list and stat counters 168954359Sroberto */ 169054359Sroberto init_recvbuff(sys_numservers + 2); 1691132451Sroberto 169254359Sroberto /* 169354359Sroberto * Open the socket 169454359Sroberto */ 169554359Sroberto 1696290001Sglebius strlcpy(service, "ntp", sizeof(service)); 1697132451Sroberto 1698182007Sroberto /* 1699182007Sroberto * Init hints addrinfo structure 1700182007Sroberto */ 1701290001Sglebius ZERO(hints); 1702182007Sroberto hints.ai_family = ai_fam_templ; 1703182007Sroberto hints.ai_flags = AI_PASSIVE; 1704182007Sroberto hints.ai_socktype = SOCK_DGRAM; 1705132451Sroberto 1706290001Sglebius if (getaddrinfo(NULL, service, &hints, &res) != 0) { 1707290001Sglebius msyslog(LOG_ERR, "getaddrinfo() failed: %m"); 1708290001Sglebius exit(1); 1709290001Sglebius /*NOTREACHED*/ 1710182007Sroberto } 1711132451Sroberto 1712182007Sroberto#ifdef SYS_WINNT 1713182007Sroberto if (check_ntp_port_in_use && ntp_port_inuse(AF_INET, NTP_PORT)){ 1714290001Sglebius msyslog(LOG_ERR, "the NTP socket is in use, exiting: %m"); 1715182007Sroberto exit(1); 1716182007Sroberto } 1717182007Sroberto#endif 1718132451Sroberto 1719182007Sroberto /* Remember the address of the addrinfo structure chain */ 1720182007Sroberto ressave = res; 1721182007Sroberto 1722182007Sroberto /* 1723182007Sroberto * For each structure returned, open and bind socket 1724182007Sroberto */ 1725182007Sroberto for(nbsock = 0; (nbsock < MAX_AF) && res ; res = res->ai_next) { 172654359Sroberto /* create a datagram (UDP) socket */ 1727182007Sroberto fd[nbsock] = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 1728182007Sroberto if (fd[nbsock] == SOCKET_ERROR) { 1729182007Sroberto#ifndef SYS_WINNT 1730132451Sroberto if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT || 1731132451Sroberto errno == EPFNOSUPPORT) 1732182007Sroberto#else 1733182007Sroberto int err = WSAGetLastError(); 1734182007Sroberto if (err == WSAEPROTONOSUPPORT || err == WSAEAFNOSUPPORT || 1735182007Sroberto err == WSAEPFNOSUPPORT) 1736182007Sroberto#endif 1737132451Sroberto continue; 1738290001Sglebius msyslog(LOG_ERR, "socket() failed: %m"); 173954359Sroberto exit(1); 174054359Sroberto /*NOTREACHED*/ 1741182007Sroberto } 1742182007Sroberto /* set socket to reuse address */ 1743182007Sroberto if (setsockopt(fd[nbsock], SOL_SOCKET, SO_REUSEADDR, (void*) &optval, sizeof(optval)) < 0) { 1744290001Sglebius msyslog(LOG_ERR, "setsockopt() SO_REUSEADDR failed: %m"); 1745182007Sroberto exit(1); 1746182007Sroberto /*NOTREACHED*/ 1747182007Sroberto } 1748132451Sroberto#ifdef IPV6_V6ONLY 1749182007Sroberto /* Restricts AF_INET6 socket to IPv6 communications (see RFC 2553bis-03) */ 1750182007Sroberto if (res->ai_family == AF_INET6) 1751182007Sroberto if (setsockopt(fd[nbsock], IPPROTO_IPV6, IPV6_V6ONLY, (void*) &optval, sizeof(optval)) < 0) { 1752290001Sglebius msyslog(LOG_ERR, "setsockopt() IPV6_V6ONLY failed: %m"); 1753182007Sroberto exit(1); 1754182007Sroberto /*NOTREACHED*/ 1755182007Sroberto } 1756132451Sroberto#endif 175754359Sroberto 1758182007Sroberto /* Remember the socket family in fd_family structure */ 1759182007Sroberto fd_family[nbsock] = res->ai_family; 1760132451Sroberto 1761182007Sroberto /* 1762182007Sroberto * bind the socket to the NTP port 1763182007Sroberto */ 1764182007Sroberto if (check_ntp_port_in_use) { 1765290001Sglebius ZERO(addr); 1766290001Sglebius INSIST(res->ai_addrlen <= sizeof(addr)); 1767290001Sglebius memcpy(&addr, res->ai_addr, res->ai_addrlen); 1768290001Sglebius rc = bind(fd[nbsock], &addr.sa, SOCKLEN(&addr)); 1769290001Sglebius if (rc < 0) { 1770290001Sglebius if (EADDRINUSE == socket_errno()) 1771290001Sglebius msyslog(LOG_ERR, "the NTP socket is in use, exiting"); 177254359Sroberto else 1773290001Sglebius msyslog(LOG_ERR, "bind() fails: %m"); 1774182007Sroberto exit(1); 1775182007Sroberto } 177654359Sroberto } 177754359Sroberto 177854359Sroberto#ifdef HAVE_POLL_H 1779182007Sroberto fdmask[nbsock].fd = fd[nbsock]; 1780182007Sroberto fdmask[nbsock].events = POLLIN; 178154359Sroberto#else 1782182007Sroberto FD_SET(fd[nbsock], &fdmask); 1783182007Sroberto if (maxfd < fd[nbsock]+1) { 1784182007Sroberto maxfd = fd[nbsock]+1; 1785182007Sroberto } 178654359Sroberto#endif 178754359Sroberto 1788182007Sroberto /* 1789182007Sroberto * set non-blocking, 1790182007Sroberto */ 179154359Sroberto#ifndef SYS_WINNT 179254359Sroberto# ifdef SYS_VXWORKS 1793182007Sroberto { 1794290001Sglebius int on = TRUE; 179554359Sroberto 1796290001Sglebius if (ioctl(fd[nbsock],FIONBIO, &on) == ERROR) { 1797290001Sglebius msyslog(LOG_ERR, "ioctl(FIONBIO) fails: %m"); 1798290001Sglebius exit(1); 1799290001Sglebius } 1800182007Sroberto } 180154359Sroberto# else /* not SYS_VXWORKS */ 180254359Sroberto# if defined(O_NONBLOCK) 1803182007Sroberto if (fcntl(fd[nbsock], F_SETFL, O_NONBLOCK) < 0) { 1804290001Sglebius msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m"); 1805182007Sroberto exit(1); 1806182007Sroberto /*NOTREACHED*/ 1807182007Sroberto } 180854359Sroberto# else /* not O_NONBLOCK */ 180954359Sroberto# if defined(FNDELAY) 1810182007Sroberto if (fcntl(fd[nbsock], F_SETFL, FNDELAY) < 0) { 1811290001Sglebius msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m"); 1812182007Sroberto exit(1); 1813182007Sroberto /*NOTREACHED*/ 1814182007Sroberto } 181554359Sroberto# else /* FNDELAY */ 181654359Sroberto# include "Bletch: Need non blocking I/O" 181754359Sroberto# endif /* FNDELAY */ 181854359Sroberto# endif /* not O_NONBLOCK */ 181954359Sroberto# endif /* SYS_VXWORKS */ 182054359Sroberto#else /* SYS_WINNT */ 1821182007Sroberto if (ioctlsocket(fd[nbsock], FIONBIO, (u_long *) &on) == SOCKET_ERROR) { 1822290001Sglebius msyslog(LOG_ERR, "ioctlsocket(FIONBIO) fails: %m"); 1823182007Sroberto exit(1); 1824182007Sroberto } 1825182007Sroberto#endif /* SYS_WINNT */ 1826182007Sroberto nbsock++; 182754359Sroberto } 1828182007Sroberto freeaddrinfo(ressave); 182954359Sroberto} 183054359Sroberto 183154359Sroberto/* 183254359Sroberto * sendpkt - send a packet to the specified destination 183354359Sroberto */ 183454359Srobertostatic void 183554359Srobertosendpkt( 1836290001Sglebius sockaddr_u *dest, 183754359Sroberto struct pkt *pkt, 183854359Sroberto int len 183954359Sroberto ) 184054359Sroberto{ 1841182007Sroberto int i; 184254359Sroberto int cc; 1843182007Sroberto SOCKET sock = INVALID_SOCKET; 184454359Sroberto 184554359Sroberto#ifdef SYS_WINNT 184654359Sroberto DWORD err; 184754359Sroberto#endif /* SYS_WINNT */ 184854359Sroberto 1849182007Sroberto /* Find a local family compatible socket to send ntp packet to ntp server */ 1850182007Sroberto for(i = 0; (i < MAX_AF); i++) { 1851290001Sglebius if(AF(dest) == fd_family[i]) { 1852182007Sroberto sock = fd[i]; 1853182007Sroberto break; 1854182007Sroberto } 1855182007Sroberto } 1856132451Sroberto 1857290001Sglebius if (INVALID_SOCKET == sock) { 1858290001Sglebius msyslog(LOG_ERR, "cannot find family compatible socket to send ntp packet"); 1859182007Sroberto exit(1); 1860182007Sroberto /*NOTREACHED*/ 1861182007Sroberto } 1862132451Sroberto 1863132451Sroberto cc = sendto(sock, (char *)pkt, len, 0, (struct sockaddr *)dest, 1864132451Sroberto SOCKLEN(dest)); 1865132451Sroberto 1866290001Sglebius if (SOCKET_ERROR == cc) { 186754359Sroberto#ifndef SYS_WINNT 186854359Sroberto if (errno != EWOULDBLOCK && errno != ENOBUFS) 186954359Sroberto#else 187054359Sroberto err = WSAGetLastError(); 187154359Sroberto if (err != WSAEWOULDBLOCK && err != WSAENOBUFS) 187254359Sroberto#endif /* SYS_WINNT */ 1873290001Sglebius msyslog(LOG_ERR, "sendto(%s): %m", stohost(dest)); 187454359Sroberto } 187554359Sroberto} 187654359Sroberto 187754359Sroberto 187854359Sroberto/* 187954359Sroberto * input_handler - receive packets asynchronously 188054359Sroberto */ 188154359Srobertovoid 188254359Srobertoinput_handler(void) 188354359Sroberto{ 188454359Sroberto register int n; 188554359Sroberto register struct recvbuf *rb; 1886290001Sglebius struct sock_timeval tvzero; 1887290001Sglebius GETSOCKNAME_SOCKLEN_TYPE fromlen; 188854359Sroberto l_fp ts; 1889182007Sroberto int i; 189054359Sroberto#ifdef HAVE_POLL_H 1891132451Sroberto struct pollfd fds[MAX_AF]; 189254359Sroberto#else 189354359Sroberto fd_set fds; 189454359Sroberto#endif 1895293896Sglebius SOCKET fdc = 0; 189654359Sroberto 189754359Sroberto /* 189854359Sroberto * Do a poll to see if we have data 189954359Sroberto */ 190054359Sroberto for (;;) { 190154359Sroberto tvzero.tv_sec = tvzero.tv_usec = 0; 190254359Sroberto#ifdef HAVE_POLL_H 1903132451Sroberto memcpy(fds, fdmask, sizeof(fdmask)); 1904182007Sroberto n = poll(fds, (unsigned int)nbsock, tvzero.tv_sec * 1000); 1905132451Sroberto 1906182007Sroberto /* 1907182007Sroberto * Determine which socket received data 1908182007Sroberto */ 1909132451Sroberto 1910182007Sroberto for(i=0; i < nbsock; i++) { 1911182007Sroberto if(fds[i].revents & POLLIN) { 1912182007Sroberto fdc = fd[i]; 1913182007Sroberto break; 1914182007Sroberto } 1915182007Sroberto } 1916132451Sroberto 191754359Sroberto#else 1918132451Sroberto fds = fdmask; 1919293896Sglebius n = select(maxfd, &fds, NULL, NULL, &tvzero); 1920132451Sroberto 1921182007Sroberto /* 1922182007Sroberto * Determine which socket received data 1923182007Sroberto */ 1924132451Sroberto 1925182007Sroberto for(i=0; i < nbsock; i++) { 1926182007Sroberto if(FD_ISSET(fd[i], &fds)) { 1927182007Sroberto fdc = fd[i]; 1928182007Sroberto break; 1929182007Sroberto } 1930182007Sroberto } 1931132451Sroberto 193254359Sroberto#endif 193354359Sroberto 193454359Sroberto /* 193554359Sroberto * If nothing to do, just return. If an error occurred, 193654359Sroberto * complain and return. If we've got some, freeze a 193754359Sroberto * timestamp. 193854359Sroberto */ 193954359Sroberto if (n == 0) 194054359Sroberto return; 194154359Sroberto else if (n == -1) { 194254359Sroberto if (errno != EINTR) 1943290001Sglebius msyslog(LOG_ERR, 194454359Sroberto#ifdef HAVE_POLL_H 194554359Sroberto "poll() error: %m" 194654359Sroberto#else 194754359Sroberto "select() error: %m" 194854359Sroberto#endif 194954359Sroberto ); 195054359Sroberto return; 195154359Sroberto } 195254359Sroberto get_systime(&ts); 195354359Sroberto 195454359Sroberto /* 195554359Sroberto * Get a buffer and read the frame. If we 195654359Sroberto * haven't got a buffer, or this is received 195754359Sroberto * on the wild card socket, just dump the packet. 195854359Sroberto */ 195954359Sroberto if (initializing || free_recvbuffs() == 0) { 196054359Sroberto char buf[100]; 196154359Sroberto 1962132451Sroberto 196354359Sroberto#ifndef SYS_WINNT 1964132451Sroberto (void) read(fdc, buf, sizeof buf); 196554359Sroberto#else 196654359Sroberto /* NT's _read does not operate on nonblocking sockets 196754359Sroberto * either recvfrom or ReadFile() has to be used here. 196854359Sroberto * ReadFile is used in [ntpd]ntp_intres() and ntpdc, 196954359Sroberto * just to be different use recvfrom() here 197054359Sroberto */ 1971132451Sroberto recvfrom(fdc, buf, sizeof(buf), 0, (struct sockaddr *)0, NULL); 197254359Sroberto#endif /* SYS_WINNT */ 197354359Sroberto continue; 197454359Sroberto } 197554359Sroberto 197654359Sroberto rb = get_free_recv_buffer(); 197754359Sroberto 1978290001Sglebius fromlen = sizeof(rb->recv_srcadr); 1979132451Sroberto rb->recv_length = recvfrom(fdc, (char *)&rb->recv_pkt, 198054359Sroberto sizeof(rb->recv_pkt), 0, 198154359Sroberto (struct sockaddr *)&rb->recv_srcadr, &fromlen); 198254359Sroberto if (rb->recv_length == -1) { 198354359Sroberto freerecvbuf(rb); 198454359Sroberto continue; 198554359Sroberto } 198654359Sroberto 198754359Sroberto /* 198854359Sroberto * Got one. Mark how and when it got here, 198954359Sroberto * put it on the full list. 199054359Sroberto */ 199154359Sroberto rb->recv_time = ts; 199254359Sroberto add_full_recv_buffer(rb); 199354359Sroberto } 199454359Sroberto} 199554359Sroberto 199654359Sroberto 199754359Sroberto#if !defined SYS_WINNT && !defined SYS_CYGWIN32 199854359Sroberto/* 199954359Sroberto * adj_systime - do a big long slew of the system time 200054359Sroberto */ 200154359Srobertostatic int 200254359Srobertol_adj_systime( 200354359Sroberto l_fp *ts 200454359Sroberto ) 200554359Sroberto{ 200654359Sroberto struct timeval adjtv, oadjtv; 200754359Sroberto int isneg = 0; 200854359Sroberto l_fp offset; 200954359Sroberto#ifndef STEP_SLEW 201054359Sroberto l_fp overshoot; 201154359Sroberto#endif 201254359Sroberto 201354359Sroberto /* 201454359Sroberto * Take the absolute value of the offset 201554359Sroberto */ 201654359Sroberto offset = *ts; 201754359Sroberto if (L_ISNEG(&offset)) { 201854359Sroberto isneg = 1; 201954359Sroberto L_NEG(&offset); 202054359Sroberto } 202154359Sroberto 202254359Sroberto#ifndef STEP_SLEW 202354359Sroberto /* 202454359Sroberto * Calculate the overshoot. XXX N.B. This code *knows* 202554359Sroberto * ADJ_OVERSHOOT is 1/2. 202654359Sroberto */ 202754359Sroberto overshoot = offset; 202854359Sroberto L_RSHIFTU(&overshoot); 202954359Sroberto if (overshoot.l_ui != 0 || (overshoot.l_uf > ADJ_MAXOVERSHOOT)) { 203054359Sroberto overshoot.l_ui = 0; 203154359Sroberto overshoot.l_uf = ADJ_MAXOVERSHOOT; 203254359Sroberto } 203354359Sroberto L_ADD(&offset, &overshoot); 203454359Sroberto#endif 203554359Sroberto TSTOTV(&offset, &adjtv); 203654359Sroberto 203754359Sroberto if (isneg) { 203854359Sroberto adjtv.tv_sec = -adjtv.tv_sec; 203954359Sroberto adjtv.tv_usec = -adjtv.tv_usec; 204054359Sroberto } 204154359Sroberto 204254359Sroberto if (adjtv.tv_usec != 0 && !debug) { 204354359Sroberto if (adjtime(&adjtv, &oadjtv) < 0) { 204454359Sroberto msyslog(LOG_ERR, "Can't adjust the time of day: %m"); 2045290001Sglebius exit(1); 204654359Sroberto } 204754359Sroberto } 204854359Sroberto return 1; 204954359Sroberto} 205054359Sroberto#endif /* SYS_WINNT */ 205154359Sroberto 205254359Sroberto 205354359Sroberto/* 205454359Sroberto * This fuction is not the same as lib/systime step_systime!!! 205554359Sroberto */ 205654359Srobertostatic int 205754359Srobertol_step_systime( 205854359Sroberto l_fp *ts 205954359Sroberto ) 206054359Sroberto{ 206154359Sroberto double dtemp; 206254359Sroberto 206354359Sroberto#ifdef SLEWALWAYS 206454359Sroberto#ifdef STEP_SLEW 206554359Sroberto l_fp ftmp; 206654359Sroberto int isneg; 206754359Sroberto int n; 206854359Sroberto 206954359Sroberto if (debug) return 1; 207054359Sroberto /* 207154359Sroberto * Take the absolute value of the offset 207254359Sroberto */ 207354359Sroberto ftmp = *ts; 207454359Sroberto if (L_ISNEG(&ftmp)) { 207554359Sroberto L_NEG(&ftmp); 207654359Sroberto isneg = 1; 207754359Sroberto } else 207854359Sroberto isneg = 0; 207954359Sroberto 208054359Sroberto if (ftmp.l_ui >= 3) { /* Step it and slew - we might win */ 208156746Sroberto LFPTOD(ts, dtemp); 208256746Sroberto n = step_systime(dtemp); 208354359Sroberto if (!n) 208454359Sroberto return n; 208554359Sroberto if (isneg) 208654359Sroberto ts->l_ui = ~0; 208754359Sroberto else 208854359Sroberto ts->l_ui = ~0; 208954359Sroberto } 209054359Sroberto /* 209154359Sroberto * Just add adjustment into the current offset. The update 209254359Sroberto * routine will take care of bringing the system clock into 209354359Sroberto * line. 209454359Sroberto */ 209554359Sroberto#endif 209654359Sroberto if (debug) 209754359Sroberto return 1; 209854359Sroberto#ifdef FORCE_NTPDATE_STEP 209954359Sroberto LFPTOD(ts, dtemp); 210054359Sroberto return step_systime(dtemp); 210154359Sroberto#else 210254359Sroberto l_adj_systime(ts); 210354359Sroberto return 1; 210454359Sroberto#endif 2105182007Sroberto#else /* SLEWALWAYS */ 210654359Sroberto if (debug) 210754359Sroberto return 1; 210854359Sroberto LFPTOD(ts, dtemp); 210954359Sroberto return step_systime(dtemp); 211054359Sroberto#endif /* SLEWALWAYS */ 211154359Sroberto} 211254359Sroberto 211354359Sroberto 211454359Sroberto/* XXX ELIMINATE printserver similar in ntptrace.c, ntpdate.c */ 211554359Sroberto/* 211654359Sroberto * printserver - print detail information for a server 211754359Sroberto */ 211854359Srobertostatic void 211954359Srobertoprintserver( 212054359Sroberto register struct server *pp, 212154359Sroberto FILE *fp 212254359Sroberto ) 212354359Sroberto{ 212454359Sroberto register int i; 212554359Sroberto char junk[5]; 2126290001Sglebius const char *str; 212754359Sroberto 212854359Sroberto if (!debug) { 212954359Sroberto (void) fprintf(fp, "server %s, stratum %d, offset %s, delay %s\n", 2130132451Sroberto stoa(&pp->srcadr), pp->stratum, 213154359Sroberto lfptoa(&pp->offset, 6), fptoa((s_fp)pp->delay, 5)); 213254359Sroberto return; 213354359Sroberto } 213454359Sroberto 213554359Sroberto (void) fprintf(fp, "server %s, port %d\n", 2136132451Sroberto stoa(&pp->srcadr), ntohs(((struct sockaddr_in*)&(pp->srcadr))->sin_port)); 213754359Sroberto 213854359Sroberto (void) fprintf(fp, "stratum %d, precision %d, leap %c%c, trust %03o\n", 213954359Sroberto pp->stratum, pp->precision, 214054359Sroberto pp->leap & 0x2 ? '1' : '0', 214154359Sroberto pp->leap & 0x1 ? '1' : '0', 214254359Sroberto pp->trust); 214354359Sroberto 214454359Sroberto if (pp->stratum == 1) { 214554359Sroberto junk[4] = 0; 214654359Sroberto memmove(junk, (char *)&pp->refid, 4); 214754359Sroberto str = junk; 214854359Sroberto } else { 2149132451Sroberto str = stoa(&pp->srcadr); 215054359Sroberto } 215154359Sroberto (void) fprintf(fp, 215254359Sroberto "refid [%s], delay %s, dispersion %s\n", 215354359Sroberto str, fptoa((s_fp)pp->delay, 5), 215454359Sroberto ufptoa(pp->dispersion, 5)); 215554359Sroberto 215654359Sroberto (void) fprintf(fp, "transmitted %d, in filter %d\n", 215754359Sroberto pp->xmtcnt, pp->filter_nextpt); 215854359Sroberto 215954359Sroberto (void) fprintf(fp, "reference time: %s\n", 216054359Sroberto prettydate(&pp->reftime)); 216154359Sroberto (void) fprintf(fp, "originate timestamp: %s\n", 216254359Sroberto prettydate(&pp->org)); 216354359Sroberto (void) fprintf(fp, "transmit timestamp: %s\n", 216454359Sroberto prettydate(&pp->xmt)); 216554359Sroberto 216654359Sroberto (void) fprintf(fp, "filter delay: "); 216754359Sroberto for (i = 0; i < NTP_SHIFT; i++) { 216854359Sroberto (void) fprintf(fp, " %-8.8s", fptoa(pp->filter_delay[i], 5)); 216954359Sroberto if (i == (NTP_SHIFT>>1)-1) 217054359Sroberto (void) fprintf(fp, "\n "); 217154359Sroberto } 217254359Sroberto (void) fprintf(fp, "\n"); 217354359Sroberto 217454359Sroberto (void) fprintf(fp, "filter offset:"); 217554359Sroberto for (i = 0; i < PEER_SHIFT; i++) { 217654359Sroberto (void) fprintf(fp, " %-8.8s", lfptoa(&pp->filter_offset[i], 6)); 217754359Sroberto if (i == (PEER_SHIFT>>1)-1) 217854359Sroberto (void) fprintf(fp, "\n "); 217954359Sroberto } 218054359Sroberto (void) fprintf(fp, "\n"); 218154359Sroberto 218254359Sroberto (void) fprintf(fp, "delay %s, dispersion %s\n", 218354359Sroberto fptoa((s_fp)pp->delay, 5), ufptoa(pp->dispersion, 5)); 218454359Sroberto 218554359Sroberto (void) fprintf(fp, "offset %s\n\n", 218654359Sroberto lfptoa(&pp->offset, 6)); 218754359Sroberto} 218854359Sroberto 218954359Sroberto 219054359Sroberto#ifdef HAVE_NETINFO 219154359Srobertostatic ni_namelist * 219254359Srobertogetnetinfoservers(void) 219354359Sroberto{ 219454359Sroberto ni_status status; 219554359Sroberto void *domain; 219654359Sroberto ni_id confdir; 2197290001Sglebius ni_namelist *namelist = emalloc(sizeof(ni_namelist)); 219854359Sroberto 219954359Sroberto /* Find a time server in NetInfo */ 220054359Sroberto if ((status = ni_open(NULL, ".", &domain)) != NI_OK) return NULL; 220154359Sroberto 220254359Sroberto while (status = ni_pathsearch(domain, &confdir, NETINFO_CONFIG_DIR) == NI_NODIR) { 220354359Sroberto void *next_domain; 220454359Sroberto if (ni_open(domain, "..", &next_domain) != NI_OK) break; 220554359Sroberto ni_free(domain); 220654359Sroberto domain = next_domain; 220754359Sroberto } 220854359Sroberto if (status != NI_OK) return NULL; 220954359Sroberto 221054359Sroberto NI_INIT(namelist); 221154359Sroberto if (ni_lookupprop(domain, &confdir, "server", namelist) != NI_OK) { 221254359Sroberto ni_namelist_free(namelist); 221354359Sroberto free(namelist); 221454359Sroberto return NULL; 221554359Sroberto } 221654359Sroberto 221754359Sroberto return(namelist); 221854359Sroberto} 221954359Sroberto#endif 2220182007Sroberto 2221182007Sroberto#ifdef SYS_WINNT 2222182007Srobertoisc_boolean_t ntp_port_inuse(int af, u_short port) 2223182007Sroberto{ 2224182007Sroberto /* 2225182007Sroberto * Check if NTP socket is already in use on this system 2226182007Sroberto * This is only for Windows Systems, as they tend not to fail on the real bind() below 2227182007Sroberto */ 2228182007Sroberto 2229182007Sroberto SOCKET checksocket; 2230182007Sroberto struct sockaddr_in checkservice; 2231182007Sroberto checksocket = socket(af, SOCK_DGRAM, 0); 2232182007Sroberto if (checksocket == INVALID_SOCKET) { 2233182007Sroberto return (ISC_TRUE); 2234182007Sroberto } 2235182007Sroberto 2236182007Sroberto checkservice.sin_family = (short) AF_INET; 2237182007Sroberto checkservice.sin_addr.s_addr = INADDR_LOOPBACK; 2238182007Sroberto checkservice.sin_port = htons(port); 2239182007Sroberto 2240182007Sroberto if (bind(checksocket, (struct sockaddr *)&checkservice, 2241182007Sroberto sizeof(checkservice)) == SOCKET_ERROR) { 2242182007Sroberto if ( WSAGetLastError() == WSAEADDRINUSE ){ 2243182007Sroberto closesocket(checksocket); 2244182007Sroberto return (ISC_TRUE); 2245182007Sroberto } 2246182007Sroberto } 2247182007Sroberto closesocket(checksocket); 2248182007Sroberto return (ISC_FALSE); 2249182007Sroberto} 2250182007Sroberto#endif 2251