HACK: 2nd try to match RowsetProperties
[wireshark-wip.git] / epan / dissectors / packet-mongo.c
blob6000844ea70a76c49a47cef9a5dd367c81f10e79
1 /* packet-mongo.c
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 * $Id$
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 * See Mongo Wire Protocol Specification
29 * http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol
30 * See also BSON Specification
31 * http://bsonspec.org/#/specification
34 #include "config.h"
36 #include <glib.h>
38 #include <epan/packet.h>
39 #include <epan/exceptions.h>
40 #include <epan/prefs.h>
41 #include <epan/expert.h>
42 #include "packet-tcp.h"
44 /* This is not IANA assigned nor registered */
45 #define TCP_PORT_MONGO 27017
47 #define OP_REPLY 1
48 #define OP_MSG 1000
49 #define OP_UPDATE 2001
50 #define OP_INSERT 2002
51 #define OP_RESERVED 2003
52 #define OP_QUERY 2004
53 #define OP_GET_MORE 2005
54 #define OP_DELETE 2006
55 #define OP_KILL_CURSORS 2007
57 /**************************************************************************/
58 /* OpCode */
59 /**************************************************************************/
60 static const value_string opcode_vals[] = {
61 { OP_REPLY, "Reply" },
62 { OP_MSG, "Message" },
63 { OP_UPDATE, "Update document" },
64 { OP_INSERT, "Insert document" },
65 { OP_RESERVED,"Reserved" },
66 { OP_QUERY, "Query" },
67 { OP_GET_MORE, "Get More" },
68 { OP_DELETE, "Delete document" },
69 { OP_KILL_CURSORS, "Kill Cursors" },
70 { 0, NULL }
73 /* BSON Element types */
74 /* See http://bsonspec.org/#/specification for detail */
75 #define BSON_ELEMENT_TYPE_DOUBLE 1
76 #define BSON_ELEMENT_TYPE_STRING 2
77 #define BSON_ELEMENT_TYPE_DOC 3
78 #define BSON_ELEMENT_TYPE_ARRAY 4
79 #define BSON_ELEMENT_TYPE_BINARY 5
80 #define BSON_ELEMENT_TYPE_UNDEF 6 /* Deprecated */
81 #define BSON_ELEMENT_TYPE_OBJ_ID 7
82 #define BSON_ELEMENT_TYPE_BOOL 8
83 #define BSON_ELEMENT_TYPE_DATETIME 9
84 #define BSON_ELEMENT_TYPE_NULL 10
85 #define BSON_ELEMENT_TYPE_REGEX 11
86 #define BSON_ELEMENT_TYPE_DB_PTR 12 /* Deprecated */
87 #define BSON_ELEMENT_TYPE_JS_CODE 13
88 #define BSON_ELEMENT_TYPE_SYMBOL 14
89 #define BSON_ELEMENT_TYPE_JS_CODE_SCOPE 15
90 #define BSON_ELEMENT_TYPE_INT32 16 /* 0x10 */
91 #define BSON_ELEMENT_TYPE_TIMESTAMP 17 /* 0x11 */
92 #define BSON_ELEMENT_TYPE_INT64 18 /* 0x12 */
93 #define BSON_ELEMENT_TYPE_MIN_KEY 255 /* 0xFF */
94 #define BSON_ELEMENT_TYPE_MAX_KEY 127 /* 0x7F */
96 static const value_string element_type_vals[] = {
97 { BSON_ELEMENT_TYPE_DOUBLE, "Double" },
98 { BSON_ELEMENT_TYPE_STRING, "String" },
99 { BSON_ELEMENT_TYPE_DOC, "Document" },
100 { BSON_ELEMENT_TYPE_ARRAY, "Array" },
101 { BSON_ELEMENT_TYPE_BINARY, "Binary" },
102 { BSON_ELEMENT_TYPE_UNDEF, "Undefined" },
103 { BSON_ELEMENT_TYPE_OBJ_ID, "Object ID" },
104 { BSON_ELEMENT_TYPE_BOOL, "Boolean" },
105 { BSON_ELEMENT_TYPE_DATETIME, "Datetime" },
106 { BSON_ELEMENT_TYPE_NULL, "NULL" },
107 { BSON_ELEMENT_TYPE_REGEX, "Regular Expression" },
108 { BSON_ELEMENT_TYPE_DB_PTR, "DBPointer" },
109 { BSON_ELEMENT_TYPE_JS_CODE, "JavaScript Code" },
110 { BSON_ELEMENT_TYPE_SYMBOL, "Symbol" },
111 { BSON_ELEMENT_TYPE_JS_CODE_SCOPE, "JavaScript Code w/Scope" },
112 { BSON_ELEMENT_TYPE_INT32, "Int32" },
113 { BSON_ELEMENT_TYPE_TIMESTAMP, "Timestamp" },
114 { BSON_ELEMENT_TYPE_INT64, "Int64" },
115 { BSON_ELEMENT_TYPE_MIN_KEY, "Min Key" },
116 { BSON_ELEMENT_TYPE_MAX_KEY, "Max Key" },
117 { 0, NULL }
120 /* BSON Element Binary subtypes */
121 #define BSON_ELEMENT_BINARY_TYPE_GENERIC 0
122 #define BSON_ELEMENT_BINARY_TYPE_FUNCTION 1
123 #define BSON_ELEMENT_BINARY_TYPE_BINARY 2 /* OLD */
124 #define BSON_ELEMENT_BINARY_TYPE_UUID 3
125 #define BSON_ELEMENT_BINARY_TYPE_MD5 4
126 #define BSON_ELEMENT_BINARY_TYPE_USER 128 /* 0x80 */
128 #if 0
129 static const value_string binary_type_vals[] = {
130 { BSON_ELEMENT_BINARY_TYPE_GENERIC, "Generic" },
131 { BSON_ELEMENT_BINARY_TYPE_FUNCTION, "Function" },
132 { BSON_ELEMENT_BINARY_TYPE_BINARY, "Binary" },
133 { BSON_ELEMENT_BINARY_TYPE_UUID, "UUID" },
134 { BSON_ELEMENT_BINARY_TYPE_MD5, "MD5" },
135 { BSON_ELEMENT_BINARY_TYPE_USER, "User" },
136 { 0, NULL }
138 #endif
140 void proto_reg_handoff_mongo(void);
143 static int proto_mongo = -1;
144 static int hf_mongo_message_length = -1;
145 static int hf_mongo_request_id = -1;
146 static int hf_mongo_response_to = -1;
147 static int hf_mongo_op_code = -1;
148 static int hf_mongo_fullcollectionname = -1;
149 static int hf_mongo_database_name = -1;
150 static int hf_mongo_collection_name = -1;
151 static int hf_mongo_reply_flags = -1;
152 static int hf_mongo_reply_flags_cursornotfound = -1;
153 static int hf_mongo_reply_flags_queryfailure = -1;
154 static int hf_mongo_reply_flags_sharedconfigstale = -1;
155 static int hf_mongo_reply_flags_awaitcapable = -1;
156 static int hf_mongo_cursor_id = -1;
157 static int hf_mongo_starting_from = -1;
158 static int hf_mongo_number_returned = -1;
159 static int hf_mongo_message = -1;
160 static int hf_mongo_zero = -1;
161 static int hf_mongo_update_flags = -1;
162 static int hf_mongo_update_flags_upsert = -1;
163 static int hf_mongo_update_flags_multiupdate = -1;
164 static int hf_mongo_selector = -1;
165 static int hf_mongo_update = -1;
166 static int hf_mongo_insert_flags = -1;
167 static int hf_mongo_insert_flags_continueonerror = -1;
168 static int hf_mongo_query_flags = -1;
169 static int hf_mongo_query_flags_tailablecursor = -1;
170 static int hf_mongo_query_flags_slaveok = -1;
171 static int hf_mongo_query_flags_oplogreplay = -1;
172 static int hf_mongo_query_flags_nocursortimeout = -1;
173 static int hf_mongo_query_flags_awaitdata = -1;
174 static int hf_mongo_query_flags_exhaust = -1;
175 static int hf_mongo_query_flags_partial = -1;
176 static int hf_mongo_number_to_skip = -1;
177 static int hf_mongo_number_to_return = -1;
178 static int hf_mongo_query = -1;
179 static int hf_mongo_return_field_selector = -1;
180 static int hf_mongo_document = -1;
181 static int hf_mongo_document_length = -1;
182 static int hf_mongo_document_empty = -1;
183 static int hf_mongo_delete_flags = -1;
184 static int hf_mongo_delete_flags_singleremove = -1;
185 static int hf_mongo_number_of_cursor_ids = -1;
186 static int hf_mongo_elements = -1;
187 static int hf_mongo_element_name = -1;
188 static int hf_mongo_element_type = -1;
189 static int hf_mongo_element_length = -1;
190 static int hf_mongo_element_value_boolean = -1;
191 static int hf_mongo_element_value_int32 = -1;
192 static int hf_mongo_element_value_int64 = -1;
193 static int hf_mongo_element_value_double = -1;
194 static int hf_mongo_element_value_string = -1;
195 static int hf_mongo_element_value_string_length = -1;
196 static int hf_mongo_element_value_binary = -1;
197 static int hf_mongo_element_value_binary_length = -1;
198 static int hf_mongo_element_value_regex_pattern = -1;
199 static int hf_mongo_element_value_regex_options = -1;
200 static int hf_mongo_element_value_objectid = -1;
201 static int hf_mongo_element_value_objectid_time = -1;
202 static int hf_mongo_element_value_objectid_machine = -1;
203 static int hf_mongo_element_value_objectid_pid = -1;
204 static int hf_mongo_element_value_objectid_inc = -1;
205 static int hf_mongo_element_value_db_ptr = -1;
206 static int hf_mongo_element_value_js_code = -1;
207 static int hf_mongo_element_value_js_scope = -1;
208 static int hf_mongo_unknown = -1;
210 static guint global_mongo_tcp_port = TCP_PORT_MONGO;
212 static gint ett_mongo = -1;
213 static gint ett_mongo_doc = -1;
214 static gint ett_mongo_elements = -1;
215 static gint ett_mongo_element = -1;
216 static gint ett_mongo_objectid = -1;
217 static gint ett_mongo_code = -1;
218 static gint ett_mongo_fcn = -1;
219 static gint ett_mongo_flags = -1;
221 static expert_field ei_mongo_document_recursion_exceeded = EI_INIT;
222 static expert_field ei_mongo_document_length_bad = EI_INIT;
223 static expert_field ei_mongo_unknown = EI_INIT;
225 static int
226 dissect_fullcollectionname(tvbuff_t *tvb, guint offset, proto_tree *tree)
228 gint32 fcn_length, dbn_length;
229 proto_item *ti;
230 proto_tree *fcn_tree;
232 fcn_length = tvb_strsize(tvb, offset);
233 ti = proto_tree_add_item(tree, hf_mongo_fullcollectionname, tvb, offset, fcn_length, ENC_ASCII|ENC_NA);
235 /* If this doesn't find anything, we'll just throw an exception below */
236 dbn_length = tvb_find_guint8(tvb, offset, fcn_length, '.') - offset;
238 fcn_tree = proto_item_add_subtree(ti, ett_mongo_fcn);
240 proto_tree_add_item(fcn_tree, hf_mongo_database_name, tvb, offset, dbn_length, ENC_ASCII|ENC_NA);
242 proto_tree_add_item(fcn_tree, hf_mongo_collection_name, tvb, offset + 1 + dbn_length, fcn_length - dbn_length - 2, ENC_ASCII|ENC_NA);
244 return fcn_length;
247 /* http://docs.mongodb.org/manual/reference/limits/ */
248 /* http://www.mongodb.org/display/DOCS/Documents */
249 #define BSON_MAX_NESTING 100
250 #define BSON_MAX_DOC_SIZE (16 * 1000 * 1000)
251 static int
252 dissect_bson_document(tvbuff_t *tvb, packet_info *pinfo, guint offset, proto_tree *tree, int hf_mongo_doc, int nest_level)
254 gint32 document_length;
255 guint final_offset;
256 proto_item *ti, *elements, *element, *objectid, *js_code, *js_scope;
257 proto_tree *doc_tree, *elements_tree, *element_sub_tree, *objectid_sub_tree, *js_code_sub_tree, *js_scope_sub_tree;
259 document_length = tvb_get_letohl(tvb, offset);
261 ti = proto_tree_add_item(tree, hf_mongo_doc, tvb, offset, document_length, ENC_NA);
262 doc_tree = proto_item_add_subtree(ti, ett_mongo_doc);
264 proto_tree_add_item(doc_tree, hf_mongo_document_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
266 if (nest_level > BSON_MAX_NESTING) {
267 expert_add_info_format(pinfo, ti, &ei_mongo_document_recursion_exceeded, "BSON document recursion exceeds %u", BSON_MAX_NESTING);
268 THROW(ReportedBoundsError);
271 if (document_length < 5) {
272 expert_add_info_format(pinfo, ti, &ei_mongo_document_length_bad, "BSON document length too short: %u", document_length);
273 THROW(ReportedBoundsError);
276 if (document_length > BSON_MAX_DOC_SIZE) {
277 expert_add_info_format(pinfo, ti, &ei_mongo_document_length_bad, "BSON document length too long: %u", document_length);
278 THROW(ReportedBoundsError);
281 if (document_length == 5) {
282 /* document with length 5 is an empty document */
283 /* don't display the element subtree */
284 proto_tree_add_item(tree, hf_mongo_document_empty, tvb, offset, document_length, ENC_NA);
285 return document_length;
288 final_offset = offset + document_length;
289 offset += 4;
291 elements = proto_tree_add_item(doc_tree, hf_mongo_elements, tvb, offset, document_length-5, ENC_NA);
292 elements_tree = proto_item_add_subtree(elements, ett_mongo_elements);
294 do {
295 /* Read document elements */
296 guint8 e_type = -1; /* Element type */
297 gint str_len = -1; /* String length */
298 gint e_len = -1; /* Element length */
299 gint doc_len = -1; /* Document length */
301 e_type = tvb_get_guint8(tvb, offset);
302 tvb_get_stringz(wmem_packet_scope(), tvb, offset+1, &str_len);
304 element = proto_tree_add_item(elements_tree, hf_mongo_element_name, tvb, offset+1, str_len-1, ENC_UTF_8|ENC_NA);
305 element_sub_tree = proto_item_add_subtree(element, ett_mongo_element);
306 proto_tree_add_item(element_sub_tree, hf_mongo_element_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
308 offset += str_len+1;
310 switch(e_type) {
311 case BSON_ELEMENT_TYPE_DOUBLE:
312 proto_tree_add_item(element_sub_tree, hf_mongo_element_value_double, tvb, offset, 8, ENC_LITTLE_ENDIAN);
313 offset += 8;
314 break;
315 case BSON_ELEMENT_TYPE_STRING:
316 case BSON_ELEMENT_TYPE_JS_CODE:
317 case BSON_ELEMENT_TYPE_SYMBOL:
318 str_len = tvb_get_letohl(tvb, offset);
319 proto_tree_add_item(element_sub_tree, hf_mongo_element_value_string_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
320 proto_tree_add_item(element_sub_tree, hf_mongo_element_value_string, tvb, offset+4, str_len, ENC_UTF_8|ENC_NA);
321 offset += str_len+4;
322 break;
323 case BSON_ELEMENT_TYPE_DOC:
324 case BSON_ELEMENT_TYPE_ARRAY:
325 offset += dissect_bson_document(tvb, pinfo, offset, element_sub_tree, hf_mongo_document, nest_level+1);
326 break;
327 case BSON_ELEMENT_TYPE_BINARY:
328 e_len = tvb_get_letohl(tvb, offset);
329 /* TODO - Add functions to decode various binary subtypes */
330 proto_tree_add_item(element_sub_tree, hf_mongo_element_value_binary_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
331 proto_tree_add_item(element_sub_tree, hf_mongo_element_value_binary, tvb, offset+5, e_len, ENC_NA);
332 offset += e_len+5;
333 break;
334 case BSON_ELEMENT_TYPE_UNDEF:
335 case BSON_ELEMENT_TYPE_NULL:
336 case BSON_ELEMENT_TYPE_MIN_KEY:
337 case BSON_ELEMENT_TYPE_MAX_KEY:
338 /* Nothing to do, as there is no element content */
339 break;
340 case BSON_ELEMENT_TYPE_OBJ_ID:
341 objectid = proto_tree_add_item(element_sub_tree, hf_mongo_element_value_objectid, tvb, offset, 12, ENC_NA);
342 objectid_sub_tree = proto_item_add_subtree(objectid, ett_mongo_objectid);
343 /* Unlike most BSON elements, parts of ObjectID are stored Big Endian, so they can be compared bit by bit */
344 proto_tree_add_item(objectid_sub_tree, hf_mongo_element_value_objectid_time, tvb, offset, 4, ENC_BIG_ENDIAN);
345 proto_tree_add_item(objectid_sub_tree, hf_mongo_element_value_objectid_machine, tvb, offset+4, 3, ENC_LITTLE_ENDIAN);
346 proto_tree_add_item(objectid_sub_tree, hf_mongo_element_value_objectid_pid, tvb, offset+7, 2, ENC_LITTLE_ENDIAN);
347 proto_tree_add_item(objectid_sub_tree, hf_mongo_element_value_objectid_inc, tvb, offset+9, 3, ENC_BIG_ENDIAN);
348 offset += 12;
349 break;
350 case BSON_ELEMENT_TYPE_BOOL:
351 proto_tree_add_item(element_sub_tree, hf_mongo_element_value_boolean, tvb, offset, 1, ENC_NA);
352 offset += 1;
353 break;
354 case BSON_ELEMENT_TYPE_REGEX:
355 /* regex pattern */
356 tvb_get_stringz(wmem_packet_scope(), tvb, offset, &str_len);
357 proto_tree_add_item(element_sub_tree, hf_mongo_element_value_regex_pattern, tvb, offset, str_len, ENC_UTF_8|ENC_NA);
358 offset += str_len;
359 /* regex options */
360 tvb_get_stringz(wmem_packet_scope(), tvb, offset, &str_len);
361 proto_tree_add_item(element_sub_tree, hf_mongo_element_value_regex_options, tvb, offset, str_len, ENC_UTF_8|ENC_NA);
362 offset += str_len;
363 break;
364 case BSON_ELEMENT_TYPE_DB_PTR:
365 str_len = tvb_get_letohl(tvb, offset);
366 proto_tree_add_item(element_sub_tree, hf_mongo_element_value_string_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
367 proto_tree_add_item(element_sub_tree, hf_mongo_element_value_string, tvb, offset+4, str_len, ENC_UTF_8|ENC_NA);
368 offset += str_len;
369 proto_tree_add_item(element_sub_tree, hf_mongo_element_value_db_ptr, tvb, offset, 12, ENC_NA);
370 offset += 12;
371 break;
372 case BSON_ELEMENT_TYPE_JS_CODE_SCOPE:
373 /* code_w_s ::= int32 string document */
374 proto_tree_add_item(element_sub_tree, hf_mongo_element_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
375 e_len = tvb_get_letohl(tvb, offset);
376 offset += 4;
377 str_len = tvb_get_letohl(tvb, offset);
378 js_code = proto_tree_add_item(element_sub_tree, hf_mongo_element_value_js_code, tvb, offset, str_len+4, ENC_NA);
379 js_code_sub_tree = proto_item_add_subtree(js_code, ett_mongo_code);
380 proto_tree_add_item(js_code_sub_tree, hf_mongo_element_value_string_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
381 proto_tree_add_item(js_code_sub_tree, hf_mongo_element_value_string, tvb, offset+4, str_len, ENC_UTF_8|ENC_NA);
382 offset += str_len+4;
383 doc_len = e_len - (str_len + 8);
384 js_scope = proto_tree_add_item(element_sub_tree, hf_mongo_element_value_js_scope, tvb, offset, doc_len, ENC_NA);
385 js_scope_sub_tree = proto_item_add_subtree(js_scope, ett_mongo_code);
386 offset += dissect_bson_document(tvb, pinfo, offset, js_scope_sub_tree, hf_mongo_document, nest_level+1);
387 break;
388 case BSON_ELEMENT_TYPE_INT32:
389 proto_tree_add_item(element_sub_tree, hf_mongo_element_value_int32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
390 offset += 4;
391 break;
392 case BSON_ELEMENT_TYPE_DATETIME:
393 case BSON_ELEMENT_TYPE_TIMESTAMP:
394 /* TODO Implement routine to convert datetime & timestamp values to UTC date/time */
395 /* for now, simply display the integer value */
396 case BSON_ELEMENT_TYPE_INT64:
397 proto_tree_add_item(element_sub_tree, hf_mongo_element_value_int64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
398 offset += 8;
399 break;
400 default:
401 break;
402 } /* end switch() */
403 } while (offset < final_offset-1);
405 return document_length;
407 static int
408 dissect_mongo_reply(tvbuff_t *tvb, packet_info *pinfo, guint offset, proto_tree *tree)
410 proto_item *ti;
411 proto_tree *flags_tree;
412 gint i, number_returned;
414 ti = proto_tree_add_item(tree, hf_mongo_reply_flags, tvb, offset, 4, ENC_NA);
415 flags_tree = proto_item_add_subtree(ti, ett_mongo_flags);
416 proto_tree_add_item(flags_tree, hf_mongo_reply_flags_cursornotfound, tvb, offset, 4, ENC_LITTLE_ENDIAN);
417 proto_tree_add_item(flags_tree, hf_mongo_reply_flags_queryfailure, tvb, offset, 4, ENC_LITTLE_ENDIAN);
418 proto_tree_add_item(flags_tree, hf_mongo_reply_flags_sharedconfigstale, tvb, offset, 4, ENC_LITTLE_ENDIAN);
419 proto_tree_add_item(flags_tree, hf_mongo_reply_flags_awaitcapable, tvb, offset, 4, ENC_LITTLE_ENDIAN);
420 offset += 4;
422 proto_tree_add_item(tree, hf_mongo_cursor_id, tvb, offset, 8, ENC_LITTLE_ENDIAN);
423 offset += 8;
425 proto_tree_add_item(tree, hf_mongo_starting_from, tvb, offset, 4, ENC_LITTLE_ENDIAN);
426 offset += 4;
428 proto_tree_add_item(tree, hf_mongo_number_returned, tvb, offset, 4, ENC_LITTLE_ENDIAN);
429 number_returned = tvb_get_letohl(tvb, offset);
430 offset += 4;
432 for (i=0; i < number_returned; i++)
434 offset += dissect_bson_document(tvb, pinfo, offset, tree, hf_mongo_document, 1);
436 return offset;
438 static int
439 dissect_mongo_msg(tvbuff_t *tvb, guint offset, proto_tree *tree)
441 proto_tree_add_item(tree, hf_mongo_message, tvb, offset, -1, ENC_ASCII|ENC_NA);
442 offset += tvb_strsize(tvb, offset);
444 return offset;
447 static int
448 dissect_mongo_update(tvbuff_t *tvb, packet_info *pinfo, guint offset, proto_tree *tree)
450 proto_item *ti;
451 proto_tree *flags_tree;
453 proto_tree_add_item(tree, hf_mongo_zero, tvb, offset, 4, ENC_NA);
454 offset += 4;
456 offset += dissect_fullcollectionname(tvb, offset, tree);
458 ti = proto_tree_add_item(tree, hf_mongo_update_flags, tvb, offset, 4, ENC_NA);
459 flags_tree = proto_item_add_subtree(ti, ett_mongo_flags);
460 proto_tree_add_item(flags_tree, hf_mongo_update_flags_upsert, tvb, offset, 4, ENC_LITTLE_ENDIAN);
461 proto_tree_add_item(flags_tree, hf_mongo_update_flags_multiupdate, tvb, offset, 4, ENC_LITTLE_ENDIAN);
462 offset += 4;
464 offset += dissect_bson_document(tvb, pinfo, offset, tree, hf_mongo_selector, 1);
466 offset += dissect_bson_document(tvb, pinfo, offset, tree, hf_mongo_update, 1);
468 return offset;
471 static int
472 dissect_mongo_insert(tvbuff_t *tvb, packet_info *pinfo, guint offset, proto_tree *tree)
474 proto_item *ti;
475 proto_tree *flags_tree;
477 ti = proto_tree_add_item(tree, hf_mongo_insert_flags, tvb, offset, 4, ENC_NA);
478 flags_tree = proto_item_add_subtree(ti, ett_mongo_flags);
479 proto_tree_add_item(flags_tree, hf_mongo_insert_flags_continueonerror, tvb, offset, 4, ENC_LITTLE_ENDIAN);
480 offset += 4;
482 offset += dissect_fullcollectionname(tvb, offset, tree);
484 while(offset < tvb_reported_length(tvb)) {
485 offset += dissect_bson_document(tvb, pinfo, offset, tree, hf_mongo_document, 1);
488 return offset;
491 static int
492 dissect_mongo_query(tvbuff_t *tvb, packet_info *pinfo, guint offset, proto_tree *tree)
494 proto_item *ti;
495 proto_tree *flags_tree;
497 ti = proto_tree_add_item(tree, hf_mongo_query_flags, tvb, offset, 4, ENC_NA);
498 flags_tree = proto_item_add_subtree(ti, ett_mongo_flags);
499 proto_tree_add_item(flags_tree, hf_mongo_query_flags_tailablecursor, tvb, offset, 4, ENC_LITTLE_ENDIAN);
500 proto_tree_add_item(flags_tree, hf_mongo_query_flags_slaveok, tvb, offset, 4, ENC_LITTLE_ENDIAN);
501 proto_tree_add_item(flags_tree, hf_mongo_query_flags_oplogreplay, tvb, offset, 4, ENC_LITTLE_ENDIAN);
502 proto_tree_add_item(flags_tree, hf_mongo_query_flags_nocursortimeout, tvb, offset, 4, ENC_LITTLE_ENDIAN);
503 proto_tree_add_item(flags_tree, hf_mongo_query_flags_awaitdata, tvb, offset, 4, ENC_LITTLE_ENDIAN);
504 proto_tree_add_item(flags_tree, hf_mongo_query_flags_exhaust, tvb, offset, 4, ENC_LITTLE_ENDIAN);
505 proto_tree_add_item(flags_tree, hf_mongo_query_flags_partial, tvb, offset, 4, ENC_LITTLE_ENDIAN);
506 offset += 4;
508 offset += dissect_fullcollectionname(tvb, offset, tree);
510 proto_tree_add_item(tree, hf_mongo_number_to_skip, tvb, offset, 4, ENC_LITTLE_ENDIAN);
511 offset += 4;
513 proto_tree_add_item(tree, hf_mongo_number_to_return, tvb, offset, 4, ENC_LITTLE_ENDIAN);
514 offset +=4;
516 offset += dissect_bson_document(tvb, pinfo, offset, tree, hf_mongo_query, 1);
518 while(offset < tvb_reported_length(tvb)) {
519 offset += dissect_bson_document(tvb, pinfo, offset, tree, hf_mongo_return_field_selector, 1);
521 return offset;
524 static int
525 dissect_mongo_getmore(tvbuff_t *tvb, guint offset, proto_tree *tree)
528 proto_tree_add_item(tree, hf_mongo_zero, tvb, offset, 4, ENC_NA);
529 offset += 4;
531 offset += dissect_fullcollectionname(tvb, offset, tree);
533 proto_tree_add_item(tree, hf_mongo_number_to_return, tvb, offset, 4, ENC_LITTLE_ENDIAN);
534 offset += 4;
536 proto_tree_add_item(tree, hf_mongo_cursor_id, tvb, offset, 8, ENC_LITTLE_ENDIAN);
537 offset += 8;
539 return offset;
542 static int
543 dissect_mongo_delete(tvbuff_t *tvb, packet_info *pinfo, guint offset, proto_tree *tree)
545 proto_item *ti;
546 proto_tree *flags_tree;
548 proto_tree_add_item(tree, hf_mongo_zero, tvb, offset, 4, ENC_NA);
549 offset += 4;
551 offset += dissect_fullcollectionname(tvb, offset, tree);
553 ti = proto_tree_add_item(tree, hf_mongo_delete_flags, tvb, offset, 4, ENC_NA);
554 flags_tree = proto_item_add_subtree(ti, ett_mongo_flags);
555 proto_tree_add_item(flags_tree, hf_mongo_delete_flags_singleremove, tvb, offset, 4, ENC_LITTLE_ENDIAN);
556 offset += 4;
558 offset += dissect_bson_document(tvb, pinfo, offset, tree, hf_mongo_selector, 1);
560 return offset;
563 static int
564 dissect_mongo_kill_cursors(tvbuff_t *tvb, guint offset, proto_tree *tree)
567 proto_tree_add_item(tree, hf_mongo_zero, tvb, offset, 4, ENC_NA);
568 offset += 4;
570 proto_tree_add_item(tree, hf_mongo_number_of_cursor_ids, tvb, offset, 4, ENC_LITTLE_ENDIAN);
571 offset += 4;
573 while(offset < tvb_reported_length(tvb)) {
574 proto_tree_add_item(tree, hf_mongo_cursor_id, tvb, offset, 8, ENC_LITTLE_ENDIAN);
575 offset +=8;
577 return offset;
579 static int
580 dissect_mongo_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
582 proto_item *ti;
583 proto_tree *mongo_tree;
584 guint offset = 0, opcode;
586 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MONGO");
588 ti = proto_tree_add_item(tree, proto_mongo, tvb, 0, -1, ENC_NA);
590 mongo_tree = proto_item_add_subtree(ti, ett_mongo);
592 proto_tree_add_item(mongo_tree, hf_mongo_message_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
593 offset += 4;
595 proto_tree_add_item(mongo_tree, hf_mongo_request_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
596 offset += 4;
598 proto_tree_add_item(mongo_tree, hf_mongo_response_to, tvb, offset, 4, ENC_LITTLE_ENDIAN);
599 offset += 4;
601 proto_tree_add_item(mongo_tree, hf_mongo_op_code, tvb, offset, 4, ENC_LITTLE_ENDIAN);
602 opcode = tvb_get_letohl(tvb, offset);
603 offset += 4;
605 if(opcode == 1)
607 col_set_str(pinfo->cinfo, COL_INFO, "Response :");
609 else
611 col_set_str(pinfo->cinfo, COL_INFO, "Request :");
614 col_append_fstr(pinfo->cinfo, COL_INFO, " %s", val_to_str_const(opcode, opcode_vals, "Unknown"));
616 switch(opcode){
617 case OP_REPLY:
618 offset = dissect_mongo_reply(tvb, pinfo, offset, mongo_tree);
619 break;
620 case OP_MSG:
621 offset = dissect_mongo_msg(tvb, offset, mongo_tree);
622 break;
623 case OP_UPDATE:
624 offset = dissect_mongo_update(tvb, pinfo, offset, mongo_tree);
625 break;
626 case OP_INSERT:
627 offset = dissect_mongo_insert(tvb, pinfo, offset, mongo_tree);
628 break;
629 case OP_QUERY:
630 offset = dissect_mongo_query(tvb, pinfo, offset, mongo_tree);
631 break;
632 case OP_GET_MORE:
633 offset = dissect_mongo_getmore(tvb, offset, mongo_tree);
634 break;
635 case OP_DELETE:
636 offset = dissect_mongo_delete(tvb, pinfo, offset, mongo_tree);
637 break;
638 case OP_KILL_CURSORS:
639 offset = dissect_mongo_kill_cursors(tvb, offset, mongo_tree);
640 break;
641 default:
642 /* No default Action */
643 break;
645 if(offset < tvb_reported_length(tvb))
647 ti = proto_tree_add_item(mongo_tree, hf_mongo_unknown, tvb, offset, -1, ENC_NA);
648 expert_add_info(pinfo, ti, &ei_mongo_unknown);
651 return tvb_length(tvb);
653 static guint
654 get_mongo_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
656 guint32 plen;
659 * Get the length of the MONGO packet.
661 plen = tvb_get_letohl(tvb, offset);
663 return plen;
666 static int
667 dissect_mongo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
669 tcp_dissect_pdus(tvb, pinfo, tree, 1, 4, get_mongo_pdu_len, dissect_mongo_pdu, data);
670 return tvb_length(tvb);
673 void
674 proto_register_mongo(void)
676 module_t *mongo_module;
677 expert_module_t* expert_mongo;
679 static hf_register_info hf[] = {
680 { &hf_mongo_message_length,
681 { "Message Length", "mongo.message_length",
682 FT_INT32, BASE_DEC, NULL, 0x0,
683 "Total message size (include this)", HFILL }
685 { &hf_mongo_request_id,
686 { "Request ID", "mongo.request_id",
687 FT_UINT32, BASE_HEX_DEC, NULL, 0x0,
688 "Identifier for this message", HFILL }
690 { &hf_mongo_response_to,
691 { "Response To", "mongo.response_to",
692 FT_UINT32, BASE_HEX_DEC, NULL, 0x0,
693 "RequestID from the original request", HFILL }
695 { &hf_mongo_op_code,
696 { "OpCode", "mongo.opcode",
697 FT_INT32, BASE_DEC, VALS(opcode_vals), 0x0,
698 "Type of request message", HFILL }
700 { &hf_mongo_query_flags,
701 { "Query Flags", "mongo.query.flags",
702 FT_NONE, BASE_NONE, NULL, 0x0,
703 "Bit vector of query options.", HFILL }
705 { &hf_mongo_fullcollectionname,
706 { "fullCollectionName", "mongo.full_collection_name",
707 FT_STRINGZ, BASE_NONE, NULL, 0x0,
708 "The full collection name is the concatenation of the database name with the"
709 " collection name, using a dot for the concatenation", HFILL }
711 { &hf_mongo_database_name,
712 { "Database Name", "mongo.database_name",
713 FT_STRING, BASE_NONE, NULL, 0x0,
714 NULL, HFILL }
716 { &hf_mongo_collection_name,
717 { "Collection Name", "mongo.collection_name",
718 FT_STRING, BASE_NONE, NULL, 0x0,
719 NULL, HFILL }
721 { &hf_mongo_reply_flags,
722 { "Reply Flags", "mongo.reply.flags",
723 FT_NONE, BASE_NONE, NULL, 0x0,
724 "Bit vector of reply options.", HFILL }
726 { &hf_mongo_reply_flags_cursornotfound,
727 { "Cursor Not Found", "mongo.reply.flags.cursornotfound",
728 FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000001,
729 "Set when getMore is called but the cursor id is not valid at the server", HFILL }
731 { &hf_mongo_reply_flags_queryfailure,
732 { "Query Failure", "mongo.reply.flags.queryfailure",
733 FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000002,
734 "Set when query failed. Results consist of one document containing an $err"
735 " field describing the failure.", HFILL }
737 { &hf_mongo_reply_flags_sharedconfigstale,
738 { "Shared Config Stale", "mongo.reply.flags.sharedconfigstale",
739 FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000004,
740 NULL, HFILL }
742 { &hf_mongo_reply_flags_awaitcapable,
743 { "Await Capable", "mongo.reply.flags.awaitcapable",
744 FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000008,
745 "Set when the server supports the AwaitData Query option", HFILL }
747 { &hf_mongo_message,
748 { "Message", "mongo.message",
749 FT_STRINGZ, BASE_NONE, NULL, 0x0,
750 "Message for the database", HFILL }
752 { &hf_mongo_cursor_id,
753 { "Cursor ID", "mongo.cursor_id",
754 FT_INT64, BASE_DEC, NULL, 0x0,
755 "Cursor id if client needs to do get more's", HFILL }
757 { &hf_mongo_starting_from,
758 { "Starting From", "mongo.starting_from",
759 FT_INT32, BASE_DEC, NULL, 0x0,
760 "Where in the cursor this reply is starting", HFILL }
762 { &hf_mongo_number_returned,
763 { "Number Returned", "mongo.number_returned",
764 FT_INT32, BASE_DEC, NULL, 0x0,
765 "Number of documents in the reply", HFILL }
767 { &hf_mongo_document,
768 { "Document", "mongo.document",
769 FT_NONE, BASE_NONE, NULL, 0x0,
770 NULL, HFILL }
772 { &hf_mongo_document_length,
773 { "Document length", "mongo.document.length",
774 FT_INT32, BASE_DEC, NULL, 0x0,
775 "Length of BSON Document", HFILL }
777 { &hf_mongo_document_empty,
778 { "Empty Document", "mongo.document.empty",
779 FT_NONE, BASE_NONE, NULL, 0x0,
780 "Document with no elements", HFILL }
782 { &hf_mongo_zero,
783 { "Zero", "mongo.document.zero",
784 FT_BYTES, BASE_NONE, NULL, 0x0,
785 "Reserved (Must be is Zero)", HFILL }
787 { &hf_mongo_update_flags,
788 { "Update Flags", "mongo.update.flags",
789 FT_NONE, BASE_NONE, NULL, 0x0,
790 "Bit vector of update options.", HFILL }
792 { &hf_mongo_update_flags_upsert,
793 { "Upsert", "mongo.update.flags.upsert",
794 FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000001,
795 "If set, the database will insert the supplied object into the collection if no"
796 " matching document is found", HFILL }
798 { &hf_mongo_update_flags_multiupdate,
799 { "Multi Update", "mongo.update.flags.multiupdate",
800 FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000002,
801 "If set, the database will update all matching objects in the collection."
802 " Otherwise only updates first matching doc.", HFILL }
804 { &hf_mongo_selector,
805 { "Selector", "mongo.selector",
806 FT_NONE, BASE_NONE, NULL, 0x0,
807 "The query to select the document", HFILL }
809 { &hf_mongo_update,
810 { "Update", "mongo.update",
811 FT_NONE, BASE_NONE, NULL, 0x0,
812 "Specification of the update to perform", HFILL }
814 { &hf_mongo_insert_flags,
815 { "Insert Flags", "mongo.insert.flags",
816 FT_NONE, BASE_NONE, NULL, 0x0,
817 "Bit vector of insert options.", HFILL }
819 { &hf_mongo_insert_flags_continueonerror,
820 { "ContinueOnError", "mongo.insert.flags.continueonerror",
821 FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000001,
822 "If set, the database will not stop processing a bulk insert if one fails"
823 " (eg due to duplicate IDs)", HFILL }
825 { &hf_mongo_query_flags_tailablecursor,
826 { "Tailable Cursor", "mongo.query.flags.tailable_cursor",
827 FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000002,
828 "Tailable means cursor is not closed when the last data is retrieved", HFILL }
830 { &hf_mongo_query_flags_slaveok,
831 { "Slave OK", "mongo.query.flags.slave_ok",
832 FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000004,
833 "Allow query of replica slave", HFILL }
835 { &hf_mongo_query_flags_oplogreplay,
836 { "Op Log Reply", "mongo.query.flags.op_log_reply",
837 FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000008,
838 "Internal replication use only", HFILL }
840 { &hf_mongo_query_flags_nocursortimeout,
841 { "No Cursor Timeout", "mongo.query.flags.no_cursor_timeout",
842 FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000010,
843 "The server normally times out idle cursors after an inactivity period (10 minutes)"
844 " to prevent excess memory use. Set this option to prevent that", HFILL }
846 { &hf_mongo_query_flags_awaitdata,
847 { "AwaitData", "mongo.query.flags.awaitdata",
848 FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000020,
849 "If we are at the end of the data, block for a while rather than returning no data."
850 " After a timeout period, we do return as normal", HFILL }
852 { &hf_mongo_query_flags_exhaust,
853 { "Exhaust", "mongo.query.flags.exhaust",
854 FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000040,
855 "Stream the data down full blast in multiple more packages, on the assumption"
856 " that the client will fully read all data queried", HFILL }
858 { &hf_mongo_query_flags_partial,
859 { "Partial", "mongo.query.flags.partial",
860 FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000080,
861 "Get partial results from a mongos if some shards are down (instead of throwing an error)", HFILL }
863 { &hf_mongo_number_to_skip,
864 { "Number To Skip", "mongo.number_to_skip",
865 FT_INT32, BASE_DEC, NULL, 0x0,
866 "Number of documents in the skip", HFILL }
868 { &hf_mongo_number_to_return,
869 { "Number to Return", "mongo.number_to_return",
870 FT_INT32, BASE_DEC, NULL, 0x0,
871 "Number of documents in the return", HFILL }
873 { &hf_mongo_query,
874 { "Query", "mongo.query",
875 FT_NONE, BASE_NONE, NULL, 0x0,
876 "Query BSON Document", HFILL }
878 { &hf_mongo_return_field_selector,
879 { "Return Field Selector", "mongo.return_field_selector",
880 FT_NONE, BASE_NONE, NULL, 0x0,
881 "Return Field Selector BSON Document", HFILL }
883 { &hf_mongo_delete_flags,
884 { "Delete Flags", "mongo.delete.flags",
885 FT_NONE, BASE_NONE, NULL, 0x0,
886 "Bit vector of delete options.", HFILL }
888 { &hf_mongo_delete_flags_singleremove,
889 { "Single Remove", "mongo.delete.flags.singleremove",
890 FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000001,
891 "If set, the database will remove only the first matching document in the"
892 " collection. Otherwise all matching documents will be removed", HFILL }
894 { &hf_mongo_number_of_cursor_ids,
895 { "Number of Cursor IDS", "mongo.number_to_cursor_ids",
896 FT_INT32, BASE_DEC, NULL, 0x0,
897 "Number of cursorIDs in message", HFILL }
899 { &hf_mongo_elements,
900 { "Elements", "mongo.elements",
901 FT_NONE, BASE_NONE, NULL, 0x0,
902 "Document Elements", HFILL }
904 { &hf_mongo_element_name,
905 { "Element", "mongo.element.name",
906 FT_STRING, BASE_NONE, NULL, 0x0,
907 "Element Name", HFILL }
909 { &hf_mongo_element_type,
910 { "Type", "mongo.element.type",
911 FT_UINT8, BASE_HEX_DEC, VALS(element_type_vals), 0x0,
912 "Element Type", HFILL }
914 { &hf_mongo_element_length,
915 { "Length", "mongo.element.length",
916 FT_INT32, BASE_DEC, NULL, 0x0,
917 "Element Length", HFILL }
919 { &hf_mongo_element_value_boolean,
920 { "Value", "mongo.element.value.bool",
921 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
922 "Element Value", HFILL }
924 { &hf_mongo_element_value_int32,
925 { "Value", "mongo.element.value.int",
926 FT_INT32, BASE_DEC, NULL, 0x0,
927 "Element Value", HFILL }
929 { &hf_mongo_element_value_int64,
930 { "Value", "mongo.element.value.int64",
931 FT_INT64, BASE_DEC, NULL, 0x0,
932 "Element Value", HFILL }
934 { &hf_mongo_element_value_double,
935 { "Value", "mongo.element.value.double",
936 FT_DOUBLE, BASE_NONE, NULL, 0x0,
937 "Element Value", HFILL }
939 { &hf_mongo_element_value_string,
940 { "Value", "mongo.element.value.string",
941 FT_STRING, BASE_NONE, NULL, 0x0,
942 "Element Value", HFILL }
944 { &hf_mongo_element_value_string_length,
945 { "Length", "mongo.element.value.length",
946 FT_INT32, BASE_DEC, NULL, 0x0,
947 "Element Value Length", HFILL }
949 { &hf_mongo_element_value_binary,
950 { "Value", "mongo.element.value.bytes",
951 FT_BYTES, BASE_NONE, NULL, 0x0,
952 "Element Value", HFILL }
954 { &hf_mongo_element_value_binary_length,
955 { "Length", "mongo.element.value.length",
956 FT_INT32, BASE_DEC, NULL, 0x0,
957 "Binary Element Length", HFILL }
959 { &hf_mongo_element_value_regex_pattern,
960 { "Value", "mongo.element.value.regex.pattern",
961 FT_STRING, BASE_NONE, NULL, 0x0,
962 "Regex Pattern", HFILL }
964 { &hf_mongo_element_value_regex_options,
965 { "Value", "mongo.element.value.regex.options",
966 FT_STRING, BASE_NONE, NULL, 0x0,
967 "Regex Options", HFILL }
969 { &hf_mongo_element_value_objectid,
970 { "ObjectID", "mongo.element.value.objectid",
971 FT_BYTES, BASE_NONE, NULL, 0x0,
972 "ObjectID Value", HFILL }
974 { &hf_mongo_element_value_objectid_time,
975 { "ObjectID Time", "mongo.element.value.objectid.time",
976 FT_INT32, BASE_DEC, NULL, 0x0,
977 "ObjectID timestampt", HFILL }
979 { &hf_mongo_element_value_objectid_machine,
980 { "ObjectID Machine", "mongo.element.value.objectid.machine",
981 FT_UINT24, BASE_HEX, NULL, 0x0,
982 "ObjectID machine ID", HFILL }
984 { &hf_mongo_element_value_objectid_pid,
985 { "ObjectID PID", "mongo.element.value.objectid.pid",
986 FT_UINT16, BASE_DEC, NULL, 0x0,
987 "ObjectID process ID", HFILL }
989 { &hf_mongo_element_value_objectid_inc,
990 { "ObjectID inc", "mongo.element.value.objectid.inc",
991 FT_UINT24, BASE_DEC, NULL, 0x0,
992 "ObjectID increment", HFILL }
994 { &hf_mongo_element_value_db_ptr,
995 { "ObjectID", "mongo.element.value.db_ptr",
996 FT_BYTES, BASE_NONE, NULL, 0x0,
997 "DBPointer", HFILL }
999 { &hf_mongo_element_value_js_code,
1000 { "JavaScript code", "mongo.element.value.js_code",
1001 FT_NONE, BASE_NONE, NULL, 0x0,
1002 "JavaScript code to be evaluated", HFILL }
1004 { &hf_mongo_element_value_js_scope,
1005 { "JavaScript scope", "mongo.element.value.js_scope",
1006 FT_NONE, BASE_NONE, NULL, 0x0,
1007 "Scope document for JavaScript evaluation", HFILL }
1009 { &hf_mongo_unknown,
1010 { "Unknown", "mongo.unknown",
1011 FT_BYTES, BASE_NONE, NULL, 0x0,
1012 "Unknown Data type", HFILL }
1016 static gint *ett[] = {
1017 &ett_mongo,
1018 &ett_mongo_doc,
1019 &ett_mongo_elements,
1020 &ett_mongo_element,
1021 &ett_mongo_objectid,
1022 &ett_mongo_code,
1023 &ett_mongo_fcn,
1024 &ett_mongo_flags
1027 static ei_register_info ei[] = {
1028 { &ei_mongo_document_recursion_exceeded, { "mongo.document.recursion_exceeded", PI_MALFORMED, PI_ERROR, "BSON document recursion exceeds", EXPFILL }},
1029 { &ei_mongo_document_length_bad, { "mongo.document.length.bad", PI_MALFORMED, PI_ERROR, "BSON document length bad", EXPFILL }},
1030 { &ei_mongo_unknown, { "mongo.unknown.expert", PI_UNDECODED, PI_WARN, "Unknown Data (not interpreted)", EXPFILL }},
1033 proto_mongo = proto_register_protocol("Mongo Wire Protocol", "MONGO", "mongo");
1035 proto_register_field_array(proto_mongo, hf, array_length(hf));
1036 proto_register_subtree_array(ett, array_length(ett));
1037 expert_mongo = expert_register_protocol(proto_mongo);
1038 expert_register_field_array(expert_mongo, ei, array_length(ei));
1040 mongo_module = prefs_register_protocol(proto_mongo,
1041 proto_reg_handoff_mongo);
1043 prefs_register_uint_preference(mongo_module, "tcp.port", "MONGO TCP Port",
1044 "MONGO TCP port if other than the default",
1045 10, &global_mongo_tcp_port);
1049 void
1050 proto_reg_handoff_mongo(void)
1052 static gboolean initialized = FALSE;
1053 static dissector_handle_t mongo_handle;
1054 static int currentPort;
1056 if (!initialized) {
1058 mongo_handle = new_create_dissector_handle(dissect_mongo, proto_mongo);
1059 initialized = TRUE;
1060 } else {
1061 dissector_delete_uint("tcp.port", currentPort, mongo_handle);
1064 currentPort = global_mongo_tcp_port;
1066 dissector_add_uint("tcp.port", currentPort, mongo_handle);
1070 * Editor modelines
1072 * Local Variables:
1073 * c-basic-offset: 2
1074 * tab-width: 8
1075 * indent-tabs-mode: nil
1076 * End:
1078 * ex: set shiftwidth=2 tabstop=8 expandtab:
1079 * :indentSize=2:tabSize=8:noTabs=true: