Coverage Report

Created: 2025-12-27 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-icep.c
Line
Count
Source
1
/* packet-icep.c
2
 * Routines for "The ICE Protocol" dissection
3
 * Copyright 2004 _FF_
4
 * Francesco Fondelli <fondelli dot francesco, tiscali dot it>
5
 *
6
 * Wireshark - Network traffic analyzer
7
 * By Gerald Combs <gerald@wireshark.org>
8
 * Copyright 1998 Gerald Combs
9
 *
10
 * SPDX-License-Identifier: GPL-2.0-or-later
11
 */
12
13
/*
14
  TODO:
15
  1) Dissect encoded data (do sth like idl2wrs for CORBA).
16
  2) Add conversations.
17
18
*/
19
20
/*
21
  NOTES:
22
  1) p. 586 Chapter 23.2 of "The ICE Protocol"
23
     "Data is always encoded using little-endian byte order for numeric types."
24
  2) Information about Ice can be found here: http://www.zeroc.com
25
*/
26
27
0
#define WS_LOG_DOMAIN "packet-icep"
28
29
#include "config.h"
30
#include <wireshark.h>
31
32
#include <epan/packet.h>
33
#include <epan/expert.h>
34
#include <epan/prefs.h>
35
#include "packet-tcp.h"
36
37
void proto_register_icep(void);
38
void proto_reg_handoff_icep(void);
39
40
static dissector_handle_t icep_tcp_handle, icep_udp_handle;
41
42
/* fixed values taken from the standard */
43
static const uint8_t icep_magic[] = { 'I', 'c', 'e', 'P' };
44
62
#define ICEP_HEADER_SIZE                14
45
9
#define ICEP_MIN_REPLY_SIZE              5
46
70
#define ICEP_MIN_PARAMS_SIZE             6
47
84
#define ICEP_MIN_COMMON_REQ_HEADER_SIZE 13
48
49
/* Initialize the protocol and registered fields */
50
static int proto_icep;
51
52
/* Message Header */
53
static int hf_icep_protocol_major;
54
static int hf_icep_protocol_minor;
55
static int hf_icep_encoding_major;
56
static int hf_icep_encoding_minor;
57
static int hf_icep_message_type;
58
static int hf_icep_compression_status;
59
static int hf_icep_message_size;
60
static int hf_icep_magic_number;
61
62
/* [Batch] Request Message Body */
63
static int hf_icep_request_id;
64
static int hf_icep_id_name;
65
static int hf_icep_id_category;
66
static int hf_icep_facet;
67
static int hf_icep_operation;
68
static int hf_icep_mode;
69
static int hf_icep_context;
70
static int hf_icep_params_size;
71
static int hf_icep_params_major;
72
static int hf_icep_params_minor;
73
static int hf_icep_params_encapsulated;
74
static int hf_icep_reply_data;
75
static int hf_icep_invocation_key;
76
static int hf_icep_invocation_value;
77
78
/* Reply Message Body */
79
static int hf_icep_reply_status;
80
81
/* Initialize the subtree pointers */
82
static int ett_icep;
83
static int ett_icep_msg;
84
static int ett_icep_invocation_context;
85
86
static expert_field ei_icep_params_size;
87
static expert_field ei_icep_context_missing;
88
static expert_field ei_icep_reply_data;
89
static expert_field ei_icep_length;
90
static expert_field ei_icep_facet_max_one_element;
91
static expert_field ei_icep_string_too_long;
92
static expert_field ei_icep_string_malformed;
93
static expert_field ei_icep_message_type;
94
static expert_field ei_icep_mode_missing;
95
static expert_field ei_icep_params_encapsulated;
96
static expert_field ei_icep_params_missing;
97
static expert_field ei_icep_batch_requests;
98
static expert_field ei_icep_empty_batch;
99
static expert_field ei_icep_facet_missing;
100
static expert_field ei_icep_context_too_long;
101
102
/* Preferences */
103
static unsigned icep_max_batch_requests    = 64;
104
static unsigned icep_max_ice_string_len    = 512;
105
static unsigned icep_max_ice_context_pairs = 64;
106
107
108
static const value_string icep_msgtype_vals[] = {
109
    {0x0, "Request"},
110
    {0x1, "Batch request"},
111
    {0x2, "Reply"},
112
    {0x3, "Validate connection"},
113
    {0x4, "Close connection"},
114
    {0, NULL}
115
};
116
117
static const value_string icep_zipstatus_vals[] = {
118
    {0x0, "Uncompressed, sender cannot accept a compressed reply"},
119
    {0x1, "Uncompressed, sender can accept a compressed reply"},
120
    {0x2, "Compressed, sender can accept a compressed reply"},
121
    {0, NULL}
122
};
123
124
static const value_string icep_replystatus_vals[] = {
125
    {0x0, "Success"},
126
    {0x1, "User exception"},
127
    {0x2, "Object does not exist"},
128
    {0x3, "Facet does not exist"},
129
    {0x4, "Operation does not exist"},
130
    {0x5, "Unknown Ice local exception"},
131
    {0x6, "Unknown Ice user exception"},
132
    {0x7, "Unknown exception"},
133
    {0, NULL}
134
};
135
136
static const value_string icep_mode_vals[] = {
137
    {0x0, "normal"},
138
    {0x1, "nonmutating"},
139
    {0x2, "idempotent"},
140
    {0, NULL}
141
};
142
143
/*
144
 * This function dissects an "Ice string", adds hf to "tree" and returns consumed
145
 * bytes in "*consumed", if errors "*consumed" is -1.
146
 *
147
 * "*dest" is a null terminated version of the dissected Ice string.
148
 */
149
static void dissect_ice_string(packet_info *pinfo, proto_tree *tree, proto_item *item, int hf_icep,
150
                               tvbuff_t *tvb, uint32_t offset, int32_t *consumed, const uint8_t **dest)
