~ubuntu-branches/debian/squeeze/ntp/squeeze-201010051545

« back to all changes in this revision

Viewing changes to ntpq/ntpq-subs.c

  • Committer: Bazaar Package Importer
  • Author(s): Kurt Roeckx
  • Date: 2009-01-05 21:10:03 UTC
  • mfrom: (1.2.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20090105211003-mh6zc3um4k1uhsj7
Tags: 1:4.2.4p4+dfsg-8
It did not properly check the return value of EVP_VerifyFinal
which results in an malformed DSA signature being treated as
a good signature rather than as an error.  (CVE-2009-0021)

Show diffs side-by-side

added added

removed removed

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