Annotation of embedaddon/ntp/ntpdc/ntpdc_ops.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * ntpdc_ops.c - subroutines which are called to perform operations by
                      3:  *              ntpdc
                      4:  */
                      5: 
                      6: #ifdef HAVE_CONFIG_H
                      7: # include <config.h>
                      8: #endif
                      9: 
                     10: #include <stdio.h>
                     11: #include <stddef.h>
                     12: 
                     13: #include "ntpdc.h"
                     14: #include "ntp_net.h"
                     15: #include "ntp_control.h"
                     16: #include "ntp_refclock.h"
                     17: #include "ntp_stdlib.h"
                     18: 
                     19: #include <ctype.h>
                     20: #ifdef HAVE_SYS_TIMEX_H
                     21: # include <sys/timex.h>
                     22: #endif
                     23: #if !defined(__bsdi__) && !defined(apollo)
                     24: #ifdef HAVE_NETINET_IN_H
                     25: #include <netinet/in.h>
                     26: #endif
                     27: #endif
                     28: 
                     29: #include <arpa/inet.h>
                     30: 
                     31: /*
                     32:  * utility functions
                     33:  */
                     34: static int     checkitems      (int, FILE *);
                     35: static int     checkitemsize   (int, int);
                     36: static int     check1item      (int, FILE *);
                     37: 
                     38: /*
                     39:  * Declarations for command handlers in here
                     40:  */
                     41: static void    peerlist        (struct parse *, FILE *);
                     42: static void    peers           (struct parse *, FILE *);
                     43: static void    doconfig        (struct parse *pcmd, FILE *fp, int mode, int refc);
                     44: static void    dmpeers         (struct parse *, FILE *);
                     45: static void    dopeers         (struct parse *, FILE *, int);
                     46: static void    printpeer       (struct info_peer *, FILE *);
                     47: static void    showpeer        (struct parse *, FILE *);
                     48: static void    peerstats       (struct parse *, FILE *);
                     49: static void    loopinfo        (struct parse *, FILE *);
                     50: static void    sysinfo         (struct parse *, FILE *);
                     51: static void    sysstats        (struct parse *, FILE *);
                     52: static void    iostats         (struct parse *, FILE *);
                     53: static void    memstats        (struct parse *, FILE *);
                     54: static void    timerstats      (struct parse *, FILE *);
                     55: static void    addpeer         (struct parse *, FILE *);
                     56: static void    addserver       (struct parse *, FILE *);
                     57: static void    addrefclock     (struct parse *, FILE *);
                     58: static void    broadcast       (struct parse *, FILE *);
                     59: static void    doconfig        (struct parse *, FILE *, int, int);
                     60: static void    unconfig        (struct parse *, FILE *);
                     61: static void    set             (struct parse *, FILE *);
                     62: static void    sys_clear       (struct parse *, FILE *);
                     63: static void    doset           (struct parse *, FILE *, int);
                     64: static void    reslist         (struct parse *, FILE *);
                     65: static void    new_restrict    (struct parse *, FILE *);
                     66: static void    unrestrict      (struct parse *, FILE *);
                     67: static void    delrestrict     (struct parse *, FILE *);
                     68: static void    do_restrict     (struct parse *, FILE *, int);
                     69: static void    monlist         (struct parse *, FILE *);
                     70: static void    reset           (struct parse *, FILE *);
                     71: static void    preset          (struct parse *, FILE *);
                     72: static void    readkeys        (struct parse *, FILE *);
                     73: static void    trustkey        (struct parse *, FILE *);
                     74: static void    untrustkey      (struct parse *, FILE *);
                     75: static void    do_trustkey     (struct parse *, FILE *, int);
                     76: static void    authinfo        (struct parse *, FILE *);
                     77: static void    traps           (struct parse *, FILE *);
                     78: static void    addtrap         (struct parse *, FILE *);
                     79: static void    clrtrap         (struct parse *, FILE *);
                     80: static void    do_addclr_trap  (struct parse *, FILE *, int);
                     81: static void    requestkey      (struct parse *, FILE *);
                     82: static void    controlkey      (struct parse *, FILE *);
                     83: static void    do_changekey    (struct parse *, FILE *, int);
                     84: static void    ctlstats        (struct parse *, FILE *);
                     85: static void    clockstat       (struct parse *, FILE *);
                     86: static void    fudge           (struct parse *, FILE *);
                     87: static void    clkbug          (struct parse *, FILE *);
                     88: static void    kerninfo        (struct parse *, FILE *);
                     89: static  void    get_if_stats    (struct parse *, FILE *);
                     90: static  void    do_if_reload    (struct parse *, FILE *);
                     91: 
                     92: /*
                     93:  * Commands we understand.  Ntpdc imports this.
                     94:  */
                     95: struct xcmd opcmds[] = {
                     96:        { "listpeers",  peerlist,       { OPT|IP_VERSION, NO, NO, NO },
                     97:          { "-4|-6", "", "", "" },
                     98:          "display list of peers the server knows about [IP Version]" },
                     99:        { "peers",      peers,  { OPT|IP_VERSION, NO, NO, NO },
                    100:          { "-4|-6", "", "", "" },
                    101:          "display peer summary information [IP Version]" },
                    102:        { "dmpeers",    dmpeers,        { OPT|IP_VERSION, NO, NO, NO },
                    103:          { "-4|-6", "", "", "" },
                    104:          "display peer summary info the way Dave Mills likes it (IP Version)" },
                    105:        { "showpeer",   showpeer,       { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD},
                    106:          { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
                    107:          "display detailed information for one or more peers" },
                    108:        { "pstats",     peerstats,      { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
                    109:          { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
                    110:          "display statistical information for one or more peers" },
                    111:        { "loopinfo",   loopinfo,       { OPT|NTP_STR, NO, NO, NO },
                    112:          { "oneline|multiline", "", "", "" },
                    113:          "display loop filter information" },
                    114:        { "sysinfo",    sysinfo,        { NO, NO, NO, NO },
                    115:          { "", "", "", "" },
                    116:          "display local server information" },
                    117:        { "sysstats",   sysstats,       { NO, NO, NO, NO },
                    118:          { "", "", "", "" },
                    119:          "display local server statistics" },
                    120:        { "memstats",   memstats,       { NO, NO, NO, NO },
                    121:          { "", "", "", "" },
                    122:          "display peer memory usage statistics" },
                    123:        { "iostats",    iostats,        { NO, NO, NO, NO },
                    124:          { "", "", "", "" },
                    125:          "display I/O subsystem statistics" },
                    126:        { "timerstats", timerstats,     { NO, NO, NO, NO },
                    127:          { "", "", "", "" },
                    128:          "display event timer subsystem statistics" },
                    129:        { "addpeer",    addpeer,        { NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
                    130:          { "addr", "keyid", "version", "minpoll#|prefer|burst|iburst|'minpoll N'|'maxpoll N'|'keyid N'|'version N' ..." },
                    131:          "configure a new peer association" },
                    132:        { "addserver",  addserver,      { NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
                    133:          { "addr", "keyid", "version", "minpoll#|prefer|burst|iburst|'minpoll N'|'maxpoll N'|'keyid N'|'version N' ..." },
                    134:          "configure a new server" },
                    135:        { "addrefclock",addrefclock,    { NTP_ADD, OPT|NTP_UINT, OPT|NTP_STR, OPT|NTP_STR },
                    136:          { "addr", "mode", "minpoll|prefer", "minpoll|prefer" },
                    137:          "configure a new server" },
                    138:        { "broadcast",  broadcast,      { NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
                    139:          { "addr", "keyid", "version", "minpoll" },
                    140:          "configure broadcasting time service" },
                    141:        { "unconfig",   unconfig,       { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
                    142:          { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
                    143:          "unconfigure existing peer assocations" },
                    144:        { "enable",     set,            { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
                    145:          { "auth|bclient|monitor|pll|kernel|stats", "...", "...", "..." },
                    146:          "set a system flag (auth, bclient, monitor, pll, kernel, stats)" },
                    147:         { "disable",   sys_clear,      { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
                    148:          { "auth|bclient|monitor|pll|kernel|stats", "...", "...", "..." },
                    149:          "clear a system flag (auth, bclient, monitor, pll, kernel, stats)" },
                    150:        { "reslist",    reslist,        {OPT|IP_VERSION, NO, NO, NO },
                    151:          { "-4|-6", "", "", "" },
                    152:          "display the server's restrict list" },
                    153:        { "restrict",   new_restrict,   { NTP_ADD, NTP_ADD, NTP_STR, OPT|NTP_STR },
                    154:          { "address", "mask",
                    155:            "ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer|version|kod",
                    156:            "..." },
                    157:          "create restrict entry/add flags to entry" },
                    158:        { "unrestrict", unrestrict,     { NTP_ADD, NTP_ADD, NTP_STR, OPT|NTP_STR },
                    159:          { "address", "mask",
                    160:            "ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer|version|kod",
                    161:            "..." },
                    162:          "remove flags from a restrict entry" },
                    163:        { "delrestrict", delrestrict,   { NTP_ADD, NTP_ADD, OPT|NTP_STR, NO },
                    164:          { "address", "mask", "ntpport", "" },
                    165:          "delete a restrict entry" },
                    166:        { "monlist",    monlist,        { OPT|NTP_INT, NO, NO, NO },
                    167:          { "version", "", "", "" },
                    168:          "display data the server's monitor routines have collected" },
                    169:        { "reset",      reset,          { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
                    170:          { "io|sys|mem|timer|auth|allpeers", "...", "...", "..." },
                    171:          "reset various subsystem statistics counters" },
                    172:        { "preset",     preset,         { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
                    173:          { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
                    174:          "reset stat counters associated with particular peer(s)" },
                    175:        { "readkeys",   readkeys,       { NO, NO, NO, NO },
                    176:          { "", "", "", "" },
                    177:          "request a reread of the keys file and re-init of system keys" },
                    178:        { "trustedkey", trustkey,       { NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT },
                    179:          { "keyid", "keyid", "keyid", "keyid" },
                    180:          "add one or more key ID's to the trusted list" },
                    181:        { "untrustedkey", untrustkey,   { NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT },
                    182:          { "keyid", "keyid", "keyid", "keyid" },
                    183:          "remove one or more key ID's from the trusted list" },
                    184:        { "authinfo",   authinfo,       { NO, NO, NO, NO },
                    185:          { "", "", "", "" },
                    186:          "display the state of the authentication code" },
                    187:        { "traps",      traps,          { NO, NO, NO, NO },
                    188:          { "", "", "", "" },
                    189:          "display the traps set in the server" },
                    190:        { "addtrap",    addtrap,        { NTP_ADD, OPT|NTP_UINT, OPT|NTP_ADD, NO },
                    191:          { "address", "port", "interface", "" },
                    192:          "configure a trap in the server" },
                    193:        { "clrtrap",    clrtrap,        { NTP_ADD, OPT|NTP_UINT, OPT|NTP_ADD, NO },
                    194:          { "address", "port", "interface", "" },
                    195:          "remove a trap (configured or otherwise) from the server" },
                    196:        { "requestkey", requestkey,     { NTP_UINT, NO, NO, NO },
                    197:          { "keyid", "", "", "" },
                    198:          "change the keyid the server uses to authenticate requests" },
                    199:        { "controlkey", controlkey,     { NTP_UINT, NO, NO, NO },
                    200:          { "keyid", "", "", "" },
                    201:          "change the keyid the server uses to authenticate control messages" },
                    202:        { "ctlstats",   ctlstats,       { NO, NO, NO, NO },
                    203:          { "", "", "", "" },
                    204:          "display packet count statistics from the control module" },
                    205:        { "clockstat",  clockstat,      { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
                    206:          { "address", "address", "address", "address" },
                    207:          "display clock status information" },
                    208:        { "fudge",      fudge,          { NTP_ADD, NTP_STR, NTP_STR, NO },
                    209:          { "address", "time1|time2|val1|val2|flags", "value", "" },
                    210:          "set/change one of a clock's fudge factors" },
                    211:        { "clkbug",     clkbug,         { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
                    212:          { "address", "address", "address", "address" },
                    213:          "display clock debugging information" },
                    214:        { "kerninfo",   kerninfo,       { NO, NO, NO, NO },
                    215:          { "", "", "", "" },
                    216:          "display the kernel pll/pps variables" },
                    217:        { "ifstats",    get_if_stats,   { NO, NO, NO, NO },
                    218:          { "", "", "", "" },
                    219:          "list interface statistics" },
                    220:        { "ifreload",   do_if_reload,   { NO, NO, NO, NO },
                    221:          { "", "", "", "" },
                    222:          "reload interface configuration" },
                    223:        { 0,            0,              { NO, NO, NO, NO },
                    224:          { "", "", "", "" }, "" }
                    225: };
                    226: 
                    227: /*
                    228:  * For quick string comparisons
                    229:  */
                    230: #define        STREQ(a, b)     (*(a) == *(b) && strcmp((a), (b)) == 0)
                    231: 
                    232: /*
                    233:  * SET_SS_LEN_IF_PRESENT - used by SET_ADDR, SET_ADDRS macros
                    234:  */
                    235: 
                    236: #ifdef ISC_PLATFORM_HAVESALEN
                    237: #define SET_SS_LEN_IF_PRESENT(psau)                            \
                    238:        do {                                                    \
                    239:                (psau)->sa.sa_len = SOCKLEN(psau);              \
                    240:        } while (0)
                    241: #else
                    242: #define SET_SS_LEN_IF_PRESENT(psau)    do { } while (0)
                    243: #endif
                    244: 
                    245: /*
                    246:  * SET_ADDR - setup address for v4/v6 as needed
                    247:  */
                    248: #define SET_ADDR(address, v6flag, v4addr, v6addr)              \
                    249: do {                                                           \
                    250:        memset(&(address), 0, sizeof(address));                 \
                    251:        if (v6flag) {                                           \
                    252:                AF(&(address)) = AF_INET6;                      \
                    253:                SOCK_ADDR6(&(address)) = (v6addr);              \
                    254:        } else {                                                \
                    255:                AF(&(address)) = AF_INET;                       \
                    256:                NSRCADR(&(address)) = (v4addr);                 \
                    257:        }                                                       \
                    258:        SET_SS_LEN_IF_PRESENT(&(address));                      \
                    259: } while (0)
                    260: 
                    261: 
                    262: /*
                    263:  * SET_ADDRS - setup source and destination addresses for 
                    264:  * v4/v6 as needed
                    265:  */
                    266: #define SET_ADDRS(a1, a2, info, a1prefix, a2prefix)            \
                    267: do {                                                           \
                    268:        memset(&(a1), 0, sizeof(a1));                           \
                    269:        memset(&(a2), 0, sizeof(a2));                           \
                    270:        if ((info)->v6_flag) {                                  \
                    271:                AF(&(a1)) = AF_INET6;                           \
                    272:                AF(&(a2)) = AF_INET6;                           \
                    273:                SOCK_ADDR6(&(a1)) = (info)->a1prefix##6;        \
                    274:                SOCK_ADDR6(&(a2)) = (info)->a2prefix##6;        \
                    275:        } else {                                                \
                    276:                AF(&(a1)) = AF_INET;                            \
                    277:                AF(&(a2)) = AF_INET;                            \
                    278:                NSRCADR(&(a1)) = (info)->a1prefix;              \
                    279:                NSRCADR(&(a2)) = (info)->a2prefix;              \
                    280:        }                                                       \
                    281:        SET_SS_LEN_IF_PRESENT(&(a1));                           \
                    282:        SET_SS_LEN_IF_PRESENT(&(a2));                           \
                    283: } while (0)
                    284: 
                    285: 
                    286: /*
                    287:  * SET_ADDRS - setup source and destination addresses for 
                    288:  * v4/v6 as needed
                    289:  */
                    290: #if 0
                    291: #define SET_ADDR_MASK(address, addrmask, info)                 \
                    292: do {                                                           \
                    293:        memset(&(address), 0, sizeof(address));                 \
                    294:        memset(&(mask), 0, sizeof(mask));                       \
                    295:        if ((info)->v6_flag) {                                  \
                    296:                AF(&(address)) = AF_INET6;                      \
                    297:                AF(&(addrmask)) = AF_INET6;                     \
                    298:                SOCK_ADDR6(&(address)) = (info)->addr6;         \
                    299:                SOCK_ADDR6(&(addrmask)) = (info)->mask6;        \
                    300:        } else {                                                \
                    301:                AF(&(address)) = AF_INET;                       \
                    302:                AF(&(addrmask)) = AF_INET;                      \
                    303:                NSRCADR(&(address)) = (info)->addr;             \
                    304:                NSRCADR(&(addrmask)) = (info)->mask;            \
                    305:        }                                                       \
                    306:        SET_SS_LEN_IF_PRESENT(&(address));                      \
                    307:        SET_SS_LEN_IF_PRESENT(&(addrmask));                     \
                    308: } while (0)
                    309: #endif
                    310: 
                    311: /*
                    312:  * checkitems - utility to print a message if no items were returned
                    313:  */
                    314: static int
                    315: checkitems(
                    316:        int items,
                    317:        FILE *fp
                    318:        )
                    319: {
                    320:        if (items == 0) {
                    321:                (void) fprintf(fp, "No data returned in response to query\n");
                    322:                return 0;
                    323:        }
                    324:        return 1;
                    325: }
                    326: 
                    327: 
                    328: /*
                    329:  * checkitemsize - utility to print a message if the item size is wrong
                    330:  */
                    331: static int
                    332: checkitemsize(
                    333:        int itemsize,
                    334:        int expected
                    335:        )
                    336: {
                    337:        if (itemsize != expected) {
                    338:                (void) fprintf(stderr,
                    339:                               "***Incorrect item size returned by remote host (%d should be %d)\n",
                    340:                               itemsize, expected);
                    341:                return 0;
                    342:        }
                    343:        return 1;
                    344: }
                    345: 
                    346: 
                    347: /*
                    348:  * check1item - check to make sure we have exactly one item
                    349:  */
                    350: static int
                    351: check1item(
                    352:        int items,
                    353:        FILE *fp
                    354:        )
                    355: {
                    356:        if (items == 0) {
                    357:                (void) fprintf(fp, "No data returned in response to query\n");
                    358:                return 0;
                    359:        }
                    360:        if (items > 1) {
                    361:                (void) fprintf(fp, "Expected one item in response, got %d\n",
                    362:                               items);
                    363:                return 0;
                    364:        }
                    365:        return 1;
                    366: }
                    367: 
                    368: 
                    369: /*
                    370:  * peerlist - get a short list of peers
                    371:  */
                    372: /*ARGSUSED*/
                    373: static void
                    374: peerlist(
                    375:        struct parse *pcmd,
                    376:        FILE *fp
                    377:        )
                    378: {
                    379:        struct info_peer_list *plist;
                    380:        sockaddr_u paddr;
                    381:        int items;
                    382:        int itemsize;
                    383:        int res;
                    384: 
                    385: again:
                    386:        res = doquery(impl_ver, REQ_PEER_LIST, 0, 0, 0, (char *)NULL, &items,
                    387:                      &itemsize, (void *)&plist, 0, 
                    388:                      sizeof(struct info_peer_list));
                    389:        
                    390:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                    391:                impl_ver = IMPL_XNTPD_OLD;
                    392:                goto again;
                    393:        }
                    394: 
                    395:        if (res != 0)
                    396:            return;
                    397: 
                    398:        if (!checkitems(items, fp))
                    399:            return;
                    400: 
                    401:        if (!checkitemsize(itemsize, sizeof(struct info_peer_list)) &&
                    402:            !checkitemsize(itemsize, v4sizeof(struct info_peer_list)))
                    403:            return;
                    404: 
                    405:        while (items > 0) {
                    406:                SET_ADDR(paddr, plist->v6_flag, plist->addr, plist->addr6);
                    407:                if ((pcmd->nargs == 0) ||
                    408:                    ((pcmd->argval->ival == 6) && (plist->v6_flag != 0)) ||
                    409:                    ((pcmd->argval->ival == 4) && (plist->v6_flag == 0)))
                    410:                        (void) fprintf(fp, "%-9s %s\n",
                    411:                                modetoa(plist->hmode),
                    412:                                nntohost(&paddr));
                    413:                plist++;
                    414:                items--;
                    415:        }
                    416: }
                    417: 
                    418: 
                    419: /*
                    420:  * peers - show peer summary
                    421:  */
                    422: static void
                    423: peers(
                    424:        struct parse *pcmd,
                    425:        FILE *fp
                    426:        )
                    427: {
                    428:        dopeers(pcmd, fp, 0);
                    429: }
                    430: 
                    431: /*
                    432:  * dmpeers - show peer summary, Dave Mills style
                    433:  */
                    434: static void
                    435: dmpeers(
                    436:        struct parse *pcmd,
                    437:        FILE *fp
                    438:        )
                    439: {
                    440:        dopeers(pcmd, fp, 1);
                    441: }
                    442: 
                    443: 
                    444: /*
                    445:  * peers - show peer summary
                    446:  */
                    447: /*ARGSUSED*/
                    448: static void
                    449: dopeers(
                    450:        struct parse *pcmd,
                    451:        FILE *fp,
                    452:        int dmstyle
                    453:        )
                    454: {
                    455:        struct info_peer_summary *plist;
                    456:        sockaddr_u dstadr;
                    457:        sockaddr_u srcadr;
                    458:        int items;
                    459:        int itemsize;
                    460:        int ntp_poll;
                    461:        int res;
                    462:        int c;
                    463:        l_fp tempts;
                    464: 
                    465: again:
                    466:        res = doquery(impl_ver, REQ_PEER_LIST_SUM, 0, 0, 0, (char *)NULL,
                    467:                      &items, &itemsize, (void *)&plist, 0, 
                    468:                      sizeof(struct info_peer_summary));
                    469:        
                    470:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                    471:                impl_ver = IMPL_XNTPD_OLD;
                    472:                goto again;
                    473:        }
                    474: 
                    475:        if (res != 0)
                    476:            return;
                    477: 
                    478:        if (!checkitems(items, fp))
                    479:            return;
                    480: 
                    481:        if (!checkitemsize(itemsize, sizeof(struct info_peer_summary)) &&
                    482:            !checkitemsize(itemsize, v4sizeof(struct info_peer_summary)))
                    483:                return;
                    484: 
                    485:        (void) fprintf(fp,
                    486:                       "     remote           local      st poll reach  delay   offset    disp\n");
                    487:        (void) fprintf(fp,
                    488:                       "=======================================================================\n");
                    489:        while (items > 0) {
                    490:                if (!dmstyle) {
                    491:                        if (plist->flags & INFO_FLAG_SYSPEER)
                    492:                            c = '*';
                    493:                        else if (plist->hmode == MODE_ACTIVE)
                    494:                            c = '+';
                    495:                        else if (plist->hmode == MODE_PASSIVE)
                    496:                            c = '-';
                    497:                        else if (plist->hmode == MODE_CLIENT)
                    498:                            c = '=';
                    499:                        else if (plist->hmode == MODE_BROADCAST)
                    500:                            c = '^';
                    501:                        else if (plist->hmode == MODE_BCLIENT)
                    502:                            c = '~';
                    503:                        else
                    504:                            c = ' ';
                    505:                } else {
                    506:                        if (plist->flags & INFO_FLAG_SYSPEER)
                    507:                            c = '*';
                    508:                        else if (plist->flags & INFO_FLAG_SHORTLIST)
                    509:                            c = '+';
                    510:                        else if (plist->flags & INFO_FLAG_SEL_CANDIDATE)
                    511:                            c = '.';
                    512:                        else
                    513:                            c = ' ';
                    514:                }
                    515:                NTOHL_FP(&(plist->offset), &tempts);
                    516:                ntp_poll = 1<<max(min3(plist->ppoll, plist->hpoll, NTP_MAXPOLL),
                    517:                                  NTP_MINPOLL);
                    518:                SET_ADDRS(dstadr, srcadr, plist, dstadr, srcadr);
                    519:                if ((pcmd->nargs == 0) ||
                    520:                    ((pcmd->argval->ival == 6) && (plist->v6_flag != 0)) ||
                    521:                    ((pcmd->argval->ival == 4) && (plist->v6_flag == 0)))
                    522:                        (void) fprintf(fp,
                    523:                            "%c%-15.15s %-15.15s %2u %4d  %3o %7.7s %9.9s %7.7s\n",
                    524:                            c, nntohost(&srcadr), stoa(&dstadr),
                    525:                            plist->stratum, ntp_poll, plist->reach,
                    526:                            fptoa(NTOHS_FP(plist->delay), 5),
                    527:                            lfptoa(&tempts, 6),
                    528:                            ufptoa(NTOHS_FP(plist->dispersion), 5));
                    529:                plist++;
                    530:                items--;
                    531:        }
                    532: }
                    533: 
                    534: /* Convert a refid & stratum (in host order) to a string */
                    535: static char*
                    536: refid_string(
                    537:        u_int32 refid,
                    538:        int stratum
                    539:        )
                    540: {
                    541:        if (stratum <= 1) {
                    542:                static char junk[5];
                    543:                junk[4] = 0;
                    544:                memmove(junk, (char *)&refid, 4);
                    545:                return junk;
                    546:        }
                    547: 
                    548:        return numtoa(refid);
                    549: }
                    550: 
                    551: static void
                    552: print_pflag(
                    553:            FILE *fp,
                    554:            u_int32 flags
                    555:            )
                    556: {
                    557:      const char *str;
                    558: 
                    559:      if (flags == 0) {
                    560:                (void) fprintf(fp, " none\n");
                    561:        } else {
                    562:                str = "";
                    563:                if (flags & INFO_FLAG_SYSPEER) {
                    564:                        (void) fprintf(fp, " system_peer");
                    565:                        str = ",";
                    566:                }
                    567:                if (flags & INFO_FLAG_CONFIG) {
                    568:                        (void) fprintf(fp, "%s config", str);
                    569:                        str = ",";
                    570:                }
                    571:                if (flags & INFO_FLAG_REFCLOCK) {
                    572:                        (void) fprintf(fp, "%s refclock", str);
                    573:                        str = ",";
                    574:                }
                    575:                if (flags & INFO_FLAG_AUTHENABLE) {
                    576:                        (void) fprintf(fp, "%s auth", str);
                    577:                        str = ",";
                    578:                }
                    579:                if (flags & INFO_FLAG_BCLIENT) {
                    580:                        (void) fprintf(fp, "%s bclient", str);
                    581:                        str = ",";
                    582:                }
                    583:                if (flags & INFO_FLAG_PREFER) {
                    584:                        (void) fprintf(fp, "%s prefer", str);
                    585:                        str = ",";
                    586:                }
                    587:                if (flags & INFO_FLAG_IBURST) {
                    588:                        (void) fprintf(fp, "%s iburst", str);
                    589:                        str = ",";
                    590:                }
                    591:                if (flags & INFO_FLAG_BURST) {
                    592:                        (void) fprintf(fp, "%s burst", str);
                    593:                }
                    594:                (void) fprintf(fp, "\n");
                    595:        }
                    596: }
                    597: /*
                    598:  * printpeer - print detail information for a peer
                    599:  */
                    600: static void
                    601: printpeer(
                    602:        register struct info_peer *pp,
                    603:        FILE *fp
                    604:        )
                    605: {
                    606:        register int i;
                    607:        l_fp tempts;
                    608:        sockaddr_u srcadr, dstadr;
                    609:        
                    610:        SET_ADDRS(dstadr, srcadr, pp, dstadr, srcadr);
                    611:        
                    612:        (void) fprintf(fp, "remote %s, local %s\n",
                    613:                       stoa(&srcadr), stoa(&dstadr));
                    614:        (void) fprintf(fp, "hmode %s, pmode %s, stratum %d, precision %d\n",
                    615:                       modetoa(pp->hmode), modetoa(pp->pmode),
                    616:                       pp->stratum, pp->precision);
                    617:        
                    618:        (void) fprintf(fp,
                    619:                       "leap %c%c, refid [%s], rootdistance %s, rootdispersion %s\n",
                    620:                       pp->leap & 0x2 ? '1' : '0',
                    621:                       pp->leap & 0x1 ? '1' : '0',
                    622:                       refid_string(pp->refid, pp->stratum), fptoa(NTOHS_FP(pp->rootdelay), 5),
                    623:                       ufptoa(NTOHS_FP(pp->rootdispersion), 5));
                    624:        
                    625:        (void) fprintf(fp,
                    626:                       "ppoll %d, hpoll %d, keyid %lu, version %d, association %u\n",
                    627:                       pp->ppoll, pp->hpoll, (u_long)pp->keyid, pp->version, ntohs(pp->associd));
                    628: 
                    629:        (void) fprintf(fp,
                    630:                       "reach %03o, unreach %d, flash 0x%04x, ",
                    631:                       pp->reach, pp->unreach, pp->flash2);
                    632: 
                    633:        (void) fprintf(fp, "boffset %s, ttl/mode %d\n",
                    634:                       fptoa(NTOHS_FP(pp->estbdelay), 5), pp->ttl);
                    635:        
                    636:        (void) fprintf(fp, "timer %lds, flags", (long)ntohl(pp->timer));
                    637:        print_pflag(fp, pp->flags); 
                    638: 
                    639:        NTOHL_FP(&pp->reftime, &tempts);
                    640:        (void) fprintf(fp, "reference time:      %s\n",
                    641:                       prettydate(&tempts));
                    642:        NTOHL_FP(&pp->org, &tempts);
                    643:        (void) fprintf(fp, "originate timestamp: %s\n",
                    644:                       prettydate(&tempts));
                    645:        NTOHL_FP(&pp->rec, &tempts);
                    646:        (void) fprintf(fp, "receive timestamp:   %s\n",
                    647:                       prettydate(&tempts));
                    648:        NTOHL_FP(&pp->xmt, &tempts);
                    649:        (void) fprintf(fp, "transmit timestamp:  %s\n",
                    650:                       prettydate(&tempts));
                    651:        
                    652:        (void) fprintf(fp, "filter delay: ");
                    653:        for (i = 0; i < NTP_SHIFT; i++) {
                    654:                (void) fprintf(fp, " %-8.8s",
                    655:                               fptoa(NTOHS_FP(pp->filtdelay[i]), 5));
                    656:                if (i == (NTP_SHIFT>>1)-1)
                    657:                    (void) fprintf(fp, "\n              ");
                    658:        }
                    659:        (void) fprintf(fp, "\n");
                    660: 
                    661:        (void) fprintf(fp, "filter offset:");
                    662:        for (i = 0; i < NTP_SHIFT; i++) {
                    663:                NTOHL_FP(&pp->filtoffset[i], &tempts);
                    664:                (void) fprintf(fp, " %-8.8s", lfptoa(&tempts, 6));
                    665:                if (i == (NTP_SHIFT>>1)-1)
                    666:                    (void) fprintf(fp, "\n              ");
                    667:        }
                    668:        (void) fprintf(fp, "\n");
                    669: 
                    670:        (void) fprintf(fp, "filter order: ");
                    671:        for (i = 0; i < NTP_SHIFT; i++) {
                    672:                (void) fprintf(fp, " %-8d", pp->order[i]);
                    673:                if (i == (NTP_SHIFT>>1)-1)
                    674:                    (void) fprintf(fp, "\n              ");
                    675:        }
                    676:        (void) fprintf(fp, "\n");
                    677:        
                    678: 
                    679:        NTOHL_FP(&pp->offset, &tempts);
                    680:        (void) fprintf(fp,
                    681:                       "offset %s, delay %s, error bound %s, filter error %s\n",
                    682:                       lfptoa(&tempts, 6), fptoa(NTOHS_FP(pp->delay), 5),
                    683:                       ufptoa(NTOHS_FP(pp->dispersion), 5),
                    684:                       ufptoa(NTOHS_FP(pp->selectdisp), 5));
                    685: }
                    686: 
                    687: 
                    688: /*
                    689:  * showpeer - show detailed information for a peer
                    690:  */
                    691: static void
                    692: showpeer(
                    693:        struct parse *pcmd,
                    694:        FILE *fp
                    695:        )
                    696: {
                    697:        struct info_peer *pp;
                    698:        /* 4 is the maximum number of peers which will fit in a packet */
                    699:        struct info_peer_list *pl, plist[min(MAXARGS, 4)];
                    700:        int qitemlim;
                    701:        int qitems;
                    702:        int items;
                    703:        int itemsize;
                    704:        int res;
                    705:        int sendsize;
                    706: 
                    707: again:
                    708:        if (impl_ver == IMPL_XNTPD)
                    709:                sendsize = sizeof(struct info_peer_list);
                    710:        else
                    711:                sendsize = v4sizeof(struct info_peer_list);
                    712: 
                    713:        qitemlim = min(pcmd->nargs, COUNTOF(plist));
                    714:        for (qitems = 0, pl = plist; qitems < qitemlim; qitems++) {
                    715:                if (IS_IPV4(&pcmd->argval[qitems].netnum)) {
                    716:                        pl->addr = NSRCADR(&pcmd->argval[qitems].netnum);
                    717:                        if (impl_ver == IMPL_XNTPD)
                    718:                                pl->v6_flag = 0;
                    719:                } else {
                    720:                        if (impl_ver == IMPL_XNTPD_OLD) {
                    721:                                fprintf(stderr,
                    722:                                    "***Server doesn't understand IPv6 addresses\n");
                    723:                                return;
                    724:                        }
                    725:                        pl->addr6 = SOCK_ADDR6(&pcmd->argval[qitems].netnum);
                    726:                        pl->v6_flag = 1;
                    727:                }
                    728:                pl->port = (u_short)s_port;
                    729:                pl->hmode = pl->flags = 0;
                    730:                pl = (struct info_peer_list *)((char *)pl + sendsize);
                    731:        }
                    732: 
                    733:        res = doquery(impl_ver, REQ_PEER_INFO, 0, qitems,
                    734:                      sendsize, (char *)plist, &items,
                    735:                      &itemsize, (void *)&pp, 0, sizeof(struct info_peer));
                    736:        
                    737:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                    738:                impl_ver = IMPL_XNTPD_OLD;
                    739:                goto again;
                    740:        }
                    741: 
                    742:        if (res != 0)
                    743:            return;
                    744: 
                    745:        if (!checkitems(items, fp))
                    746:            return;
                    747: 
                    748:        if (!checkitemsize(itemsize, sizeof(struct info_peer)) &&
                    749:            !checkitemsize(itemsize, v4sizeof(struct info_peer)))
                    750:            return;
                    751: 
                    752:        while (items-- > 0) {
                    753:                printpeer(pp, fp);
                    754:                if (items > 0)
                    755:                    (void) fprintf(fp, "\n");
                    756:                pp++;
                    757:        }
                    758: }
                    759: 
                    760: 
                    761: /*
                    762:  * peerstats - return statistics for a peer
                    763:  */
                    764: static void
                    765: peerstats(
                    766:        struct parse *pcmd,
                    767:        FILE *fp
                    768:        )
                    769: {
                    770:        struct info_peer_stats *pp;
                    771:        /* 4 is the maximum number of peers which will fit in a packet */
                    772:        struct info_peer_list *pl, plist[min(MAXARGS, 4)];
                    773:        sockaddr_u src, dst;
                    774:        int qitemlim;
                    775:        int qitems;
                    776:        int items;
                    777:        int itemsize;
                    778:        int res;
                    779:        int sendsize;
                    780: 
                    781: again:
                    782:        if (impl_ver == IMPL_XNTPD)
                    783:                sendsize = sizeof(struct info_peer_list);
                    784:        else
                    785:                sendsize = v4sizeof(struct info_peer_list);
                    786: 
                    787:        memset(plist, 0, sizeof(plist));
                    788: 
                    789:        qitemlim = min(pcmd->nargs, COUNTOF(plist));
                    790:        for (qitems = 0, pl = plist; qitems < qitemlim; qitems++) {
                    791:                if (IS_IPV4(&pcmd->argval[qitems].netnum)) {
                    792:                        pl->addr = NSRCADR(&pcmd->argval[qitems].netnum);
                    793:                        if (impl_ver == IMPL_XNTPD)
                    794:                                pl->v6_flag = 0;
                    795:                } else {
                    796:                        if (impl_ver == IMPL_XNTPD_OLD) {
                    797:                                fprintf(stderr,
                    798:                                    "***Server doesn't understand IPv6 addresses\n");
                    799:                                return;
                    800:                        }
                    801:                        pl->addr6 = SOCK_ADDR6(&pcmd->argval[qitems].netnum);
                    802:                        pl->v6_flag = 1;
                    803:                }
                    804:                pl->port = (u_short)s_port;
                    805:                pl->hmode = plist[qitems].flags = 0;
                    806:                pl = (struct info_peer_list *)((char *)pl + sendsize);
                    807:        }
                    808: 
                    809:        res = doquery(impl_ver, REQ_PEER_STATS, 0, qitems,
                    810:                      sendsize, (char *)plist, &items,
                    811:                      &itemsize, (void *)&pp, 0, 
                    812:                      sizeof(struct info_peer_stats));
                    813:        
                    814:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                    815:                impl_ver = IMPL_XNTPD_OLD;
                    816:                goto again;
                    817:        }
                    818: 
                    819:        if (res != 0)
                    820:            return;
                    821: 
                    822:        if (!checkitems(items, fp))
                    823:            return;
                    824: 
                    825:        if (!checkitemsize(itemsize, sizeof(struct info_peer_stats)) &&
                    826:            !checkitemsize(itemsize, v4sizeof(struct info_peer_stats)))
                    827:            return;
                    828: 
                    829:        while (items-- > 0) {
                    830:                ZERO_SOCK(&dst);
                    831:                ZERO_SOCK(&src);
                    832:                if (pp->v6_flag != 0) {
                    833:                        AF(&dst) = AF_INET6;
                    834:                        AF(&src) = AF_INET6;
                    835:                        SOCK_ADDR6(&dst) = pp->dstadr6;
                    836:                        SOCK_ADDR6(&src) = pp->srcadr6;
                    837:                } else {
                    838:                        AF(&dst) = AF_INET;
                    839:                        AF(&src) = AF_INET;
                    840:                        NSRCADR(&dst) = pp->dstadr;
                    841:                        NSRCADR(&src) = pp->srcadr;
                    842:                }
                    843: #ifdef ISC_PLATFORM_HAVESALEN
                    844:                src.sa.sa_len = SOCKLEN(&src);
                    845:                dst.sa.sa_len = SOCKLEN(&dst);
                    846: #endif
                    847:                fprintf(fp, "remote host:          %s\n",
                    848:                        nntohost(&src));
                    849:                fprintf(fp, "local interface:      %s\n",
                    850:                        stoa(&dst));
                    851:                fprintf(fp, "time last received:   %lus\n",
                    852:                        (u_long)ntohl(pp->timereceived));
                    853:                fprintf(fp, "time until next send: %lus\n",
                    854:                        (u_long)ntohl(pp->timetosend));
                    855:                fprintf(fp, "reachability change:  %lus\n",
                    856:                        (u_long)ntohl(pp->timereachable));
                    857:                fprintf(fp, "packets sent:         %lu\n",
                    858:                        (u_long)ntohl(pp->sent));
                    859:                fprintf(fp, "packets received:     %lu\n",
                    860:                        (u_long)ntohl(pp->processed));
                    861:                fprintf(fp, "bad authentication:   %lu\n",
                    862:                        (u_long)ntohl(pp->badauth));
                    863:                fprintf(fp, "bogus origin:         %lu\n",
                    864:                        (u_long)ntohl(pp->bogusorg));
                    865:                fprintf(fp, "duplicate:            %lu\n",
                    866:                        (u_long)ntohl(pp->oldpkt));
                    867:                fprintf(fp, "bad dispersion:       %lu\n",
                    868:                        (u_long)ntohl(pp->seldisp));
                    869:                fprintf(fp, "bad reference time:   %lu\n",
                    870:                        (u_long)ntohl(pp->selbroken));
                    871:                fprintf(fp, "candidate order:      %u\n",
                    872:                        pp->candidate);
                    873:                if (items > 0)
                    874:                        fprintf(fp, "\n");
                    875:                fprintf(fp, "flags:     ");
                    876:                print_pflag(fp, ntohs(pp->flags));
                    877:                pp++;
                    878:        }
                    879: }
                    880: 
                    881: 
                    882: /*
                    883:  * loopinfo - show loop filter information
                    884:  */
                    885: static void
                    886: loopinfo(
                    887:        struct parse *pcmd,
                    888:        FILE *fp
                    889:        )
                    890: {
                    891:        struct info_loop *il;
                    892:        int items;
                    893:        int itemsize;
                    894:        int oneline = 0;
                    895:        int res;
                    896:        l_fp tempts;
                    897: 
                    898:        if (pcmd->nargs > 0) {
                    899:                if (STREQ(pcmd->argval[0].string, "oneline"))
                    900:                    oneline = 1;
                    901:                else if (STREQ(pcmd->argval[0].string, "multiline"))
                    902:                    oneline = 0;
                    903:                else {
                    904:                        (void) fprintf(stderr, "How many lines?\n");
                    905:                        return;
                    906:                }
                    907:        }
                    908: 
                    909: again:
                    910:        res = doquery(impl_ver, REQ_LOOP_INFO, 0, 0, 0, (char *)NULL,
                    911:                      &items, &itemsize, (void *)&il, 0, 
                    912:                      sizeof(struct info_loop));
                    913:        
                    914:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                    915:                impl_ver = IMPL_XNTPD_OLD;
                    916:                goto again;
                    917:        }
                    918: 
                    919:        if (res != 0)
                    920:            return;
                    921: 
                    922:        if (!check1item(items, fp))
                    923:            return;
                    924: 
                    925:        if (!checkitemsize(itemsize, sizeof(struct info_loop)))
                    926:            return;
                    927: 
                    928:        if (oneline) {
                    929:                l_fp temp2ts;
                    930: 
                    931:                NTOHL_FP(&il->last_offset, &tempts);
                    932:                NTOHL_FP(&il->drift_comp, &temp2ts);
                    933: 
                    934:                (void) fprintf(fp,
                    935:                               "offset %s, frequency %s, time_const %ld, watchdog %ld\n",
                    936:                               lfptoa(&tempts, 6),
                    937:                               lfptoa(&temp2ts, 3),
                    938:                               (long)(int32)ntohl((u_long)il->compliance),
                    939:                               (u_long)ntohl((u_long)il->watchdog_timer));
                    940:        } else {
                    941:                NTOHL_FP(&il->last_offset, &tempts);
                    942:                (void) fprintf(fp, "offset:               %s s\n",
                    943:                               lfptoa(&tempts, 6));
                    944:                NTOHL_FP(&il->drift_comp, &tempts);
                    945:                (void) fprintf(fp, "frequency:            %s ppm\n",
                    946:                               lfptoa(&tempts, 3));
                    947:                (void) fprintf(fp, "poll adjust:          %ld\n",
                    948:                               (long)(int32)ntohl(il->compliance));
                    949:                (void) fprintf(fp, "watchdog timer:       %ld s\n",
                    950:                               (u_long)ntohl(il->watchdog_timer));
                    951:        }
                    952: }
                    953: 
                    954: 
                    955: /*
                    956:  * sysinfo - show current system state
                    957:  */
                    958: /*ARGSUSED*/
                    959: static void
                    960: sysinfo(
                    961:        struct parse *pcmd,
                    962:        FILE *fp
                    963:        )
                    964: {
                    965:        struct info_sys *is;
                    966:        sockaddr_u peeraddr;
                    967:        int items;
                    968:        int itemsize;
                    969:        int res;
                    970:        l_fp tempts;
                    971: 
                    972: again:
                    973:        res = doquery(impl_ver, REQ_SYS_INFO, 0, 0, 0, (char *)NULL,
                    974:                      &items, &itemsize, (void *)&is, 0,
                    975:                      sizeof(struct info_sys));
                    976:        
                    977:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                    978:                impl_ver = IMPL_XNTPD_OLD;
                    979:                goto again;
                    980:        }
                    981: 
                    982:        if (res != 0)
                    983:            return;
                    984: 
                    985:        if (!check1item(items, fp))
                    986:            return;
                    987: 
                    988:        if (!checkitemsize(itemsize, sizeof(struct info_sys)) &&
                    989:            !checkitemsize(itemsize, v4sizeof(struct info_sys)))
                    990:            return;
                    991: 
                    992:        SET_ADDR(peeraddr, is->v6_flag, is->peer, is->peer6);
                    993: 
                    994:        (void) fprintf(fp, "system peer:          %s\n", nntohost(&peeraddr));
                    995:        (void) fprintf(fp, "system peer mode:     %s\n", modetoa(is->peer_mode));
                    996:        (void) fprintf(fp, "leap indicator:       %c%c\n",
                    997:                       is->leap & 0x2 ? '1' : '0',
                    998:                       is->leap & 0x1 ? '1' : '0');
                    999:        (void) fprintf(fp, "stratum:              %d\n", (int)is->stratum);
                   1000:        (void) fprintf(fp, "precision:            %d\n", (int)is->precision);
                   1001:        (void) fprintf(fp, "root distance:        %s s\n",
                   1002:                       fptoa(NTOHS_FP(is->rootdelay), 5));
                   1003:        (void) fprintf(fp, "root dispersion:      %s s\n",
                   1004:                       ufptoa(NTOHS_FP(is->rootdispersion), 5));
                   1005:        (void) fprintf(fp, "reference ID:         [%s]\n",
                   1006:                       refid_string(is->refid, is->stratum));
                   1007:        NTOHL_FP(&is->reftime, &tempts);
                   1008:        (void) fprintf(fp, "reference time:       %s\n", prettydate(&tempts));
                   1009: 
                   1010:        (void) fprintf(fp, "system flags:         ");
                   1011:        if ((is->flags & (INFO_FLAG_BCLIENT | INFO_FLAG_AUTHENABLE |
                   1012:            INFO_FLAG_NTP | INFO_FLAG_KERNEL| INFO_FLAG_CAL |
                   1013:            INFO_FLAG_PPS_SYNC | INFO_FLAG_MONITOR | INFO_FLAG_FILEGEN)) == 0) {
                   1014:                (void) fprintf(fp, "none\n");
                   1015:        } else {
                   1016:                if (is->flags & INFO_FLAG_BCLIENT)
                   1017:                    (void) fprintf(fp, "bclient ");
                   1018:                if (is->flags & INFO_FLAG_AUTHENTICATE)
                   1019:                    (void) fprintf(fp, "auth ");
                   1020:                if (is->flags & INFO_FLAG_MONITOR)
                   1021:                    (void) fprintf(fp, "monitor ");
                   1022:                if (is->flags & INFO_FLAG_NTP)
                   1023:                    (void) fprintf(fp, "ntp ");
                   1024:                if (is->flags & INFO_FLAG_KERNEL)
                   1025:                    (void) fprintf(fp, "kernel ");
                   1026:                if (is->flags & INFO_FLAG_FILEGEN)
                   1027:                    (void) fprintf(fp, "stats ");
                   1028:                if (is->flags & INFO_FLAG_CAL)
                   1029:                    (void) fprintf(fp, "calibrate ");
                   1030:                if (is->flags & INFO_FLAG_PPS_SYNC)
                   1031:                    (void) fprintf(fp, "pps ");
                   1032:                (void) fprintf(fp, "\n");
                   1033:        }
                   1034:        (void) fprintf(fp, "jitter:               %s s\n",
                   1035:                       fptoa(ntohl(is->frequency), 6));
                   1036:        (void) fprintf(fp, "stability:            %s ppm\n",
                   1037:                       ufptoa(ntohl(is->stability), 3));
                   1038:        (void) fprintf(fp, "broadcastdelay:       %s s\n",
                   1039:                       fptoa(NTOHS_FP(is->bdelay), 6));
                   1040:        NTOHL_FP(&is->authdelay, &tempts);
                   1041:        (void) fprintf(fp, "authdelay:            %s s\n", lfptoa(&tempts, 6));
                   1042: }
                   1043: 
                   1044: 
                   1045: /*
                   1046:  * sysstats - print system statistics
                   1047:  */
                   1048: /*ARGSUSED*/
                   1049: static void
                   1050: sysstats(
                   1051:        struct parse *pcmd,
                   1052:        FILE *fp
                   1053:        )
                   1054: {
                   1055:        struct info_sys_stats *ss;
                   1056:        int items;
                   1057:        int itemsize;
                   1058:        int res;
                   1059: 
                   1060: again:
                   1061:        res = doquery(impl_ver, REQ_SYS_STATS, 0, 0, 0, (char *)NULL,
                   1062:                      &items, &itemsize, (void *)&ss, 0, 
                   1063:                      sizeof(struct info_sys_stats));
                   1064:        
                   1065:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   1066:                impl_ver = IMPL_XNTPD_OLD;
                   1067:                goto again;
                   1068:        }
                   1069: 
                   1070:        if (res != 0)
                   1071:            return;
                   1072: 
                   1073:        if (!check1item(items, fp))
                   1074:            return;
                   1075: 
                   1076:        if (itemsize != sizeof(struct info_sys_stats) &&
                   1077:            itemsize != sizeof(struct old_info_sys_stats)) {
                   1078:                /* issue warning according to new structure size */
                   1079:                checkitemsize(itemsize, sizeof(struct info_sys_stats));
                   1080:                return;
                   1081:        }
                   1082:        fprintf(fp, "time since restart:     %lu\n",
                   1083:                (u_long)ntohl(ss->timeup));
                   1084:        fprintf(fp, "time since reset:       %lu\n",
                   1085:                (u_long)ntohl(ss->timereset));
                   1086:        fprintf(fp, "packets received:       %lu\n",
                   1087:                (u_long)ntohl(ss->received));
                   1088:        fprintf(fp, "packets processed:      %lu\n",
                   1089:                (u_long)ntohl(ss->processed));
                   1090:        fprintf(fp, "current version:        %lu\n",
                   1091:                (u_long)ntohl(ss->newversionpkt));
                   1092:        fprintf(fp, "previous version:       %lu\n",
                   1093:                (u_long)ntohl(ss->oldversionpkt));
                   1094:        fprintf(fp, "declined:               %lu\n",
                   1095:                (u_long)ntohl(ss->unknownversion));
                   1096:        fprintf(fp, "access denied:          %lu\n",
                   1097:                (u_long)ntohl(ss->denied));
                   1098:        fprintf(fp, "bad length or format:   %lu\n",
                   1099:                (u_long)ntohl(ss->badlength));
                   1100:        fprintf(fp, "bad authentication:     %lu\n",
                   1101:                (u_long)ntohl(ss->badauth));
                   1102:        if (itemsize != sizeof(struct info_sys_stats))
                   1103:            return;
                   1104:        
                   1105:        fprintf(fp, "rate exceeded:          %lu\n",
                   1106:               (u_long)ntohl(ss->limitrejected));
                   1107: }
                   1108: 
                   1109: 
                   1110: 
                   1111: /*
                   1112:  * iostats - print I/O statistics
                   1113:  */
                   1114: /*ARGSUSED*/
                   1115: static void
                   1116: iostats(
                   1117:        struct parse *pcmd,
                   1118:        FILE *fp
                   1119:        )
                   1120: {
                   1121:        struct info_io_stats *io;
                   1122:        int items;
                   1123:        int itemsize;
                   1124:        int res;
                   1125: 
                   1126: again:
                   1127:        res = doquery(impl_ver, REQ_IO_STATS, 0, 0, 0, NULL, &items,
                   1128:                      &itemsize, (void *)&io, 0, sizeof(*io));
                   1129:        
                   1130:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   1131:                impl_ver = IMPL_XNTPD_OLD;
                   1132:                goto again;
                   1133:        }
                   1134: 
                   1135:        if (res != 0)
                   1136:                return;
                   1137: 
                   1138:        if (!check1item(items, fp))
                   1139:                return;
                   1140: 
                   1141:        if (!checkitemsize(itemsize, sizeof(*io)))
                   1142:                return;
                   1143: 
                   1144:        fprintf(fp, "time since reset:     %lu\n",
                   1145:                (u_long)ntohl(io->timereset));
                   1146:        fprintf(fp, "receive buffers:      %u\n",
                   1147:                (u_int)ntohs(io->totalrecvbufs));
                   1148:        fprintf(fp, "free receive buffers: %u\n",
                   1149:                (u_int)ntohs(io->freerecvbufs));
                   1150:        fprintf(fp, "used receive buffers: %u\n",
                   1151:                (u_int)ntohs(io->fullrecvbufs));
                   1152:        fprintf(fp, "low water refills:    %u\n",
                   1153:                (u_int)ntohs(io->lowwater));
                   1154:        fprintf(fp, "dropped packets:      %lu\n",
                   1155:                (u_long)ntohl(io->dropped));
                   1156:        fprintf(fp, "ignored packets:      %lu\n",
                   1157:                (u_long)ntohl(io->ignored));
                   1158:        fprintf(fp, "received packets:     %lu\n",
                   1159:                (u_long)ntohl(io->received));
                   1160:        fprintf(fp, "packets sent:         %lu\n",
                   1161:                (u_long)ntohl(io->sent));
                   1162:        fprintf(fp, "packets not sent:     %lu\n",
                   1163:                (u_long)ntohl(io->notsent));
                   1164:        fprintf(fp, "interrupts handled:   %lu\n",
                   1165:                (u_long)ntohl(io->interrupts));
                   1166:        fprintf(fp, "received by int:      %lu\n",
                   1167:                (u_long)ntohl(io->int_received));
                   1168: }
                   1169: 
                   1170: 
                   1171: /*
                   1172:  * memstats - print peer memory statistics
                   1173:  */
                   1174: /*ARGSUSED*/
                   1175: static void
                   1176: memstats(
                   1177:        struct parse *pcmd,
                   1178:        FILE *fp
                   1179:        )
                   1180: {
                   1181:        struct info_mem_stats *mem;
                   1182:        int i;
                   1183:        int items;
                   1184:        int itemsize;
                   1185:        int res;
                   1186: 
                   1187: again:
                   1188:        res = doquery(impl_ver, REQ_MEM_STATS, 0, 0, 0, NULL, &items,
                   1189:                      &itemsize, (void *)&mem, 0, sizeof(*mem));
                   1190:        
                   1191:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   1192:                impl_ver = IMPL_XNTPD_OLD;
                   1193:                goto again;
                   1194:        }
                   1195: 
                   1196:        if (res != 0)
                   1197:                return;
                   1198: 
                   1199:        if (!check1item(items, fp))
                   1200:                return;
                   1201: 
                   1202:        if (!checkitemsize(itemsize, sizeof(*mem)))
                   1203:                return;
                   1204: 
                   1205:        fprintf(fp, "time since reset:     %lu\n",
                   1206:                (u_long)ntohl(mem->timereset));
                   1207:        fprintf(fp, "total peer memory:    %u\n",
                   1208:                (u_int)ntohs(mem->totalpeermem));
                   1209:        fprintf(fp, "free peer memory:     %u\n",
                   1210:                (u_int)ntohs(mem->freepeermem));
                   1211:        fprintf(fp, "calls to findpeer:    %lu\n",
                   1212:                (u_long)ntohl(mem->findpeer_calls));
                   1213:        fprintf(fp, "new peer allocations: %lu\n",
                   1214:                (u_long)ntohl(mem->allocations));
                   1215:        fprintf(fp, "peer demobilizations: %lu\n",
                   1216:                (u_long)ntohl(mem->demobilizations));
                   1217: 
                   1218:        fprintf(fp, "hash table counts:   ");
                   1219:        for (i = 0; i < NTP_HASH_SIZE; i++) {
                   1220:                fprintf(fp, "%4d", (int)mem->hashcount[i]);
                   1221:                if ((i % 8) == 7 && i != (NTP_HASH_SIZE-1))
                   1222:                        fprintf(fp, "\n                     ");
                   1223:        }
                   1224:        fprintf(fp, "\n");
                   1225: }
                   1226: 
                   1227: 
                   1228: 
                   1229: /*
                   1230:  * timerstats - print timer statistics
                   1231:  */
                   1232: /*ARGSUSED*/
                   1233: static void
                   1234: timerstats(
                   1235:        struct parse *pcmd,
                   1236:        FILE *fp
                   1237:        )
                   1238: {
                   1239:        struct info_timer_stats *tim;
                   1240:        int items;
                   1241:        int itemsize;
                   1242:        int res;
                   1243: 
                   1244: again:
                   1245:        res = doquery(impl_ver, REQ_TIMER_STATS, 0, 0, 0, NULL, &items,
                   1246:                      &itemsize, (void *)&tim, 0, sizeof(*tim));
                   1247:        
                   1248:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   1249:                impl_ver = IMPL_XNTPD_OLD;
                   1250:                goto again;
                   1251:        }
                   1252: 
                   1253:        if (res != 0)
                   1254:                return;
                   1255: 
                   1256:        if (!check1item(items, fp))
                   1257:                return;
                   1258: 
                   1259:        if (!checkitemsize(itemsize, sizeof(*tim)))
                   1260:                return;
                   1261: 
                   1262:        fprintf(fp, "time since reset:  %lu\n",
                   1263:                (u_long)ntohl(tim->timereset));
                   1264:        fprintf(fp, "alarms handled:    %lu\n",
                   1265:                (u_long)ntohl(tim->alarms));
                   1266:        fprintf(fp, "alarm overruns:    %lu\n",
                   1267:                (u_long)ntohl(tim->overflows));
                   1268:        fprintf(fp, "calls to transmit: %lu\n",
                   1269:                (u_long)ntohl(tim->xmtcalls));
                   1270: }
                   1271: 
                   1272: 
                   1273: /*
                   1274:  * addpeer - configure an active mode association
                   1275:  */
                   1276: static void
                   1277: addpeer(
                   1278:        struct parse *pcmd,
                   1279:        FILE *fp
                   1280:        )
                   1281: {
                   1282:        doconfig(pcmd, fp, MODE_ACTIVE, 0);
                   1283: }
                   1284: 
                   1285: 
                   1286: /*
                   1287:  * addserver - configure a client mode association
                   1288:  */
                   1289: static void
                   1290: addserver(
                   1291:        struct parse *pcmd,
                   1292:        FILE *fp
                   1293:        )
                   1294: {
                   1295:        doconfig(pcmd, fp, MODE_CLIENT, 0);
                   1296: }
                   1297: 
                   1298: /*
                   1299:  * addrefclock - configure a reference clock association
                   1300:  */
                   1301: static void
                   1302: addrefclock(
                   1303:        struct parse *pcmd,
                   1304:        FILE *fp
                   1305:        )
                   1306: {
                   1307:        doconfig(pcmd, fp, MODE_CLIENT, 1);
                   1308: }
                   1309: 
                   1310: /*
                   1311:  * broadcast - configure a broadcast mode association
                   1312:  */
                   1313: static void
                   1314: broadcast(
                   1315:        struct parse *pcmd,
                   1316:        FILE *fp
                   1317:        )
                   1318: {
                   1319:        doconfig(pcmd, fp, MODE_BROADCAST, 0);
                   1320: }
                   1321: 
                   1322: 
                   1323: /*
                   1324:  * config - configure a new peer association
                   1325:  */
                   1326: static void
                   1327: doconfig(
                   1328:        struct parse *pcmd,
                   1329:        FILE *fp,
                   1330:        int mode,
                   1331:        int refc
                   1332:        )
                   1333: {
                   1334:        struct conf_peer cpeer;
                   1335:        int items;
                   1336:        int itemsize;
                   1337:        char *dummy;
                   1338:        u_long keyid;
                   1339:        u_int version;
                   1340:        u_char minpoll;
                   1341:        u_char maxpoll;
                   1342:        u_int flags;
                   1343:        u_char cmode;
                   1344:        int res;
                   1345:        int sendsize;
                   1346:        int numtyp;
                   1347:        long val;
                   1348: 
                   1349: again:
                   1350:        keyid = 0;
                   1351:        version = 3;
                   1352:        flags = 0;
                   1353:        res = FALSE;
                   1354:        cmode = 0;
                   1355:        minpoll = NTP_MINDPOLL;
                   1356:        maxpoll = NTP_MAXDPOLL;
                   1357:        numtyp = 1;
                   1358:        if (refc)
                   1359:                numtyp = 5;
                   1360: 
                   1361:        if (impl_ver == IMPL_XNTPD)
                   1362:                sendsize = sizeof(struct conf_peer);
                   1363:        else
                   1364:                sendsize = v4sizeof(struct conf_peer);
                   1365: 
                   1366:        items = 1;
                   1367:        while (pcmd->nargs > items) {
                   1368:                if (STREQ(pcmd->argval[items].string, "prefer"))
                   1369:                        flags |= CONF_FLAG_PREFER;
                   1370:                else if (STREQ(pcmd->argval[items].string, "burst"))
                   1371:                        flags |= CONF_FLAG_BURST;
                   1372:                else if (STREQ(pcmd->argval[items].string, "iburst"))
                   1373:                        flags |= CONF_FLAG_IBURST;
                   1374:                else if (!refc && STREQ(pcmd->argval[items].string, "keyid"))
                   1375:                        numtyp = 1;
                   1376:                else if (!refc && STREQ(pcmd->argval[items].string, "version"))
                   1377:                        numtyp = 2;
                   1378:                else if (STREQ(pcmd->argval[items].string, "minpoll"))
                   1379:                        numtyp = 3;
                   1380:                else if (STREQ(pcmd->argval[items].string, "maxpoll"))
                   1381:                        numtyp = 4;
                   1382:                else {
                   1383:                        if (!atoint(pcmd->argval[items].string, &val))
                   1384:                                numtyp = 0;
                   1385:                        switch (numtyp) {
                   1386:                        case 1:
                   1387:                                keyid = val;
                   1388:                                numtyp = 2;
                   1389:                                break;
                   1390: 
                   1391:                        case 2:
                   1392:                                version = (u_int)val;
                   1393:                                numtyp = 0;
                   1394:                                break;
                   1395: 
                   1396:                        case 3:
                   1397:                                minpoll = (u_char)val;
                   1398:                                numtyp = 0;
                   1399:                                break;
                   1400: 
                   1401:                        case 4:
                   1402:                                maxpoll = (u_char)val;
                   1403:                                numtyp = 0;
                   1404:                                break;
                   1405: 
                   1406:                        case 5:
                   1407:                                cmode = (u_char)val;
                   1408:                                numtyp = 0;
                   1409:                                break;
                   1410: 
                   1411:                        default:
                   1412:                                fprintf(fp, "*** '%s' not understood\n",
                   1413:                                        pcmd->argval[items].string);
                   1414:                                res = TRUE;
                   1415:                                numtyp = 0;
                   1416:                        }
                   1417:                        if (val < 0) {
                   1418:                                fprintf(stderr,
                   1419:                                        "*** Value '%s' should be unsigned\n",
                   1420:                                        pcmd->argval[items].string);
                   1421:                                res = TRUE;
                   1422:                        }
                   1423:                }
                   1424:                items++;
                   1425:        }
                   1426:        if (keyid > 0)
                   1427:                flags |= CONF_FLAG_AUTHENABLE;
                   1428:        if (version > NTP_VERSION || version < NTP_OLDVERSION) {
                   1429:                fprintf(fp, "***invalid version number: %u\n",
                   1430:                        version);
                   1431:                res = TRUE;
                   1432:        }
                   1433:        if (minpoll < NTP_MINPOLL || minpoll > NTP_MAXPOLL || 
                   1434:            maxpoll < NTP_MINPOLL || maxpoll > NTP_MAXPOLL || 
                   1435:            minpoll > maxpoll) {
                   1436:                fprintf(fp, "***min/max-poll must be within %d..%d\n",
                   1437:                        NTP_MINPOLL, NTP_MAXPOLL);
                   1438:                res = TRUE;
                   1439:        }                                       
                   1440: 
                   1441:        if (res)
                   1442:                return;
                   1443: 
                   1444:        memset(&cpeer, 0, sizeof(cpeer));
                   1445: 
                   1446:        if (IS_IPV4(&pcmd->argval[0].netnum)) {
                   1447:                cpeer.peeraddr = NSRCADR(&pcmd->argval[0].netnum);
                   1448:                if (impl_ver == IMPL_XNTPD)
                   1449:                        cpeer.v6_flag = 0;
                   1450:        } else {
                   1451:                if (impl_ver == IMPL_XNTPD_OLD) {
                   1452:                        fprintf(stderr,
                   1453:                            "***Server doesn't understand IPv6 addresses\n");
                   1454:                        return;
                   1455:                }
                   1456:                cpeer.peeraddr6 = SOCK_ADDR6(&pcmd->argval[0].netnum);
                   1457:                cpeer.v6_flag = 1;
                   1458:        }
                   1459:        cpeer.hmode = (u_char) mode;
                   1460:        cpeer.keyid = keyid;
                   1461:        cpeer.version = (u_char) version;
                   1462:        cpeer.minpoll = minpoll;
                   1463:        cpeer.maxpoll = maxpoll;
                   1464:        cpeer.flags = (u_char)flags;
                   1465:        cpeer.ttl = cmode;
                   1466: 
                   1467:        res = doquery(impl_ver, REQ_CONFIG, 1, 1,
                   1468:                      sendsize, (char *)&cpeer, &items,
                   1469:                      &itemsize, &dummy, 0, sizeof(struct conf_peer));
                   1470:        
                   1471:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   1472:                impl_ver = IMPL_XNTPD_OLD;
                   1473:                goto again;
                   1474:        }
                   1475: 
                   1476:        if (res == INFO_ERR_FMT) {
                   1477:                (void) fprintf(fp,
                   1478:                    "***Retrying command with old conf_peer size\n");
                   1479:                res = doquery(impl_ver, REQ_CONFIG, 1, 1,
                   1480:                              sizeof(struct old_conf_peer), (char *)&cpeer,
                   1481:                              &items, &itemsize, &dummy, 0,
                   1482:                              sizeof(struct conf_peer));
                   1483:        }
                   1484:        if (res == 0)
                   1485:            (void) fprintf(fp, "done!\n");
                   1486:        return;
                   1487: }
                   1488: 
                   1489: 
                   1490: /*
                   1491:  * unconfig - unconfigure some associations
                   1492:  */
                   1493: static void
                   1494: unconfig(
                   1495:        struct parse *pcmd,
                   1496:        FILE *fp
                   1497:        )
                   1498: {
                   1499:        /* 8 is the maximum number of peers which will fit in a packet */
                   1500:        struct conf_unpeer *pl, plist[min(MAXARGS, 8)];
                   1501:        int qitemlim;
                   1502:        int qitems;
                   1503:        int items;
                   1504:        int itemsize;
                   1505:        char *dummy;
                   1506:        int res;
                   1507:        int sendsize;
                   1508: 
                   1509: again:
                   1510:        if (impl_ver == IMPL_XNTPD)
                   1511:                sendsize = sizeof(struct conf_unpeer);
                   1512:        else
                   1513:                sendsize = v4sizeof(struct conf_unpeer);
                   1514: 
                   1515:        qitemlim = min(pcmd->nargs, COUNTOF(plist));
                   1516:        for (qitems = 0, pl = plist; qitems < qitemlim; qitems++) {
                   1517:                if (IS_IPV4(&pcmd->argval[0].netnum)) {
                   1518:                        pl->peeraddr = NSRCADR(&pcmd->argval[qitems].netnum);
                   1519:                        if (impl_ver == IMPL_XNTPD)
                   1520:                                pl->v6_flag = 0;
                   1521:                } else {
                   1522:                        if (impl_ver == IMPL_XNTPD_OLD) {
                   1523:                                fprintf(stderr,
                   1524:                                    "***Server doesn't understand IPv6 addresses\n");
                   1525:                                return;
                   1526:                        }
                   1527:                        pl->peeraddr6 =
                   1528:                            SOCK_ADDR6(&pcmd->argval[qitems].netnum);
                   1529:                        pl->v6_flag = 1;
                   1530:                }
                   1531:                pl = (struct conf_unpeer *)((char *)pl + sendsize);
                   1532:        }
                   1533: 
                   1534:        res = doquery(impl_ver, REQ_UNCONFIG, 1, qitems,
                   1535:                      sendsize, (char *)plist, &items,
                   1536:                      &itemsize, &dummy, 0, sizeof(struct conf_unpeer));
                   1537:        
                   1538:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   1539:                impl_ver = IMPL_XNTPD_OLD;
                   1540:                goto again;
                   1541:        }
                   1542: 
                   1543:        if (res == 0)
                   1544:            (void) fprintf(fp, "done!\n");
                   1545: }
                   1546: 
                   1547: 
                   1548: /*
                   1549:  * set - set some system flags
                   1550:  */
                   1551: static void
                   1552: set(
                   1553:        struct parse *pcmd,
                   1554:        FILE *fp
                   1555:        )
                   1556: {
                   1557:        doset(pcmd, fp, REQ_SET_SYS_FLAG);
                   1558: }
                   1559: 
                   1560: 
                   1561: /*
                   1562:  * clear - clear some system flags
                   1563:  */
                   1564: static void
                   1565: sys_clear(
                   1566:        struct parse *pcmd,
                   1567:        FILE *fp
                   1568:        )
                   1569: {
                   1570:        doset(pcmd, fp, REQ_CLR_SYS_FLAG);
                   1571: }
                   1572: 
                   1573: 
                   1574: /*
                   1575:  * doset - set/clear system flags
                   1576:  */
                   1577: static void
                   1578: doset(
                   1579:        struct parse *pcmd,
                   1580:        FILE *fp,
                   1581:        int req
                   1582:        )
                   1583: {
                   1584:        struct conf_sys_flags sys;
                   1585:        int items;
                   1586:        int itemsize;
                   1587:        char *dummy;
                   1588:        int res;
                   1589: 
                   1590:        sys.flags = 0;
                   1591:        res = 0;
                   1592:        for (items = 0; items < pcmd->nargs; items++) {
                   1593:                if (STREQ(pcmd->argval[items].string, "auth"))
                   1594:                        sys.flags |= SYS_FLAG_AUTH;
                   1595:                else if (STREQ(pcmd->argval[items].string, "bclient"))
                   1596:                        sys.flags |= SYS_FLAG_BCLIENT;
                   1597:                else if (STREQ(pcmd->argval[items].string, "calibrate"))
                   1598:                        sys.flags |= SYS_FLAG_CAL;
                   1599:                else if (STREQ(pcmd->argval[items].string, "kernel"))
                   1600:                        sys.flags |= SYS_FLAG_KERNEL;
                   1601:                else if (STREQ(pcmd->argval[items].string, "monitor"))
                   1602:                        sys.flags |= SYS_FLAG_MONITOR;
                   1603:                else if (STREQ(pcmd->argval[items].string, "ntp"))
                   1604:                        sys.flags |= SYS_FLAG_NTP;
                   1605:                else if (STREQ(pcmd->argval[items].string, "pps"))
                   1606:                        sys.flags |= SYS_FLAG_PPS;
                   1607:                else if (STREQ(pcmd->argval[items].string, "stats"))
                   1608:                        sys.flags |= SYS_FLAG_FILEGEN;
                   1609:                else {
                   1610:                        (void) fprintf(fp, "Unknown flag %s\n",
                   1611:                            pcmd->argval[items].string);
                   1612:                        res = 1;
                   1613:                }
                   1614:        }
                   1615: 
                   1616:        sys.flags = htonl(sys.flags);
                   1617:        if (res || sys.flags == 0)
                   1618:            return;
                   1619: 
                   1620: again:
                   1621:        res = doquery(impl_ver, req, 1, 1,
                   1622:                      sizeof(struct conf_sys_flags), (char *)&sys, &items,
                   1623:                      &itemsize, &dummy, 0, sizeof(struct conf_sys_flags));
                   1624:        
                   1625:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   1626:                impl_ver = IMPL_XNTPD_OLD;
                   1627:                goto again;
                   1628:        }
                   1629: 
                   1630:        if (res == 0)
                   1631:            (void) fprintf(fp, "done!\n");
                   1632: }
                   1633: 
                   1634: 
                   1635: /*
                   1636:  * data for printing/interrpreting the restrict flags
                   1637:  */
                   1638: struct resflags {
                   1639:   const char *str;
                   1640:        int bit;
                   1641: };
                   1642: 
                   1643: /* XXX: HMS: we apparently don't report set bits we do not recognize. */
                   1644: 
                   1645: static struct resflags resflagsV2[] = {
                   1646:        { "ignore",     0x001 },
                   1647:        { "noserve",    0x002 },
                   1648:        { "notrust",    0x004 },
                   1649:        { "noquery",    0x008 },
                   1650:        { "nomodify",   0x010 },
                   1651:        { "nopeer",     0x020 },
                   1652:        { "notrap",     0x040 },
                   1653:        { "lptrap",     0x080 },
                   1654:        { "limited",    0x100 },
                   1655:        { "",           0 }
                   1656: };
                   1657: 
                   1658: static struct resflags resflagsV3[] = {
                   1659:        { "ignore",     RES_IGNORE },
                   1660:        { "noserve",    RES_DONTSERVE },
                   1661:        { "notrust",    RES_DONTTRUST },
                   1662:        { "noquery",    RES_NOQUERY },
                   1663:        { "nomodify",   RES_NOMODIFY },
                   1664:        { "nopeer",     RES_NOPEER },
                   1665:        { "notrap",     RES_NOTRAP },
                   1666:        { "lptrap",     RES_LPTRAP },
                   1667:        { "limited",    RES_LIMITED },
                   1668:        { "version",    RES_VERSION },
                   1669:        { "kod",        RES_KOD },
                   1670:        { "timeout",    RES_TIMEOUT },
                   1671: 
                   1672:        { "",           0 }
                   1673: };
                   1674: 
                   1675: static struct resflags resmflags[] = {
                   1676:        { "ntpport",    RESM_NTPONLY },
                   1677:        { "interface",  RESM_INTERFACE },
                   1678:        { "",           0 }
                   1679: };
                   1680: 
                   1681: 
                   1682: /*
                   1683:  * reslist - obtain and print the server's restrict list
                   1684:  */
                   1685: /*ARGSUSED*/
                   1686: static void
                   1687: reslist(
                   1688:        struct parse *pcmd,
                   1689:        FILE *fp
                   1690:        )
                   1691: {
                   1692:        struct info_restrict *rl;
                   1693:        sockaddr_u resaddr;
                   1694:        sockaddr_u maskaddr;
                   1695:        int items;
                   1696:        int itemsize;
                   1697:        int res;
                   1698:        int skip;
                   1699:        char *addr;
                   1700:        char *mask;
                   1701:        struct resflags *rf;
                   1702:        u_int32 count;
                   1703:        u_short flags;
                   1704:        u_short mflags;
                   1705:        char flagstr[300];
                   1706:        static const char *comma = ", ";
                   1707: 
                   1708: again:
                   1709:        res = doquery(impl_ver, REQ_GET_RESTRICT, 0, 0, 0, (char *)NULL,
                   1710:                      &items, &itemsize, (void *)&rl, 0, 
                   1711:                      sizeof(struct info_restrict));
                   1712:        
                   1713:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   1714:                impl_ver = IMPL_XNTPD_OLD;
                   1715:                goto again;
                   1716:        }
                   1717: 
                   1718:        if (res != 0)
                   1719:            return;
                   1720: 
                   1721:        if (!checkitems(items, fp))
                   1722:            return;
                   1723: 
                   1724:        if (!checkitemsize(itemsize, sizeof(struct info_restrict)) &&
                   1725:            !checkitemsize(itemsize, v4sizeof(struct info_restrict)))
                   1726:            return;
                   1727: 
                   1728:        (void) fprintf(fp,
                   1729:               "   address          mask            count        flags\n");
                   1730:        (void) fprintf(fp,
                   1731:                       "=====================================================================\n");
                   1732: 
                   1733:        while (items > 0) {
                   1734:                SET_ADDRS(resaddr, maskaddr, rl, addr, mask);
                   1735:                if (rl->v6_flag != 0) {
                   1736:                        addr = nntohost(&resaddr);
                   1737:                } else {
                   1738:                        if ((rl->mask == (u_int32)0xffffffff))
                   1739:                                addr = nntohost(&resaddr);
                   1740:                        else
                   1741:                                addr = stoa(&resaddr);
                   1742:                }
                   1743:                mask = stoa(&maskaddr);
                   1744:                skip = 1;
                   1745:                if ((pcmd->nargs == 0) ||
                   1746:                    ((pcmd->argval->ival == 6) && (rl->v6_flag != 0)) ||
                   1747:                    ((pcmd->argval->ival == 4) && (rl->v6_flag == 0)))
                   1748:                        skip = 0;
                   1749:                count = ntohl(rl->count);
                   1750:                flags = ntohs(rl->flags);
                   1751:                mflags = ntohs(rl->mflags);
                   1752:                flagstr[0] = '\0';
                   1753: 
                   1754:                res = 1;
                   1755:                rf = &resmflags[0];
                   1756:                while (rf->bit != 0) {
                   1757:                        if (mflags & rf->bit) {
                   1758:                                if (!res)
                   1759:                                    (void) strcat(flagstr, comma);
                   1760:                                res = 0;
                   1761:                                (void) strcat(flagstr, rf->str);
                   1762:                        }
                   1763:                        rf++;
                   1764:                }
                   1765: 
                   1766:                rf = (impl_ver == IMPL_XNTPD_OLD)
                   1767:                     ? &resflagsV2[0]
                   1768:                     : &resflagsV3[0]
                   1769:                     ;
                   1770:                while (rf->bit != 0) {
                   1771:                        if (flags & rf->bit) {
                   1772:                                if (!res)
                   1773:                                    (void) strcat(flagstr, comma);
                   1774:                                res = 0;
                   1775:                                (void) strcat(flagstr, rf->str);
                   1776:                        }
                   1777:                        rf++;
                   1778:                }
                   1779: 
                   1780:                if (flagstr[0] == '\0')
                   1781:                        strcpy(flagstr, "none");
                   1782: 
                   1783:                if (!skip)
                   1784:                        fprintf(fp, "%-15.15s %-15.15s %9lu  %s\n",
                   1785:                                addr, mask, (u_long)count, flagstr);
                   1786:                rl++;
                   1787:                items--;
                   1788:        }
                   1789: }
                   1790: 
                   1791: 
                   1792: 
                   1793: /*
                   1794:  * new_restrict - create/add a set of restrictions
                   1795:  */
                   1796: static void
                   1797: new_restrict(
                   1798:        struct parse *pcmd,
                   1799:        FILE *fp
                   1800:        )
                   1801: {
                   1802:        do_restrict(pcmd, fp, REQ_RESADDFLAGS);
                   1803: }
                   1804: 
                   1805: 
                   1806: /*
                   1807:  * unrestrict - remove restriction flags from existing entry
                   1808:  */
                   1809: static void
                   1810: unrestrict(
                   1811:        struct parse *pcmd,
                   1812:        FILE *fp
                   1813:        )
                   1814: {
                   1815:        do_restrict(pcmd, fp, REQ_RESSUBFLAGS);
                   1816: }
                   1817: 
                   1818: 
                   1819: /*
                   1820:  * delrestrict - delete an existing restriction
                   1821:  */
                   1822: static void
                   1823: delrestrict(
                   1824:        struct parse *pcmd,
                   1825:        FILE *fp
                   1826:        )
                   1827: {
                   1828:        do_restrict(pcmd, fp, REQ_UNRESTRICT);
                   1829: }
                   1830: 
                   1831: 
                   1832: /*
                   1833:  * do_restrict - decode commandline restrictions and make the request
                   1834:  */
                   1835: static void
                   1836: do_restrict(
                   1837:        struct parse *pcmd,
                   1838:        FILE *fp,
                   1839:        int req_code
                   1840:        )
                   1841: {
                   1842:        struct conf_restrict cres;
                   1843:        int items;
                   1844:        int itemsize;
                   1845:        char *dummy;
                   1846:        u_int32 num;
                   1847:        u_long bit;
                   1848:        int i;
                   1849:        int res;
                   1850:        int err;
                   1851:        int sendsize;
                   1852: 
                   1853:        /* Initialize cres */
                   1854:        cres.addr = 0;
                   1855:        cres.mask = 0;
                   1856:        cres.flags = 0;
                   1857:        cres.mflags = 0;
                   1858:        cres.v6_flag = 0;
                   1859: 
                   1860: again:
                   1861:        if (impl_ver == IMPL_XNTPD)
                   1862:                sendsize = sizeof(struct conf_restrict);
                   1863:        else
                   1864:                sendsize = v4sizeof(struct conf_restrict);
                   1865: 
                   1866:        if (IS_IPV4(&pcmd->argval[0].netnum)) {
                   1867:                cres.addr = NSRCADR(&pcmd->argval[0].netnum);
                   1868:                cres.mask = NSRCADR(&pcmd->argval[1].netnum);
                   1869:                if (impl_ver == IMPL_XNTPD)
                   1870:                        cres.v6_flag = 0;
                   1871:        } else {
                   1872:                if (impl_ver == IMPL_XNTPD_OLD) {
                   1873:                        fprintf(stderr,
                   1874:                                "***Server doesn't understand IPv6 addresses\n");
                   1875:                        return;
                   1876:                }
                   1877:                cres.addr6 = SOCK_ADDR6(&pcmd->argval[0].netnum);
                   1878:                cres.v6_flag = 1;
                   1879:        }
                   1880:        cres.flags = 0;
                   1881:        cres.mflags = 0;
                   1882:        err = FALSE;
                   1883:        for (res = 2; res < pcmd->nargs; res++) {
                   1884:                if (STREQ(pcmd->argval[res].string, "ntpport")) {
                   1885:                        cres.mflags |= RESM_NTPONLY;
                   1886:                } else {
                   1887:                        for (i = 0; resflagsV3[i].bit != 0; i++) {
                   1888:                                if (STREQ(pcmd->argval[res].string,
                   1889:                                          resflagsV3[i].str))
                   1890:                                        break;
                   1891:                        }
                   1892:                        if (resflagsV3[i].bit != 0) {
                   1893:                                cres.flags |= resflagsV3[i].bit;
                   1894:                                if (req_code == REQ_UNRESTRICT) {
                   1895:                                        fprintf(fp,
                   1896:                                                "Flag %s inappropriate\n",
                   1897:                                                resflagsV3[i].str);
                   1898:                                        err = TRUE;
                   1899:                                }
                   1900:                        } else {
                   1901:                                fprintf(fp, "Unknown flag %s\n",
                   1902:                                        pcmd->argval[res].string);
                   1903:                                err = TRUE;
                   1904:                        }
                   1905:                }
                   1906:        }
                   1907:        cres.flags = htons(cres.flags);
                   1908:        cres.mflags = htons(cres.mflags);
                   1909: 
                   1910:        /*
                   1911:         * Make sure mask for default address is zero.  Otherwise,
                   1912:         * make sure mask bits are contiguous.
                   1913:         */
                   1914:        if (IS_IPV4(&pcmd->argval[0].netnum)) {
                   1915:                if (cres.addr == 0) {
                   1916:                        cres.mask = 0;
                   1917:                } else {
                   1918:                        num = ntohl(cres.mask);
                   1919:                        for (bit = 0x80000000; bit != 0; bit >>= 1)
                   1920:                                if ((num & bit) == 0)
                   1921:                                        break;
                   1922:                        for ( ; bit != 0; bit >>= 1)
                   1923:                                if ((num & bit) != 0)
                   1924:                                        break;
                   1925:                        if (bit != 0) {
                   1926:                                fprintf(fp, "Invalid mask %s\n",
                   1927:                                        numtoa(cres.mask));
                   1928:                                err = TRUE;
                   1929:                        }
                   1930:                }
                   1931:        } else {
                   1932:                /* XXX IPv6 sanity checking stuff */
                   1933:        }
                   1934: 
                   1935:        if (err)
                   1936:                return;
                   1937: 
                   1938:        res = doquery(impl_ver, req_code, 1, 1, sendsize, (char *)&cres,
                   1939:                      &items, &itemsize, &dummy, 0, sizeof(cres));
                   1940:        
                   1941:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   1942:                impl_ver = IMPL_XNTPD_OLD;
                   1943:                goto again;
                   1944:        }
                   1945: 
                   1946:        if (res == 0)
                   1947:            (void) fprintf(fp, "done!\n");
                   1948:        return;
                   1949: }
                   1950: 
                   1951: 
                   1952: /*
                   1953:  * monlist - obtain and print the server's monitor data
                   1954:  */
                   1955: /*ARGSUSED*/
                   1956: static void
                   1957: monlist(
                   1958:        struct parse *pcmd,
                   1959:        FILE *fp
                   1960:        )
                   1961: {
                   1962:        char *struct_star;
                   1963:        sockaddr_u addr;
                   1964:        sockaddr_u dstadr;
                   1965:        int items;
                   1966:        int itemsize;
                   1967:        int res;
                   1968:        int version = -1;
                   1969: 
                   1970:        if (pcmd->nargs > 0) {
                   1971:                version = pcmd->argval[0].ival;
                   1972:        }
                   1973: 
                   1974: again:
                   1975:        res = doquery(impl_ver,
                   1976:                      (version == 1 || version == -1) ? REQ_MON_GETLIST_1 :
                   1977:                      REQ_MON_GETLIST, 0, 0, 0, (char *)NULL,
                   1978:                      &items, &itemsize, &struct_star,
                   1979:                      (version < 0) ? (1 << INFO_ERR_REQ) : 0, 
                   1980:                      sizeof(struct info_monitor_1));
                   1981: 
                   1982:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   1983:                impl_ver = IMPL_XNTPD_OLD;
                   1984:                goto again;
                   1985:        }
                   1986: 
                   1987:        if (res == INFO_ERR_REQ && version < 0) 
                   1988:            res = doquery(impl_ver, REQ_MON_GETLIST, 0, 0, 0, (char *)NULL,
                   1989:                          &items, &itemsize, &struct_star, 0, 
                   1990:                          sizeof(struct info_monitor));
                   1991:        
                   1992:        if (res != 0)
                   1993:            return;
                   1994: 
                   1995:        if (!checkitems(items, fp))
                   1996:            return;
                   1997: 
                   1998:        if (itemsize == sizeof(struct info_monitor_1) ||
                   1999:            itemsize == v4sizeof(struct info_monitor_1)) {
                   2000:                struct info_monitor_1 *ml = (struct info_monitor_1 *) struct_star;
                   2001: 
                   2002:                (void) fprintf(fp,
                   2003:                               "remote address          port local address      count m ver rstr avgint  lstint\n");
                   2004:                (void) fprintf(fp,
                   2005:                               "===============================================================================\n");
                   2006:                while (items > 0) {
                   2007:                        SET_ADDRS(dstadr, addr, ml, daddr, addr);
                   2008:                        if ((pcmd->nargs == 0) ||
                   2009:                            ((pcmd->argval->ival == 6) && (ml->v6_flag != 0)) ||
                   2010:                            ((pcmd->argval->ival == 4) && (ml->v6_flag == 0)))
                   2011:                                fprintf(fp, 
                   2012:                                    "%-22.22s %5d %-15s %8lu %1u %1u %6lx %6lu %7lu\n",
                   2013:                                    nntohost(&addr), 
                   2014:                                    ntohs(ml->port),
                   2015:                                    stoa(&dstadr),
                   2016:                                    (u_long)ntohl(ml->count),
                   2017:                                    ml->mode,
                   2018:                                    ml->version,
                   2019:                                    (u_long)ntohl(ml->restr),
                   2020:                                    (u_long)ntohl(ml->lasttime),
                   2021:                                    (u_long)ntohl(ml->firsttime));
                   2022:                        ml++;
                   2023:                        items--;
                   2024:                }
                   2025:        } else if (itemsize == sizeof(struct info_monitor) ||
                   2026:            itemsize == v4sizeof(struct info_monitor)) {
                   2027:                struct info_monitor *ml = (struct info_monitor *) struct_star;
                   2028: 
                   2029:                (void) fprintf(fp,
                   2030:                               "     address               port     count mode ver rstr avgint  lstint\n");
                   2031:                (void) fprintf(fp,
                   2032:                               "===============================================================================\n");
                   2033:                while (items > 0) {
                   2034:                        SET_ADDR(dstadr, ml->v6_flag, ml->addr, ml->addr6);
                   2035:                        if ((pcmd->nargs == 0) ||
                   2036:                            ((pcmd->argval->ival == 6) && (ml->v6_flag != 0)) ||
                   2037:                            ((pcmd->argval->ival == 4) && (ml->v6_flag == 0)))
                   2038:                                (void) fprintf(fp,
                   2039:                                    "%-25.25s %5u %9lu %4u %2u %9lx %9lu %9lu\n",
                   2040:                                    nntohost(&dstadr),
                   2041:                                    ntohs(ml->port),
                   2042:                                    (u_long)ntohl(ml->count),
                   2043:                                    ml->mode,
                   2044:                                    ml->version,
                   2045:                                    (u_long)ntohl(ml->restr),
                   2046:                                    (u_long)ntohl(ml->lasttime),
                   2047:                                    (u_long)ntohl(ml->firsttime));
                   2048:                        ml++;
                   2049:                        items--;
                   2050:                }
                   2051:        } else if (itemsize == sizeof(struct old_info_monitor)) {
                   2052:                struct old_info_monitor *oml = (struct old_info_monitor *)struct_star;
                   2053:                (void) fprintf(fp,
                   2054:                               "     address          port     count  mode version  lasttime firsttime\n");
                   2055:                (void) fprintf(fp,
                   2056:                               "======================================================================\n");
                   2057:                while (items > 0) {
                   2058:                        SET_ADDR(dstadr, oml->v6_flag, oml->addr, oml->addr6);
                   2059:                        (void) fprintf(fp, "%-20.20s %5u %9lu %4u   %3u %9lu %9lu\n",
                   2060:                                       nntohost(&dstadr),
                   2061:                                       ntohs(oml->port),
                   2062:                                       (u_long)ntohl(oml->count),
                   2063:                                       oml->mode,
                   2064:                                       oml->version,
                   2065:                                       (u_long)ntohl(oml->lasttime),
                   2066:                                       (u_long)ntohl(oml->firsttime));
                   2067:                        oml++;
                   2068:                        items--;
                   2069:                }
                   2070:        } else {
                   2071:                /* issue warning according to new info_monitor size */
                   2072:                checkitemsize(itemsize, sizeof(struct info_monitor));
                   2073:        }
                   2074: }
                   2075: 
                   2076: 
                   2077: /*
                   2078:  * Mapping between command line strings and stat reset flags
                   2079:  */
                   2080: struct statreset {
                   2081:   const char *str;
                   2082:        int flag;
                   2083: } sreset[] = {
                   2084:        { "io",         RESET_FLAG_IO },
                   2085:        { "sys",        RESET_FLAG_SYS },
                   2086:        { "mem",        RESET_FLAG_MEM },
                   2087:        { "timer",      RESET_FLAG_TIMER },
                   2088:        { "auth",       RESET_FLAG_AUTH },
                   2089:        { "allpeers",   RESET_FLAG_ALLPEERS },
                   2090:        { "",           0 }
                   2091: };
                   2092: 
                   2093: /*
                   2094:  * reset - reset statistic counters
                   2095:  */
                   2096: static void
                   2097: reset(
                   2098:        struct parse *pcmd,
                   2099:        FILE *fp
                   2100:        )
                   2101: {
                   2102:        struct reset_flags rflags;
                   2103:        int items;
                   2104:        int itemsize;
                   2105:        char *dummy;
                   2106:        int i;
                   2107:        int res;
                   2108:        int err;
                   2109: 
                   2110:        err = 0;
                   2111:        rflags.flags = 0;
                   2112:        for (res = 0; res < pcmd->nargs; res++) {
                   2113:                for (i = 0; sreset[i].flag != 0; i++) {
                   2114:                        if (STREQ(pcmd->argval[res].string, sreset[i].str))
                   2115:                            break;
                   2116:                }
                   2117:                if (sreset[i].flag == 0) {
                   2118:                        (void) fprintf(fp, "Flag %s unknown\n",
                   2119:                                       pcmd->argval[res].string);
                   2120:                        err++;
                   2121:                } else {
                   2122:                        rflags.flags |= sreset[i].flag;
                   2123:                }
                   2124:        }
                   2125:        rflags.flags = htonl(rflags.flags);
                   2126: 
                   2127:        if (err) {
                   2128:                (void) fprintf(fp, "Not done due to errors\n");
                   2129:                return;
                   2130:        }
                   2131: 
                   2132: again:
                   2133:        res = doquery(impl_ver, REQ_RESET_STATS, 1, 1,
                   2134:                      sizeof(struct reset_flags), (char *)&rflags, &items,
                   2135:                      &itemsize, &dummy, 0, sizeof(struct reset_flags));
                   2136:        
                   2137:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   2138:                impl_ver = IMPL_XNTPD_OLD;
                   2139:                goto again;
                   2140:        }
                   2141: 
                   2142:        if (res == 0)
                   2143:            (void) fprintf(fp, "done!\n");
                   2144:        return;
                   2145: }
                   2146: 
                   2147: 
                   2148: 
                   2149: /*
                   2150:  * preset - reset stat counters for particular peers
                   2151:  */
                   2152: static void
                   2153: preset(
                   2154:        struct parse *pcmd,
                   2155:        FILE *fp
                   2156:        )
                   2157: {
                   2158:        /* 8 is the maximum number of peers which will fit in a packet */
                   2159:        struct conf_unpeer *pl, plist[min(MAXARGS, 8)];
                   2160:        int qitemlim;
                   2161:        int qitems;
                   2162:        int items;
                   2163:        int itemsize;
                   2164:        char *dummy;
                   2165:        int res;
                   2166:        int sendsize;
                   2167: 
                   2168: again:
                   2169:        if (impl_ver == IMPL_XNTPD)
                   2170:                sendsize = sizeof(struct conf_unpeer);
                   2171:        else
                   2172:                sendsize = v4sizeof(struct conf_unpeer);
                   2173: 
                   2174:        qitemlim = min(pcmd->nargs, COUNTOF(plist));
                   2175:        for (qitems = 0, pl = plist; qitems < qitemlim; qitems++) {
                   2176:                if (IS_IPV4(&pcmd->argval[qitems].netnum)) {
                   2177:                        pl->peeraddr = NSRCADR(&pcmd->argval[qitems].netnum);
                   2178:                        if (impl_ver == IMPL_XNTPD)
                   2179:                                pl->v6_flag = 0;
                   2180:                } else {
                   2181:                        if (impl_ver == IMPL_XNTPD_OLD) {
                   2182:                                fprintf(stderr,
                   2183:                                    "***Server doesn't understand IPv6 addresses\n");
                   2184:                                return;
                   2185:                        }
                   2186:                        pl->peeraddr6 =
                   2187:                            SOCK_ADDR6(&pcmd->argval[qitems].netnum);
                   2188:                        pl->v6_flag = 1;
                   2189:                }
                   2190:                pl = (struct conf_unpeer *)((char *)pl + sendsize);
                   2191:        }
                   2192: 
                   2193:        res = doquery(impl_ver, REQ_RESET_PEER, 1, qitems,
                   2194:                      sendsize, (char *)plist, &items,
                   2195:                      &itemsize, &dummy, 0, sizeof(struct conf_unpeer));
                   2196:        
                   2197:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   2198:                impl_ver = IMPL_XNTPD_OLD;
                   2199:                goto again;
                   2200:        }
                   2201: 
                   2202:        if (res == 0)
                   2203:            (void) fprintf(fp, "done!\n");
                   2204: }
                   2205: 
                   2206: 
                   2207: /*
                   2208:  * readkeys - request the server to reread the keys file
                   2209:  */
                   2210: /*ARGSUSED*/
                   2211: static void
                   2212: readkeys(
                   2213:        struct parse *pcmd,
                   2214:        FILE *fp
                   2215:        )
                   2216: {
                   2217:        int items;
                   2218:        int itemsize;
                   2219:        char *dummy;
                   2220:        int res;
                   2221: 
                   2222: again:
                   2223:        res = doquery(impl_ver, REQ_REREAD_KEYS, 1, 0, 0, (char *)0,
                   2224:                      &items, &itemsize, &dummy, 0, sizeof(dummy));
                   2225:        
                   2226:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   2227:                impl_ver = IMPL_XNTPD_OLD;
                   2228:                goto again;
                   2229:        }
                   2230: 
                   2231:        if (res == 0)
                   2232:            (void) fprintf(fp, "done!\n");
                   2233:        return;
                   2234: }
                   2235: 
                   2236: 
                   2237: /*
                   2238:  * trustkey - add some keys to the trusted key list
                   2239:  */
                   2240: static void
                   2241: trustkey(
                   2242:        struct parse *pcmd,
                   2243:        FILE *fp
                   2244:        )
                   2245: {
                   2246:        do_trustkey(pcmd, fp, REQ_TRUSTKEY);
                   2247: }
                   2248: 
                   2249: 
                   2250: /*
                   2251:  * untrustkey - remove some keys from the trusted key list
                   2252:  */
                   2253: static void
                   2254: untrustkey(
                   2255:        struct parse *pcmd,
                   2256:        FILE *fp
                   2257:        )
                   2258: {
                   2259:        do_trustkey(pcmd, fp, REQ_UNTRUSTKEY);
                   2260: }
                   2261: 
                   2262: 
                   2263: /*
                   2264:  * do_trustkey - do grunge work of adding/deleting keys
                   2265:  */
                   2266: static void
                   2267: do_trustkey(
                   2268:        struct parse *pcmd,
                   2269:        FILE *fp,
                   2270:        int req
                   2271:        )
                   2272: {
                   2273:        u_long keyids[MAXARGS];
                   2274:        int i;
                   2275:        int items;
                   2276:        int itemsize;
                   2277:        char *dummy;
                   2278:        int ritems;
                   2279:        int res;
                   2280: 
                   2281:        ritems = 0;
                   2282:        for (i = 0; i < pcmd->nargs; i++) {
                   2283:                keyids[ritems++] = pcmd->argval[i].uval;
                   2284:        }
                   2285: 
                   2286: again:
                   2287:        res = doquery(impl_ver, req, 1, ritems, sizeof(u_long),
                   2288:                      (char *)keyids, &items, &itemsize, &dummy, 0, 
                   2289:                      sizeof(dummy));
                   2290:        
                   2291:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   2292:                impl_ver = IMPL_XNTPD_OLD;
                   2293:                goto again;
                   2294:        }
                   2295: 
                   2296:        if (res == 0)
                   2297:            (void) fprintf(fp, "done!\n");
                   2298:        return;
                   2299: }
                   2300: 
                   2301: 
                   2302: 
                   2303: /*
                   2304:  * authinfo - obtain and print info about authentication
                   2305:  */
                   2306: /*ARGSUSED*/
                   2307: static void
                   2308: authinfo(
                   2309:        struct parse *pcmd,
                   2310:        FILE *fp
                   2311:        )
                   2312: {
                   2313:        struct info_auth *ia;
                   2314:        int items;
                   2315:        int itemsize;
                   2316:        int res;
                   2317: 
                   2318: again:
                   2319:        res = doquery(impl_ver, REQ_AUTHINFO, 0, 0, 0, NULL, &items,
                   2320:                      &itemsize, (void *)&ia, 0, sizeof(*ia));
                   2321:        
                   2322:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   2323:                impl_ver = IMPL_XNTPD_OLD;
                   2324:                goto again;
                   2325:        }
                   2326: 
                   2327:        if (res != 0)
                   2328:                return;
                   2329: 
                   2330:        if (!check1item(items, fp))
                   2331:                return;
                   2332: 
                   2333:        if (!checkitemsize(itemsize, sizeof(*ia)))
                   2334:                return;
                   2335: 
                   2336:        fprintf(fp, "time since reset:     %lu\n",
                   2337:                (u_long)ntohl(ia->timereset));
                   2338:        fprintf(fp, "stored keys:          %lu\n",
                   2339:                (u_long)ntohl(ia->numkeys));
                   2340:        fprintf(fp, "free keys:            %lu\n",
                   2341:                (u_long)ntohl(ia->numfreekeys));
                   2342:        fprintf(fp, "key lookups:          %lu\n",
                   2343:                (u_long)ntohl(ia->keylookups));
                   2344:        fprintf(fp, "keys not found:       %lu\n",
                   2345:                (u_long)ntohl(ia->keynotfound));
                   2346:        fprintf(fp, "uncached keys:        %lu\n",
                   2347:                (u_long)ntohl(ia->keyuncached));
                   2348:        fprintf(fp, "encryptions:          %lu\n",
                   2349:                (u_long)ntohl(ia->encryptions));
                   2350:        fprintf(fp, "decryptions:          %lu\n",
                   2351:                (u_long)ntohl(ia->decryptions));
                   2352:        fprintf(fp, "expired keys:         %lu\n",
                   2353:                (u_long)ntohl(ia->expired));
                   2354: }
                   2355: 
                   2356: 
                   2357: 
                   2358: /*
                   2359:  * traps - obtain and print a list of traps
                   2360:  */
                   2361: /*ARGSUSED*/
                   2362: static void
                   2363: traps(
                   2364:        struct parse *pcmd,
                   2365:        FILE *fp
                   2366:        )
                   2367: {
                   2368:        int i;
                   2369:        struct info_trap *it;
                   2370:        sockaddr_u trap_addr, local_addr;
                   2371:        int items;
                   2372:        int itemsize;
                   2373:        int res;
                   2374: 
                   2375: again:
                   2376:        res = doquery(impl_ver, REQ_TRAPS, 0, 0, 0, (char *)NULL,
                   2377:                      &items, &itemsize, (void *)&it, 0, 
                   2378:                      sizeof(struct info_trap));
                   2379:        
                   2380:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   2381:                impl_ver = IMPL_XNTPD_OLD;
                   2382:                goto again;
                   2383:        }
                   2384: 
                   2385:        if (res != 0)
                   2386:            return;
                   2387: 
                   2388:        if (!checkitems(items, fp))
                   2389:            return;
                   2390: 
                   2391:        if (!checkitemsize(itemsize, sizeof(struct info_trap)) &&
                   2392:            !checkitemsize(itemsize, v4sizeof(struct info_trap)))
                   2393:            return;
                   2394: 
                   2395:        for (i = 0; i < items; i++ ) {
                   2396:                if (i != 0)
                   2397:                    (void) fprintf(fp, "\n");
                   2398:                SET_ADDRS(trap_addr, local_addr, it, trap_address, local_address);
                   2399:                (void) fprintf(fp, "address %s, port %d\n",
                   2400:                                stoa(&trap_addr), 
                   2401:                                ntohs(it->trap_port));
                   2402:                (void) fprintf(fp, "interface: %s, ",
                   2403:                                (it->local_address == 0)
                   2404:                                ? "wildcard"
                   2405:                                : stoa(&local_addr));
                   2406:                if (ntohl(it->flags) & TRAP_CONFIGURED)
                   2407:                    (void) fprintf(fp, "configured\n");
                   2408:                else if (ntohl(it->flags) & TRAP_NONPRIO)
                   2409:                    (void) fprintf(fp, "low priority\n");
                   2410:                else
                   2411:                    (void) fprintf(fp, "normal priority\n");
                   2412:                
                   2413:                (void) fprintf(fp, "set for %ld secs, last set %ld secs ago\n",
                   2414:                               (long)ntohl(it->origtime),
                   2415:                               (long)ntohl(it->settime));
                   2416:                (void) fprintf(fp, "sequence %d, number of resets %ld\n",
                   2417:                               ntohs(it->sequence),
                   2418:                               (long)ntohl(it->resets));
                   2419:        }
                   2420: }
                   2421: 
                   2422: 
                   2423: /*
                   2424:  * addtrap - configure a trap
                   2425:  */
                   2426: static void
                   2427: addtrap(
                   2428:        struct parse *pcmd,
                   2429:        FILE *fp
                   2430:        )
                   2431: {
                   2432:        do_addclr_trap(pcmd, fp, REQ_ADD_TRAP);
                   2433: }
                   2434: 
                   2435: 
                   2436: /*
                   2437:  * clrtrap - clear a trap from the server
                   2438:  */
                   2439: static void
                   2440: clrtrap(
                   2441:        struct parse *pcmd,
                   2442:        FILE *fp
                   2443:        )
                   2444: {
                   2445:        do_addclr_trap(pcmd, fp, REQ_CLR_TRAP);
                   2446: }
                   2447: 
                   2448: 
                   2449: /*
                   2450:  * do_addclr_trap - do grunge work of adding/deleting traps
                   2451:  */
                   2452: static void
                   2453: do_addclr_trap(
                   2454:        struct parse *pcmd,
                   2455:        FILE *fp,
                   2456:        int req
                   2457:        )
                   2458: {
                   2459:        struct conf_trap ctrap;
                   2460:        int items;
                   2461:        int itemsize;
                   2462:        char *dummy;
                   2463:        int res;
                   2464:        int sendsize;
                   2465: 
                   2466: again:
                   2467:        if (impl_ver == IMPL_XNTPD)
                   2468:                sendsize = sizeof(struct conf_trap);
                   2469:        else
                   2470:                sendsize = v4sizeof(struct conf_trap);
                   2471: 
                   2472:        if (IS_IPV4(&pcmd->argval[0].netnum)) {
                   2473:                ctrap.trap_address = NSRCADR(&pcmd->argval[0].netnum);
                   2474:                if (impl_ver == IMPL_XNTPD)
                   2475:                        ctrap.v6_flag = 0;
                   2476:        } else {
                   2477:                if (impl_ver == IMPL_XNTPD_OLD) {
                   2478:                        fprintf(stderr,
                   2479:                            "***Server doesn't understand IPv6 addresses\n");
                   2480:                        return;
                   2481:                }
                   2482:                ctrap.trap_address6 = SOCK_ADDR6(&pcmd->argval[0].netnum);
                   2483:                ctrap.v6_flag = 1;
                   2484:        }
                   2485:        ctrap.local_address = 0;
                   2486:        ctrap.trap_port = htons(TRAPPORT);
                   2487:        ctrap.unused = 0;
                   2488: 
                   2489:        if (pcmd->nargs > 1) {
                   2490:                ctrap.trap_port = htons((u_short)pcmd->argval[1].uval);
                   2491:                if (pcmd->nargs > 2) {
                   2492:                        if (AF(&pcmd->argval[2].netnum) !=
                   2493:                            AF(&pcmd->argval[0].netnum)) {
                   2494:                                fprintf(stderr,
                   2495:                                    "***Cannot mix IPv4 and IPv6 addresses\n");
                   2496:                                return;
                   2497:                        }
                   2498:                        if (IS_IPV4(&pcmd->argval[2].netnum))
                   2499:                                ctrap.local_address = NSRCADR(&pcmd->argval[2].netnum);
                   2500:                        else
                   2501:                                ctrap.local_address6 = SOCK_ADDR6(&pcmd->argval[2].netnum);
                   2502:                }
                   2503:        }
                   2504: 
                   2505:        res = doquery(impl_ver, req, 1, 1, sendsize,
                   2506:                      (char *)&ctrap, &items, &itemsize, &dummy, 0, 
                   2507:                      sizeof(struct conf_trap));
                   2508:        
                   2509:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   2510:                impl_ver = IMPL_XNTPD_OLD;
                   2511:                goto again;
                   2512:        }
                   2513: 
                   2514:        if (res == 0)
                   2515:            (void) fprintf(fp, "done!\n");
                   2516:        return;
                   2517: }
                   2518: 
                   2519: 
                   2520: 
                   2521: /*
                   2522:  * requestkey - change the server's request key (a dangerous request)
                   2523:  */
                   2524: static void
                   2525: requestkey(
                   2526:        struct parse *pcmd,
                   2527:        FILE *fp
                   2528:        )
                   2529: {
                   2530:        do_changekey(pcmd, fp, REQ_REQUEST_KEY);
                   2531: }
                   2532: 
                   2533: 
                   2534: /*
                   2535:  * controlkey - change the server's control key
                   2536:  */
                   2537: static void
                   2538: controlkey(
                   2539:        struct parse *pcmd,
                   2540:        FILE *fp
                   2541:        )
                   2542: {
                   2543:        do_changekey(pcmd, fp, REQ_CONTROL_KEY);
                   2544: }
                   2545: 
                   2546: 
                   2547: 
                   2548: /*
                   2549:  * do_changekey - do grunge work of changing keys
                   2550:  */
                   2551: static void
                   2552: do_changekey(
                   2553:        struct parse *pcmd,
                   2554:        FILE *fp,
                   2555:        int req
                   2556:        )
                   2557: {
                   2558:        u_long key;
                   2559:        int items;
                   2560:        int itemsize;
                   2561:        char *dummy;
                   2562:        int res;
                   2563: 
                   2564: 
                   2565:        key = htonl((u_int32)pcmd->argval[0].uval);
                   2566: 
                   2567: again:
                   2568:        res = doquery(impl_ver, req, 1, 1, sizeof(u_int32),
                   2569:                      (char *)&key, &items, &itemsize, &dummy, 0, 
                   2570:                      sizeof(dummy));
                   2571:        
                   2572:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   2573:                impl_ver = IMPL_XNTPD_OLD;
                   2574:                goto again;
                   2575:        }
                   2576: 
                   2577:        if (res == 0)
                   2578:            (void) fprintf(fp, "done!\n");
                   2579:        return;
                   2580: }
                   2581: 
                   2582: 
                   2583: 
                   2584: /*
                   2585:  * ctlstats - obtain and print info about authentication
                   2586:  */
                   2587: /*ARGSUSED*/
                   2588: static void
                   2589: ctlstats(
                   2590:        struct parse *pcmd,
                   2591:        FILE *fp
                   2592:        )
                   2593: {
                   2594:        struct info_control *ic;
                   2595:        int items;
                   2596:        int itemsize;
                   2597:        int res;
                   2598: 
                   2599: again:
                   2600:        res = doquery(impl_ver, REQ_GET_CTLSTATS, 0, 0, 0, NULL, &items,
                   2601:                      &itemsize, (void *)&ic, 0, sizeof(*ic));
                   2602:        
                   2603:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   2604:                impl_ver = IMPL_XNTPD_OLD;
                   2605:                goto again;
                   2606:        }
                   2607: 
                   2608:        if (res != 0)
                   2609:                return;
                   2610: 
                   2611:        if (!check1item(items, fp))
                   2612:                return;
                   2613: 
                   2614:        if (!checkitemsize(itemsize, sizeof(*ic)))
                   2615:                return;
                   2616: 
                   2617:        fprintf(fp, "time since reset:       %lu\n",
                   2618:                (u_long)ntohl(ic->ctltimereset));
                   2619:        fprintf(fp, "requests received:      %lu\n",
                   2620:                (u_long)ntohl(ic->numctlreq));
                   2621:        fprintf(fp, "responses sent:         %lu\n",
                   2622:                (u_long)ntohl(ic->numctlresponses));
                   2623:        fprintf(fp, "fragments sent:         %lu\n",
                   2624:                (u_long)ntohl(ic->numctlfrags));
                   2625:        fprintf(fp, "async messages sent:    %lu\n",
                   2626:                (u_long)ntohl(ic->numasyncmsgs));
                   2627:        fprintf(fp, "error msgs sent:        %lu\n",
                   2628:                (u_long)ntohl(ic->numctlerrors));
                   2629:        fprintf(fp, "total bad pkts:         %lu\n",
                   2630:                (u_long)ntohl(ic->numctlbadpkts));
                   2631:        fprintf(fp, "packet too short:       %lu\n",
                   2632:                (u_long)ntohl(ic->numctltooshort));
                   2633:        fprintf(fp, "response on input:      %lu\n",
                   2634:                (u_long)ntohl(ic->numctlinputresp));
                   2635:        fprintf(fp, "fragment on input:      %lu\n",
                   2636:                (u_long)ntohl(ic->numctlinputfrag));
                   2637:        fprintf(fp, "error set on input:     %lu\n",
                   2638:                (u_long)ntohl(ic->numctlinputerr));
                   2639:        fprintf(fp, "bad offset on input:    %lu\n",
                   2640:                (u_long)ntohl(ic->numctlbadoffset));
                   2641:        fprintf(fp, "bad version packets:    %lu\n",
                   2642:                (u_long)ntohl(ic->numctlbadversion));
                   2643:        fprintf(fp, "data in pkt too short:  %lu\n",
                   2644:                (u_long)ntohl(ic->numctldatatooshort));
                   2645:        fprintf(fp, "unknown op codes:       %lu\n",
                   2646:                (u_long)ntohl(ic->numctlbadop));
                   2647: }
                   2648: 
                   2649: 
                   2650: /*
                   2651:  * clockstat - get and print clock status information
                   2652:  */
                   2653: static void
                   2654: clockstat(
                   2655:        struct parse *pcmd,
                   2656:        FILE *fp
                   2657:        )
                   2658: {
                   2659:        struct info_clock *cl;
                   2660:        /* 8 is the maximum number of clocks which will fit in a packet */
                   2661:        u_long clist[min(MAXARGS, 8)];
                   2662:        int qitemlim;
                   2663:        int qitems;
                   2664:        int items;
                   2665:        int itemsize;
                   2666:        int res;
                   2667:        l_fp ts;
                   2668:        struct clktype *clk;
                   2669: 
                   2670:        qitemlim = min(pcmd->nargs, COUNTOF(clist));
                   2671:        for (qitems = 0; qitems < qitemlim; qitems++)
                   2672:                clist[qitems] = NSRCADR(&pcmd->argval[qitems].netnum);
                   2673: 
                   2674: again:
                   2675:        res = doquery(impl_ver, REQ_GET_CLOCKINFO, 0, qitems,
                   2676:                      sizeof(u_int32), (char *)clist, &items,
                   2677:                      &itemsize, (void *)&cl, 0, sizeof(struct info_clock));
                   2678:        
                   2679:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   2680:                impl_ver = IMPL_XNTPD_OLD;
                   2681:                goto again;
                   2682:        }
                   2683: 
                   2684:        if (res != 0)
                   2685:                return;
                   2686: 
                   2687:        if (!checkitems(items, fp))
                   2688:                return;
                   2689: 
                   2690:        if (!checkitemsize(itemsize, sizeof(struct info_clock)))
                   2691:                return;
                   2692: 
                   2693:        while (items-- > 0) {
                   2694:                (void) fprintf(fp, "clock address:        %s\n",
                   2695:                               numtoa(cl->clockadr));
                   2696:                for (clk = clktypes; clk->code >= 0; clk++)
                   2697:                    if (clk->code == cl->type)
                   2698:                        break;
                   2699:                if (clk->code >= 0)
                   2700:                    (void) fprintf(fp, "clock type:           %s\n",
                   2701:                                   clk->clocktype);
                   2702:                else
                   2703:                    (void) fprintf(fp, "clock type:           unknown type (%d)\n",
                   2704:                                   cl->type);
                   2705:                (void) fprintf(fp, "last event:           %d\n",
                   2706:                               cl->lastevent);
                   2707:                (void) fprintf(fp, "current status:       %d\n",
                   2708:                               cl->currentstatus);
                   2709:                (void) fprintf(fp, "number of polls:      %lu\n",
                   2710:                               (u_long)ntohl(cl->polls));
                   2711:                (void) fprintf(fp, "no response to poll:  %lu\n",
                   2712:                               (u_long)ntohl(cl->noresponse));
                   2713:                (void) fprintf(fp, "bad format responses: %lu\n",
                   2714:                               (u_long)ntohl(cl->badformat));
                   2715:                (void) fprintf(fp, "bad data responses:   %lu\n",
                   2716:                               (u_long)ntohl(cl->baddata));
                   2717:                (void) fprintf(fp, "running time:         %lu\n",
                   2718:                               (u_long)ntohl(cl->timestarted));
                   2719:                NTOHL_FP(&cl->fudgetime1, &ts);
                   2720:                (void) fprintf(fp, "fudge time 1:         %s\n",
                   2721:                               lfptoa(&ts, 6));
                   2722:                NTOHL_FP(&cl->fudgetime2, &ts);
                   2723:                (void) fprintf(fp, "fudge time 2:         %s\n",
                   2724:                               lfptoa(&ts, 6));
                   2725:                (void) fprintf(fp, "stratum:              %ld\n",
                   2726:                               (u_long)ntohl(cl->fudgeval1));
                   2727:                (void) fprintf(fp, "reference ID:         %s\n",
                   2728:                               refid_string(ntohl(cl->fudgeval2), 0));
                   2729:                (void) fprintf(fp, "fudge flags:          0x%x\n",
                   2730:                               cl->flags);
                   2731: 
                   2732:                if (items > 0)
                   2733:                    (void) fprintf(fp, "\n");
                   2734:                cl++;
                   2735:        }
                   2736: }
                   2737: 
                   2738: 
                   2739: /*
                   2740:  * fudge - set clock fudge factors
                   2741:  */
                   2742: static void
                   2743: fudge(
                   2744:        struct parse *pcmd,
                   2745:        FILE *fp
                   2746:        )
                   2747: {
                   2748:        struct conf_fudge fudgedata;
                   2749:        int items;
                   2750:        int itemsize;
                   2751:        char *dummy;
                   2752:        l_fp ts;
                   2753:        int res;
                   2754:        long val;
                   2755:        u_long u_val;
                   2756:        int err;
                   2757: 
                   2758: 
                   2759:        err = 0;
                   2760:        memset((char *)&fudgedata, 0, sizeof fudgedata);
                   2761:        fudgedata.clockadr = NSRCADR(&pcmd->argval[0].netnum);
                   2762: 
                   2763:        if (STREQ(pcmd->argval[1].string, "time1")) {
                   2764:                fudgedata.which = htonl(FUDGE_TIME1);
                   2765:                if (!atolfp(pcmd->argval[2].string, &ts))
                   2766:                    err = 1;
                   2767:                else
                   2768:                    NTOHL_FP(&ts, &fudgedata.fudgetime);
                   2769:        } else if (STREQ(pcmd->argval[1].string, "time2")) {
                   2770:                fudgedata.which = htonl(FUDGE_TIME2);
                   2771:                if (!atolfp(pcmd->argval[2].string, &ts))
                   2772:                    err = 1;
                   2773:                else
                   2774:                    NTOHL_FP(&ts, &fudgedata.fudgetime);
                   2775:        } else if (STREQ(pcmd->argval[1].string, "val1")) {
                   2776:                fudgedata.which = htonl(FUDGE_VAL1);
                   2777:                if (!atoint(pcmd->argval[2].string, &val))
                   2778:                    err = 1;
                   2779:                else
                   2780:                    fudgedata.fudgeval_flags = htonl(val);
                   2781:        } else if (STREQ(pcmd->argval[1].string, "val2")) {
                   2782:                fudgedata.which = htonl(FUDGE_VAL2);
                   2783:                if (!atoint(pcmd->argval[2].string, &val))
                   2784:                    err = 1;
                   2785:                else
                   2786:                    fudgedata.fudgeval_flags = htonl((u_int32)val);
                   2787:        } else if (STREQ(pcmd->argval[1].string, "flags")) {
                   2788:                fudgedata.which = htonl(FUDGE_FLAGS);
                   2789:                if (!hextoint(pcmd->argval[2].string, &u_val))
                   2790:                    err = 1;
                   2791:                else
                   2792:                    fudgedata.fudgeval_flags = htonl((u_int32)(u_val & 0xf));
                   2793:        } else {
                   2794:                (void) fprintf(stderr, "What fudge is %s?\n",
                   2795:                               pcmd->argval[1].string);
                   2796:                return;
                   2797:        }
                   2798: 
                   2799:        if (err) {
                   2800:                (void) fprintf(stderr, "Unknown fudge parameter %s\n",
                   2801:                               pcmd->argval[2].string);
                   2802:                return;
                   2803:        }
                   2804: 
                   2805: again:
                   2806:        res = doquery(impl_ver, REQ_SET_CLKFUDGE, 1, 1,
                   2807:                      sizeof(struct conf_fudge), (char *)&fudgedata, &items,
                   2808:                      &itemsize, &dummy, 0, sizeof(dummy));
                   2809: 
                   2810:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   2811:                impl_ver = IMPL_XNTPD_OLD;
                   2812:                goto again;
                   2813:        }
                   2814: 
                   2815:        if (res == 0)
                   2816:            (void) fprintf(fp, "done!\n");
                   2817:        return;
                   2818: }
                   2819: 
                   2820: /*
                   2821:  * clkbug - get and print clock debugging information
                   2822:  */
                   2823: static void
                   2824: clkbug(
                   2825:        struct parse *pcmd,
                   2826:        FILE *fp
                   2827:        )
                   2828: {
                   2829:        register int i;
                   2830:        register int n;
                   2831:        register u_int32 s;
                   2832:        struct info_clkbug *cl;
                   2833:        /* 8 is the maximum number of clocks which will fit in a packet */
                   2834:        u_long clist[min(MAXARGS, 8)];
                   2835:        u_int32 ltemp;
                   2836:        int qitemlim;
                   2837:        int qitems;
                   2838:        int items;
                   2839:        int itemsize;
                   2840:        int res;
                   2841:        int needsp;
                   2842:        l_fp ts;
                   2843: 
                   2844:        qitemlim = min(pcmd->nargs, COUNTOF(clist));
                   2845:        for (qitems = 0; qitems < qitemlim; qitems++)
                   2846:                clist[qitems] = NSRCADR(&pcmd->argval[qitems].netnum);
                   2847: 
                   2848: again:
                   2849:        res = doquery(impl_ver, REQ_GET_CLKBUGINFO, 0, qitems,
                   2850:                      sizeof(u_int32), (char *)clist, &items,
                   2851:                      &itemsize, (void *)&cl, 0, sizeof(struct info_clkbug));
                   2852:        
                   2853:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   2854:                impl_ver = IMPL_XNTPD_OLD;
                   2855:                goto again;
                   2856:        }
                   2857: 
                   2858:        if (res != 0)
                   2859:                return;
                   2860: 
                   2861:        if (!checkitems(items, fp))
                   2862:                return;
                   2863: 
                   2864:        if (!checkitemsize(itemsize, sizeof(struct info_clkbug)))
                   2865:                return;
                   2866: 
                   2867:        while (items-- > 0) {
                   2868:                (void) fprintf(fp, "clock address:        %s\n",
                   2869:                               numtoa(cl->clockadr));
                   2870:                n = (int)cl->nvalues;
                   2871:                (void) fprintf(fp, "values: %d", n);
                   2872:                s = ntohs(cl->svalues);
                   2873:                if (n > NUMCBUGVALUES)
                   2874:                    n = NUMCBUGVALUES;
                   2875:                for (i = 0; i < n; i++) {
                   2876:                        ltemp = ntohl(cl->values[i]);
                   2877:                        ltemp &= 0xffffffff;    /* HMS: This does nothing now */
                   2878:                        if ((i & 0x3) == 0)
                   2879:                            (void) fprintf(fp, "\n");
                   2880:                        if (s & (1 << i))
                   2881:                            (void) fprintf(fp, "%12ld", (u_long)ltemp);
                   2882:                        else
                   2883:                            (void) fprintf(fp, "%12lu", (u_long)ltemp);
                   2884:                }
                   2885:                (void) fprintf(fp, "\n");
                   2886: 
                   2887:                n = (int)cl->ntimes;
                   2888:                (void) fprintf(fp, "times: %d", n);
                   2889:                s = ntohl(cl->stimes);
                   2890:                if (n > NUMCBUGTIMES)
                   2891:                    n = NUMCBUGTIMES;
                   2892:                needsp = 0;
                   2893:                for (i = 0; i < n; i++) {
                   2894:                        if ((i & 0x1) == 0) {
                   2895:                            (void) fprintf(fp, "\n");
                   2896:                        } else {
                   2897:                                for (;needsp > 0; needsp--)
                   2898:                                    putc(' ', fp);
                   2899:                        }
                   2900:                        NTOHL_FP(&cl->times[i], &ts);
                   2901:                        if (s & (1 << i)) {
                   2902:                                (void) fprintf(fp, "%17s",
                   2903:                                               lfptoa(&ts, 6));
                   2904:                                needsp = 22;
                   2905:                        } else {
                   2906:                                (void) fprintf(fp, "%37s",
                   2907:                                               uglydate(&ts));
                   2908:                                needsp = 2;
                   2909:                        }
                   2910:                }
                   2911:                (void) fprintf(fp, "\n");
                   2912:                if (items > 0) {
                   2913:                        cl++;
                   2914:                        (void) fprintf(fp, "\n");
                   2915:                }
                   2916:        }
                   2917: }
                   2918: 
                   2919: 
                   2920: /*
                   2921:  * kerninfo - display the kernel pll/pps variables
                   2922:  */
                   2923: static void
                   2924: kerninfo(
                   2925:        struct parse *pcmd,
                   2926:        FILE *fp
                   2927:        )
                   2928: {
                   2929:        struct info_kernel *ik;
                   2930:        int items;
                   2931:        int itemsize;
                   2932:        int res;
                   2933:        unsigned status;
                   2934:        double tscale = 1e-6;
                   2935: 
                   2936: again:
                   2937:        res = doquery(impl_ver, REQ_GET_KERNEL, 0, 0, 0, (char *)NULL,
                   2938:                      &items, &itemsize, (void *)&ik, 0, 
                   2939:                      sizeof(struct info_kernel));
                   2940: 
                   2941:        if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
                   2942:                impl_ver = IMPL_XNTPD_OLD;
                   2943:                goto again;
                   2944:        }
                   2945: 
                   2946:        if (res != 0)
                   2947:            return;
                   2948:        if (!check1item(items, fp))
                   2949:            return;
                   2950:        if (!checkitemsize(itemsize, sizeof(struct info_kernel)))
                   2951:            return;
                   2952: 
                   2953:        status = ntohs(ik->status) & 0xffff;
                   2954:        /*
                   2955:         * pll variables. We know more than we should about the NANO bit.
                   2956:         */
                   2957: #ifdef STA_NANO
                   2958:        if (status & STA_NANO)
                   2959:                tscale = 1e-9;
                   2960: #endif
                   2961:        (void)fprintf(fp, "pll offset:           %g s\n",
                   2962:            (int32)ntohl(ik->offset) * tscale);
                   2963:        (void)fprintf(fp, "pll frequency:        %s ppm\n",
                   2964:            fptoa((s_fp)ntohl(ik->freq), 3));
                   2965:        (void)fprintf(fp, "maximum error:        %g s\n",
                   2966:            (u_long)ntohl(ik->maxerror) * 1e-6);
                   2967:        (void)fprintf(fp, "estimated error:      %g s\n",
                   2968:            (u_long)ntohl(ik->esterror) * 1e-6);
                   2969:        (void)fprintf(fp, "status:               %04x ", status);
                   2970: #ifdef STA_PLL
                   2971:        if (status & STA_PLL) (void)fprintf(fp, " pll");
                   2972: #endif
                   2973: #ifdef STA_PPSFREQ
                   2974:        if (status & STA_PPSFREQ) (void)fprintf(fp, " ppsfreq");
                   2975: #endif
                   2976: #ifdef STA_PPSTIME
                   2977:        if (status & STA_PPSTIME) (void)fprintf(fp, " ppstime");
                   2978: #endif
                   2979: #ifdef STA_FLL
                   2980:        if (status & STA_FLL) (void)fprintf(fp, " fll");
                   2981: #endif
                   2982: #ifdef STA_INS
                   2983:        if (status & STA_INS) (void)fprintf(fp, " ins");
                   2984: #endif
                   2985: #ifdef STA_DEL
                   2986:        if (status & STA_DEL) (void)fprintf(fp, " del");
                   2987: #endif
                   2988: #ifdef STA_UNSYNC
                   2989:        if (status & STA_UNSYNC) (void)fprintf(fp, " unsync");
                   2990: #endif
                   2991: #ifdef STA_FREQHOLD
                   2992:        if (status & STA_FREQHOLD) (void)fprintf(fp, " freqhold");
                   2993: #endif
                   2994: #ifdef STA_PPSSIGNAL
                   2995:        if (status & STA_PPSSIGNAL) (void)fprintf(fp, " ppssignal");
                   2996: #endif
                   2997: #ifdef STA_PPSJITTER
                   2998:        if (status & STA_PPSJITTER) (void)fprintf(fp, " ppsjitter");
                   2999: #endif
                   3000: #ifdef STA_PPSWANDER
                   3001:        if (status & STA_PPSWANDER) (void)fprintf(fp, " ppswander");
                   3002: #endif
                   3003: #ifdef STA_PPSERROR
                   3004:        if (status & STA_PPSERROR) (void)fprintf(fp, " ppserror");
                   3005: #endif
                   3006: #ifdef STA_CLOCKERR
                   3007:        if (status & STA_CLOCKERR) (void)fprintf(fp, " clockerr");
                   3008: #endif
                   3009: #ifdef STA_NANO
                   3010:        if (status & STA_NANO) (void)fprintf(fp, " nano");
                   3011: #endif
                   3012: #ifdef STA_MODE
                   3013:        if (status & STA_MODE) (void)fprintf(fp, " mode=fll");
                   3014: #endif
                   3015: #ifdef STA_CLK
                   3016:        if (status & STA_CLK) (void)fprintf(fp, " src=B");
                   3017: #endif
                   3018:        (void)fprintf(fp, "\n");
                   3019:        (void)fprintf(fp, "pll time constant:    %ld\n",
                   3020:            (u_long)ntohl(ik->constant));
                   3021:        (void)fprintf(fp, "precision:            %g s\n",
                   3022:            (u_long)ntohl(ik->precision) * tscale);
                   3023:        (void)fprintf(fp, "frequency tolerance:  %s ppm\n",
                   3024:            fptoa((s_fp)ntohl(ik->tolerance), 0));
                   3025: 
                   3026:        /*
                   3027:         * For backwards compatibility (ugh), we find the pps variables
                   3028:         * only if the shift member is nonzero.
                   3029:         */
                   3030:        if (!ik->shift)
                   3031:            return;
                   3032: 
                   3033:        /*
                   3034:         * pps variables
                   3035:         */
                   3036:        (void)fprintf(fp, "pps frequency:        %s ppm\n",
                   3037:            fptoa((s_fp)ntohl(ik->ppsfreq), 3));
                   3038:        (void)fprintf(fp, "pps stability:        %s ppm\n",
                   3039:            fptoa((s_fp)ntohl(ik->stabil), 3));
                   3040:        (void)fprintf(fp, "pps jitter:           %g s\n",
                   3041:            (u_long)ntohl(ik->jitter) * tscale);
                   3042:        (void)fprintf(fp, "calibration interval: %d s\n",
                   3043:                      1 << ntohs(ik->shift));
                   3044:        (void)fprintf(fp, "calibration cycles:   %ld\n",
                   3045:                      (u_long)ntohl(ik->calcnt));
                   3046:        (void)fprintf(fp, "jitter exceeded:      %ld\n",
                   3047:                      (u_long)ntohl(ik->jitcnt));
                   3048:        (void)fprintf(fp, "stability exceeded:   %ld\n",
                   3049:                      (u_long)ntohl(ik->stbcnt));
                   3050:        (void)fprintf(fp, "calibration errors:   %ld\n",
                   3051:                      (u_long)ntohl(ik->errcnt));
                   3052: }
                   3053: 
                   3054: #define IF_LIST_FMT     "%2d %c %48s %c %c %12.12s %03lx %3lu %2lu %5lu %5lu %5lu %2lu %3lu %7lu\n"
                   3055: #define IF_LIST_FMT_STR "%2s %c %48s %c %c %12.12s %3s %3s %2s %5s %5s %5s %2s %3s %7s\n"
                   3056: #define IF_LIST_AFMT_STR "     %48s %c\n"
                   3057: #define IF_LIST_LABELS  "#", 'A', "Address/Mask/Broadcast", 'T', 'E', "IF name", "Flg", "TL", "#M", "recv", "sent", "drop", "S", "PC", "uptime"
                   3058: #define IF_LIST_LINE    "==================================================================================================================\n"
                   3059: 
                   3060: static void
                   3061: iflist(
                   3062:        FILE *fp,
                   3063:        struct info_if_stats *ifs,
                   3064:        int items,
                   3065:        int itemsize,
                   3066:        int res
                   3067:        )
                   3068: {
                   3069:        static char *actions = "?.+-";
                   3070:        sockaddr_u saddr;
                   3071: 
                   3072:        if (res != 0)
                   3073:            return;
                   3074: 
                   3075:        if (!checkitems(items, fp))
                   3076:            return;
                   3077: 
                   3078:        if (!checkitemsize(itemsize, sizeof(struct info_if_stats)))
                   3079:            return;
                   3080: 
                   3081:        fprintf(fp, IF_LIST_FMT_STR, IF_LIST_LABELS);
                   3082:        fprintf(fp, IF_LIST_LINE);
                   3083:        
                   3084:        while (items > 0) {
                   3085:                SET_ADDR(saddr, ntohl(ifs->v6_flag), 
                   3086:                         ifs->unaddr.addr.s_addr, ifs->unaddr.addr6);
                   3087:                fprintf(fp, IF_LIST_FMT,
                   3088:                        ntohl(ifs->ifnum),
                   3089:                        actions[(ifs->action >= 1 && ifs->action < 4) ? ifs->action : 0],
                   3090:                        stoa((&saddr)), 'A',
                   3091:                        ifs->ignore_packets ? 'D' : 'E',
                   3092:                        ifs->name,
                   3093:                        (u_long)ntohl(ifs->flags),
                   3094:                        (u_long)ntohl(ifs->last_ttl),
                   3095:                        (u_long)ntohl(ifs->num_mcast),
                   3096:                        (u_long)ntohl(ifs->received),
                   3097:                        (u_long)ntohl(ifs->sent),
                   3098:                        (u_long)ntohl(ifs->notsent),
                   3099:                        (u_long)ntohl(ifs->scopeid),
                   3100:                        (u_long)ntohl(ifs->peercnt),
                   3101:                        (u_long)ntohl(ifs->uptime));
                   3102: 
                   3103:                SET_ADDR(saddr, ntohl(ifs->v6_flag), 
                   3104:                         ifs->unmask.addr.s_addr, ifs->unmask.addr6);
                   3105:                fprintf(fp, IF_LIST_AFMT_STR, stoa(&saddr), 'M');
                   3106: 
                   3107:                if (!ntohl(ifs->v6_flag) && ntohl(ifs->flags) & (INT_BCASTOPEN)) {
                   3108:                        SET_ADDR(saddr, ntohl(ifs->v6_flag), 
                   3109:                                 ifs->unbcast.addr.s_addr, ifs->unbcast.addr6);
                   3110:                        fprintf(fp, IF_LIST_AFMT_STR, stoa(&saddr), 'B');
                   3111: 
                   3112:                }
                   3113: 
                   3114:                ifs++;
                   3115:                items--;
                   3116:        }
                   3117: }
                   3118: 
                   3119: /*ARGSUSED*/
                   3120: static void
                   3121: get_if_stats(
                   3122:        struct parse *pcmd,
                   3123:        FILE *fp
                   3124:        )
                   3125: {
                   3126:        struct info_if_stats *ifs;
                   3127:        int items;
                   3128:        int itemsize;
                   3129:        int res;
                   3130: 
                   3131:        res = doquery(impl_ver, REQ_IF_STATS, 1, 0, 0, (char *)NULL, &items,
                   3132:                      &itemsize, (void *)&ifs, 0, 
                   3133:                      sizeof(struct info_if_stats));
                   3134:        iflist(fp, ifs, items, itemsize, res);
                   3135: }
                   3136: 
                   3137: /*ARGSUSED*/
                   3138: static void
                   3139: do_if_reload(
                   3140:        struct parse *pcmd,
                   3141:        FILE *fp
                   3142:        )
                   3143: {
                   3144:        struct info_if_stats *ifs;
                   3145:        int items;
                   3146:        int itemsize;
                   3147:        int res;
                   3148: 
                   3149:        res = doquery(impl_ver, REQ_IF_RELOAD, 1, 0, 0, (char *)NULL, &items,
                   3150:                      &itemsize, (void *)&ifs, 0, 
                   3151:                      sizeof(struct info_if_stats));
                   3152:        iflist(fp, ifs, items, itemsize, res);
                   3153: }

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