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
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.
12
#include <net-snmp/net-snmp-config.h>
27
#include <sys/types.h>
28
#if TIME_WITH_SYS_TIME
30
# include <sys/timeb.h>
32
# include <sys/time.h>
37
# include <sys/time.h>
43
#include <netinet/in.h>
46
#include <arpa/inet.h>
57
#include <net-snmp/net-snmp-includes.h>
59
#include "agentx/protocol.h"
62
agentx_cmd(u_char code)
67
case AGENTX_MSG_CLOSE:
69
case AGENTX_MSG_REGISTER:
71
case AGENTX_MSG_UNREGISTER:
75
case AGENTX_MSG_GETNEXT:
77
case AGENTX_MSG_GETBULK:
79
case AGENTX_MSG_TESTSET:
81
case AGENTX_MSG_COMMITSET:
83
case AGENTX_MSG_UNDOSET:
85
case AGENTX_MSG_CLEANUPSET:
87
case AGENTX_MSG_NOTIFY:
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:
107
agentx_realloc_build_int(u_char ** buf, size_t * buf_len, size_t * out_len,
109
unsigned int value, int network_order)
111
unsigned int ivalue = value;
112
size_t ilen = *out_len;
113
#ifdef WORDS_BIGENDIAN
117
while ((*out_len + 4) >= *buf_len) {
118
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
124
#ifndef WORDS_BIGENDIAN
125
value = ntohl(value);
127
memmove((*buf + *out_len), &value, 4);
130
#ifndef WORDS_BIGENDIAN
131
memmove((*buf + *out_len), &value, 4);
134
for (i = 0; i < 4; i++) {
135
*(*buf + *out_len) = (u_char) value & 0xff;
141
DEBUGDUMPSETUP("send", (*buf + ilen), 4);
142
DEBUGMSG(("dumpv_send", " Integer:\t%lu (0x%.2lX)\n", ivalue,
148
agentx_build_int(u_char * bufp, u_int value, int network_byte_order)
150
u_char *orig_bufp = bufp;
151
u_int orig_val = value;
153
if (network_byte_order) {
154
#ifndef WORDS_BIGENDIAN
155
value = ntohl(value);
157
memmove(bufp, &value, 4);
159
#ifndef WORDS_BIGENDIAN
160
memmove(bufp, &value, 4);
162
*bufp = (u_char) value & 0xff;
165
*bufp = (u_char) value & 0xff;
168
*bufp = (u_char) value & 0xff;
171
*bufp = (u_char) value & 0xff;
174
DEBUGDUMPSETUP("send", orig_bufp, 4);
175
DEBUGMSG(("dumpv_send", " Integer:\t%ld (0x%.2X)\n", orig_val,
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)
184
unsigned short ivalue = value;
185
size_t ilen = *out_len;
186
#ifdef WORDS_BIGENDIAN
187
unsigned short i = 0;
190
while ((*out_len + 2) >= *buf_len) {
191
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
197
#ifndef WORDS_BIGENDIAN
198
value = ntohs(value);
200
memmove((*buf + *out_len), &value, 2);
203
#ifndef WORDS_BIGENDIAN
204
memmove((*buf + *out_len), &value, 2);
207
for (i = 0; i < 2; i++) {
208
*(*buf + *out_len) = (u_char) value & 0xff;
214
DEBUGDUMPSETUP("send", (*buf + ilen), 2);
215
DEBUGMSG(("dumpv_send", " Short:\t%hu (0x%.2hX)\n", ivalue, ivalue));
220
agentx_realloc_build_oid(u_char ** buf, size_t * buf_len, size_t * out_len,
222
int inclusive, oid * name, size_t name_len,
225
size_t ilen = *out_len, i = 0;
228
DEBUGPRINTINDENT("dumpv_send");
229
DEBUGMSG(("dumpv_send", "OID: "));
230
DEBUGMSGOID(("dumpv_send", name, name_len));
231
DEBUGMSG(("dumpv_send", "\n"));
233
if (name_len == 2 && (name[0] == 0 && name[1] == 0)) {
234
name_len = 0; /* Null OID */
238
* 'Compact' internet OIDs
240
if (name_len >= 5 && (name[0] == 1 && name[1] == 3 &&
241
name[2] == 6 && name[3] == 1)) {
247
while ((*out_len + 4 + (4 * name_len)) >= *buf_len) {
248
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
253
*(*buf + *out_len) = (u_char) name_len;
255
*(*buf + *out_len) = (u_char) prefix;
257
*(*buf + *out_len) = (u_char) inclusive;
259
*(*buf + *out_len) = (u_char) 0x00;
262
DEBUGDUMPHEADER("send", "OID Header");
263
DEBUGDUMPSETUP("send", (*buf + ilen), 4);
264
DEBUGMSG(("dumpv_send", " # subids:\t%d (0x%.2X)\n", 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,
272
DEBUGDUMPHEADER("send", "OID Segments");
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)) {
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,
292
size_t ilen = *out_len, i = 0;
294
while ((*out_len + 4 + (4 * ((string_len + 3) / 4))) >= *buf_len) {
295
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
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)) {
309
if (string_len == 0) {
310
DEBUGMSG(("dumpv_send", " String: <empty>\n"));
316
memmove((*buf + *out_len), string, string_len);
317
*out_len += string_len;
320
* Pad to a multiple of 4 bytes if necessary (per RFC 2741).
323
if (string_len % 4 != 0) {
324
for (i = 0; i < 4 - (string_len % 4); i++) {
325
*(*buf + *out_len) = 0;
330
DEBUGDUMPSETUP("send", (*buf + ilen + 4), ((string_len + 3) / 4) * 4);
331
DEBUGMSG(("dumpv_send", " String:\t%s\n", string));
337
#ifdef OPAQUE_SPECIAL_TYPES
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)
346
char c[sizeof(double)];
349
u_char opaque_buffer[3 + sizeof(double)];
351
opaque_buffer[0] = ASN_OPAQUE_TAG1;
352
opaque_buffer[1] = ASN_OPAQUE_DOUBLE;
353
opaque_buffer[2] = sizeof(double);
355
du.doubleVal = double_val;
356
tmp = htonl(du.intVal[0]);
357
du.intVal[0] = htonl(du.intVal[1]);
359
memcpy(&opaque_buffer[3], &du.c[0], sizeof(double));
361
return agentx_realloc_build_string(buf, buf_len, out_len,
362
allow_realloc, opaque_buffer,
363
3 + sizeof(double), network_order);
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)
374
char c[sizeof(float)];
376
u_char opaque_buffer[3 + sizeof(float)];
378
opaque_buffer[0] = ASN_OPAQUE_TAG1;
379
opaque_buffer[1] = ASN_OPAQUE_FLOAT;
380
opaque_buffer[2] = sizeof(float);
382
fu.floatVal = float_val;
383
fu.intVal = htonl(fu.intVal);
384
memcpy(&opaque_buffer[3], &fu.c[0], sizeof(float));
386
return agentx_realloc_build_string(buf, buf_len, out_len,
387
allow_realloc, opaque_buffer,
388
3 + sizeof(float), network_order);
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)
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)) {
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)) {
421
if (!agentx_realloc_build_short
422
(buf, buf_len, out_len, allow_realloc,
423
(unsigned short) vp->type, network_order)) {
430
while ((*out_len + 2) >= *buf_len) {
431
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
438
*(*buf + *out_len) = 0;
440
*(*buf + *out_len) = 0;
444
DEBUGDUMPHEADER("send", "name");
445
if (!agentx_realloc_build_oid(buf, buf_len, out_len, allow_realloc, 0,
446
vp->name, vp->name_length,
453
DEBUGDUMPHEADER("send", "value");
460
if (!agentx_realloc_build_int(buf, buf_len, out_len, allow_realloc,
461
*(vp->val.integer), network_order)) {
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),
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),
501
case ASN_OPAQUE_COUNTER64:
503
* XXX - TODO - encode as raw OPAQUE for now (so fall through
511
if (!agentx_realloc_build_string
512
(buf, buf_len, out_len, allow_realloc, vp->val.string,
513
vp->val_len, network_order)) {
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)) {
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,
540
vp->val.counter64->low,
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,
554
vp->val.counter64->high,
565
case SNMP_NOSUCHOBJECT:
566
case SNMP_NOSUCHINSTANCE:
567
case SNMP_ENDOFMIBVIEW:
571
DEBUGMSGTL(("agentx_build_varbind", "unknown type %d (0x%02x)\n",
572
vp->type, vp->type));
583
agentx_realloc_build_header(u_char ** buf, size_t * buf_len,
584
size_t * out_len, int allow_realloc,
587
size_t ilen = *out_len;
588
const int network_order =
589
pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER;
591
while ((*out_len + 4) >= *buf_len) {
592
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
598
* First 4 bytes are version, pdu type, flags, and a 0 reserved byte.
601
*(*buf + *out_len) = 1;
603
*(*buf + *out_len) = pdu->command;
605
*(*buf + *out_len) = (u_char) (pdu->flags & AGENTX_MSG_FLAGS_MASK);
607
*(*buf + *out_len) = 0;
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)));
619
DEBUGDUMPHEADER("send", "Session ID");
620
if (!agentx_realloc_build_int(buf, buf_len, out_len, allow_realloc,
621
pdu->sessid, network_order)) {
628
DEBUGDUMPHEADER("send", "Transaction ID");
629
if (!agentx_realloc_build_int(buf, buf_len, out_len, allow_realloc,
630
pdu->transid, network_order)) {
637
DEBUGDUMPHEADER("send", "Request ID");
638
if (!agentx_realloc_build_int(buf, buf_len, out_len, allow_realloc,
639
pdu->reqid, network_order)) {
646
DEBUGDUMPHEADER("send", "Dummy Length :-(");
647
if (!agentx_realloc_build_int(buf, buf_len, out_len, allow_realloc,
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)) {
672
_agentx_realloc_build(u_char ** buf, size_t * buf_len, size_t * out_len,
674
netsnmp_session * session, netsnmp_pdu *pdu)
676
size_t ilen = *out_len, prefix_offset = 0;
677
netsnmp_variable_list *vp;
679
const int network_order =
680
pdu->flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER;
682
session->s_snmp_errno = 0;
683
session->s_errno = 0;
686
* Various PDU types don't include context information (RFC 2741, p. 20).
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);
699
* Build the header (and context if appropriate).
701
if (!agentx_realloc_build_header
702
(buf, buf_len, out_len, allow_realloc, pdu)) {
707
* Everything causes a response, except for agentx-Response-PDU and
708
* agentx-CleanupSet-PDU.
711
pdu->flags |= UCD_MSG_FLAG_EXPECT_RESPONSE;
713
DEBUGDUMPHEADER("send", "AgentX Payload");
714
switch (pdu->command) {
716
case AGENTX_MSG_OPEN:
720
while ((*out_len + 4) >= *buf_len) {
721
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
726
*(*buf + *out_len) = (u_char) pdu->time;
728
for (i = 0; i < 3; i++) {
729
*(*buf + *out_len) = 0;
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)));
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)) {
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,
759
case AGENTX_MSG_CLOSE:
763
while ((*out_len + 4) >= *buf_len) {
764
if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
769
*(*buf + *out_len) = (u_char) pdu->errstat;
771
for (i = 0; i < 3; i++) {
772
*(*buf + *out_len) = 0;
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)));
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))) {
790
if (pdu->command == AGENTX_MSG_REGISTER) {
791
*(*buf + *out_len) = (u_char) pdu->time;
793
*(*buf + *out_len) = 0;
796
*(*buf + *out_len) = (u_char) pdu->priority;
798
*(*buf + *out_len) = (u_char) pdu->range_subid;
800
*(*buf + *out_len) = (u_char) 0;
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");
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)));
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)) {
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)) {
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,
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,
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)) {
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)) {
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)) {
900
DEBUGDUMPHEADER("send", "Response");
901
DEBUGDUMPSETUP("send", (*buf + *out_len - 4), 4);
902
DEBUGMSG(("dumpv_send", " sysUpTime:\t%d\n", pdu->time));
905
if (!agentx_realloc_build_short
906
(buf, buf_len, out_len, allow_realloc,
907
(u_short)pdu->errstat,
909
|| !agentx_realloc_build_short(buf, buf_len, out_len,
911
(u_short)pdu->errindex,
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));
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,
944
case AGENTX_MSG_COMMITSET:
945
case AGENTX_MSG_UNDOSET:
946
case AGENTX_MSG_PING:
952
case AGENTX_MSG_CLEANUPSET:
953
pdu->flags &= ~(UCD_MSG_FLAG_EXPECT_RESPONSE);
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)) {
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,
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)) {
992
session->s_snmp_errno = SNMPERR_UNKNOWN_PDU;
998
* Fix the payload length (ignoring the 20-byte header).
1001
agentx_build_int((*buf + 16), (*out_len - ilen) - 20, network_order);
1003
DEBUGMSGTL(("agentx_build", "packet built okay\n"));
1008
agentx_realloc_build(netsnmp_session * session, netsnmp_pdu *pdu,
1009
u_char ** buf, size_t * buf_len, size_t * out_len)
1011
if (session == NULL || buf_len == NULL ||
1012
out_len == NULL || pdu == NULL || buf == NULL) {
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;
1025
/***********************
1027
* Utility functions for parsing an AgentX packet
1029
***********************/
1032
agentx_parse_int(u_char * data, u_int network_byte_order)
1037
* Note - this doesn't handle 'PDP_ENDIAN' systems
1038
* If anyone needs this added, contact the coders list
1040
DEBUGDUMPSETUP("recv", data, 4);
1041
if (network_byte_order) {
1042
memmove(&value, data, 4);
1043
#ifndef WORDS_BIGENDIAN
1044
value = ntohl(value);
1047
#ifndef WORDS_BIGENDIAN
1048
memmove(&value, data, 4);
1051
* The equivalent of the 'ntohl()' macro,
1052
* except this macro is null on big-endian systems
1063
DEBUGMSG(("dumpv_recv", " Integer:\t%ld (0x%.2X)\n", value, value));
1070
agentx_parse_short(u_char * data, u_int network_byte_order)
1074
if (network_byte_order) {
1075
memmove(&value, data, 2);
1076
#ifndef WORDS_BIGENDIAN
1077
value = ntohs(value);
1080
#ifndef WORDS_BIGENDIAN
1081
memmove(&value, data, 2);
1084
* The equivalent of the 'ntohs()' macro,
1085
* except this macro is null on big-endian systems
1093
DEBUGDUMPSETUP("recv", data, 2);
1094
DEBUGMSG(("dumpv_recv", " Short:\t%ld (0x%.2X)\n", value, value));
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)
1107
u_int *int_ptr = (u_int *)oid_buf;
1108
u_char *buf_ptr = data;
1111
DEBUGMSGTL(("agentx", "Incomplete Object ID"));
1115
DEBUGDUMPHEADER("recv", "OID Header");
1116
DEBUGDUMPSETUP("recv", data, 4);
1117
DEBUGMSG(("dumpv_recv", " # subids:\t%d (0x%.2X)\n", data[0],
1119
DEBUGPRINTINDENT("dumpv_recv");
1120
DEBUGMSG(("dumpv_recv", " prefix: \t%d (0x%.2X)\n", data[1],
1122
DEBUGPRINTINDENT("dumpv_recv");
1123
DEBUGMSG(("dumpv_recv", " inclusive:\t%d (0x%.2X)\n", data[2],
1127
DEBUGDUMPHEADER("recv", "OID Segments");
1133
int_offset = sizeof(oid)/4;
1138
DEBUGMSG(("djp", " parse_oid\n"));
1139
DEBUGMSG(("djp", " sizeof(oid) = %d\n", sizeof(oid)));
1140
if (n_subid == 0 && prefix == 0) {
1149
DEBUGPRINTINDENT("dumpv_recv");
1150
DEBUGMSG(("dumpv_recv", "OID: NULL (0.0)\n"));
1156
if (*length < 4 * n_subid) {
1157
DEBUGMSGTL(("agentx", "Incomplete Object ID"));
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;
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);
1173
for (i = 0; i < (int) (int_offset * n_subid); i = i + int_offset) {
1175
int_ptr[i + (int_offset - 1)] = agentx_parse_int(buf_ptr, network_byte_order);
1180
*oid_len = (prefix ? n_subid + 5 : n_subid);
1183
DEBUGPRINTINDENT("dumpv_recv");
1184
DEBUGMSG(("dumpv_recv", "OID: "));
1185
DEBUGMSGOID(("dumpv_recv", oid_buf, *oid_len));
1186
DEBUGMSG(("dumpv_recv", "\n"));
1194
agentx_parse_string(u_char * data, size_t * length,
1195
u_char * string, size_t * str_len,
1196
u_int network_byte_order)
1201
DEBUGMSGTL(("agentx", "Incomplete string (too short: %d)",
1206
len = agentx_parse_int(data, network_byte_order);
1207
if (*length < len + 4) {
1208
DEBUGMSGTL(("agentx", "Incomplete string (still too short: %d)",
1212
if (len > *str_len) {
1213
DEBUGMSGTL(("agentx", "String too long (too long)"));
1216
memmove(string, data + 4, len);
1220
len += 3; /* Extend the string length to include the padding */
1224
*length -= (len + 4);
1225
DEBUGDUMPSETUP("recv", data, (len + 4));
1226
DEBUGIF("dumpv_recv") {
1228
size_t buf_len = 0, out_len = 0;
1230
if (sprint_realloc_asciistring(&buf, &buf_len, &out_len, 1,
1232
DEBUGMSG(("dumpv_recv", "String: %s\n", buf));
1234
DEBUGMSG(("dumpv_recv", "String: %s [TRUNCATED]\n", buf));
1240
return data + (len + 4);
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)
1252
char c[sizeof(double)];
1258
cp = agentx_parse_string(data, length,
1259
opaque_buf, opaque_len, network_byte_order);
1265
#ifdef OPAQUE_SPECIAL_TYPES
1266
if ((buf[0] != ASN_OPAQUE_TAG1) || (*opaque_len <= 3))
1267
return cp; /* Unrecognised opaque type */
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 */
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));
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 */
1288
memcpy(&fu.c[0], &buf[3], sizeof(double));
1289
tmp = ntohl(fu.intVal[1]);
1290
fu.intVal[1] = ntohl(fu.intVal[0]);
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));
1298
case ASN_OPAQUE_I64:
1299
case ASN_OPAQUE_U64:
1300
case ASN_OPAQUE_COUNTER64:
1302
return cp; /* Unrecognised opaque sub-type */
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)
1316
u_char *bufp = data;
1319
u_int *int_ptr = (u_int *) data_buf;
1321
DEBUGDUMPHEADER("recv", "VarBind:");
1322
DEBUGDUMPHEADER("recv", "Type");
1323
*type = agentx_parse_short(bufp, network_byte_order);
1328
bufp = agentx_parse_oid(bufp, length, NULL, oid_buf, oid_len,
1329
network_byte_order);
1340
int_val = agentx_parse_int(bufp, network_byte_order);
1341
memmove(data_buf, &int_val, 4);
1349
bufp = agentx_parse_string(bufp, length, data_buf, data_len,
1350
network_byte_order);
1354
bufp = agentx_parse_opaque(bufp, length, type, data_buf, data_len,
1355
network_byte_order);
1358
case ASN_PRIV_INCL_RANGE:
1359
case ASN_PRIV_EXCL_RANGE:
1362
agentx_parse_oid(bufp, length, NULL, (oid *) data_buf,
1363
data_len, network_byte_order);
1364
*data_len *= sizeof(oid);
1366
* 'agentx_parse_oid()' returns the number of sub_ids
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.
1376
int_offset = sizeof(long) == 8 ? 2 : 1;
1377
if (network_byte_order) {
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.
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);
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.
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);
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);
1408
case SNMP_NOSUCHOBJECT:
1409
case SNMP_NOSUCHINSTANCE:
1410
case SNMP_ENDOFMIBVIEW:
1412
* No data associated with these types.
1428
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1429
* | h.version | h.type | h.flags | <reserved> |
1430
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1432
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1433
* | h.transactionID |
1434
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1436
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1437
* | h.payload_length |
1438
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1440
* Total length = 20 bytes
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.
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.
1452
agentx_parse_header(netsnmp_pdu *pdu, u_char * data, size_t * length)
1454
register u_char *bufp = data;
1457
if (*length < 20) { /* Incomplete header */
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));
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)));
1477
DEBUGDUMPHEADER("recv", "Flags");
1478
DEBUGDUMPSETUP("recv", bufp, 1);
1479
pdu->flags |= *bufp;
1480
DEBUGMSG(("dumpv_recv", " Flags:\t0x%x\n", *bufp));
1484
DEBUGDUMPHEADER("recv", "Reserved Byte");
1485
DEBUGDUMPSETUP("recv", bufp, 1);
1486
DEBUGMSG(("dumpv_recv", " Reserved:\t0x%x\n", *bufp));
1490
DEBUGDUMPHEADER("recv", "Session ID");
1491
pdu->sessid = agentx_parse_int(bufp,
1494
AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1498
DEBUGDUMPHEADER("recv", "Transaction ID");
1499
pdu->transid = agentx_parse_int(bufp,
1502
AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1506
DEBUGDUMPHEADER("recv", "Packet ID");
1507
pdu->reqid = agentx_parse_int(bufp,
1509
flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1513
DEBUGDUMPHEADER("recv", "Payload Length");
1514
payload = agentx_parse_int(bufp,
1516
flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1521
if (*length != payload) { /* Short payload */
1529
agentx_parse(netsnmp_session * session, netsnmp_pdu *pdu, u_char * data,
1532
register u_char *bufp = data;
1533
u_char buffer[BUFSIZ];
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;
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;
1547
* Dump the packet in a formatted style
1549
pdu = (netsnmp_pdu *) malloc(sizeof(netsnmp_pdu));
1553
if (!IS_AGENTX_VERSION(session->version))
1554
return SNMPERR_BAD_VERSION;
1556
#ifndef SNMPERR_INCOMPLETE_PACKET
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.
1562
* For now, lets assume that all packets are read in one go.
1563
* I've probably inflicted enough damage on the UCD library
1566
* I'll come back to this once Wes is speaking to me again.
1568
#define SNMPERR_INCOMPLETE_PACKET SNMPERR_ASN_PARSE_ERR
1573
* Handle (common) header ....
1575
bufp = agentx_parse_header(pdu, bufp, length);
1577
return SNMPERR_INCOMPLETE_PACKET; /* i.e. wait for the rest */
1580
* Control PDU handling
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);
1587
* ... and (not-un-common) context
1589
if (pdu->flags & AGENTX_MSG_FLAG_NON_DEFAULT_CONTEXT) {
1590
DEBUGDUMPHEADER("recv", "Context");
1591
bufp = agentx_parse_string(bufp, length, buffer, &buf_len,
1594
AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1597
return SNMPERR_ASN_PARSE_ERR;
1599
pdu->community_len = buf_len;
1600
snmp_clone_mem((void **) &pdu->community,
1601
(void *) buffer, (unsigned) buf_len);
1605
DEBUGDUMPHEADER("recv", "PDU");
1607
switch (pdu->command) {
1608
case AGENTX_MSG_OPEN:
1609
pdu->time = *bufp; /* Timeout */
1614
* Store subagent OID & description in a VarBind
1616
DEBUGDUMPHEADER("recv", "Subagent OID");
1617
bufp = agentx_parse_oid(bufp, length, NULL,
1618
oid_buffer, &oid_buf_len,
1620
flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1624
return SNMPERR_ASN_PARSE_ERR;
1626
DEBUGDUMPHEADER("recv", "Subagent Description");
1627
bufp = agentx_parse_string(bufp, length, buffer, &buf_len,
1630
AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1634
return SNMPERR_ASN_PARSE_ERR;
1636
snmp_pdu_add_variable(pdu, oid_buffer, oid_buf_len,
1637
ASN_OCTET_STR, buffer, buf_len);
1639
oid_buf_len = MAX_OID_LEN;
1643
case AGENTX_MSG_CLOSE:
1644
pdu->errstat = *bufp; /* Reason */
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));
1659
pdu->priority = *bufp;
1660
DEBUGDUMPSETUP("recv", bufp, 1);
1661
DEBUGMSG(("dumpv_recv", " Priority: \t%d\n", *bufp));
1663
pdu->range_subid = *bufp;
1664
DEBUGDUMPSETUP("recv", bufp, 1);
1665
DEBUGMSG(("dumpv_recv", " Range Sub-Id:\t%d\n", *bufp));
1671
prefix_ptr = bufp + 1;
1672
DEBUGDUMPHEADER("recv", "Registration OID");
1673
bufp = agentx_parse_oid(bufp, length, NULL,
1674
oid_buffer, &oid_buf_len,
1676
flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1680
return SNMPERR_ASN_PARSE_ERR;
1683
if (pdu->range_subid) {
1684
range_bound = agentx_parse_int(bufp,
1687
AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1692
* Construct the end-OID.
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;
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);
1702
snmp_add_null_var(pdu, oid_buffer, oid_buf_len);
1705
oid_buf_len = MAX_OID_LEN;
1708
case AGENTX_MSG_GETBULK:
1709
DEBUGDUMPHEADER("recv", "Non-repeaters");
1710
pdu->non_repeaters = agentx_parse_short(bufp,
1713
AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1715
DEBUGDUMPHEADER("recv", "Max-repeaters");
1716
pdu->max_repetitions = agentx_parse_short(bufp + 2,
1719
AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1724
* Fallthrough - SearchRange handling is the same
1727
case AGENTX_MSG_GETNEXT:
1728
case AGENTX_MSG_GET:
1731
* * SearchRange List
1732
* * Keep going while we have data left
1734
DEBUGDUMPHEADER("recv", "Search Range");
1735
while (*length > 0) {
1736
bufp = agentx_parse_oid(bufp, length, &inc,
1737
oid_buffer, &oid_buf_len,
1740
AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1744
return SNMPERR_ASN_PARSE_ERR;
1746
bufp = agentx_parse_oid(bufp, length, NULL,
1747
end_oid_buf, &end_oid_buf_len,
1750
AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1754
return SNMPERR_ASN_PARSE_ERR;
1756
end_oid_buf_len *= sizeof(oid);
1758
* 'agentx_parse_oid()' returns the number of sub_ids
1762
snmp_pdu_add_variable(pdu, oid_buffer, oid_buf_len,
1763
ASN_PRIV_INCL_RANGE,
1764
(u_char *) end_oid_buf,
1767
snmp_pdu_add_variable(pdu, oid_buffer, oid_buf_len,
1768
ASN_PRIV_EXCL_RANGE,
1769
(u_char *) end_oid_buf,
1775
oid_buf_len = MAX_OID_LEN;
1776
end_oid_buf_len = MAX_OID_LEN;
1780
case AGENTX_MSG_RESPONSE:
1782
pdu->flags |= UCD_MSG_FLAG_RESPONSE_PDU;
1787
pdu->time = agentx_parse_int(bufp,
1790
AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1794
pdu->errstat = agentx_parse_short(bufp,
1797
AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1799
agentx_parse_short(bufp + 2,
1801
flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1805
* Fallthrough - VarBind handling is the same
1808
case AGENTX_MSG_INDEX_ALLOCATE:
1809
case AGENTX_MSG_INDEX_DEALLOCATE:
1810
case AGENTX_MSG_NOTIFY:
1811
case AGENTX_MSG_TESTSET:
1815
* * Keep going while we have data left
1818
DEBUGDUMPHEADER("recv", "VarBindList");
1819
while (*length > 0) {
1820
bufp = agentx_parse_varbind(bufp, length, &type,
1821
oid_buffer, &oid_buf_len,
1825
AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1829
return SNMPERR_ASN_PARSE_ERR;
1831
snmp_pdu_add_variable(pdu, oid_buffer, oid_buf_len,
1832
(u_char) type, buffer, buf_len);
1834
oid_buf_len = MAX_OID_LEN;
1840
case AGENTX_MSG_COMMITSET:
1841
case AGENTX_MSG_UNDOSET:
1842
case AGENTX_MSG_CLEANUPSET:
1843
case AGENTX_MSG_PING:
1851
case AGENTX_MSG_ADD_AGENT_CAPS:
1853
* Store AgentCap OID & description in a VarBind
1855
bufp = agentx_parse_oid(bufp, length, NULL,
1856
oid_buffer, &oid_buf_len,
1858
flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1860
return SNMPERR_ASN_PARSE_ERR;
1861
bufp = agentx_parse_string(bufp, length, buffer, &buf_len,
1864
AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1866
return SNMPERR_ASN_PARSE_ERR;
1867
snmp_pdu_add_variable(pdu, oid_buffer, oid_buf_len,
1868
ASN_OCTET_STR, buffer, buf_len);
1870
oid_buf_len = MAX_OID_LEN;
1874
case AGENTX_MSG_REMOVE_AGENT_CAPS:
1876
* Store AgentCap OID & description in a VarBind
1878
bufp = agentx_parse_oid(bufp, length, NULL,
1879
oid_buffer, &oid_buf_len,
1881
flags & AGENTX_FLAGS_NETWORK_BYTE_ORDER);
1883
return SNMPERR_ASN_PARSE_ERR;
1884
snmp_add_null_var(pdu, oid_buffer, oid_buf_len);
1886
oid_buf_len = MAX_OID_LEN;
1892
DEBUGMSGTL(("agentx", "Unrecognised PDU type: %d\n",
1894
return SNMPERR_UNKNOWN_PDU;
1899
return SNMP_ERR_NOERROR;
1907
testit(netsnmp_pdu *pdu1)
1909
char packet1[BUFSIZ];
1910
char packet2[BUFSIZ];
1913
netsnmp_session sess;
1915
memset(&pdu2, 0, sizeof(netsnmp_pdu));
1916
memset(packet1, 0, BUFSIZ);
1917
memset(packet2, 0, BUFSIZ);
1920
* Encode this into a "packet"
1923
if (agentx_build(&sess, pdu1, packet1, &len1) < 0) {
1924
DEBUGMSGTL(("agentx", "First build failed"));
1928
DEBUGMSGTL(("agentx", "First build succeeded:\n"));
1929
xdump(packet1, len1, "Ax1> ");
1932
* Unpack this into a PDU
1935
if (agentx_parse(&pdu2, packet1, &len2, (u_char **) NULL) < 0) {
1936
DEBUGMSGTL(("agentx", "First parse failed\n"));
1939
DEBUGMSGTL(("agentx", "First parse succeeded:\n"));
1941
DEBUGMSGTL(("agentx",
1942
"Warning - parsed packet has %d bytes left\n", len2));
1945
* Encode this into another "packet"
1948
if (agentx_build(&sess, &pdu2, packet2, &len2) < 0) {
1949
DEBUGMSGTL(("agentx", "Second build failed\n"));
1953
DEBUGMSGTL(("agentx", "Second build succeeded:\n"));
1954
xdump(packet2, len2, "Ax2> ");
1957
* Compare the results
1960
DEBUGMSGTL(("agentx",
1961
"Error: first build (%d) is different to second (%d)\n",
1965
if (memcmp(packet1, packet2, len1) != 0) {
1966
DEBUGMSGTL(("agentx",
1967
"Error: first build data is different to second\n"));
1971
DEBUGMSGTL(("agentx", "OK\n"));
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";
1987
* Create an example AgentX pdu structure
1990
memset(&pdu1, 0, sizeof(netsnmp_pdu));
1991
pdu1.command = AGENTX_MSG_TESTSET;
1998
pdu1.non_repeaters = 3;
1999
pdu1.max_repetitions = 32;
2001
pdu1.range_subid = 0;
2003
snmp_pdu_add_variable(&pdu1, oid_buf, sizeof(oid_buf) / sizeof(oid),
2004
ASN_OBJECT_ID, (char *) 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));
2012
printf("Test with non-network order.....\n");
2015
printf("\nTest with network order.....\n");
2016
pdu1.flags |= AGENTX_FLAGS_NETWORK_BYTE_ORDER;
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");
2030
* returns the proper length of an incoming agentx packet.
2033
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2034
* | h.version | h.type | h.flags | <reserved> |
2035
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2037
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2038
* | h.transactionID |
2039
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2041
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2042
* | h.payload_length |
2043
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2044
* 20 bytes in header
2048
agentx_check_packet(u_char * packet, size_t packet_len)
2051
if (packet_len < 20)
2052
return 0; /* minimum header length == 20 */
2054
return agentx_parse_int(packet + 16,
2056
2) & AGENTX_FLAGS_NETWORK_BYTE_ORDER) + 20;