File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / ntpdate / ntptimeset.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 7 months ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    1: /*
    2:  * ntptimeset - get/set the time via ntp
    3:  *
    4:  * GOAL:
    5:  * The goal of ntptime is to set the current time on system startup
    6:  * to the best possible time using the network very wisely. It is assumed
    7:  * that after a resonable time has been sett then ntp daemon will
    8:  * maintain it.
    9:  *
   10:  * PROBLEM DOMAIN:
   11:  * We have three sets of issues related to acheiving the goal. The first
   12:  * issue is using the network when normal traffic is happening or when
   13:  * the entire network world is recovering from a campus wide power failure
   14:  * and is restarting. The second issue is the class of machine whether it
   15:  * is a user's office workstation being handled by an uneducated user or
   16:  * a server computer being handled by a trained operations staff. The third
   17:  * issue is whether the ratio of people to computers and whether the 
   18:  * environment is stable and viable or not.
   19:  *
   20:  * NETWORK USAGE:
   21:  * The first issue of using the network wisely is a question of whether
   22:  * the network load and time server load and state are normal. If things
   23:  * are normal ntptime can do what ntpdate does of sending out 4 packets
   24:  * quickly to each server (new transmit done with each ack). However
   25:  * if network or time load is high then this scheme will simply contribute
   26:  * to problems. Given we have minimal state, we simply weight lost packets
   27:  * significantly and make sure we throttle output as much as possible
   28:  * without performance lost for quick startups.
   29:  *
   30:  * TRAINING AND KNOWLEDGE:
   31:  * The second issue of uneducated user of a office workstation versus a
   32:  * trained operation staff of a server machine translates into simply an
   33:  * issue of untrained and trained users.
   34:  * 
   35:  * The training issue implies that for the sake of the users involved in the
   36:  * handling of their office workstation, problems and options should be
   37:  * communicated simply and effectively and not in terse expert related
   38:  * descriptions without possible options to be taken. The operator's training
   39:  * and education enables them to deal with either type of communication and
   40:  * control.
   41:  *
   42:  * AUTOMATION AND MANUAL CONTROL:
   43:  * The last issue boils down to a design problem. If the design tends to go
   44:  * into a manual mode when the environment is non-viable then one person
   45:  * handling many computers all at the same time will be heavily impacted. On
   46:  * the other hand, if the design tends to be automatic and does not indicate
   47:  * a way for the user to take over control then the computer will be
   48:  * unavailable for the user until the proble is resolved by someone else or
   49:  * the user.
   50:  *
   51:  * NOTE: Please do not have this program print out every minute some line,
   52:  *       of output. If this happens and the environment is in trouble then
   53:  *       many pages of paper on many different machines will be filled up.
   54:  *       Save some tress in your lifetime.
   55:  * 
   56:  * CONCLUSION:
   57:  * The behavior of the program derived from these three issues should be
   58:  * that during normal situations it quickly sets the time and allow the
   59:  * system to startup.
   60:  *
   61:  * However during abnormal conditions as detected by unresponsive servers,
   62:  * out-of-sync or bad responses and other detections, it should print out
   63:  * a simple but clear message and continue in a mellow way to get the best
   64:  * possible time. It may never get the time and if so should also indicate
   65:  * this.
   66:  *
   67:  * Rudy Nedved
   68:  * 18-May-1993
   69:  *
   70:  ****************************************************************
   71:  *
   72:  * Much of the above is confusing or no longer relevant.  For example,
   73:  * it is rare these days for a machine's console to be a printing terminal,
   74:  * so the comment about saving trees doesn't mean much.  Nonetheless,
   75:  * the basic principles still stand:
   76:  *
   77:  * - Work automatically, without human control or intervention.  To
   78:  *   this end, we use the same configuration file as ntpd itself, so
   79:  *   you don't have to specify servers or other information on the
   80:  *   command line.  We also recognize that sometimes we won't be able
   81:  *   to contact any servers, and give up in that event instead of
   82:  *   hanging forever.
   83:  *
   84:  * - Behave in a sane way, both internally and externally, even in the
   85:  *   face of insane conditions.  That means we back off quickly when
   86:  *   we don't hear a response, to avoid network congestion.  Like
   87:  *   ntpd, we verify responses from several servers before accepting
   88:  *   the new time data.
   89:  *
   90:  *   However, we don't assume that the local clock is right, or even
   91:  *   close, because it might not be at boot time, and we want to catch
   92:  *   and correct that situation.  This behaviour has saved us in several
   93:  *   instances.  On HP-UX 9.0x, there used to be a bug in adjtimed which
   94:  *   would cause the time to be set to some wild value, making the machine
   95:  *   essentially unusable (we use Kerberos authentication pervasively,
   96:  *   and it requires workstations and servers to have a time within five
   97:  *   minutes of the Kerberos server).  We also have problems on PC's
   98:  *   running both Linux and some Microsoft OS -- they tend to disagree
   99:  *   on what the BIOS clock should say, and who should update it, and
  100:  *   when.  On those systems, we not only run ntptimeset at boot, we
  101:  *   also reset the BIOS clock based on the result, so the correct
  102:  *   time will be retained across reboots.
  103:  *
  104:  * For these reasons, and others, we have continued to use this tool
  105:  * rather than ntpdate.  It is run automatically at boot time on every
  106:  * workstation and server in our facility.
  107:  *
  108:  * In the past, we called this program 'ntptime'.  Unfortunately, the
  109:  * ntp v4 distribution also includes a program with that name.  In
  110:  * order to avoid confusion, we have renamed our program 'ntptimeset',
  111:  * which more accurately describes what it does.
  112:  *
  113:  * Jeffrey T. Hutzelman (N3NHS) <jhutz+@cmu.edu>
  114:  * School of Computer Science - Research Computing Facility
  115:  * Carnegie Mellon University - Pittsburgh, PA
  116:  * 16-Aug-1999
  117:  *
  118:  */
  119: 
  120: #ifdef HAVE_CONFIG_H
  121: # include <config.h>
  122: #endif
  123: 
  124: #include "ntp_machine.h"
  125: #include "ntp_fp.h"
  126: #include "ntp.h"
  127: #include "ntp_io.h"
  128: #include "iosignal.h"
  129: #include "ntp_unixtime.h"
  130: #include "ntpdate.h"
  131: #include "ntp_string.h"
  132: #include "ntp_syslog.h"
  133: #include "ntp_select.h"
  134: #include "ntp_stdlib.h"
  135: 
  136: #ifdef HAVE_UNISTD_H
  137: # include <unistd.h>
  138: #endif
  139: 
  140: #include <stdio.h>
  141: #include <signal.h>
  142: #include <ctype.h>
  143: #ifndef SYS_WINNT
  144: # ifdef HAVE_SYS_SIGNAL_H
  145: #  include <sys/signal.h>
  146: # else
  147: #  include <signal.h>
  148: # endif
  149: # include <sys/ioctl.h>
  150: #endif /* SYS_WINNT */
  151: 
  152: #ifdef HAVE_SYS_RESOURCE_H
  153: # include <sys/resource.h>
  154: #endif /* HAVE_SYS_RESOURCE_H */
  155: 
  156: #ifdef SYS_VXWORKS
  157: # include "ioLib.h"
  158: # include "sockLib.h"
  159: # include "timers.h"
  160: #endif
  161: 
  162: #include "recvbuff.h"
  163: 
  164: #ifdef SYS_WINNT
  165: # define TARGET_RESOLUTION 1  /* Try for 1-millisecond accuracy
  166: 				on Windows NT timers. */
  167: #pragma comment(lib, "winmm")
  168: #endif /* SYS_WINNT */
  169: 
  170: /*
  171:  * Scheduling priority we run at
  172:  */
  173: #ifndef SYS_VXWORKS
  174: # define	NTPDATE_PRIO	(-12)
  175: #else
  176: # define	NTPDATE_PRIO	(100)
  177: #endif
  178: 
  179: #if defined(HAVE_TIMER_SETTIME) || defined (HAVE_TIMER_CREATE)
  180: /* POSIX TIMERS - vxWorks doesn't have itimer - casey */
  181: static timer_t ntpdate_timerid;
  182: #endif
  183: 
  184: /*
  185:  * Compatibility stuff for Version 2
  186:  */
  187: #define NTP_MAXSKW	0x28f	/* 0.01 sec in fp format */
  188: #define NTP_MINDIST 0x51f	/* 0.02 sec in fp format */
  189: #define NTP_INFIN	15	/* max stratum, infinity a la Bellman-Ford */
  190: #define NTP_MAXWGT	(8*FP_SECOND)	/* maximum select weight 8 seconds */
  191: #define NTP_MAXLIST 5	/* maximum select list size */
  192: #define PEER_SHIFT	8	/* 8 suitable for crystal time base */
  193: 
  194: /*
  195:  * Debugging flag
  196:  */
  197: volatile int debug = 0;
  198: 
  199: /*
  200:  * File descriptor masks etc. for call to select
  201:  */
  202: int fd;
  203: fd_set fdmask;
  204: 
  205: /*
  206:  * Initializing flag.  All async routines watch this and only do their
  207:  * thing when it is clear.
  208:  */
  209: int initializing = 1;
  210: 
  211: /*
  212:  * Alarm flag.	Set when an alarm occurs
  213:  */
  214: volatile int alarm_flag = 0;
  215: 
  216: /*
  217:  * Set the time if valid time determined
  218:  */
  219: int set_time = 0;
  220: 
  221: /*
  222:  * transmission rate control
  223:  */
  224: #define	MINTRANSMITS	(3)	/* minimum total packets per server */
  225: #define	MAXXMITCOUNT	(2)	/* maximum packets per time interrupt */
  226: 
  227: /*
  228:  * time setting constraints
  229:  */
  230: #define	DESIREDDISP	(4*FP_SECOND)	/* desired dispersion, (fp 4) */
  231: int max_period = DEFMAXPERIOD;
  232: int min_servers = DEFMINSERVERS;
  233: int min_valid = DEFMINVALID;
  234: 
  235: /*
  236:  * counters related to time setting constraints
  237:  */
  238: int contacted = 0;		/* # of servers we have sent to */
  239: int responding = 0;		/* servers responding */
  240: int validcount = 0;		/* servers with valid time */
  241: int valid_n_low = 0;		/* valid time servers with low dispersion */
  242: 
  243: /*
  244:  * Unpriviledged port flag.
  245:  */
  246: int unpriv_port = 0;
  247: 
  248: /*
  249:  * Program name.
  250:  */
  251: char *progname;
  252: 
  253: /*
  254:  * Systemwide parameters and flags
  255:  */
  256: struct server **sys_servers;	/* the server list */
  257: int sys_numservers = 0; 	/* number of servers to poll */
  258: int sys_authenticate = 0;	/* true when authenticating */
  259: u_int32 sys_authkey = 0;	/* set to authentication key in use */
  260: u_long sys_authdelay = 0;	/* authentication delay */
  261: 
  262: /*
  263:  * The current internal time
  264:  */
  265: u_long current_time = 0;
  266: 
  267: /*
  268:  * File of encryption keys
  269:  */
  270: 
  271: #ifndef KEYFILE
  272: # ifndef SYS_WINNT
  273: #define KEYFILE 	"/etc/ntp.keys"
  274: # else
  275: #define KEYFILE 	"%windir%\\ntp.keys"
  276: # endif /* SYS_WINNT */
  277: #endif /* KEYFILE */
  278: 
  279: #ifndef SYS_WINNT
  280: const char *key_file = KEYFILE;
  281: #else
  282: char key_file_storage[MAX_PATH+1], *key_file ;
  283: #endif	 /* SYS_WINNT */
  284: 
  285: /*
  286:  * total packet counts
  287:  */
  288: u_long total_xmit = 0;
  289: u_long total_recv = 0;
  290: 
  291: /*
  292:  * Miscellaneous flags
  293:  */
  294: int verbose = 0;
  295: #define	HORRIBLEOK	3	/* how many packets to let out */
  296: int horrible = 0;	/* how many packets we drop for testing */
  297: int secondhalf = 0;	/* second half of timeout period */
  298: int printmsg = 0;	/* print time response analysis */
  299: 
  300: /*
  301:  * The half time and finish time in internal time
  302:  */
  303: u_long half_time = 0;
  304: u_long finish_time = 0;
  305: 
  306: 
  307: int	ntptimesetmain	P((int argc, char *argv[]));
  308: static	void	analysis	P((int final));
  309: static	int	have_enough	P((void));
  310: static	void	transmit	P((register struct server *server));
  311: static	void	receive		P((struct recvbuf *rbufp));
  312: static	void	clock_filter P((register struct server *server, s_fp d, l_fp *c));
  313: static	void	clock_count	P((void));
  314: static	struct server *clock_select P((void));
  315: static	void	set_local_clock	P((void));
  316: static	struct server *findserver P((struct sockaddr_in *addr));
  317: static	void	timer		P((void));
  318: #ifndef SYS_WINNT
  319: static	RETSIGTYPE 	alarming	P((int sig));
  320: #endif /* SYS_WINNT */
  321: static	void	init_alarm	P((void));
  322: static	void	init_io		P((void));
  323: static	int	sendpkt		P((struct sockaddr_in *dest, struct pkt *pkt, int len));
  324: 	void 	input_handler	P((l_fp *xts));
  325: static	void	printserver	P((register struct server *pp, FILE *fp));
  326: #if !defined(HAVE_VSPRINTF)
  327: int	vsprintf	P((char *str, const char *fmt, va_list ap));
  328: #endif
  329: 
  330: #ifdef HAVE_SIGNALED_IO
  331: extern  void    wait_for_signal P((void));
  332: extern  void    unblock_io_and_alarm P((void));
  333: extern  void    block_io_and_alarm P((void));
  334: #endif
  335: 
  336: 
  337: #ifdef NO_MAIN_ALLOWED
  338: CALL(ntptimeset,"ntptimeset",ntptimesetmain);
  339: 
  340: void clear_globals()
  341: {
  342:   /*
  343:    * Debugging flag
  344:    */
  345:   debug = 0;
  346: 
  347:   ntp_optind = 0;
  348: 
  349:   /*
  350:    * Initializing flag.  All async routines watch this and only do their
  351:    * thing when it is clear.
  352:    */
  353:   initializing = 1;
  354: 
  355:   /*
  356:    * Alarm flag.  Set when an alarm occurs
  357:    */
  358:   alarm_flag = 0;
  359: 
  360:   /*
  361:    * Unpriviledged port flag.
  362:    */
  363:   unpriv_port = 0;
  364: 
  365:   /*
  366:    * Systemwide parameters and flags
  367:    */
  368:   sys_numservers = 0;	  /* number of servers to poll */
  369:   sys_authenticate = 0;   /* true when authenticating */
  370:   sys_authkey = 0;	   /* set to authentication key in use */
  371:   sys_authdelay = 0;   /* authentication delay */
  372: 
  373:   /*
  374:    * The current internal time
  375:    */
  376:   current_time = 0;
  377: 
  378:   verbose = 0;
  379: }
  380: #endif /* NO_MAIN_ALLOWED */
  381: 
  382: /*
  383:  * Main program.  Initialize us and loop waiting for I/O and/or
  384:  * timer expiries.
  385:  */
  386: #ifndef NO_MAIN_ALLOWED
  387: int
  388: main(
  389: 	int argc,
  390: 	char *argv[]
  391: 	)
  392: {
  393: 	return ntptimesetmain(argc, argv);
  394: }
  395: #endif /* NO_MAIN_ALLOWED */
  396: 	   
  397: 
  398: int
  399: ntptimesetmain(
  400: 	int argc,
  401: 	char *argv[]
  402: 	)
  403: {
  404: 	int was_alarmed;
  405: 	int tot_recvbufs;
  406: 	struct recvbuf *rbuf;
  407: 	l_fp tmp;
  408: 	int errflg;
  409: 	int c;
  410: 	extern char *ntp_optarg;
  411: 	extern int ntp_optind;
  412: 	int ltmp;
  413: 	char *cfgpath;
  414: 
  415: #ifdef SYS_WINNT
  416: 	HANDLE process_handle;
  417: 
  418: 	wVersionRequested = MAKEWORD(1,1);
  419: 	if (WSAStartup(wVersionRequested, &wsaData)) {
  420: 		msyslog(LOG_ERR, "No useable winsock.dll: %m");
  421: 		exit(1);
  422: 	}
  423: #endif /* SYS_WINNT */
  424: 
  425: #ifdef NO_MAIN_ALLOWED
  426: 	clear_globals();
  427: #endif
  428: 
  429: 	errflg = 0;
  430: 	cfgpath = 0;
  431: 	progname = argv[0];
  432: 	syslogit = 0;
  433: 
  434: 	/*
  435: 	 * Decode argument list
  436: 	 */
  437: 	while ((c = ntp_getopt(argc, argv, "a:c:de:slt:uvHS:V:")) != EOF)
  438: 		switch (c)
  439: 		{
  440: 		case 'a':
  441: 			c = atoi(ntp_optarg);
  442: 			sys_authenticate = 1;
  443: 			sys_authkey = c;
  444: 			break;
  445: 		case 'c':
  446: 			cfgpath = ntp_optarg;
  447: 			break;
  448: 		case 'd':
  449: 			++debug;
  450: 			break;
  451: 		case 'e':
  452: 			if (!atolfp(ntp_optarg, &tmp)
  453: 			    || tmp.l_ui != 0) {
  454: 				(void) fprintf(stderr,
  455: 				    "%s: encryption delay %s is unlikely\n",
  456: 				    progname, ntp_optarg);
  457: 				errflg++;
  458: 			} else {
  459: 				sys_authdelay = tmp.l_uf;
  460: 			}
  461: 			break;
  462: 		case 's':
  463: 			set_time = 1;
  464: 			break;
  465: 		case 'l':
  466: 			syslogit = 1;
  467: 			break;
  468: 		case 't':
  469: 			ltmp = atoi(ntp_optarg);
  470: 			if (ltmp <= 0) {
  471: 			    (void) fprintf(stderr,
  472: 				"%s: maximum time period (%d) is invalid\n",
  473: 				progname, ltmp);
  474: 			    errflg++;
  475: 			}
  476: 			else
  477: 			    max_period = ltmp;
  478: 			break;
  479: 		case 'u':
  480: 			unpriv_port = 1;
  481: 			break;
  482: 		case 'v':
  483: 			++verbose;
  484: 			break;
  485: 		case 'H':
  486: 			horrible++;
  487: 			break;
  488: 		case 'S':
  489: 			ltmp = atoi(ntp_optarg);
  490: 			if (ltmp <= 0) {
  491: 			    (void) fprintf(stderr,
  492: 				"%s: minimum responding (%d) is invalid\n",
  493: 				progname, ltmp);
  494: 			    errflg++;
  495: 			}
  496: 			else
  497: 			    min_servers = ltmp;
  498: 			break;
  499: 		case 'V':
  500: 			ltmp = atoi(ntp_optarg);
  501: 			if (ltmp <= 0) {
  502: 			    (void) fprintf(stderr,
  503: 				"%s: minimum valid (%d) is invalid\n",
  504: 				progname, ltmp);
  505: 			    errflg++;
  506: 			}
  507: 			else
  508: 			    min_valid = ltmp;
  509: 			break;
  510: 		case '?':
  511: 			++errflg;
  512: 			break;
  513: 		default:
  514: 			break;
  515: 		}
  516: 
  517: 	
  518: 	if (errflg || ntp_optind < argc) {
  519: 		fprintf(stderr,"usage: %s [switches...]\n",progname);
  520: 		fprintf(stderr,"  -v       (verbose)\n");
  521: 		fprintf(stderr,"  -c path  (set config file path)\n");
  522: 		fprintf(stderr,"  -a key   (authenticate using key)\n");
  523: 		fprintf(stderr,"  -e delay (authentication delay)\n");
  524: 		fprintf(stderr,"  -S num   (# of servers that must respond)\n");
  525: 		fprintf(stderr,"  -V num   (# of servers that must valid)\n");
  526: 		fprintf(stderr,"  -s       (set the time based if okay)\n");
  527: 		fprintf(stderr,"  -t secs  (time period before ending)\n");
  528: 		fprintf(stderr,"  -l       (use syslog facility)\n");
  529: 		fprintf(stderr,"  -u       (use unprivileged port)\n");
  530: 		fprintf(stderr,"  -H       (drop packets for debugging)\n");
  531: 		fprintf(stderr,"  -d       (debug output)\n");
  532: 		exit(2);
  533: 	}
  534: 
  535: 	/*
  536: 	 * Logging.  Open the syslog if we have to
  537: 	 */
  538: 	if (syslogit) {
  539: #if !defined (SYS_WINNT) && !defined (SYS_VXWORKS) && !defined SYS_CYGWIN32
  540: # ifndef	LOG_DAEMON
  541: 		openlog("ntptimeset", LOG_PID);
  542: # else
  543: 
  544: #  ifndef	LOG_NTP
  545: #	define	LOG_NTP LOG_DAEMON
  546: #  endif
  547: 		openlog("ntptimeset", LOG_PID | LOG_NDELAY, LOG_NTP);
  548: 		if (debug)
  549: 			setlogmask(LOG_UPTO(LOG_DEBUG));
  550: 		else
  551: 			setlogmask(LOG_UPTO(LOG_INFO));
  552: # endif /* LOG_DAEMON */
  553: #endif	/* SYS_WINNT */
  554: 	}
  555: 
  556: 	if (debug || verbose)
  557: 		msyslog(LOG_INFO, "%s", Version);
  558: 
  559: 	if (horrible)
  560: 		msyslog(LOG_INFO, "Dropping %d out of %d packets",
  561: 			horrible,horrible+HORRIBLEOK);
  562: 	/*
  563: 	 * Add servers we are going to be polling
  564: 	 */
  565: 	loadservers(cfgpath);
  566: 
  567: 	if (sys_numservers < min_servers) {
  568: 		msyslog(LOG_ERR, "Found %d servers, require %d servers",
  569: 			sys_numservers,min_servers);
  570: 		exit(2);
  571: 	}
  572: 
  573: 	/*
  574: 	 * determine when we will end at least
  575:  	 */
  576: 	finish_time = max_period * TIMER_HZ;
  577: 	half_time = finish_time >> 1;
  578: 
  579: 	/*
  580: 	 * Initialize the time of day routines and the I/O subsystem
  581: 	 */
  582: 	if (sys_authenticate) {
  583: 		init_auth();
  584: #ifdef SYS_WINNT
  585: 		if (!key_file) key_file = KEYFILE;
  586: 		if (!ExpandEnvironmentStrings(key_file, key_file_storage, MAX_PATH))
  587: 		{
  588: 			msyslog(LOG_ERR, "ExpandEnvironmentStrings(%s) failed: %m\n",
  589: 				key_file);
  590: 		} else {
  591: 			key_file = key_file_storage;
  592: 		}
  593: #endif /* SYS_WINNT */
  594: 
  595: 		if (!authreadkeys(key_file)) {
  596: 			msyslog(LOG_ERR, "no key file, exiting");
  597: 			exit(1);
  598: 		}
  599: 		if (!authistrusted(sys_authkey)) {
  600: 			char buf[10];
  601: 
  602: 			(void) sprintf(buf, "%lu", (unsigned long)sys_authkey);
  603: 			msyslog(LOG_ERR, "authentication key %s unknown", buf);
  604: 			exit(1);
  605: 		}
  606: 	}
  607: 	init_io();
  608: 	init_alarm();
  609: 
  610: 	/*
  611: 	 * Set the priority.
  612: 	 */
  613: #ifdef SYS_VXWORKS
  614: 	taskPrioritySet( taskIdSelf(), NTPDATE_PRIO);
  615: #endif
  616: #if defined(HAVE_ATT_NICE)
  617: 	nice (NTPDATE_PRIO);
  618: #endif
  619: #if defined(HAVE_BSD_NICE)
  620: 	(void) setpriority(PRIO_PROCESS, 0, NTPDATE_PRIO);
  621: #endif
  622: #ifdef SYS_WINNT
  623: 	process_handle = GetCurrentProcess();
  624: 	if (!SetPriorityClass(process_handle, (DWORD) REALTIME_PRIORITY_CLASS)) {
  625: 		msyslog(LOG_ERR, "SetPriorityClass failed: %m");
  626: 	}
  627: #endif /* SYS_WINNT */
  628: 
  629: 	initializing = 0;
  630: 
  631: 	/*
  632: 	 * Use select() on all on all input fd's for unlimited
  633: 	 * time.  select() will terminate on SIGALARM or on the
  634: 	 * reception of input.	Using select() means we can't do
  635: 	 * robust signal handling and we get a potential race
  636: 	 * between checking for alarms and doing the select().
  637: 	 * Mostly harmless, I think.
  638: 	 * Keep going until we have enough information, or time is up.
  639: 	 */
  640: 	/* On VMS, I suspect that select() can't be interrupted
  641: 	 * by a "signal" either, so I take the easy way out and
  642: 	 * have select() time out after one second.
  643: 	 * System clock updates really aren't time-critical,
  644: 	 * and - lacking a hardware reference clock - I have
  645: 	 * yet to learn about anything else that is.
  646: 	 */
  647: 	was_alarmed = 0;
  648: 	while (finish_time > current_time) {
  649: #if !defined(HAVE_SIGNALED_IO) 
  650: 		fd_set rdfdes;
  651: 		int nfound;
  652: #elif defined(HAVE_SIGNALED_IO)
  653: 		block_io_and_alarm();
  654: #endif
  655: 
  656: 		tot_recvbufs = full_recvbuffs();	/* get received buffers */
  657: 		if (printmsg) {
  658: 			printmsg = 0;
  659: 			analysis(0);
  660: 		}
  661: 		if (alarm_flag) {		/* alarmed? */
  662: 			was_alarmed = 1;
  663: 			alarm_flag = 0;
  664: 		}
  665: 
  666: 		if (!was_alarmed && tot_recvbufs > 0) {
  667: 			/*
  668: 			 * Nothing to do.  Wait for something.
  669: 			 */
  670: #ifndef HAVE_SIGNALED_IO
  671: 			rdfdes = fdmask;
  672: # if defined(VMS) || defined(SYS_VXWORKS)
  673: 			/* make select() wake up after one second */
  674: 			{
  675: 				struct timeval t1;
  676: 
  677: 				t1.tv_sec = 1; t1.tv_usec = 0;
  678: 				nfound = select(fd+1, &rdfdes, (fd_set *)0,
  679: 						(fd_set *)0, &t1);
  680: 			}
  681: # else
  682: 			nfound = select(fd+1, &rdfdes, (fd_set *)0,
  683: 					(fd_set *)0, (struct timeval *)0);
  684: # endif /* VMS */
  685: 			if (nfound > 0) {
  686: 				l_fp ts;
  687: 				get_systime(&ts);
  688: 				(void)input_handler(&ts);
  689: 			}
  690: 			else if (nfound == -1 && errno != EINTR)
  691: 				msyslog(LOG_ERR, "select() error: %m");
  692: 			else if (debug) {
  693: # if !defined SYS_VXWORKS && !defined SYS_CYGWIN32 /* to unclutter log */
  694: 				msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound);
  695: # endif
  696: 			}
  697: #else /* HAVE_SIGNALED_IO */
  698:                         
  699: 			wait_for_signal();
  700: #endif /* HAVE_SIGNALED_IO */
  701: 			if (alarm_flag) 	/* alarmed? */
  702: 			{
  703: 				was_alarmed = 1;
  704: 				alarm_flag = 0;
  705: 			}
  706: 			tot_recvbufs = full_recvbuffs();  /* get received buffers */
  707: 		}
  708: #ifdef HAVE_SIGNALED_IO
  709: 		unblock_io_and_alarm();
  710: #endif /* HAVE_SIGNALED_IO */
  711: 
  712: 		/*
  713: 		 * Out here, signals are unblocked.  Call timer routine
  714: 		 * to process expiry.
  715: 		 */
  716: 		if (was_alarmed)
  717: 		{
  718: 			timer();
  719: 			was_alarmed = 0;
  720: 		}
  721: 
  722: 		/*
  723: 		 * Call the data procedure to handle each received
  724: 		 * packet.
  725: 		 */
  726: 		rbuf = get_full_recv_buffer();
  727: 		while (rbuf != NULL)
  728: 		{
  729: 			receive(rbuf);
  730: 			freerecvbuf(rbuf);
  731: 			rbuf = get_full_recv_buffer();
  732: 		}
  733: 
  734: 		/*
  735: 		 * Do we have enough information to stop now?
  736: 		 */
  737: 		if (have_enough())
  738: 			break;	/* time to end */
  739: 
  740: 		/*
  741: 		 * Go around again
  742: 		 */
  743: 	}
  744: 
  745: 	/*
  746: 	 * adjust the clock and exit accordingly
  747: 	 */
  748: 	set_local_clock();
  749: 
  750: 	/*
  751: 	 * if we get here then we are in trouble
  752: 	 */
  753: 	return(1);
  754: }
  755: 
  756: 
  757: /*
  758:  * analysis - print a message indicating what is happening with time service
  759:  *	      must mimic have_enough() procedure.
  760:  */
  761: static void
  762: analysis(
  763: 	int final
  764: 	)
  765: {
  766: 	if (contacted < sys_numservers) {
  767: 		printf("%d servers of %d have been probed with %d packets\n",
  768: 		       contacted,sys_numservers,MINTRANSMITS);
  769: 		return;
  770: 	}
  771: 	if (!responding) {
  772: 		printf("No response from any of %d servers, network problem?\n",
  773: 		       sys_numservers);
  774: 		return;
  775: 	}
  776: 	else if (responding < min_servers) {
  777: 		printf("%d servers out of %d responding, need at least %d.\n",
  778: 		       responding, sys_numservers, min_servers);
  779: 		return;
  780: 	}
  781: 	if (!validcount) {
  782: 		printf("%d servers responding but none have valid time\n",
  783: 		       responding);
  784: 		return;
  785: 	}
  786: 	else if (validcount < min_valid) {
  787: 		printf("%d servers responding, %d are valid, need %d valid\n",
  788: 		       responding,validcount,min_valid);
  789: 		return;
  790: 	}
  791: 	if (!final && valid_n_low != validcount) {
  792: 		printf("%d valid servers but only %d have low dispersion\n",
  793: 		       validcount,valid_n_low);
  794: 		return;
  795: 	}
  796: }
  797: 
  798: 
  799: /* have_enough - see if we have enough information to terminate probing
  800:  */
  801: static int
  802: have_enough(void)
  803: {
  804: 	/* have we contacted all servers yet? */
  805: 	if (contacted < sys_numservers)
  806: 		return 0;	/* no...try some more */
  807: 
  808: 	/* have we got at least minimum servers responding? */
  809: 	if (responding < min_servers)
  810: 		return 0;	/* no...try some more */
  811: 
  812: 	/* count the clocks */
  813: 	(void) clock_count();
  814: 
  815: 	/* have we got at least minimum valid clocks? */
  816: 	if (validcount <= 0 || validcount < min_valid)
  817: 		return 0;	/* no...try some more */
  818: 
  819: 	/* do we have all valid servers with low dispersion */
  820: 	if (!secondhalf && valid_n_low != validcount)
  821: 		return 0;
  822: 
  823: 	/* if we get into the secondhalf then we ignore dispersion */
  824: 
  825: 	/* all conditions have been met...end */
  826: 	return 1;
  827: }
  828: 
  829: 
  830: /*
  831:  * transmit - transmit a packet to the given server, or mark it completed.
  832:  *	      This is called by the timeout routine and by the receive
  833:  *	      procedure.
  834:  */
  835: static void
  836: transmit(
  837: 	register struct server *server
  838: 	)
  839: {
  840: 	struct pkt xpkt;
  841: 	int timeout;
  842: 
  843: 	if (debug > 2)
  844: 		printf("transmit(%s)\n", ntoa(&server->srcadr));
  845: 
  846: 	if ((server->reach & 01) == 0) {
  847: 		l_fp ts;
  848: 		/*
  849: 		 * Last message to this server timed out.  Shift
  850: 		 * zeros into the filter.
  851: 		 */
  852: 		L_CLR(&ts);
  853: 		clock_filter(server, 0, &ts);
  854: 	}
  855: 
  856: 	/*
  857: 	 * shift reachable register over
  858: 	 */
  859: 	server->reach <<= 1;
  860: 
  861: 	/*
  862: 	 * If we're here, send another message to the server.  Fill in
  863: 	 * the packet and let 'er rip.
  864: 	 */
  865: 	xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC,
  866: 		server->version, MODE_CLIENT);
  867: 	xpkt.stratum = STRATUM_TO_PKT(STRATUM_UNSPEC);
  868: 	xpkt.ppoll = NTP_MINPOLL;
  869: 	xpkt.precision = NTPDATE_PRECISION;
  870: 	xpkt.rootdelay = htonl(NTPDATE_DISTANCE);
  871: 	xpkt.rootdispersion = htonl(NTPDATE_DISP);
  872: 	xpkt.refid = htonl(NTPDATE_REFID);
  873: 	L_CLR(&xpkt.reftime);
  874: 	L_CLR(&xpkt.org);
  875: 	L_CLR(&xpkt.rec);
  876: 
  877: 	/*
  878: 	 * Determine whether to authenticate or not.  If so,
  879: 	 * fill in the extended part of the packet and do it.
  880: 	 * If not, just timestamp it and send it away.
  881: 	 */
  882: 	if (sys_authenticate) {
  883: 		int len;
  884: 
  885: 		xpkt.exten[0] = htonl(sys_authkey);
  886: 		get_systime(&server->xmt);
  887: 		L_ADDUF(&server->xmt, sys_authdelay);
  888: 		HTONL_FP(&server->xmt, &xpkt.xmt);
  889: 		len = authencrypt(sys_authkey, (u_int32 *)&xpkt, LEN_PKT_NOMAC);
  890: 		if (sendpkt(&(server->srcadr), &xpkt, (int)(LEN_PKT_NOMAC + len))) {
  891: 			if (debug > 1)
  892: 				printf("failed transmit auth to %s\n",
  893: 				    ntoa(&(server->srcadr)));
  894: 			return;
  895: 		}
  896: 
  897: 		if (debug > 1)
  898: 			printf("transmit auth to %s\n",
  899: 			    ntoa(&(server->srcadr)));
  900: 	} else {
  901: 		get_systime(&(server->xmt));
  902: 		HTONL_FP(&server->xmt, &xpkt.xmt);
  903: 		if (sendpkt(&(server->srcadr), &xpkt, LEN_PKT_NOMAC)) {
  904: 			if (debug > 1)
  905: 				printf("failed transmit to %s\n", 
  906: 				    ntoa(&(server->srcadr)));
  907: 			return;
  908: 		}
  909: 
  910: 		if (debug > 1)
  911: 			printf("transmit to %s\n", ntoa(&(server->srcadr)));
  912: 	}
  913: 
  914: 	/*
  915: 	 * count transmits, record contacted count and set transmit time
  916: 	 */
  917: 	if (++server->xmtcnt == MINTRANSMITS)
  918: 	    contacted++;
  919: 	server->last_xmit = current_time;
  920: 
  921: 	/*
  922: 	 * determine timeout for this packet. The more packets we send
  923: 	 * to the host, the slower we get. If the host indicates that
  924: 	 * it is not "sane" then we expect even less.
  925: 	 */
  926: 	if (server->xmtcnt < MINTRANSMITS) {
  927: 	    /* we have not sent enough */
  928: 	    timeout = TIMER_HZ;		/* 1 second probe */
  929: 	}
  930: 	else if (server->rcvcnt <= 0) {
  931: 	    /* we have heard nothing */
  932: 	    if (secondhalf)
  933: 		timeout = TIMER_HZ<<4;	/* 16 second probe */
  934: 	    else
  935: 		timeout = TIMER_HZ<<3;	/* 8 second probe */
  936: 	}
  937: 	else {
  938: 	    /* if we have low dispersion then probe infrequently */
  939: 	    if (server->dispersion <= DESIREDDISP)
  940: 		timeout = TIMER_HZ<<4;	/* 16 second probe */
  941: 	    /* if the server is not in sync then let it alone */
  942: 	    else if (server->leap == LEAP_NOTINSYNC)
  943: 		timeout = TIMER_HZ<<4;	/* 16 second probe */
  944: 	    /* if the server looks broken ignore it */
  945: 	    else if (server->org.l_ui < server->reftime.l_ui)
  946: 		timeout = TIMER_HZ<<5;	/* 32 second probe */
  947: 	    else if (secondhalf)
  948: 		timeout = TIMER_HZ<<2;	/* 4 second probe */
  949: 	    else
  950: 		timeout = TIMER_HZ<<1;	/* 2 second probe */
  951: 	}
  952: 
  953: 	/*
  954: 	 * set next transmit time based on timeout
  955: 	 */
  956: 	server->event_time = current_time + timeout;
  957: }
  958: 
  959: 
  960: /*
  961:  * receive - receive and process an incoming frame
  962:  */
  963: static void
  964: receive(
  965: 	struct recvbuf *rbufp
  966: 	)
  967: {
  968: 	register struct pkt *rpkt;
  969: 	register struct server *server;
  970: 	register s_fp di;
  971: 	l_fp t10, t23;
  972: 	l_fp org;
  973: 	l_fp rec;
  974: 	l_fp ci;
  975: 	int has_mac;
  976: 	int is_authentic;
  977: 
  978: 	if (debug > 2)
  979: 		printf("receive(%s)\n", ntoa(&rbufp->srcadr));
  980: 	/*
  981: 	 * Check to see if the packet basically looks like something
  982: 	 * intended for us.
  983: 	 */
  984: 	if (rbufp->recv_length == LEN_PKT_NOMAC)
  985: 		has_mac = 0;
  986: 	else if (rbufp->recv_length >= LEN_PKT_NOMAC)
  987: 		has_mac = 1;
  988: 	else {
  989: 		if (debug > 2)
  990: 			printf("receive: packet length %d\n",
  991: 			    rbufp->recv_length);
  992: 		return;		/* funny length packet */
  993: 	}
  994: 
  995: 	rpkt = &(rbufp->recv_pkt);
  996: 	if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION ||
  997: 	    PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) {
  998: 		if (debug > 1)
  999: 			printf("receive: bad version %d\n",
 1000: 			       PKT_VERSION(rpkt->li_vn_mode));
 1001: 		return;
 1002: 	}
 1003: 
 1004: 	if ((PKT_MODE(rpkt->li_vn_mode) != MODE_SERVER
 1005: 	    && PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE)
 1006: 	    || rpkt->stratum >=STRATUM_UNSPEC) {
 1007: 		if (debug > 1)
 1008: 			printf("receive: mode %d stratum %d\n",
 1009: 			    PKT_MODE(rpkt->li_vn_mode), rpkt->stratum);
 1010: 		return;
 1011: 	}
 1012: 	
 1013: 	/*
 1014: 	 * So far, so good.  See if this is from a server we know.
 1015: 	 */
 1016: 	server = findserver(&(rbufp->srcadr));
 1017: 	if (server == NULL) {
 1018: 		if (debug > 1)
 1019: 			printf("receive: server not found\n");
 1020: 		return;
 1021: 	}
 1022: 
 1023: 	/*
 1024: 	 * Decode the org timestamp and make sure we're getting a response
 1025: 	 * to our last request.
 1026: 	 */
 1027: 	NTOHL_FP(&rpkt->org, &org);
 1028: 	if (!L_ISEQU(&org, &server->xmt)) {
 1029: 		if (debug > 1)
 1030: 			printf("receive: pkt.org and peer.xmt differ\n");
 1031: 		return;
 1032: 	}
 1033: 	
 1034: 	/*
 1035: 	 * Check out the authenticity if we're doing that.
 1036: 	 */
 1037: 	if (!sys_authenticate)
 1038: 		is_authentic = 1;
 1039: 	else {
 1040: 		is_authentic = 0;
 1041: 
 1042: 		if (debug > 3)
 1043: 			printf("receive: rpkt keyid=%ld sys_authkey=%ld decrypt=%ld\n",
 1044: 			   (long int)ntohl(rpkt->exten[0]), (long int)sys_authkey,
 1045: 			   (long int)authdecrypt(sys_authkey, (u_int32 *)rpkt,
 1046: 				LEN_PKT_NOMAC, (int)(rbufp->recv_length - LEN_PKT_NOMAC)));
 1047: 
 1048: 		if (has_mac && ntohl(rpkt->exten[0]) == sys_authkey &&
 1049: 			authdecrypt(sys_authkey, (u_int32 *)rpkt, LEN_PKT_NOMAC,
 1050: 			(int)(rbufp->recv_length - LEN_PKT_NOMAC)))
 1051: 			is_authentic = 1;
 1052: 		if (debug)
 1053: 			printf("receive: authentication %s\n",
 1054: 			   is_authentic ? "passed" : "failed");
 1055: 	}
 1056: 	server->trust <<= 1;
 1057: 	if (!is_authentic)
 1058: 		server->trust |= 1;
 1059: 	
 1060: 	/*
 1061: 	 * Looks good.  Record info from the packet.
 1062: 	 */
 1063: 	server->leap = PKT_LEAP(rpkt->li_vn_mode);
 1064: 	server->stratum = PKT_TO_STRATUM(rpkt->stratum);
 1065: 	server->precision = rpkt->precision;
 1066: 	server->rootdelay = ntohl(rpkt->rootdelay);
 1067: 	server->rootdispersion = ntohl(rpkt->rootdispersion);
 1068: 	server->refid = rpkt->refid;
 1069: 	NTOHL_FP(&rpkt->reftime, &server->reftime);
 1070: 	NTOHL_FP(&rpkt->rec, &rec);
 1071: 	NTOHL_FP(&rpkt->xmt, &server->org);
 1072: 
 1073: 	/*
 1074: 	 * count this guy as responding
 1075: 	 */
 1076: 	server->reach |= 1;
 1077: 	if (server->rcvcnt++ == 0)
 1078: 		responding++;
 1079: 
 1080: 	/*
 1081: 	 * Make sure the server is at least somewhat sane.  If not, ignore
 1082: 	 * it for later.
 1083: 	 */
 1084: 	if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)) {
 1085: 		if (debug > 1)
 1086: 			printf("receive: pkt insane\n");
 1087: 		return;
 1088: 	}
 1089: 
 1090: 	/*
 1091: 	 * Calculate the round trip delay (di) and the clock offset (ci).
 1092: 	 * We use the equations (reordered from those in the spec):
 1093: 	 *
 1094: 	 * d = (t2 - t3) - (t1 - t0)
 1095: 	 * c = ((t2 - t3) + (t1 - t0)) / 2
 1096: 	 */
 1097: 	t10 = server->org;		/* pkt.xmt == t1 */
 1098: 	L_SUB(&t10, &rbufp->recv_time);	/* recv_time == t0*/
 1099: 
 1100: 	t23 = rec;			/* pkt.rec == t2 */
 1101: 	L_SUB(&t23, &org);		/* pkt->org == t3 */
 1102: 
 1103: 	/* now have (t2 - t3) and (t0 - t1).  Calculate (ci) and (di) */
 1104: 	ci = t10;
 1105: 	L_ADD(&ci, &t23);
 1106: 	L_RSHIFT(&ci);
 1107: 
 1108: 	/*
 1109: 	 * Calculate di in t23 in full precision, then truncate
 1110: 	 * to an s_fp.
 1111: 	 */
 1112: 	L_SUB(&t23, &t10);
 1113: 	di = LFPTOFP(&t23);
 1114: 
 1115: 	if (debug > 3)
 1116: 		printf("offset: %s, delay %s\n", lfptoa(&ci, 6), fptoa(di, 5));
 1117: 
 1118: 	di += (FP_SECOND >> (-(int)NTPDATE_PRECISION))
 1119: 	    + (FP_SECOND >> (-(int)server->precision)) + NTP_MAXSKW;
 1120: 
 1121: 	if (di <= 0) {		/* value still too raunchy to use? */
 1122: 		L_CLR(&ci);
 1123: 		di = 0;
 1124: 	} else {
 1125: 		di = max(di, NTP_MINDIST);
 1126: 	}
 1127: 
 1128: 
 1129: 	/*
 1130: 	 * This one is valid.  Give it to clock_filter(),
 1131: 	 */
 1132: 	clock_filter(server, di, &ci);
 1133: 	if (debug > 1)
 1134: 		printf("receive from %s\n", ntoa(&rbufp->srcadr));
 1135: 
 1136: 	/*
 1137: 	 * See if we should goes the transmission. If not return now
 1138: 	 * otherwise have the next event time be shortened
 1139: 	 */
 1140: 	if (server->stratum <= NTP_INFIN)
 1141: 	    return;	/* server does not have a stratum */
 1142: 	if (server->leap == LEAP_NOTINSYNC)
 1143: 	    return;	/* just booted server or out of sync */
 1144: 	if (!L_ISHIS(&server->org, &server->reftime))
 1145: 	    return;	/* broken host */
 1146: 	if (server->trust != 0)
 1147: 	    return;	/* can not trust it */
 1148: 
 1149: 	if (server->dispersion < DESIREDDISP)
 1150: 	    return;	/* we have the desired dispersion */
 1151: 
 1152: 	server->event_time -= (TIMER_HZ+1);
 1153: }
 1154: 
 1155: 
 1156: /*
 1157:  * clock_filter - add clock sample, determine a server's delay, dispersion
 1158:  *                and offset
 1159:  */
 1160: static void
 1161: clock_filter(
 1162: 	register struct server *server,
 1163: 	s_fp di,
 1164: 	l_fp *c
 1165: 	)
 1166: {
 1167: 	register int i, j;
 1168: 	int ord[NTP_SHIFT];
 1169: 
 1170: 	/*
 1171: 	 * Insert sample and increment nextpt
 1172: 	 */
 1173: 
 1174: 	i = server->filter_nextpt;
 1175: 	server->filter_delay[i] = di;
 1176: 	server->filter_offset[i] = *c;
 1177: 	server->filter_soffset[i] = LFPTOFP(c);
 1178: 	server->filter_nextpt++;
 1179: 	if (server->filter_nextpt >= NTP_SHIFT)
 1180: 		server->filter_nextpt = 0;
 1181: 
 1182: 	/*
 1183: 	 * Sort indices into increasing delay order
 1184: 	 */
 1185: 	for (i = 0; i < NTP_SHIFT; i++)
 1186: 		ord[i] = i;
 1187: 	
 1188: 	for (i = 0; i < (NTP_SHIFT-1); i++) {
 1189: 		for (j = i+1; j < NTP_SHIFT; j++) {
 1190: 			if (server->filter_delay[ord[j]] == 0)
 1191: 				continue;
 1192: 			if (server->filter_delay[ord[i]] == 0
 1193: 			    || (server->filter_delay[ord[i]]
 1194: 			    > server->filter_delay[ord[j]])) {
 1195: 				register int tmp;
 1196: 
 1197: 				tmp = ord[i];
 1198: 				ord[i] = ord[j];
 1199: 				ord[j] = tmp;
 1200: 			}
 1201: 		}
 1202: 	}
 1203: 
 1204: 	/*
 1205: 	 * Now compute the dispersion, and assign values to delay and
 1206: 	 * offset.  If there are no samples in the register, delay and
 1207: 	 * offset go to zero and dispersion is set to the maximum.
 1208: 	 */
 1209: 	if (server->filter_delay[ord[0]] == 0) {
 1210: 		server->delay = 0;
 1211: 		L_CLR(&server->offset);
 1212: 		server->soffset = 0;
 1213: 		server->dispersion = PEER_MAXDISP;
 1214: 	} else {
 1215: 		register s_fp d;
 1216: 
 1217: 		server->delay = server->filter_delay[ord[0]];
 1218: 		server->offset = server->filter_offset[ord[0]];
 1219: 		server->soffset = LFPTOFP(&server->offset);
 1220: 		server->dispersion = 0;
 1221: 		for (i = 1; i < NTP_SHIFT; i++) {
 1222: 			if (server->filter_delay[ord[i]] == 0)
 1223: 				d = PEER_MAXDISP;
 1224: 			else {
 1225: 				d = server->filter_soffset[ord[i]]
 1226: 				    - server->filter_soffset[ord[0]];
 1227: 				if (d < 0)
 1228: 					d = -d;
 1229: 				if (d > PEER_MAXDISP)
 1230: 					d = PEER_MAXDISP;
 1231: 			}
 1232: 			/*
 1233: 			 * XXX This *knows* PEER_FILTER is 1/2
 1234: 			 */
 1235: 			server->dispersion += (u_fp)(d) >> i;
 1236: 		}
 1237: 	}
 1238: 	/*
 1239: 	 * We're done
 1240: 	 */
 1241: }
 1242: 
 1243: 
 1244: /* clock_count - count the clock sources we have
 1245:  */
 1246: static void
 1247: clock_count(void)
 1248: {
 1249: 	register struct server *server;
 1250: 	register int n;
 1251: 
 1252: 	/* reset counts */
 1253: 	validcount = valid_n_low = 0;
 1254: 
 1255: 	/* go through the list of servers and count the clocks we believe
 1256: 	 * and that have low dispersion
 1257: 	 */
 1258: 	for (n = 0; n < sys_numservers; n++) {
 1259: 		server = sys_servers[n];
 1260: 		if (server->delay == 0) {
 1261: 			continue;	/* no data */
 1262: 		}
 1263: 		if (server->stratum > NTP_INFIN) {
 1264: 			continue;	/* stratum no good */
 1265: 		}
 1266: 		if (server->delay > NTP_MAXWGT) {
 1267: 			continue;	/* too far away */
 1268: 		}
 1269: 		if (server->leap == LEAP_NOTINSYNC)
 1270: 			continue;	/* he's in trouble */
 1271: 		if (!L_ISHIS(&server->org, &server->reftime)) {
 1272: 			continue;	/* very broken host */
 1273: 		}
 1274: 		if ((server->org.l_ui - server->reftime.l_ui) >= NTP_MAXAGE) {
 1275: 			continue;	/* too long without sync */
 1276: 		}
 1277: 		if (server->trust != 0) {
 1278: 			continue;
 1279: 		}
 1280: 
 1281: 		/*
 1282: 		 * This one is a valid time source..
 1283: 		 */
 1284: 		validcount++;
 1285: 
 1286: 		/*
 1287: 		 * See if this one has a okay low dispersion
 1288: 		 */
 1289: 		if (server->dispersion <= DESIREDDISP)
 1290: 		    valid_n_low++;
 1291: 	}
 1292: 
 1293: 	if (debug > 1)
 1294: 		printf("have %d, valid %d, low %d\n",
 1295: 			responding, validcount, valid_n_low);
 1296: }
 1297: 
 1298: 
 1299: /*
 1300:  * clock_select - select the pick-of-the-litter clock from the samples
 1301:  *		  we've got.
 1302:  */
 1303: static struct server *
 1304: clock_select(void)
 1305: {
 1306: 	register struct server *server;
 1307: 	register int i;
 1308: 	register int nlist;
 1309: 	register s_fp d;
 1310: 	register int j;
 1311: 	register int n;
 1312: 	s_fp local_threshold;
 1313: 	struct server *server_list[NTP_MAXCLOCK];
 1314: 	u_fp server_badness[NTP_MAXCLOCK];
 1315: 	struct server *sys_server;
 1316: 
 1317: 	/*
 1318: 	 * This first chunk of code is supposed to go through all
 1319: 	 * servers we know about to find the NTP_MAXLIST servers which
 1320: 	 * are most likely to succeed.  We run through the list
 1321: 	 * doing the sanity checks and trying to insert anyone who
 1322: 	 * looks okay.  We are at all times aware that we should
 1323: 	 * only keep samples from the top two strata and we only need
 1324: 	 * NTP_MAXLIST of them.
 1325: 	 */
 1326: 	nlist = 0;	/* none yet */
 1327: 	for (n = 0; n < sys_numservers; n++) {
 1328: 		server = sys_servers[n];
 1329: 		if (server->delay == 0)
 1330: 			continue;	/* no data */
 1331: 		if (server->stratum > NTP_INFIN)
 1332: 			continue;	/* stratum no good */
 1333: 		if (server->delay > NTP_MAXWGT) {
 1334: 			continue;	/* too far away */
 1335: 		}
 1336: 		if (server->leap == LEAP_NOTINSYNC)
 1337: 			continue;	/* he's in trouble */
 1338: 		if (!L_ISHIS(&server->org, &server->reftime)) {
 1339: 			continue;	/* very broken host */
 1340: 		}
 1341: 		if ((server->org.l_ui - server->reftime.l_ui)
 1342: 		    >= NTP_MAXAGE) {
 1343: 			continue;	/* too long without sync */
 1344: 		}
 1345: 		if (server->trust != 0) {
 1346: 			continue;
 1347: 		}
 1348: 
 1349: 		/*
 1350: 		 * This one seems sane.  Find where he belongs
 1351: 		 * on the list.
 1352: 		 */
 1353: 		d = server->dispersion + server->dispersion;
 1354: 		for (i = 0; i < nlist; i++)
 1355: 			if (server->stratum <= server_list[i]->stratum)
 1356: 				break;
 1357: 		for ( ; i < nlist; i++) {
 1358: 			if (server->stratum < server_list[i]->stratum)
 1359: 				break;
 1360: 			if (d < (s_fp) server_badness[i])
 1361: 				break;
 1362: 		}
 1363: 
 1364: 		/*
 1365: 		 * If i points past the end of the list, this
 1366: 		 * guy is a loser, else stick him in.
 1367: 		 */
 1368: 		if (i >= NTP_MAXLIST)
 1369: 			continue;
 1370: 		for (j = nlist; j > i; j--)
 1371: 			if (j < NTP_MAXLIST) {
 1372: 				server_list[j] = server_list[j-1];
 1373: 				server_badness[j]
 1374: 				    = server_badness[j-1];
 1375: 			}
 1376: 
 1377: 		server_list[i] = server;
 1378: 		server_badness[i] = d;
 1379: 		if (nlist < NTP_MAXLIST)
 1380: 			nlist++;
 1381: 	}
 1382: 
 1383: 	/*
 1384: 	 * Got the five-or-less best.  Cut the list where the number of
 1385: 	 * strata exceeds two.
 1386: 	 */
 1387: 	j = 0;
 1388: 	for (i = 1; i < nlist; i++)
 1389: 		if (server_list[i]->stratum > server_list[i-1]->stratum)
 1390: 			if (++j == 2) {
 1391: 				nlist = i;
 1392: 				break;
 1393: 			}
 1394: 
 1395: 	/*
 1396: 	 * Whew!  What we should have by now is 0 to 5 candidates for
 1397: 	 * the job of syncing us.  If we have none, we're out of luck.
 1398: 	 * If we have one, he's a winner.  If we have more, do falseticker
 1399: 	 * detection.
 1400: 	 */
 1401: 
 1402: 	if (nlist == 0)
 1403: 		sys_server = 0;
 1404: 	else if (nlist == 1) {
 1405: 		sys_server = server_list[0];
 1406: 	} else {
 1407: 		/*
 1408: 		 * Re-sort by stratum, bdelay estimate quality and
 1409: 		 * server.delay.
 1410: 		 */
 1411: 		for (i = 0; i < nlist-1; i++)
 1412: 			for (j = i+1; j < nlist; j++) {
 1413: 				if (server_list[i]->stratum
 1414: 				    < server_list[j]->stratum)
 1415: 					break;	/* already sorted by stratum */
 1416: 				if (server_list[i]->delay
 1417: 				    < server_list[j]->delay)
 1418: 					continue;
 1419: 				server = server_list[i];
 1420: 				server_list[i] = server_list[j];
 1421: 				server_list[j] = server;
 1422: 			}
 1423: 		
 1424: 		/*
 1425: 		 * Calculate the fixed part of the dispersion limit
 1426: 		 */
 1427: 		local_threshold = (FP_SECOND >> (-(int)NTPDATE_PRECISION))
 1428: 		    + NTP_MAXSKW;
 1429: 
 1430: 		/*
 1431: 		 * Now drop samples until we're down to one.
 1432: 		 */
 1433: 		while (nlist > 1) {
 1434: 			for (n = 0; n < nlist; n++) {
 1435: 				server_badness[n] = 0;
 1436: 				for (j = 0; j < nlist; j++) {
 1437: 					if (j == n)	/* with self? */
 1438: 						continue;
 1439: 					d = server_list[j]->soffset
 1440: 					    - server_list[n]->soffset;
 1441: 					if (d < 0)	/* absolute value */
 1442: 						d = -d;
 1443: 					/*
 1444: 					 * XXX This code *knows* that
 1445: 					 * NTP_SELECT is 3/4
 1446: 					 */
 1447: 					for (i = 0; i < j; i++)
 1448: 						d = (d>>1) + (d>>2);
 1449: 					server_badness[n] += d;
 1450: 				}
 1451: 			}
 1452: 
 1453: 			/*
 1454: 			 * We now have an array of nlist badness
 1455: 			 * coefficients.  Find the badest.  Find
 1456: 			 * the minimum precision while we're at
 1457: 			 * it.
 1458: 			 */
 1459: 			i = 0;
 1460: 			n = server_list[0]->precision;;
 1461: 			for (j = 1; j < nlist; j++) {
 1462: 				if (server_badness[j] >= server_badness[i])
 1463: 					i = j;
 1464: 				if (n > server_list[j]->precision)
 1465: 					n = server_list[j]->precision;
 1466: 			}
 1467: 			
 1468: 			/*
 1469: 			 * i is the index of the server with the worst
 1470: 			 * dispersion.  If his dispersion is less than
 1471: 			 * the threshold, stop now, else delete him and
 1472: 			 * continue around again.
 1473: 			 */
 1474: 			if (server_badness[i] < (local_threshold
 1475: 						 + (FP_SECOND >> (-n))))
 1476: 				break;
 1477: 			for (j = i + 1; j < nlist; j++)
 1478: 				server_list[j-1] = server_list[j];
 1479: 			nlist--;
 1480: 		}
 1481: 
 1482: 		/*
 1483: 		 * What remains is a list of less than 5 servers.  Take
 1484: 		 * the best.
 1485: 		 */
 1486: 		sys_server = server_list[0];
 1487: 	}
 1488: 
 1489: 	/*
 1490: 	 * That's it.  Return our server.
 1491: 	 */
 1492: 	return sys_server;
 1493: }
 1494: 
 1495: 
 1496: /*
 1497:  * set_local_clock -- handle setting the local clock or displaying info.
 1498:  */
 1499: static void
 1500: set_local_clock(void)
 1501: {
 1502: 	register int i;
 1503: 	register struct server *server;
 1504: 	time_t tmp;
 1505: 	double dtemp;
 1506: 
 1507: 	/*
 1508: 	 * if setting time then print final analysis
 1509: 	 */
 1510: 	if (set_time)
 1511: 	    analysis(1);
 1512: 
 1513: 	/*
 1514: 	 * pick a clock
 1515: 	 */
 1516: 	server = clock_select();
 1517: 
 1518: 	/*
 1519: 	 * do some display of information
 1520: 	 */
 1521: 	if (debug || verbose) {
 1522: 		for (i = 0; i < sys_numservers; i++)
 1523: 			printserver(sys_servers[i], stdout);
 1524: 		if (debug)
 1525: 			printf("packets sent %ld, received %ld\n",
 1526: 				total_xmit, total_recv);
 1527: 	}
 1528: 
 1529: 	/*
 1530: 	 * see if we have a server to set the time with
 1531: 	 */
 1532: 	if (server == 0) {
 1533: 	    if (!set_time || verbose)
 1534: 		fprintf(stdout,"No servers available to sync time with\n");
 1535: 	    exit(1);
 1536: 	}
 1537: 
 1538: 	/*
 1539: 	 * we have a valid and selected time to use!!!!!
 1540: 	 */
 1541: 
 1542: 	/*
 1543: 	 * if we are not setting the time then display offset and exit
 1544: 	 */
 1545: 	if (!set_time) {
 1546: 		fprintf(stdout,
 1547: 			"Your clock is off by %s seconds. (%s) [%ld/%ld]\n",
 1548: 			lfptoa(&server->offset, 7),
 1549: 			ntoa(&server->srcadr),
 1550: 			total_xmit, total_recv);
 1551: 		exit(0);
 1552: 	}
 1553: 
 1554: 	/*
 1555: 	 * set the clock
 1556: 	 * XXX: Examine the more flexible approach used by ntpdate.
 1557: 	 * Note that a design consideration here is that we sometimes
 1558: 	 * _want_ to step the clock by a _huge_ amount in either
 1559: 	 * direction, because the local clock is completely bogus.
 1560: 	 * This condition must be recognized and dealt with, so
 1561: 	 * that we always get a good time when this completes.
 1562: 	 * -- jhutz+@cmu.edu, 16-Aug-1999
 1563: 	 */
 1564: 	LFPTOD(&server->offset, dtemp);
 1565: 	step_systime(dtemp);
 1566: 	time(&tmp);
 1567: 	fprintf(stdout,"Time set to %.20s [%s %s %ld/%ld]\n",
 1568: 		ctime(&tmp)+4,
 1569: 		ntoa(&server->srcadr),
 1570: 		lfptoa(&server->offset, 7),
 1571: 		total_xmit, total_recv);
 1572: 	exit(0);
 1573: }
 1574: 
 1575: 
 1576: /*
 1577:  * findserver - find a server in the list given its address
 1578:  */
 1579: static struct server *
 1580: findserver(
 1581: 	struct sockaddr_in *addr
 1582: 	)
 1583: {
 1584: 	register int i;
 1585: 	register u_int32 netnum;
 1586: 
 1587: 	if (htons(addr->sin_port) != NTP_PORT)
 1588: 		return 0;
 1589: 	netnum = addr->sin_addr.s_addr;
 1590: 
 1591: 	for (i = 0; i < sys_numservers; i++) {
 1592: 		if (netnum == sys_servers[i]->srcadr.sin_addr.s_addr)
 1593: 			return sys_servers[i];
 1594: 	}
 1595: 	return 0;
 1596: }
 1597: 
 1598: 
 1599: /*
 1600:  * timer - process a timer interrupt
 1601:  */
 1602: static void
 1603: timer(void)
 1604: {
 1605: 	register int k;
 1606: 
 1607: 	/*
 1608: 	 * Bump the current idea of the time
 1609: 	 */
 1610: 	current_time++;
 1611: 
 1612: 	/*
 1613: 	 * see if we have reached half time
 1614: 	 */
 1615: 	if (current_time >= half_time && !secondhalf) {
 1616: 	    secondhalf++;
 1617: 	    if (debug)
 1618: 		printf("\nSecond Half of Timeout!\n");
 1619: 	    printmsg++;
 1620: 	}
 1621: 
 1622: 	/*
 1623: 	 * We only want to send a few packets per transmit interrupt
 1624: 	 * to throttle things
 1625: 	 */
 1626: 	for(k = 0;k < MAXXMITCOUNT;k++) {
 1627: 	    register int i, oldi;
 1628: 	    register u_long oldxtime;
 1629: 
 1630: 	    /*
 1631: 	     * We want to send a packet out for a server that has an
 1632: 	     * expired event time. However to be mellow about this, we only
 1633: 	     * use one expired event timer and to avoid starvation we use
 1634: 	     * the one with the oldest last transmit time.
 1635: 	     */
 1636: 	    oldi = -1;
 1637: 	    oldxtime = 0;
 1638: 	    for (i = 0; i < sys_numservers; i++) {
 1639: 		if (sys_servers[i]->event_time <= current_time) {
 1640: 		    if (oldi < 0 || oldxtime > sys_servers[i]->last_xmit) {
 1641: 			oldxtime = sys_servers[i]->last_xmit;
 1642: 			oldi = i;
 1643: 		    }
 1644: 		}
 1645: 	    }
 1646: 	    if (oldi >= 0)
 1647: 		transmit(sys_servers[oldi]);
 1648: 	    else
 1649: 		break;	/* no expired event */
 1650: 	} /* end of transmit loop */
 1651: }
 1652: 
 1653: 
 1654: #ifndef SYS_WINNT
 1655: /*
 1656:  * alarming - record the occurance of an alarm interrupt
 1657:  */
 1658: static RETSIGTYPE
 1659: alarming(
 1660: 	int sig
 1661: 	)
 1662: #else
 1663: void CALLBACK 
 1664: alarming(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
 1665: #endif /* SYS_WINNT */
 1666: {
 1667: 	alarm_flag++;
 1668: }
 1669: 
 1670: 
 1671: /*
 1672:  * init_alarm - set up the timer interrupt
 1673:  */
 1674: static void
 1675: init_alarm(void)
 1676: {
 1677: #ifndef SYS_WINNT
 1678: # ifndef HAVE_TIMER_SETTIME
 1679: 	struct itimerval itimer;
 1680: # else
 1681: 	struct itimerspec ntpdate_itimer;
 1682: # endif
 1683: #else
 1684: 	TIMECAPS tc;
 1685: 	UINT wTimerRes, wTimerID;
 1686: # endif /* SYS_WINNT */
 1687: #if defined SYS_CYGWIN32 || defined SYS_WINNT
 1688: 	HANDLE hToken;
 1689: 	TOKEN_PRIVILEGES tkp;
 1690: 	DWORD dwUser = 0;
 1691: #endif /* SYS_WINNT */
 1692: 
 1693: 	alarm_flag = 0;
 1694: 
 1695: #ifndef SYS_WINNT
 1696: # if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME)
 1697: 	alarm_flag = 0;
 1698: 	/* this code was put in as setitimer() is non existant this us the
 1699: 	 * POSIX "equivalents" setup - casey
 1700: 	 */
 1701: 	/* ntpdate_timerid is global - so we can kill timer later */
 1702: 	if (timer_create (CLOCK_REALTIME, NULL, &ntpdate_timerid) ==
 1703: #  ifdef SYS_VXWORKS
 1704: 		ERROR
 1705: #  else
 1706: 		-1
 1707: #  endif
 1708: 		)
 1709: 	{
 1710: 		fprintf (stderr, "init_alarm(): timer_create (...) FAILED\n");
 1711: 		return;
 1712: 	}
 1713: 
 1714: 	/*	TIMER_HZ = (5)
 1715: 	 * Set up the alarm interrupt.	The first comes 1/(2*TIMER_HZ)
 1716: 	 * seconds from now and they continue on every 1/TIMER_HZ seconds.
 1717: 	 */
 1718: 	(void) signal_no_reset(SIGALRM, alarming);
 1719: 	ntpdate_itimer.it_interval.tv_sec = ntpdate_itimer.it_value.tv_sec = 0;
 1720: 	ntpdate_itimer.it_interval.tv_nsec = 1000000000/TIMER_HZ;
 1721: 	ntpdate_itimer.it_value.tv_nsec = 1000000000/(TIMER_HZ<<1);
 1722: 	timer_settime(ntpdate_timerid, 0 /* !TIMER_ABSTIME */, &ntpdate_itimer, NULL);
 1723: # else
 1724: 	/*
 1725: 	 * Set up the alarm interrupt.	The first comes 1/(2*TIMER_HZ)
 1726: 	 * seconds from now and they continue on every 1/TIMER_HZ seconds.
 1727: 	 */
 1728: 	(void) signal_no_reset(SIGALRM, alarming);
 1729: 	itimer.it_interval.tv_sec = itimer.it_value.tv_sec = 0;
 1730: 	itimer.it_interval.tv_usec = 1000000/TIMER_HZ;
 1731: 	itimer.it_value.tv_usec = 1000000/(TIMER_HZ<<1);
 1732: 	setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
 1733: # endif
 1734: #if defined SYS_CYGWIN32
 1735: 	/*
 1736: 	 * Get previleges needed for fiddling with the clock
 1737: 	 */
 1738: 
 1739: 	/* get the current process token handle */
 1740: 	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
 1741: 		msyslog(LOG_ERR, "OpenProcessToken failed: %m");
 1742: 		exit(1);
 1743: 	}
 1744: 	/* get the LUID for system-time privilege. */
 1745: 	LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid);
 1746: 	tkp.PrivilegeCount = 1;  /* one privilege to set */
 1747: 	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 1748: 	/* get set-time privilege for this process. */
 1749: 	AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0);
 1750: 	/* cannot test return value of AdjustTokenPrivileges. */
 1751: 	if (GetLastError() != ERROR_SUCCESS)
 1752: 		msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m");
 1753: #endif
 1754: #else	/* SYS_WINNT */
 1755: 	_tzset();
 1756: 
 1757: 	/*
 1758: 	 * Get previleges needed for fiddling with the clock
 1759: 	 */
 1760: 
 1761: 	/* get the current process token handle */
 1762: 	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
 1763: 		msyslog(LOG_ERR, "OpenProcessToken failed: %m");
 1764: 		exit(1);
 1765: 	}
 1766: 	/* get the LUID for system-time privilege. */
 1767: 	LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid);
 1768: 	tkp.PrivilegeCount = 1;  /* one privilege to set */
 1769: 	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 1770: 	/* get set-time privilege for this process. */
 1771: 	AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0);
 1772: 	/* cannot test return value of AdjustTokenPrivileges. */
 1773: 	if (GetLastError() != ERROR_SUCCESS)
 1774: 		msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m");
 1775: 
 1776: 	/*
 1777: 	 * Set up timer interrupts for every 2**EVENT_TIMEOUT seconds
 1778: 	 * Under Win/NT, expiry of timer interval leads to invocation
 1779: 	 * of a callback function (on a different thread) rather than
 1780: 	 * generating an alarm signal
 1781: 	 */
 1782: 
 1783: 	/* determine max and min resolution supported */
 1784: 	if(timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
 1785: 		msyslog(LOG_ERR, "timeGetDevCaps failed: %m");
 1786: 		exit(1);
 1787: 	}
 1788: 	wTimerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax);
 1789: 	/* establish the minimum timer resolution that we'll use */
 1790: 	timeBeginPeriod(wTimerRes);
 1791: 
 1792: 	/* start the timer event */
 1793: 	wTimerID = timeSetEvent(
 1794: 		(UINT) (1000/TIMER_HZ),    /* Delay */
 1795: 		wTimerRes,			 /* Resolution */
 1796: 		(LPTIMECALLBACK) alarming, /* Callback function */
 1797: 		(DWORD) dwUser, 	 /* User data */
 1798: 		TIME_PERIODIC); 	 /* Event type (periodic) */
 1799: 	if (wTimerID == 0) {
 1800: 		msyslog(LOG_ERR, "timeSetEvent failed: %m");
 1801: 		exit(1);
 1802: 	}
 1803: #endif /* SYS_WINNT */
 1804: }
 1805: 
 1806: 
 1807: /*
 1808:  * init_io - initialize I/O data and open socket
 1809:  */
 1810: static void
 1811: init_io(void)
 1812: {
 1813: #ifdef SYS_WINNT
 1814:     	WORD wVersionRequested;
 1815: 	WSADATA wsaData;
 1816: 	init_transmitbuff();
 1817: #endif /* SYS_WINNT */
 1818: 
 1819: 	/*
 1820: 	 * Init buffer free list and stat counters
 1821: 	 */
 1822: 	init_recvbuff(sys_numservers + 2);
 1823: 
 1824: #if defined(HAVE_SIGNALED_IO)
 1825: 	set_signal();
 1826: #endif
 1827: 
 1828: #ifdef SYS_WINNT
 1829: 	wVersionRequested = MAKEWORD(1,1);
 1830: 	if (WSAStartup(wVersionRequested, &wsaData))
 1831: 	{
 1832: 		msyslog(LOG_ERR, "No useable winsock.dll: %m");
 1833: 		exit(1);
 1834: 	}
 1835: #endif /* SYS_WINNT */
 1836: 
 1837: 	BLOCKIO();
 1838: 
 1839: 	/* create a datagram (UDP) socket */
 1840: 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
 1841: 		msyslog(LOG_ERR, "socket() failed: %m");
 1842: 		exit(1);
 1843: 		/*NOTREACHED*/
 1844: 	}
 1845: 
 1846: 	/*
 1847: 	 * bind the socket to the NTP port
 1848: 	 */
 1849: 	if (!debug && set_time && !unpriv_port) {
 1850: 		struct sockaddr_in addr;
 1851: 
 1852: 		memset((char *)&addr, 0, sizeof addr);
 1853: 		addr.sin_family = AF_INET;
 1854: 		addr.sin_port = htons(NTP_PORT);
 1855: 		addr.sin_addr.s_addr = htonl(INADDR_ANY);
 1856: 		if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
 1857: #ifndef SYS_WINNT
 1858: 			if (errno == EADDRINUSE)
 1859: #else
 1860: 			if (WSAGetLastError() == WSAEADDRINUSE)
 1861: #endif
 1862: 				msyslog(LOG_ERR,
 1863: 				    "the NTP socket is in use, exiting");
 1864: 			else
 1865: 				msyslog(LOG_ERR, "bind() fails: %m");
 1866: 			exit(1);
 1867: 		}
 1868: 	}
 1869: 
 1870: 	FD_ZERO(&fdmask);
 1871: 	FD_SET(fd, &fdmask);
 1872: 
 1873: 	/*
 1874: 	 * set non-blocking,
 1875: 	 */
 1876: 
 1877: #ifdef USE_FIONBIO
 1878: 	/* in vxWorks we use FIONBIO, but the others are defined for old systems, so
 1879: 	 * all hell breaks loose if we leave them defined
 1880: 	 */
 1881: #undef O_NONBLOCK
 1882: #undef FNDELAY
 1883: #undef O_NDELAY
 1884: #endif
 1885: 
 1886: #if defined(O_NONBLOCK) /* POSIX */
 1887: 	if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
 1888: 	{
 1889: 		msyslog(LOG_ERR, "fcntl(O_NONBLOCK) fails: %m");
 1890: 		exit(1);
 1891: 		/*NOTREACHED*/
 1892: 	}
 1893: #elif defined(FNDELAY)
 1894: 	if (fcntl(fd, F_SETFL, FNDELAY) < 0)
 1895: 	{
 1896: 		msyslog(LOG_ERR, "fcntl(FNDELAY) fails: %m");
 1897: 		exit(1);
 1898: 		/*NOTREACHED*/
 1899: 	}
 1900: #elif defined(O_NDELAY) /* generally the same as FNDELAY */
 1901: 	if (fcntl(fd, F_SETFL, O_NDELAY) < 0)
 1902: 	{
 1903: 		msyslog(LOG_ERR, "fcntl(O_NDELAY) fails: %m");
 1904: 		exit(1);
 1905: 		/*NOTREACHED*/
 1906: 	}
 1907: #elif defined(FIONBIO)
 1908: 	if (
 1909: # if defined(VMS)
 1910: 		(ioctl(fd,FIONBIO,&1) < 0)
 1911: # elif defined(SYS_WINNT)
 1912: 		(ioctlsocket(fd,FIONBIO,(u_long *) &on) == SOCKET_ERROR)
 1913: # else
 1914: 		(ioctl(fd,FIONBIO,&on) < 0)
 1915: # endif
 1916: 	   )
 1917: 	{
 1918: 		msyslog(LOG_ERR, "ioctl(FIONBIO) fails: %m");
 1919: 		exit(1);
 1920: 		/*NOTREACHED*/
 1921: 	}
 1922: #elif defined(FIOSNBIO)
 1923: 	if (ioctl(fd,FIOSNBIO,&on) < 0)
 1924: 	{
 1925: 		msyslog(LOG_ERR, "ioctl(FIOSNBIO) fails: %m");
 1926: 		exit(1);
 1927: 		/*NOTREACHED*/
 1928: 	}
 1929: #else
 1930: # include "Bletch: Need non-blocking I/O!"
 1931: #endif
 1932: 
 1933: #ifdef HAVE_SIGNALED_IO
 1934: 	init_socket_sig(fd);
 1935: #endif /* not HAVE_SIGNALED_IO */
 1936: 
 1937: 	UNBLOCKIO();
 1938: }
 1939: 
 1940: 
 1941: /*
 1942:  * sendpkt - send a packet to the specified destination
 1943:  */
 1944: static int
 1945: sendpkt(
 1946: 	struct sockaddr_in *dest,
 1947: 	struct pkt *pkt,
 1948: 	int len
 1949: 	)
 1950: {
 1951: 	int cc;
 1952: 	static int horriblecnt = 0;
 1953: #ifdef SYS_WINNT
 1954: 	DWORD err;
 1955: #endif /* SYS_WINNT */
 1956: 
 1957: 	total_xmit++;	/* count it */
 1958: 
 1959: 	if (horrible) {
 1960: 	    if (++horriblecnt > HORRIBLEOK) {
 1961: 		if (debug > 3)
 1962: 			printf("dropping send (%s)\n", ntoa(dest));
 1963: 		if (horriblecnt >= HORRIBLEOK+horrible)
 1964: 		    horriblecnt = 0;
 1965: 		return 0;
 1966: 	    }
 1967: 	}
 1968: 
 1969: 
 1970: 	cc = sendto(fd, (char *)pkt, (size_t)len, 0, (struct sockaddr *)dest,
 1971: 	    sizeof(struct sockaddr_in));
 1972: #ifndef SYS_WINNT
 1973: 	if (cc == -1) {
 1974: 		if (errno != EWOULDBLOCK && errno != ENOBUFS)
 1975: #else
 1976: 	if (cc == SOCKET_ERROR) {
 1977: 		err = WSAGetLastError();
 1978: 		if (err != WSAEWOULDBLOCK && err != WSAENOBUFS)
 1979: #endif /* SYS_WINNT */
 1980: 			msyslog(LOG_ERR, "sendto(%s): %m", ntoa(dest));
 1981: 		return -1;
 1982: 	}
 1983: 	return 0;
 1984: }
 1985: 
 1986: 
 1987: /*
 1988:  * input_handler - receive packets asynchronously
 1989:  */
 1990: void
 1991: input_handler(l_fp *xts)
 1992: {
 1993: 	register int n;
 1994: 	register struct recvbuf *rb;
 1995: 	struct timeval tvzero;
 1996: 	int fromlen;
 1997: 	fd_set fds;
 1998: 	l_fp ts;
 1999: 	ts = *xts; /* we ignore xts, but make the compiler happy */
 2000: 
 2001: 	/*
 2002: 	 * Do a poll to see if we have data
 2003: 	 */
 2004: 	for (;;) {
 2005: 		fds = fdmask;
 2006: 		tvzero.tv_sec = tvzero.tv_usec = 0;
 2007: 		n = select(fd+1, &fds, (fd_set *)0, (fd_set *)0, &tvzero);
 2008: 
 2009: 		/*
 2010: 		 * If nothing to do, just return.  If an error occurred,
 2011: 		 * complain and return.  If we've got some, freeze a
 2012: 		 * timestamp.
 2013: 		 */
 2014: 		if (n == 0)
 2015: 			return;
 2016: 		else if (n == -1) {
 2017: 			if (errno != EINTR) {
 2018: 				msyslog(LOG_ERR, "select() error: %m");
 2019: 			}
 2020: 			return;
 2021: 		}
 2022: 		get_systime(&ts);
 2023: 
 2024: 		/*
 2025: 		 * Get a buffer and read the frame.  If we
 2026: 		 * haven't got a buffer, or this is received
 2027: 		 * on the wild card socket, just dump the packet.
 2028: 		 */
 2029: 		if (initializing || free_recvbuffs == 0) {
 2030: 			char buf[100];
 2031: 
 2032: #ifndef SYS_WINNT
 2033: 			(void) read(fd, buf, sizeof buf);
 2034: #else
 2035: 			/* NT's _read does not operate on nonblocking sockets
 2036: 			 * either recvfrom or ReadFile() has to be used here.
 2037: 			 * ReadFile is used in [ntpd]ntp_intres() and ntpdc,
 2038: 			 * just to be different use recvfrom() here
 2039: 			 */
 2040: 			recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)0, NULL);
 2041: #endif /* SYS_WINNT */
 2042: 			continue;
 2043: 		}
 2044: 
 2045: 		rb = get_free_recv_buffer();
 2046: 
 2047: 		fromlen = sizeof(struct sockaddr_in);
 2048: 		rb->recv_length = recvfrom(fd, (char *)&rb->recv_pkt,
 2049: 		    sizeof(rb->recv_pkt), 0,
 2050: 		    (struct sockaddr *)&rb->srcadr, &fromlen);
 2051: 		if (rb->recv_length == -1) {
 2052: 			freerecvbuf(rb);
 2053: 			continue;
 2054: 		}
 2055: 
 2056: 		/*
 2057: 		 * Got one.  Mark how and when it got here,
 2058: 		 * put it on the full list.
 2059: 		 */
 2060: 		rb->recv_time = ts;
 2061: 		add_full_recv_buffer(rb);
 2062: 		total_recv++;	/* count it */
 2063: 	}
 2064: }
 2065: 
 2066: 
 2067: /* XXX ELIMINATE printserver similar in ntptrace.c, ntpdate.c */
 2068: /*
 2069:  * printserver - print detail information for a server
 2070:  */
 2071: static void
 2072: printserver(
 2073: 	register struct server *pp,
 2074: 	FILE *fp
 2075: 	)
 2076: {
 2077: 	register int i;
 2078: 	char junk[5];
 2079: 	char *str;
 2080: 
 2081: 	if (!debug) {
 2082: 	    (void) fprintf(fp,
 2083: 		"%-15s %d/%d %03o v%d s%d offset %9s delay %s disp %s\n",
 2084: 		ntoa(&pp->srcadr),
 2085: 		pp->xmtcnt,pp->rcvcnt,pp->reach,
 2086: 		pp->version,pp->stratum,
 2087: 		lfptoa(&pp->offset, 6), ufptoa(pp->delay, 5),
 2088: 		ufptoa(pp->dispersion, 4));
 2089: 	    return;
 2090: 	}
 2091: 
 2092: 	(void) fprintf(fp, "server %s, port %d\n",
 2093: 			   ntoa(&pp->srcadr), ntohs(pp->srcadr.sin_port));
 2094: 
 2095: 	(void) fprintf(fp, "stratum %d, precision %d, leap %c%c, trust %03o\n",
 2096: 			   pp->stratum, pp->precision,
 2097: 			   pp->leap & 0x2 ? '1' : '0',
 2098: 			   pp->leap & 0x1 ? '1' : '0',
 2099: 			   pp->trust);
 2100: 
 2101: 	if (pp->stratum == 1) {
 2102: 		junk[4] = 0;
 2103: 		memmove(junk, (char *)&pp->refid, 4);
 2104: 		str = junk;
 2105: 	} else {
 2106: 		str = numtoa(pp->refid);
 2107: 	}
 2108: 	(void) fprintf(fp,
 2109: 			   "refid [%s], delay %s, dispersion %s\n",
 2110: 			   str, fptoa((s_fp)pp->delay, 5),
 2111: 			   ufptoa(pp->dispersion, 5));
 2112: 
 2113: 	(void) fprintf(fp, "transmitted %d, received %d, reachable %03o\n",
 2114: 	    pp->xmtcnt, pp->rcvcnt, pp->reach);
 2115: 
 2116: 	(void) fprintf(fp, "reference time:    %s\n",
 2117: 			   prettydate(&pp->reftime));
 2118: 	(void) fprintf(fp, "originate timestamp: %s\n",
 2119: 			   prettydate(&pp->org));
 2120: 	(void) fprintf(fp, "transmit timestamp:  %s\n",
 2121: 			   prettydate(&pp->xmt));
 2122: 
 2123: 	(void) fprintf(fp, "filter delay: ");
 2124: 	for (i = 0; i < NTP_SHIFT; i++) {
 2125: 		(void) fprintf(fp, " %-8.8s", fptoa(pp->filter_delay[i], 5));
 2126: 		if (i == (NTP_SHIFT>>1)-1)
 2127: 			(void) fprintf(fp, "\n        ");
 2128: 	}
 2129: 	(void) fprintf(fp, "\n");
 2130: 
 2131: 	(void) fprintf(fp, "filter offset:");
 2132: 	for (i = 0; i < PEER_SHIFT; i++) {
 2133: 		(void) fprintf(fp, " %-8.8s", lfptoa(&pp->filter_offset[i], 6));
 2134: 		if (i == (PEER_SHIFT>>1)-1)
 2135: 			(void) fprintf(fp, "\n        ");
 2136: 	}
 2137: 	(void) fprintf(fp, "\n");
 2138: 
 2139: 	(void) fprintf(fp, "delay %s, dispersion %s\n",
 2140: 			   fptoa((s_fp)pp->delay, 5), ufptoa(pp->dispersion, 5));
 2141: 
 2142: 	(void) fprintf(fp, "offset %s\n\n",
 2143: 			   lfptoa(&pp->offset, 6));
 2144: }
 2145: 
 2146: #if !defined(HAVE_VSPRINTF)
 2147: int
 2148: vsprintf(
 2149: 	char *str,
 2150: 	const char *fmt,
 2151: 	va_list ap
 2152: 	)
 2153: {
 2154: 	FILE f;
 2155: 	int len;
 2156: 
 2157: 	f._flag = _IOWRT+_IOSTRG;
 2158: 	f._ptr = str;
 2159: 	f._cnt = 32767;
 2160: 	len = _doprnt(fmt, ap, &f);
 2161: 	*f._ptr = 0;
 2162: 	return (len);
 2163: }
 2164: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>