~ubuntu-branches/ubuntu/gutsy/net-snmp/gutsy-security

« back to all changes in this revision

Viewing changes to snmplib/tools.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-09-13 12:06:21 UTC
  • Revision ID: james.westby@ubuntu.com-20040913120621-g952ntonlleihcvm
Tags: upstream-5.1.1
ImportĀ upstreamĀ versionĀ 5.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * tools.c
 
3
 */
 
4
 
 
5
#define NETSNMP_TOOLS_C 1 /* dont re-define malloc wrappers here */
 
6
 
 
7
#include <net-snmp/net-snmp-config.h>
 
8
 
 
9
#include <ctype.h>
 
10
#include <stdio.h>
 
11
#include <sys/types.h>
 
12
#if TIME_WITH_SYS_TIME
 
13
# ifdef WIN32
 
14
#  include <sys/timeb.h>
 
15
# else
 
16
#  include <sys/time.h>
 
17
# endif
 
18
# include <time.h>
 
19
#else
 
20
# if HAVE_SYS_TIME_H
 
21
#  include <sys/time.h>
 
22
# else
 
23
#  include <time.h>
 
24
# endif
 
25
#endif
 
26
#ifdef HAVE_SYS_SOCKET_H
 
27
#include <sys/socket.h>
 
28
#endif
 
29
#if HAVE_WINSOCK_H
 
30
#include <winsock.h>
 
31
#endif
 
32
#ifdef HAVE_STDLIB_H
 
33
#include <stdlib.h>
 
34
#endif
 
35
#if HAVE_STRING_H
 
36
#include <string.h>
 
37
#else
 
38
#include <strings.h>
 
39
#endif
 
40
#ifdef HAVE_NETINET_IN_H
 
41
#include <netinet/in.h>
 
42
#endif
 
43
#ifdef HAVE_ARPA_INET_H
 
44
#include <arpa/inet.h>
 
45
#endif
 
46
 
 
47
#if HAVE_DMALLOC_H
 
48
#include <dmalloc.h>
 
49
#endif
 
50
 
 
51
#include <net-snmp/types.h>
 
52
#include <net-snmp/output_api.h>
 
53
#include <net-snmp/utilities.h>
 
54
#include <net-snmp/library/tools.h>     /* for "internal" definitions */
 
55
 
 
56
#include <net-snmp/library/snmp_api.h>
 
57
#include <net-snmp/library/mib.h>
 
58
#include <net-snmp/library/scapi.h>
 
59
 
 
60
#ifdef WIN32
 
61
/**
 
62
 * This function is a wrapper for the strdup function.
 
63
 */
 
64
char * netsnmp_strdup( const char * ptr)
 
65
{
 
66
    return strdup(ptr);
 
67
}
 
68
/**
 
69
 * This function is a wrapper for the calloc function.
 
70
 */
 
71
void * netsnmp_calloc(size_t nmemb, size_t size)
 
72
{
 
73
    return calloc(nmemb, size);
 
74
}
 
75
 
 
76
/**
 
77
 * This function is a wrapper for the malloc function.
 
78
 */
 
79
void * netsnmp_malloc(size_t size)
 
80
{
 
81
    return malloc(size);
 
82
}
 
83
 
 
84
/**
 
85
 * This function is a wrapper for the realloc function.
 
86
 */
 
87
void * netsnmp_realloc( void * ptr, size_t size)
 
88
{
 
89
    return realloc(ptr, size);
 
90
}
 
91
 
 
92
/**
 
93
 * This function is a wrapper for the free function.
 
94
 * It calls free only if the calling parameter has a non-zero value.
 
95
 */
 
96
void netsnmp_free( void * ptr)
 
97
{
 
98
    if (ptr)
 
99
        free(ptr);
 
100
}
 
101
#endif /* WIN32 */
 
102
 
 
103
/**
 
104
 * This function increase the size of the buffer pointed at by *buf, which is
 
105
 * initially of size *buf_len.  Contents are preserved **AT THE BOTTOM END OF
 
106
 * THE BUFFER**.  If memory can be (re-)allocated then it returns 1, else it
 
107
 * returns 0.
 
108
 * 
 
109
 * @param buf  pointer to a buffer pointer
 
110
 * @param buf_len      pointer to current size of buffer in bytes
 
111
 * 
 
112
 * 
 
113
 */
 
