1c0b746e5SOllivier Robert /* 2c0b746e5SOllivier Robert * ntpdate - set the time of day by polling one or more NTP servers 3c0b746e5SOllivier Robert */ 4c0b746e5SOllivier Robert 5c0b746e5SOllivier Robert #ifdef HAVE_CONFIG_H 6c0b746e5SOllivier Robert # include <config.h> 7c0b746e5SOllivier Robert #endif 8c0b746e5SOllivier Robert 9c0b746e5SOllivier Robert #ifdef HAVE_SYS_TYPES_H 10c0b746e5SOllivier Robert # include <sys/types.h> 11c0b746e5SOllivier Robert #endif 12c0b746e5SOllivier Robert #ifdef HAVE_UNISTD_H 13c0b746e5SOllivier Robert # include <unistd.h> 14c0b746e5SOllivier Robert #endif 15c0b746e5SOllivier Robert 16c0b746e5SOllivier Robert #include <stdio.h> 17c0b746e5SOllivier Robert #include <signal.h> 18c0b746e5SOllivier Robert #include <ctype.h> 19c0b746e5SOllivier Robert #ifdef HAVE_POLL_H 20c0b746e5SOllivier Robert #include <poll.h> 21c0b746e5SOllivier Robert #endif 22c0b746e5SOllivier Robert #ifndef SYS_WINNT 23c0b746e5SOllivier Robert # include <netdb.h> 24c0b746e5SOllivier Robert # include <sys/signal.h> 25c0b746e5SOllivier Robert # include <sys/ioctl.h> 26c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 27c0b746e5SOllivier Robert #include <sys/time.h> 28c0b746e5SOllivier Robert #ifdef HAVE_SYS_RESOURCE_H 29c0b746e5SOllivier Robert # include <sys/resource.h> 30c0b746e5SOllivier Robert #endif /* HAVE_SYS_RESOURCE_H */ 31c0b746e5SOllivier Robert 32c0b746e5SOllivier Robert #ifdef SYS_VXWORKS 33c0b746e5SOllivier Robert # include "ioLib.h" 34c0b746e5SOllivier Robert # include "sockLib.h" 35c0b746e5SOllivier Robert # include "timers.h" 36c0b746e5SOllivier Robert 37c0b746e5SOllivier Robert /* select wants a zero structure ... */ 38c0b746e5SOllivier Robert struct timeval timeout = {0,0}; 39c0b746e5SOllivier Robert #else 40c0b746e5SOllivier Robert struct timeval timeout = {60,0}; 41c0b746e5SOllivier Robert #endif 42c0b746e5SOllivier Robert 43c0b746e5SOllivier Robert 44c0b746e5SOllivier Robert #if defined(SYS_HPUX) 45c0b746e5SOllivier Robert # include <utmp.h> 46c0b746e5SOllivier Robert #endif 47c0b746e5SOllivier Robert 48c0b746e5SOllivier Robert #ifdef HAVE_NETINFO 49c0b746e5SOllivier Robert #include <netinfo/ni.h> 50c0b746e5SOllivier Robert #endif 51c0b746e5SOllivier Robert 52c0b746e5SOllivier Robert #include "ntp_fp.h" 53c0b746e5SOllivier Robert #include "ntp.h" 54c0b746e5SOllivier Robert #include "ntp_io.h" 55c0b746e5SOllivier Robert #include "ntp_unixtime.h" 56c0b746e5SOllivier Robert #include "ntpdate.h" 57c0b746e5SOllivier Robert #include "ntp_string.h" 58c0b746e5SOllivier Robert #include "ntp_syslog.h" 59c0b746e5SOllivier Robert #include "ntp_select.h" 60c0b746e5SOllivier Robert #include "ntp_stdlib.h" 61c0b746e5SOllivier Robert #include "recvbuff.h" 62c0b746e5SOllivier Robert 63c0b746e5SOllivier Robert #ifdef SYS_WINNT 64c0b746e5SOllivier Robert # define TARGET_RESOLUTION 1 /* Try for 1-millisecond accuracy 65c0b746e5SOllivier Robert on Windows NT timers. */ 66c0b746e5SOllivier Robert #pragma comment(lib, "winmm") 67c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 68c0b746e5SOllivier Robert 69c0b746e5SOllivier Robert /* 70c0b746e5SOllivier Robert * Scheduling priority we run at 71c0b746e5SOllivier Robert */ 72c0b746e5SOllivier Robert #ifndef SYS_VXWORKS 73c0b746e5SOllivier Robert # define NTPDATE_PRIO (-12) 74c0b746e5SOllivier Robert #else 75c0b746e5SOllivier Robert # define NTPDATE_PRIO (100) 76c0b746e5SOllivier Robert #endif 77c0b746e5SOllivier Robert 78c0b746e5SOllivier Robert #if defined(HAVE_TIMER_SETTIME) || defined (HAVE_TIMER_CREATE) 79c0b746e5SOllivier Robert /* POSIX TIMERS - vxWorks doesn't have itimer - casey */ 80c0b746e5SOllivier Robert static timer_t ntpdate_timerid; 81c0b746e5SOllivier Robert #endif 82c0b746e5SOllivier Robert 83c0b746e5SOllivier Robert /* 84c0b746e5SOllivier Robert * Compatibility stuff for Version 2 85c0b746e5SOllivier Robert */ 86c0b746e5SOllivier Robert #define NTP_MAXSKW 0x28f /* 0.01 sec in fp format */ 87c0b746e5SOllivier Robert #define NTP_MINDIST 0x51f /* 0.02 sec in fp format */ 88c0b746e5SOllivier Robert #define PEER_MAXDISP (64*FP_SECOND) /* maximum dispersion (fp 64) */ 89c0b746e5SOllivier Robert #define NTP_INFIN 15 /* max stratum, infinity a la Bellman-Ford */ 90c0b746e5SOllivier Robert #define NTP_MAXWGT (8*FP_SECOND) /* maximum select weight 8 seconds */ 91c0b746e5SOllivier Robert #define NTP_MAXLIST 5 /* maximum select list size */ 92c0b746e5SOllivier Robert #define PEER_SHIFT 8 /* 8 suitable for crystal time base */ 93c0b746e5SOllivier Robert 94c0b746e5SOllivier Robert /* 95c0b746e5SOllivier Robert * Debugging flag 96c0b746e5SOllivier Robert */ 97c0b746e5SOllivier Robert volatile int debug = 0; 98c0b746e5SOllivier Robert 99c0b746e5SOllivier Robert /* 100c0b746e5SOllivier Robert * File descriptor masks etc. for call to select 101c0b746e5SOllivier Robert */ 102c0b746e5SOllivier Robert int fd; 103c0b746e5SOllivier Robert #ifdef HAVE_POLL_H 104c0b746e5SOllivier Robert struct pollfd fdmask; 105c0b746e5SOllivier Robert #else 106c0b746e5SOllivier Robert fd_set fdmask; 107c0b746e5SOllivier Robert #endif 108c0b746e5SOllivier Robert 109c0b746e5SOllivier Robert /* 110c0b746e5SOllivier Robert * Initializing flag. All async routines watch this and only do their 111c0b746e5SOllivier Robert * thing when it is clear. 112c0b746e5SOllivier Robert */ 113c0b746e5SOllivier Robert int initializing = 1; 114c0b746e5SOllivier Robert 115c0b746e5SOllivier Robert /* 116c0b746e5SOllivier Robert * Alarm flag. Set when an alarm occurs 117c0b746e5SOllivier Robert */ 118c0b746e5SOllivier Robert volatile int alarm_flag = 0; 119c0b746e5SOllivier Robert 120c0b746e5SOllivier Robert /* 121c0b746e5SOllivier Robert * Simple query flag. 122c0b746e5SOllivier Robert */ 123c0b746e5SOllivier Robert int simple_query = 0; 124c0b746e5SOllivier Robert 125c0b746e5SOllivier Robert /* 126c0b746e5SOllivier Robert * Unpriviledged port flag. 127c0b746e5SOllivier Robert */ 128c0b746e5SOllivier Robert int unpriv_port = 0; 129c0b746e5SOllivier Robert 130c0b746e5SOllivier Robert /* 131c0b746e5SOllivier Robert * Time to spend measuring drift rate 132c0b746e5SOllivier Robert */ 133c0b746e5SOllivier Robert int rate = 0; 134c0b746e5SOllivier Robert 135c0b746e5SOllivier Robert /* 136c0b746e5SOllivier Robert * Program name. 137c0b746e5SOllivier Robert */ 138c0b746e5SOllivier Robert char *progname; 139c0b746e5SOllivier Robert 140c0b746e5SOllivier Robert /* 141c0b746e5SOllivier Robert * Systemwide parameters and flags 142c0b746e5SOllivier Robert */ 143c0b746e5SOllivier Robert int sys_samples = DEFSAMPLES; /* number of samples/server */ 144c0b746e5SOllivier Robert u_long sys_timeout = DEFTIMEOUT; /* timeout time, in TIMER_HZ units */ 145c0b746e5SOllivier Robert struct server **sys_servers; /* the server list */ 146c0b746e5SOllivier Robert int sys_numservers = 0; /* number of servers to poll */ 147c0b746e5SOllivier Robert int sys_maxservers = 0; /* max number of servers to deal with */ 148c0b746e5SOllivier Robert int sys_authenticate = 0; /* true when authenticating */ 149c0b746e5SOllivier Robert u_int32 sys_authkey = 0; /* set to authentication key in use */ 150c0b746e5SOllivier Robert u_long sys_authdelay = 0; /* authentication delay */ 151c0b746e5SOllivier Robert int sys_version = NTP_VERSION; /* version to poll with */ 152c0b746e5SOllivier Robert 153c0b746e5SOllivier Robert /* 154c0b746e5SOllivier Robert * The current internal time 155c0b746e5SOllivier Robert */ 156c0b746e5SOllivier Robert u_long current_time = 0; 157c0b746e5SOllivier Robert 158c0b746e5SOllivier Robert /* 159c0b746e5SOllivier Robert * Counter for keeping track of completed servers 160c0b746e5SOllivier Robert */ 161c0b746e5SOllivier Robert int complete_servers = 0; 162c0b746e5SOllivier Robert 163c0b746e5SOllivier Robert /* 164c0b746e5SOllivier Robert * File of encryption keys 165c0b746e5SOllivier Robert */ 166c0b746e5SOllivier Robert 167c0b746e5SOllivier Robert #ifndef KEYFILE 168c0b746e5SOllivier Robert # ifndef SYS_WINNT 169c0b746e5SOllivier Robert #define KEYFILE "/etc/ntp.keys" 170c0b746e5SOllivier Robert # else 171c0b746e5SOllivier Robert #define KEYFILE "%windir%\\ntp.keys" 172c0b746e5SOllivier Robert # endif /* SYS_WINNT */ 173c0b746e5SOllivier Robert #endif /* KEYFILE */ 174c0b746e5SOllivier Robert 175c0b746e5SOllivier Robert #ifndef SYS_WINNT 176c0b746e5SOllivier Robert const char *key_file = KEYFILE; 177c0b746e5SOllivier Robert #else 178c0b746e5SOllivier Robert char key_file_storage[MAX_PATH+1], *key_file ; 179c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 180c0b746e5SOllivier Robert 181c0b746e5SOllivier Robert /* 182c0b746e5SOllivier Robert * Miscellaneous flags 183c0b746e5SOllivier Robert */ 184c0b746e5SOllivier Robert int verbose = 0; 185c0b746e5SOllivier Robert int always_step = 0; 186c0b746e5SOllivier Robert int never_step = 0; 187c0b746e5SOllivier Robert 188c0b746e5SOllivier Robert int ntpdatemain P((int, char **)); 189c0b746e5SOllivier Robert static void transmit P((struct server *)); 190c0b746e5SOllivier Robert static void receive P((struct recvbuf *)); 191c0b746e5SOllivier Robert static void server_data P((struct server *, s_fp, l_fp *, u_fp)); 192c0b746e5SOllivier Robert static void clock_filter P((struct server *)); 193c0b746e5SOllivier Robert static struct server *clock_select P((void)); 194c0b746e5SOllivier Robert static int clock_adjust P((void)); 195c0b746e5SOllivier Robert static void addserver P((char *)); 196c0b746e5SOllivier Robert static struct server *findserver P((struct sockaddr_in *)); 197c0b746e5SOllivier Robert void timer P((void)); 198c0b746e5SOllivier Robert static void init_alarm P((void)); 199c0b746e5SOllivier Robert #ifndef SYS_WINNT 200c0b746e5SOllivier Robert static RETSIGTYPE alarming P((int)); 201c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 202c0b746e5SOllivier Robert static void init_io P((void)); 203c0b746e5SOllivier Robert static void sendpkt P((struct sockaddr_in *, struct pkt *, int)); 204c0b746e5SOllivier Robert void input_handler P((void)); 205c0b746e5SOllivier Robert 206c0b746e5SOllivier Robert static int l_adj_systime P((l_fp *)); 207c0b746e5SOllivier Robert static int l_step_systime P((l_fp *)); 208c0b746e5SOllivier Robert 209c0b746e5SOllivier Robert static int getnetnum P((const char *, u_int32 *)); 210c0b746e5SOllivier Robert static void printserver P((struct server *, FILE *)); 211c0b746e5SOllivier Robert 212c0b746e5SOllivier Robert #ifdef SYS_WINNT 213c0b746e5SOllivier Robert int on = 1; 214c0b746e5SOllivier Robert WORD wVersionRequested; 215c0b746e5SOllivier Robert WSADATA wsaData; 216c0b746e5SOllivier Robert HANDLE TimerThreadHandle = NULL; 217c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 218c0b746e5SOllivier Robert 219c0b746e5SOllivier Robert #ifdef NO_MAIN_ALLOWED 220c0b746e5SOllivier Robert CALL(ntpdate,"ntpdate",ntpdatemain); 221c0b746e5SOllivier Robert 222c0b746e5SOllivier Robert void clear_globals() 223c0b746e5SOllivier Robert { 224c0b746e5SOllivier Robert /* 225c0b746e5SOllivier Robert * Debugging flag 226c0b746e5SOllivier Robert */ 227c0b746e5SOllivier Robert debug = 0; 228c0b746e5SOllivier Robert 229c0b746e5SOllivier Robert ntp_optind = 0; 230c0b746e5SOllivier Robert /* 231c0b746e5SOllivier Robert * Initializing flag. All async routines watch this and only do their 232c0b746e5SOllivier Robert * thing when it is clear. 233c0b746e5SOllivier Robert */ 234c0b746e5SOllivier Robert initializing = 1; 235c0b746e5SOllivier Robert 236c0b746e5SOllivier Robert /* 237c0b746e5SOllivier Robert * Alarm flag. Set when an alarm occurs 238c0b746e5SOllivier Robert */ 239c0b746e5SOllivier Robert alarm_flag = 0; 240c0b746e5SOllivier Robert 241c0b746e5SOllivier Robert /* 242c0b746e5SOllivier Robert * Simple query flag. 243c0b746e5SOllivier Robert */ 244c0b746e5SOllivier Robert simple_query = 0; 245c0b746e5SOllivier Robert 246c0b746e5SOllivier Robert /* 247c0b746e5SOllivier Robert * Unpriviledged port flag. 248c0b746e5SOllivier Robert */ 249c0b746e5SOllivier Robert unpriv_port = 0; 250c0b746e5SOllivier Robert 251c0b746e5SOllivier Robert /* 252c0b746e5SOllivier Robert * Time to spend measuring drift rate 253c0b746e5SOllivier Robert */ 254c0b746e5SOllivier Robert rate = 0; 255c0b746e5SOllivier Robert /* 256c0b746e5SOllivier Robert * Systemwide parameters and flags 257c0b746e5SOllivier Robert */ 258c0b746e5SOllivier Robert sys_numservers = 0; /* number of servers to poll */ 259c0b746e5SOllivier Robert sys_maxservers = 0; /* max number of servers to deal with */ 260c0b746e5SOllivier Robert sys_authenticate = 0; /* true when authenticating */ 261c0b746e5SOllivier Robert sys_authkey = 0; /* set to authentication key in use */ 262c0b746e5SOllivier Robert sys_authdelay = 0; /* authentication delay */ 263c0b746e5SOllivier Robert sys_version = NTP_VERSION; /* version to poll with */ 264c0b746e5SOllivier Robert 265c0b746e5SOllivier Robert /* 266c0b746e5SOllivier Robert * The current internal time 267c0b746e5SOllivier Robert */ 268c0b746e5SOllivier Robert current_time = 0; 269c0b746e5SOllivier Robert 270c0b746e5SOllivier Robert /* 271c0b746e5SOllivier Robert * Counter for keeping track of completed servers 272c0b746e5SOllivier Robert */ 273c0b746e5SOllivier Robert complete_servers = 0; 274c0b746e5SOllivier Robert verbose = 0; 275c0b746e5SOllivier Robert always_step = 0; 276c0b746e5SOllivier Robert never_step = 0; 277c0b746e5SOllivier Robert } 278c0b746e5SOllivier Robert #endif 279c0b746e5SOllivier Robert 280c0b746e5SOllivier Robert #ifdef HAVE_NETINFO 281c0b746e5SOllivier Robert static ni_namelist *getnetinfoservers P((void)); 282c0b746e5SOllivier Robert #endif 283c0b746e5SOllivier Robert 284c0b746e5SOllivier Robert /* 285c0b746e5SOllivier Robert * Main program. Initialize us and loop waiting for I/O and/or 286c0b746e5SOllivier Robert * timer expiries. 287c0b746e5SOllivier Robert */ 288c0b746e5SOllivier Robert #ifndef NO_MAIN_ALLOWED 289c0b746e5SOllivier Robert int 290c0b746e5SOllivier Robert main( 291c0b746e5SOllivier Robert int argc, 292c0b746e5SOllivier Robert char *argv[] 293c0b746e5SOllivier Robert ) 294c0b746e5SOllivier Robert { 295c0b746e5SOllivier Robert return ntpdatemain (argc, argv); 296c0b746e5SOllivier Robert } 297c0b746e5SOllivier Robert #endif /* NO_MAIN_ALLOWED */ 298c0b746e5SOllivier Robert 299c0b746e5SOllivier Robert int 300c0b746e5SOllivier Robert ntpdatemain ( 301c0b746e5SOllivier Robert int argc, 302c0b746e5SOllivier Robert char *argv[] 303c0b746e5SOllivier Robert ) 304c0b746e5SOllivier Robert { 305c0b746e5SOllivier Robert int was_alarmed; 306c0b746e5SOllivier Robert struct recvbuf *rbuflist; 307c0b746e5SOllivier Robert struct recvbuf *rbuf; 308c0b746e5SOllivier Robert l_fp tmp; 309c0b746e5SOllivier Robert int errflg; 310c0b746e5SOllivier Robert int c; 311c0b746e5SOllivier Robert #ifdef HAVE_NETINFO 312c0b746e5SOllivier Robert ni_namelist *netinfoservers; 313c0b746e5SOllivier Robert #endif 314c0b746e5SOllivier Robert #ifdef SYS_WINNT 315c0b746e5SOllivier Robert HANDLE process_handle; 316c0b746e5SOllivier Robert 317c0b746e5SOllivier Robert wVersionRequested = MAKEWORD(1,1); 318c0b746e5SOllivier Robert if (WSAStartup(wVersionRequested, &wsaData)) { 319c0b746e5SOllivier Robert msyslog(LOG_ERR, "No useable winsock.dll: %m"); 320c0b746e5SOllivier Robert exit(1); 321c0b746e5SOllivier Robert } 322c0b746e5SOllivier Robert 323c0b746e5SOllivier Robert key_file = key_file_storage; 324c0b746e5SOllivier Robert 325c0b746e5SOllivier Robert if (!ExpandEnvironmentStrings(KEYFILE, key_file, MAX_PATH)) 326c0b746e5SOllivier Robert { 327c0b746e5SOllivier Robert msyslog(LOG_ERR, "ExpandEnvironmentStrings(KEYFILE) failed: %m\n"); 328c0b746e5SOllivier Robert } 329c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 330c0b746e5SOllivier Robert 331c0b746e5SOllivier Robert #ifdef NO_MAIN_ALLOWED 332c0b746e5SOllivier Robert clear_globals(); 333c0b746e5SOllivier Robert #endif 334c0b746e5SOllivier Robert 335c0b746e5SOllivier Robert errflg = 0; 336c0b746e5SOllivier Robert progname = argv[0]; 337c0b746e5SOllivier Robert syslogit = 0; 338c0b746e5SOllivier Robert 339c0b746e5SOllivier Robert /* 340c0b746e5SOllivier Robert * Decode argument list 341c0b746e5SOllivier Robert */ 342c0b746e5SOllivier Robert while ((c = ntp_getopt(argc, argv, "a:bBde:k:o:p:qr:st:uv")) != EOF) 343c0b746e5SOllivier Robert switch (c) 344c0b746e5SOllivier Robert { 345c0b746e5SOllivier Robert case 'a': 346c0b746e5SOllivier Robert c = atoi(ntp_optarg); 347c0b746e5SOllivier Robert sys_authenticate = 1; 348c0b746e5SOllivier Robert sys_authkey = c; 349c0b746e5SOllivier Robert break; 350c0b746e5SOllivier Robert case 'b': 351c0b746e5SOllivier Robert always_step++; 352c0b746e5SOllivier Robert never_step = 0; 353c0b746e5SOllivier Robert break; 354c0b746e5SOllivier Robert case 'B': 355c0b746e5SOllivier Robert never_step++; 356c0b746e5SOllivier Robert always_step = 0; 357c0b746e5SOllivier Robert break; 358c0b746e5SOllivier Robert case 'd': 359c0b746e5SOllivier Robert ++debug; 360c0b746e5SOllivier Robert break; 361c0b746e5SOllivier Robert case 'e': 362c0b746e5SOllivier Robert if (!atolfp(ntp_optarg, &tmp) 363c0b746e5SOllivier Robert || tmp.l_ui != 0) { 364c0b746e5SOllivier Robert (void) fprintf(stderr, 365c0b746e5SOllivier Robert "%s: encryption delay %s is unlikely\n", 366c0b746e5SOllivier Robert progname, ntp_optarg); 367c0b746e5SOllivier Robert errflg++; 368c0b746e5SOllivier Robert } else { 369c0b746e5SOllivier Robert sys_authdelay = tmp.l_uf; 370c0b746e5SOllivier Robert } 371c0b746e5SOllivier Robert break; 372c0b746e5SOllivier Robert case 'k': 373c0b746e5SOllivier Robert key_file = ntp_optarg; 374c0b746e5SOllivier Robert break; 375c0b746e5SOllivier Robert case 'o': 376c0b746e5SOllivier Robert sys_version = atoi(ntp_optarg); 377c0b746e5SOllivier Robert break; 378c0b746e5SOllivier Robert case 'p': 379c0b746e5SOllivier Robert c = atoi(ntp_optarg); 380c0b746e5SOllivier Robert if (c <= 0 || c > NTP_SHIFT) { 381c0b746e5SOllivier Robert (void) fprintf(stderr, 382c0b746e5SOllivier Robert "%s: number of samples (%d) is invalid\n", 383c0b746e5SOllivier Robert progname, c); 384c0b746e5SOllivier Robert errflg++; 385c0b746e5SOllivier Robert } else { 386c0b746e5SOllivier Robert sys_samples = c; 387c0b746e5SOllivier Robert } 388c0b746e5SOllivier Robert break; 389c0b746e5SOllivier Robert case 'q': 390c0b746e5SOllivier Robert simple_query = 1; 391c0b746e5SOllivier Robert break; 392c0b746e5SOllivier Robert case 'r': 393c0b746e5SOllivier Robert c = atoi(ntp_optarg); 394c0b746e5SOllivier Robert if (c <= 0 || c > (60 * 60)) { 395c0b746e5SOllivier Robert (void) fprintf(stderr, 396c0b746e5SOllivier Robert "%s: rate (%d) is invalid: 0 - %d\n", 397c0b746e5SOllivier Robert progname, c, (60 * 60)); 398c0b746e5SOllivier Robert errflg++; 399c0b746e5SOllivier Robert } else { 400c0b746e5SOllivier Robert rate = c; 401c0b746e5SOllivier Robert } 402c0b746e5SOllivier Robert break; 403c0b746e5SOllivier Robert case 's': 404c0b746e5SOllivier Robert syslogit = 1; 405c0b746e5SOllivier Robert break; 406c0b746e5SOllivier Robert case 't': 407c0b746e5SOllivier Robert if (!atolfp(ntp_optarg, &tmp)) { 408c0b746e5SOllivier Robert (void) fprintf(stderr, 409c0b746e5SOllivier Robert "%s: timeout %s is undecodeable\n", 410c0b746e5SOllivier Robert progname, ntp_optarg); 411c0b746e5SOllivier Robert errflg++; 412c0b746e5SOllivier Robert } else { 413c0b746e5SOllivier Robert sys_timeout = ((LFPTOFP(&tmp) * TIMER_HZ) 414c0b746e5SOllivier Robert + 0x8000) >> 16; 415c0b746e5SOllivier Robert if (sys_timeout == 0) 416c0b746e5SOllivier Robert sys_timeout = 1; 417c0b746e5SOllivier Robert } 418c0b746e5SOllivier Robert break; 419c0b746e5SOllivier Robert case 'v': 420c0b746e5SOllivier Robert verbose = 1; 421c0b746e5SOllivier Robert break; 422c0b746e5SOllivier Robert case 'u': 423c0b746e5SOllivier Robert unpriv_port = 1; 424c0b746e5SOllivier Robert break; 425c0b746e5SOllivier Robert case '?': 426c0b746e5SOllivier Robert ++errflg; 427c0b746e5SOllivier Robert break; 428c0b746e5SOllivier Robert default: 429c0b746e5SOllivier Robert break; 430c0b746e5SOllivier Robert } 431c0b746e5SOllivier Robert 432c0b746e5SOllivier Robert if (errflg) { 433c0b746e5SOllivier Robert (void) fprintf(stderr, 434c0b746e5SOllivier Robert "usage: %s [-bBdqsv] [-a key#] [-e delay] [-k file] [-p samples] [-o version#] [-r rate] [-t timeo] server ...\n", 435c0b746e5SOllivier Robert progname); 436c0b746e5SOllivier Robert exit(2); 437c0b746e5SOllivier Robert } 438c0b746e5SOllivier Robert 439c0b746e5SOllivier Robert if (debug || simple_query) { 440c0b746e5SOllivier Robert #ifdef HAVE_SETVBUF 441c0b746e5SOllivier Robert static char buf[BUFSIZ]; 442c0b746e5SOllivier Robert setvbuf(stdout, buf, _IOLBF, BUFSIZ); 443c0b746e5SOllivier Robert #else 444c0b746e5SOllivier Robert setlinebuf(stdout); 445c0b746e5SOllivier Robert #endif 446c0b746e5SOllivier Robert } 447c0b746e5SOllivier Robert 448c0b746e5SOllivier Robert /* 449c0b746e5SOllivier Robert * Logging. Open the syslog if we have to 450c0b746e5SOllivier Robert */ 451c0b746e5SOllivier Robert if (syslogit) { 452c0b746e5SOllivier Robert #if !defined (SYS_WINNT) && !defined (SYS_VXWORKS) && !defined SYS_CYGWIN32 453c0b746e5SOllivier Robert # ifndef LOG_DAEMON 454c0b746e5SOllivier Robert openlog("ntpdate", LOG_PID); 455c0b746e5SOllivier Robert # else 456c0b746e5SOllivier Robert 457c0b746e5SOllivier Robert # ifndef LOG_NTP 458c0b746e5SOllivier Robert # define LOG_NTP LOG_DAEMON 459c0b746e5SOllivier Robert # endif 460c0b746e5SOllivier Robert openlog("ntpdate", LOG_PID | LOG_NDELAY, LOG_NTP); 461c0b746e5SOllivier Robert if (debug) 462c0b746e5SOllivier Robert setlogmask(LOG_UPTO(LOG_DEBUG)); 463c0b746e5SOllivier Robert else 464c0b746e5SOllivier Robert setlogmask(LOG_UPTO(LOG_INFO)); 465c0b746e5SOllivier Robert # endif /* LOG_DAEMON */ 466c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 467c0b746e5SOllivier Robert } 468c0b746e5SOllivier Robert 469c0b746e5SOllivier Robert if (debug || verbose) 470c0b746e5SOllivier Robert msyslog(LOG_NOTICE, "%s", Version); 471c0b746e5SOllivier Robert 472c0b746e5SOllivier Robert /* 473c0b746e5SOllivier Robert * Add servers we are going to be polling 474c0b746e5SOllivier Robert */ 475c0b746e5SOllivier Robert sys_maxservers = argc - ntp_optind; 476c0b746e5SOllivier Robert #ifdef HAVE_NETINFO 477c0b746e5SOllivier Robert if ((netinfoservers = getnetinfoservers())) 478c0b746e5SOllivier Robert sys_maxservers += netinfoservers->ni_namelist_len; 479c0b746e5SOllivier Robert #endif 480c0b746e5SOllivier Robert sys_servers = (struct server **) 481c0b746e5SOllivier Robert emalloc(sys_maxservers * sizeof(struct server *)); 482c0b746e5SOllivier Robert 483c0b746e5SOllivier Robert for ( ; ntp_optind < argc; ntp_optind++) 484c0b746e5SOllivier Robert addserver(argv[ntp_optind]); 485c0b746e5SOllivier Robert 486c0b746e5SOllivier Robert #ifdef HAVE_NETINFO 487c0b746e5SOllivier Robert if (netinfoservers) { 488c0b746e5SOllivier Robert if ( netinfoservers->ni_namelist_len && 489c0b746e5SOllivier Robert *netinfoservers->ni_namelist_val ) { 490c0b746e5SOllivier Robert u_int servercount = 0; 491c0b746e5SOllivier Robert while (servercount < netinfoservers->ni_namelist_len) { 492c0b746e5SOllivier Robert if (debug) msyslog(LOG_DEBUG, 493c0b746e5SOllivier Robert "Adding time server %s from NetInfo configuration.", 494c0b746e5SOllivier Robert netinfoservers->ni_namelist_val[servercount]); 495c0b746e5SOllivier Robert addserver(netinfoservers->ni_namelist_val[servercount++]); 496c0b746e5SOllivier Robert } 497c0b746e5SOllivier Robert } 498c0b746e5SOllivier Robert ni_namelist_free(netinfoservers); 499c0b746e5SOllivier Robert free(netinfoservers); 500c0b746e5SOllivier Robert } 501c0b746e5SOllivier Robert #endif 502c0b746e5SOllivier Robert 503c0b746e5SOllivier Robert if (sys_numservers == 0) { 504c0b746e5SOllivier Robert msyslog(LOG_ERR, "no servers can be used, exiting"); 505c0b746e5SOllivier Robert exit(1); 506c0b746e5SOllivier Robert } 507c0b746e5SOllivier Robert 508c0b746e5SOllivier Robert /* 509c0b746e5SOllivier Robert * Initialize the time of day routines and the I/O subsystem 510c0b746e5SOllivier Robert */ 511c0b746e5SOllivier Robert if (sys_authenticate) { 512c0b746e5SOllivier Robert init_auth(); 513c0b746e5SOllivier Robert if (!authreadkeys(key_file)) { 514c0b746e5SOllivier Robert msyslog(LOG_ERR, "no key file, exitting"); 515c0b746e5SOllivier Robert exit(1); 516c0b746e5SOllivier Robert } 517c0b746e5SOllivier Robert if (!authistrusted(sys_authkey)) { 518c0b746e5SOllivier Robert char buf[10]; 519c0b746e5SOllivier Robert 520c0b746e5SOllivier Robert (void) sprintf(buf, "%lu", (unsigned long)sys_authkey); 521c0b746e5SOllivier Robert msyslog(LOG_ERR, "authentication key %s unknown", buf); 522c0b746e5SOllivier Robert exit(1); 523c0b746e5SOllivier Robert } 524c0b746e5SOllivier Robert } 525c0b746e5SOllivier Robert init_io(); 526c0b746e5SOllivier Robert init_alarm(); 527c0b746e5SOllivier Robert 528c0b746e5SOllivier Robert /* 529c0b746e5SOllivier Robert * Set the priority. 530c0b746e5SOllivier Robert */ 531c0b746e5SOllivier Robert #ifdef SYS_VXWORKS 532c0b746e5SOllivier Robert taskPrioritySet( taskIdSelf(), NTPDATE_PRIO); 533c0b746e5SOllivier Robert #endif 534c0b746e5SOllivier Robert #if defined(HAVE_ATT_NICE) 535c0b746e5SOllivier Robert nice (NTPDATE_PRIO); 536c0b746e5SOllivier Robert #endif 537c0b746e5SOllivier Robert #if defined(HAVE_BSD_NICE) 538c0b746e5SOllivier Robert (void) setpriority(PRIO_PROCESS, 0, NTPDATE_PRIO); 539c0b746e5SOllivier Robert #endif 540c0b746e5SOllivier Robert #ifdef SYS_WINNT 541c0b746e5SOllivier Robert process_handle = GetCurrentProcess(); 542c0b746e5SOllivier Robert if (!SetPriorityClass(process_handle, (DWORD) REALTIME_PRIORITY_CLASS)) { 543c0b746e5SOllivier Robert msyslog(LOG_ERR, "SetPriorityClass failed: %m"); 544c0b746e5SOllivier Robert } 545c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 546c0b746e5SOllivier Robert 547c0b746e5SOllivier Robert initializing = 0; 548c0b746e5SOllivier Robert 549c0b746e5SOllivier Robert was_alarmed = 0; 550c0b746e5SOllivier Robert rbuflist = (struct recvbuf *)0; 551c0b746e5SOllivier Robert while (complete_servers < sys_numservers) { 552c0b746e5SOllivier Robert #ifdef HAVE_POLL_H 553c0b746e5SOllivier Robert struct pollfd rdfdes; 554c0b746e5SOllivier Robert #else 555c0b746e5SOllivier Robert fd_set rdfdes; 556c0b746e5SOllivier Robert #endif 557c0b746e5SOllivier Robert int nfound; 558c0b746e5SOllivier Robert 559c0b746e5SOllivier Robert if (alarm_flag) { /* alarmed? */ 560c0b746e5SOllivier Robert was_alarmed = 1; 561c0b746e5SOllivier Robert alarm_flag = 0; 562c0b746e5SOllivier Robert } 563c0b746e5SOllivier Robert rbuflist = getrecvbufs(); /* get received buffers */ 564c0b746e5SOllivier Robert 565c0b746e5SOllivier Robert if (!was_alarmed && rbuflist == (struct recvbuf *)0) { 566c0b746e5SOllivier Robert /* 567c0b746e5SOllivier Robert * Nothing to do. Wait for something. 568c0b746e5SOllivier Robert */ 569c0b746e5SOllivier Robert rdfdes = fdmask; 570c0b746e5SOllivier Robert #ifdef HAVE_POLL_H 571c0b746e5SOllivier Robert nfound = poll(&rdfdes, 1, timeout.tv_sec * 1000); 572c0b746e5SOllivier Robert #else 573c0b746e5SOllivier Robert nfound = select(fd+1, &rdfdes, (fd_set *)0, 574c0b746e5SOllivier Robert (fd_set *)0, &timeout); 575c0b746e5SOllivier Robert #endif 576c0b746e5SOllivier Robert if (nfound > 0) 577c0b746e5SOllivier Robert input_handler(); 578c0b746e5SOllivier Robert else if ( 579c0b746e5SOllivier Robert #ifndef SYS_WINNT 580c0b746e5SOllivier Robert nfound == -1 581c0b746e5SOllivier Robert #else 582c0b746e5SOllivier Robert nfound == SOCKET_ERROR 583c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 584c0b746e5SOllivier Robert ) { 585c0b746e5SOllivier Robert #ifndef SYS_WINNT 586c0b746e5SOllivier Robert if (errno != EINTR) 587c0b746e5SOllivier Robert #endif 588c0b746e5SOllivier Robert msyslog(LOG_ERR, 589c0b746e5SOllivier Robert #ifdef HAVE_POLL_H 590c0b746e5SOllivier Robert "poll() error: %m" 591c0b746e5SOllivier Robert #else 592c0b746e5SOllivier Robert "select() error: %m" 593c0b746e5SOllivier Robert #endif 594c0b746e5SOllivier Robert ); 595c0b746e5SOllivier Robert } else { 596c0b746e5SOllivier Robert #ifndef SYS_VXWORKS 597c0b746e5SOllivier Robert msyslog(LOG_DEBUG, 598c0b746e5SOllivier Robert #ifdef HAVE_POLL_H 599c0b746e5SOllivier Robert "poll(): nfound = %d, error: %m", 600c0b746e5SOllivier Robert #else 601c0b746e5SOllivier Robert "select(): nfound = %d, error: %m", 602c0b746e5SOllivier Robert #endif 603c0b746e5SOllivier Robert nfound); 604c0b746e5SOllivier Robert #endif 605c0b746e5SOllivier Robert } 606c0b746e5SOllivier Robert if (alarm_flag) { /* alarmed? */ 607c0b746e5SOllivier Robert was_alarmed = 1; 608c0b746e5SOllivier Robert alarm_flag = 0; 609c0b746e5SOllivier Robert } 610c0b746e5SOllivier Robert rbuflist = getrecvbufs(); /* get received buffers */ 611c0b746e5SOllivier Robert } 612c0b746e5SOllivier Robert 613c0b746e5SOllivier Robert /* 614c0b746e5SOllivier Robert * Out here, signals are unblocked. Call receive 615c0b746e5SOllivier Robert * procedure for each incoming packet. 616c0b746e5SOllivier Robert */ 617c0b746e5SOllivier Robert while (rbuflist != (struct recvbuf *)0) { 618c0b746e5SOllivier Robert rbuf = rbuflist; 619c0b746e5SOllivier Robert rbuflist = rbuf->next; 620c0b746e5SOllivier Robert receive(rbuf); 621c0b746e5SOllivier Robert freerecvbuf(rbuf); 622c0b746e5SOllivier Robert } 623c0b746e5SOllivier Robert 624c0b746e5SOllivier Robert /* 625c0b746e5SOllivier Robert * Call timer to process any timeouts 626c0b746e5SOllivier Robert */ 627c0b746e5SOllivier Robert if (was_alarmed) { 628c0b746e5SOllivier Robert timer(); 629c0b746e5SOllivier Robert was_alarmed = 0; 630c0b746e5SOllivier Robert } 631c0b746e5SOllivier Robert 632c0b746e5SOllivier Robert /* 633c0b746e5SOllivier Robert * Go around again 634c0b746e5SOllivier Robert */ 635c0b746e5SOllivier Robert } 636c0b746e5SOllivier Robert 637c0b746e5SOllivier Robert /* 638c0b746e5SOllivier Robert * When we get here we've completed the polling of all servers. 639c0b746e5SOllivier Robert * Adjust the clock, then exit. 640c0b746e5SOllivier Robert */ 641c0b746e5SOllivier Robert #ifdef SYS_WINNT 642c0b746e5SOllivier Robert WSACleanup(); 643c0b746e5SOllivier Robert #endif 644c0b746e5SOllivier Robert #ifdef SYS_VXWORKS 645c0b746e5SOllivier Robert close (fd); 646c0b746e5SOllivier Robert timer_delete(ntpdate_timerid); 647c0b746e5SOllivier Robert #endif 648c0b746e5SOllivier Robert return clock_adjust(); 649c0b746e5SOllivier Robert } 650c0b746e5SOllivier Robert 651c0b746e5SOllivier Robert 652c0b746e5SOllivier Robert /* 653c0b746e5SOllivier Robert * transmit - transmit a packet to the given server, or mark it completed. 654c0b746e5SOllivier Robert * This is called by the timeout routine and by the receive 655c0b746e5SOllivier Robert * procedure. 656c0b746e5SOllivier Robert */ 657c0b746e5SOllivier Robert static void 658c0b746e5SOllivier Robert transmit( 659c0b746e5SOllivier Robert register struct server *server 660c0b746e5SOllivier Robert ) 661c0b746e5SOllivier Robert { 662c0b746e5SOllivier Robert struct pkt xpkt; 663c0b746e5SOllivier Robert 664c0b746e5SOllivier Robert if (debug) 665c0b746e5SOllivier Robert printf("transmit(%s)\n", ntoa(&server->srcadr)); 666c0b746e5SOllivier Robert 667c0b746e5SOllivier Robert if (server->filter_nextpt < server->xmtcnt) { 668c0b746e5SOllivier Robert l_fp ts; 669c0b746e5SOllivier Robert /* 670c0b746e5SOllivier Robert * Last message to this server timed out. Shift 671c0b746e5SOllivier Robert * zeros into the filter. 672c0b746e5SOllivier Robert */ 673c0b746e5SOllivier Robert L_CLR(&ts); 674c0b746e5SOllivier Robert server_data(server, 0, &ts, 0); 675c0b746e5SOllivier Robert } 676c0b746e5SOllivier Robert 677c0b746e5SOllivier Robert if ((int)server->filter_nextpt >= sys_samples) { 678c0b746e5SOllivier Robert /* 679c0b746e5SOllivier Robert * Got all the data we need. Mark this guy 680c0b746e5SOllivier Robert * completed and return. 681c0b746e5SOllivier Robert */ 682c0b746e5SOllivier Robert server->event_time = 0; 683c0b746e5SOllivier Robert complete_servers++; 684c0b746e5SOllivier Robert return; 685c0b746e5SOllivier Robert } 686c0b746e5SOllivier Robert 687c0b746e5SOllivier Robert /* 688c0b746e5SOllivier Robert * If we're here, send another message to the server. Fill in 689c0b746e5SOllivier Robert * the packet and let 'er rip. 690c0b746e5SOllivier Robert */ 691c0b746e5SOllivier Robert xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC, 692c0b746e5SOllivier Robert sys_version, MODE_CLIENT); 693c0b746e5SOllivier Robert xpkt.stratum = STRATUM_TO_PKT(STRATUM_UNSPEC); 694c0b746e5SOllivier Robert xpkt.ppoll = NTP_MINPOLL; 695c0b746e5SOllivier Robert xpkt.precision = NTPDATE_PRECISION; 696c0b746e5SOllivier Robert xpkt.rootdelay = htonl(NTPDATE_DISTANCE); 697c0b746e5SOllivier Robert xpkt.rootdispersion = htonl(NTPDATE_DISP); 698c0b746e5SOllivier Robert xpkt.refid = htonl(NTPDATE_REFID); 699c0b746e5SOllivier Robert L_CLR(&xpkt.reftime); 700c0b746e5SOllivier Robert L_CLR(&xpkt.org); 701c0b746e5SOllivier Robert L_CLR(&xpkt.rec); 702c0b746e5SOllivier Robert 703c0b746e5SOllivier Robert /* 704c0b746e5SOllivier Robert * Determine whether to authenticate or not. If so, 705c0b746e5SOllivier Robert * fill in the extended part of the packet and do it. 706c0b746e5SOllivier Robert * If not, just timestamp it and send it away. 707c0b746e5SOllivier Robert */ 708c0b746e5SOllivier Robert if (sys_authenticate) { 709c0b746e5SOllivier Robert int len; 710c0b746e5SOllivier Robert 711c0b746e5SOllivier Robert xpkt.keyid1 = htonl(sys_authkey); 712c0b746e5SOllivier Robert get_systime(&server->xmt); 713c0b746e5SOllivier Robert L_ADDUF(&server->xmt, sys_authdelay); 714c0b746e5SOllivier Robert HTONL_FP(&server->xmt, &xpkt.xmt); 715c0b746e5SOllivier Robert len = authencrypt(sys_authkey, (u_int32 *)&xpkt, LEN_PKT_NOMAC); 716c0b746e5SOllivier Robert sendpkt(&(server->srcadr), &xpkt, (int)(LEN_PKT_NOMAC + len)); 717c0b746e5SOllivier Robert 718c0b746e5SOllivier Robert if (debug > 1) 719c0b746e5SOllivier Robert printf("transmit auth to %s\n", 720c0b746e5SOllivier Robert ntoa(&(server->srcadr))); 721c0b746e5SOllivier Robert } else { 722c0b746e5SOllivier Robert get_systime(&(server->xmt)); 723c0b746e5SOllivier Robert HTONL_FP(&server->xmt, &xpkt.xmt); 724c0b746e5SOllivier Robert sendpkt(&(server->srcadr), &xpkt, LEN_PKT_NOMAC); 725c0b746e5SOllivier Robert 726c0b746e5SOllivier Robert if (debug > 1) 727c0b746e5SOllivier Robert printf("transmit to %s\n", ntoa(&(server->srcadr))); 728c0b746e5SOllivier Robert } 729c0b746e5SOllivier Robert 730c0b746e5SOllivier Robert /* 731c0b746e5SOllivier Robert * Update the server timeout and transmit count 732c0b746e5SOllivier Robert */ 733c0b746e5SOllivier Robert server->event_time = current_time + sys_timeout; 734c0b746e5SOllivier Robert server->xmtcnt++; 735c0b746e5SOllivier Robert } 736c0b746e5SOllivier Robert 737c0b746e5SOllivier Robert 738c0b746e5SOllivier Robert /* 739c0b746e5SOllivier Robert * receive - receive and process an incoming frame 740c0b746e5SOllivier Robert */ 741c0b746e5SOllivier Robert static void 742c0b746e5SOllivier Robert receive( 743c0b746e5SOllivier Robert struct recvbuf *rbufp 744c0b746e5SOllivier Robert ) 745c0b746e5SOllivier Robert { 746c0b746e5SOllivier Robert register struct pkt *rpkt; 747c0b746e5SOllivier Robert register struct server *server; 748c0b746e5SOllivier Robert register s_fp di; 749c0b746e5SOllivier Robert l_fp t10, t23; 750c0b746e5SOllivier Robert l_fp org; 751c0b746e5SOllivier Robert l_fp rec; 752c0b746e5SOllivier Robert l_fp ci; 753c0b746e5SOllivier Robert int has_mac; 754c0b746e5SOllivier Robert int is_authentic; 755c0b746e5SOllivier Robert 756c0b746e5SOllivier Robert if (debug) 757c0b746e5SOllivier Robert printf("receive(%s)\n", ntoa(&rbufp->recv_srcadr)); 758c0b746e5SOllivier Robert /* 759c0b746e5SOllivier Robert * Check to see if the packet basically looks like something 760c0b746e5SOllivier Robert * intended for us. 761c0b746e5SOllivier Robert */ 762c0b746e5SOllivier Robert if (rbufp->recv_length == LEN_PKT_NOMAC) 763c0b746e5SOllivier Robert has_mac = 0; 764c0b746e5SOllivier Robert else if (rbufp->recv_length >= LEN_PKT_NOMAC) 765c0b746e5SOllivier Robert has_mac = 1; 766c0b746e5SOllivier Robert else { 767c0b746e5SOllivier Robert if (debug) 768c0b746e5SOllivier Robert printf("receive: packet length %d\n", 769c0b746e5SOllivier Robert rbufp->recv_length); 770c0b746e5SOllivier Robert return; /* funny length packet */ 771c0b746e5SOllivier Robert } 772c0b746e5SOllivier Robert 773c0b746e5SOllivier Robert rpkt = &(rbufp->recv_pkt); 774c0b746e5SOllivier Robert if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION || 775c0b746e5SOllivier Robert PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) { 776c0b746e5SOllivier Robert return; 777c0b746e5SOllivier Robert } 778c0b746e5SOllivier Robert 779c0b746e5SOllivier Robert if ((PKT_MODE(rpkt->li_vn_mode) != MODE_SERVER 780c0b746e5SOllivier Robert && PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE) 781c0b746e5SOllivier Robert || rpkt->stratum > NTP_MAXSTRATUM) { 782c0b746e5SOllivier Robert if (debug) 783c0b746e5SOllivier Robert printf("receive: mode %d stratum %d\n", 784c0b746e5SOllivier Robert PKT_MODE(rpkt->li_vn_mode), rpkt->stratum); 785c0b746e5SOllivier Robert return; 786c0b746e5SOllivier Robert } 787c0b746e5SOllivier Robert 788c0b746e5SOllivier Robert /* 789c0b746e5SOllivier Robert * So far, so good. See if this is from a server we know. 790c0b746e5SOllivier Robert */ 791c0b746e5SOllivier Robert server = findserver(&(rbufp->recv_srcadr)); 792c0b746e5SOllivier Robert if (server == NULL) { 793c0b746e5SOllivier Robert if (debug) 794c0b746e5SOllivier Robert printf("receive: server not found\n"); 795c0b746e5SOllivier Robert return; 796c0b746e5SOllivier Robert } 797c0b746e5SOllivier Robert 798c0b746e5SOllivier Robert /* 799c0b746e5SOllivier Robert * Decode the org timestamp and make sure we're getting a response 800c0b746e5SOllivier Robert * to our last request. 801c0b746e5SOllivier Robert */ 802c0b746e5SOllivier Robert NTOHL_FP(&rpkt->org, &org); 803c0b746e5SOllivier Robert if (!L_ISEQU(&org, &server->xmt)) { 804c0b746e5SOllivier Robert if (debug) 805c0b746e5SOllivier Robert printf("receive: pkt.org and peer.xmt differ\n"); 806c0b746e5SOllivier Robert return; 807c0b746e5SOllivier Robert } 808c0b746e5SOllivier Robert 809c0b746e5SOllivier Robert /* 810c0b746e5SOllivier Robert * Check out the authenticity if we're doing that. 811c0b746e5SOllivier Robert */ 812c0b746e5SOllivier Robert if (!sys_authenticate) 813c0b746e5SOllivier Robert is_authentic = 1; 814c0b746e5SOllivier Robert else { 815c0b746e5SOllivier Robert is_authentic = 0; 816c0b746e5SOllivier Robert 817c0b746e5SOllivier Robert if (debug > 3) 818c0b746e5SOllivier Robert printf("receive: rpkt keyid=%ld sys_authkey=%ld decrypt=%ld\n", 819c0b746e5SOllivier Robert (long int)ntohl(rpkt->keyid1), (long int)sys_authkey, 820c0b746e5SOllivier Robert (long int)authdecrypt(sys_authkey, (u_int32 *)rpkt, 821c0b746e5SOllivier Robert LEN_PKT_NOMAC, (int)(rbufp->recv_length - LEN_PKT_NOMAC))); 822c0b746e5SOllivier Robert 823c0b746e5SOllivier Robert if (has_mac && ntohl(rpkt->keyid1) == sys_authkey && 824c0b746e5SOllivier Robert authdecrypt(sys_authkey, (u_int32 *)rpkt, LEN_PKT_NOMAC, 825c0b746e5SOllivier Robert (int)(rbufp->recv_length - LEN_PKT_NOMAC))) 826c0b746e5SOllivier Robert is_authentic = 1; 827c0b746e5SOllivier Robert if (debug) 828c0b746e5SOllivier Robert printf("receive: authentication %s\n", 829c0b746e5SOllivier Robert is_authentic ? "passed" : "failed"); 830c0b746e5SOllivier Robert } 831c0b746e5SOllivier Robert server->trust <<= 1; 832c0b746e5SOllivier Robert if (!is_authentic) 833c0b746e5SOllivier Robert server->trust |= 1; 834c0b746e5SOllivier Robert 835c0b746e5SOllivier Robert /* 836c0b746e5SOllivier Robert * Looks good. Record info from the packet. 837c0b746e5SOllivier Robert */ 838c0b746e5SOllivier Robert server->leap = PKT_LEAP(rpkt->li_vn_mode); 839c0b746e5SOllivier Robert server->stratum = PKT_TO_STRATUM(rpkt->stratum); 840c0b746e5SOllivier Robert server->precision = rpkt->precision; 841c0b746e5SOllivier Robert server->rootdelay = ntohl(rpkt->rootdelay); 842c0b746e5SOllivier Robert server->rootdispersion = ntohl(rpkt->rootdispersion); 843c0b746e5SOllivier Robert server->refid = rpkt->refid; 844c0b746e5SOllivier Robert NTOHL_FP(&rpkt->reftime, &server->reftime); 845c0b746e5SOllivier Robert NTOHL_FP(&rpkt->rec, &rec); 846c0b746e5SOllivier Robert NTOHL_FP(&rpkt->xmt, &server->org); 847c0b746e5SOllivier Robert 848c0b746e5SOllivier Robert /* 849c0b746e5SOllivier Robert * Make sure the server is at least somewhat sane. If not, try 850c0b746e5SOllivier Robert * again. 851c0b746e5SOllivier Robert */ 852c0b746e5SOllivier Robert if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)) { 853c0b746e5SOllivier Robert transmit(server); 854c0b746e5SOllivier Robert return; 855c0b746e5SOllivier Robert } 856c0b746e5SOllivier Robert 857c0b746e5SOllivier Robert /* 858c0b746e5SOllivier Robert * Calculate the round trip delay (di) and the clock offset (ci). 859c0b746e5SOllivier Robert * We use the equations (reordered from those in the spec): 860c0b746e5SOllivier Robert * 861c0b746e5SOllivier Robert * d = (t2 - t3) - (t1 - t0) 862c0b746e5SOllivier Robert * c = ((t2 - t3) + (t1 - t0)) / 2 863c0b746e5SOllivier Robert */ 864c0b746e5SOllivier Robert t10 = server->org; /* pkt.xmt == t1 */ 865c0b746e5SOllivier Robert L_SUB(&t10, &rbufp->recv_time); /* recv_time == t0*/ 866c0b746e5SOllivier Robert 867c0b746e5SOllivier Robert t23 = rec; /* pkt.rec == t2 */ 868c0b746e5SOllivier Robert L_SUB(&t23, &org); /* pkt->org == t3 */ 869c0b746e5SOllivier Robert 870c0b746e5SOllivier Robert /* now have (t2 - t3) and (t0 - t1). Calculate (ci) and (di) */ 871c0b746e5SOllivier Robert ci = t10; 872c0b746e5SOllivier Robert L_ADD(&ci, &t23); 873c0b746e5SOllivier Robert L_RSHIFT(&ci); 874c0b746e5SOllivier Robert 875c0b746e5SOllivier Robert /* 876c0b746e5SOllivier Robert * Calculate di in t23 in full precision, then truncate 877c0b746e5SOllivier Robert * to an s_fp. 878c0b746e5SOllivier Robert */ 879c0b746e5SOllivier Robert L_SUB(&t23, &t10); 880c0b746e5SOllivier Robert di = LFPTOFP(&t23); 881c0b746e5SOllivier Robert 882c0b746e5SOllivier Robert if (debug > 3) 883c0b746e5SOllivier Robert printf("offset: %s, delay %s\n", lfptoa(&ci, 6), fptoa(di, 5)); 884c0b746e5SOllivier Robert 885c0b746e5SOllivier Robert di += (FP_SECOND >> (-(int)NTPDATE_PRECISION)) 886c0b746e5SOllivier Robert + (FP_SECOND >> (-(int)server->precision)) + NTP_MAXSKW; 887c0b746e5SOllivier Robert 888c0b746e5SOllivier Robert if (di <= 0) { /* value still too raunchy to use? */ 889c0b746e5SOllivier Robert L_CLR(&ci); 890c0b746e5SOllivier Robert di = 0; 891c0b746e5SOllivier Robert } else { 892c0b746e5SOllivier Robert di = max(di, NTP_MINDIST); 893c0b746e5SOllivier Robert } 894c0b746e5SOllivier Robert 895c0b746e5SOllivier Robert /* 896c0b746e5SOllivier Robert * Shift this data in, then transmit again. 897c0b746e5SOllivier Robert */ 898c0b746e5SOllivier Robert server_data(server, (s_fp) di, &ci, 0); 899c0b746e5SOllivier Robert transmit(server); 900c0b746e5SOllivier Robert } 901c0b746e5SOllivier Robert 902c0b746e5SOllivier Robert 903c0b746e5SOllivier Robert /* 904c0b746e5SOllivier Robert * server_data - add a sample to the server's filter registers 905c0b746e5SOllivier Robert */ 906c0b746e5SOllivier Robert static void 907c0b746e5SOllivier Robert server_data( 908c0b746e5SOllivier Robert register struct server *server, 909c0b746e5SOllivier Robert s_fp d, 910c0b746e5SOllivier Robert l_fp *c, 911c0b746e5SOllivier Robert u_fp e 912c0b746e5SOllivier Robert ) 913c0b746e5SOllivier Robert { 914c0b746e5SOllivier Robert register int i; 915c0b746e5SOllivier Robert 916c0b746e5SOllivier Robert i = server->filter_nextpt; 917c0b746e5SOllivier Robert if (i < NTP_SHIFT) { 918c0b746e5SOllivier Robert server->filter_delay[i] = d; 919c0b746e5SOllivier Robert server->filter_offset[i] = *c; 920c0b746e5SOllivier Robert server->filter_soffset[i] = LFPTOFP(c); 921c0b746e5SOllivier Robert server->filter_error[i] = e; 922c0b746e5SOllivier Robert server->filter_nextpt = i + 1; 923c0b746e5SOllivier Robert } 924c0b746e5SOllivier Robert } 925c0b746e5SOllivier Robert 926c0b746e5SOllivier Robert 927c0b746e5SOllivier Robert /* 928c0b746e5SOllivier Robert * clock_filter - determine a server's delay, dispersion and offset 929c0b746e5SOllivier Robert */ 930c0b746e5SOllivier Robert static void 931c0b746e5SOllivier Robert clock_filter( 932c0b746e5SOllivier Robert register struct server *server 933c0b746e5SOllivier Robert ) 934c0b746e5SOllivier Robert { 935c0b746e5SOllivier Robert register int i, j; 936c0b746e5SOllivier Robert int ord[NTP_SHIFT]; 937c0b746e5SOllivier Robert 938c0b746e5SOllivier Robert /* 939c0b746e5SOllivier Robert * Sort indices into increasing delay order 940c0b746e5SOllivier Robert */ 941c0b746e5SOllivier Robert for (i = 0; i < sys_samples; i++) 942c0b746e5SOllivier Robert ord[i] = i; 943c0b746e5SOllivier Robert 944c0b746e5SOllivier Robert for (i = 0; i < (sys_samples-1); i++) { 945c0b746e5SOllivier Robert for (j = i+1; j < sys_samples; j++) { 946c0b746e5SOllivier Robert if (server->filter_delay[ord[j]] == 0) 947c0b746e5SOllivier Robert continue; 948c0b746e5SOllivier Robert if (server->filter_delay[ord[i]] == 0 949c0b746e5SOllivier Robert || (server->filter_delay[ord[i]] 950c0b746e5SOllivier Robert > server->filter_delay[ord[j]])) { 951c0b746e5SOllivier Robert register int tmp; 952c0b746e5SOllivier Robert 953c0b746e5SOllivier Robert tmp = ord[i]; 954c0b746e5SOllivier Robert ord[i] = ord[j]; 955c0b746e5SOllivier Robert ord[j] = tmp; 956c0b746e5SOllivier Robert } 957c0b746e5SOllivier Robert } 958c0b746e5SOllivier Robert } 959c0b746e5SOllivier Robert 960c0b746e5SOllivier Robert /* 961c0b746e5SOllivier Robert * Now compute the dispersion, and assign values to delay and 962c0b746e5SOllivier Robert * offset. If there are no samples in the register, delay and 963c0b746e5SOllivier Robert * offset go to zero and dispersion is set to the maximum. 964c0b746e5SOllivier Robert */ 965c0b746e5SOllivier Robert if (server->filter_delay[ord[0]] == 0) { 966c0b746e5SOllivier Robert server->delay = 0; 967c0b746e5SOllivier Robert L_CLR(&server->offset); 968c0b746e5SOllivier Robert server->soffset = 0; 969c0b746e5SOllivier Robert server->dispersion = PEER_MAXDISP; 970c0b746e5SOllivier Robert } else { 971c0b746e5SOllivier Robert register s_fp d; 972c0b746e5SOllivier Robert 973c0b746e5SOllivier Robert server->delay = server->filter_delay[ord[0]]; 974c0b746e5SOllivier Robert server->offset = server->filter_offset[ord[0]]; 975c0b746e5SOllivier Robert server->soffset = LFPTOFP(&server->offset); 976c0b746e5SOllivier Robert server->dispersion = 0; 977c0b746e5SOllivier Robert for (i = 1; i < sys_samples; i++) { 978c0b746e5SOllivier Robert if (server->filter_delay[ord[i]] == 0) 979c0b746e5SOllivier Robert d = PEER_MAXDISP; 980c0b746e5SOllivier Robert else { 981c0b746e5SOllivier Robert d = server->filter_soffset[ord[i]] 982c0b746e5SOllivier Robert - server->filter_soffset[ord[0]]; 983c0b746e5SOllivier Robert if (d < 0) 984c0b746e5SOllivier Robert d = -d; 985c0b746e5SOllivier Robert if (d > PEER_MAXDISP) 986c0b746e5SOllivier Robert d = PEER_MAXDISP; 987c0b746e5SOllivier Robert } 988c0b746e5SOllivier Robert /* 989c0b746e5SOllivier Robert * XXX This *knows* PEER_FILTER is 1/2 990c0b746e5SOllivier Robert */ 991c0b746e5SOllivier Robert server->dispersion += (u_fp)(d) >> i; 992c0b746e5SOllivier Robert } 993c0b746e5SOllivier Robert } 994c0b746e5SOllivier Robert /* 995c0b746e5SOllivier Robert * We're done 996c0b746e5SOllivier Robert */ 997c0b746e5SOllivier Robert } 998c0b746e5SOllivier Robert 999c0b746e5SOllivier Robert 1000c0b746e5SOllivier Robert /* 1001c0b746e5SOllivier Robert * clock_select - select the pick-of-the-litter clock from the samples 1002c0b746e5SOllivier Robert * we've got. 1003c0b746e5SOllivier Robert */ 1004c0b746e5SOllivier Robert static struct server * 1005c0b746e5SOllivier Robert clock_select(void) 1006c0b746e5SOllivier Robert { 1007c0b746e5SOllivier Robert register struct server *server; 1008c0b746e5SOllivier Robert register int i; 1009c0b746e5SOllivier Robert register int nlist; 1010c0b746e5SOllivier Robert register s_fp d; 1011c0b746e5SOllivier Robert register int j; 1012c0b746e5SOllivier Robert register int n; 1013c0b746e5SOllivier Robert s_fp local_threshold; 1014c0b746e5SOllivier Robert struct server *server_list[NTP_MAXCLOCK]; 1015c0b746e5SOllivier Robert u_fp server_badness[NTP_MAXCLOCK]; 1016c0b746e5SOllivier Robert struct server *sys_server; 1017c0b746e5SOllivier Robert 1018c0b746e5SOllivier Robert /* 1019c0b746e5SOllivier Robert * This first chunk of code is supposed to go through all 1020c0b746e5SOllivier Robert * servers we know about to find the NTP_MAXLIST servers which 1021c0b746e5SOllivier Robert * are most likely to succeed. We run through the list 1022c0b746e5SOllivier Robert * doing the sanity checks and trying to insert anyone who 1023c0b746e5SOllivier Robert * looks okay. We are at all times aware that we should 1024c0b746e5SOllivier Robert * only keep samples from the top two strata and we only need 1025c0b746e5SOllivier Robert * NTP_MAXLIST of them. 1026c0b746e5SOllivier Robert */ 1027c0b746e5SOllivier Robert nlist = 0; /* none yet */ 1028c0b746e5SOllivier Robert for (n = 0; n < sys_numservers; n++) { 1029c0b746e5SOllivier Robert server = sys_servers[n]; 1030c0b746e5SOllivier Robert if (server->delay == 0) 1031c0b746e5SOllivier Robert continue; /* no data */ 1032c0b746e5SOllivier Robert if (server->stratum > NTP_INFIN) 1033c0b746e5SOllivier Robert continue; /* stratum no good */ 1034c0b746e5SOllivier Robert if (server->delay > NTP_MAXWGT) { 1035c0b746e5SOllivier Robert continue; /* too far away */ 1036c0b746e5SOllivier Robert } 1037c0b746e5SOllivier Robert if (server->leap == LEAP_NOTINSYNC) 1038c0b746e5SOllivier Robert continue; /* he's in trouble */ 1039c0b746e5SOllivier Robert if (!L_ISHIS(&server->org, &server->reftime)) { 1040c0b746e5SOllivier Robert continue; /* very broken host */ 1041c0b746e5SOllivier Robert } 1042c0b746e5SOllivier Robert if ((server->org.l_ui - server->reftime.l_ui) 1043c0b746e5SOllivier Robert >= NTP_MAXAGE) { 1044c0b746e5SOllivier Robert continue; /* too long without sync */ 1045c0b746e5SOllivier Robert } 1046c0b746e5SOllivier Robert if (server->trust != 0) { 1047c0b746e5SOllivier Robert continue; 1048c0b746e5SOllivier Robert } 1049c0b746e5SOllivier Robert 1050c0b746e5SOllivier Robert /* 1051c0b746e5SOllivier Robert * This one seems sane. Find where he belongs 1052c0b746e5SOllivier Robert * on the list. 1053c0b746e5SOllivier Robert */ 1054c0b746e5SOllivier Robert d = server->dispersion + server->dispersion; 1055c0b746e5SOllivier Robert for (i = 0; i < nlist; i++) 1056c0b746e5SOllivier Robert if (server->stratum <= server_list[i]->stratum) 1057c0b746e5SOllivier Robert break; 1058c0b746e5SOllivier Robert for ( ; i < nlist; i++) { 1059c0b746e5SOllivier Robert if (server->stratum < server_list[i]->stratum) 1060c0b746e5SOllivier Robert break; 1061c0b746e5SOllivier Robert if (d < (s_fp) server_badness[i]) 1062c0b746e5SOllivier Robert break; 1063c0b746e5SOllivier Robert } 1064c0b746e5SOllivier Robert 1065c0b746e5SOllivier Robert /* 1066c0b746e5SOllivier Robert * If i points past the end of the list, this 1067c0b746e5SOllivier Robert * guy is a loser, else stick him in. 1068c0b746e5SOllivier Robert */ 1069c0b746e5SOllivier Robert if (i >= NTP_MAXLIST) 1070c0b746e5SOllivier Robert continue; 1071c0b746e5SOllivier Robert for (j = nlist; j > i; j--) 1072c0b746e5SOllivier Robert if (j < NTP_MAXLIST) { 1073c0b746e5SOllivier Robert server_list[j] = server_list[j-1]; 1074c0b746e5SOllivier Robert server_badness[j] 1075c0b746e5SOllivier Robert = server_badness[j-1]; 1076c0b746e5SOllivier Robert } 1077c0b746e5SOllivier Robert 1078c0b746e5SOllivier Robert server_list[i] = server; 1079c0b746e5SOllivier Robert server_badness[i] = d; 1080c0b746e5SOllivier Robert if (nlist < NTP_MAXLIST) 1081c0b746e5SOllivier Robert nlist++; 1082c0b746e5SOllivier Robert } 1083c0b746e5SOllivier Robert 1084c0b746e5SOllivier Robert /* 1085c0b746e5SOllivier Robert * Got the five-or-less best. Cut the list where the number of 1086c0b746e5SOllivier Robert * strata exceeds two. 1087c0b746e5SOllivier Robert */ 1088c0b746e5SOllivier Robert j = 0; 1089c0b746e5SOllivier Robert for (i = 1; i < nlist; i++) 1090c0b746e5SOllivier Robert if (server_list[i]->stratum > server_list[i-1]->stratum) 1091c0b746e5SOllivier Robert if (++j == 2) { 1092c0b746e5SOllivier Robert nlist = i; 1093c0b746e5SOllivier Robert break; 1094c0b746e5SOllivier Robert } 1095c0b746e5SOllivier Robert 1096c0b746e5SOllivier Robert /* 1097c0b746e5SOllivier Robert * Whew! What we should have by now is 0 to 5 candidates for 1098c0b746e5SOllivier Robert * the job of syncing us. If we have none, we're out of luck. 1099c0b746e5SOllivier Robert * If we have one, he's a winner. If we have more, do falseticker 1100c0b746e5SOllivier Robert * detection. 1101c0b746e5SOllivier Robert */ 1102c0b746e5SOllivier Robert 1103c0b746e5SOllivier Robert if (nlist == 0) 1104c0b746e5SOllivier Robert sys_server = 0; 1105c0b746e5SOllivier Robert else if (nlist == 1) { 1106c0b746e5SOllivier Robert sys_server = server_list[0]; 1107c0b746e5SOllivier Robert } else { 1108c0b746e5SOllivier Robert /* 1109c0b746e5SOllivier Robert * Re-sort by stratum, bdelay estimate quality and 1110c0b746e5SOllivier Robert * server.delay. 1111c0b746e5SOllivier Robert */ 1112c0b746e5SOllivier Robert for (i = 0; i < nlist-1; i++) 1113c0b746e5SOllivier Robert for (j = i+1; j < nlist; j++) { 1114c0b746e5SOllivier Robert if (server_list[i]->stratum 1115c0b746e5SOllivier Robert < server_list[j]->stratum) 1116c0b746e5SOllivier Robert break; /* already sorted by stratum */ 1117c0b746e5SOllivier Robert if (server_list[i]->delay 1118c0b746e5SOllivier Robert < server_list[j]->delay) 1119c0b746e5SOllivier Robert continue; 1120c0b746e5SOllivier Robert server = server_list[i]; 1121c0b746e5SOllivier Robert server_list[i] = server_list[j]; 1122c0b746e5SOllivier Robert server_list[j] = server; 1123c0b746e5SOllivier Robert } 1124c0b746e5SOllivier Robert 1125c0b746e5SOllivier Robert /* 1126c0b746e5SOllivier Robert * Calculate the fixed part of the dispersion limit 1127c0b746e5SOllivier Robert */ 1128c0b746e5SOllivier Robert local_threshold = (FP_SECOND >> (-(int)NTPDATE_PRECISION)) 1129c0b746e5SOllivier Robert + NTP_MAXSKW; 1130c0b746e5SOllivier Robert 1131c0b746e5SOllivier Robert /* 1132c0b746e5SOllivier Robert * Now drop samples until we're down to one. 1133c0b746e5SOllivier Robert */ 1134c0b746e5SOllivier Robert while (nlist > 1) { 1135c0b746e5SOllivier Robert for (n = 0; n < nlist; n++) { 1136c0b746e5SOllivier Robert server_badness[n] = 0; 1137c0b746e5SOllivier Robert for (j = 0; j < nlist; j++) { 1138c0b746e5SOllivier Robert if (j == n) /* with self? */ 1139c0b746e5SOllivier Robert continue; 1140c0b746e5SOllivier Robert d = server_list[j]->soffset 1141c0b746e5SOllivier Robert - server_list[n]->soffset; 1142c0b746e5SOllivier Robert if (d < 0) /* absolute value */ 1143c0b746e5SOllivier Robert d = -d; 1144c0b746e5SOllivier Robert /* 1145c0b746e5SOllivier Robert * XXX This code *knows* that 1146c0b746e5SOllivier Robert * NTP_SELECT is 3/4 1147c0b746e5SOllivier Robert */ 1148c0b746e5SOllivier Robert for (i = 0; i < j; i++) 1149c0b746e5SOllivier Robert d = (d>>1) + (d>>2); 1150c0b746e5SOllivier Robert server_badness[n] += d; 1151c0b746e5SOllivier Robert } 1152c0b746e5SOllivier Robert } 1153c0b746e5SOllivier Robert 1154c0b746e5SOllivier Robert /* 1155c0b746e5SOllivier Robert * We now have an array of nlist badness 1156c0b746e5SOllivier Robert * coefficients. Find the badest. Find 1157c0b746e5SOllivier Robert * the minimum precision while we're at 1158c0b746e5SOllivier Robert * it. 1159c0b746e5SOllivier Robert */ 1160c0b746e5SOllivier Robert i = 0; 1161c0b746e5SOllivier Robert n = server_list[0]->precision;; 1162c0b746e5SOllivier Robert for (j = 1; j < nlist; j++) { 1163c0b746e5SOllivier Robert if (server_badness[j] >= server_badness[i]) 1164c0b746e5SOllivier Robert i = j; 1165c0b746e5SOllivier Robert if (n > server_list[j]->precision) 1166c0b746e5SOllivier Robert n = server_list[j]->precision; 1167c0b746e5SOllivier Robert } 1168c0b746e5SOllivier Robert 1169c0b746e5SOllivier Robert /* 1170c0b746e5SOllivier Robert * i is the index of the server with the worst 1171c0b746e5SOllivier Robert * dispersion. If his dispersion is less than 1172c0b746e5SOllivier Robert * the threshold, stop now, else delete him and 1173c0b746e5SOllivier Robert * continue around again. 1174c0b746e5SOllivier Robert */ 1175c0b746e5SOllivier Robert if ( (s_fp) server_badness[i] < (local_threshold 1176c0b746e5SOllivier Robert + (FP_SECOND >> (-n)))) 1177c0b746e5SOllivier Robert break; 1178c0b746e5SOllivier Robert for (j = i + 1; j < nlist; j++) 1179c0b746e5SOllivier Robert server_list[j-1] = server_list[j]; 1180c0b746e5SOllivier Robert nlist--; 1181c0b746e5SOllivier Robert } 1182c0b746e5SOllivier Robert 1183c0b746e5SOllivier Robert /* 1184c0b746e5SOllivier Robert * What remains is a list of less than 5 servers. Take 1185c0b746e5SOllivier Robert * the best. 1186c0b746e5SOllivier Robert */ 1187c0b746e5SOllivier Robert sys_server = server_list[0]; 1188c0b746e5SOllivier Robert } 1189c0b746e5SOllivier Robert 1190c0b746e5SOllivier Robert /* 1191c0b746e5SOllivier Robert * That's it. Return our server. 1192c0b746e5SOllivier Robert */ 1193c0b746e5SOllivier Robert return sys_server; 1194c0b746e5SOllivier Robert } 1195c0b746e5SOllivier Robert 1196c0b746e5SOllivier Robert 1197c0b746e5SOllivier Robert /* 1198c0b746e5SOllivier Robert * clock_adjust - process what we've received, and adjust the time 1199c0b746e5SOllivier Robert * if we got anything decent. 1200c0b746e5SOllivier Robert */ 1201c0b746e5SOllivier Robert static int 1202c0b746e5SOllivier Robert clock_adjust(void) 1203c0b746e5SOllivier Robert { 1204c0b746e5SOllivier Robert register int i; 1205c0b746e5SOllivier Robert register struct server *server; 1206c0b746e5SOllivier Robert s_fp absoffset; 1207c0b746e5SOllivier Robert int dostep; 1208c0b746e5SOllivier Robert 1209c0b746e5SOllivier Robert for (i = 0; i < sys_numservers; i++) 1210c0b746e5SOllivier Robert clock_filter(sys_servers[i]); 1211c0b746e5SOllivier Robert server = clock_select(); 1212c0b746e5SOllivier Robert 1213c0b746e5SOllivier Robert if (debug || simple_query) { 1214c0b746e5SOllivier Robert for (i = 0; i < sys_numservers; i++) 1215c0b746e5SOllivier Robert printserver(sys_servers[i], stdout); 1216c0b746e5SOllivier Robert } 1217c0b746e5SOllivier Robert 1218c0b746e5SOllivier Robert if (server == 0) { 1219c0b746e5SOllivier Robert msyslog(LOG_ERR, 1220c0b746e5SOllivier Robert "no server suitable for synchronization found"); 1221c0b746e5SOllivier Robert return(1); 1222c0b746e5SOllivier Robert } 1223c0b746e5SOllivier Robert 1224c0b746e5SOllivier Robert if (always_step) { 1225c0b746e5SOllivier Robert dostep = 1; 1226c0b746e5SOllivier Robert } else if (never_step) { 1227c0b746e5SOllivier Robert dostep = 0; 1228c0b746e5SOllivier Robert } else { 1229c0b746e5SOllivier Robert absoffset = server->soffset; 1230c0b746e5SOllivier Robert if (absoffset < 0) 1231c0b746e5SOllivier Robert absoffset = -absoffset; 1232c0b746e5SOllivier Robert dostep = (absoffset >= NTPDATE_THRESHOLD); 1233c0b746e5SOllivier Robert } 1234c0b746e5SOllivier Robert 1235c0b746e5SOllivier Robert if (dostep) { 1236c0b746e5SOllivier Robert if (simple_query || l_step_systime(&server->offset)) { 1237c0b746e5SOllivier Robert msyslog(LOG_NOTICE, "step time server %s offset %s sec", 1238c0b746e5SOllivier Robert ntoa(&server->srcadr), 1239c0b746e5SOllivier Robert lfptoa(&server->offset, 6)); 1240c0b746e5SOllivier Robert } 1241c0b746e5SOllivier Robert } else { 1242c0b746e5SOllivier Robert #if !defined SYS_WINNT && !defined SYS_CYGWIN32 1243c0b746e5SOllivier Robert if (simple_query || l_adj_systime(&server->offset)) { 1244c0b746e5SOllivier Robert msyslog(LOG_NOTICE, "adjust time server %s offset %s sec", 1245c0b746e5SOllivier Robert ntoa(&server->srcadr), 1246c0b746e5SOllivier Robert lfptoa(&server->offset, 6)); 1247c0b746e5SOllivier Robert } 1248c0b746e5SOllivier Robert #else 1249c0b746e5SOllivier Robert /* The NT SetSystemTimeAdjustment() call achieves slewing by 1250c0b746e5SOllivier Robert * changing the clock frequency. This means that we cannot specify 1251c0b746e5SOllivier Robert * it to slew the clock by a definite amount and then stop like 1252c0b746e5SOllivier Robert * the Unix adjtime() routine. We can technically adjust the clock 1253c0b746e5SOllivier Robert * frequency, have ntpdate sleep for a while, and then wake 1254c0b746e5SOllivier Robert * up and reset the clock frequency, but this might cause some 1255c0b746e5SOllivier Robert * grief if the user attempts to run ntpd immediately after 1256c0b746e5SOllivier Robert * ntpdate and the socket is in use. 1257c0b746e5SOllivier Robert */ 1258c0b746e5SOllivier Robert printf("\nThe -b option is required by ntpdate on Windows NT platforms\n"); 1259c0b746e5SOllivier Robert exit(1); 1260c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 1261c0b746e5SOllivier Robert } 1262c0b746e5SOllivier Robert return(0); 1263c0b746e5SOllivier Robert } 1264c0b746e5SOllivier Robert 1265c0b746e5SOllivier Robert 1266c0b746e5SOllivier Robert /* XXX ELIMINATE: merge BIG slew into adj_systime in lib/systime.c */ 1267c0b746e5SOllivier Robert /* 1268c0b746e5SOllivier Robert * addserver - determine a server's address and allocate a new structure 1269c0b746e5SOllivier Robert * for it. 1270c0b746e5SOllivier Robert */ 1271c0b746e5SOllivier Robert static void 1272c0b746e5SOllivier Robert addserver( 1273c0b746e5SOllivier Robert char *serv 1274c0b746e5SOllivier Robert ) 1275c0b746e5SOllivier Robert { 1276c0b746e5SOllivier Robert register struct server *server; 1277c0b746e5SOllivier Robert u_int32 netnum; 1278c0b746e5SOllivier Robert static int toomany = 0; 1279c0b746e5SOllivier Robert 1280c0b746e5SOllivier Robert if (sys_numservers >= sys_maxservers) { 1281c0b746e5SOllivier Robert if (!toomany) { 1282c0b746e5SOllivier Robert /* 1283c0b746e5SOllivier Robert * This is actually a `can't happen' now. Leave 1284c0b746e5SOllivier Robert * the error message in anyway, though 1285c0b746e5SOllivier Robert */ 1286c0b746e5SOllivier Robert toomany = 1; 1287c0b746e5SOllivier Robert msyslog(LOG_ERR, 1288c0b746e5SOllivier Robert "too many servers (> %d) specified, remainder not used", 1289c0b746e5SOllivier Robert sys_maxservers); 1290c0b746e5SOllivier Robert } 1291c0b746e5SOllivier Robert return; 1292c0b746e5SOllivier Robert } 1293c0b746e5SOllivier Robert 1294c0b746e5SOllivier Robert if (!getnetnum(serv, &netnum)) { 1295c0b746e5SOllivier Robert msyslog(LOG_ERR, "can't find host %s\n", serv); 1296c0b746e5SOllivier Robert return; 1297c0b746e5SOllivier Robert } 1298c0b746e5SOllivier Robert 1299c0b746e5SOllivier Robert server = (struct server *)emalloc(sizeof(struct server)); 1300c0b746e5SOllivier Robert memset((char *)server, 0, sizeof(struct server)); 1301c0b746e5SOllivier Robert 1302c0b746e5SOllivier Robert server->srcadr.sin_family = AF_INET; 1303c0b746e5SOllivier Robert server->srcadr.sin_addr.s_addr = netnum; 1304c0b746e5SOllivier Robert server->srcadr.sin_port = htons(NTP_PORT); 1305c0b746e5SOllivier Robert 1306c0b746e5SOllivier Robert sys_servers[sys_numservers++] = server; 1307c0b746e5SOllivier Robert server->event_time = sys_numservers; 1308c0b746e5SOllivier Robert } 1309c0b746e5SOllivier Robert 1310c0b746e5SOllivier Robert 1311c0b746e5SOllivier Robert /* 1312c0b746e5SOllivier Robert * findserver - find a server in the list given its address 1313c0b746e5SOllivier Robert */ 1314c0b746e5SOllivier Robert static struct server * 1315c0b746e5SOllivier Robert findserver( 1316c0b746e5SOllivier Robert struct sockaddr_in *addr 1317c0b746e5SOllivier Robert ) 1318c0b746e5SOllivier Robert { 1319c0b746e5SOllivier Robert register int i; 1320c0b746e5SOllivier Robert register u_int32 netnum; 1321c0b746e5SOllivier Robert 1322c0b746e5SOllivier Robert if (htons(addr->sin_port) != NTP_PORT) 1323c0b746e5SOllivier Robert return 0; 1324c0b746e5SOllivier Robert netnum = addr->sin_addr.s_addr; 1325c0b746e5SOllivier Robert 1326c0b746e5SOllivier Robert for (i = 0; i < sys_numservers; i++) { 1327c0b746e5SOllivier Robert if (netnum == sys_servers[i]->srcadr.sin_addr.s_addr) 1328c0b746e5SOllivier Robert return sys_servers[i]; 1329c0b746e5SOllivier Robert } 1330c0b746e5SOllivier Robert return 0; 1331c0b746e5SOllivier Robert } 1332c0b746e5SOllivier Robert 1333c0b746e5SOllivier Robert 1334c0b746e5SOllivier Robert /* 1335c0b746e5SOllivier Robert * timer - process a timer interrupt 1336c0b746e5SOllivier Robert */ 1337c0b746e5SOllivier Robert void 1338c0b746e5SOllivier Robert timer(void) 1339c0b746e5SOllivier Robert { 1340c0b746e5SOllivier Robert register int i; 1341c0b746e5SOllivier Robert 1342c0b746e5SOllivier Robert /* 1343c0b746e5SOllivier Robert * Bump the current idea of the time 1344c0b746e5SOllivier Robert */ 1345c0b746e5SOllivier Robert current_time++; 1346c0b746e5SOllivier Robert 1347c0b746e5SOllivier Robert /* 1348c0b746e5SOllivier Robert * Search through the server list looking for guys 1349c0b746e5SOllivier Robert * who's event timers have expired. Give these to 1350c0b746e5SOllivier Robert * the transmit routine. 1351c0b746e5SOllivier Robert */ 1352c0b746e5SOllivier Robert for (i = 0; i < sys_numservers; i++) { 1353c0b746e5SOllivier Robert if (sys_servers[i]->event_time != 0 1354c0b746e5SOllivier Robert && sys_servers[i]->event_time <= current_time) 1355c0b746e5SOllivier Robert transmit(sys_servers[i]); 1356c0b746e5SOllivier Robert } 1357c0b746e5SOllivier Robert } 1358c0b746e5SOllivier Robert 1359c0b746e5SOllivier Robert 1360c0b746e5SOllivier Robert #ifndef SYS_WINNT 1361c0b746e5SOllivier Robert /* 1362c0b746e5SOllivier Robert * alarming - record the occurance of an alarm interrupt 1363c0b746e5SOllivier Robert */ 1364c0b746e5SOllivier Robert static RETSIGTYPE 1365c0b746e5SOllivier Robert alarming( 1366c0b746e5SOllivier Robert int sig 1367c0b746e5SOllivier Robert ) 1368c0b746e5SOllivier Robert #else 1369c0b746e5SOllivier Robert void CALLBACK 1370c0b746e5SOllivier Robert alarming(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) 1371c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 1372c0b746e5SOllivier Robert { 1373c0b746e5SOllivier Robert alarm_flag++; 1374c0b746e5SOllivier Robert } 1375c0b746e5SOllivier Robert 1376c0b746e5SOllivier Robert 1377c0b746e5SOllivier Robert /* 1378c0b746e5SOllivier Robert * init_alarm - set up the timer interrupt 1379c0b746e5SOllivier Robert */ 1380c0b746e5SOllivier Robert static void 1381c0b746e5SOllivier Robert init_alarm(void) 1382c0b746e5SOllivier Robert { 1383c0b746e5SOllivier Robert #ifndef SYS_WINNT 1384c0b746e5SOllivier Robert # ifndef HAVE_TIMER_SETTIME 1385c0b746e5SOllivier Robert struct itimerval itimer; 1386c0b746e5SOllivier Robert # else 1387c0b746e5SOllivier Robert struct itimerspec ntpdate_itimer; 1388c0b746e5SOllivier Robert # endif 1389c0b746e5SOllivier Robert #else 1390c0b746e5SOllivier Robert TIMECAPS tc; 1391c0b746e5SOllivier Robert UINT wTimerRes, wTimerID; 1392c0b746e5SOllivier Robert # endif /* SYS_WINNT */ 1393c0b746e5SOllivier Robert #if defined SYS_CYGWIN32 || defined SYS_WINNT 1394c0b746e5SOllivier Robert HANDLE hToken; 1395c0b746e5SOllivier Robert TOKEN_PRIVILEGES tkp; 1396c0b746e5SOllivier Robert DWORD dwUser = 0; 1397c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 1398c0b746e5SOllivier Robert 1399c0b746e5SOllivier Robert alarm_flag = 0; 1400c0b746e5SOllivier Robert 1401c0b746e5SOllivier Robert #ifndef SYS_WINNT 1402c0b746e5SOllivier Robert # if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME) 1403c0b746e5SOllivier Robert alarm_flag = 0; 1404c0b746e5SOllivier Robert /* this code was put in as setitimer() is non existant this us the 1405c0b746e5SOllivier Robert * POSIX "equivalents" setup - casey 1406c0b746e5SOllivier Robert */ 1407c0b746e5SOllivier Robert /* ntpdate_timerid is global - so we can kill timer later */ 1408c0b746e5SOllivier Robert if (timer_create (CLOCK_REALTIME, NULL, &ntpdate_timerid) == 1409c0b746e5SOllivier Robert # ifdef SYS_VXWORKS 1410c0b746e5SOllivier Robert ERROR 1411c0b746e5SOllivier Robert # else 1412c0b746e5SOllivier Robert -1 1413c0b746e5SOllivier Robert # endif 1414c0b746e5SOllivier Robert ) 1415c0b746e5SOllivier Robert { 1416c0b746e5SOllivier Robert fprintf (stderr, "init_alarm(): timer_create (...) FAILED\n"); 1417c0b746e5SOllivier Robert return; 1418c0b746e5SOllivier Robert } 1419c0b746e5SOllivier Robert 1420c0b746e5SOllivier Robert /* TIMER_HZ = (5) 1421c0b746e5SOllivier Robert * Set up the alarm interrupt. The first comes 1/(2*TIMER_HZ) 1422c0b746e5SOllivier Robert * seconds from now and they continue on every 1/TIMER_HZ seconds. 1423c0b746e5SOllivier Robert */ 1424c0b746e5SOllivier Robert (void) signal_no_reset(SIGALRM, alarming); 1425c0b746e5SOllivier Robert ntpdate_itimer.it_interval.tv_sec = ntpdate_itimer.it_value.tv_sec = 0; 1426c0b746e5SOllivier Robert ntpdate_itimer.it_interval.tv_nsec = 1000000000/TIMER_HZ; 1427c0b746e5SOllivier Robert ntpdate_itimer.it_value.tv_nsec = 1000000000/(TIMER_HZ<<1); 1428c0b746e5SOllivier Robert timer_settime(ntpdate_timerid, 0 /* !TIMER_ABSTIME */, &ntpdate_itimer, NULL); 1429c0b746e5SOllivier Robert # else 1430c0b746e5SOllivier Robert /* 1431c0b746e5SOllivier Robert * Set up the alarm interrupt. The first comes 1/(2*TIMER_HZ) 1432c0b746e5SOllivier Robert * seconds from now and they continue on every 1/TIMER_HZ seconds. 1433c0b746e5SOllivier Robert */ 1434c0b746e5SOllivier Robert (void) signal_no_reset(SIGALRM, alarming); 1435c0b746e5SOllivier Robert itimer.it_interval.tv_sec = itimer.it_value.tv_sec = 0; 1436c0b746e5SOllivier Robert itimer.it_interval.tv_usec = 1000000/TIMER_HZ; 1437c0b746e5SOllivier Robert itimer.it_value.tv_usec = 1000000/(TIMER_HZ<<1); 1438c0b746e5SOllivier Robert setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0); 1439c0b746e5SOllivier Robert # endif 1440c0b746e5SOllivier Robert #if defined SYS_CYGWIN32 1441c0b746e5SOllivier Robert /* 1442c0b746e5SOllivier Robert * Get previleges needed for fiddling with the clock 1443c0b746e5SOllivier Robert */ 1444c0b746e5SOllivier Robert 1445c0b746e5SOllivier Robert /* get the current process token handle */ 1446c0b746e5SOllivier Robert if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { 1447c0b746e5SOllivier Robert msyslog(LOG_ERR, "OpenProcessToken failed: %m"); 1448c0b746e5SOllivier Robert exit(1); 1449c0b746e5SOllivier Robert } 1450c0b746e5SOllivier Robert /* get the LUID for system-time privilege. */ 1451c0b746e5SOllivier Robert LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid); 1452c0b746e5SOllivier Robert tkp.PrivilegeCount = 1; /* one privilege to set */ 1453c0b746e5SOllivier Robert tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 1454c0b746e5SOllivier Robert /* get set-time privilege for this process. */ 1455c0b746e5SOllivier Robert AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0); 1456c0b746e5SOllivier Robert /* cannot test return value of AdjustTokenPrivileges. */ 1457c0b746e5SOllivier Robert if (GetLastError() != ERROR_SUCCESS) 1458c0b746e5SOllivier Robert msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m"); 1459c0b746e5SOllivier Robert #endif 1460c0b746e5SOllivier Robert #else /* SYS_WINNT */ 1461c0b746e5SOllivier Robert _tzset(); 1462c0b746e5SOllivier Robert 1463c0b746e5SOllivier Robert /* 1464c0b746e5SOllivier Robert * Get previleges needed for fiddling with the clock 1465c0b746e5SOllivier Robert */ 1466c0b746e5SOllivier Robert 1467c0b746e5SOllivier Robert /* get the current process token handle */ 1468c0b746e5SOllivier Robert if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { 1469c0b746e5SOllivier Robert msyslog(LOG_ERR, "OpenProcessToken failed: %m"); 1470c0b746e5SOllivier Robert exit(1); 1471c0b746e5SOllivier Robert } 1472c0b746e5SOllivier Robert /* get the LUID for system-time privilege. */ 1473c0b746e5SOllivier Robert LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid); 1474c0b746e5SOllivier Robert tkp.PrivilegeCount = 1; /* one privilege to set */ 1475c0b746e5SOllivier Robert tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 1476c0b746e5SOllivier Robert /* get set-time privilege for this process. */ 1477c0b746e5SOllivier Robert AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0); 1478c0b746e5SOllivier Robert /* cannot test return value of AdjustTokenPrivileges. */ 1479c0b746e5SOllivier Robert if (GetLastError() != ERROR_SUCCESS) 1480c0b746e5SOllivier Robert msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m"); 1481c0b746e5SOllivier Robert 1482c0b746e5SOllivier Robert /* 1483c0b746e5SOllivier Robert * Set up timer interrupts for every 2**EVENT_TIMEOUT seconds 1484c0b746e5SOllivier Robert * Under Win/NT, expiry of timer interval leads to invocation 1485c0b746e5SOllivier Robert * of a callback function (on a different thread) rather than 1486c0b746e5SOllivier Robert * generating an alarm signal 1487c0b746e5SOllivier Robert */ 1488c0b746e5SOllivier Robert 1489c0b746e5SOllivier Robert /* determine max and min resolution supported */ 1490c0b746e5SOllivier Robert if(timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) { 1491c0b746e5SOllivier Robert msyslog(LOG_ERR, "timeGetDevCaps failed: %m"); 1492c0b746e5SOllivier Robert exit(1); 1493c0b746e5SOllivier Robert } 1494c0b746e5SOllivier Robert wTimerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax); 1495c0b746e5SOllivier Robert /* establish the minimum timer resolution that we'll use */ 1496c0b746e5SOllivier Robert timeBeginPeriod(wTimerRes); 1497c0b746e5SOllivier Robert 1498c0b746e5SOllivier Robert /* start the timer event */ 1499c0b746e5SOllivier Robert wTimerID = timeSetEvent( 1500c0b746e5SOllivier Robert (UINT) (1000/TIMER_HZ), /* Delay */ 1501c0b746e5SOllivier Robert wTimerRes, /* Resolution */ 1502c0b746e5SOllivier Robert (LPTIMECALLBACK) alarming, /* Callback function */ 1503c0b746e5SOllivier Robert (DWORD) dwUser, /* User data */ 1504c0b746e5SOllivier Robert TIME_PERIODIC); /* Event type (periodic) */ 1505c0b746e5SOllivier Robert if (wTimerID == 0) { 1506c0b746e5SOllivier Robert msyslog(LOG_ERR, "timeSetEvent failed: %m"); 1507c0b746e5SOllivier Robert exit(1); 1508c0b746e5SOllivier Robert } 1509c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 1510c0b746e5SOllivier Robert } 1511c0b746e5SOllivier Robert 1512c0b746e5SOllivier Robert 1513c0b746e5SOllivier Robert 1514c0b746e5SOllivier Robert 1515c0b746e5SOllivier Robert /* 1516c0b746e5SOllivier Robert * We do asynchronous input using the SIGIO facility. A number of 1517c0b746e5SOllivier Robert * recvbuf buffers are preallocated for input. In the signal 1518c0b746e5SOllivier Robert * handler we poll to see if the socket is ready and read the 1519c0b746e5SOllivier Robert * packets from it into the recvbuf's along with a time stamp and 1520c0b746e5SOllivier Robert * an indication of the source host and the interface it was received 1521c0b746e5SOllivier Robert * through. This allows us to get as accurate receive time stamps 1522c0b746e5SOllivier Robert * as possible independent of other processing going on. 1523c0b746e5SOllivier Robert * 1524c0b746e5SOllivier Robert * We allocate a number of recvbufs equal to the number of servers 1525c0b746e5SOllivier Robert * plus 2. This should be plenty. 1526c0b746e5SOllivier Robert */ 1527c0b746e5SOllivier Robert 1528c0b746e5SOllivier Robert 1529c0b746e5SOllivier Robert /* 1530c0b746e5SOllivier Robert * init_io - initialize I/O data and open socket 1531c0b746e5SOllivier Robert */ 1532c0b746e5SOllivier Robert static void 1533c0b746e5SOllivier Robert init_io(void) 1534c0b746e5SOllivier Robert { 1535c0b746e5SOllivier Robert /* 1536c0b746e5SOllivier Robert * Init buffer free list and stat counters 1537c0b746e5SOllivier Robert */ 1538c0b746e5SOllivier Robert init_recvbuff(sys_numservers + 2); 1539c0b746e5SOllivier Robert /* 1540c0b746e5SOllivier Robert * Open the socket 1541c0b746e5SOllivier Robert */ 1542c0b746e5SOllivier Robert 1543c0b746e5SOllivier Robert /* create a datagram (UDP) socket */ 1544c0b746e5SOllivier Robert if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 1545c0b746e5SOllivier Robert msyslog(LOG_ERR, "socket() failed: %m"); 1546c0b746e5SOllivier Robert exit(1); 1547c0b746e5SOllivier Robert /*NOTREACHED*/ 1548c0b746e5SOllivier Robert } 1549c0b746e5SOllivier Robert 1550c0b746e5SOllivier Robert /* 1551c0b746e5SOllivier Robert * bind the socket to the NTP port 1552c0b746e5SOllivier Robert */ 1553c0b746e5SOllivier Robert if (!debug && !simple_query && !unpriv_port) { 1554c0b746e5SOllivier Robert struct sockaddr_in addr; 1555c0b746e5SOllivier Robert 1556c0b746e5SOllivier Robert memset((char *)&addr, 0, sizeof addr); 1557c0b746e5SOllivier Robert addr.sin_family = AF_INET; 1558c0b746e5SOllivier Robert addr.sin_port = htons(NTP_PORT); 1559c0b746e5SOllivier Robert addr.sin_addr.s_addr = htonl(INADDR_ANY); 1560c0b746e5SOllivier Robert if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 1561c0b746e5SOllivier Robert #ifndef SYS_WINNT 1562c0b746e5SOllivier Robert if (errno == EADDRINUSE) 1563c0b746e5SOllivier Robert #else 1564c0b746e5SOllivier Robert if (WSAGetLastError() == WSAEADDRINUSE) 1565c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 1566c0b746e5SOllivier Robert msyslog(LOG_ERR, 1567c0b746e5SOllivier Robert "the NTP socket is in use, exiting"); 1568c0b746e5SOllivier Robert else 1569c0b746e5SOllivier Robert msyslog(LOG_ERR, "bind() fails: %m"); 1570c0b746e5SOllivier Robert exit(1); 1571c0b746e5SOllivier Robert } 1572c0b746e5SOllivier Robert } 1573c0b746e5SOllivier Robert 1574c0b746e5SOllivier Robert #ifdef HAVE_POLL_H 1575c0b746e5SOllivier Robert fdmask.fd = fd; 1576c0b746e5SOllivier Robert fdmask.events = POLLIN; 1577c0b746e5SOllivier Robert #else 1578c0b746e5SOllivier Robert FD_ZERO(&fdmask); 1579c0b746e5SOllivier Robert FD_SET(fd, &fdmask); 1580c0b746e5SOllivier Robert #endif 1581c0b746e5SOllivier Robert 1582c0b746e5SOllivier Robert /* 1583c0b746e5SOllivier Robert * set non-blocking, 1584c0b746e5SOllivier Robert */ 1585c0b746e5SOllivier Robert #ifndef SYS_WINNT 1586c0b746e5SOllivier Robert # ifdef SYS_VXWORKS 1587c0b746e5SOllivier Robert { 1588c0b746e5SOllivier Robert int on = TRUE; 1589c0b746e5SOllivier Robert 1590c0b746e5SOllivier Robert if (ioctl(fd,FIONBIO, &on) == ERROR) { 1591c0b746e5SOllivier Robert msyslog(LOG_ERR, "ioctl(FIONBIO) fails: %m"); 1592c0b746e5SOllivier Robert exit(1); 1593c0b746e5SOllivier Robert } 1594c0b746e5SOllivier Robert } 1595c0b746e5SOllivier Robert # else /* not SYS_VXWORKS */ 1596c0b746e5SOllivier Robert # if defined(O_NONBLOCK) 1597c0b746e5SOllivier Robert if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { 1598c0b746e5SOllivier Robert msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m"); 1599c0b746e5SOllivier Robert exit(1); 1600c0b746e5SOllivier Robert /*NOTREACHED*/ 1601c0b746e5SOllivier Robert } 1602c0b746e5SOllivier Robert # else /* not O_NONBLOCK */ 1603c0b746e5SOllivier Robert # if defined(FNDELAY) 1604c0b746e5SOllivier Robert if (fcntl(fd, F_SETFL, FNDELAY) < 0) { 1605c0b746e5SOllivier Robert msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m"); 1606c0b746e5SOllivier Robert exit(1); 1607c0b746e5SOllivier Robert /*NOTREACHED*/ 1608c0b746e5SOllivier Robert } 1609c0b746e5SOllivier Robert # else /* FNDELAY */ 1610c0b746e5SOllivier Robert # include "Bletch: Need non blocking I/O" 1611c0b746e5SOllivier Robert # endif /* FNDELAY */ 1612c0b746e5SOllivier Robert # endif /* not O_NONBLOCK */ 1613c0b746e5SOllivier Robert # endif /* SYS_VXWORKS */ 1614c0b746e5SOllivier Robert #else /* SYS_WINNT */ 1615c0b746e5SOllivier Robert if (ioctlsocket(fd, FIONBIO, (u_long *) &on) == SOCKET_ERROR) { 1616c0b746e5SOllivier Robert msyslog(LOG_ERR, "ioctlsocket(FIONBIO) fails: %m"); 1617c0b746e5SOllivier Robert exit(1); 1618c0b746e5SOllivier Robert } 1619c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 1620c0b746e5SOllivier Robert } 1621c0b746e5SOllivier Robert 1622c0b746e5SOllivier Robert 1623c0b746e5SOllivier Robert /* 1624c0b746e5SOllivier Robert * sendpkt - send a packet to the specified destination 1625c0b746e5SOllivier Robert */ 1626c0b746e5SOllivier Robert static void 1627c0b746e5SOllivier Robert sendpkt( 1628c0b746e5SOllivier Robert struct sockaddr_in *dest, 1629c0b746e5SOllivier Robert struct pkt *pkt, 1630c0b746e5SOllivier Robert int len 1631c0b746e5SOllivier Robert ) 1632c0b746e5SOllivier Robert { 1633c0b746e5SOllivier Robert int cc; 1634c0b746e5SOllivier Robert 1635c0b746e5SOllivier Robert #ifdef SYS_WINNT 1636c0b746e5SOllivier Robert DWORD err; 1637c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 1638c0b746e5SOllivier Robert 1639c0b746e5SOllivier Robert cc = sendto(fd, (char *)pkt, len, 0, (struct sockaddr *)dest, 1640c0b746e5SOllivier Robert sizeof(struct sockaddr_in)); 1641c0b746e5SOllivier Robert #ifndef SYS_WINNT 1642c0b746e5SOllivier Robert if (cc == -1) { 1643c0b746e5SOllivier Robert if (errno != EWOULDBLOCK && errno != ENOBUFS) 1644c0b746e5SOllivier Robert #else 1645c0b746e5SOllivier Robert if (cc == SOCKET_ERROR) { 1646c0b746e5SOllivier Robert err = WSAGetLastError(); 1647c0b746e5SOllivier Robert if (err != WSAEWOULDBLOCK && err != WSAENOBUFS) 1648c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 1649c0b746e5SOllivier Robert msyslog(LOG_ERR, "sendto(%s): %m", ntoa(dest)); 1650c0b746e5SOllivier Robert } 1651c0b746e5SOllivier Robert } 1652c0b746e5SOllivier Robert 1653c0b746e5SOllivier Robert 1654c0b746e5SOllivier Robert /* 1655c0b746e5SOllivier Robert * input_handler - receive packets asynchronously 1656c0b746e5SOllivier Robert */ 1657c0b746e5SOllivier Robert void 1658c0b746e5SOllivier Robert input_handler(void) 1659c0b746e5SOllivier Robert { 1660c0b746e5SOllivier Robert register int n; 1661c0b746e5SOllivier Robert register struct recvbuf *rb; 1662c0b746e5SOllivier Robert struct timeval tvzero; 1663c0b746e5SOllivier Robert int fromlen; 1664c0b746e5SOllivier Robert l_fp ts; 1665c0b746e5SOllivier Robert #ifdef HAVE_POLL_H 1666c0b746e5SOllivier Robert struct pollfd fds; 1667c0b746e5SOllivier Robert #else 1668c0b746e5SOllivier Robert fd_set fds; 1669c0b746e5SOllivier Robert #endif 1670c0b746e5SOllivier Robert 1671c0b746e5SOllivier Robert /* 1672c0b746e5SOllivier Robert * Do a poll to see if we have data 1673c0b746e5SOllivier Robert */ 1674c0b746e5SOllivier Robert for (;;) { 1675c0b746e5SOllivier Robert fds = fdmask; 1676c0b746e5SOllivier Robert tvzero.tv_sec = tvzero.tv_usec = 0; 1677c0b746e5SOllivier Robert #ifdef HAVE_POLL_H 1678c0b746e5SOllivier Robert n = poll(&fds, 1, tvzero.tv_sec * 1000); 1679c0b746e5SOllivier Robert #else 1680c0b746e5SOllivier Robert n = select(fd+1, &fds, (fd_set *)0, (fd_set *)0, &tvzero); 1681c0b746e5SOllivier Robert #endif 1682c0b746e5SOllivier Robert 1683c0b746e5SOllivier Robert /* 1684c0b746e5SOllivier Robert * If nothing to do, just return. If an error occurred, 1685c0b746e5SOllivier Robert * complain and return. If we've got some, freeze a 1686c0b746e5SOllivier Robert * timestamp. 1687c0b746e5SOllivier Robert */ 1688c0b746e5SOllivier Robert if (n == 0) 1689c0b746e5SOllivier Robert return; 1690c0b746e5SOllivier Robert else if (n == -1) { 1691c0b746e5SOllivier Robert if (errno != EINTR) 1692c0b746e5SOllivier Robert msyslog(LOG_ERR, 1693c0b746e5SOllivier Robert #ifdef HAVE_POLL_H 1694c0b746e5SOllivier Robert "poll() error: %m" 1695c0b746e5SOllivier Robert #else 1696c0b746e5SOllivier Robert "select() error: %m" 1697c0b746e5SOllivier Robert #endif 1698c0b746e5SOllivier Robert ); 1699c0b746e5SOllivier Robert return; 1700c0b746e5SOllivier Robert } 1701c0b746e5SOllivier Robert get_systime(&ts); 1702c0b746e5SOllivier Robert 1703c0b746e5SOllivier Robert /* 1704c0b746e5SOllivier Robert * Get a buffer and read the frame. If we 1705c0b746e5SOllivier Robert * haven't got a buffer, or this is received 1706c0b746e5SOllivier Robert * on the wild card socket, just dump the packet. 1707c0b746e5SOllivier Robert */ 1708c0b746e5SOllivier Robert if (initializing || free_recvbuffs() == 0) { 1709c0b746e5SOllivier Robert char buf[100]; 1710c0b746e5SOllivier Robert 1711c0b746e5SOllivier Robert #ifndef SYS_WINNT 1712c0b746e5SOllivier Robert (void) read(fd, buf, sizeof buf); 1713c0b746e5SOllivier Robert #else 1714c0b746e5SOllivier Robert /* NT's _read does not operate on nonblocking sockets 1715c0b746e5SOllivier Robert * either recvfrom or ReadFile() has to be used here. 1716c0b746e5SOllivier Robert * ReadFile is used in [ntpd]ntp_intres() and ntpdc, 1717c0b746e5SOllivier Robert * just to be different use recvfrom() here 1718c0b746e5SOllivier Robert */ 1719c0b746e5SOllivier Robert recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)0, NULL); 1720c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 1721c0b746e5SOllivier Robert continue; 1722c0b746e5SOllivier Robert } 1723c0b746e5SOllivier Robert 1724c0b746e5SOllivier Robert rb = get_free_recv_buffer(); 1725c0b746e5SOllivier Robert 1726c0b746e5SOllivier Robert fromlen = sizeof(struct sockaddr_in); 1727c0b746e5SOllivier Robert rb->recv_length = recvfrom(fd, (char *)&rb->recv_pkt, 1728c0b746e5SOllivier Robert sizeof(rb->recv_pkt), 0, 1729c0b746e5SOllivier Robert (struct sockaddr *)&rb->recv_srcadr, &fromlen); 1730c0b746e5SOllivier Robert if (rb->recv_length == -1) { 1731c0b746e5SOllivier Robert freerecvbuf(rb); 1732c0b746e5SOllivier Robert continue; 1733c0b746e5SOllivier Robert } 1734c0b746e5SOllivier Robert 1735c0b746e5SOllivier Robert /* 1736c0b746e5SOllivier Robert * Got one. Mark how and when it got here, 1737c0b746e5SOllivier Robert * put it on the full list. 1738c0b746e5SOllivier Robert */ 1739c0b746e5SOllivier Robert rb->recv_time = ts; 1740c0b746e5SOllivier Robert add_full_recv_buffer(rb); 1741c0b746e5SOllivier Robert } 1742c0b746e5SOllivier Robert } 1743c0b746e5SOllivier Robert 1744c0b746e5SOllivier Robert 1745c0b746e5SOllivier Robert #if !defined SYS_WINNT && !defined SYS_CYGWIN32 1746c0b746e5SOllivier Robert /* 1747c0b746e5SOllivier Robert * adj_systime - do a big long slew of the system time 1748c0b746e5SOllivier Robert */ 1749c0b746e5SOllivier Robert static int 1750c0b746e5SOllivier Robert l_adj_systime( 1751c0b746e5SOllivier Robert l_fp *ts 1752c0b746e5SOllivier Robert ) 1753c0b746e5SOllivier Robert { 1754c0b746e5SOllivier Robert struct timeval adjtv, oadjtv; 1755c0b746e5SOllivier Robert int isneg = 0; 1756c0b746e5SOllivier Robert l_fp offset; 1757c0b746e5SOllivier Robert #ifndef STEP_SLEW 1758c0b746e5SOllivier Robert l_fp overshoot; 1759c0b746e5SOllivier Robert #endif 1760c0b746e5SOllivier Robert 1761c0b746e5SOllivier Robert /* 1762c0b746e5SOllivier Robert * Take the absolute value of the offset 1763c0b746e5SOllivier Robert */ 1764c0b746e5SOllivier Robert offset = *ts; 1765c0b746e5SOllivier Robert if (L_ISNEG(&offset)) { 1766c0b746e5SOllivier Robert isneg = 1; 1767c0b746e5SOllivier Robert L_NEG(&offset); 1768c0b746e5SOllivier Robert } 1769c0b746e5SOllivier Robert 1770c0b746e5SOllivier Robert #ifndef STEP_SLEW 1771c0b746e5SOllivier Robert /* 1772c0b746e5SOllivier Robert * Calculate the overshoot. XXX N.B. This code *knows* 1773c0b746e5SOllivier Robert * ADJ_OVERSHOOT is 1/2. 1774c0b746e5SOllivier Robert */ 1775c0b746e5SOllivier Robert overshoot = offset; 1776c0b746e5SOllivier Robert L_RSHIFTU(&overshoot); 1777c0b746e5SOllivier Robert if (overshoot.l_ui != 0 || (overshoot.l_uf > ADJ_MAXOVERSHOOT)) { 1778c0b746e5SOllivier Robert overshoot.l_ui = 0; 1779c0b746e5SOllivier Robert overshoot.l_uf = ADJ_MAXOVERSHOOT; 1780c0b746e5SOllivier Robert } 1781c0b746e5SOllivier Robert L_ADD(&offset, &overshoot); 1782c0b746e5SOllivier Robert #endif 1783c0b746e5SOllivier Robert TSTOTV(&offset, &adjtv); 1784c0b746e5SOllivier Robert 1785c0b746e5SOllivier Robert if (isneg) { 1786c0b746e5SOllivier Robert adjtv.tv_sec = -adjtv.tv_sec; 1787c0b746e5SOllivier Robert adjtv.tv_usec = -adjtv.tv_usec; 1788c0b746e5SOllivier Robert } 1789c0b746e5SOllivier Robert 1790c0b746e5SOllivier Robert if (adjtv.tv_usec != 0 && !debug) { 1791c0b746e5SOllivier Robert if (adjtime(&adjtv, &oadjtv) < 0) { 1792c0b746e5SOllivier Robert msyslog(LOG_ERR, "Can't adjust the time of day: %m"); 1793c0b746e5SOllivier Robert return 0; 1794c0b746e5SOllivier Robert } 1795c0b746e5SOllivier Robert } 1796c0b746e5SOllivier Robert return 1; 1797c0b746e5SOllivier Robert } 1798c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 1799c0b746e5SOllivier Robert 1800c0b746e5SOllivier Robert 1801c0b746e5SOllivier Robert /* 1802c0b746e5SOllivier Robert * This fuction is not the same as lib/systime step_systime!!! 1803c0b746e5SOllivier Robert */ 1804c0b746e5SOllivier Robert static int 1805c0b746e5SOllivier Robert l_step_systime( 1806c0b746e5SOllivier Robert l_fp *ts 1807c0b746e5SOllivier Robert ) 1808c0b746e5SOllivier Robert { 1809c0b746e5SOllivier Robert double dtemp; 1810c0b746e5SOllivier Robert 1811c0b746e5SOllivier Robert #ifdef SLEWALWAYS 1812c0b746e5SOllivier Robert #ifdef STEP_SLEW 1813c0b746e5SOllivier Robert l_fp ftmp; 1814c0b746e5SOllivier Robert int isneg; 1815c0b746e5SOllivier Robert int n; 1816c0b746e5SOllivier Robert 1817c0b746e5SOllivier Robert if (debug) return 1; 1818c0b746e5SOllivier Robert /* 1819c0b746e5SOllivier Robert * Take the absolute value of the offset 1820c0b746e5SOllivier Robert */ 1821c0b746e5SOllivier Robert ftmp = *ts; 1822c0b746e5SOllivier Robert if (L_ISNEG(&ftmp)) { 1823c0b746e5SOllivier Robert L_NEG(&ftmp); 1824c0b746e5SOllivier Robert isneg = 1; 1825c0b746e5SOllivier Robert } else 1826c0b746e5SOllivier Robert isneg = 0; 1827c0b746e5SOllivier Robert 1828c0b746e5SOllivier Robert if (ftmp.l_ui >= 3) { /* Step it and slew - we might win */ 1829c0b746e5SOllivier Robert n = step_systime(ts); 1830c0b746e5SOllivier Robert if (!n) 1831c0b746e5SOllivier Robert return n; 1832c0b746e5SOllivier Robert if (isneg) 1833c0b746e5SOllivier Robert ts->l_ui = ~0; 1834c0b746e5SOllivier Robert else 1835c0b746e5SOllivier Robert ts->l_ui = ~0; 1836c0b746e5SOllivier Robert } 1837c0b746e5SOllivier Robert /* 1838c0b746e5SOllivier Robert * Just add adjustment into the current offset. The update 1839c0b746e5SOllivier Robert * routine will take care of bringing the system clock into 1840c0b746e5SOllivier Robert * line. 1841c0b746e5SOllivier Robert */ 1842c0b746e5SOllivier Robert #endif 1843c0b746e5SOllivier Robert if (debug) 1844c0b746e5SOllivier Robert return 1; 1845c0b746e5SOllivier Robert #ifdef FORCE_NTPDATE_STEP 1846c0b746e5SOllivier Robert LFPTOD(ts, dtemp); 1847c0b746e5SOllivier Robert return step_systime(dtemp); 1848c0b746e5SOllivier Robert #else 1849c0b746e5SOllivier Robert l_adj_systime(ts); 1850c0b746e5SOllivier Robert return 1; 1851c0b746e5SOllivier Robert #endif 1852c0b746e5SOllivier Robert #else /* SLEWALWAYS */ 1853c0b746e5SOllivier Robert if (debug) 1854c0b746e5SOllivier Robert return 1; 1855c0b746e5SOllivier Robert LFPTOD(ts, dtemp); 1856c0b746e5SOllivier Robert return step_systime(dtemp); 1857c0b746e5SOllivier Robert #endif /* SLEWALWAYS */ 1858c0b746e5SOllivier Robert } 1859c0b746e5SOllivier Robert 1860c0b746e5SOllivier Robert /* 1861c0b746e5SOllivier Robert * getnetnum - given a host name, return its net number 1862c0b746e5SOllivier Robert */ 1863c0b746e5SOllivier Robert static int 1864c0b746e5SOllivier Robert getnetnum( 1865c0b746e5SOllivier Robert const char *host, 1866c0b746e5SOllivier Robert u_int32 *num 1867c0b746e5SOllivier Robert ) 1868c0b746e5SOllivier Robert { 1869c0b746e5SOllivier Robert struct hostent *hp; 1870c0b746e5SOllivier Robert 1871c0b746e5SOllivier Robert if (decodenetnum(host, num)) { 1872c0b746e5SOllivier Robert return 1; 1873c0b746e5SOllivier Robert } else if ((hp = gethostbyname(host)) != 0) { 1874c0b746e5SOllivier Robert memmove((char *)num, hp->h_addr, sizeof(u_int32)); 1875c0b746e5SOllivier Robert return (1); 1876c0b746e5SOllivier Robert } 1877c0b746e5SOllivier Robert return (0); 1878c0b746e5SOllivier Robert } 1879c0b746e5SOllivier Robert 1880c0b746e5SOllivier Robert /* XXX ELIMINATE printserver similar in ntptrace.c, ntpdate.c */ 1881c0b746e5SOllivier Robert /* 1882c0b746e5SOllivier Robert * printserver - print detail information for a server 1883c0b746e5SOllivier Robert */ 1884c0b746e5SOllivier Robert static void 1885c0b746e5SOllivier Robert printserver( 1886c0b746e5SOllivier Robert register struct server *pp, 1887c0b746e5SOllivier Robert FILE *fp 1888c0b746e5SOllivier Robert ) 1889c0b746e5SOllivier Robert { 1890c0b746e5SOllivier Robert register int i; 1891c0b746e5SOllivier Robert char junk[5]; 1892c0b746e5SOllivier Robert char *str; 1893c0b746e5SOllivier Robert 1894c0b746e5SOllivier Robert if (!debug) { 1895c0b746e5SOllivier Robert (void) fprintf(fp, "server %s, stratum %d, offset %s, delay %s\n", 1896c0b746e5SOllivier Robert ntoa(&pp->srcadr), pp->stratum, 1897c0b746e5SOllivier Robert lfptoa(&pp->offset, 6), fptoa((s_fp)pp->delay, 5)); 1898c0b746e5SOllivier Robert return; 1899c0b746e5SOllivier Robert } 1900c0b746e5SOllivier Robert 1901c0b746e5SOllivier Robert (void) fprintf(fp, "server %s, port %d\n", 1902c0b746e5SOllivier Robert ntoa(&pp->srcadr), ntohs(pp->srcadr.sin_port)); 1903c0b746e5SOllivier Robert 1904c0b746e5SOllivier Robert (void) fprintf(fp, "stratum %d, precision %d, leap %c%c, trust %03o\n", 1905c0b746e5SOllivier Robert pp->stratum, pp->precision, 1906c0b746e5SOllivier Robert pp->leap & 0x2 ? '1' : '0', 1907c0b746e5SOllivier Robert pp->leap & 0x1 ? '1' : '0', 1908c0b746e5SOllivier Robert pp->trust); 1909c0b746e5SOllivier Robert 1910c0b746e5SOllivier Robert if (pp->stratum == 1) { 1911c0b746e5SOllivier Robert junk[4] = 0; 1912c0b746e5SOllivier Robert memmove(junk, (char *)&pp->refid, 4); 1913c0b746e5SOllivier Robert str = junk; 1914c0b746e5SOllivier Robert } else { 1915c0b746e5SOllivier Robert str = numtoa(pp->refid); 1916c0b746e5SOllivier Robert } 1917c0b746e5SOllivier Robert (void) fprintf(fp, 1918c0b746e5SOllivier Robert "refid [%s], delay %s, dispersion %s\n", 1919c0b746e5SOllivier Robert str, fptoa((s_fp)pp->delay, 5), 1920c0b746e5SOllivier Robert ufptoa(pp->dispersion, 5)); 1921c0b746e5SOllivier Robert 1922c0b746e5SOllivier Robert (void) fprintf(fp, "transmitted %d, in filter %d\n", 1923c0b746e5SOllivier Robert pp->xmtcnt, pp->filter_nextpt); 1924c0b746e5SOllivier Robert 1925c0b746e5SOllivier Robert (void) fprintf(fp, "reference time: %s\n", 1926c0b746e5SOllivier Robert prettydate(&pp->reftime)); 1927c0b746e5SOllivier Robert (void) fprintf(fp, "originate timestamp: %s\n", 1928c0b746e5SOllivier Robert prettydate(&pp->org)); 1929c0b746e5SOllivier Robert (void) fprintf(fp, "transmit timestamp: %s\n", 1930c0b746e5SOllivier Robert prettydate(&pp->xmt)); 1931c0b746e5SOllivier Robert 1932c0b746e5SOllivier Robert (void) fprintf(fp, "filter delay: "); 1933c0b746e5SOllivier Robert for (i = 0; i < NTP_SHIFT; i++) { 1934c0b746e5SOllivier Robert (void) fprintf(fp, " %-8.8s", fptoa(pp->filter_delay[i], 5)); 1935c0b746e5SOllivier Robert if (i == (NTP_SHIFT>>1)-1) 1936c0b746e5SOllivier Robert (void) fprintf(fp, "\n "); 1937c0b746e5SOllivier Robert } 1938c0b746e5SOllivier Robert (void) fprintf(fp, "\n"); 1939c0b746e5SOllivier Robert 1940c0b746e5SOllivier Robert (void) fprintf(fp, "filter offset:"); 1941c0b746e5SOllivier Robert for (i = 0; i < PEER_SHIFT; i++) { 1942c0b746e5SOllivier Robert (void) fprintf(fp, " %-8.8s", lfptoa(&pp->filter_offset[i], 6)); 1943c0b746e5SOllivier Robert if (i == (PEER_SHIFT>>1)-1) 1944c0b746e5SOllivier Robert (void) fprintf(fp, "\n "); 1945c0b746e5SOllivier Robert } 1946c0b746e5SOllivier Robert (void) fprintf(fp, "\n"); 1947c0b746e5SOllivier Robert 1948c0b746e5SOllivier Robert (void) fprintf(fp, "delay %s, dispersion %s\n", 1949c0b746e5SOllivier Robert fptoa((s_fp)pp->delay, 5), ufptoa(pp->dispersion, 5)); 1950c0b746e5SOllivier Robert 1951c0b746e5SOllivier Robert (void) fprintf(fp, "offset %s\n\n", 1952c0b746e5SOllivier Robert lfptoa(&pp->offset, 6)); 1953c0b746e5SOllivier Robert } 1954c0b746e5SOllivier Robert 1955c0b746e5SOllivier Robert #if !defined(HAVE_VSPRINTF) 1956c0b746e5SOllivier Robert int 1957c0b746e5SOllivier Robert vsprintf( 1958c0b746e5SOllivier Robert char *str, 1959c0b746e5SOllivier Robert const char *fmt, 1960c0b746e5SOllivier Robert va_list ap 1961c0b746e5SOllivier Robert ) 1962c0b746e5SOllivier Robert { 1963c0b746e5SOllivier Robert FILE f; 1964c0b746e5SOllivier Robert int len; 1965c0b746e5SOllivier Robert 1966c0b746e5SOllivier Robert f._flag = _IOWRT+_IOSTRG; 1967c0b746e5SOllivier Robert f._ptr = str; 1968c0b746e5SOllivier Robert f._cnt = 32767; 1969c0b746e5SOllivier Robert len = _doprnt(fmt, ap, &f); 1970c0b746e5SOllivier Robert *f._ptr = 0; 1971c0b746e5SOllivier Robert return (len); 1972c0b746e5SOllivier Robert } 1973c0b746e5SOllivier Robert #endif 1974c0b746e5SOllivier Robert 1975c0b746e5SOllivier Robert #if 0 1976c0b746e5SOllivier Robert /* override function in library since SA_RESTART makes ALL syscalls restart */ 1977c0b746e5SOllivier Robert #ifdef SA_RESTART 1978c0b746e5SOllivier Robert void 1979c0b746e5SOllivier Robert signal_no_reset( 1980c0b746e5SOllivier Robert int sig, 1981c0b746e5SOllivier Robert void (*func)() 1982c0b746e5SOllivier Robert ) 1983c0b746e5SOllivier Robert { 1984c0b746e5SOllivier Robert int n; 1985c0b746e5SOllivier Robert struct sigaction vec; 1986c0b746e5SOllivier Robert 1987c0b746e5SOllivier Robert vec.sa_handler = func; 1988c0b746e5SOllivier Robert sigemptyset(&vec.sa_mask); 1989c0b746e5SOllivier Robert vec.sa_flags = 0; 1990c0b746e5SOllivier Robert 1991c0b746e5SOllivier Robert while (1) 1992c0b746e5SOllivier Robert { 1993c0b746e5SOllivier Robert n = sigaction(sig, &vec, NULL); 1994c0b746e5SOllivier Robert if (n == -1 && errno == EINTR) 1995c0b746e5SOllivier Robert continue; 1996c0b746e5SOllivier Robert break; 1997c0b746e5SOllivier Robert } 1998c0b746e5SOllivier Robert if (n == -1) 1999c0b746e5SOllivier Robert { 2000c0b746e5SOllivier Robert perror("sigaction"); 2001c0b746e5SOllivier Robert exit(1); 2002c0b746e5SOllivier Robert } 2003c0b746e5SOllivier Robert } 2004c0b746e5SOllivier Robert #endif 2005c0b746e5SOllivier Robert #endif 2006c0b746e5SOllivier Robert 2007c0b746e5SOllivier Robert #ifdef HAVE_NETINFO 2008c0b746e5SOllivier Robert static ni_namelist * 2009c0b746e5SOllivier Robert getnetinfoservers(void) 2010c0b746e5SOllivier Robert { 2011c0b746e5SOllivier Robert ni_status status; 2012c0b746e5SOllivier Robert void *domain; 2013c0b746e5SOllivier Robert ni_id confdir; 2014c0b746e5SOllivier Robert ni_namelist *namelist = (ni_namelist*)malloc(sizeof(ni_namelist)); 2015c0b746e5SOllivier Robert 2016c0b746e5SOllivier Robert /* Find a time server in NetInfo */ 2017c0b746e5SOllivier Robert if ((status = ni_open(NULL, ".", &domain)) != NI_OK) return NULL; 2018c0b746e5SOllivier Robert 2019c0b746e5SOllivier Robert while (status = ni_pathsearch(domain, &confdir, NETINFO_CONFIG_DIR) == NI_NODIR) { 2020c0b746e5SOllivier Robert void *next_domain; 2021c0b746e5SOllivier Robert if (ni_open(domain, "..", &next_domain) != NI_OK) break; 2022c0b746e5SOllivier Robert ni_free(domain); 2023c0b746e5SOllivier Robert domain = next_domain; 2024c0b746e5SOllivier Robert } 2025c0b746e5SOllivier Robert if (status != NI_OK) return NULL; 2026c0b746e5SOllivier Robert 2027c0b746e5SOllivier Robert NI_INIT(namelist); 2028c0b746e5SOllivier Robert if (ni_lookupprop(domain, &confdir, "server", namelist) != NI_OK) { 2029c0b746e5SOllivier Robert ni_namelist_free(namelist); 2030c0b746e5SOllivier Robert free(namelist); 2031c0b746e5SOllivier Robert return NULL; 2032c0b746e5SOllivier Robert } 2033c0b746e5SOllivier Robert 2034c0b746e5SOllivier Robert return(namelist); 2035c0b746e5SOllivier Robert } 2036c0b746e5SOllivier Robert #endif 2037