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

« back to all changes in this revision

Viewing changes to agent/mibgroup/agentx/protocol.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
/* Portions of this file are subject to the following copyright(s).  See
 
2
 * the Net-SNMP's COPYING file for more details and other copyrights
 
3
 * that may apply:
 
4
 */
 
5
/*
 
6
 * Portions of this file are copyrighted by:
 
7
 * Copyright ļæ½ 2003 Sun Microsystems, Inc. All rights reserved.
 
8
 * Use is subject to license terms specified in the COPYING file
 
9
 * distributed with the Net-SNMP package.
 
10
 */
 
11
 
 
12
#include <net-snmp/net-snmp-config.h>
 
13
 
 
14
#include <stdio.h>
 
15
#include <errno.h>
 
16
#if HAVE_STDLIB_H
 
17
#include <stdlib.h>
 
18
#endif
 
19
#if HAVE_STRING_H
 
20
#include <string.h>
 
21
#else
 
22
#include <strings.h>
 
23
#endif
 
24
#if HAVE_UNISTD_H
 
25
#include <unistd.h>
 
26
#endif
 
27
#include <sys/types.h>
 
28
#if TIME_WITH_SYS_TIME
 
29
# ifdef WIN32
 
30
#  include <sys/timeb.h>
 
31
# else
 
32
#  include <sys/time.h>
 
33
# endif
 
34
# include <time.h>
 
35
#else
 
36
# if HAVE_SYS_TIME_H
 
37
#  include <sys/time.h>
 
38
# else
 
39
#  include <time.h>
 
40
# endif
 
41
#endif
 
42
#if HAVE_NETINET_IN_H
 
43
#include <netinet/in.h>
 
44
#endif
 
45
#if HAVE_ARPA_INET_H
 
46
#include <arpa/inet.h>
 
47
#endif
 
48
 
 
49
#if HAVE_DMALLOC_H
 
50
#include <dmalloc.h>
 
51
#endif
 
52
 
 
53
#if HAVE_WINSOCK_H
 
54
#include <winsock.h>
 
55
#endif
 
56
 
 
57
#include <net-snmp/net-snmp-includes.h>
 
58
 
 
59
#include "agentx/protocol.h"
 
60
 
 
61
const char     *
 
62
agentx_cmd(u_char code)
 
63
{
 
64
    switch (code) {
 
65
    case AGENTX_MSG_OPEN:
 
66
        return "Open";
 
67
    case AGENTX_MSG_CLOSE:
 
68
        return "Close";
 
69
    case AGENTX_MSG_REGISTER:
 
70
        return "Register";
 
71
    case AGENTX_MSG_UNREGISTER:
 
72
        return "Unregister";
 
73
    case AGENTX_MSG_GET:
 
74
        return "Get";
 
75
    case AGENTX_MSG_GETNEXT:
 
76
        return "Get Next";
 
77
    case AGENTX_MSG_GETBULK:
 
78
        return "Get Bulk";
 
79
    case AGENTX_MSG_TESTSET:
 
80
        return "Test Set";
 
81
    case AGENTX_MSG_COMMITSET:
 
82
        return "Commit Set";
 
83
    case AGENTX_MSG_UNDOSET:
 
84
        return "Undo Set";
 
85
    case AGENTX_MSG_CLEANUPSET:
 
86
        return "Cleanup Set";
 
87
    case AGENTX_MSG_NOTIFY:
 
88
        return "Notify";
 
89
    case AGENTX_MSG_PING:
 
90
        return "Ping";
 
91
    case AGENTX_MSG_INDEX_ALLOCATE:
 
92
        return "Index Allocate";
 
93
    case AGENTX_MSG_INDEX_DEALLOCATE:
 
94
        return "Index Deallocate";
 
95
    case AGENTX_MSG_ADD_AGENT_CAPS:
 
96
        return "Add Agent Caps";
 
97
    case AGENTX_MSG_REMOVE_AGENT_CAPS:
 
98
        return "Remove Agent Caps";
 
99
    case AGENTX_MSG_RESPONSE:
 
100
        return "Response";
 
101
    default:
 
102
        return "Unknown";
 
103
    }
 
104
}
 
105
 
 
106
int
 
107
agentx_realloc_build_int(u_char ** buf, size_t * buf_len, size_t * out_len,
 
108
                         int allow_realloc,
 
109
                         unsigned int value, int network_order)
 
110
{
 
111
    unsigned int    ivalue = value;
 
112
    size_t          ilen = *out_len;
 
113
#ifdef WORDS_BIGENDIAN
 
114
    unsigned int    i = 0;
 
115
#endif
 
116
 
 
117
    while ((*out_len + 4) >= *buf_len) {
 
118
        if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
119
            return 0;
 
120
        }
 
121
    }
 
122
 
 
123
    if (network_order) {
 
124
#ifndef WORDS_BIGENDIAN
 
125
        value = ntohl(value);
 
126
#endif
 
127
        memmove((*buf + *out_len), &value, 4);
 
128
        *out_len += 4;
 
129
    } else {
 
130
#ifndef WORDS_BIGENDIAN
 
131
        memmove((*buf + *out_len), &value, 4);
 
132
        *out_len += 4;
 
133
#else
 
134
        for (i = 0; i < 4; i++) {
 
135
            *(*buf + *out_len) = (u_char) value & 0xff;
 
136
            (*out_len)++;
 
137
            value >>= 8;
 
138
        }
 
139
#endif
 
140
    }
 
141
    DEBUGDUMPSETUP("send", (*buf + ilen), 4);
 
142
    DEBUGMSG(("dumpv_send", "  Integer:\t%lu (0x%.2lX)\n", ivalue,
 
143
              ivalue));
 
144
    return 1;
 
145
}
 
146
 
 
147
void
 
148
agentx_build_int(u_char * bufp, u_int value, int network_byte_order)
 
149
{
 
150
    u_char         *orig_bufp = bufp;
 
151
    u_int           orig_val = value;
 
152
 
 
153
    if (network_byte_order) {
 
154
#ifndef WORDS_BIGENDIAN
 
155
        value = ntohl(value);
 
156
#endif
 
157
        memmove(bufp, &value, 4);
 
158
    } else {
 
159
#ifndef WORDS_BIGENDIAN
 
160
        memmove(bufp, &value, 4);
 
161
#else
 
162
        *bufp = (u_char) value & 0xff;
 
163
        value >>= 8;
 
164
        bufp++;
 
165
        *bufp = (u_char) value & 0xff;
 
166
        value >>= 8;
 
167
        bufp++;
 
168
        *bufp = (u_char) value & 0xff;
 
169
        value >>= 8;
 
170
        bufp++;
 
171
        *bufp = (u_char) value & 0xff;
 
172
#endif
 
173
    }
 
174
    DEBUGDUMPSETUP("send", orig_bufp, 4);
 
175
    DEBUGMSG(("dumpv_send", "  Integer:\t%ld (0x%.2X)\n", orig_val,
 
176
              orig_val));
 
177
}
 
178
 
 
179
int
 
180
agentx_realloc_build_short(u_char ** buf, size_t * buf_len,
 
181
                           size_t * out_len, int allow_realloc,
 
182
                           unsigned short value, int network_order)
 
183
{
 
184
    unsigned short  ivalue = value;
 
185
    size_t          ilen = *out_len;
 
186
#ifdef WORDS_BIGENDIAN
 
187
    unsigned short  i = 0;
 
188
#endif
 
189
 
 
190
    while ((*out_len + 2) >= *buf_len) {
 
191
        if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
192
            return 0;
 
193
        }
 
194
    }
 
195
 
 
196
    if (network_order) {
 
197
#ifndef WORDS_BIGENDIAN
 
198
        value = ntohs(value);
 
199
#endif
 
200
        memmove((*buf + *out_len), &value, 2);
 
201
        *out_len += 2;
 
202
    } else {
 
203
#ifndef WORDS_BIGENDIAN
 
204
        memmove((*buf + *out_len), &value, 2);
 
205
        *out_len += 2;
 
206
#else
 
207
        for (i = 0; i < 2; i++) {
 
208
            *(*buf + *out_len) = (u_char) value & 0xff;
 
209
            (*out_len)++;
 
210
            value >>= 8;
 
211
        }
 
212
#endif
 
213
    }
 
214
    DEBUGDUMPSETUP("send", (*buf + ilen), 2);
 
215
    DEBUGMSG(("dumpv_send", "  Short:\t%hu (0x%.2hX)\n", ivalue, ivalue));
 
216
    return 1;
 
217
}
 
218
 
 
219
int
 
220
agentx_realloc_build_oid(u_char ** buf, size_t * buf_len, size_t * out_len,
 
221
                         int allow_realloc,
 
222
                         int inclusive, oid * name, size_t name_len,
 
223
                         int network_order)
 
224
{
 
225
    size_t          ilen = *out_len, i = 0;
 
226
    int             prefix = 0;
 
227
 
 
228
    DEBUGPRINTINDENT("dumpv_send");
 
229
    DEBUGMSG(("dumpv_send", "OID: "));
 
230
    DEBUGMSGOID(("dumpv_send", name, name_len));
 
231
    DEBUGMSG(("dumpv_send", "\n"));
 
232
 
 
233
    if (name_len == 2 && (name[0] == 0 && name[1] == 0)) {
 
234
        name_len = 0;           /* Null OID */
 
235
    }
 
236
 
 
237
    /*
 
238
     * 'Compact' internet OIDs 
 
239
     */
 
240
    if (name_len >= 5 && (name[0] == 1 && name[1] == 3 &&
 
241
                          name[2] == 6 && name[3] == 1)) {
 
242
        prefix = name[4];
 
243
        name += 5;
 
244
        name_len -= 5;
 
245
    }
 
246
 
 
247
    while ((*out_len + 4 + (4 * name_len)) >= *buf_len) {
 
248
        if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
249
            return 0;
 
250
        }
 
251
    }
 
252
 
 
253
    *(*buf + *out_len) = (u_char) name_len;
 
254
    (*out_len)++;
 
255
    *(*buf + *out_len) = (u_char) prefix;
 
256
    (*out_len)++;
 
257
    *(*buf + *out_len) = (u_char) inclusive;
 
258
    (*out_len)++;
 
259
    *(*buf + *out_len) = (u_char) 0x00;
 
260
    (*out_len)++;
 
261
 
 
262
    DEBUGDUMPHEADER("send", "OID Header");
 
263
    DEBUGDUMPSETUP("send", (*buf + ilen), 4);
 
264
    DEBUGMSG(("dumpv_send", "  # subids:\t%d (0x%.2X)\n", name_len,
 
265
              name_len));
 
266
    DEBUGPRINTINDENT("dumpv_send");
 
267
    DEBUGMSG(("dumpv_send", "  prefix:\t%d (0x%.2X)\n", prefix, prefix));
 
268
    DEBUGPRINTINDENT("dumpv_send");
 
269
    DEBUGMSG(("dumpv_send", "  inclusive:\t%d (0x%.2X)\n", inclusive,
 
270
              inclusive));
 
271
    DEBUGINDENTLESS();
 
272
    DEBUGDUMPHEADER("send", "OID Segments");
 
273
 
 
274
    for (i = 0; i < name_len; i++) {
 
275
        if (!agentx_realloc_build_int(buf, buf_len, out_len, allow_realloc,
 
276
                                      name[i], network_order)) {
 
277
            DEBUGINDENTLESS();
 
278
            return 0;
 
279
        }
 
280
    }
 
281
    DEBUGINDENTLESS();
 
282
 
 
283
    return 1;
 
284
}
 
285
 
 
286
int
 
287
agentx_realloc_build_string(u_char ** buf, size_t * buf_len,
 
288
                            size_t * out_len, int allow_realloc,
 
289
                            u_char * string, size_t string_len,
 
290
                            int network_order)
 
291
{
 
292
    size_t          ilen = *out_len, i = 0;
 
293
 
 
294
    while ((*out_len + 4 + (4 * ((string_len + 3) / 4))) >= *buf_len) {
 
295
        if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
296
            return 0;
 
297
        }
 
298
    }
 
299
 
 
300
    DEBUGDUMPHEADER("send", "Build String");
 
301
    DEBUGDUMPHEADER("send", "length");
 
302
    if (!agentx_realloc_build_int(buf, buf_len, out_len, allow_realloc,
 
303
                                  string_len, network_order)) {
 
304
        DEBUGINDENTLESS();
 
305
        DEBUGINDENTLESS();
 
306
        return 0;
 
307
    }
 
308
 
 
309
    if (string_len == 0) {
 
310
        DEBUGMSG(("dumpv_send", "  String: <empty>\n"));
 
311
        DEBUGINDENTLESS();
 
312
        DEBUGINDENTLESS();
 
313
        return 1;
 
314
    }
 
315
 
 
316
    memmove((*buf + *out_len), string, string_len);
 
317
    *out_len += string_len;
 
318
 
 
319
    /*
 
320
     * Pad to a multiple of 4 bytes if necessary (per RFC 2741).  
 
321
     */
 
322
 
 
323
    if (string_len % 4 != 0) {
 
324
        for (i = 0; i < 4 - (string_len % 4); i++) {
 
325
            *(*buf + *out_len) = 0;
 
326
            (*out_len)++;
 
327
        }
 
328
    }
 
329
 
 
330
    DEBUGDUMPSETUP("send", (*buf + ilen + 4), ((string_len + 3) / 4) * 4);
 
331
    DEBUGMSG(("dumpv_send", "  String:\t%s\n", string));
 
332
    DEBUGINDENTLESS();
 
333
    DEBUGINDENTLESS();
 
334
    return 1;
 
335
}
 
336
 
 
337
#ifdef OPAQUE_SPECIAL_TYPES
 
338
int
 
339
agentx_realloc_build_double(u_char ** buf, size_t * buf_len,
 
340
                            size_t * out_len, int allow_realloc,
 
341
                            double double_val, int network_order)
 
342
{
 
343
    union {
 
344
        double          doubleVal;
 
345
        int             intVal[2];
 
346
        char            c[sizeof(double)];
 
347
    } du;
 
348
    int             tmp;
 
349
    u_char          opaque_buffer[3 + sizeof(double)];
 
350
 
 
351
    opaque_buffer[0] = ASN_OPAQUE_TAG1;
 
352
    opaque_buffer[1] = ASN_OPAQUE_DOUBLE;
 
353
    opaque_buffer[2] = sizeof(double);
 
354
 
 
355
    du.doubleVal = double_val;
 
356
    tmp = htonl(du.intVal[0]);
 
357
    du.intVal[0] = htonl(du.intVal[1]);
 
358
    du.intVal[1] = tmp;
 
359
    memcpy(&opaque_buffer[3], &du.c[0], sizeof(double));
 
360
 
 
361
    return agentx_realloc_build_string(buf, buf_len, out_len,
 
362
                                       allow_realloc, opaque_buffer,
 
363
                                       3 + sizeof(double), network_order);
 
364
}
 
365
 
 
366
int
 
367
agentx_realloc_build_float(u_char ** buf, size_t * buf_len,
 
368
                           size_t * out_len, int allow_realloc,
 
369
                           float float_val, int network_order)
 
370
{
 
371
    union {
 
372
        float           floatVal;
 
373
        int             intVal;
 
374
        char            c[sizeof(float)];
 
375
    } fu;
 
376
    u_char          opaque_buffer[3 + sizeof(float)];
 
377
 
 
378
    opaque_buffer[0] = ASN_OPAQUE_TAG1;
 
379
    opaque_buffer[1] = ASN_OPAQUE_FLOAT;
 
380
    opaque_buffer[2] = sizeof(float);
 
381
 
 
382
    fu.floatVal = float_val;
 
383
    fu.intVal = htonl(fu.intVal);
 
384
    memcpy(&opaque_buffer[3], &fu.c[0], sizeof(float));
 
385
 
 
386
    return agentx_realloc_build_string(buf, buf_len, out_len,
 
387
                                       allow_realloc, opaque_buffer,
 
388
                                       3 + sizeof(float), network_order);
 
389
}
 
390
#endif
 
391
 
 
392
int
 
393
agentx_realloc_build_varbind(u_char ** buf, size_t * buf_len,
 
394
                             size_t * out_len, int allow_realloc,
 
395
                             netsnmp_variable_list * vp, int network_order)
 
396
{
 
397
    DEBUGDUMPHEADER("send", "VarBind");
 
398
    DEBUGDUMPHEADER("send", "type");
 
399
#ifdef OPAQUE_SPECIAL_TYPES
 
400
    if ((vp->type == ASN_OPAQUE_FLOAT) || (vp->type == ASN_OPAQUE_DOUBLE)
 
401
        || (vp->type == ASN_OPAQUE_I64) || (vp->type == ASN_OPAQUE_U64)
 
402
        || (vp->type == ASN_OPAQUE_COUNTER64)) {
 
403
        if (!agentx_realloc_build_short
 
404
            (buf, buf_len, out_len, allow_realloc,
 
405
             (unsigned short) ASN_OPAQUE, network_order)) {
 
406
            DEBUGINDENTLESS();
 
407
            DEBUGINDENTLESS();
 
408
            return 0;
 
409
        }
 
410
    } else
 
411
#endif
 
412
    if (vp->type == ASN_PRIV_INCL_RANGE || vp->type == ASN_PRIV_EXCL_RANGE) {
 
413
        if (!agentx_realloc_build_short
 
414
            (buf, buf_len, out_len, allow_realloc,
 
415
             (unsigned short) ASN_OBJECT_ID, network_order)) {
 
416
            DEBUGINDENTLESS();
 
417
            DEBUGINDENTLESS();
 
418
            return 0;
 
419
        }
 
420
    } else {
 
421
        if (!agentx_realloc_build_short
 
422
            (buf, buf_len, out_len, allow_realloc,
 
423
             (unsigned short) vp->type, network_order)) {
 
424
            DEBUGINDENTLESS();
 
425
            DEBUGINDENTLESS();
 
426
            return 0;
 
427
        }
 
428
    }
 
429
 
 
430
    while ((*out_len + 2) >= *buf_len) {
 
431
        if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
432
            DEBUGINDENTLESS();
 
433
            DEBUGINDENTLESS();
 
434
            return 0;
 
435
        }
 
436
    }
 
437
 
 
438
    *(*buf + *out_len) = 0;
 
439
    (*out_len)++;
 
440
    *(*buf + *out_len) = 0;
 
441
    (*out_len)++;
 
442
    DEBUGINDENTLESS();
 
443
 
 
444
    DEBUGDUMPHEADER("send", "name");
 
445
    if (!agentx_realloc_build_oid(buf, buf_len, out_len, allow_realloc, 0,
 
446
                                  vp->name, vp->name_length,
 
447
                                  network_order)) {
 
448
        DEBUGINDENTLESS();
 
449
        return 0;
 
450
    }
 
451
    DEBUGINDENTLESS();
 
452
 
 
453
    DEBUGDUMPHEADER("send", "value");
 
454
    switch (vp->type) {
 
455
 
 
456
    case ASN_INTEGER:
 
457
    case ASN_COUNTER:
 
458
    case ASN_GAUGE:
 
459
    case ASN_TIMETICKS:
 
460
        if (!agentx_realloc_build_int(buf, buf_len, out_len, allow_realloc,
 
461
                                      *(vp->val.integer), network_order)) {
 
462
            DEBUGINDENTLESS();
 
463
            DEBUGINDENTLESS();
 
464
            return 0;
 
465
        }
 
466
        break;
 
467
 
 
468
#ifdef OPAQUE_SPECIAL_TYPES
 
469
    case ASN_OPAQUE_FLOAT:
 
470
        DEBUGDUMPHEADER("send", "Build Opaque Float");
 
471
        DEBUGPRINTINDENT("dumpv_send");
 
472
        DEBUGMSG(("dumpv_send", "  Float:\t%f\n", *(vp->val.floatVal)));
 
473
        if (!agentx_realloc_build_float
 
474
            (buf, buf_len, out_len, allow_realloc, *(vp->val.floatVal),
 
475
             network_order)) {
 
476
            DEBUGINDENTLESS();
 
477
            DEBUGINDENTLESS();
 
478
            DEBUGINDENTLESS();
 
479
            return 0;
 
480
        }
 
481
        DEBUGINDENTLESS();
 
482
        break;
 
483
 
 
484
    case ASN_OPAQUE_DOUBLE:
 
485
        DEBUGDUMPHEADER("send", "Build Opaque Double");
 
486
        DEBUGPRINTINDENT("dumpv_send");
 
487
        DEBUGMSG(("dumpv_send", "  Double:\t%lf\n", *(vp->val.doubleVal)));
 
488
        if (!agentx_realloc_build_double
 
489
            (buf, buf_len, out_len, allow_realloc, *(vp->val.doubleVal),
 
490
             network_order)) {
 
491
            DEBUGINDENTLESS();
 
492
            DEBUGINDENTLESS();
 
493
            DEBUGINDENTLESS();
 
494
            return 0;
 
495
        }
 
496
        DEBUGINDENTLESS();
 
497
        break;
 
498
 
 
499
    case ASN_OPAQUE_I64:
 
500
    case ASN_OPAQUE_U64:
 
501
    case ASN_OPAQUE_COUNTER64:
 
502
        /*
 
503
         * XXX - TODO - encode as raw OPAQUE for now (so fall through
 
504
         * here).  
 
505
         */
 
506
#endif
 
507
 
 
508
    case ASN_OCTET_STR:
 
509
    case ASN_IPADDRESS:
 
510
    case ASN_OPAQUE:
 
511
        if (!agentx_realloc_build_string
 
512
            (buf, buf_len, out_len, allow_realloc, vp->val.string,
 
513
             vp->val_len, network_order)) {
 
514
            DEBUGINDENTLESS();
 
515
            DEBUGINDENTLESS();
 
516
            return 0;
 
517
        }
 
518
        break;
 
519
 
 
520
    case ASN_OBJECT_ID:
 
521
    case ASN_PRIV_EXCL_RANGE:
 
522
    case ASN_PRIV_INCL_RANGE:
 
523
        if (!agentx_realloc_build_oid
 
524
            (buf, buf_len, out_len, allow_realloc, 1, vp->val.objid,
 
525
             vp->val_len / sizeof(oid), network_order)) {
 
526
            DEBUGINDENTLESS();
 
527
            DEBUGINDENTLESS();
 
528
            return 0;
 
529
        }
 
530
        break;
 
531
 
 
532
    case ASN_COUNTER64:
 
533
        if (network_order) {
 
534
            DEBUGDUMPHEADER("send", "Build Counter64 (high, low)");
 
535
            if (!agentx_realloc_build_int
 
536
                (buf, buf_len, out_len, allow_realloc,
 
537
                 vp->val.counter64->high, network_order)
 
538
                || !agentx_realloc_build_int(buf, buf_len, out_len,
 
539
                                             allow_realloc,
 
540
                                             vp->val.counter64->low,
 
541
                                             network_order)) {
 
542
                DEBUGINDENTLESS();
 
543
                DEBUGINDENTLESS();
 
544
                DEBUGINDENTLESS();
 
545
                return 0;
 
546
            }
 
547
        } else {
 
548
            DEBUGDUMPHEADER("send", "Build Counter64 (low, high)");
 
549
            if (!agentx_realloc_build_int
 
550
                (buf, buf_len, out_len, allow_realloc,
 
551
                 vp->val.counter64->low, network_order)
 
552
                || !agentx_realloc_build_int(buf, buf_len, out_len,
 
553
                                             allow_realloc,
 
554
                                             vp->val.counter64->high,
 
555
                                             network_order)) {
 
556
                DEBUGINDENTLESS();
 
557
                DEBUGINDENTLESS();
 
558
                DEBUGINDENTLESS();
 
559
                return 0;
 
560
            }
 
561
        }
 
562
        break;
 
563
 
 
564
    case ASN_NULL:
 
565
    case SNMP_NOSUCHOBJECT:
 
566
    case SNMP_NOSUCHINSTANCE:
 
567
    case SNMP_ENDOFMIBVIEW:
 
568
        break;
 
569
 
 
570
    default:
 
571
        DEBUGMSGTL(("agentx_build_varbind", "unknown type %d (0x%02x)\n",
 
572
                    vp->type, vp->type));
 
573
        DEBUGINDENTLESS();
 
574
        DEBUGINDENTLESS();
 
575
        return 0;
 
576
    }
 
