Coverage Report

Created: 2026-01-02 06:13

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