114
int
 
115
snmp_realloc(u_char ** buf, size_t * buf_len)
 
116
{
 
117
    u_char         *new_buf = NULL;
 
118
    size_t          new_buf_len = 0;
 
119
 
 
120
    if (buf == NULL) {
 
121
        return 0;
 
122
    }
 
123
 
 
124
    /*
 
125
     * The current re-allocation algorithm is to increase the buffer size by
 
126
     * whichever is the greater of 256 bytes or the current buffer size, up to
 
127
     * a maximum increase of 8192 bytes.  
 
128
     */
 
129
 
 
130
    if (*buf_len <= 255) {
 
131
        new_buf_len = *buf_len + 256;
 
132
    } else if (*buf_len > 255 && *buf_len <= 8191) {
 
133
        new_buf_len = *buf_len * 2;
 
134
    } else if (*buf_len > 8191) {
 
135
        new_buf_len = *buf_len + 8192;
 
136
    }
 
137
 
 
138
    if (*buf == NULL) {
 
139
        new_buf = (u_char *) malloc(new_buf_len);
 
140
    } else {
 
141
        new_buf = (u_char *) realloc(*buf, new_buf_len);
 
142
    }
 
143
 
 
144
    if (new_buf != NULL) {
 
145
        *buf = new_buf;
 
146
        *buf_len = new_buf_len;
 
147
        return 1;
 
148
    } else {
 
149
        return 0;
 
150
    }
 
151
}
 
152
 
 
153
int
 
154
snmp_strcat(u_char ** buf, size_t * buf_len, size_t * out_len,
 
155
            int allow_realloc, const u_char * s)
 
156
{
 
157
    if (buf == NULL || buf_len == NULL || out_len == NULL) {
 
158
        return 0;
 
159
    }
 
160
 
 
161
    if (s == NULL) {
 
162
        /*
 
163
         * Appending a NULL string always succeeds since it is a NOP.  
 
164
         */
 
165
        return 1;
 
166
    }
 
167
 
 
168
    while ((*out_len + strlen((const char *) s) + 1) >= *buf_len) {
 
169
        if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
170
            return 0;
 
171
        }
 
172
    }
 
173
 
 
174
    strcpy((char *) (*buf + *out_len), (const char *) s);
 
175
    *out_len += strlen((char *) (*buf + *out_len));
 
176
    return 1;
 
177
}
 
178
 
 
179
/** zeros memory before freeing it.
 
180
 *
 
181
 *      @param *buf     Pointer at bytes to free.
 
182
 *      @param size     Number of bytes in buf.
 
183
 */
 
184
void
 
185
free_zero(void *buf, size_t size)
 
186
{
 
187
    if (buf) {
 
188
        memset(buf, 0, size);
 
189
        free(buf);
 
190
    }
 
191
 
 
192
}                               /* end free_zero() */
 
193
 
 
194
/**
 
195
 * Returns pointer to allocaed & set buffer on success, size contains
 
196
 * number of random bytes filled.  buf is NULL and *size set to KMT
 
197
 * error value upon failure.
 
198
 *
 
199
 *      @param size     Number of bytes to malloc() and fill with random bytes.
 
200
 *
 
201
 * @return a malloced buffer
 
202
 *
 
203
 */
 
204
u_char         *
 
205
malloc_random(size_t * size)
 
206
{
 
207
    int             rval = SNMPERR_SUCCESS;
 
208
    u_char         *buf = (u_char *) calloc(1, *size);
 
209
 
 
210
    if (buf) {
 
211
        rval = sc_random(buf, size);
 
212
 
 
213
        if (rval < 0) {
 
214
            free_zero(buf, *size);
 
215
            buf = NULL;
 
216
        } else {
 
217
            *size = rval;
 
218
        }
 
219
    }
 
220
 
 
221
    return buf;
 
222
 
 
223
}                               /* end malloc_random() */
 
224
 
 
225
/** Duplicates a memory block.
 
226
 *  Copies a existing memory location from a pointer to another, newly
 
227
    malloced, pointer.
 
228
 
 
229
 *      @param to       Pointer to allocate and copy memory to.
 
230
 *      @param from     Pointer to copy memory from.
 
231
 *      @param size     Size of the data to be copied.
 
232
 *      
 
233
 *      @return SNMPERR_SUCCESS on success, SNMPERR_GENERR on failure.
 
234
 */
 
235
int
 
236
memdup(u_char ** to, const u_char * from, size_t size)
 
237
{
 
238
    if (to == NULL)
 
239
        return SNMPERR_GENERR;
 
240
    if (from == NULL) {
 
241
        *to = NULL;
 
242
        return SNMPERR_SUCCESS;
 
243
    }
 
244
    if ((*to = (u_char *) malloc(size)) == NULL)
 
245
        return SNMPERR_GENERR;
 
246
    memcpy(*to, from, size);
 
247
    return SNMPERR_SUCCESS;
 
248
 
 
249
}                               /* end memdup() */
 
250
 
 
251
/** copies a (possible) unterminated string of a given length into a
 
252
 *  new buffer and null terminates it as well (new buffer MAY be one
 
253
 *  byte longer to account for this */
 
254
char           *
 
255
netsnmp_strdup_and_null(const u_char * from, size_t from_len)
 
256
{
 
257
    u_char         *ret;
 
258
 
 
259
    if (from_len == 0 || from[from_len - 1] != '\0') {
 
260
        ret = malloc(from_len + 1);
 
261
        if (!ret)
 
262
            return NULL;
 
263
        ret[from_len] = '\0';
 
264
    } else {
 
265
        ret = malloc(from_len);
 
266
        if (!ret)
 
267
            return NULL;
 
268
        ret[from_len - 1] = '\0';
 
269
    }
 
270
    memcpy(ret, from, from_len);
 
271
    return ret;
 
272
}
 
273
 
 
274
/** converts binary to hexidecimal
 
275
 *
 
276
 *      @param *input           Binary data.
 
277
 *      @param len              Length of binary data.
 
278
 *      @param **output NULL terminated string equivalent in hex.
 
279
 *      
 
280
 * @return olen Length of output string not including NULL terminator.
 
281
 *
 
282
 * FIX  Is there already one of these in the UCD SNMP codebase?
 
283
 *      The old one should be used, or this one should be moved to
 
284
 *      snmplib/snmp_api.c.
 
285
 */
 
286
u_int
 
287
binary_to_hex(const u_char * input, size_t len, char **output)
 
288
{
 
289
    u_int           olen = (len * 2) + 1;
 
290
    char           *s = (char *) calloc(1, olen), *op = s;
 
291
    const u_char   *ip = input;
 
292
 
 
293
 
 
294
    while (ip - input < (int) len) {
 
295
        *op++ = VAL2HEX((*ip >> 4) & 0xf);
 
296
        *op++ = VAL2HEX(*ip & 0xf);
 
297
        ip++;
 
298
    }
 
299
    *op = '\0';
 
300
 
 
301
    *output = s;
 
302
    return olen;
 
303
 
 
304
}                               /* end binary_to_hex() */
 
305
 
 
306
 
 
307
 
 
308
 
 
309
/**
 
310
 * hex_to_binary2
 
311
 *      @param *input           Printable data in base16.
 
312
 *      @param len              Length in bytes of data.
 
313
 *      @param **output Binary data equivalent to input.
 
314
 *      
 
315
 * @return SNMPERR_GENERR on failure, otherwise length of allocated string.
 
316
 *
 
317
 * Input of an odd length is right aligned.
 
318
 *
 
319
 * FIX  Another version of "hex-to-binary" which takes odd length input
 
320
 *      strings.  It also allocates the memory to hold the binary data.
 
321
 *      Should be integrated with the official hex_to_binary() function.
 
322
 */
 
323
int
 
324
hex_to_binary2(const u_char * input, size_t len, char **output)
 
325
{
 
326
    u_int           olen = (len / 2) + (len % 2);
 
327
    char           *s = (char *) calloc(1, (olen) ? olen : 1), *op = s;
 
328
    const u_char   *ip = input;
 
329
 
 
330
 
 
331
    *output = NULL;
 
332
    *op = 0;
 
333
    if (len % 2) {
 
334
        if (!isxdigit(*ip))
 
335
            goto hex_to_binary2_quit;
 
336
        *op++ = HEX2VAL(*ip);
 
337
        ip++;
 
338
    }
 
339
 
 
340
    while (ip - input < (int) len) {
 
341
        if (!isxdigit(*ip))
 
342
            goto hex_to_binary2_quit;
 
343
        *op = HEX2VAL(*ip) << 4;
 
344
        ip++;
 
345
 
 
346
        if (!isxdigit(*ip))
 
347
            goto hex_to_binary2_quit;
 
348
        *op++ += HEX2VAL(*ip);
 
349
        ip++;
 
350
    }
 
351
 
 
352
    *output = s;
 
353
    return olen;
 
354
 
 
355
  hex_to_binary2_quit:
 
356
    free_zero(s, olen);
 
357
    return -1;
 
358
 
 
359
}                               /* end hex_to_binary2() */
 
360
 
 
361
int
 
362
snmp_decimal_to_binary(u_char ** buf, size_t * buf_len, size_t * out_len,
 
363
                       int allow_realloc, const char *decimal)
 
364
{
 
365
    int             subid = 0;
 
366
    const char     *cp = decimal;
 
367
 
 
368
    if (buf == NULL || buf_len == NULL || out_len == NULL
 
369
        || decimal == NULL) {
 
370
        return 0;
 
371
    }
 
372
 
 
373
    while (*cp != '\0') {
 
374
        if (isspace((int) *cp) || *cp == '.') {
 
375
            cp++;
 
376
            continue;
 
377
        }
 
378
        if (!isdigit((int) *cp)) {
 
379
            return 0;
 
380
        }
 
381
        if ((subid = atoi(cp)) > 255) {
 
382
            return 0;
 
383
        }
 
384
        if ((*out_len >= *buf_len) &&
 
385
            !(allow_realloc && snmp_realloc(buf, buf_len))) {
 
386
            return 0;
 
387
        }
 
388
        *(*buf + *out_len) = (u_char) subid;
 
389
        (*out_len)++;
 
390
        while (isdigit((int) *cp)) {
 
391
            cp++;
 
392
        }
 
393
    }
 
394
    return 1;
 
395
}
 
396
 
 
397
int
 
398
snmp_hex_to_binary(u_char ** buf, size_t * buf_len, size_t * out_len,
 
399
                   int allow_realloc, const char *hex)
 
400
{
 
401
    int             subid = 0;
 
402
    const char     *cp = hex;
 
403
 
 
404
    if (buf == NULL || buf_len == NULL || out_len == NULL || hex == NULL) {
 
405
        return 0;
 
406
    }
 
407
 
 
408
    if ((*cp == '0') && ((*(cp + 1) == 'x') || (*(cp + 1) == 'X'))) {
 
409
        cp += 2;
 
410
    }
 
411
 
 
412
    while (*cp != '\0') {
 
413
        if (isspace((int) *cp)) {
 
414
            cp++;
 
415
            continue;
 
416
        }
 
417
        if (!isxdigit((int) *cp)) {
 
418
            return 0;
 
419
        }
 
420
        if (sscanf(cp, "%2x", &subid) == 0) {
 
421
            return 0;
 
422
        }
 
423
        if ((*out_len >= *buf_len) &&
 
424
            !(allow_realloc && snmp_realloc(buf, buf_len))) {
 
425
            return 0;
 
426
        }
 
427
        *(*buf + *out_len) = (u_char) subid;
 
428
        (*out_len)++;
 
429
        if (*++cp == '\0') {
 
430
            /*
 
431
             * Odd number of hex digits is an error.  
 
432
             */
 
433
            return 0;
 
434
        } else {
 
435
            cp++;
 
436
        }
 
437
    }
 
438
    return 1;
 
439
}
 
440
 
 
441
/*******************************************************************-o-******
 
442
 * dump_chunk
 
443
 *
 
444
 * Parameters:
 
445
 *      *title  (May be NULL.)
 
446
 *      *buf
 
447
 *       size
 
448
 */
 
449
void
 
450
dump_chunk(const char *debugtoken, const char *title, const u_char * buf,
 
451
           int size)
 
452
{
 
453
    u_int           printunit = 64;     /* XXX  Make global. */
 
454
    char            chunk[SNMP_MAXBUF], *s, *sp;
 
455
 
 
456
    if (title && (*title != '\0')) {
 
457
        DEBUGMSGTL((debugtoken, "%s\n", title));
 
458
    }
 
459
 
 
460
 
 
461
    memset(chunk, 0, SNMP_MAXBUF);
 
462
    size = binary_to_hex(buf, size, &s);
 
463
    sp = s;
 
464
 
 
465
    while (size > 0) {
 
466
        if (size > (int) printunit) {
 
467
            strncpy(chunk, sp, printunit);
 
468
            chunk[printunit] = '\0';
 
469
            DEBUGMSGTL((debugtoken, "\t%s\n", chunk));
 
470
        } else {
 
471
            DEBUGMSGTL((debugtoken, "\t%s\n", sp));
 
472
        }
 
473
 
 
474
        sp += printunit;
 
475
        size -= printunit;
 
476
    }
 
477
 
 
478
 
 
479
    SNMP_FREE(s);
 
480
 
 
481
}                               /* end dump_chunk() */
 
482
 
 
483
 
 
484
 
 
485
 
 
486
/*******************************************************************-o-******
 
487
 * dump_snmpEngineID
 
488
 *
 
489
 * Parameters:
 
490
 *      *estring
 
491
 *      *estring_len
 
492
 *      
 
493
 * Returns:
 
494
 *      Allocated memory pointing to a string of buflen char representing
 
495
 *      a printf'able form of the snmpEngineID.
 
496
 *
 
497
 *      -OR- NULL on error.
 
498
 *
 
499
 *
 
500
 * Translates the snmpEngineID TC into a printable string.  From RFC 2271,
 
501
 * Section 5 (pp. 36-37):
 
502
 *
 
503
 * First bit:   0       Bit string structured by means non-SNMPv3.
 
504
 *              1       Structure described by SNMPv3 SnmpEngineID TC.
 
505
 *  
 
506
 * Bytes 1-4:           Enterprise ID.  (High bit of first byte is ignored.)
 
507
 *  
 
508
 * Byte 5:      0       (RESERVED by IANA.)
 
509
 *              1       IPv4 address.           (   4 octets)
 
510
 *              2       IPv6 address.           (  16 octets)
 
511
 *              3       MAC address.            (   6 octets)
 
512
 *              4       Locally defined text.   (0-27 octets)
 
513
 *              5       Locally defined octets. (0-27 octets)
 
514
 *              6-127   (RESERVED for enterprise.)
 
515
 *  
 
516
 * Bytes 6-32:          (Determined by byte 5.)
 
517
 *  
 
518
 *
 
519
 * Non-printable characters are given in hex.  Text is given in quotes.
 
520
 * IP and MAC addresses are given in standard (UN*X) conventions.  Sections
 
521
 * are comma separated.
 
522
 *
 
523
 * esp, remaining_len and s trace the state of the constructed buffer.
 
524
 * s will be defined if there is something to return, and it will point
 
525
 * to the end of the constructed buffer.
 
526
 *
 
527
 *
 
528
 * ASSUME  "Text" means printable characters.
 
529
 *
 
530
 * XXX  Must the snmpEngineID always have a minimum length of 12?
 
531
 *      (Cf. part 2 of the TC definition.)
 
532
 * XXX  Does not enforce upper-bound of 32 bytes.
 
533
 * XXX  Need a switch to decide whether to use DNS name instead of a simple
 
534
 *      IP address.
 
535
 *
 
536
 * FIX  Use something other than snprint_hexstring which doesn't add 
 
537
 *      trailing spaces and (sometimes embedded) newlines...
 
538
 */
 
