2 * Routines for Agent Extensibility (AgentX) Protocol disassembly
5 * Copyright (c) 2005 by Oleg Terletsky <oleg.terletsky@comverse.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1999 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include <epan/packet.h>
17 #include <epan/to_str.h>
19 #include <wsutil/ws_roundup.h>
21 #include "packet-tcp.h"
23 #define AGENTX_TCP_PORT 705
25 void proto_register_agentx(void);
26 void proto_reg_handoff_agentx(void);
28 static dissector_handle_t agentx_handle
;
30 /* Define the agentx proto */
31 static int proto_agentx
;
34 static int hf_version
;
37 static int hf_flags_register
;
38 static int hf_flags_newindex
;
39 static int hf_flags_anyindex
;
40 static int hf_flags_context
;
41 static int hf_flags_byteorder
;
42 static int hf_session_id
;
43 static int hf_trans_id
;
44 static int hf_packet_id
;
45 static int hf_payload_len
;
46 static int hf_ostring_len
;
47 static int hf_ostring
;
48 static int hf_oid_sub
;
49 static int hf_oid_prefix
;
50 static int hf_oid_include
;
51 static int hf_oid_str
;
52 static int hf_resp_uptime
;
53 static int hf_resp_error
;
54 static int hf_resp_index
;
58 static int hf_open_timeout
;
59 static int hf_close_reason
;
60 static int hf_reg_timeout
;
61 static int hf_reg_prio
;
62 static int hf_reg_rsid
;
63 static int hf_reg_ubound
;
64 static int hf_unreg_timeout
;
65 static int hf_unreg_prio
;
66 static int hf_unreg_rsid
;
67 static int hf_unreg_ubound
;
68 static int hf_gbulk_nrepeat
;
69 static int hf_gbulk_mrepeat
;
73 static int ett_agentx
;
74 static int ett_pdu_hdr
;
76 static int ett_getnext
;
77 static int ett_search_range
;
78 static int ett_obj_ident
;
79 static int ett_response
;
80 static int ett_valrep
;
83 static int ett_register
;
84 static int ett_unregister
;
85 static int ett_getbulk
;
86 static int ett_testset
;
87 static int ett_commitset
;
88 static int ett_undoset
;
89 static int ett_cleanupset
;
90 static int ett_notify
;
92 static int ett_idxalloc
;
93 static int ett_idxdalloc
;
94 static int ett_addcap
;
95 static int ett_remcap
;
98 #define AGENTX_OPEN_PDU 1
99 #define AGENTX_CLOSE_PDU 2
100 #define AGENTX_REGISTER_PDU 3
101 #define AGENTX_UNREGISTER_PDU 4
102 #define AGENTX_GET_PDU 5
103 #define AGENTX_GETNEXT_PDU 6
104 #define AGENTX_GETBULK_PDU 7
105 #define AGENTX_TESTSET_PDU 8
106 #define AGENTX_COMMITSET_PDU 9
107 #define AGENTX_UNDOSET_PDU 10
108 #define AGENTX_CLEANUPSET_PDU 11
109 #define AGENTX_NOTIFY_PDU 12
110 #define AGENTX_PING_PDU 13
111 #define AGENTX_INDEX_ALLOC_PDU 14
112 #define AGENTX_INDEX_DEALLOC_PDU 15
113 #define AGENTX_ADD_AGENT_CAPS_PDU 16
114 #define AGENTX_REM_AGENT_CAPS_PDU 17
115 #define AGENTX_RESPONSE_PDU 18
118 static const value_string type_values
[] = {
119 { AGENTX_OPEN_PDU
, "Open-PDU" },
120 { AGENTX_CLOSE_PDU
, "Close-PDU" },
121 { AGENTX_REGISTER_PDU
, "Register-PDU" },
122 { AGENTX_UNREGISTER_PDU
, "Unregister-PDU" },
123 { AGENTX_GET_PDU
, "Get-PDU" },
124 { AGENTX_GETNEXT_PDU
, "GetNext-PDU" },
125 { AGENTX_GETBULK_PDU
, "GetBulk-PDU" },
126 { AGENTX_TESTSET_PDU
, "TestSet-PDU" },
127 { AGENTX_COMMITSET_PDU
, "CommitSet-PDU" },
128 { AGENTX_UNDOSET_PDU
, "UndoSet-PDU" },
129 { AGENTX_CLEANUPSET_PDU
, "CleanupSet-PDU" },
130 { AGENTX_NOTIFY_PDU
, "Notify-PDU" },
131 { AGENTX_PING_PDU
, "Ping-PDU" },
132 { AGENTX_INDEX_ALLOC_PDU
, "IndexAllocate-PDU" },
133 { AGENTX_INDEX_DEALLOC_PDU
, "IndexDeallocate-PDU" },
134 { AGENTX_ADD_AGENT_CAPS_PDU
, "AddAgentCaps-PDU" },
135 { AGENTX_REM_AGENT_CAPS_PDU
, "RemoveAgentCaps-PDU" },
136 { AGENTX_RESPONSE_PDU
, "Response-PDU" },
139 static value_string_ext type_values_ext
= VALUE_STRING_EXT_INIT(type_values
);
148 #define VB_COUNTER32 65
149 #define VB_GAUGE32 66
150 #define VB_TIMETICK 67
152 #define VB_COUNTER64 70
153 #define VB_NOSUCHOBJ 128
154 #define VB_NOSUCHINST 129
155 #define VB_ENDOFMIB 130
158 static const value_string vtag_values
[] = {
159 { VB_INT
, "Integer" },
160 { VB_OSTR
, "Octet String" },
162 { VB_OID
, "Object Identifier" },
163 { VB_IPADDR
, "IpAddress" },
164 { VB_COUNTER32
, "Counter32" },
165 { VB_GAUGE32
, "Gauge32" },
166 { VB_TIMETICK
, "TimeTicks" },
167 { VB_OPAQUE
, "Opaque" },
168 { VB_COUNTER64
, "Counter64" },
169 { VB_NOSUCHOBJ
, "noSuchObject" },
170 { VB_NOSUCHINST
, "noSuchInstance" },
171 { VB_ENDOFMIB
, "endOfMibView" },
174 static value_string_ext vtag_values_ext
= VALUE_STRING_EXT_INIT(vtag_values
);
177 #define CREASON_OTHER 1
178 #define CREASON_PARSE_ERROR 2
179 #define CREASON_PROTOCOL_ERROR 3
180 #define CREASON_TIMEOUTS 4
181 #define CREASON_SHUTDOWN 5
182 #define CREASON_BY_MANAGER 6
185 static const value_string close_reasons
[] = {
186 { CREASON_OTHER
, "reasonOther" },
187 { CREASON_PARSE_ERROR
, "reasonParseError" },
188 { CREASON_PROTOCOL_ERROR
, "reasonProtocolError" },
189 { CREASON_TIMEOUTS
, "reasonTimeouts" },
190 { CREASON_SHUTDOWN
, "reasonShutdown" },
191 { CREASON_BY_MANAGER
, "reasonByManager" },
196 /* Response errors */
197 #define AGENTX_NO_ERROR 0
198 #define AGENTX_TOO_BIG 1
199 #define AGENTX_NO_SUCH_NAME 2
200 #define AGENTX_BAD_VALUE 3
201 #define AGENTX_READ_ONLY 4
202 #define AGENTX_GEN_ERROR 5
203 #define AGENTX_NO_ACCESS 6
204 #define AGENTX_WRONG_TYPE 7
205 #define AGENTX_WRONG_LEN 8
206 #define AGENTX_WRONG_ENCODE 9
207 #define AGENTX_WRONG_VALUE 10
208 #define AGENTX_NO_CREATION 11
209 #define AGENTX_INCONSIST_VALUE 12
210 #define AGENTX_RES_UNAVAIL 13
211 #define AGENTX_COMMIT_FAILED 14
212 #define AGENTX_UNDO_FAILED 15
213 #define AGENTX_AUTH_ERROR 16
214 #define AGENTX_NOTWRITABLE 17
215 #define AGENTX_INCONSIS_NAME 18
216 #define AGENTX_OPEN_FAILED 256
217 #define AGENTX_NOT_OPEN 257
218 #define AGENTX_IDX_WRONT_TYPE 258
219 #define AGENTX_IDX_ALREAY_ALLOC 259
220 #define AGENTX_IDX_NONEAVAIL 260
221 #define AGENTX_IDX_NOTALLOC 261
222 #define AGENTX_UNSUPP_CONTEXT 262
223 #define AGENTX_DUP_REGISTR 263
224 #define AGENTX_UNKNOWN_REG 264
225 #define AGENTX_UNKNOWN_CAPS 265
228 static const value_string resp_errors
[] = {
229 { AGENTX_NO_ERROR
, "noError" },
230 { AGENTX_TOO_BIG
, "tooBig" },
231 { AGENTX_NO_SUCH_NAME
, "noSuchName" },
232 { AGENTX_BAD_VALUE
, "badValue" },
233 { AGENTX_READ_ONLY
, "readOnly" },
234 { AGENTX_GEN_ERROR
, "genErr" },
235 { AGENTX_NO_ACCESS
, "noAccess" },
236 { AGENTX_WRONG_TYPE
, "wrongType" },
237 { AGENTX_WRONG_LEN
, "wrongLength" },
238 { AGENTX_WRONG_ENCODE
, "wrongEncoding" },
239 { AGENTX_WRONG_VALUE
, "wrongValue" },
240 { AGENTX_NO_CREATION
, "noCreation" },
241 { AGENTX_INCONSIST_VALUE
, "inconsistentValue" },
242 { AGENTX_RES_UNAVAIL
, "resourceUnavailable" },
243 { AGENTX_COMMIT_FAILED
, "commitFailed" },
244 { AGENTX_UNDO_FAILED
, "undoFailed" },
245 { AGENTX_AUTH_ERROR
, "authorizationError" },
246 { AGENTX_NOTWRITABLE
, "notWritable" },
247 { AGENTX_INCONSIS_NAME
, "inconsistentName" },
248 { AGENTX_OPEN_FAILED
, "openFailed" },
249 { AGENTX_NOT_OPEN
, "notOpen" },
250 { AGENTX_IDX_WRONT_TYPE
, "indexWrongType" },
251 { AGENTX_IDX_ALREAY_ALLOC
, "indexAlreadyAllocated" },
252 { AGENTX_IDX_NONEAVAIL
, "indexNoneAvailable" },
253 { AGENTX_IDX_NOTALLOC
, "indexNotAllocated" },
254 { AGENTX_UNSUPP_CONTEXT
, "unsupportedContext" },
255 { AGENTX_DUP_REGISTR
, "duplicateRegistration" },
256 { AGENTX_UNKNOWN_REG
, "unknownRegistration" },
257 { AGENTX_UNKNOWN_CAPS
, "unknownAgentCaps" },
260 static value_string_ext resp_errors_ext
= VALUE_STRING_EXT_INIT(resp_errors
);
262 /* OID usage indicators */
264 enum OID_USAGE
{ OID_START_RANGE
, OID_END_RANGE
, OID_EXACT
};
266 /* PDU Header flags */
268 #define INSTANCE_REGISTRATION 0x01
269 #define NEW_INDEX 0x02
270 #define ANY_INDEX 0x04
271 #define NON_DEFAULT_CONTEXT 0x08
272 #define NETWORK_BYTE_ORDER 0x10
274 #define OID_IS_INCLUSIVE 0x01
276 #define PDU_HDR_LEN 20
278 #define NORLEL(flags,var,tvb,offset) \
279 var = (flags & NETWORK_BYTE_ORDER) ? \
280 tvb_get_ntohl(tvb, offset) : \
281 tvb_get_letohl(tvb, offset)
282 #define NORLES(flags,var,tvb,offset) \
283 var = (flags & NETWORK_BYTE_ORDER) ? \
284 tvb_get_ntohs(tvb, offset) : \
285 tvb_get_letohs(tvb, offset)
288 dissect_octet_string(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, uint8_t flags
)
290 uint32_t n_oct
, p_noct
;
292 NORLEL(flags
, n_oct
, tvb
, offset
);
294 p_noct
= WS_ROUNDUP_4(n_oct
);
296 proto_tree_add_uint(tree
, hf_ostring_len
, tvb
, offset
, 4, n_oct
);
298 * XXX - an "octet string" is not necessarily a text string, so
299 * having hf_ostring be FT_STRING is not necessarily appropriate.
301 proto_tree_add_item(tree
, hf_ostring
, tvb
, offset
+ 4, n_oct
, ENC_ASCII
);
306 /* XXX - Is there a particular reason we're not using oid_encoded2string() here? */
308 convert_oid_to_str(uint32_t *oid
, int len
, char* str
, int slen
, char prefix
)
315 if(slen
< len
) return 0;
318 tlen
+= snprintf(str
, slen
, ".1.3.6.1.%d", prefix
);
321 for(i
=0; i
< len
&& tlen
< slen
; i
++) {
322 tlen
+= snprintf(str
+tlen
, slen
-tlen
, ".%d", oid
[i
]);
328 dissect_object_id(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, uint8_t flags
, enum OID_USAGE oid_usage
)
338 memset(oid
, '\0', sizeof(oid
));
339 memset(str_oid
, '\0', sizeof(str_oid
));
341 n_subid
= tvb_get_uint8(tvb
, offset
);
342 prefix
= tvb_get_uint8(tvb
, offset
+ 1);
343 include
= tvb_get_uint8(tvb
, offset
+ 2);
344 tvb_get_uint8(tvb
, offset
+ 3);
346 for(i
=0; i
<n_subid
; i
++) {
347 NORLEL(flags
, oid
[i
], tvb
, (offset
+4) + (i
*4));
350 if(!convert_oid_to_str(&oid
[0], n_subid
, &str_oid
[0], 2048, prefix
))
351 snprintf(&str_oid
[0], 2048, "(null)");
354 const char *range
= "";
355 const char *inclusion
= (include
) ? " (Inclusive)" : " (Exclusive)";
357 case OID_START_RANGE
: range
= "(Range Start) "; break;
358 case OID_END_RANGE
: range
= " (Range End) "; break;
359 default: inclusion
= ""; break;
361 subtree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, 4 + (n_subid
* 4) ,
362 ett_obj_ident
, NULL
, "Object Identifier: %s%s%s", range
, str_oid
, inclusion
);
366 proto_tree_add_uint(subtree
, hf_oid_sub
, tvb
, offset
, 1, n_subid
);
367 proto_tree_add_uint(subtree
, hf_oid_prefix
, tvb
, offset
+ 1, 1, prefix
);
368 proto_tree_add_boolean(subtree
, hf_oid_include
, tvb
, offset
+ 2, 1, include
);
369 proto_tree_add_string(subtree
, hf_oid_str
, tvb
, offset
+ 4, (n_subid
* 4), str_oid
);
371 return 4 + (n_subid
* 4);
375 dissect_search_range(tvbuff_t
*tvb
, proto_tree
*tree
, int start_offset
, uint8_t flags
, uint8_t pdu_type
)
377 int offset
= start_offset
;
378 offset
+= dissect_object_id(tvb
, tree
, offset
, flags
, (pdu_type
== AGENTX_GET_PDU
) ? OID_EXACT
: OID_START_RANGE
);
379 offset
+= dissect_object_id(tvb
, tree
, offset
, flags
, (pdu_type
== AGENTX_GET_PDU
) ? OID_EXACT
: OID_END_RANGE
);
381 return (offset
- start_offset
);
385 dissect_val64(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, uint8_t flags
)
387 unsigned encoding
= (flags
& NETWORK_BYTE_ORDER
) ? ENC_BIG_ENDIAN
: ENC_LITTLE_ENDIAN
;
389 proto_tree_add_item(tree
, hf_val64
, tvb
, offset
, 8, encoding
);
395 dissect_val32(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, uint8_t flags
)
397 unsigned encoding
= (flags
& NETWORK_BYTE_ORDER
) ? ENC_BIG_ENDIAN
: ENC_LITTLE_ENDIAN
;
399 proto_tree_add_item(tree
, hf_val32
, tvb
, offset
, 4, encoding
);
405 dissect_varbind(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, uint8_t flags
)
411 NORLES(flags
, vtag
, tvb
, offset
);
412 /* 2 reserved bytes after this */
415 subtree
= proto_tree_add_subtree(tree
, tvb
, offset
, len
, ett_valrep
, NULL
, "Value Representation");
418 proto_tree_add_uint(subtree
, hf_vtag
, tvb
, offset
, 2, vtag
);
419 tlen
= dissect_object_id(tvb
, subtree
, offset
+ 4, flags
, OID_EXACT
);
424 tlen
+= dissect_object_id(tvb
, subtree
, offset
+ tlen
+ 4, flags
, OID_EXACT
);
430 tlen
+= dissect_octet_string(tvb
, subtree
, offset
+ tlen
+ 4, flags
);
437 tlen
+= dissect_val32(tvb
, subtree
, offset
+ tlen
+ 4, flags
);
441 tlen
+= dissect_val64(tvb
, subtree
, offset
+ tlen
+ 4, flags
);
454 dissect_response_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, int len
, uint8_t flags
)
457 unsigned encoding
= (flags
& NETWORK_BYTE_ORDER
) ? ENC_BIG_ENDIAN
: ENC_LITTLE_ENDIAN
;
460 subtree
= proto_tree_add_subtree(tree
, tvb
, offset
, len
, ett_response
, NULL
, "Response-PDU");
462 NORLEL(flags
, r_uptime
, tvb
, offset
);
463 proto_tree_add_uint_format(subtree
, hf_resp_uptime
, tvb
, offset
, 4, r_uptime
,
464 "sysUptime: %s", signed_time_msecs_to_str(pinfo
->pool
, r_uptime
));
465 proto_tree_add_item(subtree
, hf_resp_error
, tvb
, offset
+ 4, 2, encoding
);
466 proto_tree_add_item(subtree
, hf_resp_index
, tvb
, offset
+ 6, 2, encoding
);
470 while(len
> offset
) {
471 offset
+= dissect_varbind(tvb
, subtree
, offset
, len
, flags
);
476 dissect_getnext_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, uint8_t flags
)
480 subtree
= proto_tree_add_subtree(tree
, tvb
, offset
, len
, ett_getnext
, NULL
, "GetNext-PDU");
482 if(flags
& NON_DEFAULT_CONTEXT
) {
484 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
488 while(len
> offset
) {
489 offset
+= dissect_search_range(tvb
, subtree
, offset
, flags
, 0);
494 dissect_get_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, uint8_t flags
)
498 subtree
= proto_tree_add_subtree(tree
, tvb
, offset
, len
, ett_get
, NULL
, "Get-PDU");
500 if(flags
& NON_DEFAULT_CONTEXT
) {
502 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
506 while(len
> offset
) {
507 offset
+= dissect_search_range(tvb
, subtree
, offset
, flags
, AGENTX_GET_PDU
);
512 dissect_getbulk_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, uint8_t flags
)
515 unsigned encoding
= (flags
& NETWORK_BYTE_ORDER
) ? ENC_BIG_ENDIAN
: ENC_LITTLE_ENDIAN
;
517 subtree
= proto_tree_add_subtree(tree
, tvb
, offset
, len
, ett_getbulk
, NULL
, "GetBulk-PDU");
519 if(flags
& NON_DEFAULT_CONTEXT
) {
521 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
524 proto_tree_add_item(subtree
, hf_gbulk_nrepeat
, tvb
, offset
, 2, encoding
);
525 proto_tree_add_item(subtree
, hf_gbulk_mrepeat
, tvb
, offset
+ 2, 2, encoding
);
528 while(len
>= offset
) {
529 offset
+= dissect_search_range(tvb
, subtree
, offset
, flags
, 0);
534 dissect_open_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, uint8_t flags
)
539 subtree
= proto_tree_add_subtree(tree
, tvb
, offset
, len
, ett_open
, NULL
, "Open-PDU");
541 timeout
= tvb_get_uint8(tvb
, offset
);
542 tvb_get_ntoh24(tvb
, offset
+ 1);
544 proto_tree_add_uint(subtree
, hf_open_timeout
, tvb
, offset
, 1, timeout
);
548 offset
+= dissect_object_id(tvb
, subtree
, offset
, flags
, OID_EXACT
);
551 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
556 dissect_close_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
)
560 subtree
= proto_tree_add_subtree(tree
, tvb
, offset
, len
, ett_close
, NULL
, "Close-PDU");
562 proto_tree_add_item(subtree
, hf_close_reason
, tvb
, offset
, 1, ENC_NA
);
563 tvb_get_ntoh24(tvb
, offset
+ 1);
570 dissect_register_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, uint8_t flags
)
573 unsigned encoding
= (flags
& NETWORK_BYTE_ORDER
) ? ENC_BIG_ENDIAN
: ENC_LITTLE_ENDIAN
;
575 subtree
= proto_tree_add_subtree(tree
, tvb
, offset
, len
, ett_register
, NULL
, "Register-PDU");
577 if(flags
& NON_DEFAULT_CONTEXT
) {
579 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
582 proto_tree_add_item(subtree
, hf_reg_timeout
, tvb
, offset
, 1, encoding
);
583 proto_tree_add_item(subtree
, hf_reg_prio
, tvb
, offset
+1, 1, encoding
);
584 proto_tree_add_item(subtree
, hf_reg_rsid
, tvb
, offset
+2, 1, encoding
);
589 offset
+= dissect_object_id(tvb
, subtree
, offset
, flags
, OID_EXACT
);
593 /* Upper bound (opt) */
594 proto_tree_add_item(subtree
, hf_reg_ubound
, tvb
, offset
, 4, encoding
);
602 dissect_unregister_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, uint8_t flags
)
605 unsigned encoding
= (flags
& NETWORK_BYTE_ORDER
) ? ENC_BIG_ENDIAN
: ENC_LITTLE_ENDIAN
;
607 subtree
= proto_tree_add_subtree(tree
, tvb
, offset
, len
, ett_unregister
, NULL
, "Unregister-PDU");
609 if(flags
& NON_DEFAULT_CONTEXT
) {
611 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
614 proto_tree_add_item(subtree
, hf_unreg_timeout
, tvb
, offset
, 1, encoding
);
615 proto_tree_add_item(subtree
, hf_unreg_prio
, tvb
, offset
+1, 1, encoding
);
616 proto_tree_add_item(subtree
, hf_unreg_rsid
, tvb
, offset
+2, 1, encoding
);
620 offset
+= dissect_object_id(tvb
, subtree
, offset
, flags
, OID_EXACT
);
624 /* Upper bound (opt) */
625 proto_tree_add_item(subtree
, hf_unreg_ubound
, tvb
, offset
, 4, encoding
);
633 dissect_testset_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, uint8_t flags
)
637 subtree
= proto_tree_add_subtree(tree
, tvb
, offset
, len
, ett_testset
, NULL
, "Testset-PDU");
639 if(flags
& NON_DEFAULT_CONTEXT
) {
641 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
644 while(len
> offset
) {
645 offset
+= dissect_varbind(tvb
, subtree
, offset
, len
, flags
);
650 dissect_notify_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, uint8_t flags
)
654 subtree
= proto_tree_add_subtree(tree
, tvb
, offset
, len
, ett_notify
, NULL
, "Notify-PDU");
656 if(flags
& NON_DEFAULT_CONTEXT
) {
658 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
661 while(len
> offset
) {
662 offset
+= dissect_varbind(tvb
, subtree
, offset
, len
, flags
);
667 dissect_ping_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, uint8_t flags
)
671 subtree
= proto_tree_add_subtree(tree
, tvb
, offset
, len
, ett_ping
, NULL
, "Ping-PDU");
673 if(flags
& NON_DEFAULT_CONTEXT
) {
675 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
681 dissect_idx_alloc_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, uint8_t flags
)
685 subtree
= proto_tree_add_subtree(tree
, tvb
, offset
, len
, ett_idxalloc
, NULL
, "IndexAllocate-PDU");
687 if(flags
& NON_DEFAULT_CONTEXT
) {
689 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
692 while(len
> offset
) {
693 offset
+= dissect_varbind(tvb
, subtree
, offset
, len
, flags
);
699 dissect_idx_dealloc_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, uint8_t flags
)
703 subtree
= proto_tree_add_subtree(tree
, tvb
, offset
, len
, ett_idxdalloc
, NULL
, "IndexDeallocate-PDU");
705 if(flags
& NON_DEFAULT_CONTEXT
) {
707 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
710 while(len
> offset
) {
711 offset
+= dissect_varbind(tvb
, subtree
, offset
, len
, flags
);
716 dissect_add_caps_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, uint8_t flags
)
720 subtree
= proto_tree_add_subtree(tree
, tvb
, offset
, len
, ett_addcap
, NULL
, "AddAgentCaps-PDU");
722 if(flags
& NON_DEFAULT_CONTEXT
) {
724 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
727 offset
+= dissect_object_id(tvb
, subtree
, offset
, flags
, OID_EXACT
);
729 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
735 dissect_rem_caps_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, uint8_t flags
)
739 subtree
= proto_tree_add_subtree(tree
, tvb
, offset
, len
, ett_remcap
, NULL
, "RemoveAgentCaps-PDU");
741 if(flags
& NON_DEFAULT_CONTEXT
) {
743 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
746 offset
+= dissect_object_id(tvb
, subtree
, offset
, flags
, OID_EXACT
);
753 get_agentx_pdu_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
, void *data _U_
)
759 * Get the payload length.
761 flags
= tvb_get_uint8(tvb
, offset
+ 2);
762 NORLEL(flags
, plen
, tvb
, offset
+ 16);
765 * Arbitrarily limit it to 2^24, so we don't have to worry about
772 * That length doesn't include the header; add that in.
778 dissect_agentx_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
781 proto_tree
* agentx_tree
, *pdu_hdr_tree
;
789 uint32_t payload_len
;
790 static int * const pdu_flags
[] = {
799 version
= tvb_get_uint8(tvb
, 0); offset
+=1;
800 type
= tvb_get_uint8(tvb
, 1); offset
+=1;
801 flags
= tvb_get_uint8(tvb
, 2); offset
+=1;
802 /* skip reserved byte */
805 NORLEL(flags
, session_id
, tvb
, 4); offset
+=4;
806 NORLEL(flags
, trans_id
, tvb
, 8); offset
+=4;
807 NORLEL(flags
, packet_id
, tvb
, 12); offset
+=4;
808 NORLEL(flags
, payload_len
, tvb
, 16); offset
+=4;
810 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "AgentX");
812 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s: sid=%d, tid=%d, packid=%d, plen=%d",
813 val_to_str_ext_const(type
, &type_values_ext
, "unknown"),
814 session_id
, trans_id
, packet_id
, payload_len
);
818 return tvb_captured_length(tvb
);
820 /*t_item = proto_tree_add_item(tree, proto_agentx, tvb, 0, -1, ENC_NA);*/
821 t_item
= proto_tree_add_protocol_format(tree
, proto_agentx
, tvb
, 0, -1,
822 "Agent Extensibility (AgentX) Protocol: %s, sid=%d, tid=%d, packid=%d, plen=%d",
823 val_to_str_ext_const(type
, &type_values_ext
, "unknown"),
824 session_id
, trans_id
, packet_id
, payload_len
);
825 agentx_tree
= proto_item_add_subtree(t_item
, ett_agentx
);
827 pdu_hdr_tree
= proto_tree_add_subtree_format(agentx_tree
, tvb
, 0, PDU_HDR_LEN
,
828 ett_pdu_hdr
, NULL
, "PDU Header: Type[%u], len=%d, sid=%d, tid=%d, packid=%d",
829 (char)type
, payload_len
, session_id
, trans_id
, packet_id
);
831 proto_tree_add_uint(pdu_hdr_tree
, hf_version
, tvb
, 0, 1, version
);
832 proto_tree_add_uint(pdu_hdr_tree
, hf_type
, tvb
, 1, 1, type
);
833 proto_tree_add_bitmask(pdu_hdr_tree
, tvb
, 2, hf_flags
, ett_flags
, pdu_flags
, ENC_NA
);
835 proto_tree_add_uint(pdu_hdr_tree
, hf_session_id
, tvb
, 4, 4, session_id
);
836 proto_tree_add_uint(pdu_hdr_tree
, hf_trans_id
, tvb
, 8, 4, trans_id
);
837 proto_tree_add_uint(pdu_hdr_tree
, hf_packet_id
, tvb
, 12, 4, packet_id
);
838 proto_tree_add_uint(pdu_hdr_tree
, hf_payload_len
, tvb
, 16, 4, payload_len
);
841 case AGENTX_OPEN_PDU
:
842 dissect_open_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
845 case AGENTX_CLOSE_PDU
:
846 dissect_close_pdu(tvb
, agentx_tree
, offset
, payload_len
);
849 case AGENTX_REGISTER_PDU
:
850 dissect_register_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
853 case AGENTX_UNREGISTER_PDU
:
854 dissect_unregister_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
858 dissect_get_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
861 case AGENTX_GETNEXT_PDU
:
862 dissect_getnext_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
865 case AGENTX_GETBULK_PDU
:
866 dissect_getbulk_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
869 case AGENTX_TESTSET_PDU
:
870 dissect_testset_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
873 case AGENTX_COMMITSET_PDU
:
874 case AGENTX_UNDOSET_PDU
:
875 case AGENTX_CLEANUPSET_PDU
:
876 /* there is no parameters */
879 case AGENTX_NOTIFY_PDU
:
880 dissect_notify_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
883 case AGENTX_PING_PDU
:
884 dissect_ping_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
887 case AGENTX_INDEX_ALLOC_PDU
:
888 dissect_idx_alloc_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
891 case AGENTX_INDEX_DEALLOC_PDU
:
892 dissect_idx_dealloc_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
895 case AGENTX_ADD_AGENT_CAPS_PDU
:
896 dissect_add_caps_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
899 case AGENTX_REM_AGENT_CAPS_PDU
:
900 dissect_rem_caps_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
903 case AGENTX_RESPONSE_PDU
:
904 dissect_response_pdu(tvb
, pinfo
, agentx_tree
, offset
, payload_len
, flags
);
908 return tvb_captured_length(tvb
);
912 dissect_agentx(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
914 tcp_dissect_pdus(tvb
, pinfo
, tree
, true, 20, get_agentx_pdu_len
,
915 dissect_agentx_pdu
, data
);
916 return tvb_captured_length(tvb
);
919 static const true_false_string tfs_agentx_context
= { "Provided", "None" };
920 static const true_false_string tfs_agentx_byteorder
= { "MSB (network order)", "LSB" };
923 proto_register_agentx(void)
925 static hf_register_info hf
[] = {
928 { "Version", "agentx.version", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
929 "header version", HFILL
}},
932 { "Type", "agentx.type", FT_UINT8
, BASE_DEC
| BASE_EXT_STRING
, &type_values_ext
, 0x0,
933 "header type", HFILL
}},
936 { "Flags", "agentx.flags", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
937 "header type", HFILL
}},
939 { &hf_flags_register
,
940 { "Register", "agentx.flags.register", FT_BOOLEAN
, 8, TFS(&tfs_yes_no
),
941 INSTANCE_REGISTRATION
, "Instance Registration", HFILL
}},
943 { &hf_flags_newindex
,
944 { "New Index", "agentx.flags.newindex", FT_BOOLEAN
, 8, TFS(&tfs_yes_no
),
945 NEW_INDEX
, "New Index Requested", HFILL
}},
947 { &hf_flags_anyindex
,
948 { "Any Index", "agentx.flags.anyindex", FT_BOOLEAN
, 8, TFS(&tfs_yes_no
),
949 ANY_INDEX
, "Any Index Requested", HFILL
}},
952 { "Non-default Context", "agentx.flags.context", FT_BOOLEAN
, 8, TFS(&tfs_agentx_context
),
953 NON_DEFAULT_CONTEXT
, NULL
, HFILL
}},
955 { &hf_flags_byteorder
,
956 { "Byte Order", "agentx.flags.byteorder", FT_BOOLEAN
, 8, TFS(&tfs_agentx_byteorder
),
957 NETWORK_BYTE_ORDER
, NULL
, HFILL
}},
960 { "sessionID", "agentx.session_id", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
961 "Session ID", HFILL
}},
964 { "TransactionID", "agentx.transaction_id", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
965 "Transaction ID", HFILL
}},
968 { "PacketID", "agentx.packet_id", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
969 "Packet ID", HFILL
}},
972 { "Payload length", "agentx.payload_len", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
976 { "Octet String", "agentx.ostring", FT_STRING
, BASE_NONE
, NULL
, 0x0,
980 { "OString len", "agentx.ostring_len", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
981 "Octet String Length", HFILL
}},
984 { "Number subids", "agentx.n_subid", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
988 { "OID prefix", "agentx.oid_prefix", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
992 { "OID include", "agentx.oid_include", FT_BOOLEAN
, 8, TFS(&tfs_yes_no
),
993 OID_IS_INCLUSIVE
, NULL
, HFILL
}},
996 { "OID", "agentx.oid", FT_STRING
, BASE_NONE
, NULL
, 0x0,
1000 { "sysUpTime", "agentx.r.uptime", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1004 { "Resp. error", "agentx.r.error", FT_UINT16
, BASE_DEC
| BASE_EXT_STRING
, &resp_errors_ext
, 0x0,
1005 "response error", HFILL
}},
1008 { "Resp. index", "agentx.r.index", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1009 "response index", HFILL
}},
1012 { "Variable type", "agentx.v.tag", FT_UINT16
, BASE_DEC
| BASE_EXT_STRING
, &vtag_values_ext
, 0x0,
1016 { "Value(32)", "agentx.v.val32", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1020 { "Value(64)", "agentx.v.val64", FT_UINT64
, BASE_DEC
, NULL
, 0x0,
1024 { "Timeout", "agentx.o.timeout", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1025 "open timeout", HFILL
}},
1028 { "Reason", "agentx.c.reason", FT_UINT8
, BASE_DEC
, VALS(close_reasons
), 0x0,
1029 "close reason", HFILL
}},
1032 { "Timeout", "agentx.r.timeout", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1033 "Register timeout", HFILL
}},
1036 { "Priority", "agentx.r.priority", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1037 "Register Priority", HFILL
}},
1040 { "Range_subid", "agentx.r.range_subid", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1041 "Register range_subid", HFILL
}},
1044 { "Upper bound", "agentx.r.upper_bound", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1045 "Register upper bound", HFILL
}},
1047 { &hf_unreg_timeout
,
1048 { "Timeout", "agentx.u.timeout", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1049 "Unregister timeout", HFILL
}},
1052 { "Priority", "agentx.u.priority", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1053 "Unregister Priority", HFILL
}},
1056 { "Range_subid", "agentx.u.range_subid", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1057 "Unregister range_subid", HFILL
}},
1060 { "Upper bound", "agentx.u.upper_bound", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1061 "Register upper bound", HFILL
}},
1063 { &hf_gbulk_nrepeat
,
1064 { "Repeaters", "agentx.gb.nrepeat", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1065 "getBulk Num. repeaters", HFILL
}},
1067 { &hf_gbulk_mrepeat
,
1068 { "Max Repetition", "agentx.gb.mrepeat", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1069 "getBulk Max repetition", HFILL
}},
1072 /* Add more fields here */
1076 static int *ett
[] = {
1103 proto_agentx
= proto_register_protocol("AgentX", "AgentX", "agentx");
1105 proto_register_field_array(proto_agentx
, hf
, array_length(hf
));
1106 proto_register_subtree_array(ett
, array_length(ett
));
1108 agentx_handle
= register_dissector("agentx", dissect_agentx
, proto_agentx
);
1111 /* The registration hand-off routine */
1113 proto_reg_handoff_agentx(void)
1115 dissector_add_uint_with_preference("tcp.port", AGENTX_TCP_PORT
, agentx_handle
);
1119 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1124 * indent-tabs-mode: t
1127 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1128 * :indentSize=8:tabSize=8:noTabs=false: