2 * Routines for Mongo Wire Protocol dissection
3 * Copyright 2010, Alexis La Goutte <alexis.lagoutte at gmail dot com>
4 * BSON dissection added 2011, Thomas Buchanan <tom at thomasbuchanan dot com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
14 * See Mongo Wire Protocol Specification
15 * http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol
16 * See also BSON Specification
17 * http://bsonspec.org/#/specification
22 #include <epan/packet.h>
24 #include <wsutil/array.h>
25 #include <epan/expert.h>
26 #include <epan/proto_data.h>
27 #include <wsutil/crc32.h> // CRC32C_PRELOAD
28 #include <epan/crc32-tvb.h> // crc32c_tvb_offset_calculate
29 #include "packet-tcp.h"
34 void proto_register_mongo(void);
35 void proto_reg_handoff_mongo(void);
37 static dissector_handle_t mongo_handle
;
38 static dissector_handle_t mongo_heur_handle
;
40 /* Forward declaration */
42 dissect_opcode_types(tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned offset
, proto_tree
*mongo_tree
, unsigned opcode
, unsigned *effective_opcode
);
44 /* This is not IANA assigned nor registered */
45 #define TCP_PORT_MONGO 27017
47 /* the code can reasonably attempt to decompress buffer up to 20MB */
48 #define MAX_UNCOMPRESSED_SIZE (20 * 1024 * 1024)
50 /* All opcodes other than OP_COMPRESSED and OP_MSG were removed
51 * in MongoDB 5.1 (December 2021)
54 #define OP_MESSAGE 1000
55 #define OP_UPDATE 2001
56 #define OP_INSERT 2002
57 #define OP_RESERVED 2003
59 #define OP_GET_MORE 2005
60 #define OP_DELETE 2006
61 #define OP_KILL_CURSORS 2007
62 #define OP_COMMAND 2010
63 #define OP_COMMANDREPLY 2011
64 #define OP_COMPRESSED 2012
67 /**************************************************************************/
69 /**************************************************************************/
70 static const value_string opcode_vals
[] = {
71 { OP_REPLY
, "Reply" },
72 { OP_MESSAGE
, "Message" },
73 { OP_UPDATE
, "Update document" },
74 { OP_INSERT
, "Insert document" },
75 { OP_RESERVED
,"Reserved" },
76 { OP_QUERY
, "Query" },
77 { OP_GET_MORE
, "Get More" },
78 { OP_DELETE
, "Delete document" },
79 { OP_KILL_CURSORS
, "Kill Cursors" },
80 { OP_COMMAND
, "Command Request" },
81 { OP_COMMANDREPLY
, "Command Reply" },
82 { OP_COMPRESSED
, "Compressed Data" },
83 { OP_MSG
, "Extensible Message Format" },
88 #define KIND_DOCUMENT_SEQUENCE 1
90 /**************************************************************************/
92 /**************************************************************************/
93 static const value_string section_kind_vals
[] = {
94 { KIND_BODY
, "Body" },
95 { KIND_DOCUMENT_SEQUENCE
, "Document Sequence" },
99 /**************************************************************************/
100 /* Compression Engines */
101 /**************************************************************************/
102 #define MONGO_COMPRESSOR_NOOP 0
103 #define MONGO_COMPRESSOR_SNAPPY 1
104 #define MONGO_COMPRESSOR_ZLIB 2
105 #define MONGO_COMPRESSOR_ZSTD 3
107 static const value_string compressor_vals
[] = {
108 { MONGO_COMPRESSOR_NOOP
, "Noop (Uncompressed)" },
109 { MONGO_COMPRESSOR_SNAPPY
, "Snappy" },
110 { MONGO_COMPRESSOR_ZLIB
, "Zlib" },
111 { MONGO_COMPRESSOR_ZSTD
, "Zstd" },
115 /* BSON Element types */
116 /* See http://bsonspec.org/#/specification for detail */
117 #define BSON_ELEMENT_TYPE_DOUBLE 1
118 #define BSON_ELEMENT_TYPE_STRING 2
119 #define BSON_ELEMENT_TYPE_DOC 3
120 #define BSON_ELEMENT_TYPE_ARRAY 4
121 #define BSON_ELEMENT_TYPE_BINARY 5
122 #define BSON_ELEMENT_TYPE_UNDEF 6 /* Deprecated */
123 #define BSON_ELEMENT_TYPE_OBJ_ID 7
124 #define BSON_ELEMENT_TYPE_BOOL 8
125 #define BSON_ELEMENT_TYPE_DATETIME 9
126 #define BSON_ELEMENT_TYPE_NULL 10
127 #define BSON_ELEMENT_TYPE_REGEX 11
128 #define BSON_ELEMENT_TYPE_DB_PTR 12 /* Deprecated */
129 #define BSON_ELEMENT_TYPE_JS_CODE 13
130 #define BSON_ELEMENT_TYPE_SYMBOL 14
131 #define BSON_ELEMENT_TYPE_JS_CODE_SCOPE 15
132 #define BSON_ELEMENT_TYPE_INT32 16 /* 0x10 */
133 #define BSON_ELEMENT_TYPE_TIMESTAMP 17 /* 0x11 */
134 #define BSON_ELEMENT_TYPE_INT64 18 /* 0x12 */
135 #define BSON_ELEMENT_TYPE_DECIMAL128 19 /* 0x13 */
136 #define BSON_ELEMENT_TYPE_MIN_KEY 255 /* 0xFF */
137 #define BSON_ELEMENT_TYPE_MAX_KEY 127 /* 0x7F */
139 static const value_string element_type_vals
[] = {
140 { BSON_ELEMENT_TYPE_DOUBLE
, "Double" },
141 { BSON_ELEMENT_TYPE_STRING
, "String" },
142 { BSON_ELEMENT_TYPE_DOC
, "Document" },
143 { BSON_ELEMENT_TYPE_ARRAY
, "Array" },
144 { BSON_ELEMENT_TYPE_BINARY
, "Binary" },
145 { BSON_ELEMENT_TYPE_UNDEF
, "Undefined" },
146 { BSON_ELEMENT_TYPE_OBJ_ID
, "Object ID" },
147 { BSON_ELEMENT_TYPE_BOOL
, "Boolean" },
148 { BSON_ELEMENT_TYPE_DATETIME
, "Datetime" },
149 { BSON_ELEMENT_TYPE_NULL
, "NULL" },
150 { BSON_ELEMENT_TYPE_REGEX
, "Regular Expression" },
151 { BSON_ELEMENT_TYPE_DB_PTR
, "DBPointer" },
152 { BSON_ELEMENT_TYPE_JS_CODE
, "JavaScript Code" },
153 { BSON_ELEMENT_TYPE_SYMBOL
, "Symbol" },
154 { BSON_ELEMENT_TYPE_JS_CODE_SCOPE
, "JavaScript Code w/Scope" },
155 { BSON_ELEMENT_TYPE_INT32
, "Int32" },
156 { BSON_ELEMENT_TYPE_TIMESTAMP
, "Timestamp" },
157 { BSON_ELEMENT_TYPE_INT64
, "Int64" },
158 { BSON_ELEMENT_TYPE_DECIMAL128
, "128-bit decimal floating point" },
159 { BSON_ELEMENT_TYPE_MIN_KEY
, "Min Key" },
160 { BSON_ELEMENT_TYPE_MAX_KEY
, "Max Key" },
164 /* BSON Element Binary subtypes */
165 #define BSON_ELEMENT_BINARY_TYPE_GENERIC 0
166 #define BSON_ELEMENT_BINARY_TYPE_FUNCTION 1
167 #define BSON_ELEMENT_BINARY_TYPE_BINARY 2 /* OLD */
168 #define BSON_ELEMENT_BINARY_TYPE_UUID 3
169 #define BSON_ELEMENT_BINARY_TYPE_MD5 4
170 #define BSON_ELEMENT_BINARY_TYPE_USER 128 /* 0x80 */
173 static const value_string binary_type_vals
[] = {
174 { BSON_ELEMENT_BINARY_TYPE_GENERIC
, "Generic" },
175 { BSON_ELEMENT_BINARY_TYPE_FUNCTION
, "Function" },
176 { BSON_ELEMENT_BINARY_TYPE_BINARY
, "Binary" },
177 { BSON_ELEMENT_BINARY_TYPE_UUID
, "UUID" },
178 { BSON_ELEMENT_BINARY_TYPE_MD5
, "MD5" },
179 { BSON_ELEMENT_BINARY_TYPE_USER
, "User" },
184 static int proto_mongo
;
185 static int hf_mongo_message_length
;
186 static int hf_mongo_request_id
;
187 static int hf_mongo_response_to
;
188 static int hf_mongo_op_code
;
189 static int hf_mongo_fullcollectionname
;
190 static int hf_mongo_database_name
;
191 static int hf_mongo_collection_name
;
192 static int hf_mongo_reply_flags
;
193 static int hf_mongo_reply_flags_cursornotfound
;
194 static int hf_mongo_reply_flags_queryfailure
;
195 static int hf_mongo_reply_flags_sharedconfigstale
;
196 static int hf_mongo_reply_flags_awaitcapable
;
197 static int hf_mongo_cursor_id
;
198 static int hf_mongo_starting_from
;
199 static int hf_mongo_number_returned
;
200 static int hf_mongo_message
;
201 static int hf_mongo_zero
;
202 static int hf_mongo_update_flags
;
203 static int hf_mongo_update_flags_upsert
;
204 static int hf_mongo_update_flags_multiupdate
;
205 static int hf_mongo_selector
;
206 static int hf_mongo_update
;
207 static int hf_mongo_insert_flags
;
208 static int hf_mongo_insert_flags_continueonerror
;
209 static int hf_mongo_query_flags
;
210 static int hf_mongo_query_flags_tailablecursor
;
211 static int hf_mongo_query_flags_slaveok
;
212 static int hf_mongo_query_flags_oplogreplay
;
213 static int hf_mongo_query_flags_nocursortimeout
;
214 static int hf_mongo_query_flags_awaitdata
;
215 static int hf_mongo_query_flags_exhaust
;
216 static int hf_mongo_query_flags_partial
;
217 static int hf_mongo_number_to_skip
;
218 static int hf_mongo_number_to_return
;
219 static int hf_mongo_query
;
220 static int hf_mongo_return_field_selector
;
221 static int hf_mongo_document
;
222 static int hf_mongo_document_length
;
223 static int hf_mongo_document_empty
;
224 static int hf_mongo_delete_flags
;
225 static int hf_mongo_delete_flags_singleremove
;
226 static int hf_mongo_number_of_cursor_ids
;
227 static int hf_mongo_elements
;
228 static int hf_mongo_element_name
;
229 static int hf_mongo_element_type
;
230 static int hf_mongo_element_length
;
231 static int hf_mongo_element_value_boolean
;
232 static int hf_mongo_element_value_int32
;
233 static int hf_mongo_element_value_int64
;
234 static int hf_mongo_element_value_decimal128
;
235 static int hf_mongo_element_value_double
;
236 static int hf_mongo_element_value_string
;
237 static int hf_mongo_element_value_string_length
;
238 static int hf_mongo_element_value_binary
;
239 static int hf_mongo_element_value_binary_length
;
240 static int hf_mongo_element_value_regex_pattern
;
241 static int hf_mongo_element_value_regex_options
;
242 static int hf_mongo_element_value_objectid
;
243 static int hf_mongo_element_value_objectid_time
;
244 static int hf_mongo_element_value_objectid_host
;
245 static int hf_mongo_element_value_objectid_pid
;
246 static int hf_mongo_element_value_objectid_machine_id
;
247 static int hf_mongo_element_value_objectid_inc
;
248 static int hf_mongo_element_value_db_ptr
;
249 static int hf_mongo_element_value_js_code
;
250 static int hf_mongo_element_value_js_scope
;
251 static int hf_mongo_database
;
252 static int hf_mongo_commandname
;
253 static int hf_mongo_metadata
;
254 static int hf_mongo_commandargs
;
255 static int hf_mongo_commandreply
;
256 static int hf_mongo_outputdocs
;
257 static int hf_mongo_unknown
;
258 static int hf_mongo_compression_info
;
259 static int hf_mongo_original_op_code
;
260 static int hf_mongo_uncompressed_size
;
261 static int hf_mongo_compressor
;
262 static int hf_mongo_compressed_data
;
263 static int hf_mongo_unsupported_compressed
;
264 static int hf_mongo_msg_flags
;
265 static int hf_mongo_msg_flags_checksumpresent
;
266 static int hf_mongo_msg_flags_moretocome
;
267 static int hf_mongo_msg_flags_exhaustallowed
;
268 static int hf_mongo_msg_sections_section
;
269 static int hf_mongo_msg_sections_section_kind
;
270 static int hf_mongo_msg_sections_section_body
;
271 static int hf_mongo_msg_sections_section_doc_sequence
;
272 static int hf_mongo_msg_sections_section_size
;
273 static int hf_mongo_msg_sections_section_doc_sequence_id
;
274 static int hf_mongo_msg_checksum
;
275 static int hf_mongo_msg_checksum_status
;
277 static int ett_mongo
;
278 static int ett_mongo_doc
;
279 static int ett_mongo_elements
;
280 static int ett_mongo_element
;
281 static int ett_mongo_objectid
;
282 static int ett_mongo_machine_id
;
283 static int ett_mongo_code
;
284 static int ett_mongo_fcn
;
285 static int ett_mongo_flags
;
286 static int ett_mongo_compression_info
;
287 static int ett_mongo_sections
;
288 static int ett_mongo_section
;
289 static int ett_mongo_msg_flags
;
290 static int ett_mongo_doc_sequence
;
292 static expert_field ei_mongo_document_recursion_exceeded
;
293 static expert_field ei_mongo_document_length_bad
;
294 static expert_field ei_mongo_unknown
;
295 static expert_field ei_mongo_unsupported_compression
;
296 static expert_field ei_mongo_too_large_compressed
;
297 static expert_field ei_mongo_msg_checksum
;
300 dissect_fullcollectionname(tvbuff_t
*tvb
, unsigned offset
, proto_tree
*tree
)
302 int32_t fcn_length
, dbn_length
;
304 proto_tree
*fcn_tree
;
306 fcn_length
= tvb_strsize(tvb
, offset
);
307 ti
= proto_tree_add_item(tree
, hf_mongo_fullcollectionname
, tvb
, offset
, fcn_length
, ENC_ASCII
);
309 /* If this doesn't find anything, we'll just throw an exception below */
310 dbn_length
= tvb_find_uint8(tvb
, offset
, fcn_length
, '.') - offset
;
312 fcn_tree
= proto_item_add_subtree(ti
, ett_mongo_fcn
);
314 proto_tree_add_item(fcn_tree
, hf_mongo_database_name
, tvb
, offset
, dbn_length
, ENC_ASCII
);
316 proto_tree_add_item(fcn_tree
, hf_mongo_collection_name
, tvb
, offset
+ 1 + dbn_length
, fcn_length
- dbn_length
- 2, ENC_ASCII
);
321 /* http://docs.mongodb.org/manual/reference/limits/ */
322 /* http://www.mongodb.org/display/DOCS/Documents */
323 #define BSON_MAX_NESTING 100
324 #define BSON_MAX_DOC_SIZE (16 * 1000 * 1000)
326 // NOLINTNEXTLINE(misc-no-recursion)
327 dissect_bson_document(tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned offset
, proto_tree
*tree
, int hf_mongo_doc
)
329 int32_t document_length
;
330 unsigned final_offset
;
331 proto_item
*ti
, *elements
, *element
, *objectid
, *js_code
, *js_scope
, *machine_id
;
332 proto_tree
*doc_tree
, *elements_tree
, *element_sub_tree
, *objectid_sub_tree
, *js_code_sub_tree
, *js_scope_sub_tree
, *machine_id_sub_tree
;
334 document_length
= tvb_get_letohl(tvb
, offset
);
336 ti
= proto_tree_add_item(tree
, hf_mongo_doc
, tvb
, offset
, document_length
, ENC_NA
);
337 doc_tree
= proto_item_add_subtree(ti
, ett_mongo_doc
);
339 proto_tree_add_item(doc_tree
, hf_mongo_document_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
341 if (document_length
< 5) {
342 expert_add_info_format(pinfo
, ti
, &ei_mongo_document_length_bad
, "BSON document length too short: %u", document_length
);
343 return MAX(4, document_length
); /* see the comment above */
346 if (document_length
> BSON_MAX_DOC_SIZE
) {
347 expert_add_info_format(pinfo
, ti
, &ei_mongo_document_length_bad
, "BSON document length too long: %u", document_length
);
348 return document_length
;
351 if (document_length
== 5) {
352 /* document with length 5 is an empty document */
353 /* don't display the element subtree */
354 proto_tree_add_item(doc_tree
, hf_mongo_document_empty
, tvb
, offset
, document_length
, ENC_NA
);
355 return document_length
;
358 unsigned nest_level
= p_get_proto_depth(pinfo
, proto_mongo
);
359 if (++nest_level
> BSON_MAX_NESTING
) {
360 expert_add_info_format(pinfo
, ti
, &ei_mongo_document_recursion_exceeded
, "BSON document recursion exceeds %u", BSON_MAX_NESTING
);
361 /* return the number of bytes we consumed, these are at least the 4 bytes for the length field */
362 return MAX(4, document_length
);
364 p_set_proto_depth(pinfo
, proto_mongo
, nest_level
);
366 final_offset
= offset
+ document_length
;
369 elements
= proto_tree_add_item(doc_tree
, hf_mongo_elements
, tvb
, offset
, document_length
-5, ENC_NA
);
370 elements_tree
= proto_item_add_subtree(elements
, ett_mongo_elements
);
373 /* Read document elements */
374 uint8_t e_type
; /* Element type */
375 int str_len
= -1; /* String length */
376 int e_len
= -1; /* Element length */
377 int doc_len
= -1; /* Document length */
379 e_type
= tvb_get_uint8(tvb
, offset
);
380 tvb_get_stringz_enc(pinfo
->pool
, tvb
, offset
+1, &str_len
, ENC_ASCII
);
382 element
= proto_tree_add_item(elements_tree
, hf_mongo_element_name
, tvb
, offset
+1, str_len
-1, ENC_UTF_8
);
383 element_sub_tree
= proto_item_add_subtree(element
, ett_mongo_element
);
384 proto_tree_add_item(element_sub_tree
, hf_mongo_element_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
389 case BSON_ELEMENT_TYPE_DOUBLE
:
390 proto_tree_add_item(element_sub_tree
, hf_mongo_element_value_double
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
393 case BSON_ELEMENT_TYPE_STRING
:
394 case BSON_ELEMENT_TYPE_JS_CODE
:
395 case BSON_ELEMENT_TYPE_SYMBOL
:
396 str_len
= tvb_get_letohl(tvb
, offset
);
397 proto_tree_add_item(element_sub_tree
, hf_mongo_element_value_string_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
398 proto_tree_add_item(element_sub_tree
, hf_mongo_element_value_string
, tvb
, offset
+4, str_len
, ENC_UTF_8
);
401 case BSON_ELEMENT_TYPE_DOC
:
402 case BSON_ELEMENT_TYPE_ARRAY
:
403 offset
+= dissect_bson_document(tvb
, pinfo
, offset
, element_sub_tree
, hf_mongo_document
);
405 case BSON_ELEMENT_TYPE_BINARY
:
406 e_len
= tvb_get_letohl(tvb
, offset
);
407 /* TODO - Add functions to decode various binary subtypes */
408 proto_tree_add_item(element_sub_tree
, hf_mongo_element_value_binary_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
409 proto_tree_add_item(element_sub_tree
, hf_mongo_element_value_binary
, tvb
, offset
+5, e_len
, ENC_NA
);
412 case BSON_ELEMENT_TYPE_UNDEF
:
413 case BSON_ELEMENT_TYPE_NULL
:
414 case BSON_ELEMENT_TYPE_MIN_KEY
:
415 case BSON_ELEMENT_TYPE_MAX_KEY
:
416 /* Nothing to do, as there is no element content */
418 case BSON_ELEMENT_TYPE_OBJ_ID
:
419 objectid
= proto_tree_add_item(element_sub_tree
, hf_mongo_element_value_objectid
, tvb
, offset
, 12, ENC_NA
);
420 objectid_sub_tree
= proto_item_add_subtree(objectid
, ett_mongo_objectid
);
421 /* Unlike most BSON elements, parts of ObjectID are stored Big Endian, so they can be compared bit by bit */
422 proto_tree_add_item(objectid_sub_tree
, hf_mongo_element_value_objectid_time
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
423 /* The machine ID was traditionally split up in Host Hash/PID */
424 machine_id
= proto_tree_add_item(objectid_sub_tree
, hf_mongo_element_value_objectid_machine_id
, tvb
, offset
+4, 5, ENC_NA
);
425 machine_id_sub_tree
= proto_item_add_subtree(machine_id
, ett_mongo_machine_id
);
426 proto_tree_add_item(machine_id_sub_tree
, hf_mongo_element_value_objectid_host
, tvb
, offset
+4, 3, ENC_LITTLE_ENDIAN
);
427 proto_tree_add_item(machine_id_sub_tree
, hf_mongo_element_value_objectid_pid
, tvb
, offset
+7, 2, ENC_LITTLE_ENDIAN
);
429 proto_tree_add_item(objectid_sub_tree
, hf_mongo_element_value_objectid_inc
, tvb
, offset
+9, 3, ENC_BIG_ENDIAN
);
432 case BSON_ELEMENT_TYPE_BOOL
:
433 proto_tree_add_item(element_sub_tree
, hf_mongo_element_value_boolean
, tvb
, offset
, 1, ENC_NA
);
436 case BSON_ELEMENT_TYPE_REGEX
:
438 tvb_get_stringz_enc(pinfo
->pool
, tvb
, offset
, &str_len
, ENC_ASCII
);
439 proto_tree_add_item(element_sub_tree
, hf_mongo_element_value_regex_pattern
, tvb
, offset
, str_len
, ENC_UTF_8
);
442 tvb_get_stringz_enc(pinfo
->pool
, tvb
, offset
, &str_len
, ENC_ASCII
);
443 proto_tree_add_item(element_sub_tree
, hf_mongo_element_value_regex_options
, tvb
, offset
, str_len
, ENC_UTF_8
);
446 case BSON_ELEMENT_TYPE_DB_PTR
:
447 str_len
= tvb_get_letohl(tvb
, offset
);
448 proto_tree_add_item(element_sub_tree
, hf_mongo_element_value_string_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
449 proto_tree_add_item(element_sub_tree
, hf_mongo_element_value_string
, tvb
, offset
+4, str_len
, ENC_UTF_8
);
451 proto_tree_add_item(element_sub_tree
, hf_mongo_element_value_db_ptr
, tvb
, offset
, 12, ENC_NA
);
454 case BSON_ELEMENT_TYPE_JS_CODE_SCOPE
:
455 /* code_w_s ::= int32 string document */
456 proto_tree_add_item(element_sub_tree
, hf_mongo_element_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
457 e_len
= tvb_get_letohl(tvb
, offset
);
459 str_len
= tvb_get_letohl(tvb
, offset
);
460 js_code
= proto_tree_add_item(element_sub_tree
, hf_mongo_element_value_js_code
, tvb
, offset
, str_len
+4, ENC_NA
);
461 js_code_sub_tree
= proto_item_add_subtree(js_code
, ett_mongo_code
);
462 proto_tree_add_item(js_code_sub_tree
, hf_mongo_element_value_string_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
463 proto_tree_add_item(js_code_sub_tree
, hf_mongo_element_value_string
, tvb
, offset
+4, str_len
, ENC_UTF_8
);
465 doc_len
= e_len
- (str_len
+ 8);
466 js_scope
= proto_tree_add_item(element_sub_tree
, hf_mongo_element_value_js_scope
, tvb
, offset
, doc_len
, ENC_NA
);
467 js_scope_sub_tree
= proto_item_add_subtree(js_scope
, ett_mongo_code
);
468 offset
+= dissect_bson_document(tvb
, pinfo
, offset
, js_scope_sub_tree
, hf_mongo_document
);
470 case BSON_ELEMENT_TYPE_INT32
:
471 proto_tree_add_item(element_sub_tree
, hf_mongo_element_value_int32
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
474 case BSON_ELEMENT_TYPE_DATETIME
:
475 case BSON_ELEMENT_TYPE_TIMESTAMP
:
476 /* TODO Implement routine to convert datetime & timestamp values to UTC date/time */
477 /* for now, simply display the integer value */
478 case BSON_ELEMENT_TYPE_INT64
:
479 proto_tree_add_item(element_sub_tree
, hf_mongo_element_value_int64
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
482 case BSON_ELEMENT_TYPE_DECIMAL128
:
483 /* TODO Implement routine to convert to decimal128 for now, simply display bytes */
484 /* https://github.com/mongodb/specifications/blob/master/source/bson-decimal128/decimal128.rst */
485 proto_tree_add_item(element_sub_tree
, hf_mongo_element_value_decimal128
, tvb
, offset
, 16, ENC_NA
);
491 } while (offset
< final_offset
-1);
495 p_set_proto_depth(pinfo
, proto_mongo
, nest_level
);
497 return document_length
;
501 dissect_mongo_reply(tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned offset
, proto_tree
*tree
)
504 proto_tree
*flags_tree
;
505 int i
, number_returned
;
507 ti
= proto_tree_add_item(tree
, hf_mongo_reply_flags
, tvb
, offset
, 4, ENC_NA
);
508 flags_tree
= proto_item_add_subtree(ti
, ett_mongo_flags
);
509 proto_tree_add_item(flags_tree
, hf_mongo_reply_flags_cursornotfound
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
510 proto_tree_add_item(flags_tree
, hf_mongo_reply_flags_queryfailure
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
511 proto_tree_add_item(flags_tree
, hf_mongo_reply_flags_sharedconfigstale
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
512 proto_tree_add_item(flags_tree
, hf_mongo_reply_flags_awaitcapable
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
515 proto_tree_add_item(tree
, hf_mongo_cursor_id
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
518 proto_tree_add_item(tree
, hf_mongo_starting_from
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
521 proto_tree_add_item(tree
, hf_mongo_number_returned
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
522 number_returned
= tvb_get_letohl(tvb
, offset
);
525 for (i
=0; i
< number_returned
; i
++)
527 offset
+= dissect_bson_document(tvb
, pinfo
, offset
, tree
, hf_mongo_document
);
533 dissect_mongo_msg(tvbuff_t
*tvb
, unsigned offset
, proto_tree
*tree
)
535 proto_tree_add_item(tree
, hf_mongo_message
, tvb
, offset
, -1, ENC_ASCII
);
536 offset
+= tvb_strsize(tvb
, offset
);
542 dissect_mongo_update(tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned offset
, proto_tree
*tree
)
545 proto_tree
*flags_tree
;
547 proto_tree_add_item(tree
, hf_mongo_zero
, tvb
, offset
, 4, ENC_NA
);
550 offset
+= dissect_fullcollectionname(tvb
, offset
, tree
);
552 ti
= proto_tree_add_item(tree
, hf_mongo_update_flags
, tvb
, offset
, 4, ENC_NA
);
553 flags_tree
= proto_item_add_subtree(ti
, ett_mongo_flags
);
554 proto_tree_add_item(flags_tree
, hf_mongo_update_flags_upsert
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
555 proto_tree_add_item(flags_tree
, hf_mongo_update_flags_multiupdate
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
558 offset
+= dissect_bson_document(tvb
, pinfo
, offset
, tree
, hf_mongo_selector
);
560 offset
+= dissect_bson_document(tvb
, pinfo
, offset
, tree
, hf_mongo_update
);
566 dissect_mongo_insert(tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned offset
, proto_tree
*tree
)
569 proto_tree
*flags_tree
;
571 ti
= proto_tree_add_item(tree
, hf_mongo_insert_flags
, tvb
, offset
, 4, ENC_NA
);
572 flags_tree
= proto_item_add_subtree(ti
, ett_mongo_flags
);
573 proto_tree_add_item(flags_tree
, hf_mongo_insert_flags_continueonerror
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
576 offset
+= dissect_fullcollectionname(tvb
, offset
, tree
);
578 while(offset
< tvb_reported_length(tvb
)) {
579 offset
+= dissect_bson_document(tvb
, pinfo
, offset
, tree
, hf_mongo_document
);
586 dissect_mongo_query(tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned offset
, proto_tree
*tree
)
589 proto_tree
*flags_tree
;
591 ti
= proto_tree_add_item(tree
, hf_mongo_query_flags
, tvb
, offset
, 4, ENC_NA
);
592 flags_tree
= proto_item_add_subtree(ti
, ett_mongo_flags
);
593 proto_tree_add_item(flags_tree
, hf_mongo_query_flags_tailablecursor
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
594 proto_tree_add_item(flags_tree
, hf_mongo_query_flags_slaveok
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
595 proto_tree_add_item(flags_tree
, hf_mongo_query_flags_oplogreplay
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
596 proto_tree_add_item(flags_tree
, hf_mongo_query_flags_nocursortimeout
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
597 proto_tree_add_item(flags_tree
, hf_mongo_query_flags_awaitdata
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
598 proto_tree_add_item(flags_tree
, hf_mongo_query_flags_exhaust
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
599 proto_tree_add_item(flags_tree
, hf_mongo_query_flags_partial
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
602 offset
+= dissect_fullcollectionname(tvb
, offset
, tree
);
604 proto_tree_add_item(tree
, hf_mongo_number_to_skip
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
607 proto_tree_add_item(tree
, hf_mongo_number_to_return
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
610 offset
+= dissect_bson_document(tvb
, pinfo
, offset
, tree
, hf_mongo_query
);
612 while(offset
< tvb_reported_length(tvb
)) {
613 offset
+= dissect_bson_document(tvb
, pinfo
, offset
, tree
, hf_mongo_return_field_selector
);
619 dissect_mongo_getmore(tvbuff_t
*tvb
, unsigned offset
, proto_tree
*tree
)
622 proto_tree_add_item(tree
, hf_mongo_zero
, tvb
, offset
, 4, ENC_NA
);
625 offset
+= dissect_fullcollectionname(tvb
, offset
, tree
);
627 proto_tree_add_item(tree
, hf_mongo_number_to_return
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
630 proto_tree_add_item(tree
, hf_mongo_cursor_id
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
637 dissect_mongo_delete(tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned offset
, proto_tree
*tree
)
640 proto_tree
*flags_tree
;
642 proto_tree_add_item(tree
, hf_mongo_zero
, tvb
, offset
, 4, ENC_NA
);
645 offset
+= dissect_fullcollectionname(tvb
, offset
, tree
);
647 ti
= proto_tree_add_item(tree
, hf_mongo_delete_flags
, tvb
, offset
, 4, ENC_NA
);
648 flags_tree
= proto_item_add_subtree(ti
, ett_mongo_flags
);
649 proto_tree_add_item(flags_tree
, hf_mongo_delete_flags_singleremove
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
652 offset
+= dissect_bson_document(tvb
, pinfo
, offset
, tree
, hf_mongo_selector
);
658 dissect_mongo_kill_cursors(tvbuff_t
*tvb
, unsigned offset
, proto_tree
*tree
)
661 proto_tree_add_item(tree
, hf_mongo_zero
, tvb
, offset
, 4, ENC_NA
);
664 proto_tree_add_item(tree
, hf_mongo_number_of_cursor_ids
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
667 while(offset
< tvb_reported_length(tvb
)) {
668 proto_tree_add_item(tree
, hf_mongo_cursor_id
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
675 dissect_mongo_op_command(tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned offset
, proto_tree
*tree
)
677 int32_t db_length
, cmd_length
;
679 db_length
= tvb_strsize(tvb
, offset
);
680 proto_tree_add_item(tree
, hf_mongo_database
, tvb
, offset
, db_length
, ENC_ASCII
);
683 cmd_length
= tvb_strsize(tvb
, offset
);
684 proto_tree_add_item(tree
, hf_mongo_commandname
, tvb
, offset
, cmd_length
, ENC_ASCII
);
685 offset
+= cmd_length
;
687 offset
+= dissect_bson_document(tvb
, pinfo
, offset
, tree
, hf_mongo_metadata
);
689 offset
+= dissect_bson_document(tvb
, pinfo
, offset
, tree
, hf_mongo_commandargs
);
695 dissect_mongo_op_commandreply(tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned offset
, proto_tree
*tree
)
698 offset
+= dissect_bson_document(tvb
, pinfo
, offset
, tree
, hf_mongo_metadata
);
700 offset
+= dissect_bson_document(tvb
, pinfo
, offset
, tree
, hf_mongo_commandreply
);
702 if (tvb_reported_length_remaining(tvb
, offset
) > 0){
703 offset
+= dissect_bson_document(tvb
, pinfo
, offset
, tree
, hf_mongo_outputdocs
);
710 // NOLINTNEXTLINE(misc-no-recursion)
711 dissect_mongo_op_compressed(tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned offset
, proto_tree
*tree
, unsigned *effective_opcode
)
716 proto_tree
*compression_info_tree
;
718 ti
= proto_tree_add_item(tree
, hf_mongo_compression_info
, tvb
, offset
, 9, ENC_NA
);
719 compression_info_tree
= proto_item_add_subtree(ti
, ett_mongo_compression_info
);
720 proto_tree_add_item(compression_info_tree
, hf_mongo_original_op_code
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
721 proto_tree_add_item(compression_info_tree
, hf_mongo_uncompressed_size
, tvb
, offset
+ 4, 4, ENC_LITTLE_ENDIAN
);
722 proto_tree_add_item(compression_info_tree
, hf_mongo_compressor
, tvb
, offset
+ 8, 1, ENC_NA
);
723 proto_tree_add_item(compression_info_tree
, hf_mongo_compressed_data
, tvb
, offset
+ 9, -1, ENC_NA
);
725 opcode
= tvb_get_letohl(tvb
, offset
);
726 *effective_opcode
= opcode
;
727 compressor
= tvb_get_uint8(tvb
, offset
+ 8);
731 case MONGO_COMPRESSOR_NOOP
:
732 offset
= dissect_opcode_types(tvb
, pinfo
, offset
, tree
, opcode
, effective_opcode
);
736 case MONGO_COMPRESSOR_SNAPPY
: {
737 unsigned char *decompressed_buffer
= NULL
;
738 size_t orig_size
= 0;
740 tvbuff_t
* compressed_tvb
= NULL
;
742 /* get the raw data length */
743 ret
= snappy_uncompressed_length(tvb_get_ptr(tvb
, offset
, -1),
744 tvb_captured_length_remaining(tvb
, offset
),
746 /* if we get the length and it's reasonably short to allocate a buffer for it
747 * proceed to try decompressing the data
749 if (ret
== SNAPPY_OK
&& orig_size
<= MAX_UNCOMPRESSED_SIZE
) {
750 decompressed_buffer
= (unsigned char*)wmem_alloc(pinfo
->pool
, orig_size
);
752 ret
= snappy_uncompress(tvb_get_ptr(tvb
, offset
, -1),
753 tvb_captured_length_remaining(tvb
, offset
),
757 if (ret
== SNAPPY_OK
) {
758 compressed_tvb
= tvb_new_child_real_data(tvb
, decompressed_buffer
, (uint32_t)orig_size
, (uint32_t)orig_size
);
759 add_new_data_source(pinfo
, compressed_tvb
, "Decompressed Data");
761 dissect_opcode_types(compressed_tvb
, pinfo
, 0, tree
, opcode
, effective_opcode
);
763 expert_add_info_format(pinfo
, ti
, &ei_mongo_unsupported_compression
, "Error uncompressing snappy data");
766 if (orig_size
> MAX_UNCOMPRESSED_SIZE
) {
767 expert_add_info_format(pinfo
, ti
, &ei_mongo_too_large_compressed
, "Uncompressed size too large");
769 expert_add_info_format(pinfo
, ti
, &ei_mongo_unsupported_compression
, "Error uncompressing snappy data");
773 offset
= tvb_reported_length(tvb
);
778 case MONGO_COMPRESSOR_ZSTD
:
780 tvbuff_t
*uncompressed_tvb
= tvb_child_uncompress_zstd (tvb
, tvb
, offset
, tvb_captured_length_remaining (tvb
, offset
));
781 if (!uncompressed_tvb
) {
782 expert_add_info_format(pinfo
, ti
, &ei_mongo_unsupported_compression
, "Error uncompressing zstd data");
784 add_new_data_source(pinfo
, uncompressed_tvb
, "Decompressed Data");
785 dissect_opcode_types(uncompressed_tvb
, pinfo
, 0, tree
, opcode
, effective_opcode
);
788 offset
= tvb_reported_length(tvb
);
793 case MONGO_COMPRESSOR_ZLIB
: {
794 tvbuff_t
* compressed_tvb
= NULL
;
796 compressed_tvb
= tvb_child_uncompress_zlib(tvb
, tvb
, offset
, tvb_captured_length_remaining(tvb
, offset
));
798 if (compressed_tvb
) {
799 add_new_data_source(pinfo
, compressed_tvb
, "Decompressed Data");
801 dissect_opcode_types(compressed_tvb
, pinfo
, 0, tree
, opcode
, effective_opcode
);
803 proto_tree_add_item(compression_info_tree
, hf_mongo_unsupported_compressed
, tvb
, offset
, -1, ENC_NA
);
804 expert_add_info_format(pinfo
, ti
, &ei_mongo_unsupported_compression
, "Error uncompressing zlib data");
807 offset
= tvb_reported_length(tvb
);
811 proto_tree_add_item(compression_info_tree
, hf_mongo_unsupported_compressed
, tvb
, offset
, -1, ENC_NA
);
812 expert_add_info_format(pinfo
, ti
, &ei_mongo_unsupported_compression
, "Unsupported compression format: %d", compressor
);
813 offset
= tvb_reported_length(tvb
);
821 dissect_op_msg_section(tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned offset
, proto_tree
*tree
)
824 proto_tree
*section_tree
;
826 int section_len
= -1; /* Section length */
828 e_type
= tvb_get_uint8(tvb
, offset
);
829 section_len
= tvb_get_letohl(tvb
, offset
+1);
831 ti
= proto_tree_add_item(tree
, hf_mongo_msg_sections_section
, tvb
, offset
, 1 + section_len
, ENC_NA
);
832 section_tree
= proto_item_add_subtree(ti
, ett_mongo_section
);
833 proto_tree_add_item(section_tree
, hf_mongo_msg_sections_section_kind
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
838 section_len
= dissect_bson_document(tvb
, pinfo
, offset
, section_tree
, hf_mongo_msg_sections_section_body
);
839 /* If section_len is bogus (e.g., negative), dissect_bson_document sets
840 * an expert info and can return a different value than read above.
843 case KIND_DOCUMENT_SEQUENCE
: {
845 int32_t to_read
= section_len
;
846 proto_item
*documents
;
847 proto_tree
*documents_tree
;
849 proto_tree_add_item(section_tree
, hf_mongo_msg_sections_section_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
850 /* This is redundant with the lengths in the documents, we don't use this
851 * size at all. We could still report an expert info if it's bogus.
856 dsi_length
= tvb_strsize(tvb
, offset
);
857 proto_tree_add_item(section_tree
, hf_mongo_msg_sections_section_doc_sequence_id
, tvb
, offset
, dsi_length
, ENC_ASCII
);
858 offset
+= dsi_length
;
859 to_read
-= dsi_length
;
861 documents
= proto_tree_add_item(section_tree
, hf_mongo_msg_sections_section_doc_sequence
, tvb
, offset
, to_read
, ENC_NA
);
862 documents_tree
= proto_item_add_subtree(documents
, ett_mongo_doc_sequence
);
865 int32_t doc_size
= dissect_bson_document(tvb
, pinfo
, offset
, documents_tree
, hf_mongo_document
);
872 expert_add_info_format(pinfo
, tree
, &ei_mongo_unknown
, "Unknown section type: %u", e_type
);
875 return 1 + section_len
;
879 dissect_mongo_op_msg(tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned offset
, proto_tree
*tree
)
881 static int * const mongo_msg_flags
[] = {
882 &hf_mongo_msg_flags_checksumpresent
,
883 &hf_mongo_msg_flags_moretocome
,
884 &hf_mongo_msg_flags_exhaustallowed
,
887 int64_t op_msg_flags
;
888 bool checksum_present
= false;
890 proto_tree_add_bitmask_ret_uint64 (tree
, tvb
, offset
, hf_mongo_msg_flags
, ett_mongo_msg_flags
, mongo_msg_flags
, ENC_LITTLE_ENDIAN
, &op_msg_flags
);
891 if (op_msg_flags
& 0x00000001) {
892 checksum_present
= true;
897 while (tvb_reported_length_remaining(tvb
, offset
) > (checksum_present
? 4 : 0)){
898 offset
+= dissect_op_msg_section(tvb
, pinfo
, offset
, tree
);
901 if (checksum_present
) {
902 uint32_t calculated_checksum
= ~crc32c_tvb_offset_calculate (tvb
, 0, tvb_reported_length (tvb
) - 4, CRC32C_PRELOAD
);
903 proto_tree_add_checksum(tree
, tvb
, offset
, hf_mongo_msg_checksum
, hf_mongo_msg_checksum_status
, &ei_mongo_msg_checksum
, pinfo
, calculated_checksum
, ENC_BIG_ENDIAN
, PROTO_CHECKSUM_VERIFY
);
911 // NOLINTNEXTLINE(misc-no-recursion)
912 dissect_opcode_types(tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned offset
, proto_tree
*mongo_tree
, unsigned opcode
, unsigned *effective_opcode
)
914 *effective_opcode
= opcode
;
916 unsigned recursion_depth
= p_get_proto_depth(pinfo
, proto_mongo
);
917 DISSECTOR_ASSERT(recursion_depth
<= BSON_MAX_NESTING
);
918 p_set_proto_depth(pinfo
, proto_mongo
, recursion_depth
+ 1);
922 offset
= dissect_mongo_reply(tvb
, pinfo
, offset
, mongo_tree
);
925 offset
= dissect_mongo_msg(tvb
, offset
, mongo_tree
);
928 offset
= dissect_mongo_update(tvb
, pinfo
, offset
, mongo_tree
);
931 offset
= dissect_mongo_insert(tvb
, pinfo
, offset
, mongo_tree
);
934 offset
= dissect_mongo_query(tvb
, pinfo
, offset
, mongo_tree
);
937 offset
= dissect_mongo_getmore(tvb
, offset
, mongo_tree
);
940 offset
= dissect_mongo_delete(tvb
, pinfo
, offset
, mongo_tree
);
942 case OP_KILL_CURSORS
:
943 offset
= dissect_mongo_kill_cursors(tvb
, offset
, mongo_tree
);
946 offset
= dissect_mongo_op_command(tvb
, pinfo
, offset
, mongo_tree
);
948 case OP_COMMANDREPLY
:
949 offset
= dissect_mongo_op_commandreply(tvb
, pinfo
, offset
, mongo_tree
);
952 offset
= dissect_mongo_op_compressed(tvb
, pinfo
, offset
, mongo_tree
, effective_opcode
);
955 offset
= dissect_mongo_op_msg(tvb
, pinfo
, offset
, mongo_tree
);
958 /* No default Action */
962 p_set_proto_depth(pinfo
, proto_mongo
, recursion_depth
);
968 dissect_mongo_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
971 proto_tree
*mongo_tree
;
972 unsigned offset
= 0, opcode
, effective_opcode
= 0;
973 uint32_t response_to
;
975 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "MONGO");
977 ti
= proto_tree_add_item(tree
, proto_mongo
, tvb
, 0, -1, ENC_NA
);
979 mongo_tree
= proto_item_add_subtree(ti
, ett_mongo
);
981 proto_tree_add_item(mongo_tree
, hf_mongo_message_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
984 proto_tree_add_item(mongo_tree
, hf_mongo_request_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
987 proto_tree_add_item_ret_uint(mongo_tree
, hf_mongo_response_to
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &response_to
);
990 proto_tree_add_item(mongo_tree
, hf_mongo_op_code
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
991 opcode
= tvb_get_letohl(tvb
, offset
);
994 offset
= dissect_opcode_types(tvb
, pinfo
, offset
, mongo_tree
, opcode
, &effective_opcode
);
996 if (opcode
== 1 || response_to
!= 0)
998 col_set_str(pinfo
->cinfo
, COL_INFO
, "Response :");
1002 col_set_str(pinfo
->cinfo
, COL_INFO
, "Request :");
1005 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " %s", val_to_str_const(effective_opcode
, opcode_vals
, "Unknown"));
1007 if(opcode
!= effective_opcode
) {
1008 col_append_str(pinfo
->cinfo
, COL_INFO
, " (Compressed)");
1011 if(offset
< tvb_reported_length(tvb
))
1013 ti
= proto_tree_add_item(mongo_tree
, hf_mongo_unknown
, tvb
, offset
, -1, ENC_NA
);
1014 expert_add_info(pinfo
, ti
, &ei_mongo_unknown
);
1017 return tvb_captured_length(tvb
);
1020 get_mongo_pdu_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
, void *data _U_
)
1025 * Get the length of the MONGO packet.
1027 plen
= tvb_get_letohl(tvb
, offset
);
1028 /* XXX - This is signed, but we can only return an unsigned to
1029 * tcp_dissect_pdus. If negative, should we return something like
1030 * 1 (less than the fixed len 4) so that it causes a ReportedBoundsError?
1037 dissect_mongo(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
1039 tcp_dissect_pdus(tvb
, pinfo
, tree
, 1, 4, get_mongo_pdu_len
, dissect_mongo_pdu
, data
);
1040 return tvb_captured_length(tvb
);
1044 test_mongo(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
, void *data _U_
)
1048 if (tvb_captured_length_remaining(tvb
, offset
) < 16) {
1052 if (tvb_get_letohil(tvb
, offset
) < 4) {
1053 /* Message sizes are signed in the MongoDB Wire Protocol and
1054 * include the header.
1059 opcode
= tvb_get_letohl(tvb
, offset
+ 12);
1060 /* As 5.1 and later uses only 2 opcodes, we might be able to use that
1061 * (plus some other information) to do heuristics on other ports.
1063 return (try_val_to_str(opcode
, opcode_vals
) != NULL
);
1067 dissect_mongo_tcp_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
1069 if (!test_mongo(pinfo
, tvb
, 0, data
)) {
1071 /* The TLS heuristic dissector should catch this if over TLS. */
1073 conversation_t
*conversation
= find_or_create_conversation(pinfo
);
1074 conversation_set_dissector(conversation
, mongo_handle
);
1076 return dissect_mongo(tvb
, pinfo
, tree
, data
);
1080 proto_register_mongo(void)
1082 expert_module_t
* expert_mongo
;
1084 static hf_register_info hf
[] = {
1085 { &hf_mongo_message_length
,
1086 { "Message Length", "mongo.message_length",
1087 FT_INT32
, BASE_DEC
, NULL
, 0x0,
1088 "Total message size (including header)", HFILL
}
1090 { &hf_mongo_request_id
,
1091 { "Request ID", "mongo.request_id",
1092 FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0,
1093 "Identifier for this message", HFILL
}
1095 { &hf_mongo_response_to
,
1096 { "Response To", "mongo.response_to",
1097 FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0,
1098 "RequestID from the original request", HFILL
}
1100 { &hf_mongo_op_code
,
1101 { "OpCode", "mongo.opcode",
1102 FT_INT32
, BASE_DEC
, VALS(opcode_vals
), 0x0,
1103 "Type of request message", HFILL
}
1105 { &hf_mongo_query_flags
,
1106 { "Query Flags", "mongo.query.flags",
1107 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1108 "Bit vector of query options.", HFILL
}
1110 { &hf_mongo_fullcollectionname
,
1111 { "fullCollectionName", "mongo.full_collection_name",
1112 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
1113 "The full collection name is the concatenation of the database name with the"
1114 " collection name, using a dot for the concatenation", HFILL
}
1116 { &hf_mongo_database_name
,
1117 { "Database Name", "mongo.database_name",
1118 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1121 { &hf_mongo_collection_name
,
1122 { "Collection Name", "mongo.collection_name",
1123 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1126 { &hf_mongo_reply_flags
,
1127 { "Reply Flags", "mongo.reply.flags",
1128 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1129 "Bit vector of reply options.", HFILL
}
1131 { &hf_mongo_reply_flags_cursornotfound
,
1132 { "Cursor Not Found", "mongo.reply.flags.cursornotfound",
1133 FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00000001,
1134 "Set when getMore is called but the cursor id is not valid at the server", HFILL
}
1136 { &hf_mongo_reply_flags_queryfailure
,
1137 { "Query Failure", "mongo.reply.flags.queryfailure",
1138 FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00000002,
1139 "Set when query failed. Results consist of one document containing an $err"
1140 " field describing the failure.", HFILL
}
1142 { &hf_mongo_reply_flags_sharedconfigstale
,
1143 { "Shared Config Stale", "mongo.reply.flags.sharedconfigstale",
1144 FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00000004,
1147 { &hf_mongo_reply_flags_awaitcapable
,
1148 { "Await Capable", "mongo.reply.flags.awaitcapable",
1149 FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00000008,
1150 "Set when the server supports the AwaitData Query option", HFILL
}
1152 { &hf_mongo_message
,
1153 { "Message", "mongo.message",
1154 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
1155 "Message for the database", HFILL
}
1157 { &hf_mongo_cursor_id
,
1158 { "Cursor ID", "mongo.cursor_id",
1159 FT_INT64
, BASE_DEC
, NULL
, 0x0,
1160 "Cursor id if client needs to do get more's", HFILL
}
1162 { &hf_mongo_starting_from
,
1163 { "Starting From", "mongo.starting_from",
1164 FT_INT32
, BASE_DEC
, NULL
, 0x0,
1165 "Where in the cursor this reply is starting", HFILL
}
1167 { &hf_mongo_number_returned
,
1168 { "Number Returned", "mongo.number_returned",
1169 FT_INT32
, BASE_DEC
, NULL
, 0x0,
1170 "Number of documents in the reply", HFILL
}
1172 { &hf_mongo_document
,
1173 { "Document", "mongo.document",
1174 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1177 { &hf_mongo_document_length
,
1178 { "Document length", "mongo.document.length",
1179 FT_INT32
, BASE_DEC
, NULL
, 0x0,
1180 "Length of BSON Document", HFILL
}
1182 { &hf_mongo_document_empty
,
1183 { "Empty Document", "mongo.document.empty",
1184 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1185 "Document with no elements", HFILL
}
1188 { "Zero", "mongo.document.zero",
1189 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1190 "Reserved (Must be is Zero)", HFILL
}
1192 { &hf_mongo_update_flags
,
1193 { "Update Flags", "mongo.update.flags",
1194 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1195 "Bit vector of update options.", HFILL
}
1197 { &hf_mongo_update_flags_upsert
,
1198 { "Upsert", "mongo.update.flags.upsert",
1199 FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00000001,
1200 "If set, the database will insert the supplied object into the collection if no"
1201 " matching document is found", HFILL
}
1203 { &hf_mongo_update_flags_multiupdate
,
1204 { "Multi Update", "mongo.update.flags.multiupdate",
1205 FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00000002,
1206 "If set, the database will update all matching objects in the collection."
1207 " Otherwise only updates first matching doc.", HFILL
}
1209 { &hf_mongo_selector
,
1210 { "Selector", "mongo.selector",
1211 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1212 "The query to select the document", HFILL
}
1215 { "Update", "mongo.update",
1216 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1217 "Specification of the update to perform", HFILL
}
1219 { &hf_mongo_insert_flags
,
1220 { "Insert Flags", "mongo.insert.flags",
1221 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1222 "Bit vector of insert options.", HFILL
}
1224 { &hf_mongo_insert_flags_continueonerror
,
1225 { "ContinueOnError", "mongo.insert.flags.continueonerror",
1226 FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00000001,
1227 "If set, the database will not stop processing a bulk insert if one fails"
1228 " (eg due to duplicate IDs)", HFILL
}
1230 { &hf_mongo_query_flags_tailablecursor
,
1231 { "Tailable Cursor", "mongo.query.flags.tailable_cursor",
1232 FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00000002,
1233 "Tailable means cursor is not closed when the last data is retrieved", HFILL
}
1235 { &hf_mongo_query_flags_slaveok
,
1236 { "Slave OK", "mongo.query.flags.slave_ok",
1237 FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00000004,
1238 "Allow query of replica slave", HFILL
}
1240 { &hf_mongo_query_flags_oplogreplay
,
1241 { "Op Log Reply", "mongo.query.flags.op_log_reply",
1242 FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00000008,
1243 "Internal replication use only", HFILL
}
1245 { &hf_mongo_query_flags_nocursortimeout
,
1246 { "No Cursor Timeout", "mongo.query.flags.no_cursor_timeout",
1247 FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00000010,
1248 "The server normally times out idle cursors after an inactivity period (10 minutes)"
1249 " to prevent excess memory use. Set this option to prevent that", HFILL
}
1251 { &hf_mongo_query_flags_awaitdata
,
1252 { "AwaitData", "mongo.query.flags.awaitdata",
1253 FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00000020,
1254 "If we are at the end of the data, block for a while rather than returning no data."
1255 " After a timeout period, we do return as normal", HFILL
}
1257 { &hf_mongo_query_flags_exhaust
,
1258 { "Exhaust", "mongo.query.flags.exhaust",
1259 FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00000040,
1260 "Stream the data down full blast in multiple more packages, on the assumption"
1261 " that the client will fully read all data queried", HFILL
}
1263 { &hf_mongo_query_flags_partial
,
1264 { "Partial", "mongo.query.flags.partial",
1265 FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00000080,
1266 "Get partial results from a mongos if some shards are down (instead of throwing an error)", HFILL
}
1268 { &hf_mongo_number_to_skip
,
1269 { "Number To Skip", "mongo.number_to_skip",
1270 FT_INT32
, BASE_DEC
, NULL
, 0x0,
1271 "Number of documents in the skip", HFILL
}
1273 { &hf_mongo_number_to_return
,
1274 { "Number to Return", "mongo.number_to_return",
1275 FT_INT32
, BASE_DEC
, NULL
, 0x0,
1276 "Number of documents in the return", HFILL
}
1279 { "Query", "mongo.query",
1280 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1281 "Query BSON Document", HFILL
}
1283 { &hf_mongo_return_field_selector
,
1284 { "Return Field Selector", "mongo.return_field_selector",
1285 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1286 "Return Field Selector BSON Document", HFILL
}
1288 { &hf_mongo_delete_flags
,
1289 { "Delete Flags", "mongo.delete.flags",
1290 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1291 "Bit vector of delete options.", HFILL
}
1293 { &hf_mongo_delete_flags_singleremove
,
1294 { "Single Remove", "mongo.delete.flags.singleremove",
1295 FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00000001,
1296 "If set, the database will remove only the first matching document in the"
1297 " collection. Otherwise all matching documents will be removed", HFILL
}
1299 { &hf_mongo_compression_info
,
1300 { "Compression Info", "mongo.compression",
1301 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1302 "Compressed Packet", HFILL
}
1304 { &hf_mongo_original_op_code
,
1305 { "Original OpCode", "mongo.compression.original_opcode",
1306 FT_INT32
, BASE_DEC
, VALS(opcode_vals
), 0x0,
1307 "Type of request message (Wrapped)", HFILL
}
1309 { &hf_mongo_uncompressed_size
,
1310 { "Uncompressed Size", "mongo.compression.original_size",
1311 FT_INT32
, BASE_DEC
, NULL
, 0x0,
1312 "Size of the uncompressed packet", HFILL
}
1314 { &hf_mongo_compressor
,
1315 { "Compressor", "mongo.compression.compressor",
1316 FT_INT8
, BASE_DEC
, VALS(compressor_vals
), 0x0,
1317 "Compression engine", HFILL
}
1319 { &hf_mongo_compressed_data
,
1320 { "Compressed Data", "mongo.compression.compressed_data",
1321 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1322 "The compressed data", HFILL
}
1324 { &hf_mongo_unsupported_compressed
,
1325 { "Unsupported Compressed Data", "mongo.compression.unsupported_compressed",
1326 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1327 "This data is compressed with an unsupported compressor engine", HFILL
}
1329 { &hf_mongo_msg_flags
,
1330 { "Message Flags", "mongo.msg.flags",
1331 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
1332 "Bit vector of msg options.", HFILL
}
1334 { &hf_mongo_msg_flags_checksumpresent
,
1335 { "ChecksumPresent", "mongo.msg.flags.checksumpresent",
1336 FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00000001,
1337 "The message ends with 4 bytes containing a CRC-32C [1] checksum", HFILL
}
1339 { &hf_mongo_msg_flags_moretocome
,
1340 { "MoreToCome", "mongo.msg.flags.moretocome",
1341 FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00000002,
1342 "Another message will follow this one without further action from the receiver", HFILL
}
1344 { &hf_mongo_msg_flags_exhaustallowed
,
1345 { "ExhaustAllowed", "mongo.msg.flags.exhaustallowed",
1346 FT_BOOLEAN
, 32, TFS(&tfs_yes_no
), 0x00010000,
1347 "The client is prepared for multiple replies to this request using the moreToCome bit.", HFILL
}
1349 { &hf_mongo_msg_sections_section
,
1350 { "Section", "mongo.msg.sections.section",
1351 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1354 { &hf_mongo_msg_sections_section_kind
,
1355 { "Kind", "mongo.msg.sections.section.kind",
1356 FT_INT32
, BASE_DEC
, VALS(section_kind_vals
), 0x0,
1357 "Type of section", HFILL
}
1359 { &hf_mongo_msg_sections_section_body
,
1360 { "BodyDocument", "mongo.msg.sections.section.body",
1361 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1364 { &hf_mongo_msg_sections_section_doc_sequence
,
1365 { "DocumentSequence", "mongo.msg.sections.section.doc_sequence",
1366 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1369 { &hf_mongo_msg_sections_section_size
,
1370 { "Size", "mongo.msg.sections.section.size",
1371 FT_INT32
, BASE_DEC
, NULL
, 0x0,
1372 "Size (in bytes) of document sequence", HFILL
}
1374 { &hf_mongo_msg_sections_section_doc_sequence_id
,
1375 { "SeqID", "mongo.msg.sections.section.doc_sequence_id",
1376 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1377 "Document sequence identifier", HFILL
}
1379 { &hf_mongo_msg_checksum
,
1380 { "Checksum", "mongo.msg.checksum",
1381 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
1382 "CRC32C checksum.", HFILL
}
1384 { &hf_mongo_msg_checksum_status
,
1385 { "Checksum Status", "mongo.msg.checksum.status",
1386 FT_UINT8
, BASE_NONE
, VALS(proto_checksum_vals
), 0x0,
1389 { &hf_mongo_number_of_cursor_ids
,
1390 { "Number of Cursor IDS", "mongo.number_to_cursor_ids",
1391 FT_INT32
, BASE_DEC
, NULL
, 0x0,
1392 "Number of cursorIDs in message", HFILL
}
1394 { &hf_mongo_elements
,
1395 { "Elements", "mongo.elements",
1396 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1397 "Document Elements", HFILL
}
1399 { &hf_mongo_element_name
,
1400 { "Element", "mongo.element.name",
1401 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1402 "Element Name", HFILL
}
1404 { &hf_mongo_element_type
,
1405 { "Type", "mongo.element.type",
1406 FT_UINT8
, BASE_HEX_DEC
, VALS(element_type_vals
), 0x0,
1407 "Element Type", HFILL
}
1409 { &hf_mongo_element_length
,
1410 { "Length", "mongo.element.length",
1411 FT_INT32
, BASE_DEC
, NULL
, 0x0,
1412 "Element Length", HFILL
}
1414 { &hf_mongo_element_value_boolean
,
1415 { "Value", "mongo.element.value.bool",
1416 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1417 "Element Value", HFILL
}
1419 { &hf_mongo_element_value_int32
,
1420 { "Value", "mongo.element.value.int",
1421 FT_INT32
, BASE_DEC
, NULL
, 0x0,
1422 "Element Value", HFILL
}
1424 { &hf_mongo_element_value_int64
,
1425 { "Value", "mongo.element.value.int64",
1426 FT_INT64
, BASE_DEC
, NULL
, 0x0,
1427 "Element Value", HFILL
}
1429 { &hf_mongo_element_value_decimal128
,
1430 { "Value", "mongo.element.value.decimal128",
1431 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1432 "Element Value", HFILL
}
1434 { &hf_mongo_element_value_double
,
1435 { "Value", "mongo.element.value.double",
1436 FT_DOUBLE
, BASE_NONE
, NULL
, 0x0,
1437 "Element Value", HFILL
}
1439 { &hf_mongo_element_value_string
,
1440 { "Value", "mongo.element.value.string",
1441 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1442 "Element Value", HFILL
}
1444 { &hf_mongo_element_value_string_length
,
1445 { "Length", "mongo.element.value.length",
1446 FT_INT32
, BASE_DEC
, NULL
, 0x0,
1447 "Element Value Length", HFILL
}
1449 { &hf_mongo_element_value_binary
,
1450 { "Value", "mongo.element.value.bytes",
1451 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1452 "Element Value", HFILL
}
1454 { &hf_mongo_element_value_binary_length
,
1455 { "Length", "mongo.element.value.length",
1456 FT_INT32
, BASE_DEC
, NULL
, 0x0,
1457 "Binary Element Length", HFILL
}
1459 { &hf_mongo_element_value_regex_pattern
,
1460 { "Value", "mongo.element.value.regex.pattern",
1461 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1462 "Regex Pattern", HFILL
}
1464 { &hf_mongo_element_value_regex_options
,
1465 { "Value", "mongo.element.value.regex.options",
1466 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1467 "Regex Options", HFILL
}
1469 { &hf_mongo_element_value_objectid
,
1470 { "ObjectID", "mongo.element.value.objectid",
1471 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1472 "ObjectID Value", HFILL
}
1474 { &hf_mongo_element_value_objectid_time
,
1475 { "ObjectID Time", "mongo.element.value.objectid.time",
1476 FT_INT32
, BASE_DEC
, NULL
, 0x0,
1477 "ObjectID timestampt", HFILL
}
1479 { &hf_mongo_element_value_objectid_host
,
1480 { "ObjectID Host", "mongo.element.value.objectid.host",
1481 FT_UINT24
, BASE_HEX
, NULL
, 0x0,
1482 "ObjectID Host Hash", HFILL
}
1484 { &hf_mongo_element_value_objectid_machine_id
,
1485 { "ObjectID Machine", "mongo.element.value.objectid.machine_id",
1486 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1487 "ObjectID machine ID", HFILL
}
1489 { &hf_mongo_element_value_objectid_pid
,
1490 { "ObjectID PID", "mongo.element.value.objectid.pid",
1491 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1492 "ObjectID process ID", HFILL
}
1494 { &hf_mongo_element_value_objectid_inc
,
1495 { "ObjectID Inc", "mongo.element.value.objectid.inc",
1496 FT_UINT24
, BASE_DEC
, NULL
, 0x0,
1497 "ObjectID increment", HFILL
}
1499 { &hf_mongo_element_value_db_ptr
,
1500 { "ObjectID", "mongo.element.value.db_ptr",
1501 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1502 "DBPointer", HFILL
}
1504 { &hf_mongo_element_value_js_code
,
1505 { "JavaScript code", "mongo.element.value.js_code",
1506 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1507 "JavaScript code to be evaluated", HFILL
}
1509 { &hf_mongo_element_value_js_scope
,
1510 { "JavaScript scope", "mongo.element.value.js_scope",
1511 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1512 "Scope document for JavaScript evaluation", HFILL
}
1514 { &hf_mongo_database
,
1515 { "database", "mongo.database",
1516 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1517 "the name of the database to run the command on", HFILL
}
1519 { &hf_mongo_commandname
,
1520 { "commandName", "mongo.commandname",
1521 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1522 "the name of the command", HFILL
}
1524 { &hf_mongo_metadata
,
1525 { "metadata", "mongo.metadata",
1526 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1529 { &hf_mongo_commandargs
,
1530 { "CommandArgs", "mongo.commandargs",
1531 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1534 { &hf_mongo_commandreply
,
1535 { "CommandReply", "mongo.commandreply",
1536 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1539 { &hf_mongo_outputdocs
,
1540 { "OutputDocs", "mongo.outputdocs",
1541 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1544 { &hf_mongo_unknown
,
1545 { "Unknown", "mongo.unknown",
1546 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1547 "Unknown Data type", HFILL
}
1551 static int *ett
[] = {
1554 &ett_mongo_elements
,
1556 &ett_mongo_objectid
,
1557 &ett_mongo_machine_id
,
1561 &ett_mongo_compression_info
,
1562 &ett_mongo_sections
,
1564 &ett_mongo_msg_flags
,
1565 &ett_mongo_doc_sequence
1568 static ei_register_info ei
[] = {
1569 { &ei_mongo_document_recursion_exceeded
, { "mongo.document.recursion_exceeded", PI_MALFORMED
, PI_ERROR
, "BSON document recursion exceeds", EXPFILL
}},
1570 { &ei_mongo_document_length_bad
, { "mongo.document.length.bad", PI_MALFORMED
, PI_ERROR
, "BSON document length bad", EXPFILL
}},
1571 { &ei_mongo_unknown
, { "mongo.unknown.expert", PI_UNDECODED
, PI_WARN
, "Unknown Data (not interpreted)", EXPFILL
}},
1572 { &ei_mongo_unsupported_compression
, { "mongo.unsupported_compression.expert", PI_UNDECODED
, PI_WARN
, "This packet was compressed with an unsupported compressor", EXPFILL
}},
1573 { &ei_mongo_too_large_compressed
, { "mongo.too_large_compressed.expert", PI_UNDECODED
, PI_WARN
, "The size of the uncompressed packet exceeded the maximum allowed value", EXPFILL
}},
1574 { &ei_mongo_msg_checksum
, { "mongo.bad_checksum.expert", PI_UNDECODED
, PI_ERROR
, "Bad checksum", EXPFILL
}},
1577 proto_mongo
= proto_register_protocol("Mongo Wire Protocol", "MONGO", "mongo");
1579 /* Allow dissector to find be found by name. */
1580 mongo_handle
= register_dissector_with_description("mongo", "Mongo Wire Protocol", dissect_mongo
, proto_mongo
);
1581 mongo_heur_handle
= register_dissector_with_description("mongo_tcp", "Mongo Wire Protocol over TCP", dissect_mongo_tcp_heur
, proto_mongo
);
1583 proto_register_field_array(proto_mongo
, hf
, array_length(hf
));
1584 proto_register_subtree_array(ett
, array_length(ett
));
1585 expert_mongo
= expert_register_protocol(proto_mongo
);
1586 expert_register_field_array(expert_mongo
, ei
, array_length(ei
));
1591 proto_reg_handoff_mongo(void)
1593 dissector_add_uint_with_preference("tcp.port", TCP_PORT_MONGO
, mongo_heur_handle
);
1594 /* ssl_dissector_add registers TLS as the dissector for TCP on the given
1595 * port, but Mongo uses the same port by default with or without TLS,
1596 * so we need to test for the non-TLS version as well.
1597 * If the TLS heuristic dissector detects TLS on this port, assume Mongo.
1599 dissector_add_uint_with_preference("tls.port", TCP_PORT_MONGO
, mongo_handle
);
1607 * indent-tabs-mode: nil
1610 * ex: set shiftwidth=2 tabstop=8 expandtab:
1611 * :indentSize=2:tabSize=8:noTabs=true: