Annotation of embedaddon/ntp/ntpd/ntp_util.c, revision 1.1.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>