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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
39 #include <epan/packet.h>
40 #include <epan/prefs.h>
42 #include <epan/dissectors/packet-tcp.h>
44 static guint global_agentx_tcp_port = 705;
46 void proto_reg_handoff_agentx(void);
49 /* Define the agentx proto */
50 static int proto_agentx = -1;
53 static int hf_version = -1;
54 static int hf_type = -1;
55 static int hf_flags = -1;
56 static int hf_session_id = -1;
57 static int hf_trans_id = -1;
58 static int hf_packet_id = -1;
59 static int hf_payload_len = -1;
60 static int hf_ostring_len = -1;
61 static int hf_ostring = -1;
62 static int hf_oid_sub = -1;
63 static int hf_oid_prefix = -1;
64 static int hf_oid_include = -1;
65 static int hf_oid_str = -1;
66 static int hf_resp_uptime = -1;
67 static int hf_resp_error = -1;
68 static int hf_resp_index = -1;
69 static int hf_vtag = -1;
70 static int hf_val32 = -1;
71 static int hf_val64 = -1;
72 static int hf_open_timeout = -1;
73 static int hf_close_reason = -1;
74 static int hf_reg_timeout = -1;
75 static int hf_reg_prio = -1;
76 static int hf_reg_rsid = -1;
77 static int hf_reg_ubound = -1;
78 static int hf_unreg_timeout = -1;
79 static int hf_unreg_prio = -1;
80 static int hf_unreg_rsid = -1;
81 static int hf_unreg_ubound = -1;
82 static int hf_gbulk_nrepeat = -1;
83 static int hf_gbulk_mrepeat = -1;
86 static gint ett_agentx = -1;
87 static gint ett_pdu_hdr = -1;
88 static gint ett_get = -1;
89 static gint ett_getnext = -1;
90 static gint ett_search_range = -1;
91 static gint ett_obj_ident = -1;
92 static gint ett_response = -1;
93 static gint ett_valrep = -1;
94 static gint ett_open = -1;
95 static gint ett_close = -1;
96 static gint ett_register = -1;
97 static gint ett_unregister = -1;
98 static gint ett_getbulk = -1;
99 static gint ett_testset = -1;
100 static gint ett_commitset = -1;
101 static gint ett_undoset = -1;
102 static gint ett_cleanupset = -1;
103 static gint ett_notify = -1;
104 static gint ett_ping = -1;
105 static gint ett_idxalloc = -1;
106 static gint ett_idxdalloc = -1;
107 static gint ett_addcap = -1;
108 static gint ett_remcap = -1;
111 #define AGENTX_OPEN_PDU 1
112 #define AGENTX_CLOSE_PDU 2
113 #define AGENTX_REGISTER_PDU 3
114 #define AGENTX_UNREGISTER_PDU 4
115 #define AGENTX_GET_PDU 5
116 #define AGENTX_GETNEXT_PDU 6
117 #define AGENTX_GETBULK_PDU 7
118 #define AGENTX_TESTSET_PDU 8
119 #define AGENTX_COMMITSET_PDU 9
120 #define AGENTX_UNDOSET_PDU 10
121 #define AGENTX_CLEANUPSET_PDU 11
122 #define AGENTX_NOTIFY_PDU 12
123 #define AGENTX_PING_PDU 13
124 #define AGENTX_INDEX_ALLOC_PDU 14
125 #define AGENTX_INDEX_DEALLOC_PDU 15
126 #define AGENTX_ADD_AGENT_CAPS_PDU 16
127 #define AGENTX_REM_AGENT_CAPS_PDU 17
128 #define AGENTX_RESPONSE_PDU 18
131 static const value_string type_values [] = {
132 { AGENTX_OPEN_PDU, "Open-PDU" },
133 { AGENTX_CLOSE_PDU, "Close-PDU" },
134 { AGENTX_REGISTER_PDU, "Register-PDU" },
135 { AGENTX_UNREGISTER_PDU, "Unregister-PDU" },
136 { AGENTX_GET_PDU, "Get-PDU" },
137 { AGENTX_GETNEXT_PDU, "GetNext-PDU" },
138 { AGENTX_GETBULK_PDU, "GetBulk-PDU" },
139 { AGENTX_TESTSET_PDU, "TestSet-PDU" },
140 { AGENTX_COMMITSET_PDU, "CommitSet-PDU" },
141 { AGENTX_UNDOSET_PDU, "UndoSet-PDU" },
142 { AGENTX_CLEANUPSET_PDU, "CleanupSet-PDU" },
143 { AGENTX_NOTIFY_PDU, "Notify-PDU" },
144 { AGENTX_PING_PDU, "Ping-PDU" },
145 { AGENTX_INDEX_ALLOC_PDU, "IndexAllocate-PDU" },
146 { AGENTX_INDEX_DEALLOC_PDU, "IndexDeallocate-PDU" },
147 { AGENTX_ADD_AGENT_CAPS_PDU, "AddAgentCaps-PDU" },
148 { AGENTX_REM_AGENT_CAPS_PDU, "RemoveAgentCaps-PDU" },
149 { AGENTX_RESPONSE_PDU, "Response-PDU" },
161 #define VB_COUNTER32 65
162 #define VB_GAUGE32 66
163 #define VB_TIMETICK 67
165 #define VB_COUNTER64 70
166 #define VB_NOSUCHOBJ 128
167 #define VB_NOSUCHINST 129
168 #define VB_ENDOFMIB 130
171 static const value_string vtag_values [] = {
172 { VB_INT, "Integer" },
173 { VB_OSTR, "Octet String" },
175 { VB_OID, "Object Identifier" },
176 { VB_IPADDR, "IpAddress" },
177 { VB_COUNTER32, "Counter32" },
178 { VB_GAUGE32, "Gauge32" },
179 { VB_TIMETICK, "TimeTicks" },
180 { VB_OPAQUE, "Opaque" },
181 { VB_COUNTER64, "Counter64" },
182 { VB_NOSUCHOBJ, "noSuchObject" },
183 { VB_NOSUCHINST, "noSuchInstance" },
184 { VB_ENDOFMIB, "endOfMibView" },
190 #define CREASON_OTHER 1
191 #define CREASON_PARSE_ERROR 2
192 #define CREASON_PROTOCOL_ERROR 3
193 #define CREASON_TIMEOUTS 4
194 #define CREASON_SHUTDOWN 5
195 #define CREASON_BY_MANAGER 6
198 static const value_string close_reasons[] = {
199 { CREASON_OTHER, "reasonOther" },
200 { CREASON_PARSE_ERROR, "reasonParseError" },
201 { CREASON_PROTOCOL_ERROR, "reasonProtocolError" },
202 { CREASON_TIMEOUTS, "reasonTimeouts" },
203 { CREASON_SHUTDOWN , "reasonShutdown" },
204 { CREASON_BY_MANAGER, "reasonByManager" },
209 /* Response errors */
210 #define AGENTX_NO_ERROR 0
211 #define AGENTX_TOO_BIG 1
212 #define AGENTX_NO_SUCH_NAME 2
213 #define AGENTX_BAD_VALUE 3
214 #define AGENTX_READ_ONLY 4
215 #define AGENTX_GEN_ERROR 5
216 #define AGENTX_NO_ACCESS 6
217 #define AGENTX_WRONG_TYPE 7
218 #define AGENTX_WRONG_LEN 8
219 #define AGENTX_WRONG_ENCODE 9
220 #define AGENTX_WRONG_VALUE 10
221 #define AGENTX_NO_CREATION 11
222 #define AGENTX_INCONSIST_VALUE 12
223 #define AGENTX_RES_UNAVAIL 13
224 #define AGENTX_COMMIT_FAILED 14
225 #define AGENTX_UNDO_FAILED 15
226 #define AGENTX_AUTH_ERROR 16
227 #define AGENTX_NOTWRITABLE 17
228 #define AGENTX_INCONSIS_NAME 18
229 #define AGENTX_OPEN_FAILED 256
230 #define AGENTX_NOT_OPEN 257
231 #define AGENTX_IDX_WRONT_TYPE 258
232 #define AGENTX_IDX_ALREAY_ALLOC 259
233 #define AGENTX_IDX_NONEAVAIL 260
234 #define AGENTX_IDX_NOTALLOC 261
235 #define AGENTX_UNSUPP_CONTEXT 262
236 #define AGENTX_DUP_REGISTR 263
237 #define AGENTX_UNKNOWN_REG 264
238 #define AGENTX_UNKNOWN_CAPS 265
241 static const value_string resp_errors[] = {
242 { AGENTX_NO_ERROR, "noError" },
243 { AGENTX_TOO_BIG, "tooBig" },
244 { AGENTX_NO_SUCH_NAME, "noSuchName" },
245 { AGENTX_BAD_VALUE, "badValue" },
246 { AGENTX_READ_ONLY, "readOnly" },
247 { AGENTX_GEN_ERROR, "genErr" },
248 { AGENTX_NO_ACCESS, "noAccess" },
249 { AGENTX_WRONG_TYPE, "wrongType" },
250 { AGENTX_WRONG_LEN, "wrongLength" },
251 { AGENTX_WRONG_ENCODE, "wrongEncoding" },
252 { AGENTX_WRONG_VALUE, "wrongValue" },
253 { AGENTX_NO_CREATION, "noCreation" },
254 { AGENTX_INCONSIST_VALUE, "inconsistentValue" },
255 { AGENTX_RES_UNAVAIL, "resourceUnavailable" },
256 { AGENTX_COMMIT_FAILED, "commitFailed" },
257 { AGENTX_UNDO_FAILED , "undoFailed" },
258 { AGENTX_AUTH_ERROR, "authorizationError" },
259 { AGENTX_NOTWRITABLE, "notWritable" },
260 { AGENTX_INCONSIS_NAME, "inconsistentName" },
261 { AGENTX_OPEN_FAILED, "openFailed" },
262 { AGENTX_NOT_OPEN, "notOpen" },
263 { AGENTX_IDX_WRONT_TYPE, "indexWrongType" },
264 { AGENTX_IDX_ALREAY_ALLOC, "indexAlreadyAllocated" },
265 { AGENTX_IDX_NONEAVAIL, "indexNoneAvailable" },
266 { AGENTX_IDX_NOTALLOC, "indexNotAllocated" },
267 { AGENTX_UNSUPP_CONTEXT, "unsupportedContext" },
268 { AGENTX_DUP_REGISTR, "duplicateRegistration" },
269 { AGENTX_UNKNOWN_REG, "unknownRegistration" },
270 { AGENTX_UNKNOWN_CAPS, "unknownAgentCaps" },
277 /* PDU Header flags */
279 #define INSTANCE_REGISTRATION 0
280 #define NEW_INDEX 0x1
281 #define ANY_INDEX 0x2
282 #define NON_DEFAULT_CONTEXT 0x4
283 #define NETWORK_BYTE_ORDER 0x8
285 #define PDU_HDR_LEN 20
286 #define PADDING(x) ((((x) + 3) >> 2) << 2)
288 #define NORLEL(flags,var,tvb,offset) \
289 var = (flags & NETWORK_BYTE_ORDER) ? \
290 tvb_get_ntohl(tvb, offset) : \
291 tvb_get_letohl(tvb, offset)
292 #define NORLES(flags,var,tvb,offset) \
293 var = (flags & NETWORK_BYTE_ORDER) ? \
294 tvb_get_ntohs(tvb, offset) : \
295 tvb_get_letohs(tvb, offset)
297 static int dissect_octet_string(tvbuff_t *tvb, proto_tree *tree, int offset, char flags)
299 guint32 n_oct, p_noct;
302 NORLEL(flags, n_oct, tvb, offset);
304 p_noct = PADDING(n_oct);
306 THROW(ReportedBoundsError);
307 tvb_get_nstringz(tvb, offset + 4, n_oct, context);
310 proto_tree_add_uint(tree,hf_ostring_len,tvb,offset,4,n_oct);
311 proto_tree_add_string(tree, hf_ostring, tvb, offset + 4, n_oct, context);
316 /* XXX - Is there a particular reason we're not using oid_encoded2string() here? */
317 static int convert_oid_to_str(guint32 *oid, int len, char* str, int slen, char prefix)
324 if(slen < len) return 0;
327 tlen += g_snprintf(str,slen,".1.3.6.1.%d",prefix);
330 for(i=0; i < len && tlen < slen; i++) {
331 tlen += g_snprintf(str+tlen,slen-tlen,".%d",oid[i]);
336 static int dissect_object_id(tvbuff_t *tvb, proto_tree *tree, int offset, char flags)
347 memset(oid, '\0', sizeof(oid));
348 memset(str_oid, '\0', sizeof(str_oid));
350 n_subid = tvb_get_guint8(tvb, offset);
351 prefix = tvb_get_guint8(tvb, offset + 1);
352 include = tvb_get_guint8(tvb,offset + 2);
353 tvb_get_guint8(tvb, offset + 3);
355 for(i=0; i<n_subid; i++) {
356 NORLEL(flags, oid[i], tvb, (offset+4) + (i*4));
359 if(!(slen = convert_oid_to_str(&oid[0], n_subid, &str_oid[0], 2048, prefix)))
364 item = proto_tree_add_text(tree,tvb,offset,n_subid + 4 ,
365 "Object Identifier: (%s) %s",(include) ? "Start" : "End" , str_oid);
366 subtree = proto_item_add_subtree(item, ett_obj_ident);
367 } else return offset;
369 proto_tree_add_uint(subtree, hf_oid_sub, tvb, offset, 1, n_subid);
370 proto_tree_add_uint(subtree, hf_oid_prefix, tvb, offset + 1, 1, prefix);
371 proto_tree_add_uint(subtree, hf_oid_include, tvb, offset + 2, 1, include);
372 proto_tree_add_string(subtree,hf_oid_str, tvb, offset + 4, slen, str_oid);
374 return 4 + (n_subid * 4);
377 static int dissect_search_range(tvbuff_t *tvb, proto_tree *tree, int offset, char flags)
380 offset += dissect_object_id(tvb, tree, offset, flags);
381 offset += dissect_object_id(tvb, tree, offset, flags);
386 static int dissect_val64(tvbuff_t *tvb, proto_tree *tree, int offset, char flags)
388 gboolean little_endian = !(flags & NETWORK_BYTE_ORDER);
390 proto_tree_add_item(tree, hf_val64, tvb, offset, 8, little_endian);
395 static int dissect_val32(tvbuff_t *tvb, proto_tree *tree, int offset, char flags)
397 gboolean little_endian = !(flags & NETWORK_BYTE_ORDER);
399 proto_tree_add_item(tree, hf_val32, tvb, offset, 4, little_endian);
404 static int dissect_varbind(tvbuff_t *tvb, proto_tree *tree, int offset, int len, char flags)
411 NORLES(flags, vtag, tvb, offset);
412 /* 2 reserved bytes after this */
415 item = proto_tree_add_text(tree,tvb, offset, len, "Value Representation");
416 subtree = proto_item_add_subtree(item, ett_valrep);
419 proto_tree_add_uint(subtree, hf_vtag, tvb, offset, 2, vtag);
420 tlen = dissect_object_id(tvb, subtree, offset + 4, flags);
425 tlen += dissect_object_id(tvb, subtree, offset + tlen + 4, flags);
431 tlen += dissect_octet_string(tvb, subtree,offset + tlen + 4,flags);
438 tlen += dissect_val32(tvb, subtree,offset + tlen + 4, flags);
442 tlen += dissect_val64(tvb, subtree,offset + tlen + 4, flags);
454 static void dissect_response_pdu(tvbuff_t *tvb, proto_tree *tree,int offset,int len, char flags)
458 gboolean little_endian = !(flags & NETWORK_BYTE_ORDER);
461 item = proto_tree_add_text(tree, tvb, offset, len, "Response-PDU");
462 subtree = proto_item_add_subtree(item, ett_response);
464 r_uptime = little_endian ? \
465 tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset);
467 proto_tree_add_uint_format(subtree, hf_resp_uptime, tvb, offset, 4, r_uptime,
468 "sysUptime: %s", time_msecs_to_str(r_uptime));
469 proto_tree_add_item(subtree, hf_resp_error, tvb, offset + 4, 2, little_endian);
470 proto_tree_add_item(subtree, hf_resp_index, tvb, offset + 6, 2, little_endian);
473 while(len > offset) {
474 offset += dissect_varbind(tvb, subtree, offset, len, flags);
478 static void dissect_getnext_pdu(tvbuff_t *tvb, proto_tree *tree,int offset,int len, char flags)
483 item = proto_tree_add_text(tree, tvb, offset, len, "GetNext-PDU");
484 subtree = proto_item_add_subtree(item, ett_getnext);
486 if(flags & NON_DEFAULT_CONTEXT) {
488 offset += dissect_octet_string(tvb, subtree, offset, flags);
491 while(len > offset) {
492 offset += dissect_search_range(tvb, subtree, offset, flags);
496 static void dissect_get_pdu(tvbuff_t *tvb, proto_tree *tree,int offset,int len, char flags)
501 item = proto_tree_add_text(tree, tvb, offset, len, "Get-PDU");
502 subtree = proto_item_add_subtree(item, ett_get);
504 if(flags & NON_DEFAULT_CONTEXT) {
506 offset += dissect_octet_string(tvb, subtree, offset, flags);
509 while(len >= offset) {
510 offset += dissect_search_range(tvb, subtree, offset, flags);
511 offset += 4; /* skip 0 end dword */
515 static void dissect_getbulk_pdu(tvbuff_t *tvb, proto_tree *tree,int offset,int len, char flags)
519 gboolean little_endian = !(flags & NETWORK_BYTE_ORDER);
521 item = proto_tree_add_text(tree, tvb, offset, len, "GetBulk-PDU");
522 subtree = proto_item_add_subtree(item, ett_getbulk);
524 if(flags & NON_DEFAULT_CONTEXT) {
526 offset += dissect_octet_string(tvb, subtree, offset, flags);
529 proto_tree_add_item(subtree, hf_gbulk_nrepeat, tvb, offset, 2, little_endian);
530 proto_tree_add_item(subtree, hf_gbulk_mrepeat, tvb, offset + 2, 2, little_endian);
533 while(len >= offset) {
534 offset += dissect_search_range(tvb, subtree, offset, flags);
538 static void dissect_open_pdu(tvbuff_t *tvb, proto_tree *tree,int offset,int len, char flags)
544 item = proto_tree_add_text(tree, tvb, offset, len, "Open-PDU");
545 subtree = proto_item_add_subtree(item, ett_open);
547 timeout = tvb_get_guint8(tvb, offset);
548 tvb_get_ntoh24(tvb, offset + 1);
550 proto_tree_add_uint(subtree, hf_open_timeout, tvb, offset, 1, timeout);
554 offset += dissect_object_id(tvb, subtree, offset, flags);
557 offset += dissect_octet_string(tvb, subtree, offset, flags);
560 static void dissect_close_pdu(tvbuff_t *tvb, proto_tree *tree,int offset,int len)
566 item = proto_tree_add_text(tree, tvb, offset, len, "Close-PDU");
567 subtree = proto_item_add_subtree(item, ett_close);
569 reason = tvb_get_guint8(tvb, offset);
570 tvb_get_ntoh24(tvb, offset + 1);
572 proto_tree_add_uint(subtree, hf_close_reason, tvb, offset, 1, reason);
577 static void dissect_register_pdu(tvbuff_t *tvb, proto_tree *tree,int offset,int len, char flags)
581 gboolean little_endian = !(flags & NETWORK_BYTE_ORDER);
583 item = proto_tree_add_text(tree, tvb, offset, len, "Register-PDU");
584 subtree = proto_item_add_subtree(item, ett_register);
586 if(flags & NON_DEFAULT_CONTEXT) {
588 offset += dissect_octet_string(tvb, subtree, offset, flags);
591 proto_tree_add_item(subtree, hf_reg_timeout, tvb, offset, 1, FALSE);
592 proto_tree_add_item(subtree, hf_reg_prio, tvb, offset+1, 1, FALSE);
593 proto_tree_add_item(subtree, hf_reg_rsid, tvb, offset+2, 1, FALSE);
598 offset += dissect_object_id(tvb, subtree, offset, flags);
601 /* Upper bound (opt) */
602 proto_tree_add_item(subtree, hf_reg_ubound, tvb, offset, 4, little_endian);
608 static void dissect_unregister_pdu(tvbuff_t *tvb, proto_tree *tree,int offset,int len, char flags)
612 gboolean little_endian = !(flags & NETWORK_BYTE_ORDER);
614 item = proto_tree_add_text(tree, tvb, offset, len, "Unregister-PDU");
615 subtree = proto_item_add_subtree(item, ett_unregister);
617 if(flags & NON_DEFAULT_CONTEXT) {
619 offset += dissect_octet_string(tvb, subtree, offset, flags);
622 proto_tree_add_item(subtree, hf_unreg_timeout, tvb, offset, 1, FALSE);
623 proto_tree_add_item(subtree, hf_unreg_prio, tvb, offset+1, 1, FALSE);
624 proto_tree_add_item(subtree, hf_unreg_rsid, tvb, offset+2, 1, FALSE);
628 offset += dissect_object_id(tvb, subtree, offset, flags);
631 /* Upper bound (opt) */
632 proto_tree_add_item(subtree, hf_unreg_ubound, tvb, offset, 4, little_endian);
637 static void dissect_testset_pdu(tvbuff_t *tvb, proto_tree *tree,int offset,int len, char flags)
642 item = proto_tree_add_text(tree, tvb, offset, len, "Testset-PDU");
643 subtree = proto_item_add_subtree(item, ett_testset);
645 if(flags & NON_DEFAULT_CONTEXT) {
647 offset += dissect_octet_string(tvb, subtree, offset, flags);
650 while(len > offset) {
651 offset += dissect_varbind(tvb, subtree, offset, len, flags);
655 static void dissect_notify_pdu(tvbuff_t *tvb, proto_tree *tree,int offset,int len, char flags)
660 item = proto_tree_add_text(tree, tvb, offset, len, "Notify-PDU");
661 subtree = proto_item_add_subtree(item, ett_notify);
663 if(flags & NON_DEFAULT_CONTEXT) {
665 offset += dissect_octet_string(tvb, subtree, offset, flags);
668 while(len > offset) {
669 offset += dissect_varbind(tvb, subtree, offset, len, flags);
673 static void dissect_ping_pdu(tvbuff_t *tvb, proto_tree *tree,int offset,int len, char flags)
678 item = proto_tree_add_text(tree, tvb, offset, len, "Ping-PDU");
679 subtree = proto_item_add_subtree(item, ett_ping);
681 if(flags & NON_DEFAULT_CONTEXT) {
683 offset += dissect_octet_string(tvb, subtree, offset, flags);
687 static void dissect_idx_alloc_pdu(tvbuff_t *tvb, proto_tree *tree,int offset,int len, char flags)
692 item = proto_tree_add_text(tree, tvb, offset, len, "IndexAllocate-PDU");
693 subtree = proto_item_add_subtree(item, ett_idxalloc);
695 if(flags & NON_DEFAULT_CONTEXT) {
697 offset += dissect_octet_string(tvb, subtree, offset, flags);
700 while(len > offset) {
701 offset += dissect_varbind(tvb, subtree, offset, len, flags);
706 static void dissect_idx_dealloc_pdu(tvbuff_t *tvb, proto_tree *tree,int offset,int len, char flags)
711 item = proto_tree_add_text(tree, tvb, offset, len, "IndexDeallocate-PDU");
712 subtree = proto_item_add_subtree(item, ett_idxdalloc);
714 if(flags & NON_DEFAULT_CONTEXT) {
716 offset += dissect_octet_string(tvb, subtree, offset, flags);
719 while(len > offset) {
720 offset += dissect_varbind(tvb, subtree, offset, len, flags);
724 static void dissect_add_caps_pdu(tvbuff_t *tvb, proto_tree *tree,int offset,int len, char flags)
729 item = proto_tree_add_text(tree, tvb, offset, len, "AddAgentCaps-PDU");
730 subtree = proto_item_add_subtree(item, ett_addcap);
732 if(flags & NON_DEFAULT_CONTEXT) {
734 offset += dissect_octet_string(tvb, subtree, offset, flags);
737 offset += dissect_object_id(tvb, subtree, offset, flags);
739 offset += dissect_octet_string(tvb, subtree, offset, flags);
742 static void dissect_rem_caps_pdu(tvbuff_t *tvb, proto_tree *tree,int offset,int len, char flags)
747 item = proto_tree_add_text(tree, tvb, offset, len, "RemoveAgentCaps-PDU");
748 subtree = proto_item_add_subtree(item, ett_remcap);
750 if(flags & NON_DEFAULT_CONTEXT) {
752 offset += dissect_octet_string(tvb, subtree, offset, flags);
755 offset += dissect_object_id(tvb, subtree, offset, flags);
759 static guint get_agentx_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
765 * Get the payload length.
767 flags = tvb_get_guint8(tvb, offset + 2);
768 NORLEL(flags, plen, tvb, offset + 16);
771 * Arbitrarily limit it to 2^24, so we don't have to worry about
778 * That length doesn't include the header; add that in.
783 static void dissect_agentx_pdu(tvbuff_t *tvb, packet_info *pinfo,
787 proto_tree* agentx_tree ,*pdu_hdr_tree;
788 proto_item* pdu_item , *t_item;
797 version = tvb_get_guint8(tvb,0); offset+=1;
798 type = tvb_get_guint8(tvb,1); offset+=1;
799 flags = tvb_get_guint8(tvb,2); offset+=1;
800 /* skip reserved byte */
803 NORLEL(flags, session_id, tvb, 4); offset+=4;
804 NORLEL(flags, trans_id, tvb, 8); offset+=4;
805 NORLEL(flags, packet_id, tvb, 12); offset+=4;
806 NORLEL(flags, payload_len, tvb, 16); offset+=4;
808 if (check_col(pinfo->cinfo, COL_PROTOCOL))
809 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AgentX");
811 if (check_col(pinfo->cinfo, COL_INFO))
812 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: sid=%d, tid=%d, packid=%d, plen=%d",
813 val_to_str(type,type_values,"unknown"),
814 session_id,trans_id,packet_id,payload_len);
820 /*t_item = proto_tree_add_item(tree, proto_agentx, tvb, 0, -1, FALSE);*/
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(type,type_values,"unknown"),
824 session_id,trans_id,packet_id,payload_len);
825 agentx_tree = proto_item_add_subtree(t_item, ett_agentx);
827 pdu_item = proto_tree_add_text(agentx_tree, tvb, 0, 5, "PDU Header: Type[%u], len=%d, sid=%d, tid=%d, packid=%d",
828 (char)type,payload_len,session_id,trans_id,packet_id);
830 pdu_hdr_tree = proto_item_add_subtree(pdu_item, ett_pdu_hdr);
832 proto_tree_add_uint(pdu_hdr_tree,hf_version,tvb,0,1,version);
833 proto_tree_add_uint(pdu_hdr_tree,hf_type,tvb,1,1,type);
834 proto_tree_add_uint(pdu_hdr_tree,hf_flags,tvb,2,1,flags);
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, pdu_hdr_tree, offset,payload_len,flags);
845 case AGENTX_CLOSE_PDU:
846 dissect_close_pdu(tvb, pdu_hdr_tree, offset,payload_len);
849 case AGENTX_REGISTER_PDU:
850 dissect_register_pdu(tvb, pdu_hdr_tree, offset,payload_len,flags);
853 case AGENTX_UNREGISTER_PDU:
854 dissect_unregister_pdu(tvb, pdu_hdr_tree, offset,payload_len,flags);
858 dissect_get_pdu(tvb, pdu_hdr_tree, offset,payload_len,flags);
861 case AGENTX_GETNEXT_PDU:
862 dissect_getnext_pdu(tvb, pdu_hdr_tree, offset,payload_len,flags);
865 case AGENTX_GETBULK_PDU:
866 dissect_getbulk_pdu(tvb, pdu_hdr_tree, offset,payload_len,flags);
869 case AGENTX_TESTSET_PDU:
870 dissect_testset_pdu(tvb, pdu_hdr_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, pdu_hdr_tree, offset,payload_len,flags);
883 case AGENTX_PING_PDU:
884 dissect_ping_pdu(tvb, pdu_hdr_tree, offset,payload_len,flags);
887 case AGENTX_INDEX_ALLOC_PDU:
888 dissect_idx_alloc_pdu(tvb, pdu_hdr_tree, offset,payload_len,flags);
891 case AGENTX_INDEX_DEALLOC_PDU:
892 dissect_idx_dealloc_pdu(tvb, pdu_hdr_tree, offset,payload_len,flags);
895 case AGENTX_ADD_AGENT_CAPS_PDU:
896 dissect_add_caps_pdu(tvb, pdu_hdr_tree, offset,payload_len,flags);
899 case AGENTX_REM_AGENT_CAPS_PDU:
900 dissect_rem_caps_pdu(tvb, pdu_hdr_tree, offset,payload_len,flags);
903 case AGENTX_RESPONSE_PDU:
904 dissect_response_pdu(tvb, pdu_hdr_tree, offset, payload_len, flags);
909 static void dissect_agentx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
911 tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 20, get_agentx_pdu_len,
916 proto_register_agentx(void)
918 static hf_register_info hf[] = {
921 { "Version ", "agentx.version", FT_UINT8, BASE_DEC, NULL, 0x0,
922 "header version", HFILL }},
925 { "Type ", "agentx.type", FT_UINT8, BASE_DEC, VALS(type_values), 0x0,
926 "header type", HFILL }},
929 { "Flags ", "agentx.flags", FT_UINT8, BASE_DEC, NULL, 0x0,
930 "header type", HFILL }},
933 { "sessionID ", "agentx.session_id", FT_UINT32, BASE_DEC, NULL, 0x0,
934 "Session ID", HFILL }},
937 { "TransactionID ", "agentx.transaction_id", FT_UINT32, BASE_DEC, NULL, 0x0,
938 "Transaction ID", HFILL }},
941 { "PacketID ", "agentx.packet_id", FT_UINT32, BASE_DEC, NULL, 0x0,
942 "Packet ID", HFILL }},
945 { "Payload length ", "agentx.payload_len", FT_UINT32, BASE_DEC, NULL, 0x0,
946 "Payload length", HFILL }},
949 { "Octet String", "agentx.ostring", FT_STRING, BASE_NONE, NULL, 0x0,
950 "Octet String", HFILL }},
953 { "OString len", "agentx.ostring_len", FT_UINT32, BASE_DEC, NULL, 0x0,
954 "Octet String Length", HFILL }},
957 { "Number subids ", "agentx.n_subid", FT_UINT8, BASE_DEC, NULL, 0x0,
958 "Number subids", HFILL }},
961 { "OID prefix ", "agentx.oid_prefix", FT_UINT8, BASE_DEC, NULL, 0x0,
962 "OID prefix", HFILL }},
965 { "OID include ", "agentx.oid_include", FT_UINT8, BASE_DEC, NULL, 0x0,
966 "OID include", HFILL }},
969 { "OID", "agentx.oid", FT_STRING, BASE_DEC, NULL, 0x0,
973 { "sysUpTime", "agentx.r.uptime", FT_UINT32, BASE_DEC, NULL, 0x0,
974 "sysUpTime", HFILL }},
977 { "Resp. error", "agentx.r.error", FT_UINT16, BASE_DEC, VALS(resp_errors), 0x0,
978 "response error", HFILL }},
981 { "Resp. index", "agentx.r.index", FT_UINT16, BASE_DEC, NULL, 0x0,
982 "response index", HFILL }},
985 { "Variable type", "agentx.v.tag", FT_UINT16, BASE_DEC, VALS(vtag_values), 0x0,
989 { "Value(32)", "agentx.v.val32", FT_UINT32, BASE_DEC, NULL, 0x0,
993 { "Value(64)", "agentx.v.val64", FT_UINT64, BASE_DEC, NULL, 0x0,
997 { "Timeout", "agentx.o.timeout", FT_UINT8, BASE_DEC, NULL, 0x0,
998 "open timeout", HFILL }},
1001 { "Reason", "agentx.c.reason", FT_UINT8, BASE_DEC, VALS(close_reasons), 0x0,
1002 "close reason", HFILL }},
1005 { "Timeout", "agentx.r.timeout", FT_UINT8, BASE_DEC, NULL, 0x0,
1006 "Register timeout", HFILL }},
1009 { "Priority", "agentx.r.priority", FT_UINT8, BASE_DEC, NULL, 0x0,
1010 "Register Priority", HFILL }},
1013 { "Range_subid", "agentx.r.range_subid", FT_UINT8, BASE_DEC, NULL, 0x0,
1014 "Register range_subid", HFILL }},
1017 { "Upper bound", "agentx.r.upper_bound", FT_UINT32, BASE_DEC, NULL, 0x0,
1018 "Register upper bound", HFILL }},
1020 { &hf_unreg_timeout,
1021 { "Timeout", "agentx.u.timeout", FT_UINT8, BASE_DEC, NULL, 0x0,
1022 "Unregister timeout", HFILL }},
1025 { "Priority", "agentx.u.priority", FT_UINT8, BASE_DEC, NULL, 0x0,
1026 "Unegister Priority", HFILL }},
1029 { "Range_subid", "agentx.u.range_subid", FT_UINT8, BASE_DEC, NULL, 0x0,
1030 "Unegister range_subid", HFILL }},
1033 { "Upper bound", "agentx.u.upper_bound", FT_UINT32, BASE_DEC, NULL, 0x0,
1034 "Register upper bound", HFILL }},
1036 { &hf_gbulk_nrepeat,
1037 { "Repeaters", "agentx.gb.nrepeat", FT_UINT16, BASE_DEC, NULL, 0x0,
1038 "getBulk Num. repeaters", HFILL }},
1040 { &hf_gbulk_mrepeat,
1041 { "Max Repetition", "agentx.gb.mrepeat", FT_UINT16, BASE_DEC, NULL, 0x0,
1042 "getBulk Max repetition", HFILL }},
1045 /* Add more fields here */
1049 static gint *ett[] = {
1076 module_t *agentx_module;
1078 proto_agentx = proto_register_protocol("AgentX",
1079 "AgentX", "agentx");
1081 proto_register_field_array(proto_agentx, hf, array_length(hf));
1082 proto_register_subtree_array(ett, array_length(ett));
1084 agentx_module = prefs_register_protocol(proto_agentx, proto_reg_handoff_agentx);
1086 prefs_register_uint_preference(agentx_module, "tcp.agentx_port",
1087 "AgentX listener TCP Port",
1088 "Set the TCP port for AgentX"
1089 "(if other than the default of 705)",
1090 10, &global_agentx_tcp_port);
1093 /* The registration hand-off routine */
1095 proto_reg_handoff_agentx(void)
1097 static gboolean agentx_prefs_initialized = FALSE;
1098 static dissector_handle_t agentx_handle;
1099 static guint agentx_tcp_port;
1101 if(!agentx_prefs_initialized) {
1102 agentx_handle = create_dissector_handle(dissect_agentx, proto_agentx);
1103 agentx_prefs_initialized = TRUE;
1106 dissector_delete("tcp.port", agentx_tcp_port, agentx_handle);
1109 agentx_tcp_port = global_agentx_tcp_port;
1110 dissector_add("tcp.port", agentx_tcp_port, agentx_handle);