Annotation of embedaddon/ntp/ntpdate/ntptimeset.c, revision 1.1

1.1     ! misho       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>