Annotation of embedaddon/ntp/ntpq/ntpq-subs.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * ntpq_ops.c - subroutines which are called to perform operations by ntpq
                      3:  */
                      4: 
                      5: #include <stdio.h>
                      6: #include <ctype.h>
                      7: #include <sys/types.h>
                      8: #include <sys/time.h>
                      9: 
                     10: #include "ntp_stdlib.h"
                     11: #include "ntpq.h"
                     12: #include "ntpq-opts.h"
                     13: 
                     14: extern char *  chosts[];
                     15: extern char currenthost[];
                     16: extern int currenthostisnum;
                     17: extern int     numhosts;
                     18: int    maxhostlen;
                     19: 
                     20: /*
                     21:  * Declarations for command handlers in here
                     22:  */
                     23: static associd_t checkassocid  (u_int32);
                     24: static struct varlist *findlistvar (struct varlist *, char *);
                     25: static void    doaddvlist      (struct varlist *, const char *);
                     26: static void    dormvlist       (struct varlist *, const char *);
                     27: static void    doclearvlist    (struct varlist *);
                     28: static void    makequerydata   (struct varlist *, int *, char *);
                     29: static int     doquerylist     (struct varlist *, int, associd_t, int,
                     30:                                 u_short *, int *, const char **);
                     31: static void    doprintvlist    (struct varlist *, FILE *);
                     32: static void    addvars         (struct parse *, FILE *);
                     33: static void    rmvars          (struct parse *, FILE *);
                     34: static void    clearvars       (struct parse *, FILE *);
                     35: static void    showvars        (struct parse *, FILE *);
                     36: static int     dolist          (struct varlist *, associd_t, int, int,
                     37:                                 FILE *);
                     38: static void    readlist        (struct parse *, FILE *);
                     39: static void    writelist       (struct parse *, FILE *);
                     40: static void    readvar         (struct parse *, FILE *);
                     41: static void    writevar        (struct parse *, FILE *);
                     42: static void    clocklist       (struct parse *, FILE *);
                     43: static void    clockvar        (struct parse *, FILE *);
                     44: static int     findassidrange  (u_int32, u_int32, int *, int *);
                     45: static void    mreadlist       (struct parse *, FILE *);
                     46: static void    mreadvar        (struct parse *, FILE *);
                     47: static int     dogetassoc      (FILE *);
                     48: static void    printassoc      (int, FILE *);
                     49: static void    associations    (struct parse *, FILE *);
                     50: static void    lassociations   (struct parse *, FILE *);
                     51: static void    passociations   (struct parse *, FILE *);
                     52: static void    lpassociations  (struct parse *, FILE *);
                     53: 
                     54: #ifdef UNUSED
                     55: static void    radiostatus (struct parse *, FILE *);
                     56: #endif /* UNUSED */
                     57: 
                     58: static void    pstatus         (struct parse *, FILE *);
                     59: static long    when            (l_fp *, l_fp *, l_fp *);
                     60: static char *  prettyinterval  (char *, size_t, long);
                     61: static int     doprintpeers    (struct varlist *, int, int, int, const char *, FILE *, int);
                     62: static int     dogetpeers      (struct varlist *, associd_t, FILE *, int);
                     63: static void    dopeers         (int, FILE *, int);
                     64: static void    peers           (struct parse *, FILE *);
                     65: static void    lpeers          (struct parse *, FILE *);
                     66: static void    doopeers        (int, FILE *, int);
                     67: static void    opeers          (struct parse *, FILE *);
                     68: static void    lopeers         (struct parse *, FILE *);
                     69: static  void   config          (struct parse *, FILE *);
                     70: static         void    saveconfig      (struct parse *, FILE *);
                     71: static  void   config_from_file(struct parse *, FILE *);
                     72: 
                     73: 
                     74: /*
                     75:  * Commands we understand.     Ntpdc imports this.
                     76:  */
                     77: struct xcmd opcmds[] = {
                     78:        { "saveconfig", saveconfig, { NTP_STR, NO, NO, NO },
                     79:                { "filename", "", "", ""}, 
                     80:                "save ntpd configuration to file, . for current config file"},
                     81:        { "associations", associations, {  NO, NO, NO, NO },
                     82:          { "", "", "", "" },
                     83:          "print list of association ID's and statuses for the server's peers" },
                     84:        { "passociations", passociations,   {  NO, NO, NO, NO },
                     85:          { "", "", "", "" },
                     86:          "print list of associations returned by last associations command" },
                     87:        { "lassociations", lassociations,   {  NO, NO, NO, NO },
                     88:          { "", "", "", "" },
                     89:          "print list of associations including all client information" },
                     90:        { "lpassociations", lpassociations, {  NO, NO, NO, NO },
                     91:          { "", "", "", "" },
                     92:          "print last obtained list of associations, including client information" },
                     93:        { "addvars",    addvars,    { NTP_STR, NO, NO, NO },
                     94:          { "name[=value][,...]", "", "", "" },
                     95:          "add variables to the variable list or change their values" },
                     96:        { "rmvars", rmvars,     { NTP_STR, NO, NO, NO },
                     97:          { "name[,...]", "", "", "" },
                     98:          "remove variables from the variable list" },
                     99:        { "clearvars",  clearvars,  { NO, NO, NO, NO },
                    100:          { "", "", "", "" },
                    101:          "remove all variables from the variable list" },
                    102:        { "showvars",   showvars,   { NO, NO, NO, NO },
                    103:          { "", "", "", "" },
                    104:          "print variables on the variable list" },
                    105:        { "readlist",   readlist,   { OPT|NTP_UINT, NO, NO, NO },
                    106:          { "assocID", "", "", "" },
                    107:          "read the system or peer variables included in the variable list" },
                    108:        { "rl",     readlist,   { OPT|NTP_UINT, NO, NO, NO },
                    109:          { "assocID", "", "", "" },
                    110:          "read the system or peer variables included in the variable list" },
                    111:        { "writelist",  writelist,  { OPT|NTP_UINT, NO, NO, NO },
                    112:          { "assocID", "", "", "" },
                    113:          "write the system or peer variables included in the variable list" },
                    114:        { "readvar",    readvar,    { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
                    115:          { "assocID", "name=value[,...]", "", "" },
                    116:          "read system or peer variables" },
                    117:        { "rv",     readvar,    { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
                    118:          { "assocID", "name=value[,...]", "", "" },
                    119:          "read system or peer variables" },
                    120:        { "writevar",   writevar,   { NTP_UINT, NTP_STR, NO, NO },
                    121:          { "assocID", "name=value,[...]", "", "" },
                    122:          "write system or peer variables" },
                    123:        { "mreadlist",  mreadlist,  { NTP_UINT, NTP_UINT, NO, NO },
                    124:          { "assocID", "assocID", "", "" },
                    125:          "read the peer variables in the variable list for multiple peers" },
                    126:        { "mrl",    mreadlist,  { NTP_UINT, NTP_UINT, NO, NO },
                    127:          { "assocID", "assocID", "", "" },
                    128:          "read the peer variables in the variable list for multiple peers" },
                    129:        { "mreadvar",   mreadvar,   { NTP_UINT, NTP_UINT, OPT|NTP_STR, NO },
                    130:          { "assocID", "assocID", "name=value[,...]", "" },
                    131:          "read peer variables from multiple peers" },
                    132:        { "mrv",    mreadvar,   { NTP_UINT, NTP_UINT, OPT|NTP_STR, NO },
                    133:          { "assocID", "assocID", "name=value[,...]", "" },
                    134:          "read peer variables from multiple peers" },
                    135:        { "clocklist",  clocklist,  { OPT|NTP_UINT, NO, NO, NO },
                    136:          { "assocID", "", "", "" },
                    137:          "read the clock variables included in the variable list" },
                    138:        { "cl",     clocklist,  { OPT|NTP_UINT, NO, NO, NO },
                    139:          { "assocID", "", "", "" },
                    140:          "read the clock variables included in the variable list" },
                    141:        { "clockvar",   clockvar,   { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
                    142:          { "assocID", "name=value[,...]", "", "" },
                    143:          "read clock variables" },
                    144:        { "cv",     clockvar,   { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
                    145:          { "assocID", "name=value[,...]", "", "" },
                    146:          "read clock variables" },
                    147:        { "pstatus",    pstatus,    { NTP_UINT, NO, NO, NO },
                    148:          { "assocID", "", "", "" },
                    149:          "print status information returned for a peer" },
                    150:        { "peers",  peers,      { OPT|IP_VERSION, NO, NO, NO },
                    151:          { "-4|-6", "", "", "" },
                    152:          "obtain and print a list of the server's peers [IP version]" },
                    153:        { "lpeers", lpeers,     { OPT|IP_VERSION, NO, NO, NO },
                    154:          { "-4|-6", "", "", "" },
                    155:          "obtain and print a list of all peers and clients [IP version]" },
                    156:        { "opeers", opeers,     { OPT|IP_VERSION, NO, NO, NO },
                    157:          { "-4|-6", "", "", "" },
                    158:          "print peer list the old way, with dstadr shown rather than refid [IP version]" },
                    159:        { "lopeers", lopeers,   { OPT|IP_VERSION, NO, NO, NO },
                    160:          { "-4|-6", "", "", "" },
                    161:          "obtain and print a list of all peers and clients showing dstadr [IP version]" },
                    162:        { ":config", config,   { NTP_STR, NO, NO, NO },
                    163:          { "<configuration command line>", "", "", "" },
                    164:          "send a remote configuration command to ntpd" },
                    165:        { "config-from-file", config_from_file, { NTP_STR, NO, NO, NO },
                    166:          { "<configuration filename>", "", "", "" },
                    167:          "configure ntpd using the configuration filename" },
                    168:        { 0,            0,              { NO, NO, NO, NO },
                    169:          { "-4|-6", "", "", "" }, "" }
                    170: };
                    171: 
                    172: 
                    173: /*
                    174:  * Variable list data space
                    175:  */
                    176: #define MAXLINE     512  /* maximum length of a line */
                    177: #define MAXLIST        64      /* maximum number of variables in list */
                    178: #define LENHOSTNAME 256 /* host name is 256 characters long */
                    179: /*
                    180:  * Old CTL_PST defines for version 2.
                    181:  */
                    182: #define OLD_CTL_PST_CONFIG             0x80
                    183: #define OLD_CTL_PST_AUTHENABLE         0x40
                    184: #define OLD_CTL_PST_AUTHENTIC          0x20
                    185: #define OLD_CTL_PST_REACH              0x10
                    186: #define OLD_CTL_PST_SANE               0x08
                    187: #define OLD_CTL_PST_DISP               0x04
                    188: 
                    189: #define OLD_CTL_PST_SEL_REJECT         0
                    190: #define OLD_CTL_PST_SEL_SELCAND        1
                    191: #define OLD_CTL_PST_SEL_SYNCCAND       2
                    192: #define OLD_CTL_PST_SEL_SYSPEER        3
                    193: 
                    194: char flash2[] = " .+*    "; /* flash decode for version 2 */
                    195: char flash3[] = " x.-+#*o"; /* flash decode for peer status version 3 */
                    196: 
                    197: struct varlist {
                    198:        char *name;
                    199:        char *value;
                    200: } g_varlist[MAXLIST] = { { 0, 0 } };
                    201: 
                    202: /*
                    203:  * Imported from ntpq.c
                    204:  */
                    205: extern int showhostnames;
                    206: extern int rawmode;
                    207: extern struct servent *server_entry;
                    208: extern struct association assoc_cache[];
                    209: extern int numassoc;
                    210: extern u_char pktversion;
                    211: extern struct ctl_var peer_var[];
                    212: 
                    213: /*
                    214:  * For quick string comparisons
                    215:  */
                    216: #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
                    217: 
                    218: 
                    219: /*
                    220:  * checkassocid - return the association ID, checking to see if it is valid
                    221:  */
                    222: static associd_t
                    223: checkassocid(
                    224:        u_int32 value
                    225:        )
                    226: {
                    227:        associd_t       associd;
                    228:        u_long          ulvalue;
                    229: 
                    230:        associd = (associd_t)value;
                    231:        if (0 == associd || value != associd) {
                    232:                ulvalue = value;
                    233:                fprintf(stderr,
                    234:                        "***Invalid association ID %lu specified\n",
                    235:                        ulvalue);
                    236:                return 0;
                    237:        }
                    238: 
                    239:        return associd;
                    240: }
                    241: 
                    242: 
                    243: /*
                    244:  * findlistvar - look for the named variable in a list and return if found
                    245:  */
                    246: static struct varlist *
                    247: findlistvar(
                    248:        struct varlist *list,
                    249:        char *name
                    250:        )
                    251: {
                    252:        register struct varlist *vl;
                    253: 
                    254:        for (vl = list; vl < list + MAXLIST && vl->name != 0; vl++)
                    255:                if (STREQ(name, vl->name))
                    256:                return vl;
                    257:        if (vl < list + MAXLIST)
                    258:                return vl;
                    259:        return (struct varlist *)0;
                    260: }
                    261: 
                    262: 
                    263: /*
                    264:  * doaddvlist - add variable(s) to the variable list
                    265:  */
                    266: static void
                    267: doaddvlist(
                    268:        struct varlist *vlist,
                    269:        const char *vars
                    270:        )
                    271: {
                    272:        register struct varlist *vl;
                    273:        int len;
                    274:        char *name;
                    275:        char *value;
                    276: 
                    277:        len = strlen(vars);
                    278:        while (nextvar(&len, &vars, &name, &value)) {
                    279:                vl = findlistvar(vlist, name);
                    280:                if (vl == 0) {
                    281:                        (void) fprintf(stderr, "Variable list full\n");
                    282:                        return;
                    283:                }
                    284: 
                    285:                if (vl->name == 0) {
                    286:                        vl->name = estrdup(name);
                    287:                } else if (vl->value != 0) {
                    288:                        free(vl->value);
                    289:                        vl->value = 0;
                    290:                }
                    291: 
                    292:                if (value != 0)
                    293:                        vl->value = estrdup(value);
                    294:        }
                    295: }
                    296: 
                    297: 
                    298: /*
                    299:  * dormvlist - remove variable(s) from the variable list
                    300:  */
                    301: static void
                    302: dormvlist(
                    303:        struct varlist *vlist,
                    304:        const char *vars
                    305:        )
                    306: {
                    307:        register struct varlist *vl;
                    308:        int len;
                    309:        char *name;
                    310:        char *value;
                    311: 
                    312:        len = strlen(vars);
                    313:        while (nextvar(&len, &vars, &name, &value)) {
                    314:                vl = findlistvar(vlist, name);
                    315:                if (vl == 0 || vl->name == 0) {
                    316:                        (void) fprintf(stderr, "Variable `%s' not found\n",
                    317:                                       name);
                    318:                } else {
                    319:                        free((void *)vl->name);
                    320:                        if (vl->value != 0)
                    321:                            free(vl->value);
                    322:                        for ( ; (vl+1) < (g_varlist + MAXLIST)
                    323:                                      && (vl+1)->name != 0; vl++) {
                    324:                                vl->name = (vl+1)->name;
                    325:                                vl->value = (vl+1)->value;
                    326:                        }
                    327:                        vl->name = vl->value = 0;
                    328:                }
                    329:        }
                    330: }
                    331: 
                    332: 
                    333: /*
                    334:  * doclearvlist - clear a variable list
                    335:  */
                    336: static void
                    337: doclearvlist(
                    338:        struct varlist *vlist
                    339:        )
                    340: {
                    341:        register struct varlist *vl;
                    342: 
                    343:        for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) {
                    344:                free((void *)vl->name);
                    345:                vl->name = 0;
                    346:                if (vl->value != 0) {
                    347:                        free(vl->value);
                    348:                        vl->value = 0;
                    349:                }
                    350:        }
                    351: }
                    352: 
                    353: 
                    354: /*
                    355:  * makequerydata - form a data buffer to be included with a query
                    356:  */
                    357: static void
                    358: makequerydata(
                    359:        struct varlist *vlist,
                    360:        int *datalen,
                    361:        char *data
                    362:        )
                    363: {
                    364:        register struct varlist *vl;
                    365:        register char *cp, *cpend;
                    366:        register int namelen, valuelen;
                    367:        register int totallen;
                    368: 
                    369:        cp = data;
                    370:        cpend = data + *datalen;
                    371: 
                    372:        for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) {
                    373:                namelen = strlen(vl->name);
                    374:                if (vl->value == 0)
                    375:                        valuelen = 0;
                    376:                else
                    377:                        valuelen = strlen(vl->value);
                    378:                totallen = namelen + valuelen + (valuelen != 0) + (cp != data);
                    379:                if (cp + totallen > cpend)
                    380:                        break;
                    381: 
                    382:                if (cp != data)
                    383:                        *cp++ = ',';
                    384:                memmove(cp, vl->name, (unsigned)namelen);
                    385:                cp += namelen;
                    386:                if (valuelen != 0) {
                    387:                        *cp++ = '=';
                    388:                        memmove(cp, vl->value, (unsigned)valuelen);
                    389:                        cp += valuelen;
                    390:                }
                    391:        }
                    392:        *datalen = cp - data;
                    393: }
                    394: 
                    395: 
                    396: /*
                    397:  * doquerylist - send a message including variables in a list
                    398:  */
                    399: static int
                    400: doquerylist(
                    401:        struct varlist *vlist,
                    402:        int op,
                    403:        associd_t associd,
                    404:        int auth,
                    405:        u_short *rstatus,
                    406:        int *dsize,
                    407:        const char **datap
                    408:        )
                    409: {
                    410:        char data[CTL_MAX_DATA_LEN];
                    411:        int datalen;
                    412: 
                    413:        datalen = sizeof(data);
                    414:        makequerydata(vlist, &datalen, data);
                    415: 
                    416:        return doquery(op, associd, auth, datalen, data, rstatus,
                    417:                           dsize, datap);
                    418: }
                    419: 
                    420: 
                    421: /*
                    422:  * doprintvlist - print the variables on a list
                    423:  */
                    424: static void
                    425: doprintvlist(
                    426:        struct varlist *vlist,
                    427:        FILE *fp
                    428:        )
                    429: {
                    430:        register struct varlist *vl;
                    431: 
                    432:        if (vlist->name == 0) {
                    433:                (void) fprintf(fp, "No variables on list\n");
                    434:        } else {
                    435:                for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) {
                    436:                        if (vl->value == 0) {
                    437:                                (void) fprintf(fp, "%s\n", vl->name);
                    438:                        } else {
                    439:                                (void) fprintf(fp, "%s=%s\n",
                    440:                                                   vl->name, vl->value);
                    441:                        }
                    442:                }
                    443:        }
                    444: }
                    445: 
                    446: /*
                    447:  * addvars - add variables to the variable list
                    448:  */
                    449: /*ARGSUSED*/
                    450: static void
                    451: addvars(
                    452:        struct parse *pcmd,
                    453:        FILE *fp
                    454:        )
                    455: {
                    456:        doaddvlist(g_varlist, pcmd->argval[0].string);
                    457: }
                    458: 
                    459: 
                    460: /*
                    461:  * rmvars - remove variables from the variable list
                    462:  */
                    463: /*ARGSUSED*/
                    464: static void
                    465: rmvars(
                    466:        struct parse *pcmd,
                    467:        FILE *fp
                    468:        )
                    469: {
                    470:        dormvlist(g_varlist, pcmd->argval[0].string);
                    471: }
                    472: 
                    473: 
                    474: /*
                    475:  * clearvars - clear the variable list
                    476:  */
                    477: /*ARGSUSED*/
                    478: static void
                    479: clearvars(
                    480:        struct parse *pcmd,
                    481:        FILE *fp
                    482:        )
                    483: {
                    484:        doclearvlist(g_varlist);
                    485: }
                    486: 
                    487: 
                    488: /*
                    489:  * showvars - show variables on the variable list
                    490:  */
                    491: /*ARGSUSED*/
                    492: static void
                    493: showvars(
                    494:        struct parse *pcmd,
                    495:        FILE *fp
                    496:        )
                    497: {
                    498:        doprintvlist(g_varlist, fp);
                    499: }
                    500: 
                    501: 
                    502: /*
                    503:  * dolist - send a request with the given list of variables
                    504:  */
                    505: static int
                    506: dolist(
                    507:        struct varlist *vlist,
                    508:        associd_t associd,
                    509:        int op,
                    510:        int type,
                    511:        FILE *fp
                    512:        )
                    513: {
                    514:        const char *datap;
                    515:        int res;
                    516:        int dsize;
                    517:        u_short rstatus;
                    518:        int quiet;
                    519: 
                    520:        /*
                    521:         * if we're asking for specific variables don't include the
                    522:         * status header line in the output.
                    523:         */
                    524:        if (old_rv)
                    525:                quiet = 0;
                    526:        else
                    527:                quiet = (vlist->name != NULL);
                    528: 
                    529:        res = doquerylist(vlist, op, associd, 0, &rstatus, &dsize, &datap);
                    530: 
                    531:        if (res != 0)
                    532:                return 0;
                    533: 
                    534:        if (numhosts > 1)
                    535:                (void) fprintf(fp, "server=%s ", currenthost);
                    536:        if (dsize == 0) {
                    537:                if (associd == 0)
                    538:                        (void) fprintf(fp, "No system%s variables returned\n",
                    539:                                   (type == TYPE_CLOCK) ? " clock" : "");
                    540:                else
                    541:                        (void) fprintf(fp,
                    542:                                   "No information returned for%s association %u\n",
                    543:                                   (type == TYPE_CLOCK) ? " clock" : "", associd);
                    544:                return 1;
                    545:        }
                    546: 
                    547:        if (!quiet)
                    548:                fprintf(fp,"associd=%d ",associd);
                    549:        printvars(dsize, datap, (int)rstatus, type, quiet, fp);
                    550:        return 1;
                    551: }
                    552: 
                    553: 
                    554: /*
                    555:  * readlist - send a read variables request with the variables on the list
                    556:  */
                    557: static void
                    558: readlist(
                    559:        struct parse *pcmd,
                    560:        FILE *fp
                    561:        )
                    562: {
                    563:        associd_t       associd;
                    564:        int             type;
                    565: 
                    566:        if (pcmd->nargs == 0) {
                    567:                associd = 0;
                    568:        } else {
                    569:          /* HMS: I think we want the u_int32 target here, not the u_long */
                    570:                if (pcmd->argval[0].uval == 0)
                    571:                        associd = 0;
                    572:                else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
                    573:                        return;
                    574:        }
                    575: 
                    576:        type = (0 == associd)
                    577:                   ? TYPE_SYS
                    578:                   : TYPE_PEER;
                    579:        dolist(g_varlist, associd, CTL_OP_READVAR, type, fp);
                    580: }
                    581: 
                    582: 
                    583: /*
                    584:  * writelist - send a write variables request with the variables on the list
                    585:  */
                    586: static void
                    587: writelist(
                    588:        struct parse *pcmd,
                    589:        FILE *fp
                    590:        )
                    591: {
                    592:        const char *datap;
                    593:        int res;
                    594:        associd_t associd;
                    595:        int dsize;
                    596:        u_short rstatus;
                    597: 
                    598:        if (pcmd->nargs == 0) {
                    599:                associd = 0;
                    600:        } else {
                    601:                /* HMS: Do we really want uval here? */
                    602:                if (pcmd->argval[0].uval == 0)
                    603:                        associd = 0;
                    604:                else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
                    605:                        return;
                    606:        }
                    607: 
                    608:        res = doquerylist(g_varlist, CTL_OP_WRITEVAR, associd, 1, &rstatus,
                    609:                          &dsize, &datap);
                    610: 
                    611:        if (res != 0)
                    612:                return;
                    613: 
                    614:        if (numhosts > 1)
                    615:                (void) fprintf(fp, "server=%s ", currenthost);
                    616:        if (dsize == 0)
                    617:                (void) fprintf(fp, "done! (no data returned)\n");
                    618:        else {
                    619:                (void) fprintf(fp,"associd=%d ",associd);
                    620:                printvars(dsize, datap, (int)rstatus,
                    621:                          (associd != 0) ? TYPE_PEER : TYPE_SYS, 0, fp);
                    622:        }
                    623:        return;
                    624: }
                    625: 
                    626: 
                    627: /*
                    628:  * readvar - send a read variables request with the specified variables
                    629:  */
                    630: static void
                    631: readvar(
                    632:        struct parse *pcmd,
                    633:        FILE *fp
                    634:        )
                    635: {
                    636:        associd_t       associd;
                    637:        int             type;
                    638:        struct varlist  tmplist[MAXLIST];
                    639: 
                    640: 
                    641:        /* HMS: uval? */
                    642:        if (pcmd->nargs == 0 || pcmd->argval[0].uval == 0)
                    643:                associd = 0;
                    644:        else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
                    645:                return;
                    646: 
                    647:        memset(tmplist, 0, sizeof(tmplist));
                    648:        if (pcmd->nargs >= 2)
                    649:                doaddvlist(tmplist, pcmd->argval[1].string);
                    650: 
                    651:        type = (0 == associd)
                    652:                   ? TYPE_SYS
                    653:                   : TYPE_PEER;
                    654:        dolist(tmplist, associd, CTL_OP_READVAR, type, fp);
                    655: 
                    656:        doclearvlist(tmplist);
                    657: }
                    658: 
                    659: 
                    660: /*
                    661:  * writevar - send a write variables request with the specified variables
                    662:  */
                    663: static void
                    664: writevar(
                    665:        struct parse *pcmd,
                    666:        FILE *fp
                    667:        )
                    668: {
                    669:        const char *datap;
                    670:        int res;
                    671:        associd_t associd;
                    672:        int type;
                    673:        int dsize;
                    674:        u_short rstatus;
                    675:        struct varlist tmplist[MAXLIST];
                    676: 
                    677:        /* HMS: uval? */
                    678:        if (pcmd->argval[0].uval == 0)
                    679:                associd = 0;
                    680:        else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
                    681:                return;
                    682: 
                    683:        memset((char *)tmplist, 0, sizeof(tmplist));
                    684:        doaddvlist(tmplist, pcmd->argval[1].string);
                    685: 
                    686:        res = doquerylist(tmplist, CTL_OP_WRITEVAR, associd, 1, &rstatus,
                    687:                          &dsize, &datap);
                    688: 
                    689:        doclearvlist(tmplist);
                    690: 
                    691:        if (res != 0)
                    692:                return;
                    693: 
                    694:        if (numhosts > 1)
                    695:                fprintf(fp, "server=%s ", currenthost);
                    696:        if (dsize == 0)
                    697:                fprintf(fp, "done! (no data returned)\n");
                    698:        else {
                    699:                fprintf(fp,"associd=%d ",associd);
                    700:                type = (0 == associd)
                    701:                           ? TYPE_SYS
                    702:                           : TYPE_PEER;
                    703:                printvars(dsize, datap, (int)rstatus, type, 0, fp);
                    704:        }
                    705:        return;
                    706: }
                    707: 
                    708: 
                    709: /*
                    710:  * clocklist - send a clock variables request with the variables on the list
                    711:  */
                    712: static void
                    713: clocklist(
                    714:        struct parse *pcmd,
                    715:        FILE *fp
                    716:        )
                    717: {
                    718:        associd_t associd;
                    719: 
                    720:        /* HMS: uval? */
                    721:        if (pcmd->nargs == 0) {
                    722:                associd = 0;
                    723:        } else {
                    724:                if (pcmd->argval[0].uval == 0)
                    725:                        associd = 0;
                    726:                else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
                    727:                        return;
                    728:        }
                    729: 
                    730:        dolist(g_varlist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp);
                    731: }
                    732: 
                    733: 
                    734: /*
                    735:  * clockvar - send a clock variables request with the specified variables
                    736:  */
                    737: static void
                    738: clockvar(
                    739:        struct parse *pcmd,
                    740:        FILE *fp
                    741:        )
                    742: {
                    743:        associd_t associd;
                    744:        struct varlist tmplist[MAXLIST];
                    745: 
                    746:        /* HMS: uval? */
                    747:        if (pcmd->nargs == 0 || pcmd->argval[0].uval == 0)
                    748:                associd = 0;
                    749:        else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
                    750:                return;
                    751: 
                    752:        memset(tmplist, 0, sizeof(tmplist));
                    753:        if (pcmd->nargs >= 2)
                    754:                doaddvlist(tmplist, pcmd->argval[1].string);
                    755: 
                    756:        dolist(tmplist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp);
                    757: 
                    758:        doclearvlist(tmplist);
                    759: }
                    760: 
                    761: 
                    762: /*
                    763:  * findassidrange - verify a range of association ID's
                    764:  */
                    765: static int
                    766: findassidrange(
                    767:        u_int32 assid1,
                    768:        u_int32 assid2,
                    769:        int *from,
                    770:        int *to
                    771:        )
                    772: {
                    773:        associd_t       assids[2];
                    774:        int             ind[COUNTOF(assids)];
                    775:        int             i;
                    776:        size_t          a;
                    777: 
                    778:        assids[0] = checkassocid(assid1);
                    779:        if (0 == assids[0])
                    780:                return 0;
                    781:        assids[1] = checkassocid(assid2);
                    782:        if (0 == assids[1])
                    783:                return 0;
                    784: 
                    785:        for (a = 0; a < COUNTOF(assids); a++) {
                    786:                ind[a] = -1;
                    787:                for (i = 0; i < numassoc; i++)
                    788:                        if (assoc_cache[i].assid == assids[a])
                    789:                                ind[a] = i;
                    790:        }
                    791:        for (a = 0; a < COUNTOF(assids); a++)
                    792:                if (-1 == ind[a]) {
                    793:                        fprintf(stderr,
                    794:                                "***Association ID %u not found in list\n",
                    795:                                assids[a]);
                    796:                        return 0;
                    797:                }
                    798: 
                    799:        if (ind[0] < ind[1]) {
                    800:                *from = ind[0];
                    801:                *to = ind[1];
                    802:        } else {
                    803:                *to = ind[0];
                    804:                *from = ind[1];
                    805:        }
                    806:        return 1;
                    807: }
                    808: 
                    809: 
                    810: 
                    811: /*
                    812:  * mreadlist - send a read variables request for multiple associations
                    813:  */
                    814: static void
                    815: mreadlist(
                    816:        struct parse *pcmd,
                    817:        FILE *fp
                    818:        )
                    819: {
                    820:        int i;
                    821:        int from;
                    822:        int to;
                    823: 
                    824:        /* HMS: uval? */
                    825:        if (!findassidrange(pcmd->argval[0].uval, pcmd->argval[1].uval,
                    826:                                &from, &to))
                    827:                return;
                    828: 
                    829:        for (i = from; i <= to; i++) {
                    830:                if (i != from)
                    831:                        (void) fprintf(fp, "\n");
                    832:                if (!dolist(g_varlist, (int)assoc_cache[i].assid,
                    833:                                CTL_OP_READVAR, TYPE_PEER, fp))
                    834:                        return;
                    835:        }
                    836:        return;
                    837: }
                    838: 
                    839: 
                    840: /*
                    841:  * mreadvar - send a read variables request for multiple associations
                    842:  */
                    843: static void
                    844: mreadvar(
                    845:        struct parse *pcmd,
                    846:        FILE *fp
                    847:        )
                    848: {
                    849:        int i;
                    850:        int from;
                    851:        int to;
                    852:        struct varlist tmplist[MAXLIST];
                    853:        struct varlist *pvars;
                    854: 
                    855:        /* HMS: uval? */
                    856:        if (!findassidrange(pcmd->argval[0].uval, pcmd->argval[1].uval,
                    857:                                &from, &to))
                    858:                return;
                    859: 
                    860:        if (pcmd->nargs >= 3) {
                    861:                memset(tmplist, 0, sizeof(tmplist));
                    862:                doaddvlist(tmplist, pcmd->argval[2].string);
                    863:                pvars = tmplist;
                    864:        } else {
                    865:                pvars = g_varlist;
                    866:        }
                    867: 
                    868:        for (i = from; i <= to; i++) {
                    869:                if (i != from)
                    870:                        fprintf(fp, "\n");
                    871:                if (!dolist(pvars, (int)assoc_cache[i].assid,
                    872:                            CTL_OP_READVAR, TYPE_PEER, fp))
                    873:                        break;
                    874:        }
                    875:        doclearvlist(tmplist);
                    876:        return;
                    877: }
                    878: 
                    879: 
                    880: /*
                    881:  * dogetassoc - query the host for its list of associations
                    882:  */
                    883: static int
                    884: dogetassoc(
                    885:        FILE *fp
                    886:        )
                    887: {
                    888:        const char *datap;
                    889:        int res;
                    890:        int dsize;
                    891:        u_short rstatus;
                    892: 
                    893:        res = doquery(CTL_OP_READSTAT, 0, 0, 0, (char *)0, &rstatus,
                    894:                          &dsize, &datap);
                    895: 
                    896:        if (res != 0)
                    897:                return 0;
                    898: 
                    899:        if (dsize == 0) {
                    900:                if (numhosts > 1)
                    901:                        (void) fprintf(fp, "server=%s ", currenthost);
                    902:                (void) fprintf(fp, "No association ID's returned\n");
                    903:                return 0;
                    904:        }
                    905: 
                    906:        if (dsize & 0x3) {
                    907:                if (numhosts > 1)
                    908:                        (void) fprintf(stderr, "server=%s ", currenthost);
                    909:                (void) fprintf(stderr,
                    910:                                   "***Server returned %d octets, should be multiple of 4\n",
                    911:                                   dsize);
                    912:                return 0;
                    913:        }
                    914: 
                    915:        numassoc = 0;
                    916:        while (dsize > 0) {
                    917:                assoc_cache[numassoc].assid = ntohs(*((const u_short *)datap));
                    918:                datap += sizeof(u_short);
                    919:                assoc_cache[numassoc].status = ntohs(*((const u_short *)datap));
                    920:                datap += sizeof(u_short);
                    921:                if (++numassoc >= MAXASSOC)
                    922:                        break;
                    923:                dsize -= sizeof(u_short) + sizeof(u_short);
                    924:        }
                    925:        sortassoc();
                    926:        return 1;
                    927: }
                    928: 
                    929: 
                    930: /*
                    931:  * printassoc - print the current list of associations
                    932:  */
                    933: static void
                    934: printassoc(
                    935:        int showall,
                    936:        FILE *fp
                    937:        )
                    938: {
                    939:        register char *bp;
                    940:        int i;
                    941:        u_char statval;
                    942:        int event;
                    943:        u_long event_count;
                    944:        const char *conf;
                    945:        const char *reach;
                    946:        const char *auth;
                    947:        const char *condition = "";
                    948:        const char *last_event;
                    949:        const char *cnt;
                    950:        char buf[128];
                    951: 
                    952:        if (numassoc == 0) {
                    953:                (void) fprintf(fp, "No association ID's in list\n");
                    954:                return;
                    955:        }
                    956: 
                    957:        /*
                    958:         * Output a header
                    959:         */
                    960:        (void) fprintf(fp,
                    961:                           "\nind assid status  conf reach auth condition  last_event cnt\n");
                    962:        (void) fprintf(fp,
                    963:                           "===========================================================\n");
                    964:        for (i = 0; i < numassoc; i++) {
                    965:                statval = (u_char) CTL_PEER_STATVAL(assoc_cache[i].status);
                    966:                if (!showall && !(statval & (CTL_PST_CONFIG|CTL_PST_REACH)))
                    967:                        continue;
                    968:                event = CTL_PEER_EVENT(assoc_cache[i].status);
                    969:                event_count = CTL_PEER_NEVNT(assoc_cache[i].status);
                    970:                if (statval & CTL_PST_CONFIG)
                    971:                        conf = "yes";
                    972:                else
                    973:                        conf = "no";
                    974:                if (statval & CTL_PST_BCAST) {
                    975:                        reach = "none";
                    976:                        if (statval & CTL_PST_AUTHENABLE)
                    977:                                auth = "yes";
                    978:                        else
                    979:                                auth = "none";
                    980:                } else {
                    981:                        if (statval & CTL_PST_REACH)
                    982:                                reach = "yes";
                    983:                        else
                    984:                                reach = "no";
                    985:                        if (statval & CTL_PST_AUTHENABLE) {
                    986:                                if (statval & CTL_PST_AUTHENTIC)
                    987:                                        auth = "ok ";
                    988:                                else
                    989:                                        auth = "bad";
                    990:                        } else {
                    991:                                auth = "none";
                    992:                        }
                    993:                }
                    994:                if (pktversion > NTP_OLDVERSION) {
                    995:                        switch (statval & 0x7) {
                    996: 
                    997:                        case CTL_PST_SEL_REJECT:
                    998:                                condition = "reject";
                    999:                                break;
                   1000: 
                   1001:                        case CTL_PST_SEL_SANE:
                   1002:                                condition = "falsetick";
                   1003:                                break;
                   1004: 
                   1005:                        case CTL_PST_SEL_CORRECT:
                   1006:                                condition = "excess";
                   1007:                                break;
                   1008: 
                   1009:                        case CTL_PST_SEL_SELCAND:
                   1010:                                condition = "outlyer";
                   1011:                                break;
                   1012: 
                   1013:                        case CTL_PST_SEL_SYNCCAND:
                   1014:                                condition = "candidate";
                   1015:                                break;
                   1016: 
                   1017:                        case CTL_PST_SEL_EXCESS:
                   1018:                                condition = "backup";
                   1019:                                break;
                   1020: 
                   1021:                        case CTL_PST_SEL_SYSPEER:
                   1022:                                condition = "sys.peer";
                   1023:                                break;
                   1024: 
                   1025:                        case CTL_PST_SEL_PPS:
                   1026:                                condition = "pps.peer";
                   1027:                                break;
                   1028:                        }
                   1029:                } else {
                   1030:                        switch (statval & 0x3) {
                   1031: 
                   1032:                        case OLD_CTL_PST_SEL_REJECT:
                   1033:                                if (!(statval & OLD_CTL_PST_SANE))
                   1034:                                        condition = "insane";
                   1035:                                else if (!(statval & OLD_CTL_PST_DISP))
                   1036:                                        condition = "hi_disp";
                   1037:                                else
                   1038:                                        condition = "";
                   1039:                                break;
                   1040: 
                   1041:                        case OLD_CTL_PST_SEL_SELCAND:
                   1042:                                condition = "sel_cand";
                   1043:                                break;
                   1044: 
                   1045:                        case OLD_CTL_PST_SEL_SYNCCAND:
                   1046:                                condition = "sync_cand";
                   1047:                                break;
                   1048: 
                   1049:                        case OLD_CTL_PST_SEL_SYSPEER:
                   1050:                                condition = "sys_peer";
                   1051:                                break;
                   1052:                        }
                   1053:                }
                   1054:                switch (PEER_EVENT|event) {
                   1055: 
                   1056:                case PEVNT_MOBIL:
                   1057:                        last_event = "mobilize";
                   1058:                        break;
                   1059: 
                   1060:                case PEVNT_DEMOBIL:
                   1061:                        last_event = "demobilize";
                   1062:                        break;
                   1063: 
                   1064:                case PEVNT_REACH:
                   1065:                        last_event = "reachable";
                   1066:                        break;
                   1067: 
                   1068:                case PEVNT_UNREACH:
                   1069:                        last_event = "unreachable";
                   1070:                        break;
                   1071: 
                   1072:                case PEVNT_RESTART:
                   1073:                        last_event = "restart";
                   1074:                        break;
                   1075: 
                   1076:                case PEVNT_REPLY:
                   1077:                        last_event = "no_reply";
                   1078:                        break;
                   1079: 
                   1080:                case PEVNT_RATE:
                   1081:                        last_event = "rate_exceeded";
                   1082:                        break;
                   1083: 
                   1084:                case PEVNT_DENY:
                   1085:                        last_event = "access_denied";
                   1086:                        break;
                   1087: 
                   1088:                case PEVNT_ARMED:
                   1089:                        last_event = "leap_armed";
                   1090:                        break;
                   1091: 
                   1092:                case PEVNT_NEWPEER:
                   1093:                        last_event = "sys_peer";
                   1094:                        break;
                   1095: 
                   1096:                case PEVNT_CLOCK:
                   1097:                        last_event = "clock_alarm";
                   1098:                        break;
                   1099: 
                   1100:                default:
                   1101:                        last_event = "";
                   1102:                        break;
                   1103:                }
                   1104:                cnt = uinttoa(event_count);
                   1105:                snprintf(buf, sizeof(buf),
                   1106:                         "%3d %5u  %04x   %3.3s  %4s  %4.4s %9.9s %11s %2s",
                   1107:                         i + 1, assoc_cache[i].assid,
                   1108:                         assoc_cache[i].status, conf, reach, auth,
                   1109:                         condition, last_event, cnt);
                   1110:                bp = buf + strlen(buf);
                   1111:                while (bp > buf && ' ' == bp[-1])
                   1112:                        --bp;
                   1113:                bp[0] = '\0';
                   1114:                fprintf(fp, "%s\n", buf);
                   1115:        }
                   1116: }
                   1117: 
                   1118: 
                   1119: /*
                   1120:  * associations - get, record and print a list of associations
                   1121:  */
                   1122: /*ARGSUSED*/
                   1123: static void
                   1124: associations(
                   1125:        struct parse *pcmd,
                   1126:        FILE *fp
                   1127:        )
                   1128: {
                   1129:        if (dogetassoc(fp))
                   1130:                printassoc(0, fp);
                   1131: }
                   1132: 
                   1133: 
                   1134: /*
                   1135:  * lassociations - get, record and print a long list of associations
                   1136:  */
                   1137: /*ARGSUSED*/
                   1138: static void
                   1139: lassociations(
                   1140:        struct parse *pcmd,
                   1141:        FILE *fp
                   1142:        )
                   1143: {
                   1144:        if (dogetassoc(fp))
                   1145:                printassoc(1, fp);
                   1146: }
                   1147: 
                   1148: 
                   1149: /*
                   1150:  * passociations - print the association list
                   1151:  */
                   1152: /*ARGSUSED*/
                   1153: static void
                   1154: passociations(
                   1155:        struct parse *pcmd,
                   1156:        FILE *fp
                   1157:        )
                   1158: {
                   1159:        printassoc(0, fp);
                   1160: }
                   1161: 
                   1162: 
                   1163: /*
                   1164:  * lpassociations - print the long association list
                   1165:  */
                   1166: /*ARGSUSED*/
                   1167: static void
                   1168: lpassociations(
                   1169:        struct parse *pcmd,
                   1170:        FILE *fp
                   1171:        )
                   1172: {
                   1173:        printassoc(1, fp);
                   1174: }
                   1175: 
                   1176: 
                   1177: /*
                   1178:  *  saveconfig - dump ntp server configuration to server file
                   1179:  */
                   1180: static void
                   1181: saveconfig(
                   1182:        struct parse *pcmd,
                   1183:        FILE *fp
                   1184:        )
                   1185: {
                   1186:        const char *datap;
                   1187:        int res;
                   1188:        int dsize;
                   1189:        u_short rstatus;
                   1190: 
                   1191:        if (0 == pcmd->nargs)
                   1192:                return;
                   1193:        
                   1194:        res = doquery(CTL_OP_SAVECONFIG, 0, 1,
                   1195:                      strlen(pcmd->argval[0].string),
                   1196:                      pcmd->argval[0].string, &rstatus, &dsize,
                   1197:                      &datap);
                   1198: 
                   1199:        if (res != 0)
                   1200:                return;
                   1201: 
                   1202:        if (0 == dsize)
                   1203:                fprintf(fp, "(no response message, curiously)");
                   1204:        else
                   1205:                fprintf(fp, "%.*s", dsize, datap);
                   1206: }
                   1207: 
                   1208: 
                   1209: #ifdef UNUSED
                   1210: /*
                   1211:  * radiostatus - print the radio status returned by the server
                   1212:  */
                   1213: /*ARGSUSED*/
                   1214: static void
                   1215: radiostatus(
                   1216:        struct parse *pcmd,
                   1217:        FILE *fp
                   1218:        )
                   1219: {
                   1220:        char *datap;
                   1221:        int res;
                   1222:        int dsize;
                   1223:        u_short rstatus;
                   1224: 
                   1225:        res = doquery(CTL_OP_READCLOCK, 0, 0, 0, (char *)0, &rstatus,
                   1226:                          &dsize, &datap);
                   1227: 
                   1228:        if (res != 0)
                   1229:                return;
                   1230: 
                   1231:        if (numhosts > 1)
                   1232:                (void) fprintf(fp, "server=%s ", currenthost);
                   1233:        if (dsize == 0) {
                   1234:                (void) fprintf(fp, "No radio status string returned\n");
                   1235:                return;
                   1236:        }
                   1237: 
                   1238:        asciize(dsize, datap, fp);
                   1239: }
                   1240: #endif /* UNUSED */
                   1241: 
                   1242: /*
                   1243:  * pstatus - print peer status returned by the server
                   1244:  */
                   1245: static void
                   1246: pstatus(
                   1247:        struct parse *pcmd,
                   1248:        FILE *fp
                   1249:        )
                   1250: {
                   1251:        const char *datap;
                   1252:        int res;
                   1253:        associd_t associd;
                   1254:        int dsize;
                   1255:        u_short rstatus;
                   1256: 
                   1257:        /* HMS: uval? */
                   1258:        if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
                   1259:                return;
                   1260: 
                   1261:        res = doquery(CTL_OP_READSTAT, associd, 0, 0, NULL, &rstatus,
                   1262:                      &dsize, &datap);
                   1263: 
                   1264:        if (res != 0)
                   1265:                return;
                   1266: 
                   1267:        if (numhosts > 1)
                   1268:                fprintf(fp, "server=%s ", currenthost);
                   1269:        if (dsize == 0) {
                   1270:                fprintf(fp,
                   1271:                        "No information returned for association %u\n",
                   1272:                        associd);
                   1273:                return;
                   1274:        }
                   1275: 
                   1276:        fprintf(fp, "associd=%u ", associd);
                   1277:        printvars(dsize, datap, (int)rstatus, TYPE_PEER, 0, fp);
                   1278: }
                   1279: 
                   1280: 
                   1281: /*
                   1282:  * when - print how long its been since his last packet arrived
                   1283:  */
                   1284: static long
                   1285: when(
                   1286:        l_fp *ts,
                   1287:        l_fp *rec,
                   1288:        l_fp *reftime
                   1289:        )
                   1290: {
                   1291:        l_fp *lasttime;
                   1292: 
                   1293:        if (rec->l_ui != 0)
                   1294:                lasttime = rec;
                   1295:        else if (reftime->l_ui != 0)
                   1296:                lasttime = reftime;
                   1297:        else
                   1298:                return 0;
                   1299: 
                   1300:        return (ts->l_ui - lasttime->l_ui);
                   1301: }
                   1302: 
                   1303: 
                   1304: /*
                   1305:  * Pretty-print an interval into the given buffer, in a human-friendly format.
                   1306:  */
                   1307: static char *
                   1308: prettyinterval(
                   1309:        char *buf,
                   1310:        size_t cb,
                   1311:        long diff
                   1312:        )
                   1313: {
                   1314:        if (diff <= 0) {
                   1315:                buf[0] = '-';
                   1316:                buf[1] = 0;
                   1317:                return buf;
                   1318:        }
                   1319: 
                   1320:        if (diff <= 2048) {
                   1321:                snprintf(buf, cb, "%ld", diff);
                   1322:                return buf;
                   1323:        }
                   1324: 
                   1325:        diff = (diff + 29) / 60;
                   1326:        if (diff <= 300) {
                   1327:                snprintf(buf, cb, "%ldm", diff);
                   1328:                return buf;
                   1329:        }
                   1330: 
                   1331:        diff = (diff + 29) / 60;
                   1332:        if (diff <= 96) {
                   1333:                snprintf(buf, cb, "%ldh", diff);
                   1334:                return buf;
                   1335:        }
                   1336: 
                   1337:        diff = (diff + 11) / 24;
                   1338:        snprintf(buf, cb, "%ldd", diff);
                   1339:        return buf;
                   1340: }
                   1341: 
                   1342: static char
                   1343: decodeaddrtype(
                   1344:        sockaddr_u *sock
                   1345:        )
                   1346: {
                   1347:        char ch = '-';
                   1348:        u_int32 dummy;
                   1349: 
                   1350:        switch(AF(sock)) {
                   1351:        case AF_INET:
                   1352:                dummy = SRCADR(sock);
                   1353:                ch = (char)(((dummy&0xf0000000)==0xe0000000) ? 'm' :
                   1354:                        ((dummy&0x000000ff)==0x000000ff) ? 'b' :
                   1355:                        ((dummy&0xffffffff)==0x7f000001) ? 'l' :
                   1356:                        ((dummy&0xffffffe0)==0x00000000) ? '-' :
                   1357:                        'u');
                   1358:                break;
                   1359:        case AF_INET6:
                   1360:                if (IN6_IS_ADDR_MULTICAST(PSOCK_ADDR6(sock)))
                   1361:                        ch = 'm';
                   1362:                else
                   1363:                        ch = 'u';
                   1364:                break;
                   1365:        default:
                   1366:                ch = '-';
                   1367:                break;
                   1368:        }
                   1369:        return ch;
                   1370: }
                   1371: 
                   1372: /*
                   1373:  * A list of variables required by the peers command
                   1374:  */
                   1375: struct varlist opeervarlist[] = {
                   1376:        { "srcadr", 0 },    /* 0 */
                   1377:        { "dstadr", 0 },    /* 1 */
                   1378:        { "stratum",    0 },    /* 2 */
                   1379:        { "hpoll",  0 },    /* 3 */
                   1380:        { "ppoll",  0 },    /* 4 */
                   1381:        { "reach",  0 },    /* 5 */
                   1382:        { "delay",  0 },    /* 6 */
                   1383:        { "offset", 0 },    /* 7 */
                   1384:        { "jitter", 0 },    /* 8 */
                   1385:        { "dispersion", 0 },    /* 9 */
                   1386:        { "rec",    0 },    /* 10 */
                   1387:        { "reftime",    0 },    /* 11 */
                   1388:        { "srcport",    0 },    /* 12 */
                   1389:        { 0,            0 }
                   1390: };
                   1391: 
                   1392: struct varlist peervarlist[] = {
                   1393:        { "srcadr", 0 },    /* 0 */
                   1394:        { "refid",  0 },    /* 1 */
                   1395:        { "stratum",    0 },    /* 2 */
                   1396:        { "hpoll",  0 },    /* 3 */
                   1397:        { "ppoll",  0 },    /* 4 */
                   1398:        { "reach",  0 },    /* 5 */
                   1399:        { "delay",  0 },    /* 6 */
                   1400:        { "offset", 0 },    /* 7 */
                   1401:        { "jitter", 0 },    /* 8 */
                   1402:        { "dispersion", 0 },    /* 9 */
                   1403:        { "rec",    0 },    /* 10 */
                   1404:        { "reftime",    0 },    /* 11 */
                   1405:        { "srcport",    0 },    /* 12 */
                   1406:        { 0,            0 }
                   1407: };
                   1408: 
                   1409: #define HAVE_SRCADR 0
                   1410: #define HAVE_DSTADR 1
                   1411: #define HAVE_REFID     1
                   1412: #define HAVE_STRATUM   2
                   1413: #define HAVE_HPOLL     3
                   1414: #define HAVE_PPOLL     4
                   1415: #define HAVE_REACH     5
                   1416: #define HAVE_DELAY     6
                   1417: #define HAVE_OFFSET 7
                   1418: #define HAVE_JITTER 8
                   1419: #define HAVE_DISPERSION 9
                   1420: #define HAVE_REC       10
                   1421: #define HAVE_REFTIME   11
                   1422: #define HAVE_SRCPORT   12
                   1423: #define MAXHAVE        13
                   1424: 
                   1425: /*
                   1426:  * Decode an incoming data buffer and print a line in the peer list
                   1427:  */
                   1428: static int
                   1429: doprintpeers(
                   1430:        struct varlist *pvl,
                   1431:        int associd,
                   1432:        int rstatus,
                   1433:        int datalen,
                   1434:        const char *data,
                   1435:        FILE *fp,
                   1436:        int af
                   1437:        )
                   1438: {
                   1439:        char *name;
                   1440:        char *value = NULL;
                   1441:        int i;
                   1442:        int c;
                   1443: 
                   1444:        sockaddr_u srcadr;
                   1445:        sockaddr_u dstadr;
                   1446:        sockaddr_u refidadr;
                   1447:        u_long srcport = 0;
                   1448:        char *dstadr_refid = "0.0.0.0";
                   1449:        char *serverlocal;
                   1450:        size_t drlen;
                   1451:        u_long stratum = 0;
                   1452:        long ppoll = 0;
                   1453:        long hpoll = 0;
                   1454:        u_long reach = 0;
                   1455:        l_fp estoffset;
                   1456:        l_fp estdelay;
                   1457:        l_fp estjitter;
                   1458:        l_fp estdisp;
                   1459:        l_fp reftime;
                   1460:        l_fp rec;
                   1461:        l_fp ts;
                   1462:        u_char havevar[MAXHAVE];
                   1463:        u_long poll_sec;
                   1464:        char type = '?';
                   1465:        char refid_string[10];
                   1466:        char whenbuf[8], pollbuf[8];
                   1467:        char clock_name[LENHOSTNAME];
                   1468: 
                   1469:        memset((char *)havevar, 0, sizeof(havevar));
                   1470:        get_systime(&ts);
                   1471:        
                   1472:        ZERO_SOCK(&srcadr);
                   1473:        ZERO_SOCK(&dstadr);
                   1474: 
                   1475:        /* Initialize by zeroing out estimate variables */
                   1476:        memset((char *)&estoffset, 0, sizeof(l_fp));
                   1477:        memset((char *)&estdelay, 0, sizeof(l_fp));
                   1478:        memset((char *)&estjitter, 0, sizeof(l_fp));
                   1479:        memset((char *)&estdisp, 0, sizeof(l_fp));
                   1480: 
                   1481:        while (nextvar(&datalen, &data, &name, &value)) {
                   1482:                sockaddr_u dum_store;
                   1483: 
                   1484:                i = findvar(name, peer_var, 1);
                   1485:                if (i == 0)
                   1486:                        continue;       /* don't know this one */
                   1487:                switch (i) {
                   1488:                        case CP_SRCADR:
                   1489:                        if (decodenetnum(value, &srcadr)) {
                   1490:                                havevar[HAVE_SRCADR] = 1;
                   1491:                        }
                   1492:                        break;
                   1493:                        case CP_DSTADR:
                   1494:                        if (decodenetnum(value, &dum_store)) {
                   1495:                                type = decodeaddrtype(&dum_store);
                   1496:                                havevar[HAVE_DSTADR] = 1;
                   1497:                                dstadr = dum_store;
                   1498:                                if (pvl == opeervarlist) {
                   1499:                                        dstadr_refid = trunc_left(stoa(&dstadr), 15);
                   1500:                                }
                   1501:                        }
                   1502:                        break;
                   1503:                        case CP_REFID:
                   1504:                        if (pvl == peervarlist) {
                   1505:                                havevar[HAVE_REFID] = 1;
                   1506:                                if (*value == '\0') {
                   1507:                                        dstadr_refid = "";
                   1508:                                } else if (strlen(value) <= 4) {
                   1509:                                        refid_string[0] = '.';
                   1510:                                        (void) strcpy(&refid_string[1], value);
                   1511:                                        i = strlen(refid_string);
                   1512:                                        refid_string[i] = '.';
                   1513:                                        refid_string[i+1] = '\0';
                   1514:                                        dstadr_refid = refid_string;
                   1515:                                } else if (decodenetnum(value, &refidadr)) {
                   1516:                                        if (SOCK_UNSPEC(&refidadr))
                   1517:                                                dstadr_refid = "0.0.0.0";
                   1518:                                        else if (ISREFCLOCKADR(&refidadr))
                   1519:                                                dstadr_refid =
                   1520:                                                    refnumtoa(&refidadr);
                   1521:                                        else
                   1522:                                                dstadr_refid =
                   1523:                                                    stoa(&refidadr);
                   1524:                                } else {
                   1525:                                        havevar[HAVE_REFID] = 0;
                   1526:                                }
                   1527:                        }
                   1528:                        break;
                   1529:                        case CP_STRATUM:
                   1530:                        if (decodeuint(value, &stratum))
                   1531:                                havevar[HAVE_STRATUM] = 1;
                   1532:                        break;
                   1533:                        case CP_HPOLL:
                   1534:                        if (decodeint(value, &hpoll)) {
                   1535:                                havevar[HAVE_HPOLL] = 1;
                   1536:                                if (hpoll < 0)
                   1537:                                        hpoll = NTP_MINPOLL;
                   1538:                        }
                   1539:                        break;
                   1540:                        case CP_PPOLL:
                   1541:                        if (decodeint(value, &ppoll)) {
                   1542:                                havevar[HAVE_PPOLL] = 1;
                   1543:                                if (ppoll < 0)
                   1544:                                        ppoll = NTP_MINPOLL;
                   1545:                        }
                   1546:                        break;
                   1547:                        case CP_REACH:
                   1548:                        if (decodeuint(value, &reach))
                   1549:                                havevar[HAVE_REACH] = 1;
                   1550:                        break;
                   1551:                        case CP_DELAY:
                   1552:                        if (decodetime(value, &estdelay))
                   1553:                                havevar[HAVE_DELAY] = 1;
                   1554:                        break;
                   1555:                        case CP_OFFSET:
                   1556:                        if (decodetime(value, &estoffset))
                   1557:                                havevar[HAVE_OFFSET] = 1;
                   1558:                        break;
                   1559:                        case CP_JITTER:
                   1560:                        if (pvl == peervarlist)
                   1561:                                if (decodetime(value, &estjitter))
                   1562:                                        havevar[HAVE_JITTER] = 1;
                   1563:                        break;
                   1564:                        case CP_DISPERSION:
                   1565:                        if (decodetime(value, &estdisp))
                   1566:                                havevar[HAVE_DISPERSION] = 1;
                   1567:                        break;
                   1568:                        case CP_REC:
                   1569:                        if (decodets(value, &rec))
                   1570:                                havevar[HAVE_REC] = 1;
                   1571:                        break;
                   1572:                        case CP_SRCPORT:
                   1573:                        if (decodeuint(value, &srcport))
                   1574:                                havevar[HAVE_SRCPORT] = 1;
                   1575:                        break;
                   1576:                        case CP_REFTIME:
                   1577:                        havevar[HAVE_REFTIME] = 1;
                   1578:                        if (!decodets(value, &reftime))
                   1579:                                L_CLR(&reftime);
                   1580:                        break;
                   1581:                        default:
                   1582:                        break;
                   1583:                }
                   1584:        }
                   1585: 
                   1586:        /*
                   1587:         * Check to see if the srcport is NTP's port.  If not this probably
                   1588:         * isn't a valid peer association.
                   1589:         */
                   1590:        if (havevar[HAVE_SRCPORT] && srcport != NTP_PORT)
                   1591:                return (1);
                   1592: 
                   1593:        /*
                   1594:         * Got everything, format the line
                   1595:         */
                   1596:        poll_sec = 1<<max(min3(ppoll, hpoll, NTP_MAXPOLL), NTP_MINPOLL);
                   1597:        if (pktversion > NTP_OLDVERSION)
                   1598:                c = flash3[CTL_PEER_STATVAL(rstatus) & 0x7];
                   1599:        else
                   1600:                c = flash2[CTL_PEER_STATVAL(rstatus) & 0x3];
                   1601:        if (numhosts > 1) {
                   1602:                if (peervarlist == pvl && havevar[HAVE_DSTADR]) {
                   1603:                        serverlocal = nntohost_col(&dstadr,
                   1604:                            (size_t)min(LIB_BUFLENGTH - 1, maxhostlen),
                   1605:                            TRUE);
                   1606:                } else {
                   1607:                        if (currenthostisnum)
                   1608:                                serverlocal = trunc_left(currenthost,
                   1609:                                                         maxhostlen);
                   1610:                        else
                   1611:                                serverlocal = currenthost;
                   1612:                }
                   1613:                fprintf(fp, "%-*s ", maxhostlen, serverlocal);
                   1614:        }
                   1615:        if (AF_UNSPEC == af || AF(&srcadr) == af) {
                   1616:                strncpy(clock_name, nntohost(&srcadr), sizeof(clock_name));             
                   1617:                fprintf(fp, "%c%-15.15s ", c, clock_name);
                   1618:                drlen = strlen(dstadr_refid);
                   1619:                makeascii(drlen, dstadr_refid, fp);
                   1620:                while (drlen++ < 15)
                   1621:                        fputc(' ', fp);
                   1622:                fprintf(fp,
                   1623:                        " %2ld %c %4.4s %4.4s  %3lo  %7.7s %8.7s %7.7s\n",
                   1624:                        stratum, type,
                   1625:                        prettyinterval(whenbuf, sizeof(whenbuf),
                   1626:                                       when(&ts, &rec, &reftime)),
                   1627:                        prettyinterval(pollbuf, sizeof(pollbuf), 
                   1628:                                       (int)poll_sec),
                   1629:                        reach, lfptoms(&estdelay, 3),
                   1630:                        lfptoms(&estoffset, 3),
                   1631:                        (havevar[HAVE_JITTER])
                   1632:                            ? lfptoms(&estjitter, 3)
                   1633:                            : lfptoms(&estdisp, 3));
                   1634:                return (1);
                   1635:        }
                   1636:        else
                   1637:                return(1);
                   1638: }
                   1639: 
                   1640: #undef HAVE_SRCADR
                   1641: #undef HAVE_DSTADR
                   1642: #undef HAVE_STRATUM
                   1643: #undef HAVE_PPOLL
                   1644: #undef HAVE_HPOLL
                   1645: #undef HAVE_REACH
                   1646: #undef HAVE_ESTDELAY
                   1647: #undef HAVE_ESTOFFSET
                   1648: #undef HAVE_JITTER
                   1649: #undef HAVE_ESTDISP
                   1650: #undef HAVE_REFID
                   1651: #undef HAVE_REC
                   1652: #undef HAVE_SRCPORT
                   1653: #undef HAVE_REFTIME
                   1654: #undef MAXHAVE
                   1655: 
                   1656: 
                   1657: /*
                   1658:  * dogetpeers - given an association ID, read and print the spreadsheet
                   1659:  *             peer variables.
                   1660:  */
                   1661: static int
                   1662: dogetpeers(
                   1663:        struct varlist *pvl,
                   1664:        associd_t associd,
                   1665:        FILE *fp,
                   1666:        int af
                   1667:        )
                   1668: {
                   1669:        const char *datap;
                   1670:        int res;
                   1671:        int dsize;
                   1672:        u_short rstatus;
                   1673: 
                   1674: #ifdef notdef
                   1675:        res = doquerylist(pvl, CTL_OP_READVAR, associd, 0, &rstatus,
                   1676:                          &dsize, &datap);
                   1677: #else
                   1678:        /*
                   1679:         * Damn fuzzballs
                   1680:         */
                   1681:        res = doquery(CTL_OP_READVAR, associd, 0, 0, NULL, &rstatus,
                   1682:                          &dsize, &datap);
                   1683: #endif
                   1684: 
                   1685:        if (res != 0)
                   1686:                return 0;
                   1687: 
                   1688:        if (dsize == 0) {
                   1689:                if (numhosts > 1)
                   1690:                        fprintf(stderr, "server=%s ", currenthost);
                   1691:                fprintf(stderr,
                   1692:                        "***No information returned for association %u\n",
                   1693:                        associd);
                   1694:                return 0;
                   1695:        }
                   1696: 
                   1697:        return doprintpeers(pvl, associd, (int)rstatus, dsize, datap,
                   1698:                            fp, af);
                   1699: }
                   1700: 
                   1701: 
                   1702: /*
                   1703:  * peers - print a peer spreadsheet
                   1704:  */
                   1705: static void
                   1706: dopeers(
                   1707:        int showall,
                   1708:        FILE *fp,
                   1709:        int af
                   1710:        )
                   1711: {
                   1712:        int             i;
                   1713:        char            fullname[LENHOSTNAME];
                   1714:        sockaddr_u      netnum;
                   1715:        char *          name_or_num;
                   1716:        size_t          sl;
                   1717: 
                   1718:        if (!dogetassoc(fp))
                   1719:                return;
                   1720: 
                   1721:        for (i = 0; i < numhosts; ++i) {
                   1722:                if (getnetnum(chosts[i], &netnum, fullname, af)) {
                   1723:                        name_or_num = nntohost(&netnum);
                   1724:                        sl = strlen(name_or_num);
                   1725:                        maxhostlen = max(maxhostlen, (int)sl);
                   1726:                }
                   1727:        }
                   1728:        if (numhosts > 1)
                   1729:                fprintf(fp, "%-*.*s ", maxhostlen, maxhostlen,
                   1730:                        "server (local)");
                   1731:        fprintf(fp,
                   1732:                "     remote           refid      st t when poll reach   delay   offset  jitter\n");
                   1733:        if (numhosts > 1)
                   1734:                for (i = 0; i <= maxhostlen; ++i)
                   1735:                        fprintf(fp, "=");
                   1736:        fprintf(fp,
                   1737:                "==============================================================================\n");
                   1738: 
                   1739:        for (i = 0; i < numassoc; i++) {
                   1740:                if (!showall &&
                   1741:                        !(CTL_PEER_STATVAL(assoc_cache[i].status)
                   1742:                          & (CTL_PST_CONFIG|CTL_PST_REACH)))
                   1743:                        continue;
                   1744:                if (!dogetpeers(peervarlist, (int)assoc_cache[i].assid, fp, af)) {
                   1745:                        return;
                   1746:                }
                   1747:        }
                   1748:        return;
                   1749: }
                   1750: 
                   1751: 
                   1752: /*
                   1753:  * peers - print a peer spreadsheet
                   1754:  */
                   1755: /*ARGSUSED*/
                   1756: static void
                   1757: peers(
                   1758:        struct parse *pcmd,
                   1759:        FILE *fp
                   1760:        )
                   1761: {
                   1762:        int af = 0;
                   1763: 
                   1764:        if (pcmd->nargs == 1) {
                   1765:                if (pcmd->argval->ival == 6)
                   1766:                        af = AF_INET6;
                   1767:                else
                   1768:                        af = AF_INET;
                   1769:        }
                   1770:        dopeers(0, fp, af);
                   1771: }
                   1772: 
                   1773: 
                   1774: /*
                   1775:  * lpeers - print a peer spreadsheet including all fuzzball peers
                   1776:  */
                   1777: /*ARGSUSED*/
                   1778: static void
                   1779: lpeers(
                   1780:        struct parse *pcmd,
                   1781:        FILE *fp
                   1782:        )
                   1783: {
                   1784:        int af = 0;
                   1785: 
                   1786:        if (pcmd->nargs == 1) {
                   1787:                if (pcmd->argval->ival == 6)
                   1788:                        af = AF_INET6;
                   1789:                else
                   1790:                        af = AF_INET;
                   1791:        }
                   1792:        dopeers(1, fp, af);
                   1793: }
                   1794: 
                   1795: 
                   1796: /*
                   1797:  * opeers - print a peer spreadsheet
                   1798:  */
                   1799: static void
                   1800: doopeers(
                   1801:        int showall,
                   1802:        FILE *fp,
                   1803:        int af
                   1804:        )
                   1805: {
                   1806:        register int i;
                   1807:        char fullname[LENHOSTNAME];
                   1808:        sockaddr_u netnum;
                   1809: 
                   1810:        if (!dogetassoc(fp))
                   1811:                return;
                   1812: 
                   1813:        for (i = 0; i < numhosts; ++i) {
                   1814:                if (getnetnum(chosts[i], &netnum, fullname, af))
                   1815:                        if ((int)strlen(fullname) > maxhostlen)
                   1816:                                maxhostlen = strlen(fullname);
                   1817:        }
                   1818:        if (numhosts > 1)
                   1819:                (void) fprintf(fp, "%-*.*s ", maxhostlen, maxhostlen, "server");
                   1820:        (void) fprintf(fp,
                   1821:                           "     remote           local      st t when poll reach   delay   offset    disp\n");
                   1822:        if (numhosts > 1)
                   1823:                for (i = 0; i <= maxhostlen; ++i)
                   1824:                (void) fprintf(fp, "=");
                   1825:        (void) fprintf(fp,
                   1826:                           "==============================================================================\n");
                   1827: 
                   1828:        for (i = 0; i < numassoc; i++) {
                   1829:                if (!showall &&
                   1830:                        !(CTL_PEER_STATVAL(assoc_cache[i].status)
                   1831:                          & (CTL_PST_CONFIG|CTL_PST_REACH)))
                   1832:                        continue;
                   1833:                if (!dogetpeers(opeervarlist, (int)assoc_cache[i].assid, fp, af)) {
                   1834:                        return;
                   1835:                }
                   1836:        }
                   1837:        return;
                   1838: }
                   1839: 
                   1840: 
                   1841: /*
                   1842:  * opeers - print a peer spreadsheet the old way
                   1843:  */
                   1844: /*ARGSUSED*/
                   1845: static void
                   1846: opeers(
                   1847:        struct parse *pcmd,
                   1848:        FILE *fp
                   1849:        )
                   1850: {
                   1851:        int af = 0;
                   1852: 
                   1853:        if (pcmd->nargs == 1) {
                   1854:                if (pcmd->argval->ival == 6)
                   1855:                        af = AF_INET6;
                   1856:                else
                   1857:                        af = AF_INET;
                   1858:        }
                   1859:        doopeers(0, fp, af);
                   1860: }
                   1861: 
                   1862: 
                   1863: /*
                   1864:  * lopeers - print a peer spreadsheet including all fuzzball peers
                   1865:  */
                   1866: /*ARGSUSED*/
                   1867: static void
                   1868: lopeers(
                   1869:        struct parse *pcmd,
                   1870:        FILE *fp
                   1871:        )
                   1872: {
                   1873:        int af = 0;
                   1874: 
                   1875:        if (pcmd->nargs == 1) {
                   1876:                if (pcmd->argval->ival == 6)
                   1877:                        af = AF_INET6;
                   1878:                else
                   1879:                        af = AF_INET;
                   1880:        }
                   1881:        doopeers(1, fp, af);
                   1882: }
                   1883: 
                   1884: 
                   1885: /* 
                   1886:  * config - send a configuration command to a remote host
                   1887:  */
                   1888: static void 
                   1889: config (
                   1890:        struct parse *pcmd,
                   1891:        FILE *fp
                   1892:        )
                   1893: {
                   1894:        char *cfgcmd;
                   1895:        u_short rstatus;
                   1896:        int rsize;
                   1897:        const char *rdata;
                   1898:        char *resp;
                   1899:        int res;
                   1900:        int col;
                   1901:        int i;
                   1902: 
                   1903:        cfgcmd = pcmd->argval[0].string;
                   1904: 
                   1905:        if (debug > 2)
                   1906:                fprintf(stderr, 
                   1907:                        "In Config\n"
                   1908:                        "Keyword = %s\n"
                   1909:                        "Command = %s\n", pcmd->keyword, cfgcmd);
                   1910: 
                   1911:        res = doquery(CTL_OP_CONFIGURE, 0, 1, strlen(cfgcmd), cfgcmd,
                   1912:                      &rstatus, &rsize, &rdata);
                   1913: 
                   1914:        if (res != 0)
                   1915:                return;
                   1916: 
                   1917:        if (rsize > 0 && '\n' == rdata[rsize - 1])
                   1918:                rsize--;
                   1919: 
                   1920:        resp = emalloc(rsize + 1);
                   1921:        memcpy(resp, rdata, rsize);
                   1922:        resp[rsize] = '\0';
                   1923: 
                   1924:        col = -1;
                   1925:        if (1 == sscanf(resp, "column %d syntax error", &col)
                   1926:            && col >= 0 && (size_t)col <= strlen(cfgcmd) + 1) {
                   1927:                if (interactive) {
                   1928:                        printf("______");       /* "ntpq> " */
                   1929:                        printf("________");     /* ":config " */
                   1930:                } else
                   1931:                        printf("%s\n", cfgcmd);
                   1932:                for (i = 1; i < col; i++)
                   1933:                        putchar('_');
                   1934:                printf("^\n");
                   1935:        }
                   1936:        printf("%s\n", resp);
                   1937:        free(resp);
                   1938: }
                   1939: 
                   1940: 
                   1941: /* 
                   1942:  * config_from_file - remotely configure an ntpd daemon using the
                   1943:  * specified configuration file
                   1944:  * SK: This function is a kludge at best and is full of bad design
                   1945:  * bugs:
                   1946:  * 1. ntpq uses UDP, which means that there is no guarantee of in-order,
                   1947:  *    error-free delivery. 
                   1948:  * 2. The maximum length of a packet is constrained, and as a result, the
                   1949:  *    maximum length of a line in a configuration file is constrained. 
                   1950:  *    Longer lines will lead to unpredictable results.
                   1951:  * 3. Since this function is sending a line at a time, we can't update
                   1952:  *    the control key through the configuration file (YUCK!!)
                   1953:  */
                   1954: static void 
                   1955: config_from_file (
                   1956:        struct parse *pcmd,
                   1957:        FILE *fp
                   1958:        )
                   1959: {
                   1960:        u_short rstatus;
                   1961:        int rsize;
                   1962:        const char *rdata;
                   1963:        int res;
                   1964:        FILE *config_fd;
                   1965:        char config_cmd[MAXLINE];
                   1966:        size_t config_len;
                   1967:        int i;
                   1968:        int retry_limit;
                   1969: 
                   1970:        if (debug > 2)
                   1971:                fprintf(stderr,
                   1972:                        "In Config\n"
                   1973:                        "Keyword = %s\n"
                   1974:                        "Filename = %s\n", pcmd->keyword,
                   1975:                        pcmd->argval[0].string);
                   1976: 
                   1977:        config_fd = fopen(pcmd->argval[0].string, "r");
                   1978:        if (NULL == config_fd) {
                   1979:                printf("ERROR!! Couldn't open file: %s\n",
                   1980:                       pcmd->argval[0].string);
                   1981:                return;
                   1982:        }
                   1983: 
                   1984:        printf("Sending configuration file, one line at a time.\n");
                   1985:        i = 0;
                   1986:        while (fgets(config_cmd, MAXLINE, config_fd) != NULL) {
                   1987:                config_len = strlen(config_cmd);
                   1988:                /* ensure even the last line has newline, if possible */
                   1989:                if (config_len > 0 && 
                   1990:                    config_len + 2 < sizeof(config_cmd) &&
                   1991:                    '\n' != config_cmd[config_len - 1])
                   1992:                        config_cmd[config_len++] = '\n';
                   1993:                ++i;
                   1994:                retry_limit = 2;
                   1995:                do 
                   1996:                        res = doquery(CTL_OP_CONFIGURE, 0, 1,
                   1997:                                      strlen(config_cmd), config_cmd,
                   1998:                                      &rstatus, &rsize, &rdata);
                   1999:                while (res != 0 && retry_limit--);
                   2000:                if (res != 0) {
                   2001:                        printf("Line No: %d query failed: %s", i,
                   2002:                               config_cmd);
                   2003:                        printf("Subsequent lines not sent.\n");
                   2004:                        fclose(config_fd);
                   2005:                        return;
                   2006:                }
                   2007: 
                   2008:                if (rsize > 0 && '\n' == rdata[rsize - 1])
                   2009:                        rsize--;
                   2010:                if (rsize > 0 && '\r' == rdata[rsize - 1])
                   2011:                        rsize--;
                   2012:                printf("Line No: %d %.*s: %s", i, rsize, rdata,
                   2013:                       config_cmd);
                   2014:        }
                   2015:        printf("Done sending file\n");
                   2016:        fclose(config_fd);
                   2017: }

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