Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-agentx.c
bloba3762d35c26768b9babe4f065e173bd9f337fee7
1 /* packet-agentx.c
2 * Routines for Agent Extensibility (AgentX) Protocol disassembly
3 * RFC 2257
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
14 #include "config.h"
16 #include <epan/packet.h>
17 #include <epan/to_str.h>
18 #include <epan/tfs.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;
35 static int hf_type;
36 static int hf_flags;
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;
55 static int hf_vtag;
56 static int hf_val32;
57 static int hf_val64;
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;
72 static int ett_flags;
73 static int ett_agentx;
74 static int ett_pdu_hdr;
75 static int ett_get;
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;
81 static int ett_open;
82 static int ett_close;
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;
91 static int ett_ping;
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" },
137 { 0, NULL }
139 static value_string_ext type_values_ext = VALUE_STRING_EXT_INIT(type_values);
141 /* VarBind types */
143 #define VB_INT 2
144 #define VB_OSTR 4
145 #define VB_NULL 5
146 #define VB_OID 6
147 #define VB_IPADDR 64
148 #define VB_COUNTER32 65
149 #define VB_GAUGE32 66
150 #define VB_TIMETICK 67
151 #define VB_OPAQUE 68
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" },
161 { VB_NULL, "Null" },
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" },
172 { 0, NULL }
174 static value_string_ext vtag_values_ext = VALUE_STRING_EXT_INIT(vtag_values);
176 /* Close reasons */
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" },
192 { 0, NULL }
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" },
258 { 0, NULL }
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)
287 static int
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);
302 return p_noct + 4;
306 /* XXX - Is there a particular reason we're not using oid_encoded2string() here? */
307 static int
308 convert_oid_to_str(uint32_t *oid, int len, char* str, int slen, char prefix)
310 int i, tlen = 0;
311 if(!oid) return 0;
312 if(!str) return 0;
313 if(!len) return 0;
314 if(!slen) return 0;
315 if(slen < len) return 0;
317 if(prefix) {
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]);
324 return tlen;
327 static int
328 dissect_object_id(tvbuff_t *tvb, proto_tree *tree, int offset, uint8_t flags, enum OID_USAGE oid_usage)
330 uint8_t n_subid;
331 uint8_t prefix;
332 uint8_t include;
333 proto_tree* subtree;
334 uint32_t oid[2048];
335 char str_oid[2048];
336 int i;
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)");
353 if(tree) {
354 const char *range = "";
355 const char *inclusion = (include) ? " (Inclusive)" : " (Exclusive)";
356 switch (oid_usage) {
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);
363 } else
364 return offset;
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);
374 static int
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);
384 static int
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);
391 return 8;
394 static int
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);
401 return 4;
404 static int
405 dissect_varbind(tvbuff_t *tvb, proto_tree *tree, int offset, int len, uint8_t flags)
407 uint16_t vtag;
408 int tlen;
409 proto_tree* subtree;
411 NORLES(flags, vtag, tvb, offset);
412 /* 2 reserved bytes after this */
414 if(tree) {
415 subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_valrep, NULL, "Value Representation");
416 } else return len;
418 proto_tree_add_uint(subtree, hf_vtag, tvb, offset, 2, vtag);
419 tlen = dissect_object_id(tvb, subtree, offset + 4, flags, OID_EXACT);
421 switch(vtag)
423 case VB_OID:
424 tlen += dissect_object_id(tvb, subtree, offset + tlen + 4, flags, OID_EXACT);
425 break;
427 case VB_OPAQUE:
428 case VB_OSTR:
429 case VB_IPADDR:
430 tlen += dissect_octet_string(tvb, subtree, offset + tlen + 4, flags);
431 break;
433 case VB_TIMETICK:
434 case VB_COUNTER32:
435 case VB_INT:
436 case VB_GAUGE32:
437 tlen += dissect_val32(tvb, subtree, offset + tlen + 4, flags);
438 break;
440 case VB_COUNTER64:
441 tlen += dissect_val64(tvb, subtree, offset + tlen + 4, flags);
442 break;
444 case VB_NULL:
445 case VB_NOSUCHOBJ:
446 case VB_NOSUCHINST:
447 case VB_ENDOFMIB:
448 break;
450 return tlen + 4;
453 static void
454 dissect_response_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int len, uint8_t flags)
456 proto_tree* subtree;
457 unsigned encoding = (flags & NETWORK_BYTE_ORDER) ? ENC_BIG_ENDIAN : ENC_LITTLE_ENDIAN;
458 uint32_t r_uptime;
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);
467 offset += 8;
469 len += PDU_HDR_LEN;
470 while(len > offset) {
471 offset += dissect_varbind(tvb, subtree, offset, len, flags);
475 static void
476 dissect_getnext_pdu(tvbuff_t *tvb, proto_tree *tree, int offset, int len, uint8_t flags)
478 proto_tree* subtree;
480 subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_getnext, NULL, "GetNext-PDU");
482 if(flags & NON_DEFAULT_CONTEXT) {
483 /* show context */
484 offset += dissect_octet_string(tvb, subtree, offset, flags);
487 len += PDU_HDR_LEN;
488 while(len > offset) {
489 offset += dissect_search_range(tvb, subtree, offset, flags, 0);
493 static void
494 dissect_get_pdu(tvbuff_t *tvb, proto_tree *tree, int offset, int len, uint8_t flags)
496 proto_tree* subtree;
498 subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_get, NULL, "Get-PDU");
500 if(flags & NON_DEFAULT_CONTEXT) {
501 /* show context */
502 offset += dissect_octet_string(tvb, subtree, offset, flags);
505 len += PDU_HDR_LEN;
506 while(len > offset) {
507 offset += dissect_search_range(tvb, subtree, offset, flags, AGENTX_GET_PDU);
511 static void
512 dissect_getbulk_pdu(tvbuff_t *tvb, proto_tree *tree, int offset, int len, uint8_t flags)
514 proto_tree* subtree;
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) {
520 /* show 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);
526 offset+=4;
528 while(len >= offset) {
529 offset += dissect_search_range(tvb, subtree, offset, flags, 0);
533 static int
534 dissect_open_pdu(tvbuff_t *tvb, proto_tree *tree, int offset, int len, uint8_t flags)
536 proto_tree* subtree;
537 uint8_t timeout;
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);
545 offset+=4;
547 /* Search Range */
548 offset += dissect_object_id(tvb, subtree, offset, flags, OID_EXACT);
550 /* Octet string */
551 offset += dissect_octet_string(tvb, subtree, offset, flags);
552 return offset;
555 static int
556 dissect_close_pdu(tvbuff_t *tvb, proto_tree *tree, int offset, int len)
558 proto_tree* subtree;
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);
564 offset+=4;
565 return offset;
569 static int
570 dissect_register_pdu(tvbuff_t *tvb, proto_tree *tree, int offset, int len, uint8_t flags)
572 proto_tree* subtree;
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) {
578 /* show 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);
585 offset+=4;
587 /* Region */
589 offset += dissect_object_id(tvb, subtree, offset, flags, OID_EXACT);
591 len += PDU_HDR_LEN;
592 if(len > offset) {
593 /* Upper bound (opt) */
594 proto_tree_add_item(subtree, hf_reg_ubound, tvb, offset, 4, encoding);
595 offset += 4;
597 return offset;
601 static int
602 dissect_unregister_pdu(tvbuff_t *tvb, proto_tree *tree, int offset, int len, uint8_t flags)
604 proto_tree* subtree;
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) {
610 /* show 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);
617 offset+=4;
619 /* Region */
620 offset += dissect_object_id(tvb, subtree, offset, flags, OID_EXACT);
622 len += PDU_HDR_LEN;
623 if(len > offset) {
624 /* Upper bound (opt) */
625 proto_tree_add_item(subtree, hf_unreg_ubound, tvb, offset, 4, encoding);
626 offset += 4;
629 return offset;
632 static void
633 dissect_testset_pdu(tvbuff_t *tvb, proto_tree *tree, int offset, int len, uint8_t flags)
635 proto_tree* subtree;
637 subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_testset, NULL, "Testset-PDU");
639 if(flags & NON_DEFAULT_CONTEXT) {
640 /* show context */
641 offset += dissect_octet_string(tvb, subtree, offset, flags);
644 while(len > offset) {
645 offset += dissect_varbind(tvb, subtree, offset, len, flags);
649 static void
650 dissect_notify_pdu(tvbuff_t *tvb, proto_tree *tree, int offset, int len, uint8_t flags)
652 proto_tree* subtree;
654 subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_notify, NULL, "Notify-PDU");
656 if(flags & NON_DEFAULT_CONTEXT) {
657 /* show context */
658 offset += dissect_octet_string(tvb, subtree, offset, flags);
661 while(len > offset) {
662 offset += dissect_varbind(tvb, subtree, offset, len, flags);
666 static int
667 dissect_ping_pdu(tvbuff_t *tvb, proto_tree *tree, int offset, int len, uint8_t flags)
669 proto_tree* subtree;
671 subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_ping, NULL, "Ping-PDU");
673 if(flags & NON_DEFAULT_CONTEXT) {
674 /* show context */
675 offset += dissect_octet_string(tvb, subtree, offset, flags);
677 return offset;
680 static void
681 dissect_idx_alloc_pdu(tvbuff_t *tvb, proto_tree *tree, int offset, int len, uint8_t flags)
683 proto_tree* subtree;
685 subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_idxalloc, NULL, "IndexAllocate-PDU");
687 if(flags & NON_DEFAULT_CONTEXT) {
688 /* show context */
689 offset += dissect_octet_string(tvb, subtree, offset, flags);
692 while(len > offset) {
693 offset += dissect_varbind(tvb, subtree, offset, len, flags);
698 static void
699 dissect_idx_dealloc_pdu(tvbuff_t *tvb, proto_tree *tree, int offset, int len, uint8_t flags)
701 proto_tree* subtree;
703 subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_idxdalloc, NULL, "IndexDeallocate-PDU");
705 if(flags & NON_DEFAULT_CONTEXT) {
706 /* show context */
707 offset += dissect_octet_string(tvb, subtree, offset, flags);
710 while(len > offset) {
711 offset += dissect_varbind(tvb, subtree, offset, len, flags);
715 static int
716 dissect_add_caps_pdu(tvbuff_t *tvb, proto_tree *tree, int offset, int len, uint8_t flags)
718 proto_tree* subtree;
720 subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_addcap, NULL, "AddAgentCaps-PDU");
722 if(flags & NON_DEFAULT_CONTEXT) {
723 /* show 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);
731 return offset;
734 static int
735 dissect_rem_caps_pdu(tvbuff_t *tvb, proto_tree *tree, int offset, int len, uint8_t flags)
737 proto_tree* subtree;
739 subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_remcap, NULL, "RemoveAgentCaps-PDU");
741 if(flags & NON_DEFAULT_CONTEXT) {
742 /* show context */
743 offset += dissect_octet_string(tvb, subtree, offset, flags);
746 offset += dissect_object_id(tvb, subtree, offset, flags, OID_EXACT);
748 return offset;
752 static unsigned
753 get_agentx_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
755 uint8_t flags;
756 uint32_t plen;
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
766 * overflow.
768 if (plen > 0xFFFFFF)
769 plen = 0xFFFFFF;
772 * That length doesn't include the header; add that in.
774 return plen + 20;
777 static int
778 dissect_agentx_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
780 int offset = 0;
781 proto_tree* agentx_tree, *pdu_hdr_tree;
782 proto_item *t_item;
783 uint8_t version;
784 uint8_t type;
785 uint8_t flags;
786 uint32_t session_id;
787 uint32_t trans_id;
788 uint32_t packet_id;
789 uint32_t payload_len;
790 static int * const pdu_flags[] = {
791 &hf_flags_register,
792 &hf_flags_newindex,
793 &hf_flags_anyindex,
794 &hf_flags_context,
795 &hf_flags_byteorder,
796 NULL
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 */
803 offset+=1;
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);
817 if(!tree)
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);
840 switch(type) {
841 case AGENTX_OPEN_PDU:
842 dissect_open_pdu(tvb, agentx_tree, offset, payload_len, flags);
843 break;
845 case AGENTX_CLOSE_PDU:
846 dissect_close_pdu(tvb, agentx_tree, offset, payload_len);
847 break;
849 case AGENTX_REGISTER_PDU:
850 dissect_register_pdu(tvb, agentx_tree, offset, payload_len, flags);
851 break;
853 case AGENTX_UNREGISTER_PDU:
854 dissect_unregister_pdu(tvb, agentx_tree, offset, payload_len, flags);
855 break;
857 case AGENTX_GET_PDU:
858 dissect_get_pdu(tvb, agentx_tree, offset, payload_len, flags);
859 break;
861 case AGENTX_GETNEXT_PDU:
862 dissect_getnext_pdu(tvb, agentx_tree, offset, payload_len, flags);
863 break;
865 case AGENTX_GETBULK_PDU:
866 dissect_getbulk_pdu(tvb, agentx_tree, offset, payload_len, flags);
867 break;
869 case AGENTX_TESTSET_PDU:
870 dissect_testset_pdu(tvb, agentx_tree, offset, payload_len, flags);
871 break;
873 case AGENTX_COMMITSET_PDU:
874 case AGENTX_UNDOSET_PDU:
875 case AGENTX_CLEANUPSET_PDU:
876 /* there is no parameters */
877 break;
879 case AGENTX_NOTIFY_PDU:
880 dissect_notify_pdu(tvb, agentx_tree, offset, payload_len, flags);
881 break;
883 case AGENTX_PING_PDU:
884 dissect_ping_pdu(tvb, agentx_tree, offset, payload_len, flags);
885 break;
887 case AGENTX_INDEX_ALLOC_PDU:
888 dissect_idx_alloc_pdu(tvb, agentx_tree, offset, payload_len, flags);
889 break;
891 case AGENTX_INDEX_DEALLOC_PDU:
892 dissect_idx_dealloc_pdu(tvb, agentx_tree, offset, payload_len, flags);
893 break;
895 case AGENTX_ADD_AGENT_CAPS_PDU:
896 dissect_add_caps_pdu(tvb, agentx_tree, offset, payload_len, flags);
897 break;
899 case AGENTX_REM_AGENT_CAPS_PDU:
900 dissect_rem_caps_pdu(tvb, agentx_tree, offset, payload_len, flags);
901 break;
903 case AGENTX_RESPONSE_PDU:
904 dissect_response_pdu(tvb, pinfo, agentx_tree, offset, payload_len, flags);
905 break;
908 return tvb_captured_length(tvb);
911 static int
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" };
922 void
923 proto_register_agentx(void)
925 static hf_register_info hf[] = {
927 { &hf_version,
928 { "Version", "agentx.version", FT_UINT8, BASE_DEC, NULL, 0x0,
929 "header version", HFILL }},
931 { &hf_type,
932 { "Type", "agentx.type", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &type_values_ext, 0x0,
933 "header type", HFILL }},
935 { &hf_flags,
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 }},
951 { &hf_flags_context,
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 }},
959 { &hf_session_id,
960 { "sessionID", "agentx.session_id", FT_UINT32, BASE_DEC, NULL, 0x0,
961 "Session ID", HFILL }},
963 { &hf_trans_id,
964 { "TransactionID", "agentx.transaction_id", FT_UINT32, BASE_DEC, NULL, 0x0,
965 "Transaction ID", HFILL }},
967 { &hf_packet_id,
968 { "PacketID", "agentx.packet_id", FT_UINT32, BASE_DEC, NULL, 0x0,
969 "Packet ID", HFILL }},
971 { &hf_payload_len,
972 { "Payload length", "agentx.payload_len", FT_UINT32, BASE_DEC, NULL, 0x0,
973 NULL, HFILL }},
975 { &hf_ostring,
976 { "Octet String", "agentx.ostring", FT_STRING, BASE_NONE, NULL, 0x0,
977 NULL, HFILL }},
979 { &hf_ostring_len,
980 { "OString len", "agentx.ostring_len", FT_UINT32, BASE_DEC, NULL, 0x0,
981 "Octet String Length", HFILL }},
983 { &hf_oid_sub,
984 { "Number subids", "agentx.n_subid", FT_UINT8, BASE_DEC, NULL, 0x0,
985 NULL, HFILL }},
987 { &hf_oid_prefix,
988 { "OID prefix", "agentx.oid_prefix", FT_UINT8, BASE_DEC, NULL, 0x0,
989 NULL, HFILL }},
991 { &hf_oid_include,
992 { "OID include", "agentx.oid_include", FT_BOOLEAN, 8, TFS(&tfs_yes_no),
993 OID_IS_INCLUSIVE, NULL, HFILL }},
995 { &hf_oid_str,
996 { "OID", "agentx.oid", FT_STRING, BASE_NONE, NULL, 0x0,
997 NULL, HFILL }},
999 { &hf_resp_uptime,
1000 { "sysUpTime", "agentx.r.uptime", FT_UINT32, BASE_DEC, NULL, 0x0,
1001 NULL, HFILL }},
1003 { &hf_resp_error,
1004 { "Resp. error", "agentx.r.error", FT_UINT16, BASE_DEC | BASE_EXT_STRING, &resp_errors_ext, 0x0,
1005 "response error", HFILL }},
1007 { &hf_resp_index,
1008 { "Resp. index", "agentx.r.index", FT_UINT16, BASE_DEC, NULL, 0x0,
1009 "response index", HFILL }},
1011 { &hf_vtag,
1012 { "Variable type", "agentx.v.tag", FT_UINT16, BASE_DEC | BASE_EXT_STRING, &vtag_values_ext, 0x0,
1013 "vtag", HFILL }},
1015 { &hf_val32,
1016 { "Value(32)", "agentx.v.val32", FT_UINT32, BASE_DEC, NULL, 0x0,
1017 "val32", HFILL }},
1019 { &hf_val64,
1020 { "Value(64)", "agentx.v.val64", FT_UINT64, BASE_DEC, NULL, 0x0,
1021 "val64", HFILL }},
1023 { &hf_open_timeout,
1024 { "Timeout", "agentx.o.timeout", FT_UINT8, BASE_DEC, NULL, 0x0,
1025 "open timeout", HFILL }},
1027 { &hf_close_reason,
1028 { "Reason", "agentx.c.reason", FT_UINT8, BASE_DEC, VALS(close_reasons), 0x0,
1029 "close reason", HFILL }},
1031 { &hf_reg_timeout,
1032 { "Timeout", "agentx.r.timeout", FT_UINT8, BASE_DEC, NULL, 0x0,
1033 "Register timeout", HFILL }},
1035 { &hf_reg_prio,
1036 { "Priority", "agentx.r.priority", FT_UINT8, BASE_DEC, NULL, 0x0,
1037 "Register Priority", HFILL }},
1039 { &hf_reg_rsid,
1040 { "Range_subid", "agentx.r.range_subid", FT_UINT8, BASE_DEC, NULL, 0x0,
1041 "Register range_subid", HFILL }},
1043 { &hf_reg_ubound,
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 }},
1051 { &hf_unreg_prio,
1052 { "Priority", "agentx.u.priority", FT_UINT8, BASE_DEC, NULL, 0x0,
1053 "Unregister Priority", HFILL }},
1055 { &hf_unreg_rsid,
1056 { "Range_subid", "agentx.u.range_subid", FT_UINT8, BASE_DEC, NULL, 0x0,
1057 "Unregister range_subid", HFILL }},
1059 { &hf_unreg_ubound,
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[] = {
1077 &ett_agentx,
1078 &ett_pdu_hdr,
1079 &ett_get,
1080 &ett_getnext,
1081 &ett_search_range,
1082 &ett_obj_ident,
1083 &ett_response,
1084 &ett_valrep,
1085 &ett_open,
1086 &ett_close,
1087 &ett_register,
1088 &ett_unregister,
1089 &ett_getbulk,
1090 &ett_testset,
1091 &ett_commitset,
1092 &ett_undoset,
1093 &ett_cleanupset,
1094 &ett_notify,
1095 &ett_ping,
1096 &ett_idxalloc,
1097 &ett_idxdalloc,
1098 &ett_addcap,
1099 &ett_remcap,
1100 &ett_flags,
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 */
1112 void
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
1121 * Local variables:
1122 * c-basic-offset: 8
1123 * tab-width: 8
1124 * indent-tabs-mode: t
1125 * End:
1127 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1128 * :indentSize=8:tabSize=8:noTabs=false: