2 * Routines for Agent Extensibility (AgentX) Protocol disassembly
7 * Copyright (c) 2005 by Oleg Terletsky <oleg.terletsky@comverse.com>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1999 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <epan/packet.h>
31 #include <epan/prefs.h>
33 #include <epan/dissectors/packet-tcp.h>
35 static guint global_agentx_tcp_port
= 705;
37 void proto_register_agentx(void);
38 void proto_reg_handoff_agentx(void);
41 /* Define the agentx proto */
42 static int proto_agentx
= -1;
45 static int hf_version
= -1;
46 static int hf_type
= -1;
47 /* static int hf_flags = -1; */
48 static int hf_flags_register
= -1;
49 static int hf_flags_newindex
= -1;
50 static int hf_flags_anyindex
= -1;
51 static int hf_flags_context
= -1;
52 static int hf_flags_byteorder
= -1;
53 static int hf_session_id
= -1;
54 static int hf_trans_id
= -1;
55 static int hf_packet_id
= -1;
56 static int hf_payload_len
= -1;
57 static int hf_ostring_len
= -1;
58 static int hf_ostring
= -1;
59 static int hf_oid_sub
= -1;
60 static int hf_oid_prefix
= -1;
61 static int hf_oid_include
= -1;
62 static int hf_oid_str
= -1;
63 static int hf_resp_uptime
= -1;
64 static int hf_resp_error
= -1;
65 static int hf_resp_index
= -1;
66 static int hf_vtag
= -1;
67 static int hf_val32
= -1;
68 static int hf_val64
= -1;
69 static int hf_open_timeout
= -1;
70 static int hf_close_reason
= -1;
71 static int hf_reg_timeout
= -1;
72 static int hf_reg_prio
= -1;
73 static int hf_reg_rsid
= -1;
74 static int hf_reg_ubound
= -1;
75 static int hf_unreg_timeout
= -1;
76 static int hf_unreg_prio
= -1;
77 static int hf_unreg_rsid
= -1;
78 static int hf_unreg_ubound
= -1;
79 static int hf_gbulk_nrepeat
= -1;
80 static int hf_gbulk_mrepeat
= -1;
83 static gint ett_flags
= -1;
84 static gint ett_agentx
= -1;
85 static gint ett_pdu_hdr
= -1;
86 static gint ett_get
= -1;
87 static gint ett_getnext
= -1;
88 static gint ett_search_range
= -1;
89 static gint ett_obj_ident
= -1;
90 static gint ett_response
= -1;
91 static gint ett_valrep
= -1;
92 static gint ett_open
= -1;
93 static gint ett_close
= -1;
94 static gint ett_register
= -1;
95 static gint ett_unregister
= -1;
96 static gint ett_getbulk
= -1;
97 static gint ett_testset
= -1;
98 static gint ett_commitset
= -1;
99 static gint ett_undoset
= -1;
100 static gint ett_cleanupset
= -1;
101 static gint ett_notify
= -1;
102 static gint ett_ping
= -1;
103 static gint ett_idxalloc
= -1;
104 static gint ett_idxdalloc
= -1;
105 static gint ett_addcap
= -1;
106 static gint ett_remcap
= -1;
109 #define AGENTX_OPEN_PDU 1
110 #define AGENTX_CLOSE_PDU 2
111 #define AGENTX_REGISTER_PDU 3
112 #define AGENTX_UNREGISTER_PDU 4
113 #define AGENTX_GET_PDU 5
114 #define AGENTX_GETNEXT_PDU 6
115 #define AGENTX_GETBULK_PDU 7
116 #define AGENTX_TESTSET_PDU 8
117 #define AGENTX_COMMITSET_PDU 9
118 #define AGENTX_UNDOSET_PDU 10
119 #define AGENTX_CLEANUPSET_PDU 11
120 #define AGENTX_NOTIFY_PDU 12
121 #define AGENTX_PING_PDU 13
122 #define AGENTX_INDEX_ALLOC_PDU 14
123 #define AGENTX_INDEX_DEALLOC_PDU 15
124 #define AGENTX_ADD_AGENT_CAPS_PDU 16
125 #define AGENTX_REM_AGENT_CAPS_PDU 17
126 #define AGENTX_RESPONSE_PDU 18
129 static const value_string type_values
[] = {
130 { AGENTX_OPEN_PDU
, "Open-PDU" },
131 { AGENTX_CLOSE_PDU
, "Close-PDU" },
132 { AGENTX_REGISTER_PDU
, "Register-PDU" },
133 { AGENTX_UNREGISTER_PDU
, "Unregister-PDU" },
134 { AGENTX_GET_PDU
, "Get-PDU" },
135 { AGENTX_GETNEXT_PDU
, "GetNext-PDU" },
136 { AGENTX_GETBULK_PDU
, "GetBulk-PDU" },
137 { AGENTX_TESTSET_PDU
, "TestSet-PDU" },
138 { AGENTX_COMMITSET_PDU
, "CommitSet-PDU" },
139 { AGENTX_UNDOSET_PDU
, "UndoSet-PDU" },
140 { AGENTX_CLEANUPSET_PDU
, "CleanupSet-PDU" },
141 { AGENTX_NOTIFY_PDU
, "Notify-PDU" },
142 { AGENTX_PING_PDU
, "Ping-PDU" },
143 { AGENTX_INDEX_ALLOC_PDU
, "IndexAllocate-PDU" },
144 { AGENTX_INDEX_DEALLOC_PDU
, "IndexDeallocate-PDU" },
145 { AGENTX_ADD_AGENT_CAPS_PDU
, "AddAgentCaps-PDU" },
146 { AGENTX_REM_AGENT_CAPS_PDU
, "RemoveAgentCaps-PDU" },
147 { AGENTX_RESPONSE_PDU
, "Response-PDU" },
150 static value_string_ext type_values_ext
= VALUE_STRING_EXT_INIT(type_values
);
159 #define VB_COUNTER32 65
160 #define VB_GAUGE32 66
161 #define VB_TIMETICK 67
163 #define VB_COUNTER64 70
164 #define VB_NOSUCHOBJ 128
165 #define VB_NOSUCHINST 129
166 #define VB_ENDOFMIB 130
169 static const value_string vtag_values
[] = {
170 { VB_INT
, "Integer" },
171 { VB_OSTR
, "Octet String" },
173 { VB_OID
, "Object Identifier" },
174 { VB_IPADDR
, "IpAddress" },
175 { VB_COUNTER32
, "Counter32" },
176 { VB_GAUGE32
, "Gauge32" },
177 { VB_TIMETICK
, "TimeTicks" },
178 { VB_OPAQUE
, "Opaque" },
179 { VB_COUNTER64
, "Counter64" },
180 { VB_NOSUCHOBJ
, "noSuchObject" },
181 { VB_NOSUCHINST
, "noSuchInstance" },
182 { VB_ENDOFMIB
, "endOfMibView" },
185 static value_string_ext vtag_values_ext
= VALUE_STRING_EXT_INIT(vtag_values
);
188 #define CREASON_OTHER 1
189 #define CREASON_PARSE_ERROR 2
190 #define CREASON_PROTOCOL_ERROR 3
191 #define CREASON_TIMEOUTS 4
192 #define CREASON_SHUTDOWN 5
193 #define CREASON_BY_MANAGER 6
196 static const value_string close_reasons
[] = {
197 { CREASON_OTHER
, "reasonOther" },
198 { CREASON_PARSE_ERROR
, "reasonParseError" },
199 { CREASON_PROTOCOL_ERROR
, "reasonProtocolError" },
200 { CREASON_TIMEOUTS
, "reasonTimeouts" },
201 { CREASON_SHUTDOWN
, "reasonShutdown" },
202 { CREASON_BY_MANAGER
, "reasonByManager" },
207 /* Response errors */
208 #define AGENTX_NO_ERROR 0
209 #define AGENTX_TOO_BIG 1
210 #define AGENTX_NO_SUCH_NAME 2
211 #define AGENTX_BAD_VALUE 3
212 #define AGENTX_READ_ONLY 4
213 #define AGENTX_GEN_ERROR 5
214 #define AGENTX_NO_ACCESS 6
215 #define AGENTX_WRONG_TYPE 7
216 #define AGENTX_WRONG_LEN 8
217 #define AGENTX_WRONG_ENCODE 9
218 #define AGENTX_WRONG_VALUE 10
219 #define AGENTX_NO_CREATION 11
220 #define AGENTX_INCONSIST_VALUE 12
221 #define AGENTX_RES_UNAVAIL 13
222 #define AGENTX_COMMIT_FAILED 14
223 #define AGENTX_UNDO_FAILED 15
224 #define AGENTX_AUTH_ERROR 16
225 #define AGENTX_NOTWRITABLE 17
226 #define AGENTX_INCONSIS_NAME 18
227 #define AGENTX_OPEN_FAILED 256
228 #define AGENTX_NOT_OPEN 257
229 #define AGENTX_IDX_WRONT_TYPE 258
230 #define AGENTX_IDX_ALREAY_ALLOC 259
231 #define AGENTX_IDX_NONEAVAIL 260
232 #define AGENTX_IDX_NOTALLOC 261
233 #define AGENTX_UNSUPP_CONTEXT 262
234 #define AGENTX_DUP_REGISTR 263
235 #define AGENTX_UNKNOWN_REG 264
236 #define AGENTX_UNKNOWN_CAPS 265
239 static const value_string resp_errors
[] = {
240 { AGENTX_NO_ERROR
, "noError" },
241 { AGENTX_TOO_BIG
, "tooBig" },
242 { AGENTX_NO_SUCH_NAME
, "noSuchName" },
243 { AGENTX_BAD_VALUE
, "badValue" },
244 { AGENTX_READ_ONLY
, "readOnly" },
245 { AGENTX_GEN_ERROR
, "genErr" },
246 { AGENTX_NO_ACCESS
, "noAccess" },
247 { AGENTX_WRONG_TYPE
, "wrongType" },
248 { AGENTX_WRONG_LEN
, "wrongLength" },
249 { AGENTX_WRONG_ENCODE
, "wrongEncoding" },
250 { AGENTX_WRONG_VALUE
, "wrongValue" },
251 { AGENTX_NO_CREATION
, "noCreation" },
252 { AGENTX_INCONSIST_VALUE
, "inconsistentValue" },
253 { AGENTX_RES_UNAVAIL
, "resourceUnavailable" },
254 { AGENTX_COMMIT_FAILED
, "commitFailed" },
255 { AGENTX_UNDO_FAILED
, "undoFailed" },
256 { AGENTX_AUTH_ERROR
, "authorizationError" },
257 { AGENTX_NOTWRITABLE
, "notWritable" },
258 { AGENTX_INCONSIS_NAME
, "inconsistentName" },
259 { AGENTX_OPEN_FAILED
, "openFailed" },
260 { AGENTX_NOT_OPEN
, "notOpen" },
261 { AGENTX_IDX_WRONT_TYPE
, "indexWrongType" },
262 { AGENTX_IDX_ALREAY_ALLOC
, "indexAlreadyAllocated" },
263 { AGENTX_IDX_NONEAVAIL
, "indexNoneAvailable" },
264 { AGENTX_IDX_NOTALLOC
, "indexNotAllocated" },
265 { AGENTX_UNSUPP_CONTEXT
, "unsupportedContext" },
266 { AGENTX_DUP_REGISTR
, "duplicateRegistration" },
267 { AGENTX_UNKNOWN_REG
, "unknownRegistration" },
268 { AGENTX_UNKNOWN_CAPS
, "unknownAgentCaps" },
271 static value_string_ext resp_errors_ext
= VALUE_STRING_EXT_INIT(resp_errors
);
273 /* OID usage indicators */
275 enum OID_USAGE
{ OID_START_RANGE
, OID_END_RANGE
, OID_EXACT
};
277 /* PDU Header flags */
279 #define INSTANCE_REGISTRATION 0x01
280 #define NEW_INDEX 0x02
281 #define ANY_INDEX 0x04
282 #define NON_DEFAULT_CONTEXT 0x08
283 #define NETWORK_BYTE_ORDER 0x10
285 #define OID_IS_INCLUSIVE 0x01
287 #define PDU_HDR_LEN 20
288 #define PADDING(x) ((((x) + 3) >> 2) << 2)
290 #define NORLEL(flags,var,tvb,offset) \
291 var = (flags & NETWORK_BYTE_ORDER) ? \
292 tvb_get_ntohl(tvb, offset) : \
293 tvb_get_letohl(tvb, offset)
294 #define NORLES(flags,var,tvb,offset) \
295 var = (flags & NETWORK_BYTE_ORDER) ? \
296 tvb_get_ntohs(tvb, offset) : \
297 tvb_get_letohs(tvb, offset)
300 dissect_octet_string(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, guint8 flags
)
302 guint32 n_oct
, p_noct
;
304 NORLEL(flags
, n_oct
, tvb
, offset
);
306 p_noct
= PADDING(n_oct
);
308 proto_tree_add_uint(tree
, hf_ostring_len
, tvb
, offset
, 4, n_oct
);
310 * XXX - an "octet string" is not necessarily a text string, so
311 * having hf_ostring be FT_STRING is not necessarily appropriate.
313 proto_tree_add_item(tree
, hf_ostring
, tvb
, offset
+ 4, n_oct
, ENC_ASCII
|ENC_NA
);
318 /* XXX - Is there a particular reason we're not using oid_encoded2string() here? */
320 convert_oid_to_str(guint32
*oid
, int len
, char* str
, int slen
, char prefix
)
327 if(slen
< len
) return 0;
330 tlen
+= g_snprintf(str
, slen
, ".1.3.6.1.%d", prefix
);
333 for(i
=0; i
< len
&& tlen
< slen
; i
++) {
334 tlen
+= g_snprintf(str
+tlen
, slen
-tlen
, ".%d", oid
[i
]);
340 dissect_object_id(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, guint8 flags
, enum OID_USAGE oid_usage
)
351 memset(oid
, '\0', sizeof(oid
));
352 memset(str_oid
, '\0', sizeof(str_oid
));
354 n_subid
= tvb_get_guint8(tvb
, offset
);
355 prefix
= tvb_get_guint8(tvb
, offset
+ 1);
356 include
= tvb_get_guint8(tvb
, offset
+ 2);
357 tvb_get_guint8(tvb
, offset
+ 3);
359 for(i
=0; i
<n_subid
; i
++) {
360 NORLEL(flags
, oid
[i
], tvb
, (offset
+4) + (i
*4));
363 if(!convert_oid_to_str(&oid
[0], n_subid
, &str_oid
[0], 2048, prefix
))
364 g_snprintf(&str_oid
[0], 2048, "(null)");
367 const char *range
= "";
368 const char *inclusion
= (include
) ? " (Inclusive)" : " (Exclusive)";
370 case OID_START_RANGE
: range
= "(Range Start) "; break;
371 case OID_END_RANGE
: range
= " (Range End) "; break;
372 default: inclusion
= ""; break;
374 item
= proto_tree_add_text(tree
, tvb
, offset
, 4 + (n_subid
* 4) ,
375 "Object Identifier: %s%s%s", range
, str_oid
, inclusion
);
376 subtree
= proto_item_add_subtree(item
, ett_obj_ident
);
380 proto_tree_add_uint(subtree
, hf_oid_sub
, tvb
, offset
, 1, n_subid
);
381 proto_tree_add_uint(subtree
, hf_oid_prefix
, tvb
, offset
+ 1, 1, prefix
);
382 proto_tree_add_boolean(subtree
, hf_oid_include
, tvb
, offset
+ 2, 1, include
);
383 proto_tree_add_string(subtree
, hf_oid_str
, tvb
, offset
+ 4, (n_subid
* 4), str_oid
);
385 return 4 + (n_subid
* 4);
389 dissect_search_range(tvbuff_t
*tvb
, proto_tree
*tree
, int start_offset
, guint8 flags
, guint8 pdu_type
)
391 int offset
= start_offset
;
392 offset
+= dissect_object_id(tvb
, tree
, offset
, flags
, (pdu_type
== AGENTX_GET_PDU
) ? OID_EXACT
: OID_START_RANGE
);
393 offset
+= dissect_object_id(tvb
, tree
, offset
, flags
, (pdu_type
== AGENTX_GET_PDU
) ? OID_EXACT
: OID_END_RANGE
);
395 return (offset
- start_offset
);
399 dissect_val64(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, guint8 flags
)
401 guint encoding
= (flags
& NETWORK_BYTE_ORDER
) ? ENC_BIG_ENDIAN
: ENC_LITTLE_ENDIAN
;
403 proto_tree_add_item(tree
, hf_val64
, tvb
, offset
, 8, encoding
);
409 dissect_val32(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, guint8 flags
)
411 guint encoding
= (flags
& NETWORK_BYTE_ORDER
) ? ENC_BIG_ENDIAN
: ENC_LITTLE_ENDIAN
;
413 proto_tree_add_item(tree
, hf_val32
, tvb
, offset
, 4, encoding
);
419 dissect_varbind(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, guint8 flags
)
426 NORLES(flags
, vtag
, tvb
, offset
);
427 /* 2 reserved bytes after this */
430 item
= proto_tree_add_text(tree
, tvb
, offset
, len
, "Value Representation");
431 subtree
= proto_item_add_subtree(item
, ett_valrep
);
434 proto_tree_add_uint(subtree
, hf_vtag
, tvb
, offset
, 2, vtag
);
435 tlen
= dissect_object_id(tvb
, subtree
, offset
+ 4, flags
, OID_EXACT
);
440 tlen
+= dissect_object_id(tvb
, subtree
, offset
+ tlen
+ 4, flags
, OID_EXACT
);
446 tlen
+= dissect_octet_string(tvb
, subtree
, offset
+ tlen
+ 4, flags
);
453 tlen
+= dissect_val32(tvb
, subtree
, offset
+ tlen
+ 4, flags
);
457 tlen
+= dissect_val64(tvb
, subtree
, offset
+ tlen
+ 4, flags
);
470 dissect_response_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, guint8 flags
)
474 guint encoding
= (flags
& NETWORK_BYTE_ORDER
) ? ENC_BIG_ENDIAN
: ENC_LITTLE_ENDIAN
;
477 item
= proto_tree_add_text(tree
, tvb
, offset
, len
, "Response-PDU");
478 subtree
= proto_item_add_subtree(item
, ett_response
);
480 NORLEL(flags
, r_uptime
, tvb
, offset
);
481 proto_tree_add_uint_format(subtree
, hf_resp_uptime
, tvb
, offset
, 4, r_uptime
,
482 "sysUptime: %s", time_msecs_to_str(r_uptime
));
483 proto_tree_add_item(subtree
, hf_resp_error
, tvb
, offset
+ 4, 2, encoding
);
484 proto_tree_add_item(subtree
, hf_resp_index
, tvb
, offset
+ 6, 2, encoding
);
488 while(len
> offset
) {
489 offset
+= dissect_varbind(tvb
, subtree
, offset
, len
, flags
);
494 dissect_getnext_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, guint8 flags
)
499 item
= proto_tree_add_text(tree
, tvb
, offset
, len
, "GetNext-PDU");
500 subtree
= proto_item_add_subtree(item
, ett_getnext
);
502 if(flags
& NON_DEFAULT_CONTEXT
) {
504 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
508 while(len
> offset
) {
509 offset
+= dissect_search_range(tvb
, subtree
, offset
, flags
, 0);
514 dissect_get_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, guint8 flags
)
519 item
= proto_tree_add_text(tree
, tvb
, offset
, len
, "Get-PDU");
520 subtree
= proto_item_add_subtree(item
, ett_get
);
522 if(flags
& NON_DEFAULT_CONTEXT
) {
524 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
528 while(len
> offset
) {
529 offset
+= dissect_search_range(tvb
, subtree
, offset
, flags
, AGENTX_GET_PDU
);
534 dissect_getbulk_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, guint8 flags
)
538 guint encoding
= (flags
& NETWORK_BYTE_ORDER
) ? ENC_BIG_ENDIAN
: ENC_LITTLE_ENDIAN
;
540 item
= proto_tree_add_text(tree
, tvb
, offset
, len
, "GetBulk-PDU");
541 subtree
= proto_item_add_subtree(item
, ett_getbulk
);
543 if(flags
& NON_DEFAULT_CONTEXT
) {
545 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
548 proto_tree_add_item(subtree
, hf_gbulk_nrepeat
, tvb
, offset
, 2, encoding
);
549 proto_tree_add_item(subtree
, hf_gbulk_mrepeat
, tvb
, offset
+ 2, 2, encoding
);
552 while(len
>= offset
) {
553 offset
+= dissect_search_range(tvb
, subtree
, offset
, flags
, 0);
558 dissect_open_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, guint8 flags
)
564 item
= proto_tree_add_text(tree
, tvb
, offset
, len
, "Open-PDU");
565 subtree
= proto_item_add_subtree(item
, ett_open
);
567 timeout
= tvb_get_guint8(tvb
, offset
);
568 tvb_get_ntoh24(tvb
, offset
+ 1);
570 proto_tree_add_uint(subtree
, hf_open_timeout
, tvb
, offset
, 1, timeout
);
574 offset
+= dissect_object_id(tvb
, subtree
, offset
, flags
, OID_EXACT
);
577 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
582 dissect_close_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
)
588 item
= proto_tree_add_text(tree
, tvb
, offset
, len
, "Close-PDU");
589 subtree
= proto_item_add_subtree(item
, ett_close
);
591 reason
= tvb_get_guint8(tvb
, offset
);
592 tvb_get_ntoh24(tvb
, offset
+ 1);
594 proto_tree_add_uint(subtree
, hf_close_reason
, tvb
, offset
, 1, reason
);
601 dissect_register_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, guint8 flags
)
606 guint encoding
= (flags
& NETWORK_BYTE_ORDER
) ? ENC_BIG_ENDIAN
: ENC_LITTLE_ENDIAN
;
608 item
= proto_tree_add_text(tree
, tvb
, offset
, len
, "Register-PDU");
609 subtree
= proto_item_add_subtree(item
, ett_register
);
611 if(flags
& NON_DEFAULT_CONTEXT
) {
613 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
616 proto_tree_add_item(subtree
, hf_reg_timeout
, tvb
, offset
, 1, encoding
);
617 proto_tree_add_item(subtree
, hf_reg_prio
, tvb
, offset
+1, 1, encoding
);
618 proto_tree_add_item(subtree
, hf_reg_rsid
, tvb
, offset
+2, 1, encoding
);
623 offset
+= dissect_object_id(tvb
, subtree
, offset
, flags
, OID_EXACT
);
627 /* Upper bound (opt) */
628 proto_tree_add_item(subtree
, hf_reg_ubound
, tvb
, offset
, 4, encoding
);
636 dissect_unregister_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, guint8 flags
)
640 guint encoding
= (flags
& NETWORK_BYTE_ORDER
) ? ENC_BIG_ENDIAN
: ENC_LITTLE_ENDIAN
;
642 item
= proto_tree_add_text(tree
, tvb
, offset
, len
, "Unregister-PDU");
643 subtree
= proto_item_add_subtree(item
, ett_unregister
);
645 if(flags
& NON_DEFAULT_CONTEXT
) {
647 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
650 proto_tree_add_item(subtree
, hf_unreg_timeout
, tvb
, offset
, 1, encoding
);
651 proto_tree_add_item(subtree
, hf_unreg_prio
, tvb
, offset
+1, 1, encoding
);
652 proto_tree_add_item(subtree
, hf_unreg_rsid
, tvb
, offset
+2, 1, encoding
);
656 offset
+= dissect_object_id(tvb
, subtree
, offset
, flags
, OID_EXACT
);
660 /* Upper bound (opt) */
661 proto_tree_add_item(subtree
, hf_unreg_ubound
, tvb
, offset
, 4, encoding
);
669 dissect_testset_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, guint8 flags
)
674 item
= proto_tree_add_text(tree
, tvb
, offset
, len
, "Testset-PDU");
675 subtree
= proto_item_add_subtree(item
, ett_testset
);
677 if(flags
& NON_DEFAULT_CONTEXT
) {
679 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
682 while(len
> offset
) {
683 offset
+= dissect_varbind(tvb
, subtree
, offset
, len
, flags
);
688 dissect_notify_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, guint8 flags
)
693 item
= proto_tree_add_text(tree
, tvb
, offset
, len
, "Notify-PDU");
694 subtree
= proto_item_add_subtree(item
, ett_notify
);
696 if(flags
& NON_DEFAULT_CONTEXT
) {
698 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
701 while(len
> offset
) {
702 offset
+= dissect_varbind(tvb
, subtree
, offset
, len
, flags
);
707 dissect_ping_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, guint8 flags
)
712 item
= proto_tree_add_text(tree
, tvb
, offset
, len
, "Ping-PDU");
713 subtree
= proto_item_add_subtree(item
, ett_ping
);
715 if(flags
& NON_DEFAULT_CONTEXT
) {
717 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
723 dissect_idx_alloc_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, guint8 flags
)
728 item
= proto_tree_add_text(tree
, tvb
, offset
, len
, "IndexAllocate-PDU");
729 subtree
= proto_item_add_subtree(item
, ett_idxalloc
);
731 if(flags
& NON_DEFAULT_CONTEXT
) {
733 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
736 while(len
> offset
) {
737 offset
+= dissect_varbind(tvb
, subtree
, offset
, len
, flags
);
743 dissect_idx_dealloc_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, guint8 flags
)
748 item
= proto_tree_add_text(tree
, tvb
, offset
, len
, "IndexDeallocate-PDU");
749 subtree
= proto_item_add_subtree(item
, ett_idxdalloc
);
751 if(flags
& NON_DEFAULT_CONTEXT
) {
753 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
756 while(len
> offset
) {
757 offset
+= dissect_varbind(tvb
, subtree
, offset
, len
, flags
);
762 dissect_add_caps_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, guint8 flags
)
767 item
= proto_tree_add_text(tree
, tvb
, offset
, len
, "AddAgentCaps-PDU");
768 subtree
= proto_item_add_subtree(item
, ett_addcap
);
770 if(flags
& NON_DEFAULT_CONTEXT
) {
772 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
775 offset
+= dissect_object_id(tvb
, subtree
, offset
, flags
, OID_EXACT
);
777 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
783 dissect_rem_caps_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int len
, guint8 flags
)
788 item
= proto_tree_add_text(tree
, tvb
, offset
, len
, "RemoveAgentCaps-PDU");
789 subtree
= proto_item_add_subtree(item
, ett_remcap
);
791 if(flags
& NON_DEFAULT_CONTEXT
) {
793 offset
+= dissect_octet_string(tvb
, subtree
, offset
, flags
);
796 offset
+= dissect_object_id(tvb
, subtree
, offset
, flags
, OID_EXACT
);
803 get_agentx_pdu_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
)
809 * Get the payload length.
811 flags
= tvb_get_guint8(tvb
, offset
+ 2);
812 NORLEL(flags
, plen
, tvb
, offset
+ 16);
815 * Arbitrarily limit it to 2^24, so we don't have to worry about
822 * That length doesn't include the header; add that in.
828 dissect_agentx_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
831 proto_tree
* agentx_tree
, *pdu_hdr_tree
, *flags_tree
;
832 proto_item
* pdu_item
, *t_item
;
841 version
= tvb_get_guint8(tvb
, 0); offset
+=1;
842 type
= tvb_get_guint8(tvb
, 1); offset
+=1;
843 flags
= tvb_get_guint8(tvb
, 2); offset
+=1;
844 /* skip reserved byte */
847 NORLEL(flags
, session_id
, tvb
, 4); offset
+=4;
848 NORLEL(flags
, trans_id
, tvb
, 8); offset
+=4;
849 NORLEL(flags
, packet_id
, tvb
, 12); offset
+=4;
850 NORLEL(flags
, payload_len
, tvb
, 16); offset
+=4;
852 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "AgentX");
854 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s: sid=%d, tid=%d, packid=%d, plen=%d",
855 val_to_str_ext_const(type
, &type_values_ext
, "unknown"),
856 session_id
, trans_id
, packet_id
, payload_len
);
862 /*t_item = proto_tree_add_item(tree, proto_agentx, tvb, 0, -1, ENC_NA);*/
863 t_item
= proto_tree_add_protocol_format(tree
, proto_agentx
, tvb
, 0, -1,
864 "Agent Extensibility (AgentX) Protocol: %s, sid=%d, tid=%d, packid=%d, plen=%d",
865 val_to_str_ext_const(type
, &type_values_ext
, "unknown"),
866 session_id
, trans_id
, packet_id
, payload_len
);
867 agentx_tree
= proto_item_add_subtree(t_item
, ett_agentx
);
869 pdu_item
= proto_tree_add_text(agentx_tree
, tvb
, 0, PDU_HDR_LEN
, "PDU Header: Type[%u], len=%d, sid=%d, tid=%d, packid=%d",
870 (char)type
, payload_len
, session_id
, trans_id
, packet_id
);
872 pdu_hdr_tree
= proto_item_add_subtree(pdu_item
, ett_pdu_hdr
);
874 proto_tree_add_uint(pdu_hdr_tree
, hf_version
, tvb
, 0, 1, version
);
875 proto_tree_add_uint(pdu_hdr_tree
, hf_type
, tvb
, 1, 1, type
);
877 t_item
= proto_tree_add_text(pdu_hdr_tree
, tvb
, 2, 1, "Flags: 0x%02x", flags
);
878 flags_tree
= proto_item_add_subtree(t_item
, ett_flags
);
879 proto_tree_add_boolean(flags_tree
, hf_flags_register
, tvb
, 2, 1, flags
);
880 proto_tree_add_boolean(flags_tree
, hf_flags_newindex
, tvb
, 2, 1, flags
);
881 proto_tree_add_boolean(flags_tree
, hf_flags_anyindex
, tvb
, 2, 1, flags
);
882 proto_tree_add_boolean(flags_tree
, hf_flags_context
, tvb
, 2, 1, flags
);
883 proto_tree_add_boolean(flags_tree
, hf_flags_byteorder
, tvb
, 2, 1, flags
);
885 proto_tree_add_uint(pdu_hdr_tree
, hf_session_id
, tvb
, 4, 4, session_id
);
886 proto_tree_add_uint(pdu_hdr_tree
, hf_trans_id
, tvb
, 8, 4, trans_id
);
887 proto_tree_add_uint(pdu_hdr_tree
, hf_packet_id
, tvb
, 12, 4, packet_id
);
888 proto_tree_add_uint(pdu_hdr_tree
, hf_payload_len
, tvb
, 16, 4, payload_len
);
891 case AGENTX_OPEN_PDU
:
892 dissect_open_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
895 case AGENTX_CLOSE_PDU
:
896 dissect_close_pdu(tvb
, agentx_tree
, offset
, payload_len
);
899 case AGENTX_REGISTER_PDU
:
900 dissect_register_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
903 case AGENTX_UNREGISTER_PDU
:
904 dissect_unregister_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
908 dissect_get_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
911 case AGENTX_GETNEXT_PDU
:
912 dissect_getnext_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
915 case AGENTX_GETBULK_PDU
:
916 dissect_getbulk_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
919 case AGENTX_TESTSET_PDU
:
920 dissect_testset_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
923 case AGENTX_COMMITSET_PDU
:
924 case AGENTX_UNDOSET_PDU
:
925 case AGENTX_CLEANUPSET_PDU
:
926 /* there is no parameters */
929 case AGENTX_NOTIFY_PDU
:
930 dissect_notify_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
933 case AGENTX_PING_PDU
:
934 dissect_ping_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
937 case AGENTX_INDEX_ALLOC_PDU
:
938 dissect_idx_alloc_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
941 case AGENTX_INDEX_DEALLOC_PDU
:
942 dissect_idx_dealloc_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
945 case AGENTX_ADD_AGENT_CAPS_PDU
:
946 dissect_add_caps_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
949 case AGENTX_REM_AGENT_CAPS_PDU
:
950 dissect_rem_caps_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
953 case AGENTX_RESPONSE_PDU
:
954 dissect_response_pdu(tvb
, agentx_tree
, offset
, payload_len
, flags
);
958 return tvb_length(tvb
);
962 dissect_agentx(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
964 tcp_dissect_pdus(tvb
, pinfo
, tree
, TRUE
, 20, get_agentx_pdu_len
,
965 dissect_agentx_pdu
, data
);
966 return tvb_length(tvb
);
969 static const true_false_string tfs_agentx_include
= { "Yes", "No" };
970 static const true_false_string tfs_agentx_register
= { "Yes", "No" };
971 static const true_false_string tfs_agentx_newindex
= { "Yes", "No" };
972 static const true_false_string tfs_agentx_anyindex
= { "Yes", "No" };
973 static const true_false_string tfs_agentx_context
= { "Provided", "None" };
974 static const true_false_string tfs_agentx_byteorder
= { "MSB (network order)", "LSB" };
977 proto_register_agentx(void)
979 static hf_register_info hf
[] = {
982 { "Version", "agentx.version", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
983 "header version", HFILL
}},
986 { "Type", "agentx.type", FT_UINT8
, BASE_DEC
| BASE_EXT_STRING
, &type_values_ext
, 0x0,
987 "header type", HFILL
}},
991 { "Flags", "agentx.flags", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
992 "header type", HFILL
}},
995 { &hf_flags_register
,
996 { "Register", "agentx.flags.register", FT_BOOLEAN
, 8, TFS(&tfs_agentx_register
),
997 INSTANCE_REGISTRATION
, "Instance Registration", HFILL
}},
999 { &hf_flags_newindex
,
1000 { "New Index", "agentx.flags.newindex", FT_BOOLEAN
, 8, TFS(&tfs_agentx_newindex
),
1001 NEW_INDEX
, "New Index Requested", HFILL
}},
1003 { &hf_flags_anyindex
,
1004 { "Any Index", "agentx.flags.anyindex", FT_BOOLEAN
, 8, TFS(&tfs_agentx_anyindex
),
1005 ANY_INDEX
, "Any Index Requested", HFILL
}},
1007 { &hf_flags_context
,
1008 { "Non-default Context", "agentx.flags.context", FT_BOOLEAN
, 8, TFS(&tfs_agentx_context
),
1009 NON_DEFAULT_CONTEXT
, NULL
, HFILL
}},
1011 { &hf_flags_byteorder
,
1012 { "Byte Order", "agentx.flags.byteorder", FT_BOOLEAN
, 8, TFS(&tfs_agentx_byteorder
),
1013 NETWORK_BYTE_ORDER
, NULL
, HFILL
}},
1016 { "sessionID", "agentx.session_id", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1017 "Session ID", HFILL
}},
1020 { "TransactionID", "agentx.transaction_id", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1021 "Transaction ID", HFILL
}},
1024 { "PacketID", "agentx.packet_id", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1025 "Packet ID", HFILL
}},
1028 { "Payload length", "agentx.payload_len", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1032 { "Octet String", "agentx.ostring", FT_STRING
, BASE_NONE
, NULL
, 0x0,
1036 { "OString len", "agentx.ostring_len", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1037 "Octet String Length", HFILL
}},
1040 { "Number subids", "agentx.n_subid", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1044 { "OID prefix", "agentx.oid_prefix", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1048 { "OID include", "agentx.oid_include", FT_BOOLEAN
, 8, TFS(&tfs_agentx_include
),
1049 OID_IS_INCLUSIVE
, NULL
, HFILL
}},
1052 { "OID", "agentx.oid", FT_STRING
, BASE_NONE
, NULL
, 0x0,
1056 { "sysUpTime", "agentx.r.uptime", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1060 { "Resp. error", "agentx.r.error", FT_UINT16
, BASE_DEC
| BASE_EXT_STRING
, &resp_errors_ext
, 0x0,
1061 "response error", HFILL
}},
1064 { "Resp. index", "agentx.r.index", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1065 "response index", HFILL
}},
1068 { "Variable type", "agentx.v.tag", FT_UINT16
, BASE_DEC
| BASE_EXT_STRING
, &vtag_values_ext
, 0x0,
1072 { "Value(32)", "agentx.v.val32", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1076 { "Value(64)", "agentx.v.val64", FT_UINT64
, BASE_DEC
, NULL
, 0x0,
1080 { "Timeout", "agentx.o.timeout", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1081 "open timeout", HFILL
}},
1084 { "Reason", "agentx.c.reason", FT_UINT8
, BASE_DEC
, VALS(close_reasons
), 0x0,
1085 "close reason", HFILL
}},
1088 { "Timeout", "agentx.r.timeout", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1089 "Register timeout", HFILL
}},
1092 { "Priority", "agentx.r.priority", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1093 "Register Priority", HFILL
}},
1096 { "Range_subid", "agentx.r.range_subid", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1097 "Register range_subid", HFILL
}},
1100 { "Upper bound", "agentx.r.upper_bound", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1101 "Register upper bound", HFILL
}},
1103 { &hf_unreg_timeout
,
1104 { "Timeout", "agentx.u.timeout", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1105 "Unregister timeout", HFILL
}},
1108 { "Priority", "agentx.u.priority", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1109 "Unregister Priority", HFILL
}},
1112 { "Range_subid", "agentx.u.range_subid", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1113 "Unregister range_subid", HFILL
}},
1116 { "Upper bound", "agentx.u.upper_bound", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1117 "Register upper bound", HFILL
}},
1119 { &hf_gbulk_nrepeat
,
1120 { "Repeaters", "agentx.gb.nrepeat", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1121 "getBulk Num. repeaters", HFILL
}},
1123 { &hf_gbulk_mrepeat
,
1124 { "Max Repetition", "agentx.gb.mrepeat", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1125 "getBulk Max repetition", HFILL
}},
1128 /* Add more fields here */
1132 static gint
*ett
[] = {
1160 module_t
*agentx_module
;
1162 proto_agentx
= proto_register_protocol("AgentX",
1163 "AgentX", "agentx");
1165 proto_register_field_array(proto_agentx
, hf
, array_length(hf
));
1166 proto_register_subtree_array(ett
, array_length(ett
));
1168 agentx_module
= prefs_register_protocol(proto_agentx
, proto_reg_handoff_agentx
);
1170 prefs_register_uint_preference(agentx_module
, "tcp.agentx_port",
1171 "AgentX listener TCP Port",
1172 "Set the TCP port for AgentX"
1173 "(if other than the default of 705)",
1174 10, &global_agentx_tcp_port
);
1177 /* The registration hand-off routine */
1179 proto_reg_handoff_agentx(void)
1181 static gboolean agentx_prefs_initialized
= FALSE
;
1182 static dissector_handle_t agentx_handle
;
1183 static guint agentx_tcp_port
;
1185 if(!agentx_prefs_initialized
) {
1186 agentx_handle
= new_create_dissector_handle(dissect_agentx
, proto_agentx
);
1187 agentx_prefs_initialized
= TRUE
;
1190 dissector_delete_uint("tcp.port", agentx_tcp_port
, agentx_handle
);
1193 agentx_tcp_port
= global_agentx_tcp_port
;
1194 dissector_add_uint("tcp.port", agentx_tcp_port
, agentx_handle
);