539
#ifdef SNMP_TESTING_CODE
 
540
char           *
 
541
dump_snmpEngineID(const u_char * estring, size_t * estring_len)
 
542
{
 
543
#define eb(b)   ( *(esp+b) & 0xff )
 
544
 
 
545
    int             rval = SNMPERR_SUCCESS, gotviolation = 0, slen = 0;
 
546
    u_int           remaining_len;
 
547
 
 
548
    char            buf[SNMP_MAXBUF], *s = NULL, *t;
 
549
    const u_char   *esp = estring;
 
550
 
 
551
    struct in_addr  iaddr;
 
552
 
 
553
 
 
554
 
 
555
    /*
 
556
     * Sanity check.
 
557
     */
 
558
    if (!estring || (*estring_len <= 0)) {
 
559
        QUITFUN(SNMPERR_GENERR, dump_snmpEngineID_quit);
 
560
    }
 
561
    remaining_len = *estring_len;
 
562
    memset(buf, 0, SNMP_MAXBUF);
 
563
 
 
564
 
 
565
 
 
566
    /*
 
567
     * Test first bit.  Return immediately with a hex string, or
 
568
     * begin by formatting the enterprise ID.
 
569
     */
 
570
    if (!(*esp & 0x80)) {
 
571
        snprint_hexstring(buf, SNMP_MAXBUF, esp, remaining_len);
 
572
        s = strchr(buf, '\0');
 
573
        s -= 1;
 
574
        goto dump_snmpEngineID_quit;
 
575
    }
 
576
 
 
577
    s = buf;
 
578
    s += sprintf(s, "enterprise %d, ", ((*(esp + 0) & 0x7f) << 24) |
 
579
                 ((*(esp + 1) & 0xff) << 16) |
 
580
                 ((*(esp + 2) & 0xff) << 8) | ((*(esp + 3) & 0xff)));
 
581
    /*
 
582
     * XXX  Ick. 
 
583
     */
 
584
 
 
585
    if (remaining_len < 5) {    /* XXX  Violating string. */
 
586
        goto dump_snmpEngineID_quit;
 
587
    }
 
588
 
 
589
    esp += 4;                   /* Incremented one more in the switch below. */
 
590
    remaining_len -= 5;
 
591
 
 
592
 
 
593
 
 
594
    /*
 
595
     * Act on the fifth byte.
 
596
     */
 
597
    switch ((int) *esp++) {
 
598
    case 1:                    /* IPv4 address. */
 
599
 
 
600
        if (remaining_len < 4)
 
601
            goto dump_snmpEngineID_violation;
 
602
        memcpy(&iaddr.s_addr, esp, 4);
 
603
 
 
604
        if (!(t = inet_ntoa(iaddr)))
 
605
            goto dump_snmpEngineID_violation;
 
606
        s += sprintf(s, "%s", t);
 
607
 
 
608
        esp += 4;
 
609
        remaining_len -= 4;
 
610
        break;
 
611
 
 
612
    case 2:                    /* IPv6 address. */
 
613
 
 
614
        if (remaining_len < 16)
 
615
            goto dump_snmpEngineID_violation;
 
616
 
 
617
        s += sprintf(s,
 
618
                     "%02X%02X %02X%02X %02X%02X %02X%02X::"
 
619
                     "%02X%02X %02X%02X %02X%02X %02X%02X",
 
620
                     eb(0), eb(1), eb(2), eb(3),
 
621
                     eb(4), eb(5), eb(6), eb(7),
 
622
                     eb(8), eb(9), eb(10), eb(11),
 
623
                     eb(12), eb(13), eb(14), eb(15));
 
624
 
 
625
        esp += 16;
 
626
        remaining_len -= 16;
 
627
        break;
 
628
 
 
629
    case 3:                    /* MAC address. */
 
630
 
 
631
        if (remaining_len < 6)
 
632
            goto dump_snmpEngineID_violation;
 
633
 
 
634
        s += sprintf(s, "%02X:%02X:%02X:%02X:%02X:%02X",
 
635
                     eb(0), eb(1), eb(2), eb(3), eb(4), eb(5));
 
636
 
 
637
        esp += 6;
 
638
        remaining_len -= 6;
 
639
        break;
 
640
 
 
641
    case 4:                    /* Text. */
 
642
 
 
643
        /*
 
644
         * Doesn't exist on all (many) architectures 
 
645
         */
 
646
        /*
 
647
         * s += snprintf(s, remaining_len+3, "\"%s\"", esp); 
 
648
         */
 
649
        s += sprintf(s, "\"%s\"", esp);
 
650
        goto dump_snmpEngineID_quit;
 
651
        break;
 
652
     /*NOTREACHED*/ case 5:    /* Octets. */
 
653
 
 
654
        snprint_hexstring(s, (SNMP_MAXBUF - (s-buf)),
 
655
                          esp, remaining_len);
 
656
        s = strchr(buf, '\0');
 
657
        s -= 1;
 
658
        goto dump_snmpEngineID_quit;
 
659
        break;
 
660
       /*NOTREACHED*/ dump_snmpEngineID_violation:
 
661
    case 0:                    /* Violation of RESERVED, 
 
662
                                 * *   -OR- of expected length.
 
663
                                 */
 
664
        gotviolation = 1;
 
665
        s += sprintf(s, "!!! ");
 
666
 
 
667
    default:                   /* Unknown encoding. */
 
668
 
 
669
        if (!gotviolation) {
 
670
            s += sprintf(s, "??? ");
 
671
        }
 
672
        snprint_hexstring(s, (SNMP_MAXBUF - (s-buf)),
 
673
                          esp, remaining_len);
 
674
        s = strchr(buf, '\0');
 
675
        s -= 1;
 
676
 
 
677
        goto dump_snmpEngineID_quit;
 
678
 
 
679
    }                           /* endswitch */
 
680
 
 
681
 
 
682
 
 
683
    /*
 
684
     * Cases 1-3 (IP and MAC addresses) should not have trailing
 
685
     * octets, but perhaps they do.  Throw them in too.  XXX
 
686
     */
 
687
    if (remaining_len > 0) {
 
688
        s += sprintf(s, " (??? ");
 
689
 
 
690
        snprint_hexstring(s, (SNMP_MAXBUF - (s-buf)),
 
691
                          esp, remaining_len);
 
692
        s = strchr(buf, '\0');
 
693
        s -= 1;
 
694
 
 
695
        s += sprintf(s, ")");
 
696
    }
 
697
 
 
698
 
 
699
 
 
700
  dump_snmpEngineID_quit:
 
701
    if (s) {
 
702
        slen = s - buf + 1;
 
703
        s = calloc(1, slen);
 
704
        memcpy(s, buf, (slen) - 1);
 
705
    }
 
706
 
 
707
    memset(buf, 0, SNMP_MAXBUF);        /* XXX -- Overkill? XXX: Yes! */
 
708
 
 
709
    return s;
 
710
 
 
711
#undef eb
 
712
}                               /* end dump_snmpEngineID() */
 
713
#endif                          /* SNMP_TESTING_CODE */
 
714
 
 
715
 
 
716
/**
 
717
 * create a new time marker.
 
718
 * NOTE: Caller must free time marker when no longer needed.
 
719
 */
 
720
marker_t
 
721
atime_newMarker(void)
 
722
{
 
723
    marker_t        pm = (marker_t) calloc(1, sizeof(struct timeval));
 
724
    gettimeofday((struct timeval *) pm, 0);
 
725
    return pm;
 
726
}
 
727
 
 
728
/**
 
729
 * set a time marker.
 
730
 */
 
731
void
 
732
atime_setMarker(marker_t pm)
 
733
{
 
734
    if (!pm)
 
735
        return;
 
736
 
 
737
    gettimeofday((struct timeval *) pm, 0);
 
738
}
 
739
 
 
740
 
 
741
/**
 
742
 * Returns the difference (in msec) between the two markers
 
743
 */
 
744
long
 
745
atime_diff(marker_t first, marker_t second)
 
746
{
 
747
    struct timeval *tv1, *tv2, diff;
 
748
 
 
749
    tv1 = (struct timeval *) first;
 
750
    tv2 = (struct timeval *) second;
 
751
 
 
752
    diff.tv_sec = tv2->tv_sec - tv1->tv_sec - 1;
 
753
    diff.tv_usec = tv2->tv_usec - tv1->tv_usec + 1000000;
 
754
 
 
755
    return (diff.tv_sec * 1000 + diff.tv_usec / 1000);
 
756
}
 
757
 
 
758
/**
 
759
 * Returns the difference (in u_long msec) between the two markers
 
760
 */
 
761
u_long
 
762
uatime_diff(marker_t first, marker_t second)
 
763
{
 
764
    struct timeval *tv1, *tv2, diff;
 
765
 
 
766
    tv1 = (struct timeval *) first;
 
767
    tv2 = (struct timeval *) second;
 
768
 
 
769
    diff.tv_sec = tv2->tv_sec - tv1->tv_sec - 1;
 
770
    diff.tv_usec = tv2->tv_usec - tv1->tv_usec + 1000000;
 
771
 
 
772
    return (((u_long) diff.tv_sec) * 1000 + diff.tv_usec / 1000);
 
773
}
 
774
 
 
775
/**
 
776
 * Returns the difference (in u_long 1/100th secs) between the two markers
 
777
 * (functionally this is what sysUpTime needs)
 
778
 */
 
779
u_long
 
780
uatime_hdiff(marker_t first, marker_t second)
 
781
{
 
782
    struct timeval *tv1, *tv2, diff;
 
783
    u_long          res;
 
784
 
 
785
    tv1 = (struct timeval *) first;
 
786
    tv2 = (struct timeval *) second;
 
787
 
 
788
    diff.tv_sec = tv2->tv_sec - tv1->tv_sec - 1;
 
789
    diff.tv_usec = tv2->tv_usec - tv1->tv_usec + 1000000;
 
790
 
 
791
    res = ((u_long) diff.tv_sec) * 100 + diff.tv_usec / 10000;
 
792
    return res;
 
793
}
 
794
 
 
795
/**
 
796
 * Test: Has (marked time plus delta) exceeded current time (in msec) ?
 
797
 * Returns 0 if test fails or cannot be tested (no marker).
 
798
 */
 
799
int
 
800
atime_ready(marker_t pm, int deltaT)
 
801
{
 
802
    marker_t        now;
 
803
    long            diff;
 
804
    if (!pm)
 
805
        return 0;
 
806
 
 
807
    now = atime_newMarker();
 
808
 
 
809
    diff = atime_diff(pm, now);
 
810
    free(now);
 
811
    if (diff < deltaT)
 
812
        return 0;
 
813
 
 
814
    return 1;
 
815
}
 
816
 
 
817
/**
 
818
 * Test: Has (marked time plus delta) exceeded current time (in msec) ?
 
819
 * Returns 0 if test fails or cannot be tested (no marker).
 
820
 */
 
821
int
 
822
uatime_ready(marker_t pm, unsigned int deltaT)
 
823
{
 
824
    marker_t        now;
 
825
    u_long          diff;
 
826
    if (!pm)
 
827
        return 0;
 
828
 
 
829
    now = atime_newMarker();
 
830
 
 
831
    diff = uatime_diff(pm, now);
 
832
    free(now);
 
833
    if (diff < deltaT)
 
834
        return 0;
 
835
 
 
836
    return 1;
 
837
}
 
838
 
 
839
 
 
840
        /*
 
841
         * Time-related utility functions
 
842
         */
 
843
 
 
844
/**
 
845
 * Return the number of timeTicks since the given marker 
 
846
 */
 
847
int
 
848
marker_tticks(marker_t pm)
 
849
{
 
850
    int             res;
 
851
    marker_t        now = atime_newMarker();
 
852
 
 
853
    res = atime_diff(pm, now);
 
854
    free(now);
 
855
    return res / 10;            /* atime_diff works in msec, not csec */
 
856
}
 
857
 
 
858
int
 
859
timeval_tticks(struct timeval *tv)
 
860
{
 
861
    return marker_tticks((marker_t) tv);
 
862
}