151
695
{
152
    /* p. 586 chapter 23.2.1 and p. 588 chapter 23.2.5
153
     * string == Size + content
154
     * string = 1byte (0..254) + string not null terminated
155
     * or
156
     * string = 1byte (255) + 1int (255..2^32-1) + string not null terminated
157
     */
158
159
695
    uint32_t Size = 0;
160
695
    const uint8_t *s = NULL;
161
162
695
    (*consumed) = 0;
163
164
    /* check for first byte */
165
695
    if ( !tvb_bytes_exist(tvb, offset, 1) ) {
166
167
2
        expert_add_info_format(pinfo, item, &ei_icep_string_malformed, "1st byte of Size missing");
168
2
        col_append_str(pinfo->cinfo, COL_INFO, " (1st byte of Size missing)");
169
170
2
        (*consumed) = -1;
171
2
        return;
172
2
    }
173
174
    /* get the Size */
175
693
    Size = tvb_get_uint8(tvb, offset);
176
693
    offset++;
177
693
    (*consumed)++;
178
179
693
    if ( Size == 255 ) {
180
181
        /* check for next 4 bytes */
182
9
        if ( !tvb_bytes_exist(tvb, offset, 4) ) {
183
184
1
            expert_add_info_format(pinfo, item, &ei_icep_string_malformed, "second field of Size missing");
185
1
            col_append_str(pinfo->cinfo, COL_INFO, " (second field of Size missing)");
186
187
1
            (*consumed) = -1;
188
1
            return;
189
1
        }
190
191
        /* get second field of Size */
192
8
        Size = tvb_get_letohl(tvb, offset);
193
8
        offset += 4;
194
8
        (*consumed) += 4;
195
8
    }
196
197
692
    ws_debug("string.Size --> %d", Size);
198
199
    /* check if the string exists */
200
692
    if ( !tvb_bytes_exist(tvb, offset, Size) ) {
201
202
34
        expert_add_info_format(pinfo, item, &ei_icep_string_malformed, "missing or truncated string");
203
34
        col_append_str(pinfo->cinfo, COL_INFO, " (missing or truncated string)");
204
205
34
        (*consumed) = -1;
206
34
        return;
207
34
    }
208
209
658
    if ( Size > icep_max_ice_string_len ) {
210
211
0
        expert_add_info(pinfo, item, &ei_icep_string_too_long);
212
0
        col_append_str(pinfo->cinfo, COL_INFO, " (string too long)");
213
214
0
        (*consumed) = -1;
215
0
        return;
216
0
    }
217
218
219
658
    if ( Size != 0 ) {
220
192
        proto_tree_add_item_ret_string(tree, hf_icep, tvb, offset, Size, ENC_ASCII, pinfo->pool, &s);
221
466
    } else {
222
466
        s = (const uint8_t*)wmem_strdup(pinfo->pool, "(empty)");
223
        /* display the 0x00 Size byte when click on a empty ice_string */
224
466
        proto_tree_add_string(tree, hf_icep, tvb, offset - 1, 1, (const char*)s);
225
466
    }
226
227
658
    if ( dest != NULL )
228
585
        *dest = s;
229
230
    /*offset += Size;*/
231
658
    (*consumed) += Size;
232
658
    return;
233
658
}
234
235
/*
236
 * This function dissects an "Ice facet", adds hf(s) to "tree" and returns consumed
237
 * bytes in "*consumed", if errors "*consumed" is -1.
238
 */
239
static void dissect_ice_facet(packet_info *pinfo, proto_tree *tree, proto_item *item, int hf_icep,
240
                  tvbuff_t *tvb, uint32_t offset, int32_t *consumed)
241
66
{
242
    /*  p. 588, chapter 23.2.6:
243
     *  "facet" is a StringSeq, a StringSeq is a:
244
     *  sequence<string>
245
     *
246
     *
247
     * sequence == Size + SizeElements
248
     * sequence = 1byte (0..254) + SizeElements
249
     * or
250
     * sequence = 1byte (255) + 1int (255..2^32-1) + SizeElements
251
     *
252
     *
253
     * p.613. chapter 23.3.2
254
     * "facet has either zero elements (empty) or one element"
255
     *
256
     *
257
     */
258
259
66
    uint32_t Size = 0; /* number of elements in the sequence */
260
261
66
    (*consumed) = 0;
262
263
    /* check first byte */
264
66
    if ( !tvb_bytes_exist(tvb, offset, 1) ) {
265
266
2
        expert_add_info(pinfo, item, &ei_icep_facet_missing);
267
2
        col_append_str(pinfo->cinfo, COL_INFO, " (facet field missing)");
268
269
2
        (*consumed) = -1;
270
2
        return;
271
2
    }
272
273
    /* get first byte of Size */
274
64
    Size = tvb_get_uint8(tvb, offset);
275
64
    offset++;
276
64
    (*consumed)++;
277
278
64
    if ( Size == 0 ) {
279
        /* display the 0x00 Size byte when click on a empty ice_string */
280
46
        proto_tree_add_string(tree, hf_icep, tvb, offset - 1, 1, "(empty)");
281
46
        return;
282
46
    }
283
284
18
    if ( Size == 1 ) {
285
286
10
        int32_t consumed_facet = 0;
287
288
10
        dissect_ice_string(pinfo, tree, item, hf_icep, tvb, offset, &consumed_facet, NULL);
289
290
10
        if ( consumed_facet == -1 ) {
291
3
            (*consumed) = -1;
292
3
            return;
293
3
        }
294
295
        /*offset += consumed_facet;*/
296
7
        (*consumed) += consumed_facet;
297
7
        return;
298
10
    }
299
300
    /* if here => Size > 1 => not possible */
301
302
    /* display the XX Size byte when click here */
303
8
    expert_add_info(pinfo, item, &ei_icep_facet_max_one_element);
304
305
8
    col_append_str(pinfo->cinfo, COL_INFO, " (facet can be max one element)");
306
307
8
    (*consumed) = -1;
308
8
    return;
309
18
}
310
311
/*
312
 * This function dissects an "Ice context", adds hf(s) to "tree" and returns consumed
313
 * bytes in "*consumed", if errors "*consumed" is -1.
314
 */
315
static void dissect_ice_context(packet_info *pinfo, proto_tree *tree, proto_item *item,
316
                                tvbuff_t *tvb, uint32_t offset, int32_t *consumed)
317
48
{
318
    /*  p. 588, chapter 23.2.7 and p. 613, 23.3.2:
319
     *  "context" is a dictionary<string, string>
320
     *
321
     * dictionary<string, string> == Size + SizeKeyValuePairs
322
     * dictionary<string, string> = 1byte (0..254) + SizeKeyValuePairs
323
     * or
324
     * dictionary<string, string>= 1byte (255) + 1int (255..2^32-1)+SizeKeyValuePairs
325
     *
326
     */
327
328
48
    uint32_t Size = 0; /* number of key-value in the dictionary */
329
48
    uint32_t i = 0;
330
48
    const char *s = NULL;
331
332
48
    (*consumed) = 0;
333
334
    /* check first byte */
335
48
    if ( !tvb_bytes_exist(tvb, offset, 1) ) {
336
337
2
        expert_add_info_format(pinfo, item, &ei_icep_context_missing, "context missing");
338
2
        col_append_str(pinfo->cinfo, COL_INFO, " (context missing)");
339
340
2
        (*consumed) = -1;
341
2
        return;
342
2
    }
343
344
    /* get first byte of Size */
345
46
    Size = tvb_get_uint8(tvb, offset);
346
46
    offset++;
347
46
    (*consumed)++;
348
349
46
    if ( Size == 255 ) {
350
351
        /* check for next 4 bytes */
352
5
        if ( !tvb_bytes_exist(tvb, offset, 4) ) {
353
354
1
            expert_add_info_format(pinfo, item, &ei_icep_context_missing, "second field of Size missing");
355
1
            col_append_str(pinfo->cinfo, COL_INFO, " (second field of Size missing)");
356
357
1
            (*consumed) = -1;
358
1
            return;
359
1
        }
360
361
        /* get second field of Size */
362
4
        Size = tvb_get_letohl(tvb, offset);
363
4
        offset += 4;
364
4
        (*consumed) += 4;
365
4
    }
366
367
45
    ws_debug("context.Size --> %d", Size);
368
369
45
    if ( Size > icep_max_ice_context_pairs ) {
370
371
        /* display the XX Size byte when click here */
372
6
        expert_add_info(pinfo, item, &ei_icep_context_too_long);
373
374
6
        col_append_str(pinfo->cinfo, COL_INFO, " (too long context)");
375
376
6
        (*consumed) = -1;
377
6
        return;
378
6
    }
379
380
39
    if (Size == 0) {
381
14
        s = "(empty)";
382
        /* display the 0x00 Size byte when click on a empty context */
383
14
        proto_tree_add_string(tree, hf_icep_context, tvb, offset - 1, 1, s);
384
14
        return;
385
14
    }
386
387
    /* looping through the dictionary */
388
251
    for ( i = 0; i < Size; i++ ) {
389
        /* key */
390
245
        int32_t consumed_key = 0;
391
245
        const uint8_t *str_key = NULL;
392
        /* value */
393
245
        int32_t consumed_value = 0;
394
245
        const uint8_t *str_value = NULL;
395
245
        proto_item *ti;
396
245
        proto_tree *context_tree;
397
398
245
        ws_debug("looping through context dictionary, loop #%d", i);
399
245
        context_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_icep_invocation_context, &ti, "Invocation Context");
400
401
245
        dissect_ice_string(pinfo, context_tree, ti, hf_icep_invocation_key, tvb, offset, &consumed_key, &str_key);
402
403
245
        if ( consumed_key == -1 ) {
404
8
            (*consumed) = -1;
405
8
            return;
406
8
        }
407
408
237
        offset += consumed_key;
409
237
        (*consumed) += consumed_key;
410
411
237
        dissect_ice_string(pinfo, context_tree, ti, hf_icep_invocation_value, tvb, offset, &consumed_value, &str_value);
412
413
237
        if ( consumed_value == -1 ) {
414
11
            (*consumed) = -1;
415
11
            return;
416
11
        }
417
418
226
        offset += consumed_value;
419
226
        (*consumed) += consumed_value;
420
226
        if (ti)
421
226
            proto_item_set_len(ti, (consumed_key + consumed_value) + 1);
422
226
    }
423
25
}
424
425
/*
426
 * This function dissects an "Ice params", adds hf(s) to "tree" and returns consumed
427
 * bytes in "*consumed", if errors "*consumed" is -1.
428
 */
429
static void dissect_ice_params(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
430
                               uint32_t offset, int32_t *consumed)