577
    DEBUGINDENTLESS();
 
578
    DEBUGINDENTLESS();
 
579
    return 1;
 
580
}
 
581
 
 
582
int
 
583
agentx_realloc_build_header(u_char ** buf, size_t * buf_len,
 
584
                            size_t * out_len, int allow_realloc,
 
585
                            netsnmp_pdu *pdu)
 
586
{
 
587
    size_t          ilen = *out_len;
 
588
    const int       network_order =
 
589
        pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER;
 
590
 
 
591
    while ((*out_len + 4) >= *buf_len) {
 
592
        if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
593
            return 0;
 
594
        }
 
595
    }
 
596
 
 
597
    /*
 
598
     * First 4 bytes are version, pdu type, flags, and a 0 reserved byte.  
 
599
     */
 
600
 
 
601
    *(*buf + *out_len) = 1;
 
602
    (*out_len)++;
 
603
    *(*buf + *out_len) = pdu->command;
 
604
    (*out_len)++;
 
605
    *(*buf + *out_len) = (u_char) (pdu->flags & AGENTX_MSG_FLAGS_MASK);
 
606
    (*out_len)++;
 
607
    *(*buf + *out_len) = 0;
 
608
    (*out_len)++;
 
609
 
 
610
    DEBUGDUMPHEADER("send", "AgentX Header");
 
611
    DEBUGDUMPSETUP("send", (*buf + ilen), 4);
 
612
    DEBUGMSG(("dumpv_send", "  Version:\t%d\n", (int) *(*buf + ilen)));
 
613
    DEBUGPRINTINDENT("dumpv_send");
 
614
    DEBUGMSG(("dumpv_send", "  Command:\t%d (%s)\n", pdu->command,
 
615
              agentx_cmd((u_char)pdu->command)));
 
616
    DEBUGPRINTINDENT("dumpv_send");
 
617
    DEBUGMSG(("dumpv_send", "  Flags:\t%02x\n", (int) *(*buf + ilen + 2)));
 
618
 
 
619
    DEBUGDUMPHEADER("send", "Session ID");
 
620
    if (!agentx_realloc_build_int(buf, buf_len, out_len, allow_realloc,
 
621
                                  pdu->sessid, network_order)) {
 
622
        DEBUGINDENTLESS();
 
623
        DEBUGINDENTLESS();
 
624
        return 0;
 
625
    }
 
626
    DEBUGINDENTLESS();
 
627
 
 
628
    DEBUGDUMPHEADER("send", "Transaction ID");
 
629
    if (!agentx_realloc_build_int(buf, buf_len, out_len, allow_realloc,
 
630
                                  pdu->transid, network_order)) {
 
631
        DEBUGINDENTLESS();
 
632
        DEBUGINDENTLESS();
 
633
        return 0;
 
634
    }
 
635
    DEBUGINDENTLESS();
 
636
 
 
637
    DEBUGDUMPHEADER("send", "Request ID");
 
638
    if (!agentx_realloc_build_int(buf, buf_len, out_len, allow_realloc,
 
639
                                  pdu->reqid, network_order)) {
 
640
        DEBUGINDENTLESS();
 
641
        DEBUGINDENTLESS();
 
642
        return 0;
 
643
    }
 
644
    DEBUGINDENTLESS();
 
645
 
 
646
    DEBUGDUMPHEADER("send", "Dummy Length :-(");
 
647
    if (!agentx_realloc_build_int(buf, buf_len, out_len, allow_realloc,
 
648
                                  0, network_order)) {
 
649
        DEBUGINDENTLESS();
 
650
        DEBUGINDENTLESS();
 
651
        return 0;
 
652
    }
 
653
    DEBUGINDENTLESS();
 
654
 
 
655
    if (pdu->flags & AGENTX_MSG_FLAG_NON_DEFAULT_CONTEXT) {
 
656
        DEBUGDUMPHEADER("send", "Community");
 
657
        if (!agentx_realloc_build_string
 
658
            (buf, buf_len, out_len, allow_realloc, pdu->community,
 
659
             pdu->community_len, network_order)) {
 
660
            DEBUGINDENTLESS();
 
661
            DEBUGINDENTLESS();
 
662
            return 0;
 
663
        }
 
664
        DEBUGINDENTLESS();
 
665
    }
 
666
 
 
667
    DEBUGINDENTLESS();
 
668
    return 1;
 
669
}
 
670
 
 
671
static int
 
672
_agentx_realloc_build(u_char ** buf, size_t * buf_len, size_t * out_len,
 
673
                      int allow_realloc,
 
674
                      netsnmp_session * session, netsnmp_pdu *pdu)
 
675
{
 
676
    size_t          ilen = *out_len, prefix_offset = 0;
 
677
    netsnmp_variable_list *vp;
 
678
    int             inc, i = 0;
 
679
    const int       network_order =
 
680
        pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER;
 
681
 
 
682
    session->s_snmp_errno = 0;
 
683
    session->s_errno = 0;
 
684
 
 
685
    /*
 
686
     * Various PDU types don't include context information (RFC 2741, p. 20). 
 
687
     */
 
688
    switch (pdu->command) {
 
689
    case AGENTX_MSG_OPEN:
 
690
    case AGENTX_MSG_CLOSE:
 
691
    case AGENTX_MSG_RESPONSE:
 
692
    case AGENTX_MSG_COMMITSET:
 
693
    case AGENTX_MSG_UNDOSET:
 
694
    case AGENTX_MSG_CLEANUPSET:
 
695
        pdu->flags &= ~(AGENTX_MSG_FLAG_NON_DEFAULT_CONTEXT);
 
696
    }
 
697
 
 
698
    /*
 
699
     * Build the header (and context if appropriate).  
 
700
     */
 
701
    if (!agentx_realloc_build_header
 
702
        (buf, buf_len, out_len, allow_realloc, pdu)) {
 
703
        return 0;
 
704
    }
 
705
 
 
706
    /*
 
707
     * Everything causes a response, except for agentx-Response-PDU and
 
708
     * agentx-CleanupSet-PDU.  
 
709
     */
 
710
 
 
711
    pdu->flags |= UCD_MSG_FLAG_EXPECT_RESPONSE;
 
712
 
 
713
    DEBUGDUMPHEADER("send", "AgentX Payload");
 
714
    switch (pdu->command) {
 
715
 
 
716
    case AGENTX_MSG_OPEN:
 
717
        /*
 
718
         * Timeout  
 
719
         */
 
720
        while ((*out_len + 4) >= *buf_len) {
 
721
            if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
722
                DEBUGINDENTLESS();
 
723
                return 0;
 
724
            }
 
725
        }
 
726
        *(*buf + *out_len) = (u_char) pdu->time;
 
727
        (*out_len)++;
 
728
        for (i = 0; i < 3; i++) {
 
729
            *(*buf + *out_len) = 0;
 
730
            (*out_len)++;
 
731
        }
 
732
        DEBUGDUMPHEADER("send", "Open Timeout");
 
733
        DEBUGDUMPSETUP("send", (*buf + *out_len - 4), 4);
 
734
        DEBUGMSG(("dumpv_send", "  Timeout:\t%d\n",
 
735
                  (int) *(*buf + *out_len - 4)));
 
736
        DEBUGINDENTLESS();
 
737
 
 
738
        DEBUGDUMPHEADER("send", "Open ID");
 
739
        if (!agentx_realloc_build_oid
 
740
            (buf, buf_len, out_len, allow_realloc, 0, pdu->variables->name,
 
741
             pdu->variables->name_length, network_order)) {
 
742
            DEBUGINDENTLESS();
 
743
            DEBUGINDENTLESS();
 
744
            return 0;
 
745
        }
 
746
        DEBUGINDENTLESS();
 
747
        DEBUGDUMPHEADER("send", "Open Description");
 
748
        if (!agentx_realloc_build_string
 
749
            (buf, buf_len, out_len, allow_realloc,
 
750
             pdu->variables->val.string, pdu->variables->val_len,
 
751
             network_order)) {
 
752
            DEBUGINDENTLESS();
 
753
            DEBUGINDENTLESS();
 
754
            return 0;
 
755
        }
 
756
        DEBUGINDENTLESS();
 
757
        break;
 
758
 
 
759
    case AGENTX_MSG_CLOSE:
 
760
        /*
 
761
         * Reason  
 
762
         */
 
763
        while ((*out_len + 4) >= *buf_len) {
 
764
            if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
765
                DEBUGINDENTLESS();
 
766
                return 0;
 
767
            }
 
768
        }
 
769
        *(*buf + *out_len) = (u_char) pdu->errstat;
 
770
        (*out_len)++;
 
771
        for (i = 0; i < 3; i++) {
 
772
            *(*buf + *out_len) = 0;
 
773
            (*out_len)++;
 
774
        }
 
775
        DEBUGDUMPHEADER("send", "Close Reason");
 
776
        DEBUGDUMPSETUP("send", (*buf + *out_len - 4), 4);
 
777
        DEBUGMSG(("dumpv_send", "  Reason:\t%d\n",
 
778
                  (int) *(*buf + *out_len - 4)));
 
779
        DEBUGINDENTLESS();
 
780
        break;
 
781
 
 
782
    case AGENTX_MSG_REGISTER:
 
783
    case AGENTX_MSG_UNREGISTER:
 
784
        while ((*out_len + 4) >= *buf_len) {
 
785
            if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
 
786
                DEBUGINDENTLESS();
 
787
                return 0;
 
788
            }
 
789
        }
 
790
        if (pdu->command == AGENTX_MSG_REGISTER) {
 
791
            *(*buf + *out_len) = (u_char) pdu->time;
 
792
        } else {
 
793
            *(*buf + *out_len) = 0;
 
794
        }
 
795
        (*out_len)++;
 
796
        *(*buf + *out_len) = (u_char) pdu->priority;
 
797
        (*out_len)++;
 
798
        *(*buf + *out_len) = (u_char) pdu->range_subid;
 
799
        (*out_len)++;
 
800
        *(*buf + *out_len) = (u_char) 0;
 
801
        (*out_len)++;
 
802
 
 
803
        DEBUGDUMPHEADER("send", "(Un)Register Header");
 
804
        DEBUGDUMPSETUP("send", (*buf + *out_len - 4), 4);
 
805
        if (pdu->command == AGENTX_MSG_REGISTER) {
 
806
            DEBUGMSG(("dumpv_send", "  Timeout:\t%d\n",
 
807
                      (int) *(*buf + *out_len - 4)));
 
808
            DEBUGPRINTINDENT("dumpv_send");
 
809
        }
 
810
        DEBUGMSG(("dumpv_send", "  Priority:\t%d\n",
 
811
                  (int) *(*buf + *out_len - 3)));
 
812
        DEBUGPRINTINDENT("dumpv_send");
 
813
        DEBUGMSG(("dumpv_send", "  Range SubID:\t%d\n",
 
814
                  (int) *(*buf + *out_len - 2)));
 
815
        DEBUGINDENTLESS();
 
816
 
 
817
        vp = pdu->variables;
 
818
        prefix_offset = *out_len + 1;
 
819
        DEBUGDUMPHEADER("send", "(Un)Register Prefix");
 
820
        if (!agentx_realloc_build_oid
 
821
            (buf, buf_len, out_len, allow_realloc, 0, vp->name,
 
822
             vp->name_length, network_order)) {
 
823
 
 
824
            DEBUGINDENTLESS();
 
825
            DEBUGINDENTLESS();
 
826
            return 0;
 
827
        }
 
828
        DEBUGINDENTLESS();
 
829
 
 
830
        if (pdu->range_subid) {
 
831
            DEBUGDUMPHEADER("send", "(Un)Register Range");
 
832
            if (!agentx_realloc_build_int
 
833
                (buf, buf_len, out_len, allow_realloc,
 
834
                 vp->val.objid[pdu->range_subid - 1], network_order)) {
 
835
                DEBUGINDENTLESS();
 
836
                DEBUGINDENTLESS();
 
837
                return 0;
 
838
            }
 
839
            DEBUGINDENTLESS();
 
840
        }
 
841
        break;
 
842
 
 
843
    case AGENTX_MSG_GETBULK:
 
844
        DEBUGDUMPHEADER("send", "GetBulk Non-Repeaters");
 
845
        if (!agentx_realloc_build_short
 
846
            (buf, buf_len, out_len, allow_realloc, 
 
847
            (u_short)pdu->non_repeaters,
 
848
             network_order)) {
 
849
            DEBUGINDENTLESS();
 
850
            DEBUGINDENTLESS();
 
851
            return 0;
 
852
        }
 
853
        DEBUGINDENTLESS();
 
854
 
 
855
        DEBUGDUMPHEADER("send", "GetBulk Max-Repetitions");
 
856
        if (!agentx_realloc_build_short
 
857
            (buf, buf_len, out_len, allow_realloc, 
 
858
            (u_short)pdu->max_repetitions,
 
859
             network_order)) {
 
860
            DEBUGINDENTLESS();
 
861
            DEBUGINDENTLESS();
 
862
            return 0;
 
863
        }
 
864
        DEBUGINDENTLESS();
 
865
 
 
866
        /*
 
867
         * Fallthrough  
 
868
         */
 
869
 
 
870
    case AGENTX_MSG_GET:
 
871
    case AGENTX_MSG_GETNEXT:
 
872
        DEBUGDUMPHEADER("send", "Get* Variable List");
 
873
        for (vp = pdu->variables; vp != NULL; vp = vp->next_variable) {
 
874
            inc = (vp->type == ASN_PRIV_INCL_RANGE);
 
875
            if (!agentx_realloc_build_oid
 
876
                (buf, buf_len, out_len, allow_realloc, inc, vp->name,
 
877
                 vp->name_length, network_order)) {
 
878
                DEBUGINDENTLESS();
 
879
                DEBUGINDENTLESS();
 
880
                return 0;
 
881
            }
 
882
            if (!agentx_realloc_build_oid
 
883
                (buf, buf_len, out_len, allow_realloc, 0, vp->val.objid,
 
884
                 vp->val_len / sizeof(oid), network_order)) {
 
885
                DEBUGINDENTLESS();
 
886
                DEBUGINDENTLESS();
 
887
                return 0;
 
888
            }
 
889
        }
 
890
        DEBUGINDENTLESS();
 
891
        break;
 
892
 
 
893
    case AGENTX_MSG_RESPONSE:
 
894
        pdu->flags &= ~(UCD_MSG_FLAG_EXPECT_RESPONSE);
 
895
        if (!agentx_realloc_build_int(buf, buf_len, out_len, allow_realloc,
 
896
                                      pdu->time, network_order)) {
 
897
            DEBUGINDENTLESS();
 
898
            return 0;
 
899
        }
 
900
        DEBUGDUMPHEADER("send", "Response");
 
901
        DEBUGDUMPSETUP("send", (*buf + *out_len - 4), 4);
 
902
        DEBUGMSG(("dumpv_send", "  sysUpTime:\t%d\n", pdu->time));
 
903
        DEBUGINDENTLESS();
 
904
 
 
905
        if (!agentx_realloc_build_short
 
906
            (buf, buf_len, out_len, allow_realloc, 
 
907
            (u_short)pdu->errstat,
 
908
             network_order)
 
909
            || !agentx_realloc_build_short(buf, buf_len, out_len,
 
910
                                           allow_realloc, 
 
911
                                           (u_short)pdu->errindex,
 
912
                                           network_order)) {
 
913
            DEBUGINDENTLESS();
 
914
            return 0;
 
915
        }
 
916
        DEBUGDUMPHEADER("send", "Response errors");
 
917
        DEBUGDUMPSETUP("send", (*buf + *out_len - 4), 4);
 
918
        DEBUGMSG(("dumpv_send", "  errstat:\t%d\n", pdu->errstat));
 
919
        DEBUGPRINTINDENT("dumpv_send");
 
920
        DEBUGMSG(("dumpv_send", "  errindex:\t%d\n", pdu->errindex));
 
921
        DEBUGINDENTLESS();
 
922
 
 
923
        /*
 
924
         * Fallthrough  
 
925
         */
 
926
 
 
927
    case AGENTX_MSG_INDEX_ALLOCATE:
 
928
    case AGENTX_MSG_INDEX_DEALLOCATE:
 
929
    case AGENTX_MSG_NOTIFY:
 
930
    case AGENTX_MSG_TESTSET:
 
931
        DEBUGDUMPHEADER("send", "Get* Variable List");
 
932
        for (vp = pdu->variables; vp != NULL; vp = vp->next_variable) {
 
933
            if (!agentx_realloc_build_varbind
 
934
                (buf, buf_len, out_len, allow_realloc, vp,
 
935
                 network_order)) {
 
936
                DEBUGINDENTLESS();
 
937
                DEBUGINDENTLESS();
 
938
                return 0;
 
939
            }
 
940
        }
 
941
        DEBUGINDENTLESS();
 
942
        break;
 
943
 
 
944
    case AGENTX_MSG_COMMITSET:
 
945
    case AGENTX_MSG_UNDOSET:
 
946
    case AGENTX_MSG_PING:
 
947
        /*
 
948
         * "Empty" packet.  
 
949
         */
 
950
        break;
 
951
 
 
952
    case AGENTX_MSG_CLEANUPSET:
 
953
        pdu->flags &= ~(UCD_MSG_FLAG_EXPECT_RESPONSE);
 
954
        break;
 
955
 
 
956
    case AGENTX_MSG_ADD_AGENT_CAPS:
 
957
        DEBUGDUMPHEADER("send", "AgentCaps OID");
 
958
        if (!agentx_realloc_build_oid
 
959
            (buf, buf_len, out_len, allow_realloc, 0, pdu->variables->name,
 
960
             pdu->variables->name_length, network_order)) {
 
961
            DEBUGINDENTLESS();
 
962
            DEBUGINDENTLESS();
 
963
            return 0;
 
964
        }
 
965
        DEBUGINDENTLESS();
 
966
 
 
967
        DEBUGDUMPHEADER("send", "AgentCaps Description");
 
968
        if (!agentx_realloc_build_string
 
969
            (buf, buf_len, out_len, allow_realloc,
 
970
             pdu->variables->val.string, pdu->variables->val_len,
 
971
             network_order)) {
 
972
            DEBUGINDENTLESS();
 
973
            DEBUGINDENTLESS();
 
974
            return 0;
 
975
        }
 
976
        DEBUGINDENTLESS();
 
977
        break;
 
978
 
 
979
    case AGENTX_MSG_REMOVE_AGENT_CAPS:
 
980
        DEBUGDUMPHEADER("send", "AgentCaps OID");
 
981
        if (!agentx_realloc_build_oid
 
982
            (buf, buf_len, out_len, allow_realloc, 0, pdu->variables->name,
 
983
             pdu->variables->name_length, network_order)) {
 
984
            DEBUGINDENTLESS();
 
985
            DEBUGINDENTLESS();
 
986
            return 0;
 
987
        }
 
988
        DEBUGINDENTLESS();
 
989
        break;
 
990
 
 
991
    default:
 
992
        session->s_snmp_errno = SNMPERR_UNKNOWN_PDU;
 
993
        return 0;
 
994
    }
 
995
    DEBUGINDENTLESS();
 
996
 
 
997
    /*
 
998
     * Fix the payload length (ignoring the 20-byte header).  
 
999
     */
 
1000
 
 
1001
    agentx_build_int((*buf + 16), (*out_len - ilen) - 20, network_order);
 
1002
 
 
1003
    DEBUGMSGTL(("agentx_build", "packet built okay\n"));
 
1004
    return 1;
 
1005
}
 
1006
 
 
1007
int
 
1008
agentx_realloc_build(netsnmp_session * session, netsnmp_pdu *pdu,
 
1009
                     u_char ** buf, size_t * buf_len, size_t * out_len)
 
1010
{
 
1011
    if (session == NULL || buf_len == NULL ||
 
1012
        out_len == NULL || pdu == NULL || buf == NULL) {
 
1013
        return -1;
 
1014
    }
 
1015
    if (!_agentx_realloc_build(buf, buf_len, out_len, 1, session, pdu)) {
 
1016
        if (session->s_snmp_errno == 0) {
 
1017
            session->s_snmp_errno = SNMPERR_BAD_ASN1_BUILD;
 
1018
        }
 
1019
        return -1;
 
1020
    }
 
1021
 
 
1022
    return 0;
 
1023
}
 
1024
 
 
1025
        /***********************
 
1026
        *
 
1027
        *  Utility functions for parsing an AgentX packet
 
1028
        *
 
1029
        ***********************/
 
1030
 
 
1031
int
 
1032
agentx_parse_int(u_char * data, u_int network_byte_order)
 
1033
{
 
1034
    u_int           value = 0;
 
1035
 
 
1036
    /*
 
1037
     *  Note - this doesn't handle 'PDP_ENDIAN' systems
 
1038
     *      If anyone needs this added, contact the coders list
 
1039
     */
 
1040
    DEBUGDUMPSETUP("recv", data, 4);
 
1041
    if (network_byte_order) {
 
1042
        memmove(&value, data, 4);
 
1043
#ifndef WORDS_BIGENDIAN
 
1044
        value = ntohl(value);
 
1045
#endif
 
1046
    } else {
 
1047
#ifndef WORDS_BIGENDIAN
 
1048
        memmove(&value, data, 4);
 
1049
#else
 
1050
        /*
 
1051
         * The equivalent of the 'ntohl()' macro,
 
1052
         * except this macro is null on big-endian systems 
 
1053
         */
 
1054
        value += data[3];
 
1055
        value <<= 8;
 
1056
        value += data[2];
 
1057
        value <<= 8;
 
1058
        value += data[1];
 
1059
        value <<= 8;
 
1060
        value += data[0];
 
1061
#endif
 
1062
    }
 
1063
    DEBUGMSG(("dumpv_recv", "  Integer:\t%ld (0x%.2X)\n", value, value));
 
1064
 
 
1065
    return value;
 
1066
}
 
1067
 
 
1068
 
 
1069
int
 
1070
agentx_parse_short(u_char * data, u_int network_byte_order)
 
1071
{
 
1072
    u_short         value = 0;
 
1073
 
 
1074
    if (network_byte_order) {
 
1075
        memmove(&value, data, 2);
 
1076
#ifndef WORDS_BIGENDIAN
 
1077
        value = ntohs(value);
 
1078
#endif
 
1079
    } else {
 
1080
#ifndef WORDS_BIGENDIAN
 
1081
        memmove(&value, data, 2);
 
1082
#else
 
1083
        /*
 
1084
         * The equivalent of the 'ntohs()' macro,
 
1085
         * except this macro is null on big-endian systems 
 
1086
         */
 
1087
        value += data[1];
 
1088
        value <<= 8;
 
1089
        value += data[0];
 
1090
#endif
 
1091
    }
 
1092
 
 
1093
    DEBUGDUMPSETUP("recv", data, 2);
 
1094
    DEBUGMSG(("dumpv_recv", "  Short:\t%ld (0x%.2X)\n", value, value));
 
1095
    return value;
 
1096
}
 
1097
 
 
1098
 
 
1099
u_char         *
 
1100
agentx_parse_oid(u_char * data, size_t * length, int *inc,
 
1101
                 oid * oid_buf, size_t * oid_len, u_int network_byte_order)
 
1102
{
 
1103
    u_int           n_subid;
 
1104
    u_int           prefix;
 
1105
    int             i;
 
1106
    int             int_offset;
 
1107
    u_int          *int_ptr = (u_int *)oid_buf;
 
1108
    u_char         *buf_ptr = data;
 
1109
 
 
1110
    if (*length < 4) {
 
1111
        DEBUGMSGTL(("agentx", "Incomplete Object ID"));
 
1112
        return NULL;
 
1113
    }
 
1114
 
 
1115
    DEBUGDUMPHEADER("recv", "OID Header");
 
1116
    DEBUGDUMPSETUP("recv", data, 4);
 
1117
    DEBUGMSG(("dumpv_recv", "  # subids:\t%d (0x%.2X)\n", data[0],
 
1118
              data[0]));
 
1119
    DEBUGPRINTINDENT("dumpv_recv");
 
1120
    DEBUGMSG(("dumpv_recv", "  prefix: \t%d (0x%.2X)\n", data[1],
 
1121
              data[1]));
 
1122
    DEBUGPRINTINDENT("dumpv_recv");
 
1123
    DEBUGMSG(("dumpv_recv", "  inclusive:\t%d (0x%.2X)\n", data[2],
 
1124
              data[2]));
 
1125
 
 
1126
    DEBUGINDENTLESS();
 
1127
    DEBUGDUMPHEADER("recv", "OID Segments");
 
1128
 
 
1129
    n_subid = data[0];
 
1130
    prefix = data[1];
 
1131
    if (inc)
 
1132
        *inc = data[2];
 
1133
    int_offset = sizeof(oid)/4;
 
1134
 
 
1135
    buf_ptr += 4;
 
1136
    *length -= 4;
 
1137
 
 
1138
    DEBUGMSG(("djp", "  parse_oid\n"));
 
1139
    DEBUGMSG(("djp", "  sizeof(oid) = %d\n", sizeof(oid)));
 
1140
    if (n_subid == 0 && prefix == 0) {
 
1141
        /*
 
1142
         * Null OID 
 
1143
         */
 
1144
        *int_ptr = 0;
 
1145
        int_ptr++;
 
1146
        *int_ptr = 0;
 
1147
        int_ptr++;
 
1148
        *oid_len = 2;
 
1149
        DEBUGPRINTINDENT("dumpv_recv");
 
1150
        DEBUGMSG(("dumpv_recv", "OID: NULL (0.0)\n"));
 
1151
        DEBUGINDENTLESS();
 
1152
        return buf_ptr;
 
1153
    }
 
1154
 
 
1155
 
 
1156
    if (*length < 4 * n_subid) {
 
1157
        DEBUGMSGTL(("agentx", "Incomplete Object ID"));
 
1158
        return NULL;
 
1159
    }
 
1160
 
 
1161
    if (prefix) {        
 
1162
        if (sizeof(oid) == 8) {         /* align OID values in 64 bit agent */  
 
1163
            int_ptr[0] = int_ptr[2] = int_ptr[4] = int_ptr[6] = int_ptr[8] = 0;
 
1164
        }
 
1165
        int_ptr[int_offset - 1] = 1;
 
1166
        int_ptr[(int_offset * 2) - 1] = 3;
 
1167
        int_ptr[(int_offset * 3) - 1] = 6;
 
1168
        int_ptr[(int_offset * 4) - 1] = 1;
 
1169
        int_ptr[(int_offset * 5) - 1] = prefix;
 
1170
        int_ptr = int_ptr + (int_offset * 5);
 
1171
    }
 
1172
 
 
1173
    for (i = 0; i < (int) (int_offset * n_subid); i = i + int_offset) {
 
1174
        int_ptr[i] = 0;
 
1175
        int_ptr[i + (int_offset - 1)] = agentx_parse_int(buf_ptr, network_byte_order);
 
1176
        buf_ptr += 4;
 
1177
        *length -= 4;
 
1178
    }
 
1179
 
 
1180
    *oid_len = (prefix ? n_subid + 5 : n_subid);
 
1181
 
 
1182
    DEBUGINDENTLESS();
 
1183
    DEBUGPRINTINDENT("dumpv_recv");
 
1184
    DEBUGMSG(("dumpv_recv", "OID: "));
 
1185
    DEBUGMSGOID(("dumpv_recv", oid_buf, *oid_len));
 
1186
    DEBUGMSG(("dumpv_recv", "\n"));
 
1187
 
 
1188
    return buf_ptr;
 
1189
}
 
1190
 
 
1191
 
 
1192
 
 
1193
u_char         *
 
1194
agentx_parse_string(u_char * data, size_t * length,
 
1195
                    u_char * string, size_t * str_len,
 
1196
                    u_int network_byte_order)
 
1197
{
 
1198
    u_int           len;
 
1199
 
 
1200
    if (*length < 4) {
 
1201
        DEBUGMSGTL(("agentx", "Incomplete string (too short: %d)",
 
1202
                    *length));
 
1203
        return NULL;
 
1204
    }
 
1205
 
 
1206
    len = agentx_parse_int(data, network_byte_order);
 
1207
    if (*length < len + 4) {
 
1208
        DEBUGMSGTL(("agentx", "Incomplete string (still too short: %d)",
 
1209
                    *length));
 
1210
        return NULL;
 
1211
    }
 
1212
    if (len > *str_len) {
 
1213
        DEBUGMSGTL(("agentx", "String too long (too long)"));
 
1214
        return NULL;
 
1215
    }
 
1216
    memmove(string, data + 4, len);
 
1217
    string[len] = '\0';
 
1218
    *str_len = len;
 
1219
 
 
1220
    len += 3;                   /* Extend the string length to include the padding */
 
1221
    len >>= 2;
 
1222
    len <<= 2;
 
1223
 
 
1224
    *length -= (len + 4);
 
1225
    DEBUGDUMPSETUP("recv", data, (len + 4));
 
1226
    DEBUGIF("dumpv_recv") {
 
1227
        u_char         *buf = NULL;
 
1228
        size_t          buf_len = 0, out_len = 0;
 
1229
 
 
1230
        if (sprint_realloc_asciistring(&buf, &buf_len, &out_len, 1,
 
1231
                                       string, len)) {
 
1232
            DEBUGMSG(("dumpv_recv", "String: %s\n", buf));
 
1233
        } else {
 
1234
            DEBUGMSG(("dumpv_recv", "String: %s [TRUNCATED]\n", buf));
 
1235
        }
 
1236
        if (buf != NULL) {
 
1237
            free(buf);
 
1238
        }
 
1239
    }
 
1240
    return data + (len + 4);
 
1241
}
 
1242
 
 
1243
u_char         *
 
1244
agentx_parse_opaque(u_char * data, size_t * length, int *type,
 
1245
                    u_char * opaque_buf, size_t * opaque_len,
 
1246
                    u_int network_byte_order)
 
1247
{
 
1248
    union {
 
1249
        float           floatVal;
 
1250
        double          doubleVal;
 
1251
        int             intVal[2];
 
1252
        char            c[sizeof(double)];
 
1253
    } fu;
 
1254
    int             tmp;
 
1255
    u_char         *buf;
 
1256
    u_char         *cp;
 
1257
 
 
1258
    cp = agentx_parse_string(data, length,
 
1259
                             opaque_buf, opaque_len, network_byte_order);
 
1260
    if (cp == NULL)
 
1261
        return NULL;
 
1262
 
 
1263
    buf = opaque_buf;
 
1264
 
 
1265
#ifdef OPAQUE_SPECIAL_TYPES
 
1266
    if ((buf[0] != ASN_OPAQUE_TAG1) || (*opaque_len <= 3))
 
1267
        return cp;              /* Unrecognised opaque type */
 
1268
 
 
1269
    switch (buf[1]) {
 
1270
    case ASN_OPAQUE_FLOAT:
 
1271
        if ((*opaque_len != (3 + sizeof(float))) ||
 
1272
            (buf[2] != sizeof(float)))
 
1273
            return cp;          /* Encoding isn't right for FLOAT */
 
1274
 
 
1275
        memcpy(&fu.c[0], &buf[3], sizeof(float));
 
1276
        fu.intVal[0] = ntohl(fu.intVal[0]);
 
1277
        *opaque_len = sizeof(float);
 
1278
        memcpy(opaque_buf, &fu.c[0], sizeof(float));
 
1279
        *type = ASN_OPAQUE_FLOAT;
 
1280
        DEBUGMSG(("dumpv_recv", "Float: %f\n", fu.floatVal));
 
1281
        return cp;
 
1282
 
 
1283
    case ASN_OPAQUE_DOUBLE:
 
1284
        if ((*opaque_len != (3 + sizeof(double))) ||
 
1285
            (buf[2] != sizeof(double)))
 
1286
            return cp;          /* Encoding isn't right for DOUBLE */
 
1287
 
 
1288
        memcpy(&fu.c[0], &buf[3], sizeof(double));
 
1289
        tmp = ntohl(fu.intVal[1]);
 
1290
        fu.intVal[1] = ntohl(fu.intVal[0]);
 
1291
        fu.intVal[0] = tmp;
 
1292
        *opaque_len = sizeof(double);
 
1293
        memcpy(opaque_buf, &fu.c[0], sizeof(double));
 
1294
        *type = ASN_OPAQUE_DOUBLE;
 
1295
        DEBUGMSG(("dumpv_recv", "Double: %lf\n", fu.doubleVal));
 
1296
        return cp;
 
1297
 
 
1298
    case ASN_OPAQUE_I64:
 
1299
    case ASN_OPAQUE_U64:
 
1300
    case ASN_OPAQUE_COUNTER64:
 
1301
    default:
 
1302
        return cp;              /* Unrecognised opaque sub-type */
 
1303
    }
 
1304
#else
 
1305
    return cp;
 
1306
#endif
 
1307
}
 
1308
 
 
1309
 
 
1310
u_char         *
 
1311
agentx_parse_varbind(u_char * data, size_t * length, int *type,
 
1312
                     oid * oid_buf, size_t * oid_len,
 
1313
                     u_char * data_buf, size_t * data_len,
 
1314
                     u_int network_byte_order)
 
1315
{
 
1316
    u_char         *bufp = data;
 
1317
    u_int           int_val;
 
1318
    int            int_offset;
 
1319
    u_int          *int_ptr = (u_int *) data_buf;
 
1320
 
 
1321
    DEBUGDUMPHEADER("recv", "VarBind:");
 
1322
    DEBUGDUMPHEADER("recv", "Type");
 
1323
    *type = agentx_parse_short(bufp, network_byte_order);
 
1324
    DEBUGINDENTLESS();
 
1325
    bufp += 4;
 
1326
    *length -= 4;
 
1327
 
 
1328
    bufp = agentx_parse_oid(bufp, length, NULL, oid_buf, oid_len,
 
1329
                            network_byte_order);
 
1330
    if (bufp == NULL) {
 
1331
        DEBUGINDENTLESS();
 
1332
        return NULL;
 
1333
    }
 
1334
 
 
1335
    switch (*type) {
 
1336
    case ASN_INTEGER:
 
1337
    case ASN_COUNTER:
 
1338
    case ASN_GAUGE:
 
1339
    case ASN_TIMETICKS:
 
1340
        int_val = agentx_parse_int(bufp, network_byte_order);
 
1341
        memmove(data_buf, &int_val, 4);
 
1342
        *data_len = 4;
 
1343
        bufp += 4;
 
1344
        *length -= 4;
 
1345
        break;
 
1346
 
 
1347
    case ASN_OCTET_STR:
 
1348
    case ASN_IPADDRESS:
 
1349
        bufp = agentx_parse_string(bufp, length, data_buf, data_len,
 
1350
                                   network_byte_order);
 
1351
        break;
 
1352
 
 
1353
    case ASN_OPAQUE:
 
1354
        bufp = agentx_parse_opaque(bufp, length, type, data_buf, data_len,
 
1355
                                   network_byte_order);
 
1356
        break;
 
1357
 
 
1358
    case ASN_PRIV_INCL_RANGE:
 
1359
    case ASN_PRIV_EXCL_RANGE:
 
1360
    case ASN_OBJECT_ID:
 
1361
        bufp =
 
1362
            agentx_parse_oid(bufp, length, NULL, (oid *) data_buf,
 
1363
                             data_len, network_byte_order);
 
1364
        *data_len *= sizeof(oid);
 
1365
        /*
 
1366
         * 'agentx_parse_oid()' returns the number of sub_ids 
 
1367
         */
 
1368
        break;
 
1369
 
 
1370
    case ASN_COUNTER64:
 
1371
        /*
 
1372
         * Set up offset to be 2 for 64-bit, 1 for 32-bit.
 
1373
         * Use this value in formulas to correctly put integer values
 
1374
         * extracted from buffer into correct place in byte buffer.
 
1375
         */
 
1376
        int_offset = sizeof(long) == 8 ? 2 : 1;
 
1377
        if (network_byte_order) {
 
1378
            /*
 
1379
             * For 64-bit, clear integers 2 & 3, then place values in 0 & 1.
 
1380
             * For 32-bit, clear integers 0 & 1, then overwrite with values.
 
1381
             * Could also put a conditional in here to skip clearing 0 & 1.
 
1382
             */
 
1383
            int_ptr[(2 * int_offset) - 2] = 0;
 
1384
            int_ptr[(2 * int_offset) - 1] = 0;
 
1385
            int_ptr[0] = agentx_parse_int(bufp, network_byte_order);
 
1386
            int_ptr[1] = agentx_parse_int(bufp + 4, network_byte_order);
 
1387
        } else {
 
1388
            /*
 
1389
             * For 64-bit, clear integers 0 & 1, then place values in 2 & 3.
 
1390
             * For 32-bit, clear integers 0 & 1, then overwrite with values.
 
1391
             * Could also put a conditional in here to skip clearing 0 & 1.
 
1392
             */
 
1393
            int_ptr[0] = 0;
 
1394
            int_ptr[1] = 0;
 
1395
            int_ptr[(2 * int_offset) - 2] = agentx_parse_int(bufp + 4,
 
1396
                                                            network_byte_order);
 
1397
            int_ptr[(2 * int_offset) - 1] = agentx_parse_int(bufp,
 
1398
                                                            network_byte_order);
 
1399
        }
 
1400
 
 
1401
        /* return data_len 2*8 if 64-bit, 2*4 if 32-bit */
 
1402
        *data_len = 2 * sizeof(long);
 
1403
        bufp += 2 * sizeof(long);
 
1404
        *length -= 8;
 
1405
        break;
 
1406
 
 
1407
    case ASN_NULL:
 
1408
    case SNMP_NOSUCHOBJECT:
 
1409
    case SNMP_NOSUCHINSTANCE:
 
1410
    case SNMP_ENDOFMIBVIEW:
 
1411
        /*
 
1412
         * No data associated with these types. 
 
1413
         */
 
1414
        *data_len = 0;
 
1415
        break;
 
1416
 
 
1417
    default:
 
1418
        DEBUGINDENTLESS();
 
1419
        return NULL;
 
1420
    }
 
1421
    DEBUGINDENTLESS();
 
1422
    return bufp;
 
1423
}
 
1424
 
 
1425
/*
 
1426
 *  AgentX header:
 
1427
 *
 
1428
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
1429
 * |    h.version  |   h.type      |   h.flags     |  <reserved>   |
 
1430
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
1431
 * |                       h.sessionID                             |
 
1432
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
1433
 * |                     h.transactionID                           |
 
1434
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
1435
 * |                       h.packetID                              |
 
1436
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
1437
 * |                     h.payload_length                          |
 
1438
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
1439
 *
 
1440
 *    Total length = 20 bytes
 
1441
 *
 
1442
 *  If we don't seem to have the full packet, return NULL
 
1443
 *    and let the driving code go back for the rest.
 
1444
 *  Don't report this as an error, as it's quite "normal"
 
1445
 *    with a connection-oriented service.
 
1446
 *
 
1447
 *  Note that once the header has been successfully processed
 
1448
 *    (and hence we should have the full packet), any subsequent
 
1449
 *    "running out of room" is indeed an error.
 
1450
 */
 
1451
u_char         *
 
1452
agentx_parse_header(netsnmp_pdu *pdu, u_char * data, size_t * length)
 
1453
{
 
1454
    register u_char *bufp = data;
 
1455
    size_t          payload;
 
1456
 
 
1457
    if (*length < 20) {         /* Incomplete header */
 
1458
        return NULL;
 
1459
    }
 
1460
 
 
1461
    DEBUGDUMPHEADER("recv", "AgentX Header");
 
1462
    DEBUGDUMPHEADER("recv", "Version");
 
1463
    DEBUGDUMPSETUP("recv", bufp, 1);
 
1464
    pdu->version = AGENTX_VERSION_BASE | *bufp;
 
1465
    DEBUGMSG(("dumpv_recv", "  Version:\t%d\n", *bufp));
 
1466
    DEBUGINDENTLESS();
 
1467
    bufp++;
 
1468
 
 
1469
    DEBUGDUMPHEADER("recv", "Command");
 
1470
    DEBUGDUMPSETUP("recv", bufp, 1);
 
1471
    pdu->command = *bufp;
 
1472
    DEBUGMSG(("dumpv_recv", "  Command:\t%d (%s)\n", *bufp,
 
1473
              agentx_cmd(*bufp)));
 
1474
    DEBUGINDENTLESS();
 
1475
    bufp++;
 
1476
 
 
1477
    DEBUGDUMPHEADER("recv", "Flags");
 
1478
    DEBUGDUMPSETUP("recv", bufp, 1);
 
1479
    pdu->flags |= *bufp;
 
1480
    DEBUGMSG(("dumpv_recv", "  Flags:\t0x%x\n", *bufp));
 
1481
    DEBUGINDENTLESS();
 
1482
    bufp++;
 
1483
 
 
1484
    DEBUGDUMPHEADER("recv", "Reserved Byte");
 
1485
    DEBUGDUMPSETUP("recv", bufp, 1);
 
1486
    DEBUGMSG(("dumpv_recv", "  Reserved:\t0x%x\n", *bufp));
 
1487
    DEBUGINDENTLESS();
 
1488
    bufp++;
 
1489
 
 
1490
    DEBUGDUMPHEADER("recv", "Session ID");
 
1491
    pdu->sessid = agentx_parse_int(bufp,
 
1492
                                   pdu->
 
1493
                                   flags &
 
1494
                                   AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1495
    DEBUGINDENTLESS();
 
1496
    bufp += 4;
 
1497
 
 
1498
    DEBUGDUMPHEADER("recv", "Transaction ID");
 
1499
    pdu->transid = agentx_parse_int(bufp,
 
1500
                                    pdu->
 
1501
                                    flags &
 
1502
                                    AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1503
    DEBUGINDENTLESS();
 
1504
    bufp += 4;
 
1505
 
 
1506
    DEBUGDUMPHEADER("recv", "Packet ID");
 
1507
    pdu->reqid = agentx_parse_int(bufp,
 
1508
                                  pdu->
 
1509
                                  flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1510
    DEBUGINDENTLESS();
 
1511
    bufp += 4;
 
1512
 
 
1513
    DEBUGDUMPHEADER("recv", "Payload Length");
 
1514
    payload = agentx_parse_int(bufp,
 
1515
                               pdu->
 
1516
                               flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1517
    DEBUGINDENTLESS();
 
1518
    bufp += 4;
 
1519
 
 
1520
    *length -= 20;
 
1521
    if (*length != payload) {   /* Short payload */
 
1522
        return NULL;
 
1523
    }
 
1524
    return bufp;
 
1525
}
 
1526
 
 
1527
 
 
1528
int
 
1529
agentx_parse(netsnmp_session * session, netsnmp_pdu *pdu, u_char * data,
 
1530
             size_t len)
 
1531
{
 
1532
    register u_char *bufp = data;
 
1533
    u_char          buffer[BUFSIZ];
 
1534
    u_char         *prefix_ptr;
 
1535
    oid             oid_buffer[MAX_OID_LEN], end_oid_buf[MAX_OID_LEN];
 
1536
    size_t          buf_len = BUFSIZ;
 
1537
    size_t          oid_buf_len = MAX_OID_LEN;
 
1538
    size_t          end_oid_buf_len = MAX_OID_LEN;
 
1539
 
 
1540
    int             range_bound;        /* OID-range upper bound */
 
1541
    int             inc;        /* Inclusive SearchRange flag */
 
1542
    int             type;       /* VarBind data type */
 
1543
    size_t         *length = &len;
 
1544
 
 
1545
    if (pdu == NULL) {
 
1546
        /*
 
1547
         * Dump the packet in a formatted style 
 
1548
         */
 
1549
        pdu = (netsnmp_pdu *) malloc(sizeof(netsnmp_pdu));
 
1550
        free(pdu);
 
1551
        return (0);
 
1552
    }
 
1553
    if (!IS_AGENTX_VERSION(session->version))
 
1554
        return SNMPERR_BAD_VERSION;
 
1555
 
 
1556
#ifndef SNMPERR_INCOMPLETE_PACKET
 
1557
    /*
 
1558
     *  Ideally, "short" packets on stream connections should
 
1559
     *    be handled specially, and the driving code set up to
 
1560
     *    keep reading until the full packet is received.
 
1561
     *
 
1562
     *  For now, lets assume that all packets are read in one go.
 
1563
     *    I've probably inflicted enough damage on the UCD library
 
1564
     *    for one week!
 
1565
     *
 
1566
     *  I'll come back to this once Wes is speaking to me again.
 
1567
     */
 
1568
#define SNMPERR_INCOMPLETE_PACKET SNMPERR_ASN_PARSE_ERR
 
1569
#endif
 
1570
 
 
1571
 
 
1572
    /*
 
1573
     *  Handle (common) header ....
 
1574
     */
 
1575
    bufp = agentx_parse_header(pdu, bufp, length);
 
1576
    if (bufp == NULL)
 
1577
        return SNMPERR_INCOMPLETE_PACKET;       /* i.e. wait for the rest */
 
1578
 
 
1579
    /*
 
1580
     * Control PDU handling 
 
1581
     */
 
1582
    pdu->flags |= UCD_MSG_FLAG_ALWAYS_IN_VIEW;
 
1583
    pdu->flags |= UCD_MSG_FLAG_FORCE_PDU_COPY;
 
1584
    pdu->flags &= (~UCD_MSG_FLAG_RESPONSE_PDU);
 
1585
 
 
1586
    /*
 
1587
     *  ... and (not-un-common) context
 
1588
     */
 
1589
    if (pdu->flags & AGENTX_MSG_FLAG_NON_DEFAULT_CONTEXT) {
 
1590
        DEBUGDUMPHEADER("recv", "Context");
 
1591
        bufp = agentx_parse_string(bufp, length, buffer, &buf_len,
 
1592
                                   pdu->
 
1593
                                   flags &
 
1594
                                   AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1595
        DEBUGINDENTLESS();
 
1596
        if (bufp == NULL)
 
1597
            return SNMPERR_ASN_PARSE_ERR;
 
1598
 
 
1599
        pdu->community_len = buf_len;
 
1600
        snmp_clone_mem((void **) &pdu->community,
 
1601
                       (void *) buffer, (unsigned) buf_len);
 
1602
        buf_len = BUFSIZ;
 
1603
    }
 
1604
 
 
1605
    DEBUGDUMPHEADER("recv", "PDU");
 
1606
    DEBUGINDENTMORE();
 
1607
    switch (pdu->command) {
 
1608
    case AGENTX_MSG_OPEN:
 
1609
        pdu->time = *bufp;      /* Timeout */
 
1610
        bufp += 4;
 
1611
        *length -= 4;
 
1612
 
 
1613
        /*
 
1614
         * Store subagent OID & description in a VarBind 
 
1615
         */
 
1616
        DEBUGDUMPHEADER("recv", "Subagent OID");
 
1617
        bufp = agentx_parse_oid(bufp, length, NULL,
 
1618
                                oid_buffer, &oid_buf_len,
 
1619
                                pdu->
 
1620
                                flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1621
        DEBUGINDENTLESS();
 
1622
        if (bufp == NULL) {
 
1623
            DEBUGINDENTLESS();
 
1624
            return SNMPERR_ASN_PARSE_ERR;
 
1625
        }
 
1626
        DEBUGDUMPHEADER("recv", "Subagent Description");
 
1627
        bufp = agentx_parse_string(bufp, length, buffer, &buf_len,
 
1628
                                   pdu->
 
1629
                                   flags &
 
1630
                                   AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1631
        DEBUGINDENTLESS();
 
1632
        if (bufp == NULL) {
 
1633
            DEBUGINDENTLESS();
 
1634
            return SNMPERR_ASN_PARSE_ERR;
 
1635
        }
 
1636
        snmp_pdu_add_variable(pdu, oid_buffer, oid_buf_len,
 
1637
                              ASN_OCTET_STR, buffer, buf_len);
 
1638
 
 
1639
        oid_buf_len = MAX_OID_LEN;
 
1640
        buf_len = BUFSIZ;
 
1641
        break;
 
1642
 
 
1643
    case AGENTX_MSG_CLOSE:
 
1644
        pdu->errstat = *bufp;   /* Reason */
 
1645
        bufp += 4;
 
1646
        *length -= 4;
 
1647
 
 
1648
        break;
 
1649
 
 
1650
    case AGENTX_MSG_UNREGISTER:
 
1651
    case AGENTX_MSG_REGISTER:
 
1652
        DEBUGDUMPHEADER("recv", "Registration Header");
 
1653
        if (pdu->command == AGENTX_MSG_REGISTER) {
 
1654
            pdu->time = *bufp;  /* Timeout (Register only) */
 
1655
            DEBUGDUMPSETUP("recv", bufp, 1);
 
1656
            DEBUGMSG(("dumpv_recv", "  Timeout:     \t%d\n", *bufp));
 
1657
        }
 
1658
        bufp++;
 
1659
        pdu->priority = *bufp;
 
1660
        DEBUGDUMPSETUP("recv", bufp, 1);
 
1661
        DEBUGMSG(("dumpv_recv", "  Priority:    \t%d\n", *bufp));
 
1662
        bufp++;
 
1663
        pdu->range_subid = *bufp;
 
1664
        DEBUGDUMPSETUP("recv", bufp, 1);
 
1665
        DEBUGMSG(("dumpv_recv", "  Range Sub-Id:\t%d\n", *bufp));
 
1666
        bufp++;
 
1667
        bufp++;
 
1668
        *length -= 4;
 
1669
        DEBUGINDENTLESS();
 
1670
 
 
1671
        prefix_ptr = bufp + 1;
 
1672
        DEBUGDUMPHEADER("recv", "Registration OID");
 
1673
        bufp = agentx_parse_oid(bufp, length, NULL,
 
1674
                                oid_buffer, &oid_buf_len,
 
1675
                                pdu->
 
1676
                                flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1677
        DEBUGINDENTLESS();
 
1678
        if (bufp == NULL) {
 
1679
            DEBUGINDENTLESS();
 
1680
            return SNMPERR_ASN_PARSE_ERR;
 
1681
        }
 
1682
 
 
1683
        if (pdu->range_subid) {
 
1684
            range_bound = agentx_parse_int(bufp,
 
1685
                                           pdu->
 
1686
                                           flags &
 
1687
                                           AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1688
            bufp += 4;
 
1689
            *length -= 4;
 
1690
 
 
1691
            /*
 
1692
             * Construct the end-OID.  
 
1693
             */
 
1694
            end_oid_buf_len = oid_buf_len * sizeof(oid);
 
1695
            memcpy(end_oid_buf, oid_buffer, end_oid_buf_len);
 
1696
            end_oid_buf[pdu->range_subid - 1] = range_bound;
 
1697
 
 
1698
            snmp_pdu_add_variable(pdu, oid_buffer, oid_buf_len,
 
1699
                                  ASN_PRIV_INCL_RANGE,
 
1700
                                  (u_char *) end_oid_buf, end_oid_buf_len);
 
1701
        } else {
 
1702
            snmp_add_null_var(pdu, oid_buffer, oid_buf_len);
 
1703
        }
 
1704
 
 
1705
        oid_buf_len = MAX_OID_LEN;
 
1706
        break;
 
1707
 
 
1708
    case AGENTX_MSG_GETBULK:
 
1709
        DEBUGDUMPHEADER("recv", "Non-repeaters");
 
1710
        pdu->non_repeaters = agentx_parse_short(bufp,
 
1711
                                                pdu->
 
1712
                                                flags &
 
1713
                                                AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1714
        DEBUGINDENTLESS();
 
1715
        DEBUGDUMPHEADER("recv", "Max-repeaters");
 
1716
        pdu->max_repetitions = agentx_parse_short(bufp + 2,
 
1717
                                                  pdu->
 
1718
                                                  flags &
 
1719
                                                  AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1720
        DEBUGINDENTLESS();
 
1721
        bufp += 4;
 
1722
        *length -= 4;
 
1723
        /*
 
1724
         * Fallthrough - SearchRange handling is the same 
 
1725
         */
 
1726
 
 
1727
    case AGENTX_MSG_GETNEXT:
 
1728
    case AGENTX_MSG_GET:
 
1729
 
 
1730
        /*
 
1731
         * *  SearchRange List
 
1732
         * *  Keep going while we have data left
 
1733
         */
 
1734
        DEBUGDUMPHEADER("recv", "Search Range");
 
1735
        while (*length > 0) {
 
1736
            bufp = agentx_parse_oid(bufp, length, &inc,
 
1737
                                    oid_buffer, &oid_buf_len,
 
1738
                                    pdu->
 
1739
                                    flags &
 
1740
                                    AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1741
            if (bufp == NULL) {
 
1742
                DEBUGINDENTLESS();
 
1743
                DEBUGINDENTLESS();
 
1744
                return SNMPERR_ASN_PARSE_ERR;
 
1745
            }
 
1746
            bufp = agentx_parse_oid(bufp, length, NULL,
 
1747
                                    end_oid_buf, &end_oid_buf_len,
 
1748
                                    pdu->
 
1749
                                    flags &
 
1750
                                    AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1751
            if (bufp == NULL) {
 
1752
                DEBUGINDENTLESS();
 
1753
                DEBUGINDENTLESS();
 
1754
                return SNMPERR_ASN_PARSE_ERR;
 
1755
            }
 
1756
            end_oid_buf_len *= sizeof(oid);
 
1757
            /*
 
1758
             * 'agentx_parse_oid()' returns the number of sub_ids 
 
1759
             */
 
1760
 
 
1761
            if (inc) {
 
1762
                snmp_pdu_add_variable(pdu, oid_buffer, oid_buf_len,
 
1763
                                      ASN_PRIV_INCL_RANGE,
 
1764
                                      (u_char *) end_oid_buf,
 
1765
                                      end_oid_buf_len);
 
1766
            } else {
 
1767
                snmp_pdu_add_variable(pdu, oid_buffer, oid_buf_len,
 
1768
                                      ASN_PRIV_EXCL_RANGE,
 
1769
                                      (u_char *) end_oid_buf,
 
1770
                                      end_oid_buf_len);
 
1771
            }
 
1772
        }
 
1773
 
 
1774
        DEBUGINDENTLESS();
 
1775
        oid_buf_len = MAX_OID_LEN;
 
1776
        end_oid_buf_len = MAX_OID_LEN;
 
1777
        break;
 
1778
 
 
1779
 
 
1780
    case AGENTX_MSG_RESPONSE:
 
1781
 
 
1782
        pdu->flags |= UCD_MSG_FLAG_RESPONSE_PDU;
 
1783
 
 
1784
        /*
 
1785
         * sysUpTime 
 
1786
         */
 
1787
        pdu->time = agentx_parse_int(bufp,
 
1788
                                     pdu->
 
1789
                                     flags &
 
1790
                                     AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1791
        bufp += 4;
 
1792
        *length -= 4;
 
1793
 
 
1794
        pdu->errstat = agentx_parse_short(bufp,
 
1795
                                          pdu->
 
1796
                                          flags &
 
1797
                                          AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1798
        pdu->errindex =
 
1799
            agentx_parse_short(bufp + 2,
 
1800
                               pdu->
 
1801
                               flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1802
        bufp += 4;
 
1803
        *length -= 4;
 
1804
        /*
 
1805
         * Fallthrough - VarBind handling is the same 
 
1806
         */
 
1807
 
 
1808
    case AGENTX_MSG_INDEX_ALLOCATE:
 
1809
    case AGENTX_MSG_INDEX_DEALLOCATE:
 
1810
    case AGENTX_MSG_NOTIFY:
 
1811
    case AGENTX_MSG_TESTSET:
 
1812
 
 
1813
        /*
 
1814
         * *  VarBind List
 
1815
         * *  Keep going while we have data left
 
1816
         */
 
1817
 
 
1818
        DEBUGDUMPHEADER("recv", "VarBindList");
 
1819
        while (*length > 0) {
 
1820
            bufp = agentx_parse_varbind(bufp, length, &type,
 
1821
                                        oid_buffer, &oid_buf_len,
 
1822
                                        buffer, &buf_len,
 
1823
                                        pdu->
 
1824
                                        flags &
 
1825
                                        AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1826
            if (bufp == NULL) {
 
1827
                DEBUGINDENTLESS();
 
1828
                DEBUGINDENTLESS();
 
1829
                return SNMPERR_ASN_PARSE_ERR;
 
1830
            }
 
1831
            snmp_pdu_add_variable(pdu, oid_buffer, oid_buf_len,
 
1832
                                  (u_char) type, buffer, buf_len);
 
1833
 
 
1834
            oid_buf_len = MAX_OID_LEN;
 
1835
            buf_len = BUFSIZ;
 
1836
        }
 
1837
        DEBUGINDENTLESS();
 
1838
        break;
 
1839
 
 
1840
    case AGENTX_MSG_COMMITSET:
 
1841
    case AGENTX_MSG_UNDOSET:
 
1842
    case AGENTX_MSG_CLEANUPSET:
 
1843
    case AGENTX_MSG_PING:
 
1844
 
 
1845
        /*
 
1846
         * "Empty" packet 
 
1847
         */
 
1848
        break;
 
1849
 
 
1850
 
 
1851
    case AGENTX_MSG_ADD_AGENT_CAPS:
 
1852
        /*
 
1853
         * Store AgentCap OID & description in a VarBind 
 
1854
         */
 
1855
        bufp = agentx_parse_oid(bufp, length, NULL,
 
1856
                                oid_buffer, &oid_buf_len,
 
1857
                                pdu->
 
1858
                                flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1859
        if (bufp == NULL)
 
1860
            return SNMPERR_ASN_PARSE_ERR;
 
1861
        bufp = agentx_parse_string(bufp, length, buffer, &buf_len,
 
1862
                                   pdu->
 
1863
                                   flags &
 
1864
                                   AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1865
        if (bufp == NULL)
 
1866
            return SNMPERR_ASN_PARSE_ERR;
 
1867
        snmp_pdu_add_variable(pdu, oid_buffer, oid_buf_len,
 
1868
                              ASN_OCTET_STR, buffer, buf_len);
 
1869
 
 
1870
        oid_buf_len = MAX_OID_LEN;
 
1871
        buf_len = BUFSIZ;
 
1872
        break;
 
1873
 
 
1874
    case AGENTX_MSG_REMOVE_AGENT_CAPS:
 
1875
        /*
 
1876
         * Store AgentCap OID & description in a VarBind 
 
1877
         */
 
1878
        bufp = agentx_parse_oid(bufp, length, NULL,
 
1879
                                oid_buffer, &oid_buf_len,
 
1880
                                pdu->
 
1881
                                flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER);
 
1882
        if (bufp == NULL)
 
1883
            return SNMPERR_ASN_PARSE_ERR;
 
1884
        snmp_add_null_var(pdu, oid_buffer, oid_buf_len);
 
1885
 
 
1886
        oid_buf_len = MAX_OID_LEN;
 
1887
        break;
 
1888
 
 
1889
    default:
 
1890
        DEBUGINDENTLESS();
 
1891
        DEBUGINDENTLESS();
 
1892
        DEBUGMSGTL(("agentx", "Unrecognised PDU type: %d\n",
 
1893
                    pdu->command));
 
1894
        return SNMPERR_UNKNOWN_PDU;
 
1895
    }
 
1896
    DEBUGINDENTLESS();
 
1897
    DEBUGINDENTLESS();
 
1898
    DEBUGINDENTLESS();
 
1899
    return SNMP_ERR_NOERROR;
 
1900
}
 
1901
 
 
1902
 
 
1903
 
 
1904
 
 
1905
#ifdef TESTING
 
1906
 
 
1907
testit(netsnmp_pdu *pdu1)
 
1908
{
 
1909
    char            packet1[BUFSIZ];
 
1910
    char            packet2[BUFSIZ];
 
1911
    int             len1, len2;
 
1912
    netsnmp_pdu     pdu2;
 
1913
    netsnmp_session sess;
 
1914
 
 
1915
    memset(&pdu2, 0, sizeof(netsnmp_pdu));
 
1916
    memset(packet1, 0, BUFSIZ);
 
1917
    memset(packet2, 0, BUFSIZ);
 
1918
 
 
1919
    /*
 
1920
     * Encode this into a "packet" 
 
1921
     */
 
1922
    len1 = BUFSIZ;
 
1923
    if (agentx_build(&sess, pdu1, packet1, &len1) < 0) {
 
1924
        DEBUGMSGTL(("agentx", "First build failed"));
 
1925
        exit(1);
 
1926
    }
 
1927
 
 
1928
    DEBUGMSGTL(("agentx", "First build succeeded:\n"));
 
1929
    xdump(packet1, len1, "Ax1> ");
 
1930
 
 
1931
    /*
 
1932
     * Unpack this into a PDU 
 
1933
     */
 
1934
    len2 = len1;
 
1935
    if (agentx_parse(&pdu2, packet1, &len2, (u_char **) NULL) < 0) {
 
1936
        DEBUGMSGTL(("agentx", "First parse failed\n"));
 
1937
        exit(1);
 
1938
    }
 
1939
    DEBUGMSGTL(("agentx", "First parse succeeded:\n"));
 
1940
    if (len2 != 0)
 
1941
        DEBUGMSGTL(("agentx",
 
1942
                    "Warning - parsed packet has %d bytes left\n", len2));
 
1943
 
 
1944
    /*
 
1945
     * Encode this into another "packet" 
 
1946
     */
 
1947
    len2 = BUFSIZ;
 
1948
    if (agentx_build(&sess, &pdu2, packet2, &len2) < 0) {
 
1949
        DEBUGMSGTL(("agentx", "Second build failed\n"));
 
1950
        exit(1);
 
1951
    }
 
1952
 
 
1953
    DEBUGMSGTL(("agentx", "Second build succeeded:\n"));
 
1954
    xdump(packet2, len2, "Ax2> ");
 
1955
 
 
1956
    /*
 
1957
     * Compare the results 
 
1958
     */
 
1959
    if (len1 != len2) {
 
1960
        DEBUGMSGTL(("agentx",
 
1961
                    "Error: first build (%d) is different to second (%d)\n",
 
1962
                    len1, len2));
 
1963
        exit(1);
 
1964
    }
 
1965
    if (memcmp(packet1, packet2, len1) != 0) {
 
1966
        DEBUGMSGTL(("agentx",
 
1967
                    "Error: first build data is different to second\n"));
 
1968
        exit(1);
 
1969
    }
 
1970
 
 
1971
    DEBUGMSGTL(("agentx", "OK\n"));
 
1972
}
 
1973
 
 
1974
 
 
1975
 
 
1976
main()
 
1977
{
 
1978
    netsnmp_pdu     pdu1;
 
1979
    oid             oid_buf[] = { 1, 3, 6, 1, 2, 1, 10 };
 
1980
    oid             oid_buf2[] = { 1, 3, 6, 1, 2, 1, 20 };
 
1981
    oid             null_oid[] = { 0, 0 };
 
1982
    char           *string = "Example string";
 
1983
    char           *context = "LUCS";
 
1984
 
 
1985
 
 
1986
    /*
 
1987
     * Create an example AgentX pdu structure 
 
1988
     */
 
1989
 
 
1990
    memset(&pdu1, 0, sizeof(netsnmp_pdu));
 
1991
    pdu1.command = AGENTX_MSG_TESTSET;
 
1992
    pdu1.flags = 0;
 
1993
    pdu1.sessid = 16;
 
1994
    pdu1.transid = 24;
 
1995
    pdu1.reqid = 132;
 
1996
 
 
1997
    pdu1.time = 10;
 
1998
    pdu1.non_repeaters = 3;
 
1999
    pdu1.max_repetitions = 32;
 
2000
    pdu1.priority = 5;
 
2001
    pdu1.range_subid = 0;
 
2002
 
 
2003
    snmp_pdu_add_variable(&pdu1, oid_buf, sizeof(oid_buf) / sizeof(oid),
 
2004
                          ASN_OBJECT_ID, (char *) oid_buf2,
 
2005
                          sizeof(oid_buf2));
 
2006
    snmp_pdu_add_variable(&pdu1, oid_buf, sizeof(oid_buf) / sizeof(oid),
 
2007
                          ASN_INTEGER, (char *) &pdu1.reqid,
 
2008
                          sizeof(pdu1.reqid));
 
2009
    snmp_pdu_add_variable(&pdu1, oid_buf, sizeof(oid_buf) / sizeof(oid),
 
2010
                          ASN_OCTET_STR, (char *) string, strlen(string));
 
2011
 
 
2012
    printf("Test with non-network order.....\n");
 
2013
    testit(&pdu1);
 
2014
 
 
2015
    printf("\nTest with network order.....\n");
 
2016
    pdu1.flags |= AGENTX_FLAGS_NETWORK_BYTE_ORDER;
 
2017
    testit(&pdu1);
 
2018
 
 
2019
    pdu1.community = context;
 
2020
    pdu1.community_len = strlen(context);
 
2021
    pdu1.flags |= AGENTX_FLAGS_NON_DEFAULT_CONTEXT;
 
2022
    printf("Test with non-default context.....\n");
 
2023
    testit(&pdu1);
 
2024
 
 
2025
 
 
2026
}
 
2027
#endif
 
2028
 
 
2029
/*
 
2030
 * returns the proper length of an incoming agentx packet. 
 
2031
 */
 
2032
/*
 
2033
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
2034
 *    |   h.version   |    h.type     |    h.flags    |  <reserved>   |
 
2035
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
2036
 *    |                          h.sessionID                          |
 
2037
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
2038
 *    |                        h.transactionID                        |
 
2039
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
2040
 *    |                          h.packetID                           |
 
2041
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
2042
 *    |                        h.payload_length                       |
 
2043
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
2044
 *    20 bytes in header
 
2045
 */
 
2046
 
 
2047
int
 
2048
agentx_check_packet(u_char * packet, size_t packet_len)
 
2049
{
 
2050
 
 
2051
    if (packet_len < 20)
 
2052
        return 0;               /* minimum header length == 20 */
 
2053
 
 
2054
    return agentx_parse_int(packet + 16,
 
2055
                            *(packet +
 
2056
                              2) & AGENTX_FLAGS_NETWORK_BYTE_ORDER) + 20;
 
2057
}