Annotation of embedaddon/ntp/ntpd/ntp_util.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * ntp_util.c - stuff I didn't have any other place for
        !             3:  */
        !             4: #ifdef HAVE_CONFIG_H
        !             5: # include <config.h>
        !             6: #endif
        !             7: 
        !             8: #include "ntpd.h"
        !             9: #include "ntp_io.h"
        !            10: #include "ntp_unixtime.h"
        !            11: #include "ntp_filegen.h"
        !            12: #include "ntp_if.h"
        !            13: #include "ntp_stdlib.h"
        !            14: #include "ntp_assert.h"
        !            15: 
        !            16: #include <stdio.h>
        !            17: #include <ctype.h>
        !            18: #include <sys/types.h>
        !            19: #ifdef HAVE_SYS_IOCTL_H
        !            20: # include <sys/ioctl.h>
        !            21: #endif
        !            22: 
        !            23: #ifdef HAVE_IEEEFP_H
        !            24: # include <ieeefp.h>
        !            25: #endif
        !            26: #ifdef HAVE_MATH_H
        !            27: # include <math.h>
        !            28: #endif
        !            29: 
        !            30: #ifdef  DOSYNCTODR
        !            31: # if !defined(VMS)
        !            32: #  include <sys/resource.h>
        !            33: # endif /* VMS */
        !            34: #endif
        !            35: 
        !            36: #if defined(VMS)
        !            37: # include <descrip.h>
        !            38: #endif /* VMS */
        !            39: 
        !            40: /*
        !            41:  * Defines used by the leapseconds stuff
        !            42:  */
        !            43: #define        MAX_TAI 100                     /* max TAI offset (s) */
        !            44: #define        L_DAY   86400UL                 /* seconds per day */
        !            45: #define        L_YEAR  (L_DAY * 365)           /* days per year */
        !            46: #define        L_LYEAR (L_YEAR + L_DAY)        /* days per leap year */
        !            47: #define        L_4YEAR (L_LYEAR + 3 * L_YEAR)  /* days per leap cycle */
        !            48: #define        L_CENT  (L_4YEAR * 25)          /* days per century */
        !            49: 
        !            50: /*
        !            51:  * This contains odds and ends, including the hourly stats, various
        !            52:  * configuration items, leapseconds stuff, etc.
        !            53:  */
        !            54: /*
        !            55:  * File names
        !            56:  */
        !            57: static char *key_file_name;            /* keys file name */
        !            58: char   *leapseconds_file_name;         /* leapseconds file name */
        !            59: char   *stats_drift_file;              /* frequency file name */
        !            60: static char *stats_temp_file;          /* temp frequency file name */
        !            61: double wander_resid;                   /* wander threshold */
        !            62: double wander_threshold = 1e-7;        /* initial wander threshold */
        !            63: int    drift_file_sw;                  /* clock update switch */
        !            64: 
        !            65: /*
        !            66:  * Statistics file stuff
        !            67:  */
        !            68: #ifndef NTP_VAR
        !            69: # ifndef SYS_WINNT
        !            70: #  define NTP_VAR "/var/NTP/"          /* NOTE the trailing '/' */
        !            71: # else
        !            72: #  define NTP_VAR "c:\\var\\ntp\\"     /* NOTE the trailing '\\' */
        !            73: # endif /* SYS_WINNT */
        !            74: #endif
        !            75: 
        !            76: #ifndef MAXPATHLEN
        !            77: # define MAXPATHLEN 256
        !            78: #endif
        !            79: 
        !            80: #ifdef DEBUG_TIMING
        !            81: static FILEGEN timingstats;
        !            82: #endif
        !            83: #ifdef OPENSSL
        !            84: static FILEGEN cryptostats;
        !            85: #endif /* OPENSSL */
        !            86: 
        !            87: static char statsdir[MAXPATHLEN] = NTP_VAR;
        !            88: static FILEGEN peerstats;
        !            89: static FILEGEN loopstats;
        !            90: static FILEGEN clockstats;
        !            91: static FILEGEN rawstats;
        !            92: static FILEGEN sysstats;
        !            93: static FILEGEN protostats;
        !            94: 
        !            95: /*
        !            96:  * This controls whether stats are written to the fileset. Provided
        !            97:  * so that ntpdc can turn off stats when the file system fills up. 
        !            98:  */
        !            99: int stats_control;
        !           100: 
        !           101: /*
        !           102:  * Initial frequency offset later passed to the loopfilter.
        !           103:  */
        !           104: double old_drift = 1e9;                /* current frequency */
        !           105: static double prev_drift_comp;         /* last frequency update */
        !           106: 
        !           107: /*
        !           108:  * Static prototypes
        !           109:  */
        !           110: static int leap_file(FILE *);
        !           111: static void record_sys_stats(void);
        !           112: 
        !           113: /* 
        !           114:  * Prototypes
        !           115:  */
        !           116: #ifdef DEBUG
        !           117: void   uninit_util(void);
        !           118: #endif
        !           119: 
        !           120: 
        !           121: /*
        !           122:  * uninit_util - free memory allocated by init_util
        !           123:  */
        !           124: #ifdef DEBUG
        !           125: void
        !           126: uninit_util(void)
        !           127: {
        !           128: #if defined(_MSC_VER) && defined (_DEBUG)
        !           129:        _CrtCheckMemory();
        !           130: #endif
        !           131:        if (stats_drift_file) {
        !           132:                free(stats_drift_file);
        !           133:                free(stats_temp_file);
        !           134:                stats_drift_file = NULL;
        !           135:                stats_temp_file = NULL;
        !           136:        }
        !           137:        if (key_file_name) {
        !           138:                free(key_file_name);
        !           139:                key_file_name = NULL;
        !           140:        }
        !           141:        filegen_unregister("peerstats");
        !           142:        filegen_unregister("loopstats");
        !           143:        filegen_unregister("clockstats");
        !           144:        filegen_unregister("rawstats");
        !           145:        filegen_unregister("sysstats");
        !           146:        filegen_unregister("protostats");
        !           147: #ifdef OPENSSL
        !           148:        filegen_unregister("cryptostats");
        !           149: #endif /* OPENSSL */
        !           150: #ifdef DEBUG_TIMING
        !           151:        filegen_unregister("timingstats");
        !           152: #endif /* DEBUG_TIMING */
        !           153: 
        !           154: #if defined(_MSC_VER) && defined (_DEBUG)
        !           155:        _CrtCheckMemory();
        !           156: #endif
        !           157: }
        !           158: #endif /* DEBUG */
        !           159: 
        !           160: 
        !           161: /*
        !           162:  * init_util - initialize the utilities (ntpd included)
        !           163:  */
        !           164: void
        !           165: init_util(void)
        !           166: {
        !           167:        stats_drift_file = NULL;
        !           168:        stats_temp_file = NULL;
        !           169:        key_file_name = NULL;
        !           170:        filegen_register(statsdir, "peerstats",   &peerstats);
        !           171:        filegen_register(statsdir, "loopstats",   &loopstats);
        !           172:        filegen_register(statsdir, "clockstats",  &clockstats);
        !           173:        filegen_register(statsdir, "rawstats",    &rawstats);
        !           174:        filegen_register(statsdir, "sysstats",    &sysstats);
        !           175:        filegen_register(statsdir, "protostats",  &protostats);
        !           176: #ifdef OPENSSL
        !           177:        filegen_register(statsdir, "cryptostats", &cryptostats);
        !           178: #endif /* OPENSSL */
        !           179: #ifdef DEBUG_TIMING
        !           180:        filegen_register(statsdir, "timingstats", &timingstats);
        !           181: #endif /* DEBUG_TIMING */
        !           182: #ifdef DEBUG
        !           183:        atexit(uninit_util);
        !           184: #endif /* DEBUG */
        !           185: }
        !           186: 
        !           187: 
        !           188: /*
        !           189:  * hourly_stats - print some interesting stats
        !           190:  */
        !           191: void
        !           192: write_stats(void)
        !           193: {
        !           194:        FILE    *fp;
        !           195:        double  ftemp;
        !           196: #ifdef DOSYNCTODR
        !           197:        struct timeval tv;
        !           198: #if !defined(VMS)
        !           199:        int     prio_set;
        !           200: #endif
        !           201: #ifdef HAVE_GETCLOCK
        !           202:         struct timespec ts;
        !           203: #endif
        !           204:        int     o_prio;
        !           205: 
        !           206:        /*
        !           207:         * Sometimes having a Sun can be a drag.
        !           208:         *
        !           209:         * The kernel variable dosynctodr controls whether the system's
        !           210:         * soft clock is kept in sync with the battery clock. If it
        !           211:         * is zero, then the soft clock is not synced, and the battery
        !           212:         * clock is simply left to rot. That means that when the system
        !           213:         * reboots, the battery clock (which has probably gone wacky)
        !           214:         * sets the soft clock. That means ntpd starts off with a very
        !           215:         * confused idea of what time it is. It then takes a large
        !           216:         * amount of time to figure out just how wacky the battery clock
        !           217:         * has made things drift, etc, etc. The solution is to make the
        !           218:         * battery clock sync up to system time. The way to do THAT is
        !           219:         * to simply set the time of day to the current time of day, but
        !           220:         * as quickly as possible. This may, or may not be a sensible
        !           221:         * thing to do.
        !           222:         *
        !           223:         * CAVEAT: settimeofday() steps the sun clock by about 800 us,
        !           224:         *         so setting DOSYNCTODR seems a bad idea in the
        !           225:         *         case of us resolution
        !           226:         */
        !           227: 
        !           228: #if !defined(VMS)
        !           229:        /*
        !           230:         * (prr) getpriority returns -1 on error, but -1 is also a valid
        !           231:         * return value (!), so instead we have to zero errno before the
        !           232:         * call and check it for non-zero afterwards.
        !           233:         */
        !           234:        errno = 0;
        !           235:        prio_set = 0;
        !           236:        o_prio = getpriority(PRIO_PROCESS,0); /* Save setting */
        !           237: 
        !           238:        /*
        !           239:         * (prr) if getpriority succeeded, call setpriority to raise
        !           240:         * scheduling priority as high as possible.  If that succeeds
        !           241:         * as well, set the prio_set flag so we remember to reset
        !           242:         * priority to its previous value below.  Note that on Solaris
        !           243:         * 2.6 (and beyond?), both getpriority and setpriority will fail
        !           244:         * with ESRCH, because sched_setscheduler (called from main) put
        !           245:         * us in the real-time scheduling class which setpriority
        !           246:         * doesn't know about. Being in the real-time class is better
        !           247:         * than anything setpriority can do, anyhow, so this error is
        !           248:         * silently ignored.
        !           249:         */
        !           250:        if ((errno == 0) && (setpriority(PRIO_PROCESS,0,-20) == 0))
        !           251:                prio_set = 1;   /* overdrive */
        !           252: #endif /* VMS */
        !           253: #ifdef HAVE_GETCLOCK
        !           254:         (void) getclock(TIMEOFDAY, &ts);
        !           255:         tv.tv_sec = ts.tv_sec;
        !           256:         tv.tv_usec = ts.tv_nsec / 1000;
        !           257: #else /*  not HAVE_GETCLOCK */
        !           258:        GETTIMEOFDAY(&tv,(struct timezone *)NULL);
        !           259: #endif /* not HAVE_GETCLOCK */
        !           260:        if (ntp_set_tod(&tv,(struct timezone *)NULL) != 0)
        !           261:                msyslog(LOG_ERR, "can't sync battery time: %m");
        !           262: #if !defined(VMS)
        !           263:        if (prio_set)
        !           264:                setpriority(PRIO_PROCESS, 0, o_prio); /* downshift */
        !           265: #endif /* VMS */
        !           266: #endif /* DOSYNCTODR */
        !           267:        record_sys_stats();
        !           268:        ftemp = fabs(prev_drift_comp - drift_comp); 
        !           269:        prev_drift_comp = drift_comp;
        !           270:        if (ftemp > clock_phi)
        !           271:                return;
        !           272: 
        !           273:        if (stats_drift_file != 0 && drift_file_sw) {
        !           274: 
        !           275:                /*
        !           276:                 * When the frequency file is written, initialize the
        !           277:                 * wander threshold to a configured initial value.
        !           278:                 * Thereafter reduce it by a factor of 0.5. When it
        !           279:                 * drops below the frequency wander, write the frequency
        !           280:                 * file. This adapts to the prevailing wander yet
        !           281:                 * minimizes the file writes.
        !           282:                 */
        !           283:                drift_file_sw = FALSE;
        !           284:                wander_resid *= 0.5;
        !           285: #ifdef DEBUG
        !           286:                if (debug)
        !           287:                        printf("write_stats: wander %.6lf thresh %.6lf, freq %.6lf\n",
        !           288:                            clock_stability * 1e6, wander_resid * 1e6,
        !           289:                            drift_comp * 1e6);
        !           290: #endif
        !           291:                if (sys_leap != LEAP_NOTINSYNC && clock_stability >
        !           292:                    wander_resid) {
        !           293:                        wander_resid = wander_threshold;
        !           294:                        if ((fp = fopen(stats_temp_file, "w")) == NULL)
        !           295:                            {
        !           296:                                msyslog(LOG_ERR,
        !           297:                                    "frequency file %s: %m",
        !           298:                                    stats_temp_file);
        !           299:                                return;
        !           300:                        }
        !           301:                        fprintf(fp, "%.3f\n", drift_comp * 1e6);
        !           302:                        (void)fclose(fp);
        !           303:                        /* atomic */
        !           304: #ifdef SYS_WINNT
        !           305:                        if (_unlink(stats_drift_file)) /* rename semantics differ under NT */
        !           306:                                msyslog(LOG_WARNING, 
        !           307:                                        "Unable to remove prior drift file %s, %m", 
        !           308:                                        stats_drift_file);
        !           309: #endif /* SYS_WINNT */
        !           310: 
        !           311: #ifndef NO_RENAME
        !           312:                        if (rename(stats_temp_file, stats_drift_file))
        !           313:                                msyslog(LOG_WARNING, 
        !           314:                                        "Unable to rename temp drift file %s to %s, %m", 
        !           315:                                        stats_temp_file, stats_drift_file);
        !           316: #else
        !           317:                        /* we have no rename NFS of ftp in use */
        !           318:                        if ((fp = fopen(stats_drift_file, "w")) ==
        !           319:                            NULL) {
        !           320:                                msyslog(LOG_ERR,
        !           321:                                    "frequency file %s: %m",
        !           322:                                    stats_drift_file);
        !           323:                                return;
        !           324:                        }
        !           325: #endif
        !           326: 
        !           327: #if defined(VMS)
        !           328:                        /* PURGE */
        !           329:                        {
        !           330:                                $DESCRIPTOR(oldvers,";-1");
        !           331:                                struct dsc$descriptor driftdsc = {
        !           332:                                        strlen(stats_drift_file), 0, 0,
        !           333:                                            stats_drift_file };
        !           334:                                while(lib$delete_file(&oldvers,
        !           335:                                    &driftdsc) & 1);
        !           336:                        }
        !           337: #endif
        !           338:                } else {
        !           339:                        /* XXX: Log a message at INFO level */
        !           340:                }
        !           341:        }
        !           342: }
        !           343: 
        !           344: 
        !           345: /*
        !           346:  * stats_config - configure the stats operation
        !           347:  */
        !           348: void
        !           349: stats_config(
        !           350:        int item,
        !           351:        const char *invalue     /* only one type so far */
        !           352:        )
        !           353: {
        !           354:        FILE    *fp;
        !           355:        const char *value;
        !           356:        int     len;
        !           357:        char    tbuf[80];
        !           358:        char    str1[20], str2[20];
        !           359: #ifndef VMS
        !           360:        const char temp_ext[] = ".TEMP";
        !           361: #else
        !           362:        const char temp_ext[] = "-TEMP";
        !           363: #endif
        !           364: 
        !           365:        /*
        !           366:         * Expand environment strings under Windows NT, since the
        !           367:         * command interpreter doesn't do this, the program must.
        !           368:         */
        !           369: #ifdef SYS_WINNT
        !           370:        char newvalue[MAX_PATH], parameter[MAX_PATH];
        !           371: 
        !           372:        if (!ExpandEnvironmentStrings(invalue, newvalue, MAX_PATH)) {
        !           373:                switch(item) {
        !           374:                    case STATS_FREQ_FILE:
        !           375:                        strcpy(parameter,"STATS_FREQ_FILE");
        !           376:                        break;
        !           377: 
        !           378:                    case STATS_LEAP_FILE:
        !           379:                        strcpy(parameter,"STATS_LEAP_FILE");
        !           380:                        break;
        !           381: 
        !           382:                    case STATS_STATSDIR:
        !           383:                        strcpy(parameter,"STATS_STATSDIR");
        !           384:                        break;
        !           385: 
        !           386:                    case STATS_PID_FILE:
        !           387:                        strcpy(parameter,"STATS_PID_FILE");
        !           388:                        break;
        !           389: 
        !           390:                    default:
        !           391:                        strcpy(parameter,"UNKNOWN");
        !           392:                        break;
        !           393:                }
        !           394:                value = invalue;
        !           395:                msyslog(LOG_ERR,
        !           396:                    "ExpandEnvironmentStrings(%s) failed: %m\n",
        !           397:                    parameter);
        !           398:        } else {
        !           399:                value = newvalue;
        !           400:        }
        !           401: #else    
        !           402:        value = invalue;
        !           403: #endif /* SYS_WINNT */
        !           404: 
        !           405:        switch(item) {
        !           406: 
        !           407:        /*
        !           408:         * Open and read frequency file.
        !           409:         */
        !           410:        case STATS_FREQ_FILE:
        !           411:                if (!value || (len = strlen(value)) == 0)
        !           412:                        break;
        !           413: 
        !           414:                stats_drift_file = erealloc(stats_drift_file, len + 1);
        !           415:                stats_temp_file = erealloc(stats_temp_file, 
        !           416:                                           len + sizeof(".TEMP"));
        !           417: 
        !           418:                memcpy(stats_drift_file, value, (unsigned)(len+1));
        !           419:                memcpy(stats_temp_file, value, (unsigned)len);
        !           420:                memcpy(stats_temp_file + len, temp_ext,
        !           421:                       sizeof(temp_ext));
        !           422: 
        !           423:                /*
        !           424:                 * Open drift file and read frequency. If the file is
        !           425:                 * missing or contains errors, tell the loop to reset.
        !           426:                 */
        !           427:                if ((fp = fopen(stats_drift_file, "r")) == NULL)
        !           428:                        break;
        !           429: 
        !           430:                if (fscanf(fp, "%lf", &old_drift) != 1) {
        !           431:                        msyslog(LOG_ERR,
        !           432:                                "format error frequency file %s", 
        !           433:                                stats_drift_file);
        !           434:                        fclose(fp);
        !           435:                        break;
        !           436: 
        !           437:                }
        !           438:                fclose(fp);
        !           439:                old_drift /= 1e6;
        !           440:                prev_drift_comp = old_drift;
        !           441:                break;
        !           442: 
        !           443:        /*
        !           444:         * Specify statistics directory.
        !           445:         */
        !           446:        case STATS_STATSDIR:
        !           447: 
        !           448:                /*
        !           449:                 * HMS: the following test is insufficient:
        !           450:                 * - value may be missing the DIR_SEP
        !           451:                 * - we still need the filename after it
        !           452:                 */
        !           453:                if (strlen(value) >= sizeof(statsdir)) {
        !           454:                        msyslog(LOG_ERR,
        !           455:                            "statsdir too long (>%d, sigh)",
        !           456:                            (int)sizeof(statsdir) - 1);
        !           457:                } else {
        !           458:                        l_fp now;
        !           459:                        int add_dir_sep;
        !           460:                        int value_l = strlen(value);
        !           461: 
        !           462:                        /* Add a DIR_SEP unless we already have one. */
        !           463:                        if (value_l == 0)
        !           464:                                add_dir_sep = 0;
        !           465:                        else
        !           466:                                add_dir_sep = (DIR_SEP !=
        !           467:                                    value[value_l - 1]);
        !           468: 
        !           469:                        if (add_dir_sep)
        !           470:                            snprintf(statsdir, sizeof(statsdir),
        !           471:                                "%s%c", value, DIR_SEP);
        !           472:                        else
        !           473:                            snprintf(statsdir, sizeof(statsdir),
        !           474:                                "%s", value);
        !           475: 
        !           476:                        get_systime(&now);
        !           477:                        if(peerstats.prefix == &statsdir[0] &&
        !           478:                            peerstats.fp != NULL) {
        !           479:                                fclose(peerstats.fp);
        !           480:                                peerstats.fp = NULL;
        !           481:                                filegen_setup(&peerstats, now.l_ui);
        !           482:                        }
        !           483:                        if(loopstats.prefix == &statsdir[0] &&
        !           484:                            loopstats.fp != NULL) {
        !           485:                                fclose(loopstats.fp);
        !           486:                                loopstats.fp = NULL;
        !           487:                                filegen_setup(&loopstats, now.l_ui);
        !           488:                        }
        !           489:                        if(clockstats.prefix == &statsdir[0] &&
        !           490:                            clockstats.fp != NULL) {
        !           491:                                fclose(clockstats.fp);
        !           492:                                clockstats.fp = NULL;
        !           493:                                filegen_setup(&clockstats, now.l_ui);
        !           494:                        }
        !           495:                        if(rawstats.prefix == &statsdir[0] &&
        !           496:                            rawstats.fp != NULL) {
        !           497:                                fclose(rawstats.fp);
        !           498:                                rawstats.fp = NULL;
        !           499:                                filegen_setup(&rawstats, now.l_ui);
        !           500:                        }
        !           501:                        if(sysstats.prefix == &statsdir[0] &&
        !           502:                            sysstats.fp != NULL) {
        !           503:                                fclose(sysstats.fp);
        !           504:                                sysstats.fp = NULL;
        !           505:                                filegen_setup(&sysstats, now.l_ui);
        !           506:                        }
        !           507:                        if(protostats.prefix == &statsdir[0] &&
        !           508:                            protostats.fp != NULL) {
        !           509:                                fclose(protostats.fp);
        !           510:                                protostats.fp = NULL;
        !           511:                                filegen_setup(&protostats, now.l_ui);
        !           512:                        }
        !           513: #ifdef OPENSSL
        !           514:                        if(cryptostats.prefix == &statsdir[0] &&
        !           515:                            cryptostats.fp != NULL) {
        !           516:                                fclose(cryptostats.fp);
        !           517:                                cryptostats.fp = NULL;
        !           518:                                filegen_setup(&cryptostats, now.l_ui);
        !           519:                        }
        !           520: #endif /* OPENSSL */
        !           521: #ifdef DEBUG_TIMING
        !           522:                        if(timingstats.prefix == &statsdir[0] &&
        !           523:                            timingstats.fp != NULL) {
        !           524:                                fclose(timingstats.fp);
        !           525:                                timingstats.fp = NULL;
        !           526:                                filegen_setup(&timingstats, now.l_ui);
        !           527:                        }
        !           528: #endif /* DEBUG_TIMING */
        !           529:                }
        !           530:                break;
        !           531: 
        !           532:        /*
        !           533:         * Open pid file.
        !           534:         */
        !           535:        case STATS_PID_FILE:
        !           536:                if ((fp = fopen(value, "w")) == NULL) {
        !           537:                        msyslog(LOG_ERR, "pid file %s: %m",
        !           538:                            value);
        !           539:                        break;
        !           540:                }
        !           541:                fprintf(fp, "%d", (int)getpid());
        !           542:                fclose(fp);;
        !           543:                break;
        !           544: 
        !           545:        /*
        !           546:         * Read leapseconds file.
        !           547:         */
        !           548:        case STATS_LEAP_FILE:
        !           549:                if ((fp = fopen(value, "r")) == NULL) {
        !           550:                        msyslog(LOG_ERR, "leapseconds file %s: %m",
        !           551:                            value);
        !           552:                        break;
        !           553:                }
        !           554: 
        !           555:                if (leap_file(fp) < 0) {
        !           556:                        msyslog(LOG_ERR,
        !           557:                            "format error leapseconds file %s",
        !           558:                            value);
        !           559:                } else {
        !           560:                        strcpy(str1, fstostr(leap_sec));
        !           561:                        strcpy(str2, fstostr(leap_expire));
        !           562:                        snprintf(tbuf, sizeof(tbuf),
        !           563:                            "%d leap %s expire %s", leap_tai, str1,
        !           564:                            str2);
        !           565:                        report_event(EVNT_TAI, NULL, tbuf);
        !           566:                }
        !           567:                fclose(fp);
        !           568:                break;
        !           569: 
        !           570:        default:
        !           571:                /* oh well */
        !           572:                break;
        !           573:        }
        !           574: }
        !           575: 
        !           576: 
        !           577: /*
        !           578:  * record_peer_stats - write peer statistics to file
        !           579:  *
        !           580:  * file format:
        !           581:  * day (MJD)
        !           582:  * time (s past UTC midnight)
        !           583:  * IP address
        !           584:  * status word (hex)
        !           585:  * offset
        !           586:  * delay
        !           587:  * dispersion
        !           588:  * jitter
        !           589: */
        !           590: void
        !           591: record_peer_stats(
        !           592:        sockaddr_u *addr,
        !           593:        int     status,
        !           594:        double  offset,         /* offset */
        !           595:        double  delay,          /* delay */
        !           596:        double  dispersion,     /* dispersion */
        !           597:        double  jitter          /* jitter */
        !           598:        )
        !           599: {
        !           600:        l_fp    now;
        !           601:        u_long  day;
        !           602: 
        !           603:        if (!stats_control)
        !           604:                return;
        !           605: 
        !           606:        get_systime(&now);
        !           607:        filegen_setup(&peerstats, now.l_ui);
        !           608:        day = now.l_ui / 86400 + MJD_1900;
        !           609:        now.l_ui %= 86400;
        !           610:        if (peerstats.fp != NULL) {
        !           611:                fprintf(peerstats.fp,
        !           612:                    "%lu %s %s %x %.9f %.9f %.9f %.9f\n", day,
        !           613:                    ulfptoa(&now, 3), stoa(addr), status, offset,
        !           614:                    delay, dispersion, jitter);
        !           615:                fflush(peerstats.fp);
        !           616:        }
        !           617: }
        !           618: 
        !           619: 
        !           620: /*
        !           621:  * record_loop_stats - write loop filter statistics to file
        !           622:  *
        !           623:  * file format:
        !           624:  * day (MJD)
        !           625:  * time (s past midnight)
        !           626:  * offset
        !           627:  * frequency (PPM)
        !           628:  * jitter
        !           629:  * wnder (PPM)
        !           630:  * time constant (log2)
        !           631:  */
        !           632: void
        !           633: record_loop_stats(
        !           634:        double  offset,         /* offset */
        !           635:        double  freq,           /* frequency (PPM) */
        !           636:        double  jitter,         /* jitter */
        !           637:        double  wander,         /* wander (PPM) */
        !           638:        int spoll
        !           639:        )
        !           640: {
        !           641:        l_fp    now;
        !           642:        u_long  day;
        !           643: 
        !           644:        if (!stats_control)
        !           645:                return;
        !           646: 
        !           647:        get_systime(&now);
        !           648:        filegen_setup(&loopstats, now.l_ui);
        !           649:        day = now.l_ui / 86400 + MJD_1900;
        !           650:        now.l_ui %= 86400;
        !           651:        if (loopstats.fp != NULL) {
        !           652:                fprintf(loopstats.fp, "%lu %s %.9f %.3f %.9f %.6f %d\n",
        !           653:                    day, ulfptoa(&now, 3), offset, freq * 1e6, jitter,
        !           654:                    wander * 1e6, spoll);
        !           655:                fflush(loopstats.fp);
        !           656:        }
        !           657: }
        !           658: 
        !           659: 
        !           660: /*
        !           661:  * record_clock_stats - write clock statistics to file
        !           662:  *
        !           663:  * file format:
        !           664:  * day (MJD)
        !           665:  * time (s past midnight)
        !           666:  * IP address
        !           667:  * text message
        !           668:  */
        !           669: void
        !           670: record_clock_stats(
        !           671:        sockaddr_u *addr,
        !           672:        const char *text        /* timecode string */
        !           673:        )
        !           674: {
        !           675:        l_fp    now;
        !           676:        u_long  day;
        !           677: 
        !           678:        if (!stats_control)
        !           679:                return;
        !           680: 
        !           681:        get_systime(&now);
        !           682:        filegen_setup(&clockstats, now.l_ui);
        !           683:        day = now.l_ui / 86400 + MJD_1900;
        !           684:        now.l_ui %= 86400;
        !           685:        if (clockstats.fp != NULL) {
        !           686:                fprintf(clockstats.fp, "%lu %s %s %s\n", day,
        !           687:                    ulfptoa(&now, 3), stoa(addr), text);
        !           688:                fflush(clockstats.fp);
        !           689:        }
        !           690: }
        !           691: 
        !           692: 
        !           693: /*
        !           694:  * record_raw_stats - write raw timestamps to file
        !           695:  *
        !           696:  * file format
        !           697:  * day (MJD)
        !           698:  * time (s past midnight)
        !           699:  * peer ip address
        !           700:  * IP address
        !           701:  * t1 t2 t3 t4 timestamps
        !           702:  */
        !           703: void
        !           704: record_raw_stats(
        !           705:        sockaddr_u *srcadr,
        !           706:        sockaddr_u *dstadr,
        !           707:        l_fp    *t1,            /* originate timestamp */
        !           708:        l_fp    *t2,            /* receive timestamp */
        !           709:        l_fp    *t3,            /* transmit timestamp */
        !           710:        l_fp    *t4             /* destination timestamp */
        !           711:        )
        !           712: {
        !           713:        l_fp    now;
        !           714:        u_long  day;
        !           715: 
        !           716:        if (!stats_control)
        !           717:                return;
        !           718: 
        !           719:        get_systime(&now);
        !           720:        filegen_setup(&rawstats, now.l_ui);
        !           721:        day = now.l_ui / 86400 + MJD_1900;
        !           722:        now.l_ui %= 86400;
        !           723:        if (rawstats.fp != NULL) {
        !           724:                fprintf(rawstats.fp, "%lu %s %s %s %s %s %s %s\n", day,
        !           725:                    ulfptoa(&now, 3), stoa(srcadr), dstadr ? 
        !           726:                    stoa(dstadr) : "-", ulfptoa(t1, 9), ulfptoa(t2, 9),
        !           727:                    ulfptoa(t3, 9), ulfptoa(t4, 9));
        !           728:                fflush(rawstats.fp);
        !           729:        }
        !           730: }
        !           731: 
        !           732: 
        !           733: /*
        !           734:  * record_sys_stats - write system statistics to file
        !           735:  *
        !           736:  * file format
        !           737:  * day (MJD)
        !           738:  * time (s past midnight)
        !           739:  * time since reset
        !           740:  * packets recieved
        !           741:  * packets for this host
        !           742:  * current version
        !           743:  * old version
        !           744:  * access denied
        !           745:  * bad length or format
        !           746:  * bad authentication
        !           747:  * declined
        !           748:  * rate exceeded
        !           749:  * KoD sent
        !           750:  */
        !           751: void
        !           752: record_sys_stats(void)
        !           753: {
        !           754:        l_fp    now;
        !           755:        u_long  day;
        !           756: 
        !           757:        if (!stats_control)
        !           758:                return;
        !           759: 
        !           760:        get_systime(&now);
        !           761:        filegen_setup(&sysstats, now.l_ui);
        !           762:        day = now.l_ui / 86400 + MJD_1900;
        !           763:        now.l_ui %= 86400;
        !           764:        if (sysstats.fp != NULL) {
        !           765:                fprintf(sysstats.fp,
        !           766:                    "%lu %s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
        !           767:                    day, ulfptoa(&now, 3), current_time - sys_stattime,
        !           768:                    sys_received, sys_processed, sys_newversion,
        !           769:                    sys_oldversion, sys_restricted, sys_badlength,
        !           770:                    sys_badauth, sys_declined, sys_limitrejected,
        !           771:                    sys_kodsent);
        !           772:                fflush(sysstats.fp);
        !           773:                proto_clr_stats();
        !           774:        }
        !           775: }
        !           776: 
        !           777: 
        !           778: /*
        !           779:  * record_proto_stats - write system statistics to file
        !           780:  *
        !           781:  * file format
        !           782:  * day (MJD)
        !           783:  * time (s past midnight)
        !           784:  * text message
        !           785:  */
        !           786: void
        !           787: record_proto_stats(
        !           788:        char    *str            /* text string */
        !           789:        )
        !           790: {
        !           791:        l_fp    now;
        !           792:        u_long  day;
        !           793: 
        !           794:        if (!stats_control)
        !           795:                return;
        !           796: 
        !           797:        get_systime(&now);
        !           798:        filegen_setup(&protostats, now.l_ui);
        !           799:        day = now.l_ui / 86400 + MJD_1900;
        !           800:        now.l_ui %= 86400;
        !           801:        if (protostats.fp != NULL) {
        !           802:                fprintf(protostats.fp, "%lu %s %s\n", day,
        !           803:                    ulfptoa(&now, 3), str);
        !           804:                fflush(protostats.fp);
        !           805:        }
        !           806: }
        !           807: 
        !           808: 
        !           809: #ifdef OPENSSL
        !           810: /*
        !           811:  * record_crypto_stats - write crypto statistics to file
        !           812:  *
        !           813:  * file format:
        !           814:  * day (mjd)
        !           815:  * time (s past midnight)
        !           816:  * peer ip address
        !           817:  * text message
        !           818:  */
        !           819: void
        !           820: record_crypto_stats(
        !           821:        sockaddr_u *addr,
        !           822:        const char *text        /* text message */
        !           823:        )
        !           824: {
        !           825:        l_fp    now;
        !           826:        u_long  day;
        !           827: 
        !           828:        if (!stats_control)
        !           829:                return;
        !           830: 
        !           831:        get_systime(&now);
        !           832:        filegen_setup(&cryptostats, now.l_ui);
        !           833:        day = now.l_ui / 86400 + MJD_1900;
        !           834:        now.l_ui %= 86400;
        !           835:        if (cryptostats.fp != NULL) {
        !           836:                if (addr == NULL)
        !           837:                        fprintf(cryptostats.fp, "%lu %s 0.0.0.0 %s\n",
        !           838:                            day, ulfptoa(&now, 3), text);
        !           839:                else
        !           840:                        fprintf(cryptostats.fp, "%lu %s %s %s\n",
        !           841:                            day, ulfptoa(&now, 3), stoa(addr), text);
        !           842:                fflush(cryptostats.fp);
        !           843:        }
        !           844: }
        !           845: #endif /* OPENSSL */
        !           846: 
        !           847: 
        !           848: #ifdef DEBUG_TIMING
        !           849: /*
        !           850:  * record_timing_stats - write timing statistics to file
        !           851:  *
        !           852:  * file format:
        !           853:  * day (mjd)
        !           854:  * time (s past midnight)
        !           855:  * text message
        !           856:  */
        !           857: void
        !           858: record_timing_stats(
        !           859:        const char *text        /* text message */
        !           860:        )
        !           861: {
        !           862:        static unsigned int flshcnt;
        !           863:        l_fp    now;
        !           864:        u_long  day;
        !           865: 
        !           866:        if (!stats_control)
        !           867:                return;
        !           868: 
        !           869:        get_systime(&now);
        !           870:        filegen_setup(&timingstats, now.l_ui);
        !           871:        day = now.l_ui / 86400 + MJD_1900;
        !           872:        now.l_ui %= 86400;
        !           873:        if (timingstats.fp != NULL) {
        !           874:                fprintf(timingstats.fp, "%lu %s %s\n", day, lfptoa(&now,
        !           875:                    3), text);
        !           876:                if (++flshcnt % 100 == 0)
        !           877:                        fflush(timingstats.fp);
        !           878:        }
        !           879: }
        !           880: #endif
        !           881: 
        !           882: 
        !           883: /*
        !           884:  * leap_file - read leapseconds file
        !           885:  *
        !           886:  * Read the ERTS leapsecond file in NIST text format and extract the
        !           887:  * NTP seconds of the latest leap and TAI offset after the leap.
        !           888:  */
        !           889: static int
        !           890: leap_file(
        !           891:        FILE    *fp             /* file handle */
        !           892:        )
        !           893: {
        !           894:        char    buf[NTP_MAXSTRLEN]; /* file line buffer */
        !           895:        u_long  leap;           /* NTP time at leap */
        !           896:        u_long  expire;         /* NTP time when file expires */
        !           897:        int     offset;         /* TAI offset at leap (s) */
        !           898:        int     i;
        !           899: 
        !           900:        /*
        !           901:         * Read and parse the leapseconds file. Empty lines and comments
        !           902:         * are ignored. A line beginning with #@ contains the file
        !           903:         * expiration time in NTP seconds. Other lines begin with two
        !           904:         * integers followed by junk or comments. The first integer is
        !           905:         * the NTP seconds at the leap, the second is the TAI offset
        !           906:         * after the leap.
        !           907:         */
        !           908:        offset = 0;
        !           909:        leap = 0;
        !           910:        expire = 0;
        !           911:        i = 10;
        !           912:        while (fgets(buf, NTP_MAXSTRLEN - 1, fp) != NULL) {
        !           913:                if (strlen(buf) < 1)
        !           914:                        continue;
        !           915: 
        !           916:                if (buf[0] == '#') {
        !           917:                        if (strlen(buf) < 3)
        !           918:                                continue;
        !           919: 
        !           920:                        /*
        !           921:                         * Note the '@' flag was used only in the 2006
        !           922:                         * table; previious to that the flag was '$'.
        !           923:                         */
        !           924:                        if (buf[1] == '@' || buf[1] == '$') {
        !           925:                                if (sscanf(&buf[2], "%lu", &expire) !=
        !           926:                                    1)
        !           927:                                        return (-1);
        !           928: 
        !           929:                                continue;
        !           930:                        }
        !           931:                }
        !           932:                if (sscanf(buf, "%lu %d", &leap, &offset) == 2) {
        !           933: 
        !           934:                        /*
        !           935:                         * Valid offsets must increase by one for each
        !           936:                         * leap.
        !           937:                         */
        !           938:                        if (i++ != offset)
        !           939:                                return (-1);
        !           940:                }
        !           941:        }
        !           942: 
        !           943:        /*
        !           944:         * There must be at least one leap.
        !           945:         */
        !           946:        if (i == 10)
        !           947:                return (-1);
        !           948: 
        !           949:        leap_tai = offset;
        !           950:        leap_sec = leap;
        !           951:        leap_expire = expire;
        !           952:        return (0);
        !           953: }
        !           954: 
        !           955: 
        !           956: /*
        !           957:  * leap_month - returns seconds until the end of the month.
        !           958:  */
        !           959: u_long
        !           960: leap_month(
        !           961:        u_long  sec             /* current NTP second */
        !           962:        )
        !           963: {
        !           964:        u_long  ltemp;
        !           965:        u_long  *ptr;
        !           966:        u_long  year[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30,
        !           967:                    31}; 
        !           968:        u_long  lyear[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30,
        !           969:                    31}; 
        !           970: 
        !           971:        /*
        !           972:         * Find current leap cycle.
        !           973:         */
        !           974:        ltemp = sec;
        !           975:        while (ltemp >= L_CENT)
        !           976:                ltemp -= L_CENT;
        !           977:        while (ltemp >= L_4YEAR)
        !           978:                ltemp -= L_4YEAR;
        !           979: 
        !           980:        /*
        !           981:         * We are within four years of the target. If in leap year, use
        !           982:         * leap year month table; otherwise, use year month table.
        !           983:         */
        !           984:        if (ltemp < L_LYEAR) {
        !           985:                ptr = lyear;
        !           986:        } else {
        !           987:                ptr = year;
        !           988:                ltemp -= L_LYEAR;
        !           989:                while (ltemp >= L_YEAR)
        !           990:                        ltemp -= L_YEAR;
        !           991:        }
        !           992: 
        !           993:        /*
        !           994:         * We are within one year of the target. Find the month of the
        !           995:         * leap.
        !           996:         */
        !           997:        while (ltemp >= *ptr * L_DAY)
        !           998:                ltemp -= *ptr++ * L_DAY;
        !           999: 
        !          1000:        /*
        !          1001:         * The result is the number of seconds until the end of the
        !          1002:         * month when the leap is to occur.
        !          1003:         */
        !          1004:        return (*ptr * L_DAY - ltemp - L_DAY);
        !          1005: }
        !          1006: 
        !          1007: 
        !          1008: /*
        !          1009:  * getauthkeys - read the authentication keys from the specified file
        !          1010:  */
        !          1011: void
        !          1012: getauthkeys(
        !          1013:        const char *keyfile
        !          1014:        )
        !          1015: {
        !          1016:        int len;
        !          1017: 
        !          1018:        len = strlen(keyfile);
        !          1019:        if (!len)
        !          1020:                return;
        !          1021:        
        !          1022: #ifndef SYS_WINNT
        !          1023:        key_file_name = erealloc(key_file_name, len + 1);
        !          1024:        memmove(key_file_name, keyfile, len + 1);
        !          1025: #else
        !          1026:        key_file_name = erealloc(key_file_name, _MAX_PATH);
        !          1027:        if (len + 1 > _MAX_PATH)
        !          1028:                return;
        !          1029:        if (!ExpandEnvironmentStrings(keyfile, key_file_name,
        !          1030:                                      _MAX_PATH)) {
        !          1031:                msyslog(LOG_ERR,
        !          1032:                        "ExpandEnvironmentStrings(KEY_FILE) failed: %m");
        !          1033:                strncpy(key_file_name, keyfile, _MAX_PATH);
        !          1034:        }
        !          1035: #endif /* SYS_WINNT */
        !          1036: 
        !          1037:        authreadkeys(key_file_name);
        !          1038: }
        !          1039: 
        !          1040: 
        !          1041: /*
        !          1042:  * rereadkeys - read the authentication key file over again.
        !          1043:  */
        !          1044: void
        !          1045: rereadkeys(void)
        !          1046: {
        !          1047:        if (NULL != key_file_name)
        !          1048:                authreadkeys(key_file_name);
        !          1049: }
        !          1050: 
        !          1051: 
        !          1052: /*
        !          1053:  * sock_hash - hash a sockaddr_u structure
        !          1054:  */
        !          1055: u_short
        !          1056: sock_hash(
        !          1057:        sockaddr_u *addr
        !          1058:        )
        !          1059: {
        !          1060:        u_int hashVal;
        !          1061:        u_int j;
        !          1062:        size_t len;
        !          1063:        u_char *pch;
        !          1064:        hashVal = 0;
        !          1065:        len = 0;
        !          1066: 
        !          1067:        /*
        !          1068:         * We can't just hash the whole thing because there are hidden
        !          1069:         * fields in sockaddr_in6 that might be filled in by recvfrom(),
        !          1070:         * so just use the family, port and address.
        !          1071:         */
        !          1072:        pch = (u_char *)&AF(addr);
        !          1073:        hashVal = 37 * hashVal + *pch;
        !          1074:        if (sizeof(AF(addr)) > 1) {
        !          1075:                pch++;
        !          1076:                hashVal = 37 * hashVal + *pch;
        !          1077:        }
        !          1078:        switch(AF(addr)) {
        !          1079:        case AF_INET:
        !          1080:                pch = (u_char *)&SOCK_ADDR4(addr);
        !          1081:                len = sizeof(SOCK_ADDR4(addr));
        !          1082:                break;
        !          1083: 
        !          1084:        case AF_INET6:
        !          1085:                pch = (u_char *)&SOCK_ADDR6(addr);
        !          1086:                len = sizeof(SOCK_ADDR6(addr));
        !          1087:                break;
        !          1088:        }
        !          1089: 
        !          1090:        for (j = 0; j < len ; j++)
        !          1091:                hashVal = 37 * hashVal + pch[j];
        !          1092: 
        !          1093:        hashVal = hashVal & NTP_HASH_MASK;
        !          1094: 
        !          1095:        return (u_short)hashVal;
        !          1096: }
        !          1097: 
        !          1098: 
        !          1099: #if notyet
        !          1100: /*
        !          1101:  * ntp_exit - document explicitly that ntpd has exited
        !          1102:  */
        !          1103: void
        !          1104: ntp_exit(int retval)
        !          1105: {
        !          1106:        msyslog(LOG_ERR, "EXITING with return code %d", retval);
        !          1107:        exit(retval);
        !          1108: }
        !          1109: #endif
        !          1110: 
        !          1111: /*
        !          1112:  * fstostr - prettyprint NTP seconds
        !          1113:  */
        !          1114: char * fstostr(
        !          1115:        time_t  ntp_stamp
        !          1116:        )
        !          1117: {
        !          1118:        static char     str[20];
        !          1119:        struct tm *     tm;
        !          1120:        time_t          unix_stamp;
        !          1121: 
        !          1122:        unix_stamp = ntp_stamp - JAN_1970;
        !          1123:        tm = gmtime(&unix_stamp);
        !          1124:        if (NULL != tm)
        !          1125:                snprintf(str, sizeof(str),
        !          1126:                         "%04d%02d%02d%02d%02d",
        !          1127:                         tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
        !          1128:                         tm->tm_hour, tm->tm_min);
        !          1129:        else
        !          1130:                strcpy(str, "gmtime() error");
        !          1131: 
        !          1132:        return str;
        !          1133: }

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