431
20
{
432
    /*  p. 612, chapter 23.3.2 and p. 587, 23.2.2:
433
     *  "params" is an Encapsulation
434
     *
435
     *  struct Encapsulation {
436
     *      int size;
437
     *      byte major;
438
     *      byte minor;
439
     *      //(size - 6) bytes of data
440
     *  }
441
     *
442
     */
443
444
20
    int32_t size = 0;
445
20
    int tvb_data_remained = 0;
446
447
20
    (*consumed) = 0;
448
449
    /* check first 6 bytes */
450
20
    if ( !tvb_bytes_exist(tvb, offset, ICEP_MIN_PARAMS_SIZE) ) {
451
452
2
        expert_add_info(pinfo, item, &ei_icep_params_missing);
453
2
        col_append_str(pinfo->cinfo, COL_INFO, " (params missing)");
454
455
2
        (*consumed) = -1;
456
2
        return;
457
2
    }
458
459
    /* get the size */
460
18
    size = tvb_get_letohl(tvb, offset);
461
462
18
    ws_debug("params.size --> %d", size);
463
464
18
    if ( size < ICEP_MIN_PARAMS_SIZE ) {
465
466
10
        expert_add_info(pinfo, item, &ei_icep_params_size);
467
10
        col_append_str(pinfo->cinfo, COL_INFO, " (params size too small)");
468
469
10
        (*consumed) = -1;
470
10
        return;
471
10
    }
472
473
8
    if ( tree ) {
474
475
8
        proto_tree_add_item(tree, hf_icep_params_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
476
8
        offset += 4;
477
8
        (*consumed) += 4;
478
479
8
        proto_tree_add_item(tree, hf_icep_params_major, tvb, offset, 1, ENC_LITTLE_ENDIAN);
480
8
        offset += 1;
481
8
        (*consumed)++;
482
483
8
        proto_tree_add_item(tree, hf_icep_params_minor, tvb, offset, 1, ENC_LITTLE_ENDIAN);
484
8
        offset += 1;
485
8
        (*consumed)++;
486
487
8
    } else {
488
        /* skip size, major, minor */
489
0
        offset += 6;
490
0
        (*consumed) += 6;
491
0
    }
492
493
8
    if( size == ICEP_MIN_PARAMS_SIZE ) /* no encapsulated data present, it's normal */
494
0
        return;
495
496
    /* check if I got all encapsulated data */
497
8
    tvb_data_remained = tvb_reported_length_remaining(tvb, offset);
498
499
8
    if ( tvb_data_remained < ( size - ICEP_MIN_PARAMS_SIZE ) ) {
500
501
4
        expert_add_info_format(pinfo, item, &ei_icep_params_encapsulated, "missing encapsulated data (%d bytes)", size - ICEP_MIN_PARAMS_SIZE - tvb_data_remained);
502
503
4
        col_append_fstr(pinfo->cinfo, COL_INFO,
504
4
                    " (missing encapsulated data (%d bytes))",
505
4
                    size - ICEP_MIN_PARAMS_SIZE - tvb_data_remained);
506
507
4
        (*consumed) = -1;
508
4
        return;
509
4
    }
510
511
    /* encapsulated params */
512
4
    proto_tree_add_item(tree, hf_icep_params_encapsulated, tvb, offset, (size - ICEP_MIN_PARAMS_SIZE), ENC_NA);
513
514
4
    (*consumed) += (size - ICEP_MIN_PARAMS_SIZE);
515
4
}
516
517
static void dissect_icep_request_common(tvbuff_t *tvb, uint32_t offset,
518
                    packet_info *pinfo, proto_tree *icep_sub_tree, proto_item* icep_sub_item, int32_t *total_consumed)
519
84
{
520
    /*  p. 613, chapter 23.3.3 and p. 612 chapter 23.3.2:
521
     *  Request and BatchRequest differ only in the first 4 bytes (requestID)
522
     *  so them share this part
523
     *
524
     *   Ice::Identity id;
525
     *   Ice::StringSeq facet;
526
     *   string operation;
527
     *   byte mode;
528
     *   Ice::Context context;
529
     *   Encapsulation params;
530
     *  }
531
     */
532
533
84
    int32_t consumed = 0;
534
84
    const uint8_t *namestr = NULL;
535
84
    const uint8_t *opstr = NULL;
536
537
84
    (*total_consumed) = 0;
538
539
    /* check common header (i.e. the batch request one)*/
540
84
    if ( !tvb_bytes_exist(tvb, offset, ICEP_MIN_COMMON_REQ_HEADER_SIZE) ) {
541
542
6
        expert_add_info_format(pinfo, icep_sub_item, &ei_icep_length, "too short header");
543
6
        col_append_str(pinfo->cinfo, COL_INFO, " (too short header)");
544
545
6
        goto error;
546
6
    }
547
548
    /* got at least 15 bytes */
549
550
    /*  "id" is a:
551
     *  struct Identity {
552
     *      string name;
553
     *  string category;
554
     *  }
555
     */
556
557
78
    dissect_ice_string(pinfo, icep_sub_tree, icep_sub_item, hf_icep_id_name, tvb, offset, &consumed, &namestr);
558
559
78
    if ( consumed == -1 )
560
6
        goto error;
561
562
72
    offset += consumed; ws_debug("consumed --> %d", consumed);
563
72
    (*total_consumed) += consumed;
564
565
566
72
    dissect_ice_string(pinfo, icep_sub_tree, icep_sub_item, hf_icep_id_category, tvb, offset, &consumed, NULL);
567
568
72
    if ( consumed == -1 )
569
6
        goto error;
570
571
66
    offset += consumed; ws_debug("consumed --> %d", consumed);
572
66
    (*total_consumed) += consumed;
573
574
575
    /*  "facet" is a:
576
     *  sequence<string> StringSeq
577
     *
578
     */
579
580
66
    dissect_ice_facet(pinfo, icep_sub_tree, icep_sub_item, hf_icep_facet, tvb, offset, &consumed);
581
582
66
    if ( consumed == -1 )
583
13
        goto error;
584
585
53
    offset += consumed; ws_debug("consumed --> %d", consumed);
586
53
    (*total_consumed) += consumed;
587
588
    /*  "operation" is an ice_string
589
     *
590
     */
591
592
53
    dissect_ice_string(pinfo, icep_sub_tree, icep_sub_item, hf_icep_operation, tvb, offset, &consumed, &opstr);
593
594
53
    if ( consumed == -1 )
595
3
        goto error;
596
50
    else {
597
50
        offset += consumed; ws_debug("consumed --> %d", consumed);
598
50
        (*total_consumed) += consumed;
599
600
50
        if ( opstr && namestr ) {
601
50
            ws_debug("operation --> %s.%s()", namestr, opstr);
602
50
            col_append_fstr(pinfo->cinfo, COL_INFO, " %s.%s()",
603
50
                        namestr, opstr);
604
50
            opstr = NULL;
605
50
            namestr = NULL;
606
50
        }
607
50
    }
608
609
    /* check and get mode byte */
610
50
    if ( !tvb_bytes_exist(tvb, offset, 1) ) {
611
612
2
        expert_add_info(pinfo, icep_sub_item, &ei_icep_mode_missing);
613
614
2
        col_append_str(pinfo->cinfo, COL_INFO, " (mode field missing)");
615
2
        goto error;
616
2
    }
617
618
48
    proto_tree_add_item(icep_sub_tree, hf_icep_mode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
619
620
48
    offset++; ws_debug("consumed --> 1");
621
48
    (*total_consumed)++;
622
623
624
    /*  "context" is a dictionary<string, string>
625
     *
626
     */
627
628
48
    dissect_ice_context(pinfo, icep_sub_tree, icep_sub_item, tvb, offset, &consumed);
629
630
48
    if ( consumed == -1 )
631
28
        goto error;
632
633
20
    offset += consumed; ws_debug("consumed --> %d", consumed);
634
20
    (*total_consumed) += consumed;
635
636
    /*  "params" is a Encapsulation
637
     *
638
     */
639
640
20
    dissect_ice_params(pinfo, icep_sub_tree, icep_sub_item, tvb, offset, &consumed);
641
642
20
    if ( consumed == -1 )
643
16
        goto error;
644
645
    /*offset += consumed;*/
646
4
     ws_debug("consumed --> %d", consumed);
647
4
    (*total_consumed) += consumed;
648
649
4
    return;
650
651
80
error:
652
80
    (*total_consumed) = -1;
653
80
}
654
655
656
static void dissect_icep_request(tvbuff_t *tvb, uint32_t offset,
657
                                 packet_info *pinfo, proto_tree *icep_tree, proto_item* icep_item)
658
85
{
659
    /*  p. 612, chapter 23.3.2:
660
     *
661
     *  struct RequestData {
662
     *   int requestID;
663
     *   Ice::Identity id;
664
     *   Ice::StringSeq facet;
665
     *   string operation;
666
     *   byte mode;
667
     *   Ice::Context context;
668
     *   Encapsulation params;
669
     *  }
670
     */
671
672
85
    proto_item *ti = NULL;
673
85
    proto_tree *icep_sub_tree = NULL;
674
85
    int32_t consumed = 0;
675
85
    uint32_t reqid = 0;
676
677
85
    ws_debug("dissect request");
678
679
    /* check for req id */
680
85
    if ( !tvb_bytes_exist(tvb, offset, 4) ) {
681
682
2
        expert_add_info_format(pinfo, icep_item, &ei_icep_length, "too short header");
683
2
        col_append_str(pinfo->cinfo, COL_INFO, " (too short header)");
684
2
        return;
685
2
    }
686
687
    /* got at least 4 bytes */
688
689
    /* create display subtree for this message type */
690
691
83
    reqid = tvb_get_letohl(tvb, offset);
692
693
83
    icep_sub_tree = proto_tree_add_subtree(icep_tree, tvb, offset, -1, ett_icep_msg, &ti, "Request Message Body");
694
695
83
    proto_tree_add_item(icep_sub_tree, hf_icep_request_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
696
697
83
    if ( reqid != 0 ) {
698
69
        col_append_fstr(pinfo->cinfo, COL_INFO, "(%d):", tvb_get_letohl(tvb, offset));
699
69
    } else
700
14
        col_append_str(pinfo->cinfo, COL_INFO, "(oneway):");
701
702
703
83
    offset += 4;
704
83
    ws_debug("consumed --> 4");
705
706
83
    dissect_icep_request_common(tvb, offset, pinfo, icep_sub_tree, ti, &consumed);
707
708
83
    if ( consumed == -1 )
709
79
        return;
710
711
    /*offset += consumed;*/
712
4
    ws_debug("consumed --> %d", consumed);
713
4
}
714
715
716
717
static void dissect_icep_batch_request(tvbuff_t *tvb, uint32_t offset,
718
                                        packet_info *pinfo, proto_tree *icep_tree, proto_item* icep_item)
719
13
{
720
    /*  p. 613, chapter 23.3.3
721
     *  A batch request msg is a "sequence" of batch request
722
     *  Sequence is Size + elements
723
     *
724
     *  struct BatchRequestData {
725
     *   Ice::Identity id;
726
     *   Ice::StringSeq facet;
727
     *   string operation;
728
     *   byte mode;
729
     *   Ice::Context context;
730
     *   Encapsulation params;
731
     *  }
732
     *
733
     * NOTE!!!:
734
     * The only real implementation of the Ice protocol puts a 32bit count in front
735
     * of a Batch Request, *not* an Ice::Sequence (as the standard says). Basically the
736
     * same people wrote both code and standard so I'll follow the code.
737
     */
738
739
13
    proto_item *ti = NULL;
740
13
    proto_tree *icep_sub_tree = NULL;
741
13
    uint32_t num_reqs = 0;
742
13
    uint32_t i = 0;
743
13
    int32_t consumed = 0;
744
745
13
    ws_debug("dissect batch request");
746
747
    /* check for first 4 byte */
748
13
    if ( !tvb_bytes_exist(tvb, offset, 4) ) {
749
750
1
        expert_add_info_format(pinfo, icep_item, &ei_icep_length, "counter of batch requests missing");
751
1
        col_append_str(pinfo->cinfo, COL_INFO, " (counter of batch requests missing)");
752
1
        return;
753
1
    }
754
755
12
    num_reqs = tvb_get_letohl(tvb, offset);
756
12
    offset += 4;
757
758
12
    ws_debug("batch_requests.count --> %d", num_reqs);
759
760
12
    if ( num_reqs > icep_max_batch_requests ) {
761
762
10
        expert_add_info_format(pinfo, icep_item, &ei_icep_batch_requests, "too many batch requests (%d)", num_reqs);
763
764
10
        col_append_fstr(pinfo->cinfo, COL_INFO, " (too many batch requests, %d)", num_reqs);
765
10
        return;
766
10
    }
767
768
2
    if ( num_reqs == 0 ) {
769
770
1
        proto_tree_add_expert(icep_tree, pinfo, &ei_icep_empty_batch, tvb, offset, -1);
771
1
        col_append_str(pinfo->cinfo, COL_INFO, " (empty batch requests sequence)");
772
773
1
        return;
774
1
    }
775
776
777
1
    col_append_str(pinfo->cinfo, COL_INFO, ":");
778
779
    /*
780
     * process requests
781
     */
782
783
1
    for ( i = 0; i < num_reqs; i++ ) {
784
785
1
        ws_debug("looping through sequence of batch requests, loop #%d", i);
786
787
        /* create display subtree for this message type */
788
789
1
        icep_sub_tree = proto_tree_add_subtree_format(icep_tree, tvb, offset, -1,
790
1
                         ett_icep_msg, &ti, "Batch Request Message Body: #%d", i);
791
792
1
        if (i != 0) {
793
0
            col_append_str(pinfo->cinfo, COL_INFO, ",");
794
0
        }
795
796
1
        dissect_icep_request_common(tvb, offset, pinfo, icep_sub_tree, ti, &consumed);
797
798
1
        if ( consumed == -1 )
799
1
            return;
800
801
0
        if ( icep_tree && ti )
802
0
            proto_item_set_len(ti, consumed);
803
804
0
        offset += consumed;
805
0
        ws_debug("consumed --> %d", consumed);
806
0
    }
807
1
}
808
809
static void dissect_icep_reply(tvbuff_t *tvb, uint32_t offset,
810
                               packet_info *pinfo, proto_tree *icep_tree, proto_item* icep_item)
811
5
{
812
    /*  p. 614, chapter 23.3.4:
813
     *
814
     *  struct ReplyData {
815
     *   int requestId;
816
     *   byte replyStatus;
817
     *   [... messageSize - 19 bytes ...  ]
818
     *  }
819
     */
820
821
5
    int32_t messageSize = 0;
822
5
    uint32_t tvb_data_remained = 0;
823
5
    uint32_t reported_reply_data = 0;
824
5
    proto_item *ti = NULL;
825
5
    proto_tree *icep_sub_tree = NULL;
826
827
5
    ws_debug("dissect reply");
828
829
    /* get at least a full reply message header */
830
831
5
    if ( !tvb_bytes_exist(tvb, offset, ICEP_MIN_REPLY_SIZE) ) {
832
833
1
        expert_add_info_format(pinfo, icep_item, &ei_icep_length, "too short header");
834
835
1
        col_append_str(pinfo->cinfo, COL_INFO, " (too short header)");
836
1
        return;
837
1
    }
838
839
    /* got 5 bytes, then data */
840
841
    /* create display subtree for this message type */
842
843
4
    icep_sub_tree = proto_tree_add_subtree(icep_tree, tvb, offset, -1,
844
4
                     ett_icep_msg, &ti, "Reply Message Body");
845
846
4
    proto_tree_add_item(icep_sub_tree, hf_icep_request_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
847
848
4
    col_append_fstr(pinfo->cinfo, COL_INFO, "(%d):", tvb_get_letohl(tvb, offset));
849
850
4
    offset += 4;
851
852
4
    proto_tree_add_item(icep_sub_tree, hf_icep_reply_status, tvb, offset, 1, ENC_LITTLE_ENDIAN);
853
854
4
    col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
855
4
                val_to_str_const(tvb_get_uint8(tvb, offset),
856
4
                                                 icep_replystatus_vals,
857
4
                                                 "unknown reply status"));
858
859
4
    offset++;
860
861
4
    ws_debug("consumed --> %d", 5);
862
863
    /* check if I got all reply data */
864
4
    tvb_data_remained = tvb_reported_length_remaining(tvb, offset);
865
4
    messageSize = tvb_get_letohl(tvb, 10);
866
4
    reported_reply_data = messageSize - (ICEP_HEADER_SIZE + ICEP_MIN_REPLY_SIZE);
867
868
    /* no */
869
4
    if ( tvb_data_remained < reported_reply_data ) {
870
871
2
        expert_add_info_format(pinfo, ti, &ei_icep_reply_data, "Reply Data (missing %d bytes out of %d)", reported_reply_data - tvb_data_remained, reported_reply_data);
872
873
2
        col_append_fstr(pinfo->cinfo, COL_INFO,
874
2
                    " (missing reply data, %d bytes)",
875
2
                    reported_reply_data - tvb_data_remained);
876
877
        /*offset += tvb_data_remained;*/
878
2
        ws_debug("consumed --> %d", tvb_data_remained);
879
2
        return;
880
2
    }
881
882
    /* yes (reported_reply_data can be 0) */
883
884
2
    proto_tree_add_item(icep_sub_tree, hf_icep_reply_data, tvb, offset, reported_reply_data, ENC_NA);
885
886
    /*offset += reported_reply_data;*/
887
2
    ws_debug("consumed --> %d", reported_reply_data);
888
2
}
889
890
static unsigned get_icep_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb,
891
                              int offset, void *data _U_)
892
72
{
893
72
    return tvb_get_letohl(tvb, offset + 10);
894
72
}
895
896
static int dissect_icep_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
897
118
{
898
    /*  p. 611, chapter 23.3.1:
899
     *
900
     *  struct HeaderData {
901
     *   int magic;
902
     *   byte protocolMajor;
903
     *   byte protocolMinor;
904
     *   byte encodingMajor;
905
     *   byte encodingMinor;
906
     *   byte messageType;
907
     *   byte compressionStatus;
908
     *   int messageSize;
909
     *  }
910
     */
911
912
118
    proto_item *ti, *msg_item = NULL;
913
118
    proto_tree *icep_tree;
914
118
    uint32_t offset = 0;
915
916
    /* Make entries in Protocol column and Info column on summary display */
917
918
118
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICEP");
919
920
118
    col_add_str(pinfo->cinfo, COL_INFO,
921
118
                 val_to_str(pinfo->pool, tvb_get_uint8(tvb, 8),
922
118
                    icep_msgtype_vals,
923
118
                    "Unknown Message Type: 0x%02x"));
924
925
118
    ws_debug("got an icep msg, start analysis");
926
927
    /* create display subtree for the protocol */
928
929
118
    ti = proto_tree_add_item(tree, proto_icep, tvb, 0, -1, ENC_NA);
930
118
    icep_tree = proto_item_add_subtree(ti, ett_icep);
931
932
118
    if (icep_tree) {
933
        /* add items to the subtree */
934
935
        /* message header */
936
937
118
        proto_tree_add_item(icep_tree, hf_icep_magic_number, tvb, offset, 4, ENC_ASCII);
938
118
        offset += 4;
939
940
118
        proto_tree_add_item(icep_tree, hf_icep_protocol_major,
941
118
                    tvb, offset, 1, ENC_LITTLE_ENDIAN);
942
118
        offset++;
943
944
118
        proto_tree_add_item(icep_tree, hf_icep_protocol_minor,
945
118
                    tvb, offset, 1, ENC_LITTLE_ENDIAN);
946
118
        offset++;
947
948
118
        proto_tree_add_item(icep_tree, hf_icep_encoding_major,
949
118
                    tvb, offset, 1, ENC_LITTLE_ENDIAN);
950
118
        offset++;
951
952
118
        proto_tree_add_item(icep_tree, hf_icep_encoding_minor,
953
118
                    tvb, offset, 1, ENC_LITTLE_ENDIAN);
954
118
        offset++;
955
956
118
        msg_item = proto_tree_add_item(icep_tree, hf_icep_message_type,
957
118
                    tvb, offset, 1, ENC_LITTLE_ENDIAN);
958
118
        offset++;
959
960
118
        proto_tree_add_item(icep_tree, hf_icep_compression_status,
961
118
                    tvb, offset, 1, ENC_LITTLE_ENDIAN);
962
118
        offset++;
963
964
118
        proto_tree_add_item(icep_tree, hf_icep_message_size,
965
118
                    tvb, offset, 4, ENC_LITTLE_ENDIAN);
966
118
        offset += 4;
967
118
    } else {
968
0
        offset += ICEP_HEADER_SIZE;
969
0
    }
970
971
118
    switch(tvb_get_uint8(tvb, 8)) {
972
85
    case 0x0:
973
85
        ws_debug("request message body: parsing %d bytes",
974
85
            tvb_captured_length_remaining(tvb, offset));
975
85
        dissect_icep_request(tvb, offset, pinfo, icep_tree, ti);
976
85
        break;
977
13
    case 0x1:
978
13
        ws_debug("batch request message body: parsing %d bytes",
979
13
            tvb_captured_length_remaining(tvb, offset));
980
13
        dissect_icep_batch_request(tvb, offset, pinfo, icep_tree, ti);
981
13
        break;
982
5
    case 0x2:
983
5
        ws_debug("reply message body: parsing %d bytes",
984
5
            tvb_captured_length_remaining(tvb, offset));
985
5
        dissect_icep_reply(tvb, offset, pinfo, icep_tree, ti);
986
5
        break;
987
2
    case 0x3:
988
4
    case 0x4:
989
            /* messages already dissected */
990
4
        break;
991
10
    default:
992
10
        expert_add_info_format(pinfo, msg_item, &ei_icep_message_type, "Unknown Message Type: 0x%02x", tvb_get_uint8(tvb, 8));
993
10
        break;
994
118
    }
995
114
    return tvb_captured_length(tvb);
996
118
}
997
998
/* entry point */
999
static gboolean dissect_icep_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1000
3.98k
{
1001
3.98k
    ws_debug("triggered");
1002
1003
3.98k
    if ( tvb_memeql(tvb, 0, icep_magic, 4) == -1 ) {
1004
        /* Not a ICEP packet. */
1005
3.92k
        return FALSE;
1006
3.92k
    }
1007
1008
    /* start dissecting */
1009
1010
58
    tcp_dissect_pdus(tvb, pinfo, tree, true, ICEP_HEADER_SIZE,
1011
58
        get_icep_pdu_len, dissect_icep_pdu, data);
1012
1013
58
    return TRUE;
1014
3.98k
}
1015
1016
static bool
1017
dissect_icep_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1018
3.98k
{
1019
3.98k
    return (bool)dissect_icep_tcp(tvb, pinfo, tree, data) > 0;
1020
3.98k
}
1021
1022
static gboolean dissect_icep_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1023
2.12k
{
1024
2.12k
    ws_debug("triggered");
1025
1026
2.12k
    if ( tvb_memeql(tvb, 0, icep_magic, 4) == -1 ) {
1027
        /* Not a ICEP packet. */
1028
2.07k
        return false;
1029
2.07k
    }
1030
1031
    /* start dissecting */
1032
52
    dissect_icep_pdu(tvb, pinfo, tree, data);
1033
52
    return true;
1034
2.12k
}
1035
1036
static bool
1037
dissect_icep_udp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1038
2.12k
{
1039
2.12k
    return (bool)dissect_icep_udp(tvb, pinfo, tree, data) > 0;
1040
2.12k
}
1041
1042
/* Register the protocol with Wireshark */
1043
1044
void proto_register_icep(void)
1045
14
{
1046
14
    module_t *icep_module;
1047
14
    expert_module_t* expert_icep;
1048
1049
    /* Setup list of header fields */
1050
1051
14
    static hf_register_info hf[] = {
1052
1053
14
        { &hf_icep_protocol_major,
1054
14
          {
1055
14
              "Protocol Major", "icep.protocol_major",
1056
14
              FT_INT8, BASE_DEC, NULL, 0x0,
1057
14
              "The protocol major version number", HFILL
1058
14
          }
1059
14
        },
1060
1061
14
        { &hf_icep_protocol_minor,
1062
14
          {
1063
14
              "Protocol Minor", "icep.protocol_minor",
1064
14
              FT_INT8, BASE_DEC, NULL, 0x0,
1065
14
              "The protocol minor version number", HFILL
1066
14
          }
1067
14
        },
1068
1069
14
        { &hf_icep_encoding_major,
1070
14
          {
1071
14
              "Encoding Major", "icep.encoding_major",
1072
14
              FT_INT8, BASE_DEC, NULL, 0x0,
1073
14
              "The encoding major version number", HFILL
1074
14
          }
1075
14
        },
1076
1077
14
        { &hf_icep_encoding_minor,
1078
14
          {
1079
14
              "Encoding Minor", "icep.encoding_minor",
1080
14
              FT_INT8, BASE_DEC, NULL, 0x0,
1081
14
              "The encoding minor version number", HFILL
1082
14
          }
1083
14
        },
1084
1085
14
        { &hf_icep_message_type,
1086
14
          {
1087
14
              "Message Type", "icep.message_type",
1088
14
              FT_INT8, BASE_DEC, VALS(icep_msgtype_vals), 0x0,
1089
14
              "The message type", HFILL
1090
14
          }
1091
14
        },
1092
1093
14
        { &hf_icep_magic_number,
1094
14
          {
1095
14
              "Magic Number", "icep.magic_number",
1096
14
              FT_STRING, BASE_NONE, NULL, 0x0,
1097
14
              NULL, HFILL
1098
14
          }
1099
14
        },
1100
1101
14
        { &hf_icep_compression_status,
1102
14
          {
1103
14
              "Compression Status", "icep.compression_status",
1104
14
              FT_INT8, BASE_DEC, VALS(icep_zipstatus_vals), 0x0,
1105
14
              "The compression status of the message", HFILL
1106
14
          }
1107
14
        },
1108
1109
14
        { &hf_icep_message_size,
1110
14
          {
1111
14
              "Message Size", "icep.message_status",
1112
14
              FT_INT32, BASE_DEC, NULL, 0x0,
1113
14
              "The size of the message in bytes, including the header",
1114
14
              HFILL
1115
14
          }
1116
14
        },
1117
1118
14
        { &hf_icep_request_id,
1119
14
          {
1120
14
              "Request Identifier", "icep.request_id",
1121
14
              FT_INT32, BASE_DEC, NULL, 0x0,
1122
14
              "The request identifier",
1123
14
              HFILL
1124
14
          }
1125
14
        },
1126
1127
14
        { &hf_icep_reply_status,
1128
14
          {
1129
14
              "Reply Status", "icep.protocol_major",
1130
14
              FT_INT8, BASE_DEC, VALS(icep_replystatus_vals), 0x0,
1131
14
              "The reply status", HFILL
1132
14
          }
1133
14
        },
1134
1135
14
        { &hf_icep_id_name,
1136
14
          {
1137
14
              "Object Identity Name", "icep.id.name",
1138
14
              FT_STRINGZ, BASE_NONE, NULL, 0x0,
1139
14
              "The object identity name", HFILL
1140
14
          }
1141
14
        },
1142
1143
14
        { &hf_icep_id_category,
1144
14
          {
1145
14
              "Object Identity Content", "icep.id.content",
1146
14
              FT_STRINGZ, BASE_NONE, NULL, 0x0,
1147
14
              "The object identity content", HFILL
1148
14
          }
1149
14
        },
1150
1151
14
        { &hf_icep_facet,
1152
14
          {
1153
14
              "Facet Name", "icep.facet",
1154
14
              FT_STRINGZ, BASE_NONE, NULL, 0x0,
1155
14
              "The facet name", HFILL
1156
14
          }
1157
14
        },
1158
1159
14
        { &hf_icep_operation,
1160
14
          {
1161
14
              "Operation Name", "icep.operation",
1162
14
              FT_STRINGZ, BASE_NONE, NULL, 0x0,
1163
14
              "The operation name", HFILL
1164
14
          }
1165
14
        },
1166
1167
14
        { &hf_icep_mode,
1168
14
          {
1169
14
              "Ice::OperationMode", "icep.operation_mode",
1170
14
              FT_INT8, BASE_DEC, VALS(icep_mode_vals), 0x0,
1171
14
              "A byte representing Ice::OperationMode", HFILL
1172
14
          }
1173
14
        },
1174
1175
14
        { &hf_icep_context,
1176
14
          {
1177
14
              "Invocation Context", "icep.context",
1178
14
              FT_STRINGZ, BASE_NONE, NULL, 0x0,
1179
14
              "The invocation context", HFILL
1180
14
          }
1181
14
        },
1182
1183
14
        { &hf_icep_params_size,
1184
14
          {
1185
14
              "Input Parameters Size", "icep.params.size",
1186
14
              FT_INT32, BASE_DEC, NULL, 0x0,
1187
14
              "The encapsulated input parameters size",
1188
14
              HFILL
1189
14
          }
1190
14
        },
1191
1192
14
        { &hf_icep_params_major,
1193
14
          {
1194
14
              "Input Parameters Encoding Major",
1195
14
              "icep.params.major",
1196
14
              FT_INT8, BASE_DEC, NULL, 0x0,
1197
14
              "The major encoding version of encapsulated parameters",
1198
14
              HFILL
1199
14
          }
1200
14
        },
1201
1202
14
        { &hf_icep_params_minor,
1203
14
          {
1204
14
              "Input Parameters Encoding Minor",
1205
14
              "icep.params.minor",
1206
14
              FT_INT8, BASE_DEC, NULL, 0x0,
1207
14
              "The minor encoding version of encapsulated parameters",
1208
14
              HFILL
1209
14
          }
1210
14
        },
1211
1212
14
        { &hf_icep_params_encapsulated,
1213
14
          {
1214
14
              "Encapsulated parameters",
1215
14
              "icep.params.encapsulated",
1216
14
              FT_BYTES, BASE_NONE, NULL, 0x0,
1217
14
              "Remaining encapsulated parameters",
1218
14
              HFILL
1219
14
          }
1220
14
        },
1221
1222
14
        { &hf_icep_reply_data,
1223
14
          {
1224
14
              "Reported reply data",
1225
14
              "icep.params.reply_data",
1226
14
              FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL
1227
14
          }
1228
14
        },
1229
1230
14
        { &hf_icep_invocation_key,
1231
14
          {
1232
14
              "Key",
1233
14
              "icep.invocation_key",
1234
14
              FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL
1235
14
          }
1236
14
        },
1237
1238
14
        { &hf_icep_invocation_value,
1239
14
          {
1240
14
              "Value",
1241
14
              "icep.invocation_value",
1242
14
              FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL
1243
14
          }
1244
14
        },
1245
14
    };
1246
1247
    /* Setup protocol subtree array */
1248
1249
14
    static int *ett[] = {
1250
14
        &ett_icep,
1251
14
        &ett_icep_msg,
1252
14
        &ett_icep_invocation_context,
1253
14
    };
1254
1255
14
    static ei_register_info ei[] = {
1256
14
        { &ei_icep_string_malformed, { "icep.string.malformed", PI_MALFORMED, PI_ERROR, "String malformed", EXPFILL }},
1257
14
        { &ei_icep_string_too_long, { "icep.string.too_long", PI_PROTOCOL, PI_WARN, "string too long", EXPFILL }},
1258
14
        { &ei_icep_facet_missing, { "icep.facet.missing", PI_MALFORMED, PI_ERROR, "facet field missing", EXPFILL }},
1259
14
        { &ei_icep_facet_max_one_element, { "icep.facet.max_one_element", PI_PROTOCOL, PI_WARN, "facet can be max one element", EXPFILL }},
1260
14
        { &ei_icep_context_missing, { "icep.context.missing", PI_MALFORMED, PI_ERROR, "context missing", EXPFILL }},
1261
14
        { &ei_icep_context_too_long, { "icep.context.too_long", PI_PROTOCOL, PI_WARN, "too long context", EXPFILL }},
1262
14
        { &ei_icep_params_missing, { "icep.params.missing", PI_MALFORMED, PI_ERROR, "params missing", EXPFILL }},
1263
14
        { &ei_icep_params_size, { "icep.params.size.invalid", PI_PROTOCOL, PI_WARN, "params size too small", EXPFILL }},
1264
14
        { &ei_icep_params_encapsulated, { "icep.params.encapsulated.missing", PI_PROTOCOL, PI_WARN, "missing encapsulated data", EXPFILL }},
1265
14
        { &ei_icep_length, { "icep.length_invalid", PI_MALFORMED, PI_ERROR, "Invalid length", EXPFILL }},
1266
14
        { &ei_icep_mode_missing, { "icep.mode.missing", PI_MALFORMED, PI_ERROR, "mode field missing", EXPFILL }},
1267
14
        { &ei_icep_batch_requests, { "icep.batch_requests.invalid", PI_PROTOCOL, PI_WARN, "too many batch requests", EXPFILL }},
1268
14
        { &ei_icep_empty_batch, { "icep.batch_requests.empty", PI_PROTOCOL, PI_WARN, "empty batch requests sequence", EXPFILL }},
1269
14
        { &ei_icep_reply_data, { "icep.params.reply_data.missing", PI_MALFORMED, PI_ERROR, "Reply Data missing", EXPFILL }},
1270
14
        { &ei_icep_message_type, { "icep.message_type.unknown", PI_PROTOCOL, PI_WARN, "Unknown Message Type", EXPFILL }},
1271
14
    };
1272
1273
    /* Register the protocol name and description */
1274
1275
14
    proto_icep =
1276
14
        proto_register_protocol("Internet Communications Engine Protocol", "ICEP", "icep");
1277
1278
    /* Required function calls to register the header fields and subtrees used */
1279
1280
14
    proto_register_field_array(proto_icep, hf, array_length(hf));
1281
14
    proto_register_subtree_array(ett, array_length(ett));
1282
14
    expert_icep = expert_register_protocol(proto_icep);
1283
14
    expert_register_field_array(expert_icep, ei, array_length(ei));
1284
1285
14
    icep_module = prefs_register_protocol(proto_icep, NULL);
1286
14
    prefs_register_uint_preference(icep_module, "max_batch_requests",
1287
14
                                  "Maximum batch requests",
1288
14
                                  "Maximum number of batch requests allowed",
1289
14
                                  10, &icep_max_batch_requests);
1290
1291
14
    prefs_register_uint_preference(icep_module, "max_ice_string_len",
1292
14
                                  "Maximum string length",
1293
14
                                  "Maximum length allowed of an ICEP string",
1294
14
                                  10, &icep_max_ice_string_len);
1295
1296
14
    prefs_register_uint_preference(icep_module, "max_ice_context_pairs",
1297
14
                                  "Maximum context pairs",
1298
14
                                  "Maximum number of context pairs allowed",
1299
14
                                  10, &icep_max_ice_context_pairs);
1300
1301
14
    icep_tcp_handle = register_dissector("iecp.tcp", dissect_icep_tcp, proto_icep);
1302
14
    icep_udp_handle = register_dissector("iecp.udp", dissect_icep_udp, proto_icep);
1303
14
}
1304
1305
1306
void proto_reg_handoff_icep(void)
1307
14
{
1308
    /* Register as a heuristic TCP/UDP dissector */
1309
14
    heur_dissector_add("tcp", dissect_icep_tcp_heur, "ICEP over TCP", "icep_tcp", proto_icep, HEURISTIC_ENABLE);
1310
14
    heur_dissector_add("udp", dissect_icep_udp_heur, "ICEP over UDP", "icep_udp", proto_icep, HEURISTIC_ENABLE);
1311
1312
    /* Register TCP port for dissection */
1313
14
    dissector_add_for_decode_as_with_preference("tcp.port", icep_tcp_handle);
1314
    /* Register UDP port for dissection */
1315
14
    dissector_add_for_decode_as_with_preference("udp.port", icep_udp_handle);
1316
14
}
1317
1318
/*
1319
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1320
 *
1321
 * Local variables:
1322
 * c-basic-offset: 4
1323
 * tab-width: 8
1324
 * indent-tabs-mode: nil
1325
 * End:
1326
 *
1327
 * vi: set shiftwidth=4 tabstop=8 expandtab:
1328
 * :indentSize=4:tabSize=8:noTabs=true:
1329
 */