Revert "Fixup: tvb_* -> tvb_captured"
[metze/wireshark/wip.git] / epan / dissectors / packet-mojito.c
1 /* packet-mojito.c
2  * Routines for Dissecting the Gnutella Mojito DHT Protocol
3  * http://limewire.negatis.com/index.php?title=Mojito_Message_Format
4  *
5  * Copyright (c) 2008 by Travis Dawson <travis.dawson@sprint.com>
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 #include "config.h"
27
28 #include <epan/packet.h>
29 #include <epan/prefs.h>
30 #include <epan/expert.h>
31
32 void proto_register_mojito(void);
33 void proto_reg_handoff_mojito(void);
34
35 #define MOJITO_HEADER_LENGTH    38
36
37 /* All the Defines for OpCodes */
38 #define MOJITO_PING_REQUEST                1
39 #define MOJITO_PING_RESPONSE               2
40 #define MOJITO_STORE_REQUEST               3
41 #define MOJITO_STORE_RESPONSE              4
42 #define MOJITO_FIND_NODE_REQUEST           5
43 #define MOJITO_FIND_NODE_RESPONSE          6
44 #define MOJITO_FIND_VALUE_REQUEST          7
45 #define MOJITO_FIND_VALUE_RESPONSE         8
46 #define MOJITO_STATS_REQUEST_DEPRECATED    9
47 #define MOJITO_STATS_RESPONSE_DEPRECATED  10
48
49 /* Initialize the protocol and registered fields */
50 static int proto_mojito = -1;
51
52 /* Start of fields */
53 static int hf_mojito_messageid = -1;
54 static int hf_mojito_fdhtmessage = -1;
55 static int hf_mojito_mjrversion = -1;
56 static int hf_mojito_mnrversion = -1;
57 static int hf_mojito_length = -1;
58 static int hf_mojito_opcode = -1;
59 static int hf_mojito_vendor = -1;
60 static int hf_mojito_origmjrversion = -1;
61 static int hf_mojito_origmnrversion = -1;
62 static int hf_mojito_kuid = -1;
63 static int hf_mojito_socketaddress_version = -1;
64 static int hf_mojito_socketaddress_ipv4 = -1;
65 static int hf_mojito_socketaddress_ipv6 = -1;
66 static int hf_mojito_socketaddress_port = -1;
67 static int hf_mojito_instanceid = -1;
68 static int hf_mojito_flags = -1;
69 static int hf_mojito_flags_shutdown = -1;
70 static int hf_mojito_flags_firewalled = -1;
71 static int hf_mojito_extendedlength = -1;
72 static int hf_mojito_kuidcount = -1;
73 static int hf_mojito_bigintegerlen = -1;
74 static int hf_mojito_bigintegerval = -1;
75 static int hf_mojito_dhtvaluetype = -1;
76 static int hf_mojito_sectokenlen = -1;
77 static int hf_mojito_sectoken = -1;
78 static int hf_mojito_contactcount = -1;
79 static int hf_mojito_contactvendor = -1;
80 static int hf_mojito_contactversion = -1;
81 static int hf_mojito_contactkuid = -1;
82 static int hf_mojito_dhtvaluecount = -1;
83 static int hf_mojito_dhtvalue_kuid = -1;
84 static int hf_mojito_target_kuid = -1;
85 static int hf_mojito_dhtvalue_valuetype = -1;
86 static int hf_mojito_dhtvalue_version = -1;
87 static int hf_mojito_dhtvalue_length = -1;
88 static int hf_mojito_dhtvalue_value = -1;
89 static int hf_mojito_bigint_value_one = -1;
90 static int hf_mojito_bigint_value_two = -1;
91 static int hf_mojito_bigint_value_three = -1;
92 static int hf_mojito_bigint_value_four = -1;
93 static int hf_mojito_storestatuscode_count = -1;
94 static int hf_mojito_storestatuscode_code = -1;
95 static int hf_mojito_storestatuscode_kuid = -1;
96 static int hf_mojito_storestatuscode_secondary_kuid = -1;
97 static int hf_mojito_requestload = -1;
98 #if 0
99 static int hf_mojito_startflag = -1;
100 static int hf_mojito_endflag = -1;
101 static int hf_mojito_priorityflag = -1;
102 #endif
103 static int hf_mojito_opcode_data = -1;
104
105 /* Initialize the subtree pointers */
106 static gint ett_mojito = -1;
107 static gint ett_mojito_header = -1;
108 static gint ett_mojito_header_version = -1;
109 static gint ett_mojito_contact = -1;
110 static gint ett_mojito_contact_version = -1;
111 static gint ett_mojito_socket_address = -1;
112 static gint ett_mojito_flags = -1;
113 static gint ett_mojito_bigint = -1;
114 static gint ett_mojito_opcode = -1;
115 static gint ett_mojito_dht_version = -1;
116 static gint ett_mojito_dht = -1;
117 static gint ett_mojito_status_code = -1;
118 static gint ett_mojito_kuids = -1;
119
120 static expert_field ei_mojito_socketaddress_unknown = EI_INIT;
121 static expert_field ei_mojito_bigint_unsupported = EI_INIT;
122
123 /* Preferences */
124 static int udp_mojito_port = 0;
125
126 typedef struct mojito_header_data {
127         guint8 opcode;
128         guint32 payloadlength;
129 } mojito_header_data_t;
130
131 /* Values for OPCode Flags */
132 static const value_string opcodeflags[] = {
133         { MOJITO_PING_REQUEST,              "PING REQUEST" },
134         { MOJITO_PING_RESPONSE,             "PING RESPONSE" },
135         { MOJITO_STORE_REQUEST,             "STORE REQUEST" },
136         { MOJITO_STORE_RESPONSE,            "STORE RESPONSE" },
137         { MOJITO_FIND_NODE_REQUEST,         "FIND NODE REQUEST" },
138         { MOJITO_FIND_NODE_RESPONSE,        "FIND NODE RESPONSE" },
139         { MOJITO_FIND_VALUE_REQUEST,        "FIND VALUE REQUEST" },
140         { MOJITO_FIND_VALUE_RESPONSE,       "FIND VALUE RESPONSE" },
141         { MOJITO_STATS_REQUEST_DEPRECATED,  "STATS REQUEST (DEPRECATED)" },
142         { MOJITO_STATS_RESPONSE_DEPRECATED, "STATS RESPONSE (DEPRECATED)" },
143         { 0, NULL }
144 };
145
146 static const value_string statuscodeflags[] = {
147         { 1, "OK" },
148         { 2, "Error" },
149         { 0, NULL }
150 };
151
152 #if 0
153 static const value_string vendorcodeflags[] = {
154         {  0, "MESSAGES_SUPPORTED" },
155         {  4, "HOPS_FLOW" },
156         {  5, "CRAWLER_PING" },
157         {  6, "CRAWLER_PONG" },
158         {  7, "UDP_CONNECT_BACK" },
159         {  8, "UDP_CONNECT_BACK_REDIR" },
160         {  9, "NGTH_MINUS_PAYLOAD" },
161         { 10, "CAPABILITIES" },
162         { 11, "LIME_ACK" },
163         { 12, "REPLY_NUMBER" },
164         { 13, "OOB_PROXYING_CONTROL" },
165         { 14, "GIVE_STATS" },
166         { 15, "STATISTICS" },
167         { 16, "SIMPP_REQ" },
168         { 17, "SIMPP" },
169         { 21, "PUSH_PROXY_REQ" },
170         { 22, "PUSH_PROXY_ACK" },
171         { 23, "UDP_HEAD_PING" },
172         { 24, "UDP_HEAD_PONG" },
173         { 25, "HEADER_UPDATE" },
174         { 26, "UPDATE_REQ" },
175         { 27, "UPDATE_RESP" },
176         { 28, "CONTENT_REQ" },
177         { 29, "CONTENT_RESP" },
178         { 30, "INSPECTION_REQ" },
179         { 31, "INSPECTION_RESP" },
180         { 32, "ADVANCED_TOGGLE" },
181         { 33, "DHT_CONTACTS" },
182
183         { 0, NULL }
184 };
185 #endif
186
187 static int
188 dissect_mojito_address(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
189                 int offset, const char *title)
190 {
191         int         offset_start;
192         guint8      socket_address_version;
193         proto_tree *socket_tree;
194         proto_item *socket_item;
195
196         offset_start = offset;
197
198         /* new subtree for socket address*/
199         socket_address_version = tvb_get_guint8(tvb, offset);
200         socket_item = proto_tree_add_text(tree, tvb, offset, 1, "%s", title);
201         socket_tree = proto_item_add_subtree(socket_item, ett_mojito_socket_address);
202
203         proto_tree_add_item(socket_tree, hf_mojito_socketaddress_version, tvb, offset, 1, ENC_NA);
204         offset += 1;
205
206         switch (socket_address_version)
207         {
208         case FT_IPv4_LEN: /* IPv4 */
209
210                 proto_tree_add_item(socket_tree, hf_mojito_socketaddress_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN);
211                 offset += 4;
212                 break;
213
214         case FT_IPv6_LEN: /* IPv6 */
215
216                 proto_tree_add_item(socket_tree, hf_mojito_socketaddress_ipv6, tvb, offset, 16, ENC_NA);
217                 offset += 16;
218                 break;
219
220         default: /* ABORT */
221                 expert_add_info(pinfo, socket_item, &ei_mojito_socketaddress_unknown);
222                 return 0;
223         }
224
225         proto_tree_add_item(socket_tree, hf_mojito_socketaddress_port, tvb, offset, 2, ENC_BIG_ENDIAN);
226         offset += 2;
227
228         proto_item_set_len(socket_item, offset - offset_start);
229
230         return offset;
231 }
232
233 static int
234 dissect_mojito_contact(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int contact_id)
235 {
236         int         offset_start;
237         proto_tree *contact_tree, *version_tree;
238         proto_item *contact_item, *version_item;
239
240         offset_start = offset;
241
242         if (contact_id > 0)
243         {
244                 contact_item = proto_tree_add_text(tree, tvb, offset, 1, "Contact #%d", contact_id);
245         }
246         else
247         {
248                 contact_item = proto_tree_add_text(tree, tvb, offset, 1, "Contact");
249         }
250         contact_tree = proto_item_add_subtree(contact_item, ett_mojito_contact);
251
252         proto_tree_add_item(contact_tree, hf_mojito_contactvendor, tvb, offset, 4, ENC_ASCII|ENC_NA);
253         offset += 4;
254
255         version_item = proto_tree_add_item(contact_tree, hf_mojito_contactversion, tvb, offset, 2, ENC_BIG_ENDIAN);
256         version_tree = proto_item_add_subtree(version_item, ett_mojito_contact_version);
257         proto_tree_add_item(version_tree, hf_mojito_mjrversion, tvb, offset, 1, ENC_BIG_ENDIAN);
258         offset += 1;
259         proto_tree_add_item(version_tree, hf_mojito_mnrversion, tvb, offset, 1, ENC_BIG_ENDIAN);
260         offset += 1;
261
262         proto_tree_add_item(contact_tree, hf_mojito_contactkuid, tvb, offset, 20, ENC_NA);
263         offset += 20;
264
265         offset = dissect_mojito_address(tvb, pinfo, contact_tree, offset, "Socket Address");
266
267         if (offset == 0)
268         {
269                 return 0;
270         }
271
272         proto_item_set_len(contact_item, offset - offset_start);
273
274         return offset - offset_start;
275 }
276
277 static int
278 dissect_mojito_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
279                       int offset, mojito_header_data_t* header_data)
280 {
281         proto_tree *header_tree, *version_tree, *contact_tree, *flag_tree;
282         proto_item *header_item, *version_item, *contact_item, *flag_item;
283         int         start_offset = offset;
284         int         contact_start_offset;
285
286         header_item = proto_tree_add_text(tree, tvb, offset, 61, "Gnutella Header");
287         header_tree = proto_item_add_subtree(header_item, ett_mojito_header);
288
289         proto_tree_add_item(header_tree, hf_mojito_messageid, tvb, offset, 16, ENC_NA);
290         offset += 16;
291
292         proto_tree_add_item(header_tree, hf_mojito_fdhtmessage, tvb, offset, 1, ENC_BIG_ENDIAN);
293         offset += 1;
294
295         version_item = proto_tree_add_text(header_tree, tvb, offset, 2, "Version");
296         version_tree = proto_item_add_subtree(version_item, ett_mojito_header_version);
297
298         proto_tree_add_item(version_tree, hf_mojito_mjrversion, tvb, offset, 1, ENC_BIG_ENDIAN);
299         offset += 1;
300         proto_tree_add_item(version_tree, hf_mojito_mnrversion, tvb, offset, 1, ENC_BIG_ENDIAN);
301         offset += 1;
302
303         /* Payload Length : in Little Endian */
304         header_data->payloadlength = tvb_get_letohl(tvb, offset);
305         proto_tree_add_item(header_tree, hf_mojito_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
306         offset += 4;
307
308         header_data->opcode = tvb_get_guint8(tvb, offset);
309         col_add_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_const(header_data->opcode, opcodeflags, "Unknown"));
310         proto_tree_add_item(header_tree, hf_mojito_opcode, tvb, offset, 1, ENC_BIG_ENDIAN);
311         offset += 1;
312
313         contact_start_offset = offset;
314         contact_item = proto_tree_add_text(header_tree, tvb, offset, 35, "Originating Contact");
315         contact_tree = proto_item_add_subtree(contact_item, ett_mojito_contact);
316
317         proto_tree_add_item(contact_tree, hf_mojito_vendor, tvb, offset, 4, ENC_ASCII|ENC_NA);
318         offset += 4;
319
320         version_item = proto_tree_add_text(contact_tree, tvb, offset, 2, "Contact Version");
321         version_tree = proto_item_add_subtree(version_item, ett_mojito_contact_version);
322
323         proto_tree_add_item(version_tree, hf_mojito_origmjrversion, tvb, offset, 1, ENC_BIG_ENDIAN);
324         offset += 1;
325         proto_tree_add_item(version_tree, hf_mojito_origmnrversion, tvb, offset, 1, ENC_BIG_ENDIAN);
326         offset += 1;
327
328         proto_tree_add_item(contact_tree, hf_mojito_kuid, tvb, offset, 20, ENC_NA);
329         offset += 20;
330
331         offset = dissect_mojito_address(tvb, pinfo, contact_tree, offset, "Socket Address");
332
333         if (offset == 0)
334         {
335                 return 0;
336         }
337
338         proto_item_set_len(contact_item, offset - contact_start_offset);
339
340         proto_tree_add_item(header_tree, hf_mojito_instanceid, tvb, offset, 1, ENC_BIG_ENDIAN);
341         offset += 1;
342
343         /*Flags*/
344         flag_item = proto_tree_add_item(header_tree, hf_mojito_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
345         flag_tree = proto_item_add_subtree(flag_item, ett_mojito_flags);
346         proto_tree_add_item(flag_tree, hf_mojito_flags_shutdown, tvb, offset, 1, ENC_BIG_ENDIAN);
347         proto_tree_add_item(flag_tree, hf_mojito_flags_firewalled, tvb, offset, 1, ENC_BIG_ENDIAN);
348         offset += 1;
349
350         proto_tree_add_item(header_tree, hf_mojito_extendedlength, tvb, offset, 2, ENC_BIG_ENDIAN);
351         offset += 2;
352
353         proto_item_set_len(header_item, offset-start_offset);
354         return offset;
355 }
356
357 static void
358 dissect_mojito_ping_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
359 {
360         guint8      bigintlen;
361         proto_tree *bigint_tree;
362         proto_item *bigint_item;
363
364         offset = dissect_mojito_address(tvb, pinfo, tree,
365                         offset, "Requester's External Socket Address");
366
367         if (offset == 0)
368         {
369                 return;
370         }
371
372         /* BigInt subtree */
373         bigintlen = tvb_get_guint8(tvb, offset);
374         bigint_item = proto_tree_add_text(tree, tvb, offset, bigintlen + 1 , "Estimated DHT size");
375         bigint_tree = proto_item_add_subtree(bigint_item, ett_mojito_bigint);
376
377         proto_tree_add_item(bigint_tree, hf_mojito_bigintegerlen, tvb, offset, 1, ENC_BIG_ENDIAN);
378         offset += 1;
379
380         switch (bigintlen)
381         {
382         case 1: /* 1 byte */
383                 proto_tree_add_item(bigint_tree, hf_mojito_bigint_value_one, tvb, offset, bigintlen, ENC_BIG_ENDIAN);
384                 break;
385
386         case 2: /* 2 byte */
387                 proto_tree_add_item(bigint_tree, hf_mojito_bigint_value_two, tvb, offset, bigintlen, ENC_BIG_ENDIAN);
388                 break;
389
390         case 3: /* 3 byte */
391                 proto_tree_add_item(bigint_tree, hf_mojito_bigint_value_three, tvb, offset, bigintlen, ENC_BIG_ENDIAN);
392                 break;
393
394         case 4: /* 4 byte */
395                 proto_tree_add_item(bigint_tree, hf_mojito_bigint_value_four, tvb, offset, bigintlen, ENC_BIG_ENDIAN);
396                 break;
397         default: /* ABORT */
398                 expert_add_info(pinfo, bigint_item, &ei_mojito_bigint_unsupported);
399                 return;
400         }
401
402         /* BigInt Value */
403         proto_tree_add_item(bigint_tree, hf_mojito_bigintegerval, tvb, offset, bigintlen, ENC_NA);
404 }
405
406 static void
407 dissect_mojito_store_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
408 {
409         proto_tree *dht_tree, *version_tree;
410         proto_item *dht_item, *version_item;
411         guint8      ii, contactcount;
412         guint8      sectokenlen = tvb_get_guint8(tvb, offset);
413         guint16     dhtvaluelength;
414         int         contact_offset, start_offset;
415
416         proto_tree_add_item(tree, hf_mojito_sectokenlen, tvb, offset, 1, ENC_BIG_ENDIAN);
417         offset += 1;
418
419         proto_tree_add_item(tree, hf_mojito_sectoken, tvb, offset, sectokenlen, ENC_NA);
420         offset += sectokenlen;
421
422         /* Contact count */
423         proto_tree_add_item(tree, hf_mojito_dhtvaluecount, tvb, offset, 1, ENC_BIG_ENDIAN);
424         contactcount = tvb_get_guint8(tvb, offset);
425         offset += 1;
426
427         /* For each Contact, display the info */
428         for (ii = 0; ii < contactcount; ii++)
429         {
430                 dht_item = proto_tree_add_text(tree, tvb, offset, 1, "DHTValue #%d", ii+1);
431                 dht_tree = proto_item_add_subtree(dht_item, ett_mojito_dht);
432                 start_offset = offset;
433                 contact_offset = dissect_mojito_contact(tvb, pinfo, dht_tree, offset, -1);
434                 if (contact_offset == 0)
435                         return;
436                 offset += contact_offset;
437
438                 proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_kuid, tvb, offset, 20, ENC_NA);
439                 offset += 20;
440
441                 proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_valuetype, tvb, offset, 4, ENC_ASCII|ENC_NA);
442                 offset += 4;
443
444                 /* Version */
445                 version_item = proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_version, tvb, offset, 2, ENC_BIG_ENDIAN);
446                 version_tree = proto_item_add_subtree(version_item, ett_mojito_dht_version);
447
448                 proto_tree_add_item(version_tree, hf_mojito_mjrversion, tvb, offset, 1, ENC_BIG_ENDIAN);
449                 offset += 1;
450                 proto_tree_add_item(version_tree, hf_mojito_mnrversion, tvb, offset, 1, ENC_BIG_ENDIAN);
451                 offset += 1;
452
453                 dhtvaluelength = tvb_get_ntohs(tvb, offset);
454                 proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_length, tvb, offset, 2, ENC_BIG_ENDIAN);
455                 offset += 2;
456
457                 proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_value, tvb, offset, dhtvaluelength, ENC_ASCII|ENC_NA);
458                 offset += dhtvaluelength;
459
460                 proto_item_set_len(dht_item, offset-start_offset);
461         }
462 }
463
464 static void
465 dissect_mojito_store_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
466 {
467         proto_tree *sc_tree;
468         proto_item *sc_item;
469         guint8      ii, contactcount = tvb_get_guint8(tvb, offset);
470         guint16     dhtvaluelength;
471         int         start_offset;
472
473         proto_tree_add_item(tree, hf_mojito_storestatuscode_count, tvb, offset, 1, ENC_BIG_ENDIAN);
474         offset += 1;
475
476         /* For each Contact, display the info */
477         for (ii = 0; ii < contactcount; ii++)
478         {
479                 sc_item = proto_tree_add_text(tree, tvb, offset, 23, "Status Code %d", ii+1);
480                 sc_tree = proto_item_add_subtree(sc_item, ett_mojito_status_code);
481
482                 start_offset = offset;
483
484                 /*Primary KUID */
485                 proto_tree_add_item(sc_tree, hf_mojito_storestatuscode_kuid, tvb, offset, 20, ENC_NA);
486                 offset += 20;
487
488                 if (tvb_reported_length_remaining(tvb, offset+3) > 0)
489                 {
490                         /* Must be a secondard KUID */
491                         proto_tree_add_item(sc_tree, hf_mojito_storestatuscode_secondary_kuid, tvb, offset, 20, ENC_NA);
492                         offset += 20;
493                 }
494
495                 proto_tree_add_item(sc_tree, hf_mojito_storestatuscode_code, tvb, offset, 2, ENC_BIG_ENDIAN);
496                 offset += 2;
497
498                 dhtvaluelength = tvb_get_ntohs(tvb, offset);
499                 proto_tree_add_item(sc_tree, hf_mojito_dhtvalue_length, tvb, offset, 2, ENC_BIG_ENDIAN);
500                 offset += 2;
501
502                 proto_tree_add_item(sc_tree, hf_mojito_dhtvalue_value, tvb, offset, dhtvaluelength, ENC_ASCII|ENC_NA);
503                 offset += dhtvaluelength;
504
505                 proto_item_set_len(sc_item, offset-start_offset);
506         }
507 }
508
509 static void
510 dissect_mojito_find_node_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
511 {
512         guint8 ii, contactcount;
513         guint8 sectokenlen = tvb_get_guint8(tvb, offset);
514         int    contact_offset;
515
516         proto_tree_add_item(tree, hf_mojito_sectokenlen, tvb, offset, 1, ENC_BIG_ENDIAN);
517         offset += 1;
518
519         proto_tree_add_item(tree, hf_mojito_sectoken, tvb, offset, sectokenlen, ENC_NA);
520         offset += sectokenlen;
521
522         contactcount = tvb_get_guint8(tvb, offset);
523         proto_tree_add_item(tree, hf_mojito_contactcount, tvb, offset, 1, ENC_BIG_ENDIAN);
524         offset += 1;
525
526         /* For each Contact, display the info */
527         for (ii = 0; ii < contactcount; ii++)
528         {
529                 contact_offset = dissect_mojito_contact(tvb, pinfo, tree, offset, ii+1);
530                 if (contact_offset == 0)
531                         return;
532                 offset += contact_offset;
533         }
534 }
535
536 static void
537 dissect_mojito_find_value_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
538 {
539         proto_tree *kuid_tree;
540         proto_item *kuid_item;
541         guint8      i, kuidcount;
542
543         if (!tree)
544                 return;
545
546         proto_tree_add_item(tree, hf_mojito_target_kuid, tvb, offset, 20, ENC_NA);
547         offset += 20;
548
549         kuidcount = tvb_get_guint8(tvb, offset);
550
551         kuid_item = proto_tree_add_text(tree, tvb, offset, (20 * kuidcount) + 1 , "Secondary KUID\'s");
552         kuid_tree = proto_item_add_subtree(kuid_item, ett_mojito_kuids);
553
554         proto_tree_add_item(kuid_tree, hf_mojito_kuidcount, tvb, offset, 1, ENC_BIG_ENDIAN);
555         offset += 1;
556
557         /* All the Secondary KUID's */
558         for (i = 0; i < kuidcount; i++)
559         {
560                 proto_tree_add_item(kuid_tree, hf_mojito_kuid, tvb, offset, 20, ENC_NA);
561                 offset += 20;
562         }
563
564         proto_tree_add_item(tree, hf_mojito_dhtvaluetype, tvb, offset, 4, ENC_ASCII|ENC_NA);
565         /*offset += 4;*/
566 }
567
568 static void
569 dissect_mojito_find_value_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
570 {
571         proto_tree *dht_tree, *version_tree, *kuid_tree;
572         proto_item *dht_item, *version_item, *kuid_item;
573         guint16     dhtvaluelength;
574         int         contact_offset, start_offset;
575         guint8      ii, dhtvaluescount, kuidcount;
576
577         proto_tree_add_item(tree, hf_mojito_requestload, tvb, offset, 4, ENC_BIG_ENDIAN);
578         offset += 4;
579
580         dhtvaluescount = tvb_get_guint8(tvb, offset);
581         proto_tree_add_item(tree, hf_mojito_dhtvaluecount, tvb, offset, 1, ENC_BIG_ENDIAN);
582         offset += 1;
583
584         /* For each Contact, display the info */
585         for (ii = 0; ii < dhtvaluescount; ii++)
586         {
587                 dht_item = proto_tree_add_text(tree, tvb, offset, 1, "DHTValue #%d", ii+1);
588                 dht_tree = proto_item_add_subtree(dht_item, ett_mojito_dht);
589                 start_offset = offset;
590                 contact_offset = dissect_mojito_contact(tvb, pinfo, dht_tree, offset, -1);
591                 if (contact_offset == 0)
592                         return;
593
594                 offset += contact_offset;
595
596                 proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_kuid, tvb, offset, 20, ENC_NA);
597                 offset += 20;
598
599                 proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_valuetype, tvb, offset, 4, ENC_ASCII|ENC_NA);
600                 offset += 4;
601
602                 /* Version */
603                 version_item = proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_version, tvb, offset, 2, ENC_BIG_ENDIAN);
604                 version_tree = proto_item_add_subtree(version_item, ett_mojito_dht_version);
605
606                 proto_tree_add_item(version_tree, hf_mojito_mjrversion, tvb, offset, 1, ENC_BIG_ENDIAN);
607                 offset += 1;
608                 proto_tree_add_item(version_tree, hf_mojito_mnrversion, tvb, offset, 1, ENC_BIG_ENDIAN);
609                 offset += 1;
610
611                 /* Length */
612                 dhtvaluelength = tvb_get_ntohs(tvb, offset);
613                 proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_length, tvb, offset, 2, ENC_BIG_ENDIAN);
614                 offset += 2;
615
616                 /* Value */
617                 proto_tree_add_item(dht_tree, hf_mojito_dhtvalue_value, tvb, offset, dhtvaluelength, ENC_ASCII|ENC_NA);
618                 offset += dhtvaluelength;
619
620                 proto_item_set_len(dht_item, offset-start_offset);
621         }
622
623         /*KUID Count */
624         kuidcount = tvb_get_guint8(tvb, offset);
625         kuid_item = proto_tree_add_text(tree, tvb, offset, (20 * kuidcount) + 1 , "Secondary KUID\'s");
626         kuid_tree = proto_item_add_subtree(kuid_item, ett_mojito_kuids);
627         proto_tree_add_item(kuid_tree, hf_mojito_kuidcount, tvb, offset, 1, ENC_BIG_ENDIAN);
628         offset += 1;
629
630         /* All the Secondary KUID's */
631         for (ii = 0; ii < kuidcount; ii++)
632         {
633                 proto_tree_add_item(kuid_tree, hf_mojito_kuid, tvb, offset, 20, ENC_NA);
634                 offset += 20;
635         }
636 }
637
638 static int
639 dissect_mojito(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
640 {
641         proto_tree           *mojito_tree, *opcode_tree;
642         proto_item           *ti, *opcode_item;
643         mojito_header_data_t  header_data;
644         gint                  offset = 0;
645
646         col_set_str(pinfo->cinfo, COL_PROTOCOL, "Mojito");
647         col_clear(pinfo->cinfo, COL_INFO);
648
649         /* Add a new item to the tree */
650         ti = proto_tree_add_item(tree, proto_mojito, tvb, 0, -1, ENC_NA);
651         mojito_tree = proto_item_add_subtree(ti, ett_mojito);
652
653         offset = dissect_mojito_header(tvb, pinfo, mojito_tree, offset, &header_data);
654         if (offset == 0) /* Some error occurred */
655                 return 0;
656
657         opcode_item = proto_tree_add_text(mojito_tree, tvb,
658                                           offset, header_data.payloadlength - MOJITO_HEADER_LENGTH,
659                                           "Opcode specific data (%s)",
660                                           val_to_str_const(header_data.opcode, opcodeflags, "Unknown"));
661         opcode_tree = proto_item_add_subtree(opcode_item, ett_mojito_opcode);
662
663         /* Now use the opcode to figure out what to do next */
664         switch (header_data.opcode)
665         {
666         case MOJITO_PING_RESPONSE: /* PING RESPONSE */
667                 dissect_mojito_ping_response(tvb, pinfo, opcode_tree, offset);
668                 break;
669
670         case MOJITO_STORE_REQUEST: /* STORE REQUEST */
671                 dissect_mojito_store_request(tvb, pinfo, opcode_tree, offset);
672                 break;
673
674         case MOJITO_STORE_RESPONSE: /* STORE RESPONSE */
675                 dissect_mojito_store_response(tvb, pinfo, opcode_tree, offset);
676                 break;
677
678         case MOJITO_FIND_NODE_REQUEST: /* FIND NODE REQUEST */
679                 proto_tree_add_item(opcode_tree, hf_mojito_target_kuid, tvb, offset, 20, ENC_NA);
680                 break;
681
682         case MOJITO_FIND_NODE_RESPONSE: /* FIND NODE RESPONSE */
683                 dissect_mojito_find_node_response(tvb, pinfo, opcode_tree, offset);
684                 break;
685
686         case MOJITO_FIND_VALUE_REQUEST: /* FIND VALUE REQUEST */
687                 dissect_mojito_find_value_request(tvb, pinfo, opcode_tree, offset);
688                 break;
689
690         case MOJITO_FIND_VALUE_RESPONSE: /* FIND VALUE RESPONSE */
691                 dissect_mojito_find_value_response(tvb, pinfo, opcode_tree, offset);
692                 break;
693
694         case MOJITO_PING_REQUEST: /* PING REQUEST */
695         case MOJITO_STATS_REQUEST_DEPRECATED: /* STATS REQUEST (DEPRECATED) */
696         case MOJITO_STATS_RESPONSE_DEPRECATED: /* STATS RESPONSE (DEPRECATED) */
697         default:
698                 if (header_data.payloadlength - MOJITO_HEADER_LENGTH > 0)
699                         proto_tree_add_item(opcode_tree, hf_mojito_opcode_data, tvb,
700                                             offset, header_data.payloadlength - MOJITO_HEADER_LENGTH, ENC_NA);
701                 break;
702         }
703
704         return tvb_length(tvb);
705 }
706
707 static gboolean dissect_mojito_heuristic (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
708 {
709         /*
710           Test the overall length to make sure it's at least 61 bytes (the header)
711           Test to make sure that it's of type 44 (mojito)
712           Test to make sure that the length field is there and correct
713           (tvb_get_letohl(tvb, 20) + 23) == tvb_length(tvb)
714         */
715         if ((tvb_length(tvb) >= 60) &&
716             (tvb_get_guint8(tvb, 16) == 68) &&
717             ((tvb_get_letohl(tvb, 19) + 23) == tvb_reported_length(tvb)))
718         {
719                 dissect_mojito(tvb, pinfo, tree, NULL);
720                 return TRUE;
721         }
722
723         return FALSE;
724 }
725
726 /* Register the mojito dissector */
727 void
728 proto_register_mojito(void)
729 {
730         module_t *mojito_module;
731         expert_module_t* expert_mojito;
732
733         static hf_register_info hf[] = {
734                 { &hf_mojito_dhtvaluecount,
735                   { "DHTValue Count", "mojito.dhtvaluecount",
736                     FT_UINT8, BASE_DEC,
737                     NULL, 0x0,
738                     NULL, HFILL }
739                 },
740                 { &hf_mojito_messageid,
741                   { "Message ID", "mojito.messageid",
742                     FT_BYTES, BASE_NONE,
743                     NULL, 0x0,
744                     NULL, HFILL }
745                 },
746                 { &hf_mojito_requestload,
747                   { "Request Load", "mojito.requestload",
748                     FT_UINT32, BASE_DEC,
749                     NULL, 0x0,
750                     NULL, HFILL }
751                 },
752                 { &hf_mojito_fdhtmessage,
753                   { "FDHTMessage", "mojito.fdhtmessage",
754                     FT_UINT8, BASE_HEX,
755                     NULL, 0x0,
756                     NULL, HFILL }
757                 },
758                 { &hf_mojito_mjrversion,
759                   { "Major Version", "mojito.majorversion",
760                     FT_UINT8, BASE_DEC,
761                     NULL, 0x0,
762                     NULL, HFILL }
763                 },
764                 { &hf_mojito_mnrversion,
765                   { "Minor Version", "mojito.minorversion",
766                     FT_UINT8, BASE_DEC,
767                     NULL, 0x0,
768                     NULL, HFILL }
769                 },
770                 { &hf_mojito_length,
771                   { "Payload Length", "mojito.payloadlength",
772                     FT_UINT32, BASE_DEC,
773                     NULL, 0x0,
774                     NULL, HFILL }
775                 },
776                 { &hf_mojito_opcode,
777                   { "OPCode", "mojito.opcode",
778                     FT_UINT8, BASE_DEC,
779                     VALS(opcodeflags), 0x0,
780                     NULL, HFILL }
781                 },
782                 { &hf_mojito_vendor,
783                   { "Vendor", "mojito.vendor",
784                     FT_STRING, BASE_NONE,
785                     NULL, 0x0,
786                     NULL, HFILL }
787                 },
788                 { &hf_mojito_origmjrversion,
789                   { "Major Version", "mojito.majorversion",
790                     FT_UINT8, BASE_DEC,
791                     NULL, 0x0,
792                     NULL, HFILL }
793                 },
794                 { &hf_mojito_origmnrversion,
795                   { "Minor Version", "mojito.minorversion",
796                     FT_UINT8, BASE_DEC,
797                     NULL, 0x0,
798                     NULL, HFILL }
799                 },
800                 { &hf_mojito_kuid,
801                   { "Kademlia Unique ID (KUID)", "mojito.kuid",
802                     FT_BYTES, BASE_NONE,
803                     NULL, 0x0,
804                     NULL, HFILL }
805                 },
806                 { &hf_mojito_socketaddress_version,
807                   { "IP Version", "mojito.socketaddressversion",
808                     FT_UINT8, BASE_DEC,
809                     NULL, 0x0,
810                     NULL, HFILL }
811                 },
812                 { &hf_mojito_socketaddress_ipv4,
813                   { "IP Address", "mojito.socketaddressipv4",
814                     FT_IPv4, BASE_NONE,
815                     NULL, 0x0,
816                     NULL, HFILL }
817                 },
818                 { &hf_mojito_socketaddress_ipv6,
819                   { "IP Address", "mojito.socketaddressipv6",
820                     FT_IPv6, BASE_NONE,
821                     NULL, 0x0,
822                     NULL, HFILL }
823                 },
824                 { &hf_mojito_socketaddress_port,
825                   { "IP Port", "mojito.socketaddressport",
826                     FT_UINT16, BASE_DEC,
827                     NULL, 0x0,
828                     NULL, HFILL }
829                 },
830                 { &hf_mojito_instanceid,
831                   { "Instance ID", "mojito.instanceid",
832                     FT_UINT8, BASE_DEC,
833                     NULL, 0x0,
834                     NULL, HFILL }
835                 },
836                 { &hf_mojito_flags,
837                   { "Flags", "mojito.flags",
838                     FT_UINT8, BASE_HEX,
839                     NULL, 0x0,
840                     NULL, HFILL }
841                 },
842                 { &hf_mojito_flags_shutdown,
843                   { "SHUTDOWN", "mojito.shutdownflag",
844                     FT_BOOLEAN, 8,
845                     NULL, 2,
846                     NULL, HFILL }
847                 },
848                 { &hf_mojito_flags_firewalled,
849                   { "Firewalled", "mojito.firewalledflag",
850                     FT_BOOLEAN, 8,
851                     NULL, 1,
852                     NULL, HFILL }
853                 },
854                 { &hf_mojito_extendedlength,
855                   { "Extended Length", "mojito.extlength",
856                     FT_UINT16, BASE_DEC,
857                     NULL, 0x0,
858                     NULL, HFILL }
859                 },
860                 { &hf_mojito_kuidcount,
861                   { "Secondary KUID Count", "mojito.kuidcount",
862                     FT_UINT8, BASE_DEC,
863                     NULL, 0x0,
864                     NULL, HFILL }
865                 },
866                 { &hf_mojito_dhtvaluetype,
867                   { "DHT Value Type", "mojito.dhtvaluetype",
868                     FT_STRING, BASE_NONE,
869                     NULL, 0x0,
870                     NULL, HFILL }
871                 },
872                 { &hf_mojito_bigintegerlen,
873                   { "Big Integer Length", "mojito.bigintegerlen",
874                     FT_UINT8, BASE_DEC,
875                     NULL, 0x0,
876                     NULL, HFILL }
877                 },
878                 { &hf_mojito_bigintegerval,
879                   { "Big Integer HEX Value", "mojito.bigintegerhexval",
880                     FT_BYTES, BASE_NONE,
881                     NULL, 0x0,
882                     NULL, HFILL }
883                 },
884                 { &hf_mojito_sectokenlen,
885                   { "Security Token Length", "mojito.sectokenlen",
886                     FT_UINT8, BASE_DEC,
887                     NULL, 0x0,
888                     NULL, HFILL }
889                 },
890                 { &hf_mojito_sectoken,
891                   { "Security Token", "mojito.sectoken",
892                     FT_BYTES, BASE_NONE,
893                     NULL, 0x0,
894                     NULL, HFILL }
895                 },
896                 { &hf_mojito_contactcount,
897                   { "Contact Count", "mojito.contactcount",
898                     FT_UINT8, BASE_DEC,
899                     NULL, 0x0,
900                     NULL, HFILL }
901                 },
902                 { &hf_mojito_contactvendor,
903                   { "Vendor", "mojito.contactvendor",
904                     FT_STRING, BASE_NONE,
905                     NULL, 0x0,
906                     NULL, HFILL }
907                 },
908                 { &hf_mojito_contactversion,
909                   { "Contact Version", "mojito.contactversion",
910                     FT_UINT16, BASE_DEC,
911                     NULL, 0x0,
912                     NULL, HFILL }
913                 },
914                 { &hf_mojito_contactkuid,
915                   { "KUID of the Contact", "mojito.contactkuid",
916                     FT_BYTES, BASE_NONE,
917                     NULL, 0x0,
918                     NULL, HFILL }
919                 },
920                 { &hf_mojito_dhtvalue_valuetype,
921                   { "DHTValue ValueType", "mojito.dhtvaluevaluetype",
922                     FT_STRING, BASE_NONE,
923                     NULL, 0x0,
924                     NULL, HFILL }
925                 },
926                 { &hf_mojito_dhtvalue_version,
927                   { "DHTValue Version", "mojito.dhtvalueversion",
928                     FT_UINT16, BASE_DEC,
929                     NULL, 0x0,
930                     NULL, HFILL }
931                 },
932                 { &hf_mojito_dhtvalue_length,
933                   { "DHTValue Length", "mojito.dhtvaluelength",
934                     FT_UINT16, BASE_DEC,
935                     NULL, 0x0,
936                     NULL, HFILL }
937                 },
938                 { &hf_mojito_dhtvalue_value,
939                   { "DHTValue", "mojito.dhtvaluehexvalue",
940                     FT_STRING, BASE_NONE,
941                     NULL, 0x0,
942                     NULL, HFILL }
943                 },
944                 { &hf_mojito_bigint_value_one,
945                   { "Big Integer DEC Value", "mojito.bigintegerval",
946                     FT_UINT8, BASE_DEC,
947                     NULL, 0x0,
948                     NULL, HFILL }
949                 },
950                 { &hf_mojito_bigint_value_two,
951                   { "Big Integer DEC Value", "mojito.bigintegerval",
952                     FT_UINT16, BASE_DEC,
953                     NULL, 0x0,
954                     NULL, HFILL }
955                 },
956                 { &hf_mojito_bigint_value_three,
957                   { "Big Integer DEC Value", "mojito.bigintegerval",
958                     FT_UINT24, BASE_DEC,
959                     NULL, 0x0,
960                     NULL, HFILL }
961                 },
962                 { &hf_mojito_bigint_value_four,
963                   { "Big Integer DEC Value", "mojito.bigintegerval",
964                     FT_UINT32, BASE_DEC,
965                     NULL, 0x0,
966                     NULL, HFILL }
967                 },
968                 { &hf_mojito_dhtvalue_kuid,
969                   { "Kademlia Unique ID (KUID)", "mojito.kuid",
970                     FT_BYTES, BASE_NONE,
971                     NULL, 0x0,
972                     NULL, HFILL }
973                 },
974                 { &hf_mojito_target_kuid,
975                   { "Target Kademlia Unique ID (KUID)", "mojito.kuid",
976                     FT_BYTES, BASE_NONE,
977                     NULL, 0x0,
978                     NULL, HFILL }
979                 },
980                 { &hf_mojito_storestatuscode_count,
981                   { "Status Code Count", "mojito.statuscodecount",
982                     FT_UINT8, BASE_DEC,
983                     NULL, 0x0,
984                     NULL, HFILL }
985                 },
986                 { &hf_mojito_storestatuscode_code,
987                   { "StatusCode", "mojito.statuscodecount",
988                     FT_UINT16, BASE_DEC,
989                     VALS(statuscodeflags), 0x0,
990                     NULL, HFILL }
991                 },
992                 { &hf_mojito_storestatuscode_kuid,
993                   { "Primary KUID of the Status Code", "mojito.statuscodekuid",
994                     FT_BYTES, BASE_NONE,
995                     NULL, 0x0,
996                     NULL, HFILL }
997                 },
998                 { &hf_mojito_storestatuscode_secondary_kuid,
999                   { "Secondary KUID of the Status Code", "mojito.statuscodesecondarykuid",
1000                     FT_BYTES, BASE_NONE,
1001                     NULL, 0x0,
1002                     NULL, HFILL }
1003                 },
1004                 { &hf_mojito_opcode_data,
1005                   { "Data", "mojito.opcode.data",
1006                     FT_BYTES, BASE_NONE,
1007                     NULL, 0x0,
1008                     NULL, HFILL }
1009                 }
1010         };
1011
1012         /* Setup protocol subtree array */
1013         static gint *ett[] = {
1014                 &ett_mojito,
1015                 &ett_mojito_header,
1016                 &ett_mojito_header_version,
1017                 &ett_mojito_contact,
1018                 &ett_mojito_contact_version,
1019                 &ett_mojito_socket_address,
1020                 &ett_mojito_flags,
1021                 &ett_mojito_bigint,
1022                 &ett_mojito_opcode,
1023                 &ett_mojito_dht_version,
1024                 &ett_mojito_dht,
1025                 &ett_mojito_status_code,
1026                 &ett_mojito_kuids
1027         };
1028
1029         static ei_register_info ei[] = {
1030                 { &ei_mojito_socketaddress_unknown, { "mojito.socketaddress.unknown", PI_PROTOCOL, PI_ERROR, "Unsupported Socket Address Type", EXPFILL }},
1031                 { &ei_mojito_bigint_unsupported, { "mojito.bigint.unsupported", PI_PROTOCOL, PI_ERROR, "Unsupported BigInt length", EXPFILL }},
1032         };
1033
1034         proto_mojito = proto_register_protocol("Mojito DHT", "Mojito", "mojito");
1035
1036         proto_register_field_array(proto_mojito, hf, array_length(hf));
1037         proto_register_subtree_array(ett, array_length(ett));
1038         expert_mojito = expert_register_protocol(proto_mojito);
1039         expert_register_field_array(expert_mojito, ei, array_length(ei));
1040
1041         /* Set the Prefs */
1042         mojito_module = prefs_register_protocol(proto_mojito, NULL);
1043
1044         prefs_register_uint_preference(mojito_module,
1045                                        "udp.port",
1046                                        "Mojito UDP Port",
1047                                        "Mojito UDP Port",
1048                                        10,
1049                                        &udp_mojito_port);
1050 }
1051
1052 /* Control the handoff */
1053 void
1054 proto_reg_handoff_mojito(void)
1055 {
1056         static gboolean           initialized         = FALSE;
1057         static int                old_mojito_udp_port = 0;
1058         static dissector_handle_t mojito_handle;
1059
1060         if (!initialized) {
1061                 mojito_handle = new_create_dissector_handle(dissect_mojito, proto_mojito);
1062                 heur_dissector_add("udp", dissect_mojito_heuristic, proto_mojito);
1063                 initialized = TRUE;
1064         }
1065
1066         /* Register UDP port for dissection */
1067         if(old_mojito_udp_port != 0 && old_mojito_udp_port != udp_mojito_port){
1068                 dissector_delete_uint("udp.port", old_mojito_udp_port, mojito_handle);
1069         }
1070
1071         if(udp_mojito_port != 0 && old_mojito_udp_port != udp_mojito_port) {
1072                 dissector_add_uint("udp.port", udp_mojito_port, mojito_handle);
1073         }
1074
1075         old_mojito_udp_port = udp_mojito_port;
1076 }
1077
1078 /*
1079  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1080  *
1081  * Local variables:
1082  * c-basic-offset: 8
1083  * tab-width: 8
1084  * indent-tabs-mode: t
1085  * End:
1086  *
1087  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1088  * :indentSize=8:tabSize=8:noTabs=false:
1089  */