2 * Routines for JDWP (Java Debug Wire Protocol) dissection
3 * Copyright 2020, Eugene Adell <eugene.adell@gmail.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include <epan/packet.h>
15 #include <epan/prefs.h>
16 #include <epan/expert.h>
17 #include <epan/to_str.h>
18 #include <epan/conversation.h>
19 #include <epan/wmem_scopes.h>
21 #include "packet-tcp.h"
23 void proto_register_jdwp(void);
24 void proto_reg_handoff_jdwp(void);
26 static dissector_handle_t jdwp_handle
;
28 /* IMPORTANT IMPLEMENTATION NOTES
30 * You need to be looking at:
32 * https://docs.oracle.com/javase/8/docs/technotes/guides/jpda/jdwp-spec.html
34 * Last update: up to Java 19
36 * https://docs.oracle.com/en/java/javase/19/docs/specs/jdwp/jdwp-protocol.html
40 #define JDWP_PORT 9009 /* Not IANA registered */
41 #define FRAME_HEADER_LEN 11
42 #define JDWP_MIN_LENGTH 11
43 #define JDWP_HANDSHAKE_LENGTH 14
44 #define JDWP_HANDSHAKE_MSG "JDWP-Handshake"
46 #define PACKET_TYPE_COMMAND 0
47 #define PACKET_TYPE_REPLY 128
49 #define COMMAND_SET_VIRTUALMACHINE 1
50 #define COMMAND_SET_REFERENCETYPE 2
51 #define COMMAND_SET_CLASSTYPE 3
52 #define COMMAND_SET_ARRAYTYPE 4
53 #define COMMAND_SET_INTERFACETYPE 5
54 #define COMMAND_SET_METHOD 6
55 #define COMMAND_SET_FIELD 8
56 #define COMMAND_SET_OBJECTREFERENCE 9
57 #define COMMAND_SET_STRINGREFERENCE 10
58 #define COMMAND_SET_THREADREFERENCE 11
59 #define COMMAND_SET_THREADGROUPREFERENCE 12
60 #define COMMAND_SET_ARRAYREFERENCE 13
61 #define COMMAND_SET_CLASSLOADERREFERENCE 14
62 #define COMMAND_SET_EVENTREQUEST 15
63 #define COMMAND_SET_STACKFRAME 16
64 #define COMMAND_SET_CLASSOBJECTREFERENCE 17
65 #define COMMAND_SET_MODULEREFERENCE 18
66 #define COMMAND_SET_EVENT 64
68 static int proto_jdwp
;
70 static int hf_jdwp_type
;
71 static int hf_jdwp_length
;
72 static int hf_jdwp_id
;
73 static int hf_jdwp_flags
;
74 static int hf_jdwp_commandset
;
75 static int hf_jdwp_commandset_virtualmachine
;
76 static int hf_jdwp_commandset_referencetype
;
77 static int hf_jdwp_commandset_classtype
;
78 static int hf_jdwp_commandset_arraytype
;
79 static int hf_jdwp_commandset_interfacetype
;
80 static int hf_jdwp_commandset_method
;
81 static int hf_jdwp_commandset_field
;
82 static int hf_jdwp_commandset_objectreference
;
83 static int hf_jdwp_commandset_stringreference
;
84 static int hf_jdwp_commandset_threadreference
;
85 static int hf_jdwp_commandset_threadgroupreference
;
86 static int hf_jdwp_commandset_arrayreference
;
87 static int hf_jdwp_commandset_classloaderreference
;
88 static int hf_jdwp_commandset_eventrequest
;
89 static int hf_jdwp_commandset_stackframe
;
90 static int hf_jdwp_commandset_classobjectreference
;
91 static int hf_jdwp_commandset_modulereference
;
92 static int hf_jdwp_commandset_event
;
93 static int hf_jdwp_errorcode
;
94 static int hf_jdwp_data
;
98 static expert_field ei_jdwp_hlen_invalid
;
99 static expert_field ei_jdwp_flags_invalid
;
101 // contains the command set names
102 static const value_string commandsetnames
[] = {
103 {1, "VirtualMachine"},
104 {2, "ReferenceType"},
107 {5, "InterfaceType"},
110 {9, "ObjectReference"},
111 {10, "StringReference"},
112 {11, "ThreadReference"},
113 {12, "ThreadGroupReference"},
114 {13, "ArrayReference"},
115 {14, "ClassLoaderReference"},
116 {15, "EventRequest"},
118 {17, "ClassObjectReference"},
119 {18, "ModuleReference"},
124 // contains the commands for the command set of type Virtual Machine
125 static const value_string commandset_virtualmachine
[] = {
127 {2, "ClassesBySignature"},
130 {5, "TopLevelThreadGroups"},
136 {11, "CreateString"},
137 {12, "Capabilities"},
139 {14, "DisposeObjects"},
141 {16, "ReleaseEvents"},
142 {17, "CapabilitiesNew"},
143 {18, "RedefineClasses"},
144 {19, "SetDefaultStratum"},
145 {20, "AllClassesWithGeneric"},
146 {21, "InstanceCounts"},
151 // contains the commands for the command set of type Reference
152 static const value_string commandset_referencetype
[] = {
164 {12, "SourceDebugExtension"},
165 {13, "SignatureWithGeneric"},
166 {14, "FieldsWithGeneric"},
167 {15, "MethodsWithGeneric"},
169 {17, "ClassFileVersion"},
170 {18, "ConstantPool"},
175 // contains the commands for the command set of type Class
176 static const value_string commandset_classtype
[] = {
184 // contains the commands for the command set of type Array
185 static const value_string commandset_arraytype
[] = {
190 // contains the commands for the command set of type Interface
191 static const value_string commandset_interfacetype
[] = {
196 // contains the commands for the command set of type Method
197 static const value_string commandset_method
[] = {
199 {2, "VariableTable"},
202 {5, "VariableTableWithGeneric"},
206 // contains the commands for the command set of type Field
207 static const value_string commandset_field
[] = {
211 // contains the commands for the command set of type Object Reference
212 static const value_string commandset_objectreference
[] = {
213 {1, "ReferenceType"},
218 {7, "DisableCollection"},
219 {8, "EnableCollection"},
221 {10, "ReferringObjects"},
225 // contains the commands for the command set of type String Reference
226 static const value_string commandset_stringreference
[] = {
231 // contains the commands for the command set of type Thread Reference
232 static const value_string commandset_threadreference
[] = {
240 {8, "OwnedMonitors"},
241 {9, "CurrentContentedMonitor"},
244 {12, "SuspendCount"},
245 {13, "OwnedMonitorsStackDepthInfo"},
246 {14, "ForceEarlyReturn"},
251 // contains the commands for the command set of type ThreadGroup Reference
252 static const value_string commandset_threadgroupreference
[] = {
259 // contains the commands for the command set of type Array Reference
260 static const value_string commandset_arrayreference
[] = {
267 // contains the commands for the command set of type ClassLoader Reference
268 static const value_string commandset_classloaderreference
[] = {
269 {1, "VisibleClasses"},
273 // contains the commands for the command set of type EventRequest
274 static const value_string commandset_eventrequest
[] = {
277 {3, "ClearAllBreakpoints"},
281 // contains the commands for the command set of type StackFrame
282 static const value_string commandset_stackframe
[] = {
290 // contains the commands for the command set of type ClassObject Reference
291 static const value_string commandset_classobjectreference
[] = {
292 {1, "ReflectedType"},
296 // contains the commands for the command set of type Module Reference
297 static const value_string commandset_modulereference
[] = {
303 // contains the commands for the command set of type Event
304 static const value_string commandset_event
[] = {
309 /* translates the error code to human readable value
310 * value 0 ("NONE") means SUCCESS, all other values mean FAILURE
312 static const value_string error_codes
[] = {
314 {10, "INVALID_THREAD"},
315 {11, "INVALID_THREAD_GROUP"},
316 {12, "INVALID_PRIORITY"},
317 {13, "THREAD_NOT_SUSPENDED"},
318 {14, "THREAD_SUSPENDED"},
319 {20, "INVALID_OBJECT"},
320 {21, "INVALID_CLASS"},
321 {22, "CLASS_NOT_PREPARED"},
322 {23, "INVALID_METHODID"},
323 {24, "INVALID_LOCATION"},
324 {25, "INVALID_FIELDID"},
325 {30, "INVALID_FRAMEID"},
326 {31, "NO_MORE_FRAMES"},
327 {32, "OPAQUE_FRAME"},
328 {33, "NOT_CURRENT_FRAME"},
329 {34, "TYPE_MISMATCH"},
330 {35, "INVALID_SLOT"},
333 {50, "INVALID_MONITOR"},
334 {51, "NOT_MONITOR_OWNER"},
336 {60, "INVALID_CLASS_FORMAT"},
337 {61, "CIRCULAR_CLASS_DEFINITION"},
338 {62, "FAILS_VERIFICATION"},
339 {63, "ADD_METHOD_NOT_IMPLEMENTED"},
340 {64, "SCHEMA_CHANGE_NOT_IMPLEMENTED"},
341 {65, "INVALID_TYPESTATE"},
342 {66, "HIERARCHY_CHANGE_NOT_IMPLEMENTED"},
343 {67, "DELETE_METHOD_NOT_IMPLEMENTED"},
344 {68, "UNSUPPORTED_VERSION"},
345 {69, "NAMES_DONT_MATCH"},
346 {70, "CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED"},
347 {71, "METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED"},
348 {99, "NOT_IMPLEMENTED"},
349 {100, "NULL_POINTER"},
350 {101, "ABSENT_INFORMATION"},
351 {102, "INVALID_EVENT_TYPE"},
352 {103, "ILLEGAL_ARGUMENT"},
353 {110, "OUT_OF_MEMORY"},
354 {111, "ACCESS_DENIED"},
357 {115, "UNATTACHED_THREAD"},
358 {500, "INVALID_TAG"},
359 {502, "ALREADY_INVOKING"},
360 {503, "INVALID_INDEX"},
361 {504, "INVALID_LENGTH"},
362 {506, "INVALID_STRING"},
363 {507, "INVALID_CLASS_LOADER"},
364 {508, "INVALID_ARRAY"},
365 {509, "TRANSPORT_LOAD"},
366 {510, "TRANSPORT_INIT"},
367 {511, "NATIVE_METHOD"},
368 {512, "INVALID_COUNT"},
372 /* determine PDU length of protocol JDWP */
374 get_jdwp_message_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
, void *data _U_
)
376 /* Handshake messages don't contain the length field and
377 * they all are strictly identical in length and content
379 if (tvb_reported_length(tvb
) == JDWP_HANDSHAKE_LENGTH
) {
380 if (tvb_strneql(tvb
, offset
, JDWP_HANDSHAKE_MSG
, JDWP_HANDSHAKE_LENGTH
) == 0) {
381 return JDWP_HANDSHAKE_LENGTH
;
385 /* All other packets are either a Command or a Reply, of different lengths
386 * and this length is indicated on the 4 first bytes
388 return (unsigned)tvb_get_ntohl(tvb
, offset
);
392 dissect_jdwp_message(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
396 /* packet type can take 3 values (handshake, command, reply) */
402 /* flag can take 2 values (0, 128) */
405 /* fields that need to be remembered */
406 uint32_t mem_commandset
= -1;
407 uint32_t mem_errorcode
= -1;
409 /* Check that there's enough data */
410 if (tvb_reported_length(tvb
) < JDWP_MIN_LENGTH
)
413 /* Set the Protocol Column */
414 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "JDWP");
415 col_clear(pinfo
->cinfo
, COL_INFO
);
417 proto_item
*ti
, *hlen_item
, *flags_item
;
418 proto_tree
*jdwp_tree
;
420 /* Clear out stuff in the info column */
421 col_clear(pinfo
->cinfo
,COL_INFO
);
423 ti
= proto_tree_add_item(tree
, proto_jdwp
, tvb
, 0, -1, ENC_NA
);
424 jdwp_tree
= proto_item_add_subtree(ti
, ett_jdwp
);
426 /* The two first packets are Handshake packets and
427 * their content is always "JDWP-Handshake"
428 * All other packets are either a Command or a Reply
431 if (tvb_reported_length(tvb
) == JDWP_HANDSHAKE_LENGTH
) {
432 if (tvb_strneql(tvb
, offset
, JDWP_HANDSHAKE_MSG
, JDWP_HANDSHAKE_LENGTH
) == 0) {
433 col_append_str(pinfo
->cinfo
, COL_INFO
, "JDWP Handshake");
438 if (packet_type
== 0) {
439 proto_tree_add_item(jdwp_tree
, hf_jdwp_type
, tvb
, offset
, 14, ENC_ASCII
);
440 return tvb_captured_length(tvb
);
445 hlen_item
= proto_tree_add_item_ret_uint(jdwp_tree
, hf_jdwp_length
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &hlen
);
450 proto_tree_add_item(jdwp_tree
, hf_jdwp_id
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
455 flags_item
= proto_tree_add_item_ret_uint(jdwp_tree
, hf_jdwp_flags
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &flags
);
461 case PACKET_TYPE_COMMAND
:
462 col_append_str(pinfo
->cinfo
, COL_INFO
, "Command");
463 proto_tree_add_item_ret_uint(jdwp_tree
, hf_jdwp_commandset
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &mem_commandset
);
466 switch (mem_commandset
) {
468 case COMMAND_SET_VIRTUALMACHINE
:
469 proto_tree_add_item(jdwp_tree
, hf_jdwp_commandset_virtualmachine
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
473 case COMMAND_SET_REFERENCETYPE
:
474 proto_tree_add_item(jdwp_tree
, hf_jdwp_commandset_referencetype
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
478 case COMMAND_SET_CLASSTYPE
:
479 proto_tree_add_item(jdwp_tree
, hf_jdwp_commandset_classtype
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
483 case COMMAND_SET_ARRAYTYPE
:
484 proto_tree_add_item(jdwp_tree
, hf_jdwp_commandset_arraytype
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
488 case COMMAND_SET_INTERFACETYPE
:
489 proto_tree_add_item(jdwp_tree
, hf_jdwp_commandset_interfacetype
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
493 case COMMAND_SET_METHOD
:
494 proto_tree_add_item(jdwp_tree
, hf_jdwp_commandset_method
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
498 case COMMAND_SET_FIELD
:
499 proto_tree_add_item(jdwp_tree
, hf_jdwp_commandset_field
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
503 case COMMAND_SET_OBJECTREFERENCE
:
504 proto_tree_add_item(jdwp_tree
, hf_jdwp_commandset_objectreference
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
508 case COMMAND_SET_STRINGREFERENCE
:
509 proto_tree_add_item(jdwp_tree
, hf_jdwp_commandset_stringreference
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
513 case COMMAND_SET_THREADREFERENCE
:
514 proto_tree_add_item(jdwp_tree
, hf_jdwp_commandset_threadreference
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
518 case COMMAND_SET_THREADGROUPREFERENCE
:
519 proto_tree_add_item(jdwp_tree
, hf_jdwp_commandset_threadgroupreference
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
523 case COMMAND_SET_ARRAYREFERENCE
:
524 proto_tree_add_item(jdwp_tree
, hf_jdwp_commandset_arrayreference
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
528 case COMMAND_SET_CLASSLOADERREFERENCE
:
529 proto_tree_add_item(jdwp_tree
, hf_jdwp_commandset_classloaderreference
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
533 case COMMAND_SET_EVENTREQUEST
:
534 proto_tree_add_item(jdwp_tree
, hf_jdwp_commandset_eventrequest
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
538 case COMMAND_SET_STACKFRAME
:
539 proto_tree_add_item(jdwp_tree
, hf_jdwp_commandset_stackframe
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
543 case COMMAND_SET_CLASSOBJECTREFERENCE
:
544 proto_tree_add_item(jdwp_tree
, hf_jdwp_commandset_classobjectreference
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
548 case COMMAND_SET_MODULEREFERENCE
:
549 proto_tree_add_item(jdwp_tree
, hf_jdwp_commandset_modulereference
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
553 case COMMAND_SET_EVENT
:
554 proto_tree_add_item(jdwp_tree
, hf_jdwp_commandset_event
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
559 proto_tree_add_item(jdwp_tree
, hf_jdwp_commandset_virtualmachine
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
565 /* command comes with data when the minimal length is 12 */
567 proto_tree_add_item(jdwp_tree
, hf_jdwp_data
, tvb
, offset
, hlen
- 11, ENC_NA
);
568 } else if (hlen
< 11) {
569 expert_add_info(pinfo
, hlen_item
, &ei_jdwp_hlen_invalid
);
574 case PACKET_TYPE_REPLY
:
575 proto_tree_add_item_ret_uint(jdwp_tree
, hf_jdwp_errorcode
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &mem_errorcode
);
578 if(mem_errorcode
== 0) {
579 col_append_str(pinfo
->cinfo
, COL_INFO
, "Reply (Success)");
581 col_append_str(pinfo
->cinfo
, COL_INFO
, "Reply (Failure)");
584 /* reply comes with data when the minimal length is 12 */
586 proto_tree_add_item(jdwp_tree
, hf_jdwp_data
, tvb
, offset
, hlen
- 11, ENC_NA
);
587 } else if (hlen
< 11) {
588 expert_add_info(pinfo
, hlen_item
, &ei_jdwp_hlen_invalid
);
594 expert_add_info(pinfo
, flags_item
, &ei_jdwp_flags_invalid
);
598 return tvb_captured_length(tvb
);
602 dissect_jdwp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
604 tcp_dissect_pdus(tvb
, pinfo
, tree
, true, FRAME_HEADER_LEN
,
605 get_jdwp_message_len
, dissect_jdwp_message
, data
);
606 return tvb_captured_length(tvb
);
610 proto_register_jdwp(void)
613 expert_module_t
* expert_jdwp
;
615 static hf_register_info hf
[] = {
617 { "Packet Type", "jdwp.type", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
,
621 { "Length", "jdwp.length", FT_UINT32
, BASE_DEC
, NULL
, 0x0, "Data Length",
625 { "id", "jdwp.id", FT_UINT32
, BASE_DEC
, NULL
, 0x0, "unique identifier",
629 { "flags", "jdwp.flags", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "tag packets as a command or reply",
632 { &hf_jdwp_commandset
,
633 { "command set", "jdwp.commandset", FT_UINT8
, BASE_DEC
, VALS(commandsetnames
), 0x0, NULL
,
636 { &hf_jdwp_commandset_virtualmachine
,
637 { "command", "jdwp.command", FT_UINT8
, BASE_DEC
, VALS(commandset_virtualmachine
), 0x0, NULL
,
640 { &hf_jdwp_commandset_referencetype
,
641 { "command", "jdwp.command", FT_UINT8
, BASE_DEC
, VALS(commandset_referencetype
), 0x0, NULL
,
644 { &hf_jdwp_commandset_classtype
,
645 { "command", "jdwp.command", FT_UINT8
, BASE_DEC
, VALS(commandset_classtype
), 0x0, NULL
,
648 { &hf_jdwp_commandset_arraytype
,
649 { "command", "jdwp.command", FT_UINT8
, BASE_DEC
, VALS(commandset_arraytype
), 0x0, NULL
,
652 { &hf_jdwp_commandset_interfacetype
,
653 { "command", "jdwp.command", FT_UINT8
, BASE_DEC
, VALS(commandset_interfacetype
), 0x0, NULL
,
656 { &hf_jdwp_commandset_method
,
657 { "command", "jdwp.command", FT_UINT8
, BASE_DEC
, VALS(commandset_method
), 0x0, NULL
,
660 { &hf_jdwp_commandset_field
,
661 { "command", "jdwp.command", FT_UINT8
, BASE_DEC
, VALS(commandset_field
), 0x0, NULL
,
664 { &hf_jdwp_commandset_objectreference
,
665 { "command", "jdwp.command", FT_UINT8
, BASE_DEC
, VALS(commandset_objectreference
), 0x0, NULL
,
668 { &hf_jdwp_commandset_stringreference
,
669 { "command", "jdwp.command", FT_UINT8
, BASE_DEC
, VALS(commandset_stringreference
), 0x0, NULL
,
672 { &hf_jdwp_commandset_threadreference
,
673 { "command", "jdwp.command", FT_UINT8
, BASE_DEC
, VALS(commandset_threadreference
), 0x0, NULL
,
676 { &hf_jdwp_commandset_threadgroupreference
,
677 { "command", "jdwp.command", FT_UINT8
, BASE_DEC
, VALS(commandset_threadgroupreference
), 0x0, NULL
,
680 { &hf_jdwp_commandset_arrayreference
,
681 { "command", "jdwp.command", FT_UINT8
, BASE_DEC
, VALS(commandset_arrayreference
), 0x0, NULL
,
684 { &hf_jdwp_commandset_classloaderreference
,
685 { "command", "jdwp.command", FT_UINT8
, BASE_DEC
, VALS(commandset_classloaderreference
), 0x0, NULL
,
688 { &hf_jdwp_commandset_eventrequest
,
689 { "command", "jdwp.command", FT_UINT8
, BASE_DEC
, VALS(commandset_eventrequest
), 0x0, NULL
,
692 { &hf_jdwp_commandset_stackframe
,
693 { "command", "jdwp.command", FT_UINT8
, BASE_DEC
, VALS(commandset_stackframe
), 0x0, NULL
,
696 { &hf_jdwp_commandset_classobjectreference
,
697 { "command", "jdwp.command", FT_UINT8
, BASE_DEC
, VALS(commandset_classobjectreference
), 0x0, NULL
,
700 { &hf_jdwp_commandset_modulereference
,
701 { "command", "jdwp.command", FT_UINT8
, BASE_DEC
, VALS(commandset_modulereference
), 0x0, NULL
,
704 { &hf_jdwp_commandset_event
,
705 { "command", "jdwp.command", FT_UINT8
, BASE_DEC
, VALS(commandset_event
), 0x0, NULL
,
708 { &hf_jdwp_errorcode
,
709 { "error code", "jdwp.errorcode", FT_UINT16
, BASE_DEC
, VALS(error_codes
), 0x0, NULL
,
713 { "data", "jdwp.data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, "details of the command or reply",
718 static ei_register_info ei
[] = {
719 { &ei_jdwp_hlen_invalid
, { "jdwp.hlen.invalid", PI_MALFORMED
, PI_ERROR
, "Decode aborted: invalid packet length", EXPFILL
}},
720 { &ei_jdwp_flags_invalid
, { "jdwp.flags.invalid", PI_MALFORMED
, PI_ERROR
, "Decode aborted: invalid flags value", EXPFILL
}}
723 static int *ett
[] = {
727 proto_jdwp
= proto_register_protocol("Java Debug Wire Protocol", "JDWP", "jdwp");
728 jdwp_handle
= register_dissector("jdwp", dissect_jdwp
, proto_jdwp
);
729 proto_register_field_array(proto_jdwp
, hf
, array_length(hf
));
730 proto_register_subtree_array(ett
, array_length(ett
));
731 expert_jdwp
= expert_register_protocol(proto_jdwp
);
732 expert_register_field_array(expert_jdwp
, ei
, array_length(ei
));
737 proto_reg_handoff_jdwp(void)
739 dissector_add_uint_with_preference("tcp.port", JDWP_PORT
, jdwp_handle
);
743 * Editor modelines - https://www.wireshark.org/tools/modelines.html
748 * indent-tabs-mode: nil
751 * vi: set shiftwidth=2 tabstop=8 expandtab:
752 * :indentSize=2:tabSize=8:noTabs=true: