ntpdate.c revision 132451
154359Sroberto/* 254359Sroberto * ntpdate - set the time of day by polling one or more NTP servers 354359Sroberto */ 454359Sroberto 554359Sroberto#ifdef HAVE_CONFIG_H 654359Sroberto# include <config.h> 754359Sroberto#endif 854359Sroberto 982498Sroberto#ifdef HAVE_NETINFO 1082498Sroberto#include <netinfo/ni.h> 1154359Sroberto#endif 1282498Sroberto 13106163Sroberto#include "ntp_machine.h" 1482498Sroberto#include "ntp_fp.h" 1582498Sroberto#include "ntp.h" 1682498Sroberto#include "ntp_io.h" 1782498Sroberto#include "ntp_unixtime.h" 1882498Sroberto#include "ntpdate.h" 1982498Sroberto#include "ntp_string.h" 2082498Sroberto#include "ntp_syslog.h" 2182498Sroberto#include "ntp_select.h" 2282498Sroberto#include "ntp_stdlib.h" 2382498Sroberto 2454359Sroberto#ifdef HAVE_UNISTD_H 2554359Sroberto# include <unistd.h> 2654359Sroberto#endif 2754359Sroberto 2854359Sroberto#include <stdio.h> 2954359Sroberto#include <signal.h> 3054359Sroberto#include <ctype.h> 3154359Sroberto#ifdef HAVE_POLL_H 3282498Sroberto# include <poll.h> 3354359Sroberto#endif 3454359Sroberto#ifndef SYS_WINNT 3554359Sroberto# include <netdb.h> 36106163Sroberto# ifdef HAVE_SYS_SIGNAL_H 37106163Sroberto# include <sys/signal.h> 38106163Sroberto# else 39106163Sroberto# include <signal.h> 40106163Sroberto# endif 4182498Sroberto# ifdef HAVE_SYS_IOCTL_H 4282498Sroberto# include <sys/ioctl.h> 4382498Sroberto# endif 4454359Sroberto#endif /* SYS_WINNT */ 4554359Sroberto#ifdef HAVE_SYS_RESOURCE_H 4654359Sroberto# include <sys/resource.h> 4754359Sroberto#endif /* HAVE_SYS_RESOURCE_H */ 4854359Sroberto 49132451Sroberto#include <arpa/inet.h> 50132451Sroberto 51132451Sroberto#ifdef __QNXNTO__ 52132451Sroberto# include "adjtime.h" 53132451Sroberto#endif 54132451Sroberto 5554359Sroberto#ifdef SYS_VXWORKS 5654359Sroberto# include "ioLib.h" 5754359Sroberto# include "sockLib.h" 5854359Sroberto# include "timers.h" 5954359Sroberto 6054359Sroberto/* select wants a zero structure ... */ 6154359Srobertostruct timeval timeout = {0,0}; 6254359Sroberto#else 6354359Srobertostruct timeval timeout = {60,0}; 6454359Sroberto#endif 6554359Sroberto 66132451Sroberto#ifdef HAVE_NETINFO 67132451Sroberto#include <netinfo/ni.h> 68132451Sroberto#endif 69132451Sroberto 7054359Sroberto#include "recvbuff.h" 7154359Sroberto 7254359Sroberto#ifdef SYS_WINNT 73132451Sroberto#define EPROTONOSUPPORT WSAEPROTONOSUPPORT 74132451Sroberto#define EAFNOSUPPORT WSAEAFNOSUPPORT 75132451Sroberto#define EPFNOSUPPORT WSAEPFNOSUPPORT 76132451Sroberto#define TARGET_RESOLUTION 1 /* Try for 1-millisecond accuracy 7754359Sroberto on Windows NT timers. */ 7854359Sroberto#pragma comment(lib, "winmm") 7954359Sroberto#endif /* SYS_WINNT */ 8054359Sroberto 8154359Sroberto/* 8254359Sroberto * Scheduling priority we run at 8354359Sroberto */ 8454359Sroberto#ifndef SYS_VXWORKS 8554359Sroberto# define NTPDATE_PRIO (-12) 8654359Sroberto#else 8754359Sroberto# define NTPDATE_PRIO (100) 8854359Sroberto#endif 8954359Sroberto 9054359Sroberto#if defined(HAVE_TIMER_SETTIME) || defined (HAVE_TIMER_CREATE) 9154359Sroberto/* POSIX TIMERS - vxWorks doesn't have itimer - casey */ 9254359Srobertostatic timer_t ntpdate_timerid; 9354359Sroberto#endif 9454359Sroberto 9554359Sroberto/* 9654359Sroberto * Compatibility stuff for Version 2 9754359Sroberto */ 9854359Sroberto#define NTP_MAXSKW 0x28f /* 0.01 sec in fp format */ 9954359Sroberto#define NTP_MINDIST 0x51f /* 0.02 sec in fp format */ 10054359Sroberto#define PEER_MAXDISP (64*FP_SECOND) /* maximum dispersion (fp 64) */ 10154359Sroberto#define NTP_INFIN 15 /* max stratum, infinity a la Bellman-Ford */ 10254359Sroberto#define NTP_MAXWGT (8*FP_SECOND) /* maximum select weight 8 seconds */ 10354359Sroberto#define NTP_MAXLIST 5 /* maximum select list size */ 10454359Sroberto#define PEER_SHIFT 8 /* 8 suitable for crystal time base */ 10554359Sroberto 10654359Sroberto/* 10754359Sroberto * Debugging flag 10854359Sroberto */ 10954359Srobertovolatile int debug = 0; 11054359Sroberto 11154359Sroberto/* 11254359Sroberto * File descriptor masks etc. for call to select 11354359Sroberto */ 114132451Sroberto 115132451Srobertoint ai_fam_templ; 116132451Srobertoint nbsock; 117132451SrobertoSOCKET fd[MAX_AF]; /* support up to 2 sockets */ 118132451Srobertoint fd_family[MAX_AF]; /* to remember the socket family */ 11954359Sroberto#ifdef HAVE_POLL_H 120132451Srobertostruct pollfd fdmask[MAX_AF]; 12154359Sroberto#else 12254359Srobertofd_set fdmask; 123132451Srobertoint maxfd; 12454359Sroberto#endif 125132451Srobertoint polltest = 0; 12654359Sroberto 12754359Sroberto/* 12854359Sroberto * Initializing flag. All async routines watch this and only do their 12954359Sroberto * thing when it is clear. 13054359Sroberto */ 13154359Srobertoint initializing = 1; 13254359Sroberto 13354359Sroberto/* 13454359Sroberto * Alarm flag. Set when an alarm occurs 13554359Sroberto */ 13654359Srobertovolatile int alarm_flag = 0; 13754359Sroberto 13854359Sroberto/* 13954359Sroberto * Simple query flag. 14054359Sroberto */ 14154359Srobertoint simple_query = 0; 14254359Sroberto 14354359Sroberto/* 14454359Sroberto * Unpriviledged port flag. 14554359Sroberto */ 14654359Srobertoint unpriv_port = 0; 14754359Sroberto 14854359Sroberto/* 14954359Sroberto * Time to spend measuring drift rate 15054359Sroberto */ 15154359Srobertoint rate = 0; 15254359Sroberto 15354359Sroberto/* 15454359Sroberto * Program name. 15554359Sroberto */ 15654359Srobertochar *progname; 15754359Sroberto 15854359Sroberto/* 15954359Sroberto * Systemwide parameters and flags 16054359Sroberto */ 16154359Srobertoint sys_samples = DEFSAMPLES; /* number of samples/server */ 16254359Srobertou_long sys_timeout = DEFTIMEOUT; /* timeout time, in TIMER_HZ units */ 16356746Srobertostruct server *sys_servers; /* the server list */ 16454359Srobertoint sys_numservers = 0; /* number of servers to poll */ 16554359Srobertoint sys_authenticate = 0; /* true when authenticating */ 16654359Srobertou_int32 sys_authkey = 0; /* set to authentication key in use */ 16754359Srobertou_long sys_authdelay = 0; /* authentication delay */ 16854359Srobertoint sys_version = NTP_VERSION; /* version to poll with */ 16954359Sroberto 17054359Sroberto/* 17154359Sroberto * The current internal time 17254359Sroberto */ 17354359Srobertou_long current_time = 0; 17454359Sroberto 17554359Sroberto/* 17654359Sroberto * Counter for keeping track of completed servers 17754359Sroberto */ 17854359Srobertoint complete_servers = 0; 17954359Sroberto 18054359Sroberto/* 18154359Sroberto * File of encryption keys 18254359Sroberto */ 18354359Sroberto 18454359Sroberto#ifndef KEYFILE 18554359Sroberto# ifndef SYS_WINNT 18654359Sroberto#define KEYFILE "/etc/ntp.keys" 18754359Sroberto# else 18854359Sroberto#define KEYFILE "%windir%\\ntp.keys" 18954359Sroberto# endif /* SYS_WINNT */ 19054359Sroberto#endif /* KEYFILE */ 19154359Sroberto 19254359Sroberto#ifndef SYS_WINNT 19354359Srobertoconst char *key_file = KEYFILE; 19454359Sroberto#else 19554359Srobertochar key_file_storage[MAX_PATH+1], *key_file ; 19654359Sroberto#endif /* SYS_WINNT */ 19754359Sroberto 19854359Sroberto/* 19954359Sroberto * Miscellaneous flags 20054359Sroberto */ 20154359Srobertoint verbose = 0; 20254359Srobertoint always_step = 0; 20354359Srobertoint never_step = 0; 20454359Sroberto 20554359Srobertoint ntpdatemain P((int, char **)); 206132451Sroberto 20754359Srobertostatic void transmit P((struct server *)); 20854359Srobertostatic void receive P((struct recvbuf *)); 20954359Srobertostatic void server_data P((struct server *, s_fp, l_fp *, u_fp)); 21054359Srobertostatic void clock_filter P((struct server *)); 21154359Srobertostatic struct server *clock_select P((void)); 21254359Srobertostatic int clock_adjust P((void)); 21354359Srobertostatic void addserver P((char *)); 214132451Srobertostatic struct server *findserver P((struct sockaddr_storage *)); 21554359Sroberto void timer P((void)); 21654359Srobertostatic void init_alarm P((void)); 21754359Sroberto#ifndef SYS_WINNT 21854359Srobertostatic RETSIGTYPE alarming P((int)); 21954359Sroberto#endif /* SYS_WINNT */ 22054359Srobertostatic void init_io P((void)); 221132451Srobertostatic void sendpkt P((struct sockaddr_storage *, struct pkt *, int)); 22254359Srobertovoid input_handler P((void)); 22354359Sroberto 22454359Srobertostatic int l_adj_systime P((l_fp *)); 22554359Srobertostatic int l_step_systime P((l_fp *)); 22654359Sroberto 22754359Srobertostatic void printserver P((struct server *, FILE *)); 22854359Sroberto 22954359Sroberto#ifdef SYS_WINNT 23054359Srobertoint on = 1; 23154359SrobertoWORD wVersionRequested; 23254359SrobertoWSADATA wsaData; 23354359SrobertoHANDLE TimerThreadHandle = NULL; 23454359Sroberto#endif /* SYS_WINNT */ 23554359Sroberto 23654359Sroberto#ifdef NO_MAIN_ALLOWED 23754359SrobertoCALL(ntpdate,"ntpdate",ntpdatemain); 23854359Sroberto 23954359Srobertovoid clear_globals() 24054359Sroberto{ 24154359Sroberto /* 24254359Sroberto * Debugging flag 24354359Sroberto */ 24454359Sroberto debug = 0; 24554359Sroberto 24654359Sroberto ntp_optind = 0; 24754359Sroberto /* 24854359Sroberto * Initializing flag. All async routines watch this and only do their 24954359Sroberto * thing when it is clear. 25054359Sroberto */ 25154359Sroberto initializing = 1; 25254359Sroberto 25354359Sroberto /* 25454359Sroberto * Alarm flag. Set when an alarm occurs 25554359Sroberto */ 25654359Sroberto alarm_flag = 0; 25754359Sroberto 25854359Sroberto /* 25954359Sroberto * Simple query flag. 26054359Sroberto */ 26154359Sroberto simple_query = 0; 26254359Sroberto 26354359Sroberto /* 26454359Sroberto * Unpriviledged port flag. 26554359Sroberto */ 26654359Sroberto unpriv_port = 0; 26754359Sroberto 26854359Sroberto /* 26954359Sroberto * Time to spend measuring drift rate 27054359Sroberto */ 27154359Sroberto rate = 0; 27254359Sroberto /* 27354359Sroberto * Systemwide parameters and flags 27454359Sroberto */ 27554359Sroberto sys_numservers = 0; /* number of servers to poll */ 27654359Sroberto sys_authenticate = 0; /* true when authenticating */ 27754359Sroberto sys_authkey = 0; /* set to authentication key in use */ 27854359Sroberto sys_authdelay = 0; /* authentication delay */ 27954359Sroberto sys_version = NTP_VERSION; /* version to poll with */ 28054359Sroberto 28154359Sroberto /* 28254359Sroberto * The current internal time 28354359Sroberto */ 28454359Sroberto current_time = 0; 28554359Sroberto 28654359Sroberto /* 28754359Sroberto * Counter for keeping track of completed servers 28854359Sroberto */ 28954359Sroberto complete_servers = 0; 29054359Sroberto verbose = 0; 29154359Sroberto always_step = 0; 29254359Sroberto never_step = 0; 29354359Sroberto} 29454359Sroberto#endif 29554359Sroberto 29654359Sroberto#ifdef HAVE_NETINFO 29754359Srobertostatic ni_namelist *getnetinfoservers P((void)); 29854359Sroberto#endif 29954359Sroberto 30054359Sroberto/* 30154359Sroberto * Main program. Initialize us and loop waiting for I/O and/or 30254359Sroberto * timer expiries. 30354359Sroberto */ 30454359Sroberto#ifndef NO_MAIN_ALLOWED 30554359Srobertoint 30654359Srobertomain( 30754359Sroberto int argc, 30854359Sroberto char *argv[] 30954359Sroberto ) 31054359Sroberto{ 31154359Sroberto return ntpdatemain (argc, argv); 31254359Sroberto} 31354359Sroberto#endif /* NO_MAIN_ALLOWED */ 31454359Sroberto 31554359Srobertoint 31654359Srobertontpdatemain ( 31754359Sroberto int argc, 31854359Sroberto char *argv[] 31954359Sroberto ) 32054359Sroberto{ 32154359Sroberto int was_alarmed; 32254359Sroberto struct recvbuf *rbuflist; 32354359Sroberto struct recvbuf *rbuf; 32454359Sroberto l_fp tmp; 32554359Sroberto int errflg; 32654359Sroberto int c; 327132451Sroberto int nfound; 328132451Sroberto 32954359Sroberto#ifdef HAVE_NETINFO 33054359Sroberto ni_namelist *netinfoservers; 33154359Sroberto#endif 33254359Sroberto#ifdef SYS_WINNT 33354359Sroberto HANDLE process_handle; 33454359Sroberto 33554359Sroberto wVersionRequested = MAKEWORD(1,1); 33654359Sroberto if (WSAStartup(wVersionRequested, &wsaData)) { 337132451Sroberto netsyslog(LOG_ERR, "No useable winsock.dll: %m"); 33854359Sroberto exit(1); 33954359Sroberto } 34054359Sroberto 34154359Sroberto key_file = key_file_storage; 34254359Sroberto 34354359Sroberto if (!ExpandEnvironmentStrings(KEYFILE, key_file, MAX_PATH)) 34454359Sroberto { 34554359Sroberto msyslog(LOG_ERR, "ExpandEnvironmentStrings(KEYFILE) failed: %m\n"); 34654359Sroberto } 34754359Sroberto#endif /* SYS_WINNT */ 34854359Sroberto 34954359Sroberto#ifdef NO_MAIN_ALLOWED 35054359Sroberto clear_globals(); 35154359Sroberto#endif 35254359Sroberto 35354359Sroberto errflg = 0; 35454359Sroberto progname = argv[0]; 35554359Sroberto syslogit = 0; 35654359Sroberto 35754359Sroberto /* 35854359Sroberto * Decode argument list 35954359Sroberto */ 360132451Sroberto while ((c = ntp_getopt(argc, argv, "46a:bBde:k:o:p:qr:st:uv")) != EOF) 36154359Sroberto switch (c) 36254359Sroberto { 363132451Sroberto case '4': 364132451Sroberto ai_fam_templ = AF_INET; 365132451Sroberto break; 366132451Sroberto case '6': 367132451Sroberto ai_fam_templ = AF_INET6; 368132451Sroberto break; 36954359Sroberto case 'a': 37054359Sroberto c = atoi(ntp_optarg); 37154359Sroberto sys_authenticate = 1; 37254359Sroberto sys_authkey = c; 37354359Sroberto break; 37454359Sroberto case 'b': 37554359Sroberto always_step++; 37654359Sroberto never_step = 0; 37754359Sroberto break; 37854359Sroberto case 'B': 37954359Sroberto never_step++; 38054359Sroberto always_step = 0; 38154359Sroberto break; 38254359Sroberto case 'd': 38354359Sroberto ++debug; 38454359Sroberto break; 38554359Sroberto case 'e': 38654359Sroberto if (!atolfp(ntp_optarg, &tmp) 38754359Sroberto || tmp.l_ui != 0) { 38854359Sroberto (void) fprintf(stderr, 38954359Sroberto "%s: encryption delay %s is unlikely\n", 39054359Sroberto progname, ntp_optarg); 39154359Sroberto errflg++; 39254359Sroberto } else { 39354359Sroberto sys_authdelay = tmp.l_uf; 39454359Sroberto } 39554359Sroberto break; 39654359Sroberto case 'k': 39754359Sroberto key_file = ntp_optarg; 39854359Sroberto break; 39954359Sroberto case 'o': 40054359Sroberto sys_version = atoi(ntp_optarg); 40154359Sroberto break; 40254359Sroberto case 'p': 40354359Sroberto c = atoi(ntp_optarg); 40454359Sroberto if (c <= 0 || c > NTP_SHIFT) { 40554359Sroberto (void) fprintf(stderr, 40654359Sroberto "%s: number of samples (%d) is invalid\n", 40754359Sroberto progname, c); 40854359Sroberto errflg++; 40954359Sroberto } else { 41054359Sroberto sys_samples = c; 41154359Sroberto } 41254359Sroberto break; 41354359Sroberto case 'q': 41454359Sroberto simple_query = 1; 41554359Sroberto break; 41654359Sroberto case 'r': 41754359Sroberto c = atoi(ntp_optarg); 41854359Sroberto if (c <= 0 || c > (60 * 60)) { 41954359Sroberto (void) fprintf(stderr, 42054359Sroberto "%s: rate (%d) is invalid: 0 - %d\n", 42154359Sroberto progname, c, (60 * 60)); 42254359Sroberto errflg++; 42354359Sroberto } else { 42454359Sroberto rate = c; 42554359Sroberto } 42654359Sroberto break; 42754359Sroberto case 's': 42854359Sroberto syslogit = 1; 42954359Sroberto break; 43054359Sroberto case 't': 43154359Sroberto if (!atolfp(ntp_optarg, &tmp)) { 43254359Sroberto (void) fprintf(stderr, 43354359Sroberto "%s: timeout %s is undecodeable\n", 43454359Sroberto progname, ntp_optarg); 43554359Sroberto errflg++; 43654359Sroberto } else { 43754359Sroberto sys_timeout = ((LFPTOFP(&tmp) * TIMER_HZ) 43854359Sroberto + 0x8000) >> 16; 43954359Sroberto if (sys_timeout == 0) 44054359Sroberto sys_timeout = 1; 44154359Sroberto } 44254359Sroberto break; 44354359Sroberto case 'v': 44454359Sroberto verbose = 1; 44554359Sroberto break; 44654359Sroberto case 'u': 44754359Sroberto unpriv_port = 1; 44854359Sroberto break; 44954359Sroberto case '?': 45054359Sroberto ++errflg; 45154359Sroberto break; 45254359Sroberto default: 45354359Sroberto break; 45454359Sroberto } 45554359Sroberto 45654359Sroberto if (errflg) { 45754359Sroberto (void) fprintf(stderr, 458132451Sroberto "usage: %s [-46bBdqsuv] [-a key#] [-e delay] [-k file] [-p samples] [-o version#] [-r rate] [-t timeo] server ...\n", 459132451Sroberto progname); 46054359Sroberto exit(2); 46154359Sroberto } 46254359Sroberto 46354359Sroberto if (debug || simple_query) { 46454359Sroberto#ifdef HAVE_SETVBUF 46554359Sroberto static char buf[BUFSIZ]; 46654359Sroberto setvbuf(stdout, buf, _IOLBF, BUFSIZ); 46754359Sroberto#else 46854359Sroberto setlinebuf(stdout); 46954359Sroberto#endif 47054359Sroberto } 47154359Sroberto 47254359Sroberto /* 47354359Sroberto * Logging. Open the syslog if we have to 47454359Sroberto */ 47554359Sroberto if (syslogit) { 47654359Sroberto#if !defined (SYS_WINNT) && !defined (SYS_VXWORKS) && !defined SYS_CYGWIN32 47754359Sroberto# ifndef LOG_DAEMON 47854359Sroberto openlog("ntpdate", LOG_PID); 47954359Sroberto# else 48054359Sroberto 48154359Sroberto# ifndef LOG_NTP 48254359Sroberto# define LOG_NTP LOG_DAEMON 48354359Sroberto# endif 48454359Sroberto openlog("ntpdate", LOG_PID | LOG_NDELAY, LOG_NTP); 48554359Sroberto if (debug) 48654359Sroberto setlogmask(LOG_UPTO(LOG_DEBUG)); 48754359Sroberto else 48854359Sroberto setlogmask(LOG_UPTO(LOG_INFO)); 48954359Sroberto# endif /* LOG_DAEMON */ 49054359Sroberto#endif /* SYS_WINNT */ 49154359Sroberto } 49254359Sroberto 49354359Sroberto if (debug || verbose) 49454359Sroberto msyslog(LOG_NOTICE, "%s", Version); 49554359Sroberto 49654359Sroberto /* 49754359Sroberto * Add servers we are going to be polling 49854359Sroberto */ 49954359Sroberto#ifdef HAVE_NETINFO 50082498Sroberto netinfoservers = getnetinfoservers(); 50154359Sroberto#endif 50254359Sroberto 50354359Sroberto for ( ; ntp_optind < argc; ntp_optind++) 50454359Sroberto addserver(argv[ntp_optind]); 50554359Sroberto 50654359Sroberto#ifdef HAVE_NETINFO 50754359Sroberto if (netinfoservers) { 50854359Sroberto if ( netinfoservers->ni_namelist_len && 50954359Sroberto *netinfoservers->ni_namelist_val ) { 51054359Sroberto u_int servercount = 0; 51154359Sroberto while (servercount < netinfoservers->ni_namelist_len) { 51254359Sroberto if (debug) msyslog(LOG_DEBUG, 51354359Sroberto "Adding time server %s from NetInfo configuration.", 51454359Sroberto netinfoservers->ni_namelist_val[servercount]); 51554359Sroberto addserver(netinfoservers->ni_namelist_val[servercount++]); 51654359Sroberto } 51754359Sroberto } 51854359Sroberto ni_namelist_free(netinfoservers); 51954359Sroberto free(netinfoservers); 52054359Sroberto } 52154359Sroberto#endif 52254359Sroberto 52354359Sroberto if (sys_numservers == 0) { 52454359Sroberto msyslog(LOG_ERR, "no servers can be used, exiting"); 52554359Sroberto exit(1); 52654359Sroberto } 52754359Sroberto 52854359Sroberto /* 52954359Sroberto * Initialize the time of day routines and the I/O subsystem 53054359Sroberto */ 53154359Sroberto if (sys_authenticate) { 53254359Sroberto init_auth(); 53354359Sroberto if (!authreadkeys(key_file)) { 53482498Sroberto msyslog(LOG_ERR, "no key file <%s>, exiting", key_file); 53554359Sroberto exit(1); 53654359Sroberto } 53782498Sroberto authtrust(sys_authkey, 1); 53854359Sroberto if (!authistrusted(sys_authkey)) { 53954359Sroberto char buf[10]; 54054359Sroberto 54154359Sroberto (void) sprintf(buf, "%lu", (unsigned long)sys_authkey); 54254359Sroberto msyslog(LOG_ERR, "authentication key %s unknown", buf); 54354359Sroberto exit(1); 54454359Sroberto } 54554359Sroberto } 54654359Sroberto init_io(); 54754359Sroberto init_alarm(); 54854359Sroberto 54954359Sroberto /* 55054359Sroberto * Set the priority. 55154359Sroberto */ 55254359Sroberto#ifdef SYS_VXWORKS 55354359Sroberto taskPrioritySet( taskIdSelf(), NTPDATE_PRIO); 55454359Sroberto#endif 55554359Sroberto#if defined(HAVE_ATT_NICE) 55654359Sroberto nice (NTPDATE_PRIO); 55754359Sroberto#endif 55854359Sroberto#if defined(HAVE_BSD_NICE) 55954359Sroberto (void) setpriority(PRIO_PROCESS, 0, NTPDATE_PRIO); 56054359Sroberto#endif 56154359Sroberto#ifdef SYS_WINNT 56254359Sroberto process_handle = GetCurrentProcess(); 56354359Sroberto if (!SetPriorityClass(process_handle, (DWORD) REALTIME_PRIORITY_CLASS)) { 56454359Sroberto msyslog(LOG_ERR, "SetPriorityClass failed: %m"); 56554359Sroberto } 56654359Sroberto#endif /* SYS_WINNT */ 56754359Sroberto 568132451Sroberto 569132451Sroberto 57054359Sroberto initializing = 0; 57154359Sroberto was_alarmed = 0; 57254359Sroberto rbuflist = (struct recvbuf *)0; 573132451Sroberto 57454359Sroberto while (complete_servers < sys_numservers) { 57554359Sroberto#ifdef HAVE_POLL_H 576132451Sroberto struct pollfd* rdfdes; 577132451Sroberto rdfdes = fdmask; 57854359Sroberto#else 57954359Sroberto fd_set rdfdes; 580132451Sroberto rdfdes = fdmask; 58154359Sroberto#endif 58254359Sroberto 58354359Sroberto if (alarm_flag) { /* alarmed? */ 58454359Sroberto was_alarmed = 1; 58554359Sroberto alarm_flag = 0; 58654359Sroberto } 58754359Sroberto rbuflist = getrecvbufs(); /* get received buffers */ 58854359Sroberto 58954359Sroberto if (!was_alarmed && rbuflist == (struct recvbuf *)0) { 59054359Sroberto /* 59154359Sroberto * Nothing to do. Wait for something. 59254359Sroberto */ 59354359Sroberto#ifdef HAVE_POLL_H 594132451Sroberto nfound = poll(rdfdes, (unsigned int)nbsock, timeout.tv_sec * 1000); 595132451Sroberto 59654359Sroberto#else 597132451Sroberto nfound = select(maxfd, &rdfdes, (fd_set *)0, 59854359Sroberto (fd_set *)0, &timeout); 59954359Sroberto#endif 60054359Sroberto if (nfound > 0) 60154359Sroberto input_handler(); 60254359Sroberto else if ( 60354359Sroberto#ifndef SYS_WINNT 60454359Sroberto nfound == -1 60554359Sroberto#else 60654359Sroberto nfound == SOCKET_ERROR 60754359Sroberto#endif /* SYS_WINNT */ 60854359Sroberto ) { 60954359Sroberto#ifndef SYS_WINNT 61054359Sroberto if (errno != EINTR) 61154359Sroberto#endif 612132451Sroberto netsyslog(LOG_ERR, 61354359Sroberto#ifdef HAVE_POLL_H 61454359Sroberto "poll() error: %m" 61554359Sroberto#else 61654359Sroberto "select() error: %m" 61754359Sroberto#endif 61854359Sroberto ); 61954359Sroberto } else { 62054359Sroberto#ifndef SYS_VXWORKS 621132451Sroberto netsyslog(LOG_DEBUG, 62254359Sroberto#ifdef HAVE_POLL_H 62354359Sroberto "poll(): nfound = %d, error: %m", 62454359Sroberto#else 62554359Sroberto "select(): nfound = %d, error: %m", 62654359Sroberto#endif 62754359Sroberto nfound); 62854359Sroberto#endif 62954359Sroberto } 63054359Sroberto if (alarm_flag) { /* alarmed? */ 63154359Sroberto was_alarmed = 1; 63254359Sroberto alarm_flag = 0; 63354359Sroberto } 63454359Sroberto rbuflist = getrecvbufs(); /* get received buffers */ 63554359Sroberto } 63654359Sroberto 63754359Sroberto /* 63854359Sroberto * Out here, signals are unblocked. Call receive 63954359Sroberto * procedure for each incoming packet. 64054359Sroberto */ 64154359Sroberto while (rbuflist != (struct recvbuf *)0) { 64254359Sroberto rbuf = rbuflist; 64354359Sroberto rbuflist = rbuf->next; 64454359Sroberto receive(rbuf); 64554359Sroberto freerecvbuf(rbuf); 64654359Sroberto } 64754359Sroberto 64854359Sroberto /* 64954359Sroberto * Call timer to process any timeouts 65054359Sroberto */ 65154359Sroberto if (was_alarmed) { 65254359Sroberto timer(); 65354359Sroberto was_alarmed = 0; 65454359Sroberto } 65554359Sroberto 65654359Sroberto /* 65754359Sroberto * Go around again 65854359Sroberto */ 65954359Sroberto } 66054359Sroberto 66154359Sroberto /* 66254359Sroberto * When we get here we've completed the polling of all servers. 66354359Sroberto * Adjust the clock, then exit. 66454359Sroberto */ 66554359Sroberto#ifdef SYS_WINNT 66654359Sroberto WSACleanup(); 66754359Sroberto#endif 66854359Sroberto#ifdef SYS_VXWORKS 66954359Sroberto close (fd); 67054359Sroberto timer_delete(ntpdate_timerid); 67154359Sroberto#endif 672132451Sroberto 67354359Sroberto return clock_adjust(); 67454359Sroberto} 67554359Sroberto 67654359Sroberto 67754359Sroberto/* 67854359Sroberto * transmit - transmit a packet to the given server, or mark it completed. 67954359Sroberto * This is called by the timeout routine and by the receive 68054359Sroberto * procedure. 68154359Sroberto */ 68254359Srobertostatic void 68354359Srobertotransmit( 68454359Sroberto register struct server *server 68554359Sroberto ) 68654359Sroberto{ 68754359Sroberto struct pkt xpkt; 68854359Sroberto 68954359Sroberto if (debug) 690132451Sroberto printf("transmit(%s)\n", stoa(&(server->srcadr))); 69154359Sroberto 69254359Sroberto if (server->filter_nextpt < server->xmtcnt) { 69354359Sroberto l_fp ts; 69454359Sroberto /* 69554359Sroberto * Last message to this server timed out. Shift 69654359Sroberto * zeros into the filter. 69754359Sroberto */ 69854359Sroberto L_CLR(&ts); 69954359Sroberto server_data(server, 0, &ts, 0); 70054359Sroberto } 70154359Sroberto 70254359Sroberto if ((int)server->filter_nextpt >= sys_samples) { 70354359Sroberto /* 70454359Sroberto * Got all the data we need. Mark this guy 70554359Sroberto * completed and return. 70654359Sroberto */ 70754359Sroberto server->event_time = 0; 70854359Sroberto complete_servers++; 70954359Sroberto return; 71054359Sroberto } 71154359Sroberto 71254359Sroberto /* 71354359Sroberto * If we're here, send another message to the server. Fill in 71454359Sroberto * the packet and let 'er rip. 71554359Sroberto */ 71654359Sroberto xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC, 71754359Sroberto sys_version, MODE_CLIENT); 71854359Sroberto xpkt.stratum = STRATUM_TO_PKT(STRATUM_UNSPEC); 71954359Sroberto xpkt.ppoll = NTP_MINPOLL; 72054359Sroberto xpkt.precision = NTPDATE_PRECISION; 72154359Sroberto xpkt.rootdelay = htonl(NTPDATE_DISTANCE); 72254359Sroberto xpkt.rootdispersion = htonl(NTPDATE_DISP); 72354359Sroberto xpkt.refid = htonl(NTPDATE_REFID); 72454359Sroberto L_CLR(&xpkt.reftime); 72554359Sroberto L_CLR(&xpkt.org); 72654359Sroberto L_CLR(&xpkt.rec); 72754359Sroberto 72854359Sroberto /* 72954359Sroberto * Determine whether to authenticate or not. If so, 73054359Sroberto * fill in the extended part of the packet and do it. 73154359Sroberto * If not, just timestamp it and send it away. 73254359Sroberto */ 73354359Sroberto if (sys_authenticate) { 73454359Sroberto int len; 73554359Sroberto 73682498Sroberto xpkt.exten[0] = htonl(sys_authkey); 73754359Sroberto get_systime(&server->xmt); 73854359Sroberto L_ADDUF(&server->xmt, sys_authdelay); 73954359Sroberto HTONL_FP(&server->xmt, &xpkt.xmt); 74054359Sroberto len = authencrypt(sys_authkey, (u_int32 *)&xpkt, LEN_PKT_NOMAC); 74154359Sroberto sendpkt(&(server->srcadr), &xpkt, (int)(LEN_PKT_NOMAC + len)); 74254359Sroberto 74354359Sroberto if (debug > 1) 74454359Sroberto printf("transmit auth to %s\n", 745132451Sroberto stoa(&(server->srcadr))); 74654359Sroberto } else { 74754359Sroberto get_systime(&(server->xmt)); 74854359Sroberto HTONL_FP(&server->xmt, &xpkt.xmt); 74954359Sroberto sendpkt(&(server->srcadr), &xpkt, LEN_PKT_NOMAC); 75054359Sroberto 75154359Sroberto if (debug > 1) 752132451Sroberto printf("transmit to %s\n", stoa(&(server->srcadr))); 75354359Sroberto } 75454359Sroberto 75554359Sroberto /* 75654359Sroberto * Update the server timeout and transmit count 75754359Sroberto */ 75854359Sroberto server->event_time = current_time + sys_timeout; 75954359Sroberto server->xmtcnt++; 76054359Sroberto} 76154359Sroberto 76254359Sroberto 76354359Sroberto/* 76454359Sroberto * receive - receive and process an incoming frame 76554359Sroberto */ 76654359Srobertostatic void 76754359Srobertoreceive( 76854359Sroberto struct recvbuf *rbufp 76954359Sroberto ) 77054359Sroberto{ 77154359Sroberto register struct pkt *rpkt; 77254359Sroberto register struct server *server; 77354359Sroberto register s_fp di; 774106163Sroberto l_fp t10, t23, tmp; 77554359Sroberto l_fp org; 77654359Sroberto l_fp rec; 77754359Sroberto l_fp ci; 77854359Sroberto int has_mac; 77954359Sroberto int is_authentic; 78054359Sroberto 78154359Sroberto if (debug) 782132451Sroberto printf("receive(%s)\n", stoa(&rbufp->recv_srcadr)); 78354359Sroberto /* 78454359Sroberto * Check to see if the packet basically looks like something 78554359Sroberto * intended for us. 78654359Sroberto */ 78754359Sroberto if (rbufp->recv_length == LEN_PKT_NOMAC) 78854359Sroberto has_mac = 0; 78954359Sroberto else if (rbufp->recv_length >= LEN_PKT_NOMAC) 79054359Sroberto has_mac = 1; 79154359Sroberto else { 79254359Sroberto if (debug) 79354359Sroberto printf("receive: packet length %d\n", 79454359Sroberto rbufp->recv_length); 79554359Sroberto return; /* funny length packet */ 79654359Sroberto } 79754359Sroberto 79854359Sroberto rpkt = &(rbufp->recv_pkt); 79954359Sroberto if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION || 80054359Sroberto PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) { 80154359Sroberto return; 80254359Sroberto } 80354359Sroberto 80454359Sroberto if ((PKT_MODE(rpkt->li_vn_mode) != MODE_SERVER 80554359Sroberto && PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE) 80682498Sroberto || rpkt->stratum >= STRATUM_UNSPEC) { 80754359Sroberto if (debug) 80854359Sroberto printf("receive: mode %d stratum %d\n", 80954359Sroberto PKT_MODE(rpkt->li_vn_mode), rpkt->stratum); 81054359Sroberto return; 81154359Sroberto } 81254359Sroberto 81354359Sroberto /* 81454359Sroberto * So far, so good. See if this is from a server we know. 81554359Sroberto */ 81654359Sroberto server = findserver(&(rbufp->recv_srcadr)); 81754359Sroberto if (server == NULL) { 81854359Sroberto if (debug) 81954359Sroberto printf("receive: server not found\n"); 82054359Sroberto return; 82154359Sroberto } 82254359Sroberto 82354359Sroberto /* 82454359Sroberto * Decode the org timestamp and make sure we're getting a response 82554359Sroberto * to our last request. 82654359Sroberto */ 82754359Sroberto NTOHL_FP(&rpkt->org, &org); 82854359Sroberto if (!L_ISEQU(&org, &server->xmt)) { 82954359Sroberto if (debug) 83054359Sroberto printf("receive: pkt.org and peer.xmt differ\n"); 83154359Sroberto return; 83254359Sroberto } 83354359Sroberto 83454359Sroberto /* 83554359Sroberto * Check out the authenticity if we're doing that. 83654359Sroberto */ 83754359Sroberto if (!sys_authenticate) 83854359Sroberto is_authentic = 1; 83954359Sroberto else { 84054359Sroberto is_authentic = 0; 84154359Sroberto 84254359Sroberto if (debug > 3) 84354359Sroberto printf("receive: rpkt keyid=%ld sys_authkey=%ld decrypt=%ld\n", 84482498Sroberto (long int)ntohl(rpkt->exten[0]), (long int)sys_authkey, 84554359Sroberto (long int)authdecrypt(sys_authkey, (u_int32 *)rpkt, 84654359Sroberto LEN_PKT_NOMAC, (int)(rbufp->recv_length - LEN_PKT_NOMAC))); 84754359Sroberto 84882498Sroberto if (has_mac && ntohl(rpkt->exten[0]) == sys_authkey && 84954359Sroberto authdecrypt(sys_authkey, (u_int32 *)rpkt, LEN_PKT_NOMAC, 85054359Sroberto (int)(rbufp->recv_length - LEN_PKT_NOMAC))) 85154359Sroberto is_authentic = 1; 85254359Sroberto if (debug) 85354359Sroberto printf("receive: authentication %s\n", 85454359Sroberto is_authentic ? "passed" : "failed"); 85554359Sroberto } 85654359Sroberto server->trust <<= 1; 85754359Sroberto if (!is_authentic) 85854359Sroberto server->trust |= 1; 85954359Sroberto 86054359Sroberto /* 86154359Sroberto * Looks good. Record info from the packet. 86254359Sroberto */ 86354359Sroberto server->leap = PKT_LEAP(rpkt->li_vn_mode); 86454359Sroberto server->stratum = PKT_TO_STRATUM(rpkt->stratum); 86554359Sroberto server->precision = rpkt->precision; 86654359Sroberto server->rootdelay = ntohl(rpkt->rootdelay); 86754359Sroberto server->rootdispersion = ntohl(rpkt->rootdispersion); 86854359Sroberto server->refid = rpkt->refid; 86954359Sroberto NTOHL_FP(&rpkt->reftime, &server->reftime); 87054359Sroberto NTOHL_FP(&rpkt->rec, &rec); 87154359Sroberto NTOHL_FP(&rpkt->xmt, &server->org); 87254359Sroberto 87354359Sroberto /* 87454359Sroberto * Make sure the server is at least somewhat sane. If not, try 87554359Sroberto * again. 87654359Sroberto */ 87754359Sroberto if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)) { 87854359Sroberto transmit(server); 87954359Sroberto return; 88054359Sroberto } 88154359Sroberto 88254359Sroberto /* 88354359Sroberto * Calculate the round trip delay (di) and the clock offset (ci). 88454359Sroberto * We use the equations (reordered from those in the spec): 88554359Sroberto * 88654359Sroberto * d = (t2 - t3) - (t1 - t0) 88754359Sroberto * c = ((t2 - t3) + (t1 - t0)) / 2 88854359Sroberto */ 88954359Sroberto t10 = server->org; /* pkt.xmt == t1 */ 89054359Sroberto L_SUB(&t10, &rbufp->recv_time); /* recv_time == t0*/ 89154359Sroberto 89254359Sroberto t23 = rec; /* pkt.rec == t2 */ 89354359Sroberto L_SUB(&t23, &org); /* pkt->org == t3 */ 89454359Sroberto 89554359Sroberto /* now have (t2 - t3) and (t0 - t1). Calculate (ci) and (di) */ 896106163Sroberto /* 897106163Sroberto * Calculate (ci) = ((t1 - t0) / 2) + ((t2 - t3) / 2) 898106163Sroberto * For large offsets this may prevent an overflow on '+' 899106163Sroberto */ 90054359Sroberto ci = t10; 90154359Sroberto L_RSHIFT(&ci); 902106163Sroberto tmp = t23; 903106163Sroberto L_RSHIFT(&tmp); 904106163Sroberto L_ADD(&ci, &tmp); 90554359Sroberto 90654359Sroberto /* 90754359Sroberto * Calculate di in t23 in full precision, then truncate 90854359Sroberto * to an s_fp. 90954359Sroberto */ 91054359Sroberto L_SUB(&t23, &t10); 91154359Sroberto di = LFPTOFP(&t23); 91254359Sroberto 91354359Sroberto if (debug > 3) 91454359Sroberto printf("offset: %s, delay %s\n", lfptoa(&ci, 6), fptoa(di, 5)); 91554359Sroberto 91654359Sroberto di += (FP_SECOND >> (-(int)NTPDATE_PRECISION)) 91754359Sroberto + (FP_SECOND >> (-(int)server->precision)) + NTP_MAXSKW; 91854359Sroberto 91954359Sroberto if (di <= 0) { /* value still too raunchy to use? */ 92054359Sroberto L_CLR(&ci); 92154359Sroberto di = 0; 92254359Sroberto } else { 92354359Sroberto di = max(di, NTP_MINDIST); 92454359Sroberto } 92554359Sroberto 92654359Sroberto /* 92754359Sroberto * Shift this data in, then transmit again. 92854359Sroberto */ 92954359Sroberto server_data(server, (s_fp) di, &ci, 0); 93054359Sroberto transmit(server); 93154359Sroberto} 93254359Sroberto 93354359Sroberto 93454359Sroberto/* 93554359Sroberto * server_data - add a sample to the server's filter registers 93654359Sroberto */ 93754359Srobertostatic void 93854359Srobertoserver_data( 93954359Sroberto register struct server *server, 94054359Sroberto s_fp d, 94154359Sroberto l_fp *c, 94254359Sroberto u_fp e 94354359Sroberto ) 94454359Sroberto{ 945132451Sroberto u_short i; 94654359Sroberto 94754359Sroberto i = server->filter_nextpt; 94854359Sroberto if (i < NTP_SHIFT) { 94954359Sroberto server->filter_delay[i] = d; 95054359Sroberto server->filter_offset[i] = *c; 95154359Sroberto server->filter_soffset[i] = LFPTOFP(c); 95254359Sroberto server->filter_error[i] = e; 953132451Sroberto server->filter_nextpt = (u_short)(i + 1); 95454359Sroberto } 95554359Sroberto} 95654359Sroberto 95754359Sroberto 95854359Sroberto/* 95954359Sroberto * clock_filter - determine a server's delay, dispersion and offset 96054359Sroberto */ 96154359Srobertostatic void 96254359Srobertoclock_filter( 96354359Sroberto register struct server *server 96454359Sroberto ) 96554359Sroberto{ 96654359Sroberto register int i, j; 96754359Sroberto int ord[NTP_SHIFT]; 96854359Sroberto 96954359Sroberto /* 97054359Sroberto * Sort indices into increasing delay order 97154359Sroberto */ 97254359Sroberto for (i = 0; i < sys_samples; i++) 97354359Sroberto ord[i] = i; 97454359Sroberto 97554359Sroberto for (i = 0; i < (sys_samples-1); i++) { 97654359Sroberto for (j = i+1; j < sys_samples; j++) { 97754359Sroberto if (server->filter_delay[ord[j]] == 0) 97854359Sroberto continue; 97954359Sroberto if (server->filter_delay[ord[i]] == 0 98054359Sroberto || (server->filter_delay[ord[i]] 98154359Sroberto > server->filter_delay[ord[j]])) { 98254359Sroberto register int tmp; 98354359Sroberto 98454359Sroberto tmp = ord[i]; 98554359Sroberto ord[i] = ord[j]; 98654359Sroberto ord[j] = tmp; 98754359Sroberto } 98854359Sroberto } 98954359Sroberto } 99054359Sroberto 99154359Sroberto /* 99254359Sroberto * Now compute the dispersion, and assign values to delay and 99354359Sroberto * offset. If there are no samples in the register, delay and 99454359Sroberto * offset go to zero and dispersion is set to the maximum. 99554359Sroberto */ 99654359Sroberto if (server->filter_delay[ord[0]] == 0) { 99754359Sroberto server->delay = 0; 99854359Sroberto L_CLR(&server->offset); 99954359Sroberto server->soffset = 0; 100054359Sroberto server->dispersion = PEER_MAXDISP; 100154359Sroberto } else { 100254359Sroberto register s_fp d; 100354359Sroberto 100454359Sroberto server->delay = server->filter_delay[ord[0]]; 100554359Sroberto server->offset = server->filter_offset[ord[0]]; 100654359Sroberto server->soffset = LFPTOFP(&server->offset); 100754359Sroberto server->dispersion = 0; 100854359Sroberto for (i = 1; i < sys_samples; i++) { 100954359Sroberto if (server->filter_delay[ord[i]] == 0) 101054359Sroberto d = PEER_MAXDISP; 101154359Sroberto else { 101254359Sroberto d = server->filter_soffset[ord[i]] 101354359Sroberto - server->filter_soffset[ord[0]]; 101454359Sroberto if (d < 0) 101554359Sroberto d = -d; 101654359Sroberto if (d > PEER_MAXDISP) 101754359Sroberto d = PEER_MAXDISP; 101854359Sroberto } 101954359Sroberto /* 102054359Sroberto * XXX This *knows* PEER_FILTER is 1/2 102154359Sroberto */ 102254359Sroberto server->dispersion += (u_fp)(d) >> i; 102354359Sroberto } 102454359Sroberto } 102554359Sroberto /* 102654359Sroberto * We're done 102754359Sroberto */ 102854359Sroberto} 102954359Sroberto 103054359Sroberto 103154359Sroberto/* 103254359Sroberto * clock_select - select the pick-of-the-litter clock from the samples 103354359Sroberto * we've got. 103454359Sroberto */ 103554359Srobertostatic struct server * 103654359Srobertoclock_select(void) 103754359Sroberto{ 103854359Sroberto register struct server *server; 103954359Sroberto register int i; 104054359Sroberto register int nlist; 104154359Sroberto register s_fp d; 104254359Sroberto register int j; 104354359Sroberto register int n; 104454359Sroberto s_fp local_threshold; 104554359Sroberto struct server *server_list[NTP_MAXCLOCK]; 104654359Sroberto u_fp server_badness[NTP_MAXCLOCK]; 104754359Sroberto struct server *sys_server; 104854359Sroberto 104954359Sroberto /* 105054359Sroberto * This first chunk of code is supposed to go through all 105154359Sroberto * servers we know about to find the NTP_MAXLIST servers which 105254359Sroberto * are most likely to succeed. We run through the list 105354359Sroberto * doing the sanity checks and trying to insert anyone who 105454359Sroberto * looks okay. We are at all times aware that we should 105554359Sroberto * only keep samples from the top two strata and we only need 105654359Sroberto * NTP_MAXLIST of them. 105754359Sroberto */ 105854359Sroberto nlist = 0; /* none yet */ 105956746Sroberto for (server = sys_servers; server != NULL; server = server->next_server) { 1060106163Sroberto if (server->delay == 0) { 1061106163Sroberto if (debug) 1062106163Sroberto printf("%s: Server dropped: no data\n", ntoa(&server->srcadr)); 1063106163Sroberto continue; /* no data */ 1064106163Sroberto } 1065106163Sroberto if (server->stratum > NTP_INFIN) { 1066106163Sroberto if (debug) 1067106163Sroberto printf("%s: Server dropped: strata too high\n", ntoa(&server->srcadr)); 1068106163Sroberto continue; /* stratum no good */ 1069106163Sroberto } 107054359Sroberto if (server->delay > NTP_MAXWGT) { 1071106163Sroberto if (debug) 1072106163Sroberto printf("%s: Server dropped: server too far away\n", 1073106163Sroberto ntoa(&server->srcadr)); 1074106163Sroberto continue; /* too far away */ 107554359Sroberto } 1076106163Sroberto if (server->leap == LEAP_NOTINSYNC) { 1077106163Sroberto if (debug) 1078106163Sroberto printf("%s: Server dropped: Leap not in sync\n", ntoa(&server->srcadr)); 1079106163Sroberto continue; /* he's in trouble */ 1080106163Sroberto } 108154359Sroberto if (!L_ISHIS(&server->org, &server->reftime)) { 1082106163Sroberto if (debug) 1083106163Sroberto printf("%s: Server dropped: server is very broken\n", 1084106163Sroberto ntoa(&server->srcadr)); 1085106163Sroberto continue; /* very broken host */ 108654359Sroberto } 108754359Sroberto if ((server->org.l_ui - server->reftime.l_ui) 1088106163Sroberto >= NTP_MAXAGE) { 1089106163Sroberto if (debug) 1090106163Sroberto printf("%s: Server dropped: Server has gone too long without sync\n", 1091106163Sroberto ntoa(&server->srcadr)); 109254359Sroberto continue; /* too long without sync */ 109354359Sroberto } 109454359Sroberto if (server->trust != 0) { 1095106163Sroberto if (debug) 1096106163Sroberto printf("%s: Server dropped: Server is untrusted\n", 1097106163Sroberto ntoa(&server->srcadr)); 109854359Sroberto continue; 109954359Sroberto } 110054359Sroberto 110154359Sroberto /* 110254359Sroberto * This one seems sane. Find where he belongs 110354359Sroberto * on the list. 110454359Sroberto */ 110554359Sroberto d = server->dispersion + server->dispersion; 110654359Sroberto for (i = 0; i < nlist; i++) 110754359Sroberto if (server->stratum <= server_list[i]->stratum) 110854359Sroberto break; 110954359Sroberto for ( ; i < nlist; i++) { 111054359Sroberto if (server->stratum < server_list[i]->stratum) 111154359Sroberto break; 111254359Sroberto if (d < (s_fp) server_badness[i]) 111354359Sroberto break; 111454359Sroberto } 111554359Sroberto 111654359Sroberto /* 111754359Sroberto * If i points past the end of the list, this 111854359Sroberto * guy is a loser, else stick him in. 111954359Sroberto */ 112054359Sroberto if (i >= NTP_MAXLIST) 112154359Sroberto continue; 112254359Sroberto for (j = nlist; j > i; j--) 112354359Sroberto if (j < NTP_MAXLIST) { 112454359Sroberto server_list[j] = server_list[j-1]; 112554359Sroberto server_badness[j] 112654359Sroberto = server_badness[j-1]; 112754359Sroberto } 112854359Sroberto 112954359Sroberto server_list[i] = server; 113054359Sroberto server_badness[i] = d; 113154359Sroberto if (nlist < NTP_MAXLIST) 113254359Sroberto nlist++; 113354359Sroberto } 113454359Sroberto 113554359Sroberto /* 113654359Sroberto * Got the five-or-less best. Cut the list where the number of 113754359Sroberto * strata exceeds two. 113854359Sroberto */ 113954359Sroberto j = 0; 114054359Sroberto for (i = 1; i < nlist; i++) 114154359Sroberto if (server_list[i]->stratum > server_list[i-1]->stratum) 114254359Sroberto if (++j == 2) { 114354359Sroberto nlist = i; 114454359Sroberto break; 114554359Sroberto } 114654359Sroberto 114754359Sroberto /* 114854359Sroberto * Whew! What we should have by now is 0 to 5 candidates for 114954359Sroberto * the job of syncing us. If we have none, we're out of luck. 115054359Sroberto * If we have one, he's a winner. If we have more, do falseticker 115154359Sroberto * detection. 115254359Sroberto */ 115354359Sroberto 115454359Sroberto if (nlist == 0) 115554359Sroberto sys_server = 0; 115654359Sroberto else if (nlist == 1) { 115754359Sroberto sys_server = server_list[0]; 115854359Sroberto } else { 115954359Sroberto /* 116054359Sroberto * Re-sort by stratum, bdelay estimate quality and 116154359Sroberto * server.delay. 116254359Sroberto */ 116354359Sroberto for (i = 0; i < nlist-1; i++) 116454359Sroberto for (j = i+1; j < nlist; j++) { 116554359Sroberto if (server_list[i]->stratum 116654359Sroberto < server_list[j]->stratum) 116754359Sroberto break; /* already sorted by stratum */ 116854359Sroberto if (server_list[i]->delay 116954359Sroberto < server_list[j]->delay) 117054359Sroberto continue; 117154359Sroberto server = server_list[i]; 117254359Sroberto server_list[i] = server_list[j]; 117354359Sroberto server_list[j] = server; 117454359Sroberto } 117554359Sroberto 117654359Sroberto /* 117754359Sroberto * Calculate the fixed part of the dispersion limit 117854359Sroberto */ 117954359Sroberto local_threshold = (FP_SECOND >> (-(int)NTPDATE_PRECISION)) 118054359Sroberto + NTP_MAXSKW; 118154359Sroberto 118254359Sroberto /* 118354359Sroberto * Now drop samples until we're down to one. 118454359Sroberto */ 118554359Sroberto while (nlist > 1) { 118654359Sroberto for (n = 0; n < nlist; n++) { 118754359Sroberto server_badness[n] = 0; 118854359Sroberto for (j = 0; j < nlist; j++) { 118954359Sroberto if (j == n) /* with self? */ 119054359Sroberto continue; 119154359Sroberto d = server_list[j]->soffset 119254359Sroberto - server_list[n]->soffset; 119354359Sroberto if (d < 0) /* absolute value */ 119454359Sroberto d = -d; 119554359Sroberto /* 119654359Sroberto * XXX This code *knows* that 119754359Sroberto * NTP_SELECT is 3/4 119854359Sroberto */ 119954359Sroberto for (i = 0; i < j; i++) 120054359Sroberto d = (d>>1) + (d>>2); 120154359Sroberto server_badness[n] += d; 120254359Sroberto } 120354359Sroberto } 120454359Sroberto 120554359Sroberto /* 120654359Sroberto * We now have an array of nlist badness 120754359Sroberto * coefficients. Find the badest. Find 120854359Sroberto * the minimum precision while we're at 120954359Sroberto * it. 121054359Sroberto */ 121154359Sroberto i = 0; 121254359Sroberto n = server_list[0]->precision;; 121354359Sroberto for (j = 1; j < nlist; j++) { 121454359Sroberto if (server_badness[j] >= server_badness[i]) 121554359Sroberto i = j; 121654359Sroberto if (n > server_list[j]->precision) 121754359Sroberto n = server_list[j]->precision; 121854359Sroberto } 121954359Sroberto 122054359Sroberto /* 122154359Sroberto * i is the index of the server with the worst 122254359Sroberto * dispersion. If his dispersion is less than 122354359Sroberto * the threshold, stop now, else delete him and 122454359Sroberto * continue around again. 122554359Sroberto */ 122654359Sroberto if ( (s_fp) server_badness[i] < (local_threshold 122754359Sroberto + (FP_SECOND >> (-n)))) 122854359Sroberto break; 122954359Sroberto for (j = i + 1; j < nlist; j++) 123054359Sroberto server_list[j-1] = server_list[j]; 123154359Sroberto nlist--; 123254359Sroberto } 123354359Sroberto 123454359Sroberto /* 123554359Sroberto * What remains is a list of less than 5 servers. Take 123654359Sroberto * the best. 123754359Sroberto */ 123854359Sroberto sys_server = server_list[0]; 123954359Sroberto } 124054359Sroberto 124154359Sroberto /* 124254359Sroberto * That's it. Return our server. 124354359Sroberto */ 124454359Sroberto return sys_server; 124554359Sroberto} 124654359Sroberto 124754359Sroberto 124854359Sroberto/* 124954359Sroberto * clock_adjust - process what we've received, and adjust the time 125054359Sroberto * if we got anything decent. 125154359Sroberto */ 125254359Srobertostatic int 125354359Srobertoclock_adjust(void) 125454359Sroberto{ 125556746Sroberto register struct server *sp, *server; 125654359Sroberto s_fp absoffset; 125754359Sroberto int dostep; 125854359Sroberto 125956746Sroberto for (sp = sys_servers; sp != NULL; sp = sp->next_server) 126056746Sroberto clock_filter(sp); 126154359Sroberto server = clock_select(); 126254359Sroberto 126354359Sroberto if (debug || simple_query) { 126456746Sroberto for (sp = sys_servers; sp != NULL; sp = sp->next_server) 126556746Sroberto printserver(sp, stdout); 126654359Sroberto } 126754359Sroberto 126854359Sroberto if (server == 0) { 126954359Sroberto msyslog(LOG_ERR, 127054359Sroberto "no server suitable for synchronization found"); 127154359Sroberto return(1); 127254359Sroberto } 127354359Sroberto 127454359Sroberto if (always_step) { 127554359Sroberto dostep = 1; 127654359Sroberto } else if (never_step) { 127754359Sroberto dostep = 0; 127854359Sroberto } else { 127954359Sroberto absoffset = server->soffset; 128054359Sroberto if (absoffset < 0) 128154359Sroberto absoffset = -absoffset; 1282106424Sroberto dostep = (absoffset >= NTPDATE_THRESHOLD || absoffset < 0); 128354359Sroberto } 128454359Sroberto 128554359Sroberto if (dostep) { 128654359Sroberto if (simple_query || l_step_systime(&server->offset)) { 128754359Sroberto msyslog(LOG_NOTICE, "step time server %s offset %s sec", 1288132451Sroberto stoa(&server->srcadr), 128954359Sroberto lfptoa(&server->offset, 6)); 129054359Sroberto } 129154359Sroberto } else { 129254359Sroberto#if !defined SYS_WINNT && !defined SYS_CYGWIN32 129354359Sroberto if (simple_query || l_adj_systime(&server->offset)) { 129454359Sroberto msyslog(LOG_NOTICE, "adjust time server %s offset %s sec", 1295132451Sroberto stoa(&server->srcadr), 129654359Sroberto lfptoa(&server->offset, 6)); 129754359Sroberto } 129854359Sroberto#else 129954359Sroberto /* The NT SetSystemTimeAdjustment() call achieves slewing by 130054359Sroberto * changing the clock frequency. This means that we cannot specify 130154359Sroberto * it to slew the clock by a definite amount and then stop like 130254359Sroberto * the Unix adjtime() routine. We can technically adjust the clock 130354359Sroberto * frequency, have ntpdate sleep for a while, and then wake 130454359Sroberto * up and reset the clock frequency, but this might cause some 130554359Sroberto * grief if the user attempts to run ntpd immediately after 130654359Sroberto * ntpdate and the socket is in use. 130754359Sroberto */ 130854359Sroberto printf("\nThe -b option is required by ntpdate on Windows NT platforms\n"); 130954359Sroberto exit(1); 131054359Sroberto#endif /* SYS_WINNT */ 131154359Sroberto } 131254359Sroberto return(0); 131354359Sroberto} 131454359Sroberto 131554359Sroberto 131654359Sroberto/* XXX ELIMINATE: merge BIG slew into adj_systime in lib/systime.c */ 131754359Sroberto/* 131854359Sroberto * addserver - determine a server's address and allocate a new structure 131954359Sroberto * for it. 132054359Sroberto */ 132154359Srobertostatic void 132254359Srobertoaddserver( 132354359Sroberto char *serv 132454359Sroberto ) 132554359Sroberto{ 132654359Sroberto register struct server *server; 1327132451Sroberto /* Address infos structure to store result of getaddrinfo */ 1328132451Sroberto struct addrinfo *addrResult; 1329132451Sroberto /* Address infos structure to store hints for getaddrinfo */ 1330132451Sroberto struct addrinfo hints; 1331132451Sroberto /* Error variable for getaddrinfo */ 1332132451Sroberto int error; 1333132451Sroberto /* Service name */ 1334132451Sroberto char service[5]; 1335132451Sroberto strcpy(service, "ntp"); 133654359Sroberto 1337132451Sroberto /* Get host address. Looking for UDP datagram connection. */ 1338132451Sroberto memset(&hints, 0, sizeof(hints)); 1339132451Sroberto hints.ai_family = ai_fam_templ; 1340132451Sroberto hints.ai_socktype = SOCK_DGRAM; 1341132451Sroberto 1342132451Sroberto printf("Looking for host %s and service %s\n", serv, service); 1343132451Sroberto 1344132451Sroberto error = getaddrinfo(serv, service, &hints, &addrResult); 1345132451Sroberto if (error != 0) { 1346132451Sroberto fprintf(stderr, "Error : %s\n", gai_strerror(error)); 134754359Sroberto msyslog(LOG_ERR, "can't find host %s\n", serv); 134854359Sroberto return; 134954359Sroberto } 1350132451Sroberto else { 1351132451Sroberto fprintf(stderr, "host found : %s\n", stohost((struct sockaddr_storage*)addrResult->ai_addr)); 1352132451Sroberto } 135354359Sroberto 135454359Sroberto server = (struct server *)emalloc(sizeof(struct server)); 135554359Sroberto memset((char *)server, 0, sizeof(struct server)); 135654359Sroberto 1357132451Sroberto /* For now we only get the first returned server of the addrinfo list */ 1358132451Sroberto memset(&(server->srcadr), 0, sizeof(struct sockaddr_storage)); 1359132451Sroberto memcpy(&(server->srcadr), addrResult->ai_addr, addrResult->ai_addrlen); 136056746Sroberto server->event_time = ++sys_numservers; 136156746Sroberto if (sys_servers == NULL) 136256746Sroberto sys_servers = server; 136356746Sroberto else { 136456746Sroberto struct server *sp; 136556746Sroberto 136656746Sroberto for (sp = sys_servers; sp->next_server != NULL; 136756746Sroberto sp = sp->next_server) ; 136856746Sroberto sp->next_server = server; 136956746Sroberto } 137054359Sroberto} 137154359Sroberto 137254359Sroberto 137354359Sroberto/* 137454359Sroberto * findserver - find a server in the list given its address 1375132451Sroberto * ***(For now it isn't totally AF-Independant, to check later..) 137654359Sroberto */ 137754359Srobertostatic struct server * 137854359Srobertofindserver( 1379132451Sroberto struct sockaddr_storage *addr 138054359Sroberto ) 138154359Sroberto{ 138256746Sroberto struct server *server; 138356746Sroberto struct server *mc_server; 138454359Sroberto 138556746Sroberto mc_server = NULL; 1386132451Sroberto if (htons(((struct sockaddr_in*)addr)->sin_port) != NTP_PORT) 138754359Sroberto return 0; 138854359Sroberto 138956746Sroberto for (server = sys_servers; server != NULL; 139056746Sroberto server = server->next_server) { 139156746Sroberto 1392132451Sroberto if (memcmp(addr, &server->srcadr, SOCKLEN(addr))==0) 139356746Sroberto return server; 1394132451Sroberto /* Multicast compatibility to verify here... I'm not sure it's working */ 1395132451Sroberto if(addr->ss_family == AF_INET) { 1396132451Sroberto if (IN_MULTICAST(ntohl(((struct sockaddr_in*)addr)->sin_addr.s_addr))) 1397132451Sroberto mc_server = server; 1398132451Sroberto } 1399132451Sroberto else { 1400132451Sroberto#ifdef AF_INET6 1401132451Sroberto if (IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)(&server->srcadr))->sin6_addr)) 140256746Sroberto mc_server = server; 1403132451Sroberto#else 1404132451Sroberto return 0; 1405132451Sroberto#endif 1406132451Sroberto } 140754359Sroberto } 140856746Sroberto 140956746Sroberto if (mc_server != NULL) { 1410132451Sroberto 141156746Sroberto struct server *sp; 141256746Sroberto 141356746Sroberto if (mc_server->event_time != 0) { 141456746Sroberto mc_server->event_time = 0; 141556746Sroberto complete_servers++; 141656746Sroberto } 1417132451Sroberto 141856746Sroberto server = (struct server *)emalloc(sizeof(struct server)); 141956746Sroberto memset((char *)server, 0, sizeof(struct server)); 142056746Sroberto 1421132451Sroberto memcpy(&server->srcadr, &addr, sizeof(struct sockaddr_storage)); 142256746Sroberto 142356746Sroberto server->event_time = ++sys_numservers; 1424132451Sroberto 142556746Sroberto for (sp = sys_servers; sp->next_server != NULL; 142656746Sroberto sp = sp->next_server) ; 142756746Sroberto sp->next_server = server; 142856746Sroberto transmit(server); 142956746Sroberto } 143056746Sroberto return NULL; 143154359Sroberto} 143254359Sroberto 143354359Sroberto 143454359Sroberto/* 143554359Sroberto * timer - process a timer interrupt 143654359Sroberto */ 143754359Srobertovoid 143854359Srobertotimer(void) 143954359Sroberto{ 144056746Sroberto struct server *server; 144154359Sroberto 144254359Sroberto /* 144354359Sroberto * Bump the current idea of the time 144454359Sroberto */ 144554359Sroberto current_time++; 144654359Sroberto 144754359Sroberto /* 144854359Sroberto * Search through the server list looking for guys 144954359Sroberto * who's event timers have expired. Give these to 145054359Sroberto * the transmit routine. 145154359Sroberto */ 145256746Sroberto for (server = sys_servers; server != NULL; 145356746Sroberto server = server->next_server) { 145456746Sroberto if (server->event_time != 0 145556746Sroberto && server->event_time <= current_time) 145656746Sroberto transmit(server); 145754359Sroberto } 145854359Sroberto} 145954359Sroberto 146054359Sroberto 146182498Sroberto/* 146282498Sroberto * The code duplication in the following subroutine sucks, but 146382498Sroberto * we need to appease ansi2knr. 146482498Sroberto */ 146582498Sroberto 146654359Sroberto#ifndef SYS_WINNT 146754359Sroberto/* 146854359Sroberto * alarming - record the occurance of an alarm interrupt 146954359Sroberto */ 147054359Srobertostatic RETSIGTYPE 147154359Srobertoalarming( 147254359Sroberto int sig 147354359Sroberto ) 147482498Sroberto{ 147582498Sroberto alarm_flag++; 147682498Sroberto} 147754359Sroberto#else 147854359Srobertovoid CALLBACK 147954359Srobertoalarming(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) 148054359Sroberto{ 148154359Sroberto alarm_flag++; 148254359Sroberto} 148382498Sroberto#endif /* SYS_WINNT */ 148454359Sroberto 148554359Sroberto 148654359Sroberto/* 148754359Sroberto * init_alarm - set up the timer interrupt 148854359Sroberto */ 148954359Srobertostatic void 149054359Srobertoinit_alarm(void) 149154359Sroberto{ 149254359Sroberto#ifndef SYS_WINNT 149354359Sroberto# ifndef HAVE_TIMER_SETTIME 149454359Sroberto struct itimerval itimer; 149554359Sroberto# else 149654359Sroberto struct itimerspec ntpdate_itimer; 149754359Sroberto# endif 149854359Sroberto#else 149954359Sroberto TIMECAPS tc; 150054359Sroberto UINT wTimerRes, wTimerID; 150154359Sroberto# endif /* SYS_WINNT */ 150254359Sroberto#if defined SYS_CYGWIN32 || defined SYS_WINNT 150354359Sroberto HANDLE hToken; 150454359Sroberto TOKEN_PRIVILEGES tkp; 150554359Sroberto DWORD dwUser = 0; 150654359Sroberto#endif /* SYS_WINNT */ 150754359Sroberto 150854359Sroberto alarm_flag = 0; 150954359Sroberto 151054359Sroberto#ifndef SYS_WINNT 151154359Sroberto# if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME) 151254359Sroberto alarm_flag = 0; 151354359Sroberto /* this code was put in as setitimer() is non existant this us the 151454359Sroberto * POSIX "equivalents" setup - casey 151554359Sroberto */ 151654359Sroberto /* ntpdate_timerid is global - so we can kill timer later */ 151754359Sroberto if (timer_create (CLOCK_REALTIME, NULL, &ntpdate_timerid) == 151854359Sroberto# ifdef SYS_VXWORKS 151954359Sroberto ERROR 152054359Sroberto# else 152154359Sroberto -1 152254359Sroberto# endif 152354359Sroberto ) 152454359Sroberto { 152554359Sroberto fprintf (stderr, "init_alarm(): timer_create (...) FAILED\n"); 152654359Sroberto return; 152754359Sroberto } 152854359Sroberto 152954359Sroberto /* TIMER_HZ = (5) 153054359Sroberto * Set up the alarm interrupt. The first comes 1/(2*TIMER_HZ) 153154359Sroberto * seconds from now and they continue on every 1/TIMER_HZ seconds. 153254359Sroberto */ 153354359Sroberto (void) signal_no_reset(SIGALRM, alarming); 153454359Sroberto ntpdate_itimer.it_interval.tv_sec = ntpdate_itimer.it_value.tv_sec = 0; 153554359Sroberto ntpdate_itimer.it_interval.tv_nsec = 1000000000/TIMER_HZ; 153654359Sroberto ntpdate_itimer.it_value.tv_nsec = 1000000000/(TIMER_HZ<<1); 153754359Sroberto timer_settime(ntpdate_timerid, 0 /* !TIMER_ABSTIME */, &ntpdate_itimer, NULL); 153854359Sroberto# else 153954359Sroberto /* 154054359Sroberto * Set up the alarm interrupt. The first comes 1/(2*TIMER_HZ) 154154359Sroberto * seconds from now and they continue on every 1/TIMER_HZ seconds. 154254359Sroberto */ 154354359Sroberto (void) signal_no_reset(SIGALRM, alarming); 154454359Sroberto itimer.it_interval.tv_sec = itimer.it_value.tv_sec = 0; 154554359Sroberto itimer.it_interval.tv_usec = 1000000/TIMER_HZ; 154654359Sroberto itimer.it_value.tv_usec = 1000000/(TIMER_HZ<<1); 1547132451Sroberto 154854359Sroberto setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0); 154954359Sroberto# endif 155054359Sroberto#if defined SYS_CYGWIN32 155154359Sroberto /* 155254359Sroberto * Get previleges needed for fiddling with the clock 155354359Sroberto */ 155454359Sroberto 155554359Sroberto /* get the current process token handle */ 155654359Sroberto if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { 155754359Sroberto msyslog(LOG_ERR, "OpenProcessToken failed: %m"); 155854359Sroberto exit(1); 155954359Sroberto } 156054359Sroberto /* get the LUID for system-time privilege. */ 156154359Sroberto LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid); 156254359Sroberto tkp.PrivilegeCount = 1; /* one privilege to set */ 156354359Sroberto tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 156454359Sroberto /* get set-time privilege for this process. */ 156554359Sroberto AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0); 156654359Sroberto /* cannot test return value of AdjustTokenPrivileges. */ 156754359Sroberto if (GetLastError() != ERROR_SUCCESS) 156854359Sroberto msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m"); 156954359Sroberto#endif 157054359Sroberto#else /* SYS_WINNT */ 157154359Sroberto _tzset(); 157254359Sroberto 157354359Sroberto /* 157454359Sroberto * Get previleges needed for fiddling with the clock 157554359Sroberto */ 157654359Sroberto 157754359Sroberto /* get the current process token handle */ 157854359Sroberto if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { 157954359Sroberto msyslog(LOG_ERR, "OpenProcessToken failed: %m"); 158054359Sroberto exit(1); 158154359Sroberto } 158254359Sroberto /* get the LUID for system-time privilege. */ 158354359Sroberto LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid); 158454359Sroberto tkp.PrivilegeCount = 1; /* one privilege to set */ 158554359Sroberto tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 158654359Sroberto /* get set-time privilege for this process. */ 158754359Sroberto AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0); 158854359Sroberto /* cannot test return value of AdjustTokenPrivileges. */ 158954359Sroberto if (GetLastError() != ERROR_SUCCESS) 159054359Sroberto msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m"); 159154359Sroberto 159254359Sroberto /* 159354359Sroberto * Set up timer interrupts for every 2**EVENT_TIMEOUT seconds 159454359Sroberto * Under Win/NT, expiry of timer interval leads to invocation 159554359Sroberto * of a callback function (on a different thread) rather than 159654359Sroberto * generating an alarm signal 159754359Sroberto */ 159854359Sroberto 159954359Sroberto /* determine max and min resolution supported */ 160054359Sroberto if(timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) { 160154359Sroberto msyslog(LOG_ERR, "timeGetDevCaps failed: %m"); 160254359Sroberto exit(1); 160354359Sroberto } 160454359Sroberto wTimerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax); 160554359Sroberto /* establish the minimum timer resolution that we'll use */ 160654359Sroberto timeBeginPeriod(wTimerRes); 160754359Sroberto 160854359Sroberto /* start the timer event */ 160954359Sroberto wTimerID = timeSetEvent( 161054359Sroberto (UINT) (1000/TIMER_HZ), /* Delay */ 161154359Sroberto wTimerRes, /* Resolution */ 161254359Sroberto (LPTIMECALLBACK) alarming, /* Callback function */ 161354359Sroberto (DWORD) dwUser, /* User data */ 161454359Sroberto TIME_PERIODIC); /* Event type (periodic) */ 161554359Sroberto if (wTimerID == 0) { 161654359Sroberto msyslog(LOG_ERR, "timeSetEvent failed: %m"); 161754359Sroberto exit(1); 161854359Sroberto } 161954359Sroberto#endif /* SYS_WINNT */ 162054359Sroberto} 162154359Sroberto 162254359Sroberto 162354359Sroberto 162454359Sroberto 162554359Sroberto/* 162654359Sroberto * We do asynchronous input using the SIGIO facility. A number of 162754359Sroberto * recvbuf buffers are preallocated for input. In the signal 162854359Sroberto * handler we poll to see if the socket is ready and read the 162954359Sroberto * packets from it into the recvbuf's along with a time stamp and 163054359Sroberto * an indication of the source host and the interface it was received 163154359Sroberto * through. This allows us to get as accurate receive time stamps 163254359Sroberto * as possible independent of other processing going on. 163354359Sroberto * 163454359Sroberto * We allocate a number of recvbufs equal to the number of servers 163554359Sroberto * plus 2. This should be plenty. 163654359Sroberto */ 163754359Sroberto 163854359Sroberto 163954359Sroberto/* 164054359Sroberto * init_io - initialize I/O data and open socket 164154359Sroberto */ 164254359Srobertostatic void 164354359Srobertoinit_io(void) 164454359Sroberto{ 1645132451Sroberto struct addrinfo *res, *ressave; 1646132451Sroberto struct addrinfo hints; 1647132451Sroberto char service[5]; 1648132451Sroberto int optval = 1; 1649132451Sroberto 165054359Sroberto /* 165154359Sroberto * Init buffer free list and stat counters 165254359Sroberto */ 165354359Sroberto init_recvbuff(sys_numservers + 2); 1654132451Sroberto 165554359Sroberto /* 165654359Sroberto * Open the socket 165754359Sroberto */ 165854359Sroberto 1659132451Sroberto strcpy(service, "ntp"); 1660132451Sroberto 1661132451Sroberto /* 1662132451Sroberto * Init hints addrinfo structure 1663132451Sroberto */ 1664132451Sroberto memset(&hints, 0, sizeof(hints)); 1665132451Sroberto hints.ai_flags = AI_PASSIVE; 1666132451Sroberto hints.ai_socktype = SOCK_DGRAM; 1667132451Sroberto 1668132451Sroberto if(getaddrinfo(NULL, service, &hints, &res) != 0) { 1669132451Sroberto msyslog(LOG_ERR, "getaddrinfo() failed: %m"); 1670132451Sroberto exit(1); 1671132451Sroberto /*NOTREACHED*/ 1672132451Sroberto } 1673132451Sroberto 1674132451Sroberto /* Remember the address of the addrinfo structure chain */ 1675132451Sroberto ressave = res; 1676132451Sroberto 1677132451Sroberto /* 1678132451Sroberto * For each structure returned, open and bind socket 1679132451Sroberto */ 1680132451Sroberto for(nbsock = 0; (nbsock < MAX_AF) && res ; res = res->ai_next) { 168154359Sroberto /* create a datagram (UDP) socket */ 1682132451Sroberto if ((fd[nbsock] = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) { 1683132451Sroberto if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT || 1684132451Sroberto errno == EPFNOSUPPORT) 1685132451Sroberto continue; 1686132451Sroberto netsyslog(LOG_ERR, "socket() failed: %m"); 168754359Sroberto exit(1); 168854359Sroberto /*NOTREACHED*/ 168954359Sroberto } 1690132451Sroberto /* set socket to reuse address */ 1691132451Sroberto if (setsockopt(fd[nbsock], SOL_SOCKET, SO_REUSEADDR, (void*) &optval, sizeof(optval)) < 0) { 1692132451Sroberto netsyslog(LOG_ERR, "setsockopt() SO_REUSEADDR failed: %m"); 1693132451Sroberto exit(1); 1694132451Sroberto /*NOTREACHED*/ 1695132451Sroberto } 1696132451Sroberto#ifdef IPV6_V6ONLY 1697132451Sroberto /* Restricts AF_INET6 socket to IPv6 communications (see RFC 2553bis-03) */ 1698132451Sroberto if (res->ai_family == AF_INET6) 1699132451Sroberto if (setsockopt(fd[nbsock], IPPROTO_IPV6, IPV6_V6ONLY, (void*) &optval, sizeof(optval)) < 0) { 1700132451Sroberto netsyslog(LOG_ERR, "setsockopt() IPV6_V6ONLY failed: %m"); 1701132451Sroberto exit(1); 1702132451Sroberto /*NOTREACHED*/ 1703132451Sroberto } 1704132451Sroberto#endif 170554359Sroberto 1706132451Sroberto /* Remember the socket family in fd_family structure */ 1707132451Sroberto fd_family[nbsock] = res->ai_family; 1708132451Sroberto 170954359Sroberto /* 171054359Sroberto * bind the socket to the NTP port 171154359Sroberto */ 171254359Sroberto if (!debug && !simple_query && !unpriv_port) { 1713132451Sroberto if (bind(fd[nbsock], res->ai_addr, SOCKLEN(res->ai_addr)) < 0) { 171454359Sroberto#ifndef SYS_WINNT 171554359Sroberto if (errno == EADDRINUSE) 171654359Sroberto#else 171754359Sroberto if (WSAGetLastError() == WSAEADDRINUSE) 171854359Sroberto#endif /* SYS_WINNT */ 1719132451Sroberto netsyslog(LOG_ERR, 172054359Sroberto "the NTP socket is in use, exiting"); 172154359Sroberto else 1722132451Sroberto netsyslog(LOG_ERR, "bind() fails: %m"); 172354359Sroberto exit(1); 172454359Sroberto } 172554359Sroberto } 172654359Sroberto 172754359Sroberto#ifdef HAVE_POLL_H 1728132451Sroberto fdmask[nbsock].fd = fd[nbsock]; 1729132451Sroberto fdmask[nbsock].events = POLLIN; 173054359Sroberto#else 1731132451Sroberto FD_SET(fd[nbsock], &fdmask); 1732132451Sroberto if ((SOCKET) maxfd < fd[nbsock]+1) { 1733132451Sroberto maxfd = fd[nbsock]+1; 1734132451Sroberto } 173554359Sroberto#endif 173654359Sroberto 173754359Sroberto /* 173854359Sroberto * set non-blocking, 173954359Sroberto */ 174054359Sroberto#ifndef SYS_WINNT 174154359Sroberto# ifdef SYS_VXWORKS 174254359Sroberto { 174354359Sroberto int on = TRUE; 174454359Sroberto 1745132451Sroberto if (ioctl(fd[nbsock],FIONBIO, &on) == ERROR) { 1746132451Sroberto netsyslog(LOG_ERR, "ioctl(FIONBIO) fails: %m"); 174754359Sroberto exit(1); 174854359Sroberto } 174954359Sroberto } 175054359Sroberto# else /* not SYS_VXWORKS */ 175154359Sroberto# if defined(O_NONBLOCK) 1752132451Sroberto if (fcntl(fd[nbsock], F_SETFL, O_NONBLOCK) < 0) { 1753132451Sroberto netsyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m"); 175454359Sroberto exit(1); 175554359Sroberto /*NOTREACHED*/ 175654359Sroberto } 175754359Sroberto# else /* not O_NONBLOCK */ 175854359Sroberto# if defined(FNDELAY) 1759132451Sroberto if (fcntl(fd[nbsock], F_SETFL, FNDELAY) < 0) { 1760132451Sroberto netsyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m"); 176154359Sroberto exit(1); 176254359Sroberto /*NOTREACHED*/ 176354359Sroberto } 176454359Sroberto# else /* FNDELAY */ 176554359Sroberto# include "Bletch: Need non blocking I/O" 176654359Sroberto# endif /* FNDELAY */ 176754359Sroberto# endif /* not O_NONBLOCK */ 176854359Sroberto# endif /* SYS_VXWORKS */ 176954359Sroberto#else /* SYS_WINNT */ 1770132451Sroberto if (ioctlsocket(fd[nbsock], FIONBIO, (u_long *) &on) == SOCKET_ERROR) { 1771132451Sroberto netsyslog(LOG_ERR, "ioctlsocket(FIONBIO) fails: %m"); 177254359Sroberto exit(1); 177354359Sroberto } 177454359Sroberto#endif /* SYS_WINNT */ 1775132451Sroberto nbsock++; 1776132451Sroberto } 1777132451Sroberto freeaddrinfo(ressave); 177854359Sroberto} 177954359Sroberto 178054359Sroberto/* 178154359Sroberto * sendpkt - send a packet to the specified destination 178254359Sroberto */ 178354359Srobertostatic void 178454359Srobertosendpkt( 1785132451Sroberto struct sockaddr_storage *dest, 178654359Sroberto struct pkt *pkt, 178754359Sroberto int len 178854359Sroberto ) 178954359Sroberto{ 1790132451Sroberto int i; 179154359Sroberto int cc; 1792132451Sroberto SOCKET sock = 0; 179354359Sroberto 179454359Sroberto#ifdef SYS_WINNT 179554359Sroberto DWORD err; 179654359Sroberto#endif /* SYS_WINNT */ 179754359Sroberto 1798132451Sroberto /* Find a local family compatible socket to send ntp packet to ntp server */ 1799132451Sroberto for(i = 0; (i < MAX_AF); i++) { 1800132451Sroberto if(dest->ss_family == fd_family[i]) { 1801132451Sroberto sock = fd[i]; 1802132451Sroberto break; 1803132451Sroberto } 1804132451Sroberto } 1805132451Sroberto 1806132451Sroberto if ( sock == 0 ) { 1807132451Sroberto netsyslog(LOG_ERR, "cannot find family compatible socket to send ntp packet"); 1808132451Sroberto exit(1); 1809132451Sroberto /*NOTREACHED*/ 1810132451Sroberto } 1811132451Sroberto 1812132451Sroberto cc = sendto(sock, (char *)pkt, len, 0, (struct sockaddr *)dest, 1813132451Sroberto SOCKLEN(dest)); 1814132451Sroberto 181554359Sroberto#ifndef SYS_WINNT 181654359Sroberto if (cc == -1) { 181754359Sroberto if (errno != EWOULDBLOCK && errno != ENOBUFS) 181854359Sroberto#else 181954359Sroberto if (cc == SOCKET_ERROR) { 182054359Sroberto err = WSAGetLastError(); 182154359Sroberto if (err != WSAEWOULDBLOCK && err != WSAENOBUFS) 182254359Sroberto#endif /* SYS_WINNT */ 1823132451Sroberto netsyslog(LOG_ERR, "sendto(%s): %m", stohost(dest)); 182454359Sroberto } 182554359Sroberto} 182654359Sroberto 182754359Sroberto 182854359Sroberto/* 182954359Sroberto * input_handler - receive packets asynchronously 183054359Sroberto */ 183154359Srobertovoid 183254359Srobertoinput_handler(void) 183354359Sroberto{ 183454359Sroberto register int n; 183554359Sroberto register struct recvbuf *rb; 183654359Sroberto struct timeval tvzero; 183754359Sroberto int fromlen; 183854359Sroberto l_fp ts; 1839132451Sroberto int i; 184054359Sroberto#ifdef HAVE_POLL_H 1841132451Sroberto struct pollfd fds[MAX_AF]; 184254359Sroberto#else 184354359Sroberto fd_set fds; 184454359Sroberto#endif 1845132451Sroberto int fdc = 0; 184654359Sroberto 184754359Sroberto /* 184854359Sroberto * Do a poll to see if we have data 184954359Sroberto */ 185054359Sroberto for (;;) { 185154359Sroberto tvzero.tv_sec = tvzero.tv_usec = 0; 185254359Sroberto#ifdef HAVE_POLL_H 1853132451Sroberto memcpy(fds, fdmask, sizeof(fdmask)); 1854132451Sroberto n = poll(fds, (unsigned int)nbsock, tvzero.tv_sec * 1000); 1855132451Sroberto 1856132451Sroberto /* 1857132451Sroberto * Determine which socket received data 1858132451Sroberto */ 1859132451Sroberto 1860132451Sroberto for(i=0; i < nbsock; i++) { 1861132451Sroberto if(fds[i].revents & POLLIN) { 1862132451Sroberto fdc = fd[i]; 1863132451Sroberto break; 1864132451Sroberto } 1865132451Sroberto } 1866132451Sroberto 186754359Sroberto#else 1868132451Sroberto fds = fdmask; 1869132451Sroberto n = select(maxfd, &fds, (fd_set *)0, (fd_set *)0, &tvzero); 1870132451Sroberto 1871132451Sroberto /* 1872132451Sroberto * Determine which socket received data 1873132451Sroberto */ 1874132451Sroberto 1875132451Sroberto for(i=0; i < maxfd; i++) { 1876132451Sroberto if(FD_ISSET(fd[i], &fds)) { 1877132451Sroberto fdc = fd[i]; 1878132451Sroberto break; 1879132451Sroberto } 1880132451Sroberto } 1881132451Sroberto 188254359Sroberto#endif 188354359Sroberto 188454359Sroberto /* 188554359Sroberto * If nothing to do, just return. If an error occurred, 188654359Sroberto * complain and return. If we've got some, freeze a 188754359Sroberto * timestamp. 188854359Sroberto */ 188954359Sroberto if (n == 0) 189054359Sroberto return; 189154359Sroberto else if (n == -1) { 189254359Sroberto if (errno != EINTR) 1893132451Sroberto netsyslog(LOG_ERR, 189454359Sroberto#ifdef HAVE_POLL_H 189554359Sroberto "poll() error: %m" 189654359Sroberto#else 189754359Sroberto "select() error: %m" 189854359Sroberto#endif 189954359Sroberto ); 190054359Sroberto return; 190154359Sroberto } 190254359Sroberto get_systime(&ts); 190354359Sroberto 190454359Sroberto /* 190554359Sroberto * Get a buffer and read the frame. If we 190654359Sroberto * haven't got a buffer, or this is received 190754359Sroberto * on the wild card socket, just dump the packet. 190854359Sroberto */ 190954359Sroberto if (initializing || free_recvbuffs() == 0) { 191054359Sroberto char buf[100]; 191154359Sroberto 1912132451Sroberto 191354359Sroberto#ifndef SYS_WINNT 1914132451Sroberto (void) read(fdc, buf, sizeof buf); 191554359Sroberto#else 191654359Sroberto /* NT's _read does not operate on nonblocking sockets 191754359Sroberto * either recvfrom or ReadFile() has to be used here. 191854359Sroberto * ReadFile is used in [ntpd]ntp_intres() and ntpdc, 191954359Sroberto * just to be different use recvfrom() here 192054359Sroberto */ 1921132451Sroberto recvfrom(fdc, buf, sizeof(buf), 0, (struct sockaddr *)0, NULL); 192254359Sroberto#endif /* SYS_WINNT */ 192354359Sroberto continue; 192454359Sroberto } 192554359Sroberto 192654359Sroberto rb = get_free_recv_buffer(); 192754359Sroberto 1928132451Sroberto fromlen = sizeof(struct sockaddr_storage); 1929132451Sroberto rb->recv_length = recvfrom(fdc, (char *)&rb->recv_pkt, 193054359Sroberto sizeof(rb->recv_pkt), 0, 193154359Sroberto (struct sockaddr *)&rb->recv_srcadr, &fromlen); 193254359Sroberto if (rb->recv_length == -1) { 193354359Sroberto freerecvbuf(rb); 193454359Sroberto continue; 193554359Sroberto } 193654359Sroberto 193754359Sroberto /* 193854359Sroberto * Got one. Mark how and when it got here, 193954359Sroberto * put it on the full list. 194054359Sroberto */ 194154359Sroberto rb->recv_time = ts; 194254359Sroberto add_full_recv_buffer(rb); 194354359Sroberto } 194454359Sroberto} 194554359Sroberto 194654359Sroberto 194754359Sroberto#if !defined SYS_WINNT && !defined SYS_CYGWIN32 194854359Sroberto/* 194954359Sroberto * adj_systime - do a big long slew of the system time 195054359Sroberto */ 195154359Srobertostatic int 195254359Srobertol_adj_systime( 195354359Sroberto l_fp *ts 195454359Sroberto ) 195554359Sroberto{ 195654359Sroberto struct timeval adjtv, oadjtv; 195754359Sroberto int isneg = 0; 195854359Sroberto l_fp offset; 195954359Sroberto#ifndef STEP_SLEW 196054359Sroberto l_fp overshoot; 196154359Sroberto#endif 196254359Sroberto 196354359Sroberto /* 196454359Sroberto * Take the absolute value of the offset 196554359Sroberto */ 196654359Sroberto offset = *ts; 196754359Sroberto if (L_ISNEG(&offset)) { 196854359Sroberto isneg = 1; 196954359Sroberto L_NEG(&offset); 197054359Sroberto } 197154359Sroberto 197254359Sroberto#ifndef STEP_SLEW 197354359Sroberto /* 197454359Sroberto * Calculate the overshoot. XXX N.B. This code *knows* 197554359Sroberto * ADJ_OVERSHOOT is 1/2. 197654359Sroberto */ 197754359Sroberto overshoot = offset; 197854359Sroberto L_RSHIFTU(&overshoot); 197954359Sroberto if (overshoot.l_ui != 0 || (overshoot.l_uf > ADJ_MAXOVERSHOOT)) { 198054359Sroberto overshoot.l_ui = 0; 198154359Sroberto overshoot.l_uf = ADJ_MAXOVERSHOOT; 198254359Sroberto } 198354359Sroberto L_ADD(&offset, &overshoot); 198454359Sroberto#endif 198554359Sroberto TSTOTV(&offset, &adjtv); 198654359Sroberto 198754359Sroberto if (isneg) { 198854359Sroberto adjtv.tv_sec = -adjtv.tv_sec; 198954359Sroberto adjtv.tv_usec = -adjtv.tv_usec; 199054359Sroberto } 199154359Sroberto 199254359Sroberto if (adjtv.tv_usec != 0 && !debug) { 199354359Sroberto if (adjtime(&adjtv, &oadjtv) < 0) { 199454359Sroberto msyslog(LOG_ERR, "Can't adjust the time of day: %m"); 199554359Sroberto return 0; 199654359Sroberto } 199754359Sroberto } 199854359Sroberto return 1; 199954359Sroberto} 200054359Sroberto#endif /* SYS_WINNT */ 200154359Sroberto 200254359Sroberto 200354359Sroberto/* 200454359Sroberto * This fuction is not the same as lib/systime step_systime!!! 200554359Sroberto */ 200654359Srobertostatic int 200754359Srobertol_step_systime( 200854359Sroberto l_fp *ts 200954359Sroberto ) 201054359Sroberto{ 201154359Sroberto double dtemp; 201254359Sroberto 201354359Sroberto#ifdef SLEWALWAYS 201454359Sroberto#ifdef STEP_SLEW 201554359Sroberto l_fp ftmp; 201654359Sroberto int isneg; 201754359Sroberto int n; 201854359Sroberto 201954359Sroberto if (debug) return 1; 202054359Sroberto /* 202154359Sroberto * Take the absolute value of the offset 202254359Sroberto */ 202354359Sroberto ftmp = *ts; 202454359Sroberto if (L_ISNEG(&ftmp)) { 202554359Sroberto L_NEG(&ftmp); 202654359Sroberto isneg = 1; 202754359Sroberto } else 202854359Sroberto isneg = 0; 202954359Sroberto 203054359Sroberto if (ftmp.l_ui >= 3) { /* Step it and slew - we might win */ 203156746Sroberto LFPTOD(ts, dtemp); 203256746Sroberto n = step_systime(dtemp); 203354359Sroberto if (!n) 203454359Sroberto return n; 203554359Sroberto if (isneg) 203654359Sroberto ts->l_ui = ~0; 203754359Sroberto else 203854359Sroberto ts->l_ui = ~0; 203954359Sroberto } 204054359Sroberto /* 204154359Sroberto * Just add adjustment into the current offset. The update 204254359Sroberto * routine will take care of bringing the system clock into 204354359Sroberto * line. 204454359Sroberto */ 204554359Sroberto#endif 204654359Sroberto if (debug) 204754359Sroberto return 1; 204854359Sroberto#ifdef FORCE_NTPDATE_STEP 204954359Sroberto LFPTOD(ts, dtemp); 205054359Sroberto return step_systime(dtemp); 205154359Sroberto#else 205254359Sroberto l_adj_systime(ts); 205354359Sroberto return 1; 205454359Sroberto#endif 205554359Sroberto#else /* SLEWALWAYS */ 205654359Sroberto if (debug) 205754359Sroberto return 1; 205854359Sroberto LFPTOD(ts, dtemp); 205954359Sroberto return step_systime(dtemp); 206054359Sroberto#endif /* SLEWALWAYS */ 206154359Sroberto} 206254359Sroberto 206354359Sroberto 206454359Sroberto/* XXX ELIMINATE printserver similar in ntptrace.c, ntpdate.c */ 206554359Sroberto/* 206654359Sroberto * printserver - print detail information for a server 206754359Sroberto */ 206854359Srobertostatic void 206954359Srobertoprintserver( 207054359Sroberto register struct server *pp, 207154359Sroberto FILE *fp 207254359Sroberto ) 207354359Sroberto{ 207454359Sroberto register int i; 207554359Sroberto char junk[5]; 207654359Sroberto char *str; 207754359Sroberto 207854359Sroberto if (!debug) { 207954359Sroberto (void) fprintf(fp, "server %s, stratum %d, offset %s, delay %s\n", 2080132451Sroberto stoa(&pp->srcadr), pp->stratum, 208154359Sroberto lfptoa(&pp->offset, 6), fptoa((s_fp)pp->delay, 5)); 208254359Sroberto return; 208354359Sroberto } 208454359Sroberto 208554359Sroberto (void) fprintf(fp, "server %s, port %d\n", 2086132451Sroberto stoa(&pp->srcadr), ntohs(((struct sockaddr_in*)&(pp->srcadr))->sin_port)); 208754359Sroberto 208854359Sroberto (void) fprintf(fp, "stratum %d, precision %d, leap %c%c, trust %03o\n", 208954359Sroberto pp->stratum, pp->precision, 209054359Sroberto pp->leap & 0x2 ? '1' : '0', 209154359Sroberto pp->leap & 0x1 ? '1' : '0', 209254359Sroberto pp->trust); 209354359Sroberto 209454359Sroberto if (pp->stratum == 1) { 209554359Sroberto junk[4] = 0; 209654359Sroberto memmove(junk, (char *)&pp->refid, 4); 209754359Sroberto str = junk; 209854359Sroberto } else { 2099132451Sroberto str = stoa(&pp->srcadr); 210054359Sroberto } 210154359Sroberto (void) fprintf(fp, 210254359Sroberto "refid [%s], delay %s, dispersion %s\n", 210354359Sroberto str, fptoa((s_fp)pp->delay, 5), 210454359Sroberto ufptoa(pp->dispersion, 5)); 210554359Sroberto 210654359Sroberto (void) fprintf(fp, "transmitted %d, in filter %d\n", 210754359Sroberto pp->xmtcnt, pp->filter_nextpt); 210854359Sroberto 210954359Sroberto (void) fprintf(fp, "reference time: %s\n", 211054359Sroberto prettydate(&pp->reftime)); 211154359Sroberto (void) fprintf(fp, "originate timestamp: %s\n", 211254359Sroberto prettydate(&pp->org)); 211354359Sroberto (void) fprintf(fp, "transmit timestamp: %s\n", 211454359Sroberto prettydate(&pp->xmt)); 211554359Sroberto 211654359Sroberto (void) fprintf(fp, "filter delay: "); 211754359Sroberto for (i = 0; i < NTP_SHIFT; i++) { 211854359Sroberto (void) fprintf(fp, " %-8.8s", fptoa(pp->filter_delay[i], 5)); 211954359Sroberto if (i == (NTP_SHIFT>>1)-1) 212054359Sroberto (void) fprintf(fp, "\n "); 212154359Sroberto } 212254359Sroberto (void) fprintf(fp, "\n"); 212354359Sroberto 212454359Sroberto (void) fprintf(fp, "filter offset:"); 212554359Sroberto for (i = 0; i < PEER_SHIFT; i++) { 212654359Sroberto (void) fprintf(fp, " %-8.8s", lfptoa(&pp->filter_offset[i], 6)); 212754359Sroberto if (i == (PEER_SHIFT>>1)-1) 212854359Sroberto (void) fprintf(fp, "\n "); 212954359Sroberto } 213054359Sroberto (void) fprintf(fp, "\n"); 213154359Sroberto 213254359Sroberto (void) fprintf(fp, "delay %s, dispersion %s\n", 213354359Sroberto fptoa((s_fp)pp->delay, 5), ufptoa(pp->dispersion, 5)); 213454359Sroberto 213554359Sroberto (void) fprintf(fp, "offset %s\n\n", 213654359Sroberto lfptoa(&pp->offset, 6)); 213754359Sroberto} 213854359Sroberto 213954359Sroberto#if !defined(HAVE_VSPRINTF) 214054359Srobertoint 214154359Srobertovsprintf( 214254359Sroberto char *str, 214354359Sroberto const char *fmt, 214454359Sroberto va_list ap 214554359Sroberto ) 214654359Sroberto{ 214754359Sroberto FILE f; 214854359Sroberto int len; 214954359Sroberto 215054359Sroberto f._flag = _IOWRT+_IOSTRG; 215154359Sroberto f._ptr = str; 215254359Sroberto f._cnt = 32767; 215354359Sroberto len = _doprnt(fmt, ap, &f); 215454359Sroberto *f._ptr = 0; 215554359Sroberto return (len); 215654359Sroberto} 215754359Sroberto#endif 215854359Sroberto 215954359Sroberto#if 0 216054359Sroberto/* override function in library since SA_RESTART makes ALL syscalls restart */ 216154359Sroberto#ifdef SA_RESTART 216254359Srobertovoid 216354359Srobertosignal_no_reset( 216454359Sroberto int sig, 216554359Sroberto void (*func)() 216654359Sroberto ) 216754359Sroberto{ 216854359Sroberto int n; 216954359Sroberto struct sigaction vec; 217054359Sroberto 217154359Sroberto vec.sa_handler = func; 217254359Sroberto sigemptyset(&vec.sa_mask); 217354359Sroberto vec.sa_flags = 0; 217454359Sroberto 217554359Sroberto while (1) 217654359Sroberto { 217754359Sroberto n = sigaction(sig, &vec, NULL); 217854359Sroberto if (n == -1 && errno == EINTR) 217954359Sroberto continue; 218054359Sroberto break; 218154359Sroberto } 218254359Sroberto if (n == -1) 218354359Sroberto { 218454359Sroberto perror("sigaction"); 218554359Sroberto exit(1); 218654359Sroberto } 218754359Sroberto} 218854359Sroberto#endif 218954359Sroberto#endif 219054359Sroberto 219154359Sroberto#ifdef HAVE_NETINFO 219254359Srobertostatic ni_namelist * 219354359Srobertogetnetinfoservers(void) 219454359Sroberto{ 219554359Sroberto ni_status status; 219654359Sroberto void *domain; 219754359Sroberto ni_id confdir; 219854359Sroberto ni_namelist *namelist = (ni_namelist*)malloc(sizeof(ni_namelist)); 219954359Sroberto 220054359Sroberto /* Find a time server in NetInfo */ 220154359Sroberto if ((status = ni_open(NULL, ".", &domain)) != NI_OK) return NULL; 220254359Sroberto 220354359Sroberto while (status = ni_pathsearch(domain, &confdir, NETINFO_CONFIG_DIR) == NI_NODIR) { 220454359Sroberto void *next_domain; 220554359Sroberto if (ni_open(domain, "..", &next_domain) != NI_OK) break; 220654359Sroberto ni_free(domain); 220754359Sroberto domain = next_domain; 220854359Sroberto } 220954359Sroberto if (status != NI_OK) return NULL; 221054359Sroberto 221154359Sroberto NI_INIT(namelist); 221254359Sroberto if (ni_lookupprop(domain, &confdir, "server", namelist) != NI_OK) { 221354359Sroberto ni_namelist_free(namelist); 221454359Sroberto free(namelist); 221554359Sroberto return NULL; 221654359Sroberto } 221754359Sroberto 221854359Sroberto return(namelist); 221954359Sroberto} 222054359Sroberto#endif 2221