Coverage Report

Created: 2025-08-04 07:15

/src/wireshark/epan/conversation.c
Line
Count
Source (jump to first uncovered line)
1
/* conversation.c
2
 * Routines for building lists of packets that are part of a "conversation"
3
 *
4
 * Wireshark - Network traffic analyzer
5
 * By Gerald Combs <gerald@wireshark.org>
6
 * Copyright 1998 Gerald Combs
7
 *
8
 * SPDX-License-Identifier: GPL-2.0-or-later
9
 */
10
11
#include "config.h"
12
13
#include <string.h>
14
15
#include <glib.h>
16
17
#include <wiretap/wtap.h>
18
#include <wsutil/array.h>
19
20
#include "packet.h"
21
#include "to_str.h"
22
#include "conversation.h"
23
24
// The conversation database is a map of maps that contain conversation_t's.
25
// Top-level map keys are strings that describe each conversation type.
26
// Second-level map keys are conversation_element_t arrays.
27
// {
28
//   "uint,endpoint": {
29
//     [ { type: CE_ADDR, addr_val: 10.20.30.40}, { type: CE_PORT, uint_val: 80 } ... ]: <conversation_t>
30
//     [ { type: CE_ADDR, addr_val: 1.1.1.1}, { type: CE_PORT, uint_val: 53 } ... ]: <conversation_t>
31
//   }
32
// }
33
// Instead of using strings as keys we could bit-shift conversation endpoint types
34
// into a uint64_t, e.g. 0x0000000102010200 for CE_ADDRESS,CE_PORT,CE_ADDRESS,CE_PORT,CE_CONVERSATION_TYPE.
35
// We could also use this to prepend a type+length indicator for element arrays.
36
37
/* define DEBUG_CONVERSATION for pretty debug printing */
38
/* #define DEBUG_CONVERSATION */
39
#include "conversation_debug.h"
40
41
#ifdef DEBUG_CONVERSATION
42
int _debug_conversation_indent;
43
#endif
44
45
/*
46
 * We could use an element list here, but this is effectively a parameter list
47
 * for find_conversation and is more compact.
48
 */
49
struct conversation_addr_port_endpoints {
50
    address addr1;
51
    address addr2;
52
    uint32_t port1;
53
    uint32_t port2;
54
    conversation_type ctype;
55
};
56
57
/* Element offsets for address+port conversations */
58
enum {
59
    ADDR1_IDX,
60
    PORT1_IDX,
61
    ADDR2_IDX,
62
    PORT2_IDX,
63
    ENDP_EXACT_IDX,
64
    EXACT_IDX_COUNT,
65
    ADDRS_IDX_COUNT = PORT2_IDX,
66
    PORT2_NO_ADDR2_IDX = ADDR2_IDX,
67
    ENDP_NO_ADDR2_IDX = PORT2_IDX,
68
    ENDP_NO_PORT2_IDX = PORT2_IDX,
69
    ENDP_NO_ADDR2_PORT2_IDX = ADDR2_IDX,
70
    NO_ADDR2_IDX_COUNT = ENDP_EXACT_IDX,
71
    NO_PORT2_IDX_COUNT = ENDP_EXACT_IDX,
72
    NO_ADDR2_PORT2_IDX_COUNT = PORT2_IDX,
73
    ENDP_NO_PORTS_IDX = ADDR2_IDX,
74
    ERR_PKTS_COUNT = PORT2_IDX
75
};
76
77
/* Element offsets for the deinterlacer conversations */
78
enum {
79
    DEINTR_ADDR1_IDX,
80
    DEINTR_ADDR2_IDX,
81
    DEINTR_KEY1_IDX,
82
    DEINTR_KEY2_IDX,
83
    DEINTR_KEY3_IDX,
84
    DEINTR_ENDP_IDX
85
};
86
87
/* Element offsets for the deinterlaced conversations */
88
enum {
89
    DEINTD_ADDR1_IDX,
90
    DEINTD_ADDR2_IDX,
91
    DEINTD_PORT1_IDX,
92
    DEINTD_PORT2_IDX,
93
    DEINTD_ENDP_EXACT_IDX,
94
    DEINTD_EXACT_IDX_COUNT,
95
    DEINTD_ADDRS_IDX_COUNT = DEINTD_PORT2_IDX,
96
    DEINTD_ENDP_NO_PORTS_IDX = DEINTD_PORT1_IDX,
97
    DEINTD_NO_ADDR2_IDX_COUNT = DEINTD_EXACT_IDX_COUNT,
98
    DEINTD_NO_PORT2_IDX_COUNT = DEINTD_EXACT_IDX_COUNT,
99
    DEINTD_NO_ADDR2_PORT2_IDX_COUNT = DEINTD_ENDP_EXACT_IDX
100
};
101
102
/* Names for conversation_element_type values. */
103
static const char *type_names[] = {
104
    "endpoint",
105
    "address",
106
    "port",
107
    "string",
108
    "uint",
109
    "uint64",
110
    "int",
111
    "int64",
112
    "blob",
113
};
114
115
/*
116
 * Hash table of hash tables for conversations identified by element lists.
117
 */
118
static wmem_map_t *conversation_hashtable_element_list;
119
120
/*
121
 * Hash table for conversations based on addresses only
122
 */
123
static wmem_map_t *conversation_hashtable_exact_addr;
124
125
/*
126
 * Hash table for conversations with no wildcards.
127
 */
128
static wmem_map_t *conversation_hashtable_exact_addr_port;
129
130
/*
131
 * Hash table for conversations with one wildcard address.
132
 */
133
static wmem_map_t *conversation_hashtable_no_addr2;
134
135
/*
136
 * Hash table for conversations with one wildcard port.
137
 */
138
static wmem_map_t *conversation_hashtable_no_port2;
139
140
/*
141
 * Hash table for conversations with one wildcard address and port.
142
 */
143
static wmem_map_t *conversation_hashtable_no_addr2_or_port2;
144
145
/*
146
 * Hash table for conversations with a single unsigned ID number.
147
 */
148
static wmem_map_t *conversation_hashtable_id;
149
150
/*
151
 * Hash table for conversations with no wildcards, and an anchor
152
 */
153
static wmem_map_t *conversation_hashtable_exact_addr_port_anc = NULL;
154
155
/*
156
 * Hash table for conversations based on addresses only, and an anchor
157
 */
158
static wmem_map_t *conversation_hashtable_exact_addr_anc = NULL;
159
160
/*
161
 * Hash table for conversations with one wildcard address, and an anchor
162
 */
163
static wmem_map_t *conversation_hashtable_no_addr2_anc = NULL;
164
165
/*
166
 * Hash table for conversations with one wildcard port, and an anchor
167
 */
168
static wmem_map_t *conversation_hashtable_no_port2_anc = NULL;
169
170
/*
171
 * Hash table for conversations with one wildcard address and port, and an anchor.
172
 */
173
static wmem_map_t *conversation_hashtable_no_addr2_or_port2_anc;
174
175
/*
176
 * Hash table for deinterlacing conversations (typically L1 or L2)
177
 */
178
static wmem_map_t *conversation_hashtable_deinterlacer = NULL;
179
180
/*
181
 * Hash table for tracking conversations involved in error packets.
182
 * Conversations stored here don't have an autonomous existence,
183
 * strictly speaking, but are a reference to other ones stored in
184
 * other tables (such as conversation_hashtable_exact_addr_port).
185
 * This table should be understood as an outgrowth of other tables.
186
 * Note on this table keys: they are composed of 3 elements:
187
 *  id   : the conv_index for this conversation in this table
188
 *  rid  : reference conv_index for the transport conversation
189
 *         stored in table conversation_hashtable_exact_addr_port
190
 *  ctype: conversation type of the transport conversation
191
 */
192
static wmem_map_t *conversation_hashtable_err_pkts = NULL;
193
194
static uint32_t new_index;
195
196
/*
197
 * Placeholder for address-less conversations.
198
 */
199
static address null_address_ = ADDRESS_INIT_NONE;
200
201
202
/* Element count including the terminating CE_CONVERSATION_TYPE */
203
#define MAX_CONVERSATION_ELEMENTS 8 // Arbitrary.
204
static size_t
205
conversation_element_count(conversation_element_t *elements)
206
15.6k
{
207
15.6k
    size_t count = 0;
208
48.6k
    while (elements[count].type != CE_CONVERSATION_TYPE) {
209
33.0k
        count++;
210
33.0k
        DISSECTOR_ASSERT(count < MAX_CONVERSATION_ELEMENTS);
211
33.0k
    }
212
15.6k
    count++;
213
    // Keying on the endpoint type alone isn't very useful.
214
15.6k
    DISSECTOR_ASSERT(count > 1);
215
15.6k
    return count;
216
15.6k
}
217
218
static conversation_type
219
conversation_get_key_type(conversation_element_t *elements)
220
0
{
221
0
    size_t count = 0;
222
0
    while (elements[count].type != CE_CONVERSATION_TYPE) {
223
0
        count++;
224
0
        DISSECTOR_ASSERT(count < MAX_CONVERSATION_ELEMENTS);
225
0
    }
226
0
    return elements[count].conversation_type_val;
227
0
}
228
229
/* Create a string based on element types. */
230
static char*
231
14.3k
conversation_element_list_name(wmem_allocator_t *allocator, conversation_element_t *elements) {
232
14.3k
    char *sep = "";
233
14.3k
    wmem_strbuf_t *conv_hash_group = wmem_strbuf_new(allocator, "");
234
14.3k
    size_t element_count = conversation_element_count(elements);
235
58.4k
    for (size_t i = 0; i < element_count; i++) {
236
44.0k
        conversation_element_t *cur_el = &elements[i];
237
44.0k
        DISSECTOR_ASSERT(cur_el->type < array_length(type_names));
238
44.0k
        wmem_strbuf_append_printf(conv_hash_group, "%s%s", sep, type_names[cur_el->type]);
239
44.0k
        sep = ",";
240
44.0k
    }
241
14.3k
    return wmem_strbuf_finalize(conv_hash_group);
242
14.3k
}
243
244
#if 0 // debugging
245
static char* conversation_element_list_values(conversation_element_t *elements) {
246
    char *sep = "";
247
    GString *value_str = g_string_new("");
248
    size_t element_count = conversation_element_count(elements);
249
    for (size_t i = 0; i < element_count; i++) {
250
        conversation_element_t *cur_el = &elements[i];
251
        g_string_append_printf(value_str, "%s%s=", sep, type_names[cur_el->type]);
252
        sep = ",";
253
        switch (cur_el->type) {
254
        case CE_CONVERSATION_TYPE:
255
            g_string_append_printf(value_str, "%d", cur_el->conversation_type_val);
256
            break;
257
        case CE_ADDRESS:
258
        {
259
            char *as = address_to_str(NULL, &cur_el->addr_val);
260
            g_string_append(value_str, as);
261
            g_free(as);
262
        }
263
            break;
264
        case CE_PORT:
265
            g_string_append_printf(value_str, "%u", cur_el->port_val);
266
            break;
267
        case CE_STRING:
268
            g_string_append(value_str, cur_el->str_val);
269
            break;
270
        case CE_UINT:
271
            g_string_append_printf(value_str, "%u", cur_el->uint_val);
272
            break;
273
        case CE_UINT64:
274
            g_string_append_printf(value_str, "%" PRIu64, cur_el->uint64_val);
275
            break;
276
        case CE_INT:
277
            g_string_append_printf(value_str, "%d", cur_el->int_val);
278
            break;
279
        case CE_INT64:
280
            g_string_append_printf(value_str, "%" PRId64, cur_el->int64_val);
281
            break;
282
        case CE_BLOB:
283
        {
284
            size_t l;
285
            uint8_t const *p;
286
            for (l = cur_el->blob.len, p = cur_el->blob.val; l > 0; l--, p++)
287
                g_string_append_printf(value_str, "%02x", *p);
288
        }
289
            break;
290
        }
291
    }
292
    return g_string_free(value_str, FALSE);
293
}
294
#endif
295
296
static bool
297
is_no_addr2_key(conversation_element_t *key)
298
0
{
299
0
    if (key[ADDR1_IDX].type == CE_ADDRESS && key[PORT1_IDX].type == CE_PORT
300
0
            && key[PORT2_NO_ADDR2_IDX].type == CE_PORT && key[ENDP_NO_ADDR2_IDX].type == CE_CONVERSATION_TYPE) {
301
0
        return true;
302
0
    }
303
0
    return false;
304
0
}
305
306
static bool
307
is_no_port2_key(conversation_element_t *key)
308
0
{
309
0
    if (key[ADDR1_IDX].type == CE_ADDRESS && key[PORT1_IDX].type == CE_PORT
310
0
            && key[ADDR2_IDX].type == CE_ADDRESS && key[ENDP_NO_PORT2_IDX].type == CE_CONVERSATION_TYPE) {
311
0
        return true;
312
0
    }
313
0
    return false;
314
0
}
315
316
static bool
317
is_no_addr2_port2_key(conversation_element_t *key)
318
0
{
319
0
    if (key[ADDR1_IDX].type == CE_ADDRESS && key[PORT1_IDX].type == CE_PORT
320
0
            && key[ENDP_NO_ADDR2_PORT2_IDX].type == CE_CONVERSATION_TYPE) {
321
0
        return true;
322
0
    }
323
0
    return false;
324
0
}
325
326
/*
327
 * Creates a new conversation with known endpoints based on a conversation
328
 * created with the CONVERSATION_TEMPLATE option while keeping the
329
 * conversation created with the CONVERSATION_TEMPLATE option so it can still
330
 * match future connections.
331
 *
332
 * Passing a pointer to a conversation whose options mask does not include
333
 * CONVERSATION_TEMPLATE or where the conversation's protocol type (ptype)
334
 * indicates a non-connnection oriented protocol will return the conversation
335
 * without changes.
336
 *
337
 * addr2 and port2 are used in the function if their respective conversation
338
 * options bits are set (NO_ADDR2 and NO_PORT2).
339
 */
340
static conversation_t *
341
conversation_create_from_template(conversation_t *conversation, const address *addr2, const uint32_t port2)
342
0
{
343
0
    conversation_type ctype = conversation_get_key_type(conversation->key_ptr);
344
    /*
345
     * Add a new conversation and keep the conversation template only if the
346
     * CONVERSATION_TEMPLATE bit is set for a connection oriented protocol.
347
     */
348
0
    if (conversation->options & CONVERSATION_TEMPLATE && ctype != CONVERSATION_UDP)
349
0
    {
350
        /*
351
         * Set up a new options mask where the conversation template bit and the
352
         * bits for absence of a second address and port pair have been removed.
353
         */
354
0
        conversation_t *new_conversation_from_template;
355
0
        unsigned options = conversation->options & ~(CONVERSATION_TEMPLATE | NO_ADDR2 | NO_PORT2);
356
357
        /*
358
         * Are both the NO_ADDR2 and NO_PORT2 wildcards set in the options mask?
359
         */
360
0
        if (conversation->options & NO_ADDR2 && conversation->options & NO_PORT2
361
0
                && is_no_addr2_port2_key(conversation->key_ptr))
362
0
        {
363
            /*
364
             * The conversation template was created without knowledge of both
365
             * the second address as well as the second port. Create a new
366
             * conversation with new 2nd address and 2nd port.
367
             */
368
0
            new_conversation_from_template =
369
0
                conversation_new(conversation->setup_frame,
370
0
                        &conversation->key_ptr[ADDR1_IDX].addr_val, addr2,
371
0
                        ctype, conversation->key_ptr[PORT1_IDX].port_val,
372
0
                        port2, options);
373
0
        }
374
0
        else if (conversation->options & NO_PORT2 && is_no_port2_key(conversation->key_ptr))
375
0
        {
376
            /*
377
             * The conversation template was created without knowledge of port 2
378
             * only. Create a new conversation with new 2nd port.
379
             */
380
0
            new_conversation_from_template =
381
0
                conversation_new(conversation->setup_frame,
382
0
                        &conversation->key_ptr[ADDR1_IDX].addr_val, &conversation->key_ptr[ADDR2_IDX].addr_val,
383
0
                        ctype, conversation->key_ptr[PORT1_IDX].port_val,
384
0
                        port2, options);
385
0
        }
386
0
        else if (conversation->options & NO_ADDR2 && is_no_addr2_key(conversation->key_ptr))
387
0
        {
388
            /*
389
             * The conversation template was created without knowledge of address
390
             * 2. Create a new conversation with new 2nd address.
391
             */
392
0
            new_conversation_from_template =
393
0
                conversation_new(conversation->setup_frame,
394
0
                        &conversation->key_ptr[ADDR1_IDX].addr_val, addr2,
395
0
                        ctype, conversation->key_ptr[PORT1_IDX].port_val,
396
0
                        conversation->key_ptr[PORT2_NO_ADDR2_IDX].port_val, options);
397
0
        }
398
0
        else
399
0
        {
400
            /*
401
             * The CONVERSATION_TEMPLATE bit was set, but no other bit that the
402
             * CONVERSATION_TEMPLATE bit controls is active. Just return the old
403
             * conversation.
404
             */
405
0
            return conversation;
406
0
        }
407
408
        /*
409
         * Set the protocol dissector used for the template conversation as
410
         * the handler of the new conversation as well.
411
         */
412
0
        new_conversation_from_template->dissector_tree = conversation->dissector_tree;
413
414
0
        return new_conversation_from_template;
415
0
    }
416
0
    else
417
0
    {
418
0
        return conversation;
419
0
    }
420
0
}
421
422
/*
423
 * Compute the hash value for two given element lists if the match
424
 * is to be exact.
425
 */
426
/* https://web.archive.org/web/20070615045827/http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx#existing
427
 * (formerly at http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx#existing)
428
 * One-at-a-Time hash
429
 */
430
static unsigned
431
conversation_hash_element_list(const void *v)
432
1.80M
{
433
1.80M
    const conversation_element_t *element = (const conversation_element_t*)v;
434
1.80M
    unsigned hash_val = 0;
435
436
7.30M
    for (;;) {
437
        // XXX We could use a hash_arbitrary_bytes routine. Abuse add_address_to_hash in the mean time.
438
7.30M
        address tmp_addr;
439
7.30M
        switch (element->type) {
440
3.00M
        case CE_ADDRESS:
441
3.00M
            hash_val = add_address_to_hash(hash_val, &element->addr_val);
442
3.00M
            break;
443
2.45M
        case CE_PORT:
444
2.45M
            tmp_addr.len = (int) sizeof(element->port_val);
445
2.45M
            tmp_addr.data = &element->port_val;
446
2.45M
            hash_val = add_address_to_hash(hash_val, &tmp_addr);
447
2.45M
            break;
448
0
        case CE_STRING:
449
0
            tmp_addr.len = (int) strlen(element->str_val);
450
0
            tmp_addr.data = element->str_val;
451
0
            hash_val = add_address_to_hash(hash_val, &tmp_addr);
452
0
            break;
453
13.8k
        case CE_UINT:
454
13.8k
            tmp_addr.len = (int) sizeof(element->uint_val);
455
13.8k
            tmp_addr.data = &element->uint_val;
456
13.8k
            hash_val = add_address_to_hash(hash_val, &tmp_addr);
457
13.8k
            break;
458
28.5k
        case CE_UINT64:
459
28.5k
            tmp_addr.len = (int) sizeof(element->uint64_val);
460
28.5k
            tmp_addr.data = &element->uint64_val;
461
28.5k
            hash_val = add_address_to_hash(hash_val, &tmp_addr);
462
28.5k
            break;
463
0
        case CE_INT:
464
0
            tmp_addr.len = (int) sizeof(element->int_val);
465
0
            tmp_addr.data = &element->int_val;
466
0
            hash_val = add_address_to_hash(hash_val, &tmp_addr);
467
0
            break;
468
0
        case CE_INT64:
469
0
            tmp_addr.len = (int) sizeof(element->int64_val);
470
0
            tmp_addr.data = &element->int64_val;
471
0
            hash_val = add_address_to_hash(hash_val, &tmp_addr);
472
0
            break;
473
0
        case CE_BLOB:
474
0
            tmp_addr.len = (int) element->blob.len;
475
0
            tmp_addr.data = element->blob.val;
476
0
            hash_val = add_address_to_hash(hash_val, &tmp_addr);
477
0
            break;
478
1.80M
        case CE_CONVERSATION_TYPE:
479
1.80M
            tmp_addr.len = (int) sizeof(element->conversation_type_val);
480
1.80M
            tmp_addr.data = &element->conversation_type_val;
481
1.80M
            hash_val = add_address_to_hash(hash_val, &tmp_addr);
482
1.80M
            goto done;
483
0
            break;
484
7.30M
        }
485
5.50M
        element++;
486
5.50M
    }
487
488
1.80M
done:
489
1.80M
    hash_val += ( hash_val << 3 );
490
1.80M
    hash_val ^= ( hash_val >> 11 );
491
1.80M
    hash_val += ( hash_val << 15 );
492
493
1.80M
    return hash_val;
494
1.80M
}
495
496
/*
497
 * Compare two conversation keys for an exact match.
498
 */
499
static gboolean
500
conversation_match_element_list(const void *v1, const void *v2)
501
487k
{
502
487k
    const conversation_element_t *element1 = (const conversation_element_t*)v1;
503
487k
    const conversation_element_t *element2 = (const conversation_element_t*)v2;
504
505
2.21M
    for (;;) {
506
2.21M
        if (element1->type != element2->type) {
507
0
            return FALSE;
508
0
        }
509
510
2.21M
        switch (element1->type) {
511
936k
        case CE_ADDRESS:
512
936k
            if (!addresses_equal(&element1->addr_val, &element2->addr_val)) {
513
652
                return FALSE;
514
652
            }
515
936k
            break;
516
936k
        case CE_PORT:
517
767k
            if (element1->port_val != element2->port_val) {
518
0
                return FALSE;
519
0
            }
520
767k
            break;
521
767k
        case CE_STRING:
522
0
            if (strcmp(element1->str_val, element2->str_val)) {
523
0
                return FALSE;
524
0
            }
525
0
            break;
526
6.82k
        case CE_UINT:
527
6.82k
            if (element1->uint_val != element2->uint_val) {
528
0
                return FALSE;
529
0
            }
530
6.82k
            break;
531
22.2k
        case CE_UINT64:
532
22.2k
            if (element1->uint64_val != element2->uint64_val) {
533
0
                return FALSE;
534
0
            }
535
22.2k
            break;
536
22.2k
        case CE_INT:
537
0
            if (element1->int_val != element2->int_val) {
538
0
                return FALSE;
539
0
            }
540
0
            break;
541
0
        case CE_INT64:
542
0
            if (element1->int64_val != element2->int64_val) {
543
0
                return FALSE;
544
0
            }
545
0
            break;
546
0
        case CE_BLOB:
547
0
            if (element1->blob.len != element2->blob.len ||
548
0
                (element1->blob.len > 0 && memcmp(element1->blob.val, element2->blob.val, element1->blob.len) != 0)) {
549
0
                return FALSE;
550
0
            }
551
0
            break;
552
486k
        case CE_CONVERSATION_TYPE:
553
486k
            if (element1->conversation_type_val != element2->conversation_type_val) {
554
0
                return FALSE;
555
0
            }
556
486k
            goto done;
557
486k
            break;
558
2.21M
        }
559
1.73M
        element1++;
560
1.73M
        element2++;
561
1.73M
    }
562
563
486k
    done:
564
    // Everything matched so far.
565
486k
    return TRUE;
566
487k
}
567
568
/**
569
 * Create a new hash tables for conversations.
570
 */
571
void
572
conversation_init(void)
573
14
{
574
    /*
575
     * Free up any space allocated for conversation protocol data
576
     * areas.
577
     *
578
     * We can free the space, as the structures it contains are
579
     * pointed to by conversation data structures that were freed
580
     * above.
581
     */
582
14
    conversation_hashtable_element_list = wmem_map_new(wmem_epan_scope(), wmem_str_hash, g_str_equal);
583
584
14
    conversation_element_t exact_elements[EXACT_IDX_COUNT] = {
585
14
        { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE },
586
14
        { CE_PORT, .port_val = 0 },
587
14
        { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE },
588
14
        { CE_PORT, .port_val = 0 },
589
14
        { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
590
14
    };
591
14
    char *exact_map_key = conversation_element_list_name(wmem_epan_scope(), exact_elements);
592
14
    conversation_hashtable_exact_addr_port = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
593
14
                                                                    conversation_hash_element_list,
594
14
                                                                    conversation_match_element_list);
595
14
    wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), exact_map_key),
596
14
                    conversation_hashtable_exact_addr_port);
597
598
14
    conversation_element_t addrs_elements[ADDRS_IDX_COUNT] = {
599
14
        { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE },
600
14
        { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE },
601
14
        { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
602
14
    };
603
14
    char *addrs_map_key = conversation_element_list_name(wmem_epan_scope(), addrs_elements);
604
14
    conversation_hashtable_exact_addr = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
605
14
                                                                    conversation_hash_element_list,
606
14
                                                                    conversation_match_element_list);
607
14
    wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), addrs_map_key),
608
14
                    conversation_hashtable_exact_addr);
609
610
14
    conversation_element_t no_addr2_elements[NO_ADDR2_IDX_COUNT] = {
611
14
        { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE },
612
14
        { CE_PORT, .port_val = 0 },
613
14
        { CE_PORT, .port_val = 0 },
614
14
        { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
615
14
    };
616
14
    char *no_addr2_map_key = conversation_element_list_name(wmem_epan_scope(), no_addr2_elements);
617
14
    conversation_hashtable_no_addr2 = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
618
14
                                                       conversation_hash_element_list,
619
14
                                                       conversation_match_element_list);
620
14
    wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), no_addr2_map_key),
621
14
                    conversation_hashtable_no_addr2);
622
623
14
    conversation_element_t no_port2_elements[NO_PORT2_IDX_COUNT] = {
624
14
        { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE },
625
14
        { CE_PORT, .port_val = 0 },
626
14
        { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE },
627
14
        { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
628
14
    };
629
14
    char *no_port2_map_key = conversation_element_list_name(wmem_epan_scope(), no_port2_elements);
630
14
    conversation_hashtable_no_port2 = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
631
14
                                                       conversation_hash_element_list,
632
14
                                                       conversation_match_element_list);
633
14
    wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), no_port2_map_key),
634
14
                    conversation_hashtable_no_port2);
635
636
14
    conversation_element_t no_addr2_or_port2_elements[NO_ADDR2_PORT2_IDX_COUNT] = {
637
14
        { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE },
638
14
        { CE_PORT, .port_val = 0 },
639
14
        { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
640
14
    };
641
14
    char *no_addr2_or_port2_map_key = conversation_element_list_name(wmem_epan_scope(), no_addr2_or_port2_elements);
642
14
    conversation_hashtable_no_addr2_or_port2 = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
643
14
                                                                    conversation_hash_element_list,
644
14
                                                                    conversation_match_element_list);
645
14
    wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), no_addr2_or_port2_map_key),
646
14
                    conversation_hashtable_no_addr2_or_port2);
647
648
14
    conversation_element_t id_elements[2] = {
649
14
        { CE_UINT, .uint_val = 0 },
650
14
        { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
651
14
    };
652
14
    char *id_map_key = conversation_element_list_name(wmem_epan_scope(), id_elements);
653
14
    conversation_hashtable_id = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
654
14
                                                       conversation_hash_element_list,
655
14
                                                       conversation_match_element_list);
656
14
    wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), id_map_key),
657
14
                    conversation_hashtable_id);
658
659
    /*
660
     * Initialize the "deinterlacer" table, which is used as the basis for the
661
     * deinterlacing process, and in conjunction with the "anchor" tables
662
     *
663
     * Typically the elements are:
664
     *   ETH address 1
665
     *   ETH address 2
666
     *   Interface id
667
     *   VLAN id
668
     *   not used yet
669
     *
670
     * By the time of implementation, these table is invoked through the
671
     * conversation_deinterlacing_key user preference.
672
     */
673
14
    conversation_element_t deinterlacer_elements[EXACT_IDX_COUNT+1] = {
674
14
        { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE },
675
14
        { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE },
676
14
        { CE_UINT, .port_val = 0 },
677
14
        { CE_UINT, .port_val = 0 },
678
14
        { CE_UINT, .uint_val = 0 },
679
14
        { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
680
14
    };
681
14
    char *deinterlacer_map_key = conversation_element_list_name(wmem_epan_scope(), deinterlacer_elements);
682
14
    conversation_hashtable_deinterlacer = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
683
14
                                                                    conversation_hash_element_list,
684
14
                                                                    conversation_match_element_list);
685
14
    wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), deinterlacer_map_key),
686
14
                    conversation_hashtable_deinterlacer);
687
688
    /*
689
     * Initialize the "_anc" tables, which are very similar to their standard counterparts
690
     * but contain an additional "anchor" materialized as an integer. This value is supposed
691
     * to indicate a stream ID of the underlying protocol, thus attaching two conversations
692
     * of two protocols together.
693
     *
694
     * By the time of implementation, these table is invoked through the
695
     * conversation_deinterlacing_key user preference.
696
     */
697
14
    conversation_element_t exact_elements_anc[EXACT_IDX_COUNT+1] = {
698
14
        { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE },
699
14
        { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE },
700
14
        { CE_PORT, .port_val = 0 },
701
14
        { CE_PORT, .port_val = 0 },
702
14
        { CE_UINT, .uint_val = 0 },
703
14
        { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
704
14
    };
705
14
    char *exact_anc_map_key = conversation_element_list_name(wmem_epan_scope(), exact_elements_anc);
706
14
    conversation_hashtable_exact_addr_port_anc = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
707
14
                                                                    conversation_hash_element_list,
708
14
                                                                    conversation_match_element_list);
709
14
    wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), exact_anc_map_key),
710
14
                    conversation_hashtable_exact_addr_port_anc);
711
712
14
    conversation_element_t addrs_elements_anc[ADDRS_IDX_COUNT+1] = {
713
14
        { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE },
714
14
        { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE },
715
14
        { CE_UINT, .uint_val = 0 },
716
14
        { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
717
14
    };
718
14
    char *addrs_anc_map_key = conversation_element_list_name(wmem_epan_scope(), addrs_elements_anc);
719
14
    conversation_hashtable_exact_addr_anc = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
720
14
                                                                    conversation_hash_element_list,
721
14
                                                                    conversation_match_element_list);
722
14
    wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), addrs_anc_map_key),
723
14
                    conversation_hashtable_exact_addr_anc);
724
725
14
    conversation_element_t no_addr2_elements_anc[DEINTD_NO_PORT2_IDX_COUNT] = {
726
14
        { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE },
727
14
        { CE_PORT, .port_val = 0 },
728
14
        { CE_PORT, .port_val = 0 },
729
14
        { CE_UINT, .uint_val = 0 },
730
14
        { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
731
14
    };
732
14
    char *no_addr2_anc_map_key = conversation_element_list_name(wmem_epan_scope(), no_addr2_elements_anc);
733
14
    conversation_hashtable_no_addr2_anc = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
734
14
                                                                    conversation_hash_element_list,
735
14
                                                                    conversation_match_element_list);
736
14
    wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), no_addr2_anc_map_key),
737
14
                    conversation_hashtable_no_addr2_anc);
738
739
14
    conversation_element_t no_port2_elements_anc[DEINTD_NO_PORT2_IDX_COUNT] = {
740
14
        { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE },
741
14
        { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE },
742
14
        { CE_PORT, .port_val = 0 },
743
14
        { CE_UINT, .uint_val = 0 },
744
14
        { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
745
14
    };
746
14
    char *no_port2_anc_map_key = conversation_element_list_name(wmem_epan_scope(), no_port2_elements_anc);
747
14
    conversation_hashtable_no_port2_anc = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
748
14
                                                                    conversation_hash_element_list,
749
14
                                                                    conversation_match_element_list);
750
14
    wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), no_port2_anc_map_key),
751
14
                    conversation_hashtable_no_port2_anc);
752
753
14
    conversation_element_t no_addr2_or_port2_elements_anc[DEINTD_NO_ADDR2_PORT2_IDX_COUNT] = {
754
14
        { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE },
755
14
        { CE_PORT, .port_val = 0 },
756
14
        { CE_UINT, .uint_val = 0 },
757
14
        { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
758
14
    };
759
14
    char *no_addr2_or_port2_anc_map_key = conversation_element_list_name(wmem_epan_scope(), no_addr2_or_port2_elements_anc);
760
14
    conversation_hashtable_no_addr2_or_port2_anc = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
761
14
                                                                    conversation_hash_element_list,
762
14
                                                                    conversation_match_element_list);
763
14
    wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), no_addr2_or_port2_anc_map_key),
764
14
                    conversation_hashtable_no_addr2_or_port2_anc);
765
766
14
    conversation_element_t err_pkts_elements[ERR_PKTS_COUNT] = {
767
14
        { CE_UINT, .uint_val = 0 },
768
14
        { CE_UINT, .uint_val = 0 },
769
14
        { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
770
14
    };
771
14
    char *err_pkts_map_key = conversation_element_list_name(wmem_epan_scope(), err_pkts_elements);
772
14
    conversation_hashtable_err_pkts = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
773
14
                                                       conversation_hash_element_list,
774
14
                                                       conversation_match_element_list);
775
14
    wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), err_pkts_map_key),
776
14
                    conversation_hashtable_err_pkts);
777
778
14
}
779
780
/**
781
 * Initialize some variables every time a file is loaded or re-loaded.
782
 */
783
void
784
conversation_epan_reset(void)
785
14
{
786
    /*
787
     * Start the conversation indices over at 0.
788
     */
789
14
    new_index = 0;
790
14
}
791
792
/*
793
 * Does the right thing when inserting into one of the conversation hash tables,
794
 * taking into account ordering and hash chains and all that good stuff.
795
 *
796
 * Mostly adapted from the old conversation_new().
797
 */
798
static void
799
conversation_insert_into_hashtable(wmem_map_t *hashtable, conversation_t *conv)
800
71.6k
{
801
71.6k
    conversation_t *chain_head, *chain_tail, *cur, *prev;
802
803
71.6k
    chain_head = (conversation_t *)wmem_map_lookup(hashtable, conv->key_ptr);
804
805
71.6k
    if (NULL==chain_head) {
806
        /* New entry */
807
63.8k
        conv->next = NULL;
808
63.8k
        conv->last = conv;
809
810
63.8k
        wmem_map_insert(hashtable, conv->key_ptr, conv);
811
63.8k
        DPRINT(("created a new conversation chain"));
812
63.8k
    }
813
7.79k
    else {
814
        /* There's an existing chain for this key */
815
7.79k
        DPRINT(("there's an existing conversation chain"));
816
817
7.79k
        chain_tail = chain_head->last;
818
819
7.79k
        if (conv->setup_frame >= chain_tail->setup_frame) {
820
            /* This convo belongs at the end of the chain */
821
7.79k
            conv->next = NULL;
822
7.79k
            conv->last = NULL;
823
7.79k
            chain_tail->next = conv;
824
7.79k
            chain_head->last = conv;
825
7.79k
        }
826
0
        else {
827
            /* Loop through the chain to find the right spot */
828
0
            cur = chain_head;
829
0
            prev = NULL;
830
831
0
            for (; (conv->setup_frame > cur->setup_frame) && cur->next; prev=cur, cur=cur->next)
832
0
                ;
833
834
0
            if (NULL==prev) {
835
                /* Changing the head of the chain */
836
0
                conv->next = chain_head;
837
0
                conv->last = chain_tail;
838
0
                chain_head->last = NULL;
839
0
                wmem_map_insert(hashtable, conv->key_ptr, conv);
840
0
            }
841
0
            else {
842
                /* Inserting into the middle of the chain */
843
0
                conv->next = cur;
844
0
                conv->last = NULL;
845
0
                prev->next = conv;
846
0
            }
847
0
        }
848
7.79k
    }
849
71.6k
}
850
851
/*
852
 * Does the right thing when removing from one of the conversation hash tables,
853
 * taking into account ordering and hash chains and all that good stuff.
854
 */
855
static void
856
conversation_remove_from_hashtable(wmem_map_t *hashtable, conversation_t *conv)
857
6
{
858
6
    conversation_t *chain_head, *cur, *prev;
859
860
6
    chain_head = (conversation_t *)wmem_map_lookup(hashtable, conv->key_ptr);
861
862
6
    if (conv == chain_head) {
863
        /* We are currently the front of the chain */
864
6
        if (NULL == conv->next) {
865
            /* We are the only conversation in the chain, no need to
866
             * update next pointer, but do not call
867
             * wmem_map_remove() either because the conv data
868
             * will be re-inserted. */
869
6
            wmem_map_steal(hashtable, conv->key_ptr);
870
6
        }
871
0
        else {
872
            /* Update the head of the chain */
873
0
            chain_head = conv->next;
874
0
            chain_head->last = conv->last;
875
876
0
            if (conv->latest_found == conv)
877
0
                chain_head->latest_found = NULL;
878
0
            else
879
0
                chain_head->latest_found = conv->latest_found;
880
881
0
            wmem_map_insert(hashtable, chain_head->key_ptr, chain_head);
882
0
        }
883
6
    }
884
0
    else {
885
        /* We are not the front of the chain. Loop through to find us.
886
         * Start loop at chain_head->next rather than chain_head because
887
         * we already know we're not at the head. */
888
0
        cur = chain_head->next;
889
0
        prev = chain_head;
890
891
0
        for (; (cur != conv) && cur->next; prev=cur, cur=cur->next)
892
0
            ;
893
894
0
        if (cur != conv) {
895
            /* XXX: Conversation not found. Wrong hashtable? */
896
0
            return;
897
0
        }
898
899
0
        prev->next = conv->next;
900
901
0
        if (NULL == conv->next) {
902
            /* We're at the very end of the list. */
903
0
            chain_head->last = prev;
904
0
        }
905
906
0
        if (chain_head->latest_found == conv)
907
0
            chain_head->latest_found = prev;
908
0
    }
909
6
}
910
911
conversation_t *conversation_new_full(const uint32_t setup_frame, conversation_element_t *elements)
912
1.33k
{
913
1.33k
    DISSECTOR_ASSERT(elements);
914
915
1.33k
    char *el_list_map_key = conversation_element_list_name(wmem_epan_scope(), elements);
916
1.33k
    wmem_map_t *el_list_map = (wmem_map_t *) wmem_map_lookup(conversation_hashtable_element_list, el_list_map_key);
917
1.33k
    if (!el_list_map) {
918
3
        el_list_map = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), conversation_hash_element_list,
919
3
                conversation_match_element_list);
920
3
        wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), el_list_map_key), el_list_map);
921
3
    }
922
923
1.33k
    size_t element_count = conversation_element_count(elements);
924
1.33k
    conversation_element_t *conv_key = wmem_memdup(wmem_file_scope(), elements, sizeof(conversation_element_t) * element_count);
925
5.93k
    for (size_t i = 0; i < element_count; i++) {
926
4.60k
        if (conv_key[i].type == CE_ADDRESS) {
927
446
            copy_address_wmem(wmem_file_scope(), &conv_key[i].addr_val, &elements[i].addr_val);
928
4.15k
        } else if (conv_key[i].type == CE_STRING) {
929
0
            conv_key[i].str_val = wmem_strdup(wmem_file_scope(), elements[i].str_val);
930
4.15k
        } else if (conv_key[i].type == CE_BLOB) {
931
0
            conv_key[i].blob.val = wmem_memdup(wmem_file_scope(), elements[i].blob.val, elements[i].blob.len);
932
0
        }
933
4.60k
    }
934
935
1.33k
    conversation_t *conversation = wmem_new0(wmem_file_scope(), conversation_t);
936
1.33k
    conversation->conv_index = new_index;
937
1.33k
    conversation->setup_frame = conversation->last_frame = setup_frame;
938
939
1.33k
    new_index++;
940
941
1.33k
    conversation->key_ptr = conv_key;
942
1.33k
    conversation_insert_into_hashtable(el_list_map, conversation);
943
1.33k
    return conversation;
944
1.33k
}
945
946
/*
947
 * Given two address/port pairs for a packet, create a new conversation
948
 * to contain packets between those address/port pairs.
949
 *
950
 * The options field is used to specify whether the address 2 value
951
 * and/or port 2 value are not given and any value is acceptable
952
 * when searching for this conversation.
953
 */
954
conversation_t *
955
conversation_new(const uint32_t setup_frame, const address *addr1, const address *addr2,
956
        const conversation_type ctype, const uint32_t port1, const uint32_t port2, const unsigned options)
957
69.2k
{
958
    /*
959
       DISSECTOR_ASSERT(!(options | CONVERSATION_TEMPLATE) || ((options | (NO_ADDR2 | NO_PORT2 | NO_PORT2_FORCE))) &&
960
       "A conversation template may not be constructed without wildcard options");
961
     */
962
69.2k
    wmem_map_t* hashtable;
963
69.2k
    conversation_t *conversation = NULL;
964
    /*
965
     * Verify that the correct options are used, if any.
966
     */
967
69.2k
    DISSECTOR_ASSERT_HINT(!(options & NO_MASK_B), "Use NO_ADDR2 and/or NO_PORT2 or NO_PORT2_FORCE as option");
968
969
#ifdef DEBUG_CONVERSATION
970
    char *addr1_str, *addr2_str;
971
    if (addr1 == NULL) {
972
        /*
973
         * No address 1.
974
         */
975
        if (options & NO_ADDR2) {
976
            /*
977
             * Neither address 1 nor address 2.
978
             */
979
            if (options & NO_PORT2) {
980
                /*
981
                 * Port 1 but not port 2.
982
                 */
983
                DPRINT(("creating conversation for frame #%u: ID %u (ctype=%d)",
984
                            setup_frame, port1, ctype));
985
            } else {
986
                /*
987
                 * Ports 1 and 2.
988
                 */
989
                DPRINT(("creating conversation for frame #%u: %u -> %u (ctype=%d)",
990
                            setup_frame, port1, port2, ctype));
991
            }
992
        } else {
993
            /*
994
             * Address 2 but not address 1.
995
             */
996
            addr2_str = address_to_str(NULL, addr2);
997
            if (options & NO_PORT2) {
998
                /*
999
                 * Port 1 but not port 2.
1000
                 */
1001
                DPRINT(("creating conversation for frame #%u: ID %u, address %s (ctype=%d)",
1002
                            setup_frame, port1, addr2_str, ctype));
1003
            } else {
1004
                /*
1005
                 * Ports 1 and 2.
1006
                 */
1007
                DPRINT(("creating conversation for frame #%u: %u -> %s:%u (ctype=%d)",
1008
                            setup_frame, port1, addr2_str, port2, ctype));
1009
            }
1010
            wmem_free(NULL, addr2_str);
1011
        }
1012
    } else {
1013
        /*
1014
         * Address 1.
1015
         */
1016
        addr1_str = address_to_str(NULL, addr1);
1017
        if (options & NO_ADDR2) {
1018
            /*
1019
             * Address 1 but no address 2.
1020
             */
1021
            if (options & NO_PORT2) {
1022
                /*
1023
                 * Port 1 but not port 2.
1024
                 */
1025
                DPRINT(("creating conversation for frame #%u: %s:%u (ctype=%d)",
1026
                            setup_frame, addr1_str, port1, ctype));
1027
            } else {
1028
                /*
1029
                 * Ports 1 and 2.
1030
                 */
1031
                DPRINT(("creating conversation for frame #%u: %s:%u -> %u (ctype=%d)",
1032
                            setup_frame, addr1_str, port1, port2, ctype));
1033
            }
1034
        } else {
1035
            /*
1036
             * Addresses 1 and 2.
1037
             */
1038
            addr2_str = address_to_str(NULL, addr2);
1039
            if (options & NO_PORT2) {
1040
                /*
1041
                 * Port 1 but not port 2.
1042
                 */
1043
                DPRINT(("creating conversation for frame #%u: %s:%u -> %s (ctype=%d)",
1044
                            setup_frame, addr1_str, port1, addr2_str, ctype));
1045
            } else if (options & NO_PORTS) {
1046
                /*
1047
                 * No Ports.
1048
                 */
1049
                DPRINT(("creating conversation for frame #%u: %s -> %s (ctype=%d)",
1050
                            setup_frame, addr1_str, addr2_str, ctype));
1051
            } else {
1052
                /*
1053
                 * Ports 1 and 2.
1054
                 */
1055
                DPRINT(("creating conversation for frame #%u: %s:%u -> %s:%u (ctype=%d)",
1056
                            setup_frame, addr1_str, port1, addr2_str, port2, ctype));
1057
            }
1058
            wmem_free(NULL, addr2_str);
1059
        }
1060
        wmem_free(NULL, addr1_str);
1061
    }
1062
#endif
1063
1064
    // Always allocate an "exact"-sized key in case we call conversation_set_port2
1065
    // or conversation_set_addr2 later.
1066
69.2k
    conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * EXACT_IDX_COUNT);
1067
69.2k
    size_t addr2_idx = 0;
1068
69.2k
    size_t port2_idx = 0;
1069
69.2k
    size_t endp_idx;
1070
1071
69.2k
    new_key[ADDR1_IDX].type = CE_ADDRESS;
1072
69.2k
    if (addr1 != NULL) {
1073
69.2k
        copy_address_wmem(wmem_file_scope(), &new_key[ADDR1_IDX].addr_val, addr1);
1074
69.2k
    } else {
1075
0
        clear_address(&new_key[ADDR1_IDX].addr_val);
1076
0
    }
1077
1078
69.2k
    if (!(options & NO_PORTS)) {
1079
36.4k
        new_key[PORT1_IDX].type = CE_PORT;
1080
36.4k
        new_key[PORT1_IDX].port_val = port1;
1081
36.4k
    }
1082
1083
69.2k
    if (options & NO_ADDR2) {
1084
253
        if (options & (NO_PORT2|NO_PORT2_FORCE)) {
1085
251
            hashtable = conversation_hashtable_no_addr2_or_port2;
1086
251
            endp_idx = ENDP_NO_ADDR2_PORT2_IDX;
1087
251
        } else {
1088
2
            hashtable = conversation_hashtable_no_addr2;
1089
2
            port2_idx = PORT2_NO_ADDR2_IDX;
1090
2
            endp_idx = ENDP_NO_ADDR2_IDX;
1091
2
        }
1092
68.9k
    } else {
1093
68.9k
        if (options & (NO_PORT2|NO_PORT2_FORCE)) {
1094
888
            hashtable = conversation_hashtable_no_port2;
1095
888
            addr2_idx = ADDR2_IDX;
1096
888
            endp_idx = ENDP_NO_PORT2_IDX;
1097
68.0k
        } else if (options & NO_PORTS) {
1098
32.7k
            hashtable = conversation_hashtable_exact_addr;
1099
32.7k
            addr2_idx = PORT1_IDX;
1100
32.7k
            endp_idx = ENDP_NO_PORTS_IDX;
1101
35.2k
        } else {
1102
35.2k
            hashtable = conversation_hashtable_exact_addr_port;
1103
35.2k
            addr2_idx = ADDR2_IDX;
1104
35.2k
            port2_idx = PORT2_IDX;
1105
35.2k
            endp_idx = ENDP_EXACT_IDX;
1106
35.2k
        }
1107
68.9k
    }
1108
1109
69.2k
    if (addr2_idx) {
1110
68.9k
        new_key[addr2_idx].type = CE_ADDRESS;
1111
68.9k
        if (addr2 != NULL) {
1112
68.9k
            copy_address_wmem(wmem_file_scope(), &new_key[addr2_idx].addr_val, addr2);
1113
68.9k
        } else {
1114
0
            clear_address(&new_key[addr2_idx].addr_val);
1115
0
        }
1116
68.9k
    }
1117
1118
69.2k
    if (port2_idx) {
1119
35.2k
        new_key[port2_idx].type = CE_PORT;
1120
35.2k
        new_key[port2_idx].port_val = port2;
1121
35.2k
    }
1122
1123
69.2k
    new_key[endp_idx].type = CE_CONVERSATION_TYPE;
1124
69.2k
    new_key[endp_idx].conversation_type_val = ctype;
1125
1126
69.2k
    conversation = wmem_new0(wmem_file_scope(), conversation_t);
1127
1128
69.2k
    conversation->conv_index = new_index;
1129
69.2k
    conversation->setup_frame = conversation->last_frame = setup_frame;
1130
1131
    /* set the options and key pointer */
1132
69.2k
    conversation->options = options;
1133
69.2k
    conversation->key_ptr = new_key;
1134
1135
69.2k
    new_index++;
1136
1137
69.2k
    DINDENT();
1138
69.2k
    conversation_insert_into_hashtable(hashtable, conversation);
1139
69.2k
    DENDENT();
1140
1141
69.2k
    return conversation;
1142
69.2k
}
1143
1144
conversation_t *
1145
conversation_new_strat(const packet_info *pinfo, const conversation_type ctype, const unsigned options)
1146
56.4k
{
1147
56.4k
    conversation_t *conversation = NULL;
1148
56.4k
    bool is_ordinary_conv = true;
1149
1150
    /* deinterlacing is only supported for the Ethernet wtap for now */
1151
56.4k
    if( (pinfo->pseudo_header != NULL)
1152
56.4k
        && (pinfo->rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_ETHERNET)
1153
56.4k
        && (prefs.conversation_deinterlacing_key>0)) {
1154
0
        conversation_t *underlying_conv = find_conversation_deinterlacer_pinfo(pinfo);
1155
0
        if(underlying_conv) {
1156
0
            is_ordinary_conv = false;
1157
0
            conversation = conversation_new_deinterlaced(pinfo->num, &pinfo->src, &pinfo->dst, ctype,
1158
0
                                        pinfo->srcport, pinfo->destport, underlying_conv->conv_index, options);
1159
0
        }
1160
0
    }
1161
1162
56.4k
    if(is_ordinary_conv) {
1163
56.4k
        conversation = conversation_new(pinfo->num, &pinfo->src, &pinfo->dst, ctype, pinfo->srcport, pinfo->destport, options);
1164
56.4k
    }
1165
1166
56.4k
    return conversation;
1167
56.4k
}
1168
1169
conversation_t *
1170
conversation_new_strat_xtd(const packet_info *pinfo, const uint32_t setup_frame, const address *addr1, const address *addr2,
1171
        const conversation_type ctype, const uint32_t port1, const uint32_t port2, const unsigned options)
1172
85
{
1173
85
    conversation_t *conversation = NULL;
1174
85
    bool is_ordinary_conv = true;
1175
1176
    /* deinterlacing is only supported for the Ethernet wtap for now */
1177
85
    if( (pinfo->pseudo_header != NULL)
1178
85
        && (pinfo->rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_ETHERNET)
1179
85
        && (prefs.conversation_deinterlacing_key>0)) {
1180
0
        conversation_t *underlying_conv = find_conversation_deinterlacer_pinfo(pinfo);
1181
0
        if(underlying_conv) {
1182
0
            is_ordinary_conv = false;
1183
0
            conversation = conversation_new_deinterlaced(setup_frame, addr1, addr2, ctype,
1184
0
                                        port1, port2, underlying_conv->conv_index, options);
1185
0
        }
1186
0
    }
1187
1188
85
    if(is_ordinary_conv) {
1189
85
        conversation = conversation_new(setup_frame, addr1, addr2, ctype, port1, port2, options);
1190
85
    }
1191
1192
85
    return conversation;
1193
85
}
1194
1195
conversation_t *
1196
conversation_new_by_id(const uint32_t setup_frame, const conversation_type ctype, const uint32_t id)
1197
64
{
1198
64
    conversation_t *conversation = wmem_new0(wmem_file_scope(), conversation_t);
1199
64
    conversation->conv_index = new_index;
1200
64
    conversation->setup_frame = conversation->last_frame = setup_frame;
1201
1202
64
    new_index++;
1203
1204
64
    conversation_element_t *elements = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * 2);
1205
64
    elements[0].type = CE_UINT;
1206
64
    elements[0].uint_val = id;
1207
64
    elements[1].type = CE_CONVERSATION_TYPE;
1208
64
    elements[1].conversation_type_val = ctype;
1209
64
    conversation->key_ptr = elements;
1210
64
    conversation_insert_into_hashtable(conversation_hashtable_id, conversation);
1211
1212
64
    return conversation;
1213
64
}
1214
1215
conversation_t *
1216
conversation_new_err_pkts(const uint32_t setup_frame, const conversation_type ctype, const uint32_t id, const uint32_t rid)
1217
1.05k
{
1218
1.05k
    conversation_t *conversation = wmem_new0(wmem_file_scope(), conversation_t);
1219
1.05k
    conversation->conv_index = new_index;
1220
1.05k
    conversation->setup_frame = conversation->last_frame = setup_frame;
1221
1222
1.05k
    new_index++;
1223
1224
1.05k
    conversation_element_t *elements = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * 3);
1225
1.05k
    elements[0].type = CE_UINT;
1226
1.05k
    elements[0].uint_val = id;
1227
1.05k
    elements[1].type = CE_UINT;
1228
1.05k
    elements[1].uint_val = rid;
1229
1.05k
    elements[2].type = CE_CONVERSATION_TYPE;
1230
1.05k
    elements[2].conversation_type_val = ctype;
1231
1.05k
    conversation->key_ptr = elements;
1232
1.05k
    conversation_insert_into_hashtable(conversation_hashtable_err_pkts, conversation);
1233
1234
1.05k
    return conversation;
1235
1.05k
}
1236
1237
conversation_t *
1238
conversation_new_deinterlacer(const uint32_t setup_frame, const address *addr1, const address *addr2,
1239
        const conversation_type ctype, const uint32_t key1, const uint32_t key2, const uint32_t key3)
1240
0
{
1241
1242
0
    conversation_t *conversation = wmem_new0(wmem_file_scope(), conversation_t);
1243
0
    conversation->conv_index = new_index;
1244
0
    conversation->setup_frame = conversation->last_frame = setup_frame;
1245
1246
0
    conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * (DEINTR_ENDP_IDX+1));
1247
1248
0
    new_key[DEINTR_ADDR1_IDX].type = CE_ADDRESS;
1249
0
    if (addr1 != NULL) {
1250
0
        copy_address_wmem(wmem_file_scope(), &new_key[DEINTR_ADDR1_IDX].addr_val, addr1);
1251
0
    }
1252
0
    else {
1253
0
        clear_address(&new_key[DEINTR_ADDR1_IDX].addr_val);
1254
0
    }
1255
1256
0
    new_key[DEINTR_ADDR2_IDX].type = CE_ADDRESS;
1257
0
    if (addr2 != NULL) {
1258
0
        copy_address_wmem(wmem_file_scope(), &new_key[DEINTR_ADDR2_IDX].addr_val, addr2);
1259
0
    }
1260
0
    else {
1261
0
        clear_address(&new_key[DEINTR_ADDR2_IDX].addr_val);
1262
0
    }
1263
1264
0
    new_key[DEINTR_KEY1_IDX].type = CE_UINT;
1265
0
    new_key[DEINTR_KEY1_IDX].uint_val = key1;
1266
1267
0
    new_key[DEINTR_KEY2_IDX].type = CE_UINT;
1268
0
    new_key[DEINTR_KEY2_IDX].uint_val = key2;
1269
1270
0
    new_key[DEINTR_KEY3_IDX].type = CE_UINT;
1271
0
    new_key[DEINTR_KEY3_IDX].uint_val = key3;
1272
1273
0
    new_key[DEINTR_ENDP_IDX].type = CE_CONVERSATION_TYPE;
1274
0
    new_key[DEINTR_ENDP_IDX].conversation_type_val = ctype;
1275
1276
0
    conversation->key_ptr = new_key;
1277
1278
0
    new_index++;
1279
1280
0
    conversation_insert_into_hashtable(conversation_hashtable_deinterlacer, conversation);
1281
1282
0
    return conversation;
1283
0
}
1284
1285
conversation_t *
1286
conversation_new_deinterlaced(const uint32_t setup_frame, const address *addr1, const address *addr2,
1287
        const conversation_type ctype, const uint32_t port1, const uint32_t port2, const uint32_t anchor, const unsigned options)
1288
0
{
1289
1290
0
    conversation_t *conversation = wmem_new0(wmem_file_scope(), conversation_t);
1291
0
    conversation->conv_index = new_index;
1292
0
    conversation->setup_frame = conversation->last_frame = setup_frame;
1293
1294
0
    if (options & NO_PORTS) {
1295
0
        conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * (DEINTD_ENDP_NO_PORTS_IDX+2));
1296
1297
0
        new_key[DEINTD_ADDR1_IDX].type = CE_ADDRESS;
1298
0
        if (addr1 != NULL) {
1299
0
            copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR1_IDX].addr_val, addr1);
1300
0
        }
1301
0
        else {
1302
0
          clear_address(&new_key[DEINTD_ADDR1_IDX].addr_val);
1303
0
        }
1304
1305
0
        new_key[DEINTD_ADDR2_IDX].type = CE_ADDRESS;
1306
0
        if (addr2 != NULL) {
1307
0
            copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR2_IDX].addr_val, addr2);
1308
0
        }
1309
0
        else {
1310
0
          clear_address(&new_key[DEINTD_ADDR2_IDX].addr_val);
1311
0
        }
1312
1313
0
        new_key[DEINTD_ENDP_NO_PORTS_IDX].type = CE_UINT;
1314
0
        new_key[DEINTD_ENDP_NO_PORTS_IDX].uint_val = anchor;
1315
1316
0
        new_key[DEINTD_ENDP_NO_PORTS_IDX+ 1].type = CE_CONVERSATION_TYPE;
1317
0
        new_key[DEINTD_ENDP_NO_PORTS_IDX+ 1].conversation_type_val = ctype;
1318
1319
        // set the options and key pointer
1320
0
        conversation->options = options;
1321
0
        conversation->key_ptr = new_key;
1322
1323
0
        new_index++;
1324
1325
0
        conversation_insert_into_hashtable(conversation_hashtable_exact_addr_anc, conversation);
1326
1327
0
        return conversation;
1328
0
    }
1329
0
    else if (options & NO_ADDR2) {
1330
0
        if (options & NO_PORT2) {
1331
1332
0
            conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * (DEINTD_NO_ADDR2_PORT2_IDX_COUNT+1));
1333
1334
0
            new_key[DEINTD_ADDR1_IDX].type = CE_ADDRESS;
1335
0
            if (addr1 != NULL) {
1336
0
                copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR1_IDX].addr_val, addr1);
1337
0
            }
1338
0
            else {
1339
0
                clear_address(&new_key[DEINTD_ADDR1_IDX].addr_val);
1340
0
            }
1341
1342
0
            new_key[DEINTD_PORT1_IDX-1].type = CE_PORT;
1343
0
            new_key[DEINTD_PORT1_IDX-1].port_val = port1;
1344
1345
0
            new_key[DEINTD_NO_ADDR2_PORT2_IDX_COUNT-2].type = CE_UINT;
1346
0
            new_key[DEINTD_NO_ADDR2_PORT2_IDX_COUNT-2].uint_val = anchor;
1347
1348
0
            new_key[DEINTD_NO_ADDR2_PORT2_IDX_COUNT-1].type = CE_CONVERSATION_TYPE;
1349
0
            new_key[DEINTD_NO_ADDR2_PORT2_IDX_COUNT-1].conversation_type_val = ctype;
1350
1351
            // set the options and key pointer
1352
0
            conversation->options = options;
1353
0
            conversation->key_ptr = new_key;
1354
1355
0
            new_index++;
1356
1357
0
            conversation_insert_into_hashtable(conversation_hashtable_no_addr2_or_port2_anc, conversation);
1358
1359
0
            return conversation;
1360
0
        }
1361
1362
0
        else {
1363
0
            conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * (DEINTD_NO_ADDR2_IDX_COUNT+1));
1364
1365
0
            new_key[DEINTD_ADDR1_IDX].type = CE_ADDRESS;
1366
0
            if (addr1 != NULL) {
1367
0
                copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR1_IDX].addr_val, addr1);
1368
0
            }
1369
0
            else {
1370
0
                clear_address(&new_key[DEINTD_ADDR1_IDX].addr_val);
1371
0
            }
1372
1373
0
            new_key[DEINTD_PORT1_IDX-1].type = CE_PORT;
1374
0
            new_key[DEINTD_PORT1_IDX-1].port_val = port1;
1375
1376
0
            new_key[DEINTD_PORT2_IDX-1].type = CE_PORT;
1377
0
            new_key[DEINTD_PORT2_IDX-1].port_val = port2;
1378
1379
0
            new_key[DEINTD_NO_ADDR2_IDX_COUNT-2].type = CE_UINT;
1380
0
            new_key[DEINTD_NO_ADDR2_IDX_COUNT-2].uint_val = anchor;
1381
1382
0
            new_key[DEINTD_NO_ADDR2_IDX_COUNT-1].type = CE_CONVERSATION_TYPE;
1383
0
            new_key[DEINTD_NO_ADDR2_IDX_COUNT-1].conversation_type_val = ctype;
1384
1385
            // set the options and key pointer
1386
0
            conversation->options = options;
1387
0
            conversation->key_ptr = new_key;
1388
1389
0
            new_index++;
1390
1391
0
            conversation_insert_into_hashtable(conversation_hashtable_no_addr2_anc, conversation);
1392
1393
0
            return conversation;
1394
0
        }
1395
0
    }
1396
0
    else if (options & NO_PORT2) {
1397
0
        conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * (DEINTD_EXACT_IDX_COUNT+1));
1398
1399
0
        new_key[DEINTD_ADDR1_IDX].type = CE_ADDRESS;
1400
0
        if (addr1 != NULL) {
1401
0
            copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR1_IDX].addr_val, addr1);
1402
0
        }
1403
0
        else {
1404
0
          clear_address(&new_key[DEINTD_ADDR1_IDX].addr_val);
1405
0
        }
1406
1407
0
        new_key[DEINTD_ADDR2_IDX].type = CE_ADDRESS;
1408
0
        if (addr2 != NULL) {
1409
0
            copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR2_IDX].addr_val, addr2);
1410
0
        }
1411
0
        else {
1412
0
          clear_address(&new_key[DEINTD_ADDR2_IDX].addr_val);
1413
0
        }
1414
1415
0
        new_key[DEINTD_PORT1_IDX].type = CE_PORT;
1416
0
        new_key[DEINTD_PORT1_IDX].port_val = port1;
1417
1418
0
        new_key[DEINTD_PORT1_IDX + 1].type = CE_UINT;
1419
0
        new_key[DEINTD_PORT1_IDX + 1].uint_val = anchor;
1420
1421
0
        new_key[DEINTD_PORT1_IDX + 2].type = CE_CONVERSATION_TYPE;
1422
0
        new_key[DEINTD_PORT1_IDX + 2].conversation_type_val = ctype;
1423
1424
        // set the options and key pointer
1425
0
        conversation->options = options;
1426
0
        conversation->key_ptr = new_key;
1427
1428
0
        new_index++;
1429
1430
0
        conversation_insert_into_hashtable(conversation_hashtable_exact_addr_port_anc, conversation);
1431
1432
0
        return conversation;
1433
0
    }
1434
0
    else {
1435
0
        conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * (DEINTD_EXACT_IDX_COUNT+2));
1436
1437
0
        new_key[DEINTD_ADDR1_IDX].type = CE_ADDRESS;
1438
0
        if (addr1 != NULL) {
1439
0
            copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR1_IDX].addr_val, addr1);
1440
0
        }
1441
0
        else {
1442
0
          clear_address(&new_key[DEINTD_ADDR1_IDX].addr_val);
1443
0
        }
1444
1445
0
        new_key[DEINTD_ADDR2_IDX].type = CE_ADDRESS;
1446
0
        if (addr2 != NULL) {
1447
0
            copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR2_IDX].addr_val, addr2);
1448
0
        }
1449
0
        else {
1450
0
          clear_address(&new_key[DEINTD_ADDR2_IDX].addr_val);
1451
0
        }
1452
1453
0
        new_key[DEINTD_PORT1_IDX].type = CE_PORT;
1454
0
        new_key[DEINTD_PORT1_IDX].port_val = port1;
1455
1456
0
        new_key[DEINTD_PORT2_IDX].type = CE_PORT;
1457
0
        new_key[DEINTD_PORT2_IDX].port_val = port2;
1458
1459
0
        new_key[DEINTD_ENDP_EXACT_IDX].type = CE_UINT;
1460
0
        new_key[DEINTD_ENDP_EXACT_IDX].uint_val = anchor;
1461
1462
0
        new_key[DEINTD_ENDP_EXACT_IDX + 1].type = CE_CONVERSATION_TYPE;
1463
0
        new_key[DEINTD_ENDP_EXACT_IDX + 1].conversation_type_val = ctype;
1464
1465
        // set the options and key pointer
1466
0
        conversation->options = options;
1467
0
        conversation->key_ptr = new_key;
1468
1469
0
        new_index++;
1470
1471
0
        conversation_insert_into_hashtable(conversation_hashtable_exact_addr_port_anc, conversation);
1472
1473
0
        return conversation;
1474
0
    }
1475
0
}
1476
1477
/*
1478
 * Set the port 2 value in a key. Remove the original from table,
1479
 * update the options and port values, insert the updated key.
1480
 */
1481
void
1482
conversation_set_port2(conversation_t *conv, const uint32_t port)
1483
3
{
1484
3
    DISSECTOR_ASSERT_HINT(!(conv->options & CONVERSATION_TEMPLATE),
1485
3
            "Use the conversation_create_from_template function when the CONVERSATION_TEMPLATE bit is set in the options mask");
1486
1487
3
    DPRINT(("called for port=%d", port));
1488
1489
    /*
1490
     * If the port 2 value is not wildcarded, don't set it.
1491
     */
1492
3
    if ((!(conv->options & NO_PORT2)) || (conv->options & NO_PORT2_FORCE))
1493
0
        return;
1494
1495
3
    DINDENT();
1496
3
    if (conv->options & NO_ADDR2) {
1497
0
        conversation_remove_from_hashtable(conversation_hashtable_no_addr2_or_port2, conv);
1498
3
    } else {
1499
3
        conversation_remove_from_hashtable(conversation_hashtable_no_port2, conv);
1500
3
    }
1501
1502
    // Shift our endpoint element over and set our port. We assume that conv->key_ptr
1503
    // was created with conversation_new and that we have enough element slots.
1504
3
    conv->options &= ~NO_PORT2;
1505
3
    if (conv->options & NO_ADDR2) {
1506
        // addr1,port1,endp -> addr1,port1,port2,endp
1507
0
        conv->key_ptr[ENDP_NO_ADDR2_IDX] = conv->key_ptr[ENDP_NO_ADDR2_PORT2_IDX];
1508
0
        conv->key_ptr[PORT2_NO_ADDR2_IDX].type = CE_PORT;
1509
0
        conv->key_ptr[PORT2_NO_ADDR2_IDX].port_val = port;
1510
0
        conversation_insert_into_hashtable(conversation_hashtable_no_addr2, conv);
1511
3
    } else {
1512
        // addr1,port1,addr2,endp -> addr1,port1,addr2,port2,endp
1513
3
        conv->key_ptr[ENDP_EXACT_IDX] = conv->key_ptr[ENDP_NO_PORT2_IDX];
1514
3
        conv->key_ptr[PORT2_IDX].type = CE_PORT;
1515
3
        conv->key_ptr[PORT2_IDX].port_val = port;
1516
3
        conversation_insert_into_hashtable(conversation_hashtable_exact_addr_port, conv);
1517
3
    }
1518
3
    DENDENT();
1519
3
}
1520
1521
/*
1522
 * Set the address 2 value in a key.  Remove the original from
1523
 * table, update the options and port values, insert the updated key.
1524
 */
1525
void
1526
conversation_set_addr2(conversation_t *conv, const address *addr)
1527
3
{
1528
3
    char* addr_str;
1529
3
    DISSECTOR_ASSERT_HINT(!(conv->options & CONVERSATION_TEMPLATE),
1530
3
            "Use the conversation_create_from_template function when the CONVERSATION_TEMPLATE bit is set in the options mask");
1531
1532
3
    addr_str = address_to_str(NULL, addr);
1533
3
    DPRINT(("called for addr=%s", addr_str));
1534
3
    wmem_free(NULL, addr_str);
1535
1536
    /*
1537
     * If the address 2 value is not wildcarded, don't set it.
1538
     */
1539
3
    if (!(conv->options & NO_ADDR2))
1540
0
        return;
1541
1542
3
    DINDENT();
1543
3
    if (conv->options & NO_PORT2) {
1544
3
        conversation_remove_from_hashtable(conversation_hashtable_no_addr2_or_port2, conv);
1545
3
    } else {
1546
0
        conversation_remove_from_hashtable(conversation_hashtable_no_addr2, conv);
1547
0
    }
1548
1549
    // Shift our endpoint and, if needed, our port element over and set our address.
1550
    // We assume that conv->key_ptr was created with conversation_new and that we have
1551
    // enough element slots.
1552
3
    conv->options &= ~NO_ADDR2;
1553
3
    wmem_map_t *hashtable;
1554
3
    if (conv->options & NO_PORT2) {
1555
        // addr1,port1,endp -> addr1,port1,addr2,endp
1556
3
        conv->key_ptr[ENDP_NO_PORT2_IDX] = conv->key_ptr[ENDP_NO_ADDR2_PORT2_IDX];
1557
3
        hashtable = conversation_hashtable_no_port2;
1558
3
    } else {
1559
        // addr1,port1,port2,endp -> addr1,port1,addr2,port2,endp
1560
0
        conv->key_ptr[ENDP_EXACT_IDX] = conv->key_ptr[ENDP_NO_ADDR2_IDX];
1561
0
        conv->key_ptr[PORT2_IDX] = conv->key_ptr[PORT2_NO_ADDR2_IDX];
1562
0
        hashtable = conversation_hashtable_exact_addr_port;
1563
0
    }
1564
3
    conv->key_ptr[ADDR2_IDX].type = CE_ADDRESS;
1565
3
    copy_address_wmem(wmem_file_scope(), &conv->key_ptr[ADDR2_IDX].addr_val, addr);
1566
3
    conversation_insert_into_hashtable(hashtable, conv);
1567
3
    DENDENT();
1568
3
}
1569
1570
static conversation_t *conversation_lookup_hashtable(wmem_map_t *conversation_hashtable, const uint32_t frame_num, conversation_element_t *conv_key)
1571
1.80M
{
1572
1.80M
    conversation_t* convo = NULL;
1573
1.80M
    conversation_t* match = NULL;
1574
1.80M
    conversation_t* chain_head = NULL;
1575
1.80M
    chain_head = (conversation_t *)wmem_map_lookup(conversation_hashtable, conv_key);
1576
1577
1.80M
    if (chain_head && (chain_head->setup_frame <= frame_num)) {
1578
478k
        match = chain_head;
1579
1580
478k
        if (chain_head->last && (chain_head->last->setup_frame <= frame_num))
1581
478k
            return chain_head->last;
1582
1583
0
        if (chain_head->latest_found && (chain_head->latest_found->setup_frame <= frame_num))
1584
0
            match = chain_head->latest_found;
1585
1586
0
        for (convo = match; convo && convo->setup_frame <= frame_num; convo = convo->next) {
1587
0
            if (convo->setup_frame > match->setup_frame) {
1588
0
                match = convo;
1589
0
            }
1590
0
        }
1591
0
    }
1592
1593
1.32M
    if (match) {
1594
0
        chain_head->latest_found = match;
1595
0
    }
1596
1597
1.32M
    return match;
1598
1.80M
}
1599
1600
conversation_t *find_conversation_full(const uint32_t frame_num, conversation_element_t *elements)
1601
12.8k
{
1602
12.8k
    char *el_list_map_key = conversation_element_list_name(NULL, elements);
1603
12.8k
    wmem_map_t *el_list_map = (wmem_map_t *) wmem_map_lookup(conversation_hashtable_element_list, el_list_map_key);
1604
12.8k
    g_free(el_list_map_key);
1605
12.8k
    if (!el_list_map) {
1606
5
        return NULL;
1607
5
    }
1608
1609
12.8k
    return conversation_lookup_hashtable(el_list_map, frame_num, elements);
1610
12.8k
}
1611
1612
/*
1613
 * Search a particular hash table for a conversation with the specified
1614
 * {addr1, port1, addr2, port2} and set up before frame_num.
1615
 */
1616
static conversation_t *
1617
conversation_lookup_exact(const uint32_t frame_num, const address *addr1, const uint32_t port1,
1618
                          const address *addr2, const uint32_t port2, const conversation_type ctype)
1619
800k
{
1620
800k
    conversation_element_t key[EXACT_IDX_COUNT] = {
1621
800k
        { CE_ADDRESS, .addr_val = *addr1 },
1622
800k
        { CE_PORT, .port_val = port1 },
1623
800k
        { CE_ADDRESS, .addr_val = *addr2 },
1624
800k
        { CE_PORT, .port_val = port2 },
1625
800k
        { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1626
800k
    };
1627
800k
    return conversation_lookup_hashtable(conversation_hashtable_exact_addr_port, frame_num, key);
1628
800k
}
1629
1630
/*
1631
 * Search a particular hash table for a conversation with the specified
1632
 * {addr1, port1, port2} and set up before frame_num.
1633
 */
1634
static conversation_t *
1635
conversation_lookup_no_addr2(const uint32_t frame_num, const address *addr1, const uint32_t port1,
1636
                          const uint32_t port2, const conversation_type ctype)
1637
147k
{
1638
147k
    conversation_element_t key[NO_ADDR2_IDX_COUNT] = {
1639
147k
        { CE_ADDRESS, .addr_val = *addr1 },
1640
147k
        { CE_PORT, .port_val = port1 },
1641
147k
        { CE_PORT, .port_val = port2 },
1642
147k
        { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1643
147k
    };
1644
147k
    return conversation_lookup_hashtable(conversation_hashtable_no_addr2, frame_num, key);
1645
147k
}
1646
1647
/*
1648
 * Search a particular hash table for a conversation with the specified
1649
 * {addr1, port1, addr2} and set up before frame_num.
1650
 */
1651
static conversation_t *
1652
conversation_lookup_no_port2(const uint32_t frame_num, const address *addr1, const uint32_t port1,
1653
                          const address *addr2, const conversation_type ctype)
1654
148k
{
1655
148k
    conversation_element_t key[NO_PORT2_IDX_COUNT] = {
1656
148k
        { CE_ADDRESS, .addr_val = *addr1 },
1657
148k
        { CE_PORT, .port_val = port1 },
1658
148k
        { CE_ADDRESS, .addr_val = *addr2 },
1659
148k
        { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1660
148k
    };
1661
148k
    return conversation_lookup_hashtable(conversation_hashtable_no_port2, frame_num, key);
1662
148k
}
1663
1664
/*
1665
 * Search a particular hash table for a conversation with the specified
1666
 * {addr1, port1, addr2} and set up before frame_num.
1667
 */
1668
static conversation_t *
1669
conversation_lookup_no_addr2_or_port2(const uint32_t frame_num, const address *addr1, const uint32_t port1,
1670
                          const conversation_type ctype)
1671
542k
{
1672
542k
    conversation_element_t key[NO_ADDR2_PORT2_IDX_COUNT] = {
1673
542k
        { CE_ADDRESS, .addr_val = *addr1 },
1674
542k
        { CE_PORT, .port_val = port1 },
1675
542k
        { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1676
542k
    };
1677
542k
    return conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2, frame_num, key);
1678
542k
}
1679
1680
/*
1681
 * Search a particular hash table for a conversation with the specified
1682
 * {addr1, addr2} and set up before frame_num.
1683
 */
1684
static conversation_t *
1685
conversation_lookup_no_ports(const uint32_t frame_num, const address *addr1,
1686
                          const address *addr2, const conversation_type ctype)
1687
149k
{
1688
149k
    conversation_element_t key[ADDRS_IDX_COUNT] = {
1689
149k
        { CE_ADDRESS, .addr_val = *addr1 },
1690
149k
        { CE_ADDRESS, .addr_val = *addr2 },
1691
149k
        { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1692
149k
    };
1693
149k
    return conversation_lookup_hashtable(conversation_hashtable_exact_addr, frame_num, key);
1694
149k
}
1695
1696
/*
1697
 * Search a particular hash table for a conversation with the specified
1698
 * {addr1, port1, addr2, port2, anchor} and set up before frame_num.
1699
 */
1700
static conversation_t *
1701
conversation_lookup_exact_anc(const uint32_t frame_num, const address *addr1, const uint32_t port1,
1702
                          const address *addr2, const uint32_t port2, const conversation_type ctype,
1703
                          const uint32_t anchor)
1704
0
{
1705
0
    conversation_element_t key[DEINTD_EXACT_IDX_COUNT+1] = {
1706
0
        { CE_ADDRESS, .addr_val = *addr1 },
1707
0
        { CE_ADDRESS, .addr_val = *addr2 },
1708
0
        { CE_PORT, .port_val = port1 },
1709
0
        { CE_PORT, .port_val = port2 },
1710
0
        { CE_UINT, .uint_val = anchor },
1711
0
        { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1712
0
    };
1713
0
    return conversation_lookup_hashtable(conversation_hashtable_exact_addr_port_anc, frame_num, key);
1714
0
}
1715
1716
/*
1717
 * Search a particular hash table for a conversation with the specified
1718
 * {addr1, addr2, anchor} and set up before frame_num.
1719
 */
1720
static conversation_t *
1721
conversation_lookup_no_ports_anc(const uint32_t frame_num, const address *addr1,
1722
                          const address *addr2, const conversation_type ctype, const uint32_t anchor)
1723
0
{
1724
0
    conversation_element_t key[DEINTD_ADDRS_IDX_COUNT+1] = {
1725
0
        { CE_ADDRESS, .addr_val = *addr1 },
1726
0
        { CE_ADDRESS, .addr_val = *addr2 },
1727
0
        { CE_UINT, .uint_val = anchor },
1728
0
        { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1729
0
    };
1730
0
    return conversation_lookup_hashtable(conversation_hashtable_exact_addr_anc, frame_num, key);
1731
0
}
1732
1733
/*
1734
 * Search a particular hash table for a conversation with the specified
1735
 * {addr1, port1, port2, anchor} and set up before frame_num.
1736
 */
1737
static conversation_t *
1738
conversation_lookup_no_addr2_anc(const uint32_t frame_num, const address *addr1, const uint32_t port1,
1739
                          const uint32_t port2, const conversation_type ctype,
1740
                          const uint32_t anchor)
1741
0
{
1742
0
    conversation_element_t key[DEINTD_NO_ADDR2_IDX_COUNT] = {
1743
0
        { CE_ADDRESS, .addr_val = *addr1 },
1744
0
        { CE_PORT, .port_val = port1 },
1745
0
        { CE_PORT, .port_val = port2 },
1746
0
        { CE_UINT, .uint_val = anchor },
1747
0
        { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1748
0
    };
1749
0
    return conversation_lookup_hashtable(conversation_hashtable_no_addr2_anc , frame_num, key);
1750
0
}
1751
1752
/*
1753
 * Search a particular hash table for a conversation with the specified
1754
 * {addr1, port1, addr2, anchor} and set up before frame_num.
1755
 */
1756
static conversation_t *
1757
conversation_lookup_no_port2_anc(const uint32_t frame_num, const address *addr1, const uint32_t port1,
1758
                          const address *addr2, const conversation_type ctype,
1759
                          const uint32_t anchor)
1760
0
{
1761
0
    conversation_element_t key[DEINTD_NO_PORT2_IDX_COUNT] = {
1762
0
        { CE_ADDRESS, .addr_val = *addr1 },
1763
0
        { CE_ADDRESS, .addr_val = *addr2 },
1764
0
        { CE_PORT, .port_val = port1 },
1765
0
        { CE_UINT, .uint_val = anchor },
1766
0
        { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1767
0
    };
1768
0
    return conversation_lookup_hashtable(conversation_hashtable_exact_addr_port_anc, frame_num, key);
1769
0
}
1770
1771
/*
1772
 * Search a particular hash table for a conversation with the specified
1773
 * {addr1, port1, addr2} and set up before frame_num.
1774
 */
1775
static conversation_t *
1776
conversation_lookup_no_addr2_or_port2_anc(const uint32_t frame_num, const address *addr1, const uint32_t port1,
1777
                          const conversation_type ctype, const uint32_t anchor)
1778
0
{
1779
0
    conversation_element_t key[DEINTD_NO_ADDR2_PORT2_IDX_COUNT] = {
1780
0
        { CE_ADDRESS, .addr_val = *addr1 },
1781
0
        { CE_PORT, .port_val = port1 },
1782
0
        { CE_UINT, .uint_val = anchor },
1783
0
        { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1784
0
    };
1785
0
    return conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2_anc, frame_num, key);
1786
0
}
1787
1788
/*
1789
 * Search a particular hash table for a conversation with the specified
1790
 * {addr1, addr2, key1, key2, key3} and set up before frame_num.
1791
 * At this moment only the deinterlace table is likely to be called.
1792
 */
1793
static conversation_t *
1794
conversation_lookup_deinterlacer(const uint32_t frame_num, const address *addr1,
1795
                          const address *addr2, const conversation_type ctype,
1796
                          const uint32_t key1, const uint32_t key2, const uint32_t key3)
1797
0
{
1798
0
    conversation_element_t key[DEINTR_ENDP_IDX+1] = {
1799
0
        { CE_ADDRESS, .addr_val = *addr1 },
1800
0
        { CE_ADDRESS, .addr_val = *addr2 },
1801
0
        { CE_UINT, .uint_val = key1 },
1802
0
        { CE_UINT, .uint_val = key2 },
1803
0
        { CE_UINT, .uint_val = key3 },
1804
0
        { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1805
0
    };
1806
0
    return conversation_lookup_hashtable(conversation_hashtable_deinterlacer, frame_num, key);
1807
0
}
1808
1809
/*
1810
 * Given two address/port pairs for a packet, search for a conversation
1811
 * containing packets between those address/port pairs.  Returns NULL if
1812
 * not found.
1813
 *
1814
 * We try to find the most exact match that we can, and then proceed to
1815
 * try wildcard matches on the "addr_b" and/or "port_b" argument if a more
1816
 * exact match failed.
1817
 *
1818
 * Either or both of the "addr_b" and "port_b" arguments may be specified as
1819
 * a wildcard by setting the NO_ADDR_B or NO_PORT_B flags in the "options"
1820
 * argument.  We do only wildcard matches on addresses and ports specified
1821
 * as wildcards.
1822
 *
1823
 * I.e.:
1824
 *
1825
 *  if neither "addr_b" nor "port_b" were specified as wildcards, we
1826
 *  do an exact match (addr_a/port_a and addr_b/port_b) and, if that
1827
 *  succeeds, we return a pointer to the matched conversation;
1828
 *
1829
 *  otherwise, if "port_b" wasn't specified as a wildcard, we try to
1830
 *  match any address 2 with the specified port 2 (addr_a/port_a and
1831
 *  {any}/port_b) and, if that succeeds, we return a pointer to the
1832
 *  matched conversation;
1833
 *
1834
 *  otherwise, if "addr_b" wasn't specified as a wildcard, we try to
1835
 *  match any port 2 with the specified address 2 (addr_a/port_a and
1836
 *  addr_b/{any}) and, if that succeeds, we return a pointer to the
1837
 *  matched conversation;
1838
 *
1839
 *  otherwise, we try to match any address 2 and any port 2
1840
 *  (addr_a/port_a and {any}/{any}) and, if that succeeds, we return
1841
 *  a pointer to the matched conversation;
1842
 *
1843
 *  otherwise, we found no matching conversation, and return NULL.
1844
 */
1845
conversation_t *
1846
find_conversation(const uint32_t frame_num, const address *addr_a, const address *addr_b, const conversation_type ctype,
1847
        const uint32_t port_a, const uint32_t port_b, const unsigned options)
1848
757k
{
1849
757k
    conversation_t *conversation, *other_conv;
1850
1851
757k
    if (!addr_a) {
1852
0
        addr_a = &null_address_;
1853
0
    }
1854
1855
757k
    if (!addr_b) {
1856
3
        addr_b = &null_address_;
1857
3
    }
1858
1859
757k
    DINSTR(char *addr_a_str = address_to_str(NULL, addr_a));
1860
757k
    DINSTR(char *addr_b_str = address_to_str(NULL, addr_b));
1861
    /*
1862
     * Verify that the correct options are used, if any.
1863
     */
1864
757k
    DISSECTOR_ASSERT_HINT((options == 0) || (options & NO_MASK_B), "Use NO_ADDR_B and/or NO_PORT_B as option");
1865
    /*
1866
     * First try an exact match, if we have two addresses and ports.
1867
     */
1868
757k
    if (!(options & (NO_ADDR_B|NO_PORT_B|NO_PORT_X|EXACT_EXCLUDED))) {
1869
        /*
1870
         * Neither search address B nor search port B are wildcarded,
1871
         * start out with an exact match.
1872
         */
1873
400k
        DPRINT(("trying exact match: %s:%d -> %s:%d",
1874
400k
                    addr_a_str, port_a, addr_b_str, port_b));
1875
400k
        conversation = conversation_lookup_exact(frame_num, addr_a, port_a, addr_b, port_b, ctype);
1876
        /*
1877
         * Look for an alternate conversation in the opposite direction, which
1878
         * might fit better. Note that using the helper functions such as
1879
         * find_conversation_pinfo and find_or_create_conversation will finally
1880
         * call this function and look for an orientation-agnostic conversation.
1881
         * If oriented conversations had to be implemented, amend this code or
1882
         * create new functions.
1883
         */
1884
1885
400k
        DPRINT(("trying exact match: %s:%d -> %s:%d",
1886
400k
                    addr_b_str, port_b, addr_a_str, port_a));
1887
400k
        other_conv = conversation_lookup_exact(frame_num, addr_b, port_b, addr_a, port_a, ctype);
1888
400k
        if (other_conv != NULL) {
1889
19.6k
            if (conversation != NULL) {
1890
16.8k
                if(other_conv->conv_index > conversation->conv_index) {
1891
368
                    conversation = other_conv;
1892
368
                }
1893
16.8k
            }
1894
2.85k
            else {
1895
2.85k
                conversation = other_conv;
1896
2.85k
            }
1897
19.6k
        }
1898
400k
        if ((conversation == NULL) && (addr_a->type == AT_FC)) {
1899
            /* In Fibre channel, OXID & RXID are never swapped as
1900
             * TCP/UDP ports are in TCP/IP.
1901
             */
1902
379
            DPRINT(("trying exact match: %s:%d -> %s:%d",
1903
379
                        addr_b_str, port_a, addr_a_str, port_b));
1904
379
            conversation = conversation_lookup_exact(frame_num, addr_b, port_a, addr_a, port_b, ctype);
1905
379
        }
1906
400k
        DPRINT(("exact match %sfound",conversation?"":"not "));
1907
400k
        if (conversation != NULL)
1908
355k
            goto end;
1909
45.1k
        else if(options & NO_GREEDY)
1910
10.8k
            goto end;
1911
400k
    }
1912
1913
    /*
1914
     * Well, that didn't find anything.  Try matches that wildcard
1915
     * one of the addresses, if we have two ports.
1916
     */
1917
391k
    if (!(options & (NO_PORT_B|NO_PORT_X))) {
1918
        /*
1919
         * Search port B isn't wildcarded.
1920
         *
1921
         * First try looking for a conversation with the specified
1922
         * address A and port A as the first address and port, and
1923
         * with any address and the specified port B as the second
1924
         * address and port.
1925
         * ("addr_b" doesn't take part in this lookup.)
1926
         */
1927
113k
        DPRINT(("trying wildcarded match: %s:%d -> *:%d",
1928
113k
                    addr_a_str, port_a, port_b));
1929
113k
        conversation = conversation_lookup_no_addr2(frame_num, addr_a, port_a, port_b, ctype);
1930
113k
        if ((conversation == NULL) && (addr_a->type == AT_FC)) {
1931
            /* In Fibre channel, OXID & RXID are never swapped as
1932
             * TCP/UDP ports are in TCP/IP.
1933
             */
1934
379
            DPRINT(("trying wildcarded match: %s:%d -> *:%d",
1935
379
                        addr_b_str, port_a, port_b));
1936
379
            conversation = conversation_lookup_no_addr2(frame_num, addr_b, port_a, port_b, ctype);
1937
379
        }
1938
113k
        if (conversation != NULL) {
1939
            /*
1940
             * If search address B isn't wildcarded, and this is for a
1941
             * connection-oriented protocol, set the second address for this
1942
             * conversation to address B, as that's the address that matched the
1943
             * wildcarded second address for this conversation.
1944
             *
1945
             * (This assumes that, for all connection oriented protocols, the
1946
             * endpoints of a connection have only one address each, i.e. you
1947
             * don't get packets in a given direction coming from more than one
1948
             * address, unless the CONVERSATION_TEMPLATE option is set.)
1949
             */
1950
21
            DPRINT(("wildcarded dest address match found"));
1951
21
            if (!(conversation->options & NO_ADDR2) && ctype != CONVERSATION_UDP)
1952
0
            {
1953
0
                if (!(conversation->options & CONVERSATION_TEMPLATE))
1954
0
                {
1955
0
                    conversation_set_addr2(conversation, addr_b);
1956
0
                }
1957
0
                else
1958
0
                {
1959
0
                    conversation =
1960
0
                        conversation_create_from_template(conversation, addr_b, 0);
1961
0
                }
1962
0
            }
1963
21
            goto end;
1964
21
        }
1965
1966
        /*
1967
         * Well, that didn't find anything.
1968
         * If search address B was specified, try looking for a
1969
         * conversation with the specified address B and port B as
1970
         * the first address and port, and with any address and the
1971
         * specified port A as the second address and port (this
1972
         * packet may be going in the opposite direction from the
1973
         * first packet in the conversation).
1974
         * ("addr_a" doesn't take part in this lookup.)
1975
         */
1976
113k
        if (!(options & NO_ADDR_B)) {
1977
34.3k
            DPRINT(("trying wildcarded match: %s:%d -> *:%d",
1978
34.3k
                        addr_b_str, port_b, port_a));
1979
34.3k
            conversation = conversation_lookup_no_addr2(frame_num, addr_b, port_b, port_a, ctype);
1980
34.3k
            if (conversation != NULL) {
1981
                /*
1982
                 * If this is for a connection-oriented
1983
                 * protocol, set the second address for
1984
                 * this conversation to address A, as
1985
                 * that's the address that matched the
1986
                 * wildcarded second address for this
1987
                 * conversation.
1988
                 */
1989
0
                DPRINT(("match found"));
1990
0
                if (ctype != CONVERSATION_UDP) {
1991
0
                    if (!(conversation->options & CONVERSATION_TEMPLATE))
1992
0
                    {
1993
0
                        conversation_set_addr2(conversation, addr_a);
1994
0
                    }
1995
0
                    else
1996
0
                    {
1997
0
                        conversation =
1998
0
                            conversation_create_from_template(conversation, addr_a, 0);
1999
0
                    }
2000
0
                }
2001
0
                goto end;
2002
0
            }
2003
34.3k
        }
2004
113k
    }
2005
2006
    /*
2007
     * Well, that didn't find anything.  Try matches that wildcard
2008
     * one of the ports, if we have two addresses.
2009
     */
2010
391k
    if (!(options & (NO_ADDR_B|NO_PORT_X))) {
2011
        /*
2012
         * Search address B isn't wildcarded.
2013
         *
2014
         * First try looking for a conversation with the specified
2015
         * address A and port A as the first address and port, and
2016
         * with the specified address B and any port as the second
2017
         * address and port.
2018
         * ("port_b" doesn't take part in this lookup.)
2019
         */
2020
114k
        DPRINT(("trying wildcarded match: %s:%d -> %s:*",
2021
114k
                    addr_a_str, port_a, addr_b_str));
2022
114k
        conversation = conversation_lookup_no_port2(frame_num, addr_a, port_a, addr_b, ctype);
2023
114k
        if ((conversation == NULL) && (addr_a->type == AT_FC)) {
2024
            /* In Fibre channel, OXID & RXID are never swapped as
2025
             * TCP/UDP ports are in TCP/IP
2026
             */
2027
542
            DPRINT(("trying wildcarded match: %s:%d -> %s:*", addr_b_str, port_a, addr_a_str));
2028
542
            conversation = conversation_lookup_no_port2(frame_num, addr_b, port_a, addr_a, ctype);
2029
542
        }
2030
114k
        if (conversation != NULL) {
2031
            /*
2032
             * If search port B isn't wildcarded, and this is for a connection-
2033
             * oriented protocol, set the second port for this conversation to
2034
             * port B, as that's the port that matched the wildcarded second port
2035
             * for this conversation.
2036
             *
2037
             * (This assumes that, for all connection oriented protocols, the
2038
             * endpoints of a connection have only one port each, i.e. you don't
2039
             * get packets in a given direction coming from more than one port,
2040
             * unless the CONVERSATION_TEMPLATE option is set.)
2041
             */
2042
688
            DPRINT(("match found"));
2043
688
            if (!(conversation->options & NO_PORT2) && ctype != CONVERSATION_UDP)
2044
0
            {
2045
0
                if (!(conversation->options & CONVERSATION_TEMPLATE))
2046
0
                {
2047
0
                    conversation_set_port2(conversation, port_b);
2048
0
                }
2049
0
                else
2050
0
                {
2051
0
                    conversation =
2052
0
                        conversation_create_from_template(conversation, 0, port_b);
2053
0
                }
2054
0
            }
2055
688
            goto end;
2056
688
        }
2057
2058
        /*
2059
         * Well, that didn't find anything.
2060
         * If search port B was specified, try looking for a
2061
         * conversation with the specified address B and port B
2062
         * as the first address and port, and with the specified
2063
         * address A and any port as the second address and port
2064
         * (this packet may be going in the opposite direction
2065
         * from the first packet in the conversation).
2066
         * ("port_a" doesn't take part in this lookup.)
2067
         */
2068
113k
        if (!(options & NO_PORT_B)) {
2069
34.3k
            DPRINT(("trying wildcarded match: %s:%d -> %s:*",
2070
34.3k
                        addr_b_str, port_b, addr_a_str));
2071
34.3k
            conversation = conversation_lookup_no_port2(frame_num, addr_b, port_b, addr_a, ctype);
2072
34.3k
            if (conversation != NULL) {
2073
                /*
2074
                 * If this is for a connection-oriented
2075
                 * protocol, set the second port for
2076
                 * this conversation to port A, as
2077
                 * that's the address that matched the
2078
                 * wildcarded second address for this
2079
                 * conversation.
2080
                 */
2081
6
                DPRINT(("match found"));
2082
6
                if (ctype != CONVERSATION_UDP)
2083
0
                {
2084
0
                    if (!(conversation->options & CONVERSATION_TEMPLATE))
2085
0
                    {
2086
0
                        conversation_set_port2(conversation, port_a);
2087
0
                    }
2088
0
                    else
2089
0
                    {
2090
0
                        conversation =
2091
0
                            conversation_create_from_template(conversation, 0, port_a);
2092
0
                    }
2093
0
                }
2094
6
                goto end;
2095
6
            }
2096
34.3k
        }
2097
113k
        if(options & NO_GREEDY) {
2098
0
            goto end;
2099
0
        }
2100
113k
    }
2101
2102
    /*
2103
     * Well, that didn't find anything.  Try matches that wildcard
2104
     * one address/port pair.
2105
     *
2106
     * First try looking for a conversation with the specified address A
2107
     * and port A as the first address and port.
2108
     * (Neither "addr_b" nor "port_b" take part in this lookup.)
2109
     */
2110
391k
    if (!(options & NO_PORT_X)) {
2111
274k
        DPRINT(("trying wildcarded match: %s:%d -> *:*", addr_a_str, port_a));
2112
274k
        conversation = conversation_lookup_no_addr2_or_port2(frame_num, addr_a, port_a, ctype);
2113
274k
        if (conversation != NULL) {
2114
            /*
2115
             * If this is for a connection-oriented protocol:
2116
             *
2117
             * if search address B isn't wildcarded, set the
2118
             * second address for this conversation to address
2119
             * B, as that's the address that matched the
2120
             * wildcarded second address for this conversation;
2121
             *
2122
             * if search port B isn't wildcarded, set the
2123
             * second port for this conversation to port B,
2124
             * as that's the port that matched the wildcarded
2125
             * second port for this conversation.
2126
             */
2127
5.23k
            DPRINT(("match found"));
2128
5.23k
            if (ctype != CONVERSATION_UDP)
2129
997
            {
2130
997
                if (!(conversation->options & CONVERSATION_TEMPLATE))
2131
997
                {
2132
997
                    if (!(conversation->options & NO_ADDR2))
2133
0
                        conversation_set_addr2(conversation, addr_b);
2134
997
                    if (!(conversation->options & NO_PORT2))
2135
0
                        conversation_set_port2(conversation, port_b);
2136
997
                }
2137
0
                else
2138
0
                {
2139
0
                    conversation =
2140
0
                        conversation_create_from_template(conversation, addr_b, port_b);
2141
0
                }
2142
997
            }
2143
5.23k
            goto end;
2144
5.23k
        }
2145
        /* for Infiniband, don't try to look in addresses of reverse
2146
         * direction, because it could be another different
2147
         * valid conversation than what is being searched using
2148
         * addr_a, port_a.
2149
         */
2150
269k
        if (ctype != CONVERSATION_IBQP)
2151
267k
        {
2152
    
2153
            /*
2154
             * Well, that didn't find anything.
2155
             * If search address and port B were specified, try looking for a
2156
             * conversation with the specified address B and port B as the
2157
             * first address and port, and with any second address and port
2158
             * (this packet may be going in the opposite direction from the
2159
             * first packet in the conversation).
2160
             * (Neither "addr_a" nor "port_a" take part in this lookup.)
2161
             */
2162
267k
            if (addr_a->type == AT_FC) {
2163
539
                DPRINT(("trying wildcarded match: %s:%d -> *:*",
2164
539
                            addr_b_str, port_a));
2165
539
                conversation = conversation_lookup_no_addr2_or_port2(frame_num, addr_b, port_a, ctype);
2166
267k
            } else {
2167
267k
                DPRINT(("trying wildcarded match: %s:%d -> *:*",
2168
267k
                            addr_b_str, port_b));
2169
267k
                conversation = conversation_lookup_no_addr2_or_port2(frame_num, addr_b, port_b, ctype);
2170
267k
            }
2171
267k
            if (conversation != NULL) {
2172
                /*
2173
                 * If this is for a connection-oriented protocol, set the
2174
                 * second address for this conversation to address A, as
2175
                 * that's the address that matched the wildcarded second
2176
                 * address for this conversation, and set the second port
2177
                 * for this conversation to port A, as that's the port
2178
                 * that matched the wildcarded second port for this
2179
                 * conversation.
2180
                 */
2181
2.20k
                DPRINT(("match found"));
2182
2.20k
                if (ctype != CONVERSATION_UDP)
2183
3
                {
2184
3
                    if (!(conversation->options & CONVERSATION_TEMPLATE))
2185
3
                    {
2186
3
                        conversation_set_addr2(conversation, addr_a);
2187
3
                        conversation_set_port2(conversation, port_a);
2188
3
                    }
2189
0
                    else
2190
0
                    {
2191
0
                        conversation = conversation_create_from_template(conversation, addr_a, port_a);
2192
0
                    }
2193
3
                }
2194
2.20k
                goto end;
2195
2.20k
            }
2196
267k
        }
2197
269k
    }
2198
2199
    /*
2200
     * Well, that didn't find anything.  Try matches between two
2201
     * addresses, but no ports. Typically ETH and IP protocols fall
2202
     * into this category.
2203
     *
2204
     * First try looking for a conversation with the specified address A
2205
     * and address B.
2206
     * (Neither "port_a" nor "port_b" take part in this lookup.)
2207
     */
2208
383k
    if (options & NO_PORT_X) {
2209
        /*
2210
         * Search for conversations between two addresses, strictly
2211
         */
2212
116k
        DPRINT(("trying exact match: %s -> %s",
2213
116k
                    addr_a_str, addr_b_str));
2214
116k
        conversation = conversation_lookup_no_ports(frame_num, addr_a, addr_b, ctype);
2215
2216
116k
        if (conversation != NULL) {
2217
83.3k
            DPRINT(("match found"));
2218
83.3k
            goto end;
2219
83.3k
        }
2220
        /*
2221
         * Look for a conversation in the opposite direction.
2222
         */
2223
33.2k
        else {
2224
33.2k
            DPRINT(("trying exact match: %s -> %s",
2225
33.2k
                        addr_b_str, addr_a_str));
2226
33.2k
            conversation = conversation_lookup_no_ports(frame_num, addr_b, addr_a, ctype);
2227
33.2k
            if (conversation != NULL) {
2228
473
                DPRINT(("match found"));
2229
473
                goto end;
2230
473
            }
2231
33.2k
        }
2232
116k
    }
2233
2234
299k
    DPRINT(("no matches found"));
2235
2236
    /*
2237
     * We found no conversation.
2238
     */
2239
299k
    conversation = NULL;
2240
2241
757k
end:
2242
757k
    DINSTR(wmem_free(NULL, addr_a_str));
2243
757k
    DINSTR(wmem_free(NULL, addr_b_str));
2244
757k
    return conversation;
2245
299k
}
2246
2247
conversation_t *
2248
find_conversation_deinterlaced(const uint32_t frame_num, const address *addr_a, const address *addr_b, const conversation_type ctype,
2249
        const uint32_t port_a, const uint32_t port_b, const uint32_t anchor, const unsigned options)
2250
0
{
2251
0
    conversation_t *conversation, *other_conv;
2252
2253
0
    if (!addr_a) {
2254
0
        addr_a = &null_address_;
2255
0
    }
2256
2257
0
    if (!addr_b) {
2258
0
        addr_b = &null_address_;
2259
0
    }
2260
2261
0
    DINSTR(char *addr_a_str = address_to_str(NULL, addr_a));
2262
0
    DINSTR(char *addr_b_str = address_to_str(NULL, addr_b));
2263
2264
    /*
2265
     * First try an exact match, if we have two addresses and ports.
2266
     */
2267
0
    if (!(options & (NO_ADDR_B|NO_PORT_B|NO_PORTS|EXACT_EXCLUDED) )) {
2268
        /*
2269
         * Neither search address B nor search port B are wildcarded,
2270
         * start out with an exact match.
2271
         */
2272
0
        DPRINT(("trying exact match: %s:%d -> %s:%d",
2273
0
                    addr_a_str, port_a, addr_b_str, port_b));
2274
0
        conversation = conversation_lookup_exact_anc(frame_num, addr_a, port_a, addr_b, port_b, ctype, anchor);
2275
        /*
2276
         * Look for an alternate conversation in the opposite direction, which
2277
         * might fit better. Note that using the helper functions such as
2278
         * find_conversation_pinfo and find_or_create_conversation will finally
2279
         * call this function and look for an orientation-agnostic conversation.
2280
         * If oriented conversations had to be implemented, amend this code or
2281
         * create new functions.
2282
         */
2283
2284
0
        DPRINT(("trying exact match: %s:%d -> %s:%d",
2285
0
                    addr_b_str, port_b, addr_a_str, port_a));
2286
0
        other_conv = conversation_lookup_exact_anc(frame_num, addr_b, port_b, addr_a, port_a, ctype, anchor);
2287
0
        if (other_conv != NULL) {
2288
0
            if (conversation != NULL) {
2289
0
                if(other_conv->conv_index > conversation->conv_index) {
2290
0
                    conversation = other_conv;
2291
0
                }
2292
0
            }
2293
0
            else {
2294
0
                conversation = other_conv;
2295
0
            }
2296
0
        }
2297
0
        if ((conversation == NULL) && (addr_a->type == AT_FC)) {
2298
            /* In Fibre channel, OXID & RXID are never swapped as
2299
             * TCP/UDP ports are in TCP/IP.
2300
             */
2301
0
            DPRINT(("trying exact match: %s:%d -> %s:%d",
2302
0
                        addr_b_str, port_a, addr_a_str, port_b));
2303
0
            conversation = conversation_lookup_exact_anc(frame_num, addr_b, port_a, addr_a, port_b, ctype, anchor);
2304
0
        }
2305
0
        DPRINT(("exact match %sfound",conversation?"":"not "));
2306
0
        if (conversation != NULL) {
2307
0
            goto end;
2308
0
        }
2309
0
        else if(options & NO_GREEDY) {
2310
0
            goto end;
2311
0
        }
2312
0
    }
2313
2314
    /*
2315
     * Well, that didn't find anything.  Try matches that wildcard
2316
     * one of the addresses, if we have two ports.
2317
     */
2318
0
    if (!(options & (NO_PORT_B|NO_PORTS))) {
2319
        /*
2320
         * Search port B isn't wildcarded.
2321
         *
2322
         * First try looking for a conversation with the specified
2323
         * address A and port A as the first address and port, and
2324
         * with any address and the specified port B as the second
2325
         * address and port.
2326
         * ("addr_b" doesn't take part in this lookup.)
2327
         */
2328
0
        DPRINT(("trying wildcarded match: %s:%d -> *:%d",
2329
0
                    addr_a_str, port_a, port_b));
2330
0
        conversation = conversation_lookup_no_addr2_anc(frame_num, addr_a, port_a, port_b, ctype, anchor);
2331
0
        if ((conversation == NULL) && (addr_a->type == AT_FC)) {
2332
            /* In Fibre channel, OXID & RXID are never swapped as
2333
             * TCP/UDP ports are in TCP/IP.
2334
             */
2335
0
            DPRINT(("trying wildcarded match: %s:%d -> *:%d",
2336
0
                        addr_b_str, port_a, port_b));
2337
0
            conversation = conversation_lookup_no_addr2_anc(frame_num, addr_b, port_a, port_b, ctype, anchor);
2338
0
        }
2339
0
        if (conversation != NULL) {
2340
            /*
2341
             * If search address B isn't wildcarded, and this is for a
2342
             * connection-oriented protocol, set the second address for this
2343
             * conversation to address B, as that's the address that matched the
2344
             * wildcarded second address for this conversation.
2345
             *
2346
             * (This assumes that, for all connection oriented protocols, the
2347
             * endpoints of a connection have only one address each, i.e. you
2348
             * don't get packets in a given direction coming from more than one
2349
             * address, unless the CONVERSATION_TEMPLATE option is set.)
2350
             */
2351
0
            DPRINT(("wildcarded dest address match found"));
2352
0
            if (!(conversation->options & NO_ADDR2) && ctype != CONVERSATION_UDP)
2353
0
            {
2354
0
                if (!(conversation->options & CONVERSATION_TEMPLATE))
2355
0
                {
2356
0
                    conversation_set_addr2(conversation, addr_b);
2357
0
                }
2358
0
                else
2359
0
                {
2360
0
                    conversation =
2361
0
                        conversation_create_from_template(conversation, addr_b, 0);
2362
0
                }
2363
0
            }
2364
0
            goto end;
2365
0
        }
2366
2367
        /*
2368
         * Well, that didn't find anything.
2369
         * If search address B was specified, try looking for a
2370
         * conversation with the specified address B and port B as
2371
         * the first address and port, and with any address and the
2372
         * specified port A as the second address and port (this
2373
         * packet may be going in the opposite direction from the
2374
         * first packet in the conversation).
2375
         * ("addr_a" doesn't take part in this lookup.)
2376
         */
2377
0
        if (!(options & NO_ADDR_B)) {
2378
0
            DPRINT(("trying wildcarded match: %s:%d -> *:%d",
2379
0
                        addr_b_str, port_b, port_a));
2380
0
            conversation = conversation_lookup_no_addr2_anc(frame_num, addr_b, port_b, port_a, ctype, anchor);
2381
0
            if (conversation != NULL) {
2382
                /*
2383
                 * If this is for a connection-oriented
2384
                 * protocol, set the second address for
2385
                 * this conversation to address A, as
2386
                 * that's the address that matched the
2387
                 * wildcarded second address for this
2388
                 * conversation.
2389
                 */
2390
0
                DPRINT(("match found"));
2391
0
                if (ctype != CONVERSATION_UDP) {
2392
0
                    if (!(conversation->options & CONVERSATION_TEMPLATE))
2393
0
                    {
2394
0
                        conversation_set_addr2(conversation, addr_a);
2395
0
                    }
2396
0
                    else
2397
0
                    {
2398
0
                        conversation =
2399
0
                            conversation_create_from_template(conversation, addr_a, 0);
2400
0
                    }
2401
0
                }
2402
0
                goto end;
2403
0
            }
2404
0
        }
2405
0
    }
2406
2407
    /*
2408
     * Well, that didn't find anything.  Try matches that wildcard
2409
     * one of the ports, if we have two addresses.
2410
     */
2411
0
    if (!(options & (NO_ADDR_B|NO_PORTS))) {
2412
        /*
2413
         * Search address B isn't wildcarded.
2414
         *
2415
         * First try looking for a conversation with the specified
2416
         * address A and port A as the first address and port, and
2417
         * with the specified address B and any port as the second
2418
         * address and port.
2419
         * ("port_b" doesn't take part in this lookup.)
2420
         */
2421
0
        DPRINT(("trying wildcarded match: %s:%d -> %s:*",
2422
0
                    addr_a_str, port_a, addr_b_str));
2423
0
        conversation = conversation_lookup_no_port2_anc(frame_num, addr_a, port_a, addr_b, ctype, anchor);
2424
0
        if ((conversation == NULL) && (addr_a->type == AT_FC)) {
2425
            /* In Fibre channel, OXID & RXID are never swapped as
2426
             * TCP/UDP ports are in TCP/IP
2427
             */
2428
0
            DPRINT(("trying wildcarded match: %s:%d -> %s:*", addr_b_str, port_a, addr_a_str));
2429
0
            conversation = conversation_lookup_no_port2_anc(frame_num, addr_b, port_a, addr_a, ctype, anchor);
2430
0
        }
2431
0
        if (conversation != NULL) {
2432
            /*
2433
             * If search port B isn't wildcarded, and this is for a connection-
2434
             * oriented protocol, set the second port for this conversation to
2435
             * port B, as that's the port that matched the wildcarded second port
2436
             * for this conversation.
2437
             *
2438
             * (This assumes that, for all connection oriented protocols, the
2439
             * endpoints of a connection have only one port each, i.e. you don't
2440
             * get packets in a given direction coming from more than one port,
2441
             * unless the CONVERSATION_TEMPLATE option is set.)
2442
             */
2443
0
            DPRINT(("match found"));
2444
0
            if (!(conversation->options & NO_PORT2) && ctype != CONVERSATION_UDP)
2445
0
            {
2446
0
                if (!(conversation->options & CONVERSATION_TEMPLATE))
2447
0
                {
2448
0
                    conversation_set_port2(conversation, port_b);
2449
0
                }
2450
0
                else
2451
0
                {
2452
0
                    conversation =
2453
0
                        conversation_create_from_template(conversation, 0, port_b);
2454
0
                }
2455
0
            }
2456
0
            goto end;
2457
0
        }
2458
2459
        /*
2460
         * Well, that didn't find anything.
2461
         * If search port B was specified, try looking for a
2462
         * conversation with the specified address B and port B
2463
         * as the first address and port, and with the specified
2464
         * address A and any port as the second address and port
2465
         * (this packet may be going in the opposite direction
2466
         * from the first packet in the conversation).
2467
         * ("port_a" doesn't take part in this lookup.)
2468
         */
2469
0
        if (!(options & NO_PORT_B)) {
2470
0
            DPRINT(("trying wildcarded match: %s:%d -> %s:*",
2471
0
                        addr_b_str, port_b, addr_a_str));
2472
0
            conversation = conversation_lookup_no_port2_anc(frame_num, addr_b, port_b, addr_a, ctype, anchor);
2473
0
            if (conversation != NULL) {
2474
                /*
2475
                 * If this is for a connection-oriented
2476
                 * protocol, set the second port for
2477
                 * this conversation to port A, as
2478
                 * that's the address that matched the
2479
                 * wildcarded second address for this
2480
                 * conversation.
2481
                 */
2482
0
                DPRINT(("match found"));
2483
0
                if (ctype != CONVERSATION_UDP)
2484
0
                {
2485
0
                    if (!(conversation->options & CONVERSATION_TEMPLATE))
2486
0
                    {
2487
0
                        conversation_set_port2(conversation, port_a);
2488
0
                    }
2489
0
                    else
2490
0
                    {
2491
0
                        conversation =
2492
0
                            conversation_create_from_template(conversation, 0, port_a);
2493
0
                    }
2494
0
                }
2495
0
                goto end;
2496
0
            }
2497
0
        }
2498
0
        if(options & NO_GREEDY) {
2499
0
            goto end;
2500
0
        }
2501
0
    }
2502
2503
    /*
2504
     * Well, that didn't find anything.  Try matches that wildcard
2505
     * one address/port pair.
2506
     *
2507
     * First try looking for a conversation with the specified address A
2508
     * and port A as the first address and port.
2509
     * (Neither "addr_b" nor "port_b" take part in this lookup.)
2510
     */
2511
0
    DPRINT(("trying wildcarded match: %s:%d -> *:*", addr_a_str, port_a));
2512
0
    conversation = conversation_lookup_no_addr2_or_port2_anc(frame_num, addr_a, port_a, ctype, anchor);
2513
0
    if (conversation != NULL) {
2514
        /*
2515
         * If this is for a connection-oriented protocol:
2516
         *
2517
         * if search address B isn't wildcarded, set the
2518
         * second address for this conversation to address
2519
         * B, as that's the address that matched the
2520
         * wildcarded second address for this conversation;
2521
         *
2522
         * if search port B isn't wildcarded, set the
2523
         * second port for this conversation to port B,
2524
         * as that's the port that matched the wildcarded
2525
         * second port for this conversation.
2526
         */
2527
0
        DPRINT(("match found"));
2528
0
        if (ctype != CONVERSATION_UDP)
2529
0
        {
2530
0
            if (!(conversation->options & CONVERSATION_TEMPLATE))
2531
0
            {
2532
0
                if (!(conversation->options & NO_ADDR2))
2533
0
                    conversation_set_addr2(conversation, addr_b);
2534
0
                if (!(conversation->options & NO_PORT2))
2535
0
                    conversation_set_port2(conversation, port_b);
2536
0
            }
2537
0
            else
2538
0
            {
2539
0
                conversation =
2540
0
                    conversation_create_from_template(conversation, addr_b, port_b);
2541
0
            }
2542
0
        }
2543
0
        goto end;
2544
0
    }
2545
2546
    /* for Infiniband, don't try to look in addresses of reverse
2547
     * direction, because it could be another different
2548
     * valid conversation than what is being searched using
2549
     * addr_a, port_a.
2550
     */
2551
0
    if (ctype != CONVERSATION_IBQP)
2552
0
    {
2553
2554
        /*
2555
         * Well, that didn't find anything.
2556
         * If search address and port B were specified, try looking for a
2557
         * conversation with the specified address B and port B as the
2558
         * first address and port, and with any second address and port
2559
         * (this packet may be going in the opposite direction from the
2560
         * first packet in the conversation).
2561
         * (Neither "addr_a" nor "port_a" take part in this lookup.)
2562
         */
2563
0
        if (addr_a->type == AT_FC) {
2564
0
            DPRINT(("trying wildcarded match: %s:%d -> *:*",
2565
0
                        addr_b_str, port_a));
2566
0
            conversation = conversation_lookup_no_addr2_or_port2_anc(frame_num, addr_b, port_a, ctype, anchor);
2567
0
        } else {
2568
0
            DPRINT(("trying wildcarded match: %s:%d -> *:*",
2569
0
                        addr_b_str, port_b));
2570
0
            conversation = conversation_lookup_no_addr2_or_port2_anc(frame_num, addr_b, port_b, ctype, anchor);
2571
0
        }
2572
0
        if (conversation != NULL) {
2573
            /*
2574
             * If this is for a connection-oriented protocol, set the
2575
             * second address for this conversation to address A, as
2576
             * that's the address that matched the wildcarded second
2577
             * address for this conversation, and set the second port
2578
             * for this conversation to port A, as that's the port
2579
             * that matched the wildcarded second port for this
2580
             * conversation.
2581
             */
2582
0
            DPRINT(("match found"));
2583
0
            if (ctype != CONVERSATION_UDP)
2584
0
            {
2585
0
                if (!(conversation->options & CONVERSATION_TEMPLATE))
2586
0
                {
2587
0
                    conversation_set_addr2(conversation, addr_a);
2588
0
                    conversation_set_port2(conversation, port_a);
2589
0
                }
2590
0
                else
2591
0
                {
2592
0
                    conversation = conversation_create_from_template(conversation, addr_a, port_a);
2593
0
                }
2594
0
            }
2595
0
            goto end;
2596
0
        }
2597
0
    }
2598
2599
0
    if (options & NO_PORT_X) {
2600
        /*
2601
         * Search for conversations between two addresses, strictly
2602
         */
2603
0
        DPRINT(("trying exact match: %s -> %s",
2604
0
                    addr_a_str, addr_b_str));
2605
0
        conversation = conversation_lookup_no_ports_anc(frame_num, addr_a, addr_b, ctype, anchor);
2606
2607
0
        if (conversation != NULL) {
2608
0
            DPRINT(("match found"));
2609
0
            goto end;
2610
0
        }
2611
0
        else {
2612
0
            conversation = conversation_lookup_no_ports_anc(frame_num, addr_b, addr_a, ctype, anchor);
2613
0
            if (conversation != NULL) {
2614
0
                DPRINT(("match found"));
2615
0
                goto end;
2616
0
            }
2617
0
        }
2618
0
    }
2619
2620
0
    DPRINT(("no matches found"));
2621
2622
    /*
2623
     * We found no conversation.
2624
     */
2625
0
    conversation = NULL;
2626
2627
0
end:
2628
2629
0
    DINSTR(wmem_free(NULL, addr_a_str));
2630
0
    DINSTR(wmem_free(NULL, addr_b_str));
2631
0
    return conversation;
2632
0
}
2633
2634
conversation_t *
2635
find_conversation_deinterlacer(const uint32_t frame_num, const address *addr_a, const address *addr_b,
2636
        const conversation_type ctype, const uint32_t key_a, const uint32_t key_b, const uint32_t key_c)
2637
0
{
2638
0
    conversation_t *conversation, *other_conv;
2639
2640
0
    conversation = conversation_lookup_deinterlacer(frame_num, addr_a, addr_b, ctype, key_a, key_b, key_c);
2641
2642
0
    other_conv = conversation_lookup_deinterlacer(frame_num, addr_b, addr_a, ctype, key_a, key_b, key_c);
2643
0
    if (other_conv != NULL) {
2644
0
        if (conversation != NULL) {
2645
0
            if(other_conv->conv_index > conversation->conv_index) {
2646
0
                conversation = other_conv;
2647
0
            }
2648
0
        }
2649
0
        else {
2650
0
            conversation = other_conv;
2651
0
        }
2652
0
    }
2653
2654
0
    return conversation;
2655
0
}
2656
2657
conversation_t *
2658
find_conversation_deinterlacer_pinfo(const packet_info *pinfo)
2659
0
{
2660
0
  conversation_t *conv=NULL;
2661
0
  unsigned dr_conv_type; /* deinterlacer conv type */
2662
0
  uint32_t dtlc_iface = 0;
2663
0
  uint32_t dtlc_vlan = 0;
2664
2665
  /* evaluate the execution context: user pref, interface, VLAN */
2666
0
  if(prefs.conversation_deinterlacing_key>0) {
2667
0
    if(prefs.conversation_deinterlacing_key&CONV_DEINT_KEY_INTERFACE &&
2668
0
       pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID) {
2669
2670
0
      if(prefs.conversation_deinterlacing_key&CONV_DEINT_KEY_VLAN &&
2671
0
         pinfo->vlan_id>0) {
2672
2673
0
        dr_conv_type = CONVERSATION_ETH_IV;
2674
0
        dtlc_vlan = pinfo->vlan_id;
2675
0
      }
2676
0
      else {
2677
0
        dr_conv_type = CONVERSATION_ETH_IN;
2678
0
      }
2679
0
      dtlc_iface = pinfo->rec->rec_header.packet_header.interface_id;
2680
0
    }
2681
0
    else {
2682
0
      if(prefs.conversation_deinterlacing_key&CONV_DEINT_KEY_VLAN &&
2683
0
         pinfo->vlan_id>0) {
2684
2685
0
        dr_conv_type = CONVERSATION_ETH_NV;
2686
0
        dtlc_vlan = pinfo->vlan_id;
2687
0
      }
2688
0
      else {
2689
0
        dr_conv_type = CONVERSATION_ETH_NN;
2690
0
      }
2691
0
    }
2692
2693
0
    conv = find_conversation_deinterlacer(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, dr_conv_type, dtlc_iface, dtlc_vlan , 0);
2694
0
  }
2695
2696
0
  return conv;
2697
0
}
2698
2699
conversation_t *
2700
find_conversation_by_id(const uint32_t frame, const conversation_type ctype, const uint32_t id)
2701
469
{
2702
469
    conversation_element_t elements[2] = {
2703
469
        { CE_UINT, .uint_val = id },
2704
469
        { CE_CONVERSATION_TYPE, .conversation_type_val = ctype }
2705
469
    };
2706
2707
469
    return conversation_lookup_hashtable(conversation_hashtable_id, frame, elements);
2708
469
}
2709
2710
static gboolean
2711
find_conversation_by_index(void *key _U_, void *value, void *user_data)
2712
0
{
2713
0
    uint32_t convid = GPOINTER_TO_UINT(user_data);
2714
0
    conversation_t *conv = (conversation_t*)value;
2715
0
    if (conv->conv_index == convid) {
2716
0
        return true;
2717
0
    }
2718
0
    return false;
2719
0
}
2720
2721
conversation_t *
2722
find_conversation_err_pkts(const uint32_t frame, const conversation_type ctype, const uint32_t id, const uint32_t rid)
2723
3.99k
{
2724
3.99k
    conversation_element_t elements[3] = {
2725
3.99k
        { CE_UINT, .uint_val = id },
2726
3.99k
        { CE_UINT, .uint_val = rid },
2727
3.99k
        { CE_CONVERSATION_TYPE, .conversation_type_val = ctype }
2728
3.99k
    };
2729
2730
3.99k
    return conversation_lookup_hashtable(conversation_hashtable_err_pkts, frame, elements);
2731
3.99k
}
2732
2733
void
2734
conversation_add_proto_data(conversation_t *conv, const int proto, void *proto_data)
2735
77.3k
{
2736
77.3k
    if (conv == NULL) {
2737
0
        REPORT_DISSECTOR_BUG("%s: Can't add proto data to a NULL conversation.", proto_get_protocol_name(proto));
2738
0
    }
2739
    /* Add it to the list of items for this conversation. */
2740
77.3k
    if (conv->data_list == NULL)
2741
68.7k
        conv->data_list = wmem_tree_new(wmem_file_scope());
2742
2743
77.3k
    wmem_tree_insert32(conv->data_list, proto, proto_data);
2744
77.3k
}
2745
2746
void *
2747
conversation_get_proto_data(const conversation_t *conv, const int proto)
2748
342k
{
2749
342k
    if (conv == NULL) {
2750
0
        REPORT_DISSECTOR_BUG("%s: Can't get proto from a NULL conversation.", proto_get_protocol_name(proto));
2751
0
    }
2752
    /* No tree created yet */
2753
342k
    if (conv->data_list == NULL) {
2754
68.7k
        return NULL;
2755
68.7k
    }
2756
2757
273k
    return wmem_tree_lookup32(conv->data_list, proto);
2758
342k
}
2759
2760
void
2761
conversation_delete_proto_data(conversation_t *conv, const int proto)
2762
2
{
2763
2
    if (conv == NULL) {
2764
0
        REPORT_DISSECTOR_BUG("%s: Can't delete a NULL conversation.", proto_get_protocol_name(proto));
2765
0
    }
2766
2
    if (conv->data_list != NULL)
2767
2
        wmem_tree_remove32(conv->data_list, proto);
2768
2
}
2769
2770
void
2771
conversation_set_dissector_from_frame_number(conversation_t *conversation,
2772
        const uint32_t starting_frame_num, const dissector_handle_t handle)
2773
2.09k
{
2774
2.09k
    if (!conversation->dissector_tree) {
2775
1.73k
        conversation->dissector_tree = wmem_tree_new(wmem_file_scope());
2776
1.73k
    }
2777
2.09k
    wmem_tree_insert32(conversation->dissector_tree, starting_frame_num, (void *)handle);
2778
2.09k
}
2779
2780
void
2781
conversation_set_dissector(conversation_t *conversation, const dissector_handle_t handle)
2782
1.94k
{
2783
1.94k
    conversation_set_dissector_from_frame_number(conversation, 0, handle);
2784
1.94k
}
2785
2786
dissector_handle_t
2787
conversation_get_dissector(conversation_t *conversation, const uint32_t frame_num)
2788
805
{
2789
805
    if (!conversation->dissector_tree) {
2790
286
        return NULL;
2791
286
    }
2792
519
    return (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, frame_num);
2793
805
}
2794
2795
static bool
2796
try_conversation_call_dissector_helper(conversation_t *conversation, bool* dissector_success,
2797
        tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
2798
121k
{
2799
121k
    if (!conversation->dissector_tree) {
2800
118k
        return false;
2801
118k
    }
2802
2803
2.08k
    int ret;
2804
2.08k
    dissector_handle_t handle = (dissector_handle_t)wmem_tree_lookup32_le(
2805
2.08k
            conversation->dissector_tree, pinfo->num);
2806
2.08k
    if (handle == NULL) {
2807
0
        return false;
2808
0
    }
2809
2810
2.08k
    ret = call_dissector_only(handle, tvb, pinfo, tree, data);
2811
2812
    /* Let the caller decide what to do with success or rejection */
2813
2.08k
    (*dissector_success) = (ret != 0);
2814
2815
2.08k
    return true;
2816
2.08k
}
2817
2818
/*
2819
 * Given two address/port pairs for a packet, search for a matching
2820
 * conversation and, if found and it has a conversation dissector,
2821
 * call that dissector and return true, otherwise return false.
2822
 *
2823
 * This helper uses call_dissector_only which will NOT call the default
2824
 * "data" dissector if the packet was rejected.
2825
 * Our caller is responsible to call the data dissector explicitly in case
2826
 * this function returns false.
2827
 */
2828
bool
2829
try_conversation_dissector(const address *addr_a, const address *addr_b, const conversation_type ctype,
2830
        const uint32_t port_a, const uint32_t port_b, tvbuff_t *tvb, packet_info *pinfo,
2831
        proto_tree *tree, void* data, const unsigned options)
2832
37.7k
{
2833
37.7k
    conversation_t *conversation;
2834
37.7k
    bool dissector_success;
2835
2836
    /*
2837
     * Verify that the correct options are used, if any.
2838
     */
2839
37.7k
    DISSECTOR_ASSERT_HINT((options == 0) || (options & NO_MASK_B), "Use NO_ADDR_B and/or NO_PORT_B as option");
2840
2841
    /* Try each mode based on option flags */
2842
37.7k
    conversation = find_conversation(pinfo->num, addr_a, addr_b, ctype, port_a, port_b, 0);
2843
37.7k
    if (conversation != NULL) {
2844
37.7k
        if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
2845
865
            return dissector_success;
2846
37.7k
    }
2847
2848
36.8k
    if (options & NO_ADDR_B) {
2849
0
        conversation = find_conversation(pinfo->num, addr_a, addr_b, ctype, port_a, port_b, NO_ADDR_B);
2850
0
        if (conversation != NULL) {
2851
0
            if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
2852
0
                return dissector_success;
2853
0
        }
2854
0
    }
2855
2856
36.8k
    if (options & NO_PORT_B) {
2857
0
        conversation = find_conversation(pinfo->num, addr_a, addr_b, ctype, port_a, port_b, NO_PORT_B);
2858
0
        if (conversation != NULL) {
2859
0
            if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
2860
0
                return dissector_success;
2861
0
        }
2862
0
    }
2863
2864
36.8k
    if (options & (NO_ADDR_B|NO_PORT_B)) {
2865
0
        conversation = find_conversation(pinfo->num, addr_a, addr_b, ctype, port_a, port_b, NO_ADDR_B|NO_PORT_B);
2866
0
        if (conversation != NULL) {
2867
0
            if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
2868
0
                return dissector_success;
2869
0
        }
2870
0
    }
2871
2872
36.8k
    return false;
2873
36.8k
}
2874
2875
/*
2876
 * Similar to try_conversation_dissector() with the particularity of calling
2877
 * find_conversation_strat() in place of find_conversation() everywhere.
2878
 */
2879
bool
2880
try_conversation_dissector_strat(packet_info *pinfo, const conversation_type ctype,
2881
        tvbuff_t *tvb, proto_tree *tree, void* data, const unsigned options)
2882
79.1k
{
2883
79.1k
    conversation_t *conversation;
2884
79.1k
    bool dissector_success;
2885
2886
    /*
2887
     * Verify that the correct options are used, if any.
2888
     */
2889
79.1k
    DISSECTOR_ASSERT_HINT((options == 0) || (options & NO_MASK_B), "Use NO_ADDR_B and/or NO_PORT_B as option");
2890
2891
    /* Try each mode based on option flags */
2892
79.1k
    conversation = find_conversation_strat(pinfo, ctype, 0, false);
2893
79.1k
    if (conversation != NULL) {
2894
79.1k
        if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
2895
506
            return dissector_success;
2896
79.1k
    }
2897
2898
78.6k
    if (options & NO_ADDR_B) {
2899
78.3k
        conversation = find_conversation_strat(pinfo, ctype, NO_ADDR_B, false);
2900
78.3k
        if (conversation != NULL) {
2901
1.40k
            if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
2902
16
                return dissector_success;
2903
1.40k
        }
2904
78.3k
    }
2905
2906
78.6k
    if (options & NO_PORT_B) {
2907
78.3k
        conversation = find_conversation_strat(pinfo, ctype, NO_PORT_B, false);
2908
78.3k
        if (conversation != NULL) {
2909
1.37k
            if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data)) {
2910
6
                return dissector_success;
2911
6
            }
2912
1.37k
        }
2913
2914
78.3k
    }
2915
2916
78.6k
    if (options & (NO_ADDR_B|NO_PORT_B)) {
2917
78.3k
        conversation = find_conversation_strat(pinfo, ctype, NO_ADDR_B|NO_PORT_B, false);
2918
78.3k
        if (conversation != NULL) {
2919
1.36k
            if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data)) {
2920
0
                return dissector_success;
2921
0
            }
2922
1.36k
        }
2923
78.3k
    }
2924
2925
78.6k
    return false;
2926
78.6k
}
2927
2928
bool
2929
try_conversation_dissector_by_id(const conversation_type ctype, const uint32_t id, tvbuff_t *tvb,
2930
        packet_info *pinfo, proto_tree *tree, void* data)
2931
247
{
2932
247
    conversation_t *conversation;
2933
2934
247
    conversation = find_conversation_by_id(pinfo->num, ctype, id);
2935
2936
247
    if (conversation != NULL) {
2937
142
        if (!conversation->dissector_tree) {
2938
0
            return false;
2939
0
        }
2940
2941
142
        int ret;
2942
142
        dissector_handle_t handle = (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, pinfo->num);
2943
2944
142
        if (handle == NULL) {
2945
0
            return false;
2946
0
        }
2947
2948
142
        ret = call_dissector_only(handle, tvb, pinfo, tree, data);
2949
142
        if (!ret) {
2950
            /* this packet was rejected by the dissector
2951
             * so return false in case our caller wants
2952
             * to do some cleaning up.
2953
             */
2954
22
            return false;
2955
22
        }
2956
120
        return true;
2957
142
    }
2958
105
    return false;
2959
247
}
2960
2961
/* Identifies a conversation ("classic" or deinterlaced) */
2962
conversation_t *
2963
find_conversation_strat(const packet_info *pinfo, const conversation_type ctype, const unsigned options, const bool direction)
2964
534k
{
2965
534k
  conversation_t *conv=NULL;
2966
  /* deinterlacing is only supported for the Ethernet wtap for now */
2967
534k
  if( (pinfo->pseudo_header != NULL)
2968
534k
      && (pinfo->rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_ETHERNET)
2969
534k
      && (prefs.conversation_deinterlacing_key>0)) {
2970
0
    conversation_t *underlying_conv = find_conversation_deinterlacer_pinfo(pinfo);
2971
0
    if(underlying_conv) {
2972
0
        if(direction) { // reverse flow (dst to src)
2973
0
            conv = find_conversation_deinterlaced(pinfo->num, &pinfo->dst, &pinfo->src, ctype, pinfo->destport, pinfo->srcport, underlying_conv->conv_index, options);
2974
0
        }
2975
0
        else {
2976
0
            conv = find_conversation_deinterlaced(pinfo->num, &pinfo->src, &pinfo->dst, ctype, pinfo->srcport, pinfo->destport, underlying_conv->conv_index, options);
2977
0
        }
2978
0
    }
2979
0
  }
2980
534k
  else {
2981
534k
    if(direction) { // reverse flow (dst to src)
2982
352
      conv = find_conversation(pinfo->num, &pinfo->dst, &pinfo->src, ctype, pinfo->destport, pinfo->srcport, options);
2983
352
    }
2984
533k
    else { // default (src to dst)
2985
533k
      conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, ctype, pinfo->srcport, pinfo->destport, options);
2986
533k
    }
2987
534k
  }
2988
534k
  return conv;
2989
534k
}
2990
2991
/* Identifies a conversation ("classic" or deinterlaced) */
2992
conversation_t *
2993
find_conversation_strat_xtd(const packet_info *pinfo, const uint32_t frame_num, const address *addr_a, const address *addr_b,
2994
     const conversation_type ctype, const uint32_t port_a, const uint32_t port_b, const unsigned options)
2995
520
{
2996
520
  conversation_t *conv=NULL;
2997
  /* deinterlacing is only supported for the Ethernet wtap for now */
2998
520
  if( (pinfo->pseudo_header != NULL)
2999
520
      && (pinfo->rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_ETHERNET)
3000
520
      && (prefs.conversation_deinterlacing_key>0)) {
3001
0
    conversation_t *underlying_conv = find_conversation_deinterlacer_pinfo(pinfo);
3002
0
    if(underlying_conv) {
3003
0
        conv = find_conversation_deinterlaced(frame_num, addr_a, addr_b, ctype, port_a, port_b, underlying_conv->conv_index, options);
3004
0
    }
3005
0
  }
3006
520
  else {
3007
520
      conv = find_conversation(frame_num, addr_a, addr_b, ctype, port_a, port_b, options);
3008
520
  }
3009
520
  return conv;
3010
520
}
3011
3012
/**  A helper function that calls find_conversation() using data from pinfo
3013
 *  The frame number and addresses are taken from pinfo.
3014
 */
3015
conversation_t *
3016
find_conversation_pinfo(const packet_info *pinfo, const unsigned options)
3017
156k
{
3018
156k
    conversation_t *conv = NULL;
3019
3020
156k
    DINSTR(char *src_str = address_to_str(NULL, &pinfo->src));
3021
156k
    DINSTR(char *dst_str = address_to_str(NULL, &pinfo->dst));
3022
156k
    DPRINT(("called for frame #%u: %s:%d -> %s:%d (ptype=%d)",
3023
156k
                pinfo->num, src_str, pinfo->srcport,
3024
156k
                dst_str, pinfo->destport, pinfo->ptype));
3025
156k
    DINDENT();
3026
156k
    DINSTR(wmem_free(NULL, src_str));
3027
156k
    DINSTR(wmem_free(NULL, dst_str));
3028
3029
    /* Have we seen this conversation before? */
3030
156k
    if (pinfo->use_conv_addr_port_endpoints) {
3031
2.69k
        DISSECTOR_ASSERT(pinfo->conv_addr_port_endpoints);
3032
2.69k
        if ((conv = find_conversation(pinfo->num, &pinfo->conv_addr_port_endpoints->addr1, &pinfo->conv_addr_port_endpoints->addr2,
3033
2.69k
                        pinfo->conv_addr_port_endpoints->ctype, pinfo->conv_addr_port_endpoints->port1,
3034
2.69k
                        pinfo->conv_addr_port_endpoints->port2, 0)) != NULL) {
3035
2.15k
            DPRINT(("found previous conversation for frame #%u (last_frame=%d)",
3036
2.15k
                    pinfo->num, conv->last_frame));
3037
2.15k
            if (pinfo->num > conv->last_frame) {
3038
932
                conv->last_frame = pinfo->num;
3039
932
            }
3040
2.15k
        }
3041
154k
    } else if (pinfo->conv_elements) {
3042
12.5k
        if ((conv = find_conversation_full(pinfo->num, pinfo->conv_elements)) != NULL) {
3043
11.4k
            DPRINT(("found previous conversation elements for frame #%u (last_frame=%d)",
3044
11.4k
                        pinfo->num, conv->last_frame));
3045
11.4k
            if (pinfo->num > conv->last_frame) {
3046
2.84k
                conv->last_frame = pinfo->num;
3047
2.84k
            }
3048
11.4k
        }
3049
141k
    } else {
3050
141k
        if ((conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
3051
141k
                        conversation_pt_to_conversation_type(pinfo->ptype), pinfo->srcport,
3052
141k
                        pinfo->destport, options)) != NULL) {
3053
132k
            DPRINT(("found previous conversation for frame #%u (last_frame=%d)",
3054
132k
                        pinfo->num, conv->last_frame));
3055
132k
            if (pinfo->num > conv->last_frame) {
3056
14.4k
                conv->last_frame = pinfo->num;
3057
14.4k
            }
3058
132k
        }
3059
141k
    }
3060
3061
156k
    DENDENT();
3062
3063
156k
    return conv;
3064
156k
}
3065
3066
conversation_t *
3067
find_conversation_pinfo_deinterlaced(const packet_info *pinfo, const uint32_t anchor, const unsigned options)
3068
0
{
3069
0
    conversation_t *conv = NULL;
3070
3071
0
    DINSTR(char *src_str = address_to_str(NULL, &pinfo->src));
3072
0
    DINSTR(char *dst_str = address_to_str(NULL, &pinfo->dst));
3073
0
    DPRINT(("called for frame #%u: %s:%d -> %s:%d (ptype=%d)",
3074
0
                pinfo->num, src_str, pinfo->srcport,
3075
0
                dst_str, pinfo->destport, pinfo->ptype));
3076
0
    DINDENT();
3077
0
    DINSTR(wmem_free(NULL, src_str));
3078
0
    DINSTR(wmem_free(NULL, dst_str));
3079
3080
    /* Have we seen this conversation before? */
3081
0
    if (pinfo->use_conv_addr_port_endpoints) {
3082
        // XXX - not implemented yet. Necessary ?
3083
0
    } else if (pinfo->conv_elements) {
3084
        // XXX - not implemented yet. Necessary ?
3085
0
    } else {
3086
0
        if ((conv = find_conversation_deinterlaced(pinfo->num, &pinfo->src, &pinfo->dst,
3087
0
                        conversation_pt_to_conversation_type(pinfo->ptype), pinfo->srcport,
3088
0
                        pinfo->destport, anchor, options)) != NULL) {
3089
0
            DPRINT(("found previous conversation for frame #%u (last_frame=%d)",
3090
0
                        pinfo->num, conv->last_frame));
3091
0
            if (pinfo->num > conv->last_frame) {
3092
0
                conv->last_frame = pinfo->num;
3093
0
            }
3094
0
        }
3095
0
    }
3096
3097
0
    DENDENT();
3098
3099
0
    return conv;
3100
0
}
3101
3102
conversation_t *
3103
find_conversation_pinfo_strat(const packet_info *pinfo, const unsigned options)
3104
67
{
3105
67
  conversation_t *conv=NULL;
3106
3107
  /* deinterlacing is only supported for the Ethernet wtap for now */
3108
  // XXX - a Boolean returning function could be appropriate for this test
3109
67
  if( (pinfo->pseudo_header != NULL)
3110
67
      && (pinfo->rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_ETHERNET)
3111
67
      && (prefs.conversation_deinterlacing_key>0)) {
3112
3113
0
    conversation_t *underlying_conv = find_conversation_deinterlacer_pinfo(pinfo);
3114
3115
0
    if(underlying_conv) {
3116
0
        conv = find_conversation_pinfo_deinterlaced(pinfo, underlying_conv->conv_index, options);
3117
0
    }
3118
0
  }
3119
67
  else {
3120
67
      conv = find_conversation_pinfo(pinfo, options);
3121
67
  }
3122
3123
67
  return conv;
3124
67
}
3125
3126
/**  A helper function that calls find_conversation() using data from pinfo,
3127
 *  as above, but somewhat simplified for being accessed from packet_list.
3128
 *  The frame number and addresses are taken from pinfo.
3129
 */
3130
conversation_t *
3131
find_conversation_pinfo_ro(const packet_info *pinfo, const unsigned options)
3132
0
{
3133
0
    conversation_t *conv = NULL;
3134
3135
0
    DINSTR(char *src_str = address_to_str(NULL, &pinfo->src));
3136
0
    DINSTR(char *dst_str = address_to_str(NULL, &pinfo->dst));
3137
0
    DPRINT(("called for frame #%u: %s:%d -> %s:%d (ptype=%d)",
3138
0
                pinfo->num, src_str, pinfo->srcport,
3139
0
                dst_str, pinfo->destport, pinfo->ptype));
3140
0
    DINDENT();
3141
0
    DINSTR(wmem_free(NULL, src_str));
3142
0
    DINSTR(wmem_free(NULL, dst_str));
3143
3144
    /* Have we seen this conversation before? */
3145
0
    if (pinfo->use_conv_addr_port_endpoints) {
3146
0
        DISSECTOR_ASSERT(pinfo->conv_addr_port_endpoints);
3147
0
        if ((conv = find_conversation(pinfo->num, &pinfo->conv_addr_port_endpoints->addr1, &pinfo->conv_addr_port_endpoints->addr2,
3148
0
                        pinfo->conv_addr_port_endpoints->ctype, pinfo->conv_addr_port_endpoints->port1,
3149
0
                        pinfo->conv_addr_port_endpoints->port2, 0)) != NULL) {
3150
0
            DPRINT(("found previous conversation for frame #%u (last_frame=%d)",
3151
0
                    pinfo->num, conv->last_frame));
3152
0
        }
3153
0
    } else if (pinfo->conv_elements) {
3154
0
        if ((conv = find_conversation_full(pinfo->num, pinfo->conv_elements)) != NULL) {
3155
0
            DPRINT(("found previous conversation elements for frame #%u (last_frame=%d)",
3156
0
                        pinfo->num, conv->last_frame));
3157
0
        }
3158
0
    } else if ((conv = find_conversation_strat(pinfo, conversation_pt_to_conversation_type(pinfo->ptype), options, false)) != NULL) {
3159
0
             DPRINT(("found previous conversation for frame #%u (last_frame=%d)",
3160
0
                         pinfo->num, conv->last_frame));
3161
0
    }
3162
    /* If none of the above found any ordinary conversation,
3163
     * we might be dealing with an error packet referencing/carrying a known conversation.
3164
     * ICMP Type 3/11 are good examples, give them a chance to be identified.
3165
     * Note, any Transport protocol might be updated to allow this mechanism to work.
3166
     */
3167
0
    else if( (pinfo->track_ctype>0) ) {
3168
3169
        /* reference id */
3170
0
        uint32_t conv_index = 0;
3171
3172
        /* Parse all keys and find the one matching id and ctype,
3173
         * the reference id is what we are looking for.
3174
         */
3175
0
        wmem_list_t *err_pkts_keys = wmem_map_get_keys(NULL, conversation_hashtable_err_pkts);
3176
0
        for (wmem_list_frame_t *cur_frame = wmem_list_head(err_pkts_keys ); cur_frame; cur_frame = wmem_list_frame_next(cur_frame)) {
3177
0
            conversation_element_t *cet = (conversation_element_t *)wmem_list_frame_data(cur_frame);
3178
0
            if(cet) {
3179
0
                if( (cet[2].conversation_type_val == pinfo->track_ctype) && (cet[0].uint_val == pinfo->stream_id) ) {
3180
0
                    conv_index = cet[1].uint_val;
3181
0
                    break;
3182
0
                }
3183
0
            }
3184
0
        }
3185
0
        wmem_destroy_list(err_pkts_keys);
3186
3187
        /* Now, bring the transport conversation as we know its conv_index.
3188
         * Note: the way conversations are added (starting from lower layers),
3189
         * it's currently not possible to see a transport conversation
3190
         * with conv_index with value 0.
3191
         * XXX - Check if that is also true for PDU.
3192
         */
3193
0
        if(conv_index>0) {
3194
0
            conversation_t *tsconv = NULL;
3195
3196
            /* If a deinterlacing key was requested, search for the conversation
3197
             * in the deinterlaced version of the "addr_port" table.
3198
             * XXX - as this check is becoming redundant, isolate it in a function ?
3199
             */
3200
0
            if( (pinfo->pseudo_header != NULL)
3201
0
              && (pinfo->rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_ETHERNET)
3202
0
              && (prefs.conversation_deinterlacing_key>0)) {
3203
0
                tsconv = wmem_map_find(conversation_hashtable_exact_addr_port_anc, find_conversation_by_index, GUINT_TO_POINTER(conv_index));
3204
0
            }
3205
0
            else {
3206
0
                tsconv = wmem_map_find(conversation_hashtable_exact_addr_port, find_conversation_by_index, GUINT_TO_POINTER(conv_index));
3207
0
            }
3208
0
            if(tsconv) {
3209
0
                conv = tsconv;
3210
0
            }
3211
0
        }
3212
0
    }
3213
    /* else: something is either not implemented or not handled */
3214
3215
0
    DENDENT();
3216
3217
0
    return conv;
3218
0
}
3219
3220
/*  A helper function that calls find_conversation() and, if a conversation is
3221
 *  not found, calls conversation_new().
3222
 *  The frame number and addresses are taken from pinfo.
3223
 *  No options are used, though we could extend this API to include an options
3224
 *  parameter.
3225
 */
3226
conversation_t *
3227
find_or_create_conversation(const packet_info *pinfo)
3228
139k
{
3229
139k
    conversation_t *conv=NULL;
3230
3231
    /* Have we seen this conversation before? */
3232
139k
    if ((conv = find_conversation_pinfo(pinfo, 0)) == NULL) {
3233
        /* No, this is a new conversation. */
3234
5.77k
        DPRINT(("did not find previous conversation for frame #%u",
3235
5.77k
                    pinfo->num));
3236
5.77k
        DINDENT();
3237
5.77k
        if (pinfo->use_conv_addr_port_endpoints) {
3238
543
            conv = conversation_new(pinfo->num, &pinfo->conv_addr_port_endpoints->addr1, &pinfo->conv_addr_port_endpoints->addr2,
3239
543
                        pinfo->conv_addr_port_endpoints->ctype, pinfo->conv_addr_port_endpoints->port1,
3240
543
                        pinfo->conv_addr_port_endpoints->port2, 0);
3241
5.22k
        } else if (pinfo->conv_elements) {
3242
1.11k
            conv = conversation_new_full(pinfo->num, pinfo->conv_elements);
3243
4.11k
        } else {
3244
4.11k
            conv = conversation_new(pinfo->num, &pinfo->src,
3245
4.11k
                    &pinfo->dst, conversation_pt_to_conversation_type(pinfo->ptype),
3246
4.11k
                    pinfo->srcport, pinfo->destport, 0);
3247
4.11k
        }
3248
5.77k
        DENDENT();
3249
5.77k
    }
3250
3251
139k
    return conv;
3252
139k
}
3253
3254
conversation_t *
3255
find_or_create_conversation_deinterlaced(const packet_info *pinfo, const uint32_t conv_index)
3256
0
{
3257
0
    conversation_t *conv=NULL;
3258
3259
    /* Have we seen this conversation before? */
3260
0
    if ((conv = find_conversation_pinfo_deinterlaced(pinfo, conv_index, 0)) == NULL) {
3261
        /* No, this is a new conversation. */
3262
0
        DPRINT(("did not find previous conversation for frame #%u",
3263
0
                    pinfo->num));
3264
0
        DINDENT();
3265
0
        if (pinfo->use_conv_addr_port_endpoints) {
3266
0
            conv = conversation_new_strat(pinfo, pinfo->conv_addr_port_endpoints->ctype, 0);
3267
0
        } else if (pinfo->conv_elements) {
3268
0
            conv = conversation_new_full(pinfo->num, pinfo->conv_elements);
3269
0
        } else {
3270
0
            conv = conversation_new_deinterlaced(pinfo->num, &pinfo->src, &pinfo->dst,
3271
0
                    conversation_pt_to_conversation_type(pinfo->ptype),
3272
0
                    pinfo->srcport, pinfo->destport, conv_index, 0);
3273
0
        }
3274
0
        DENDENT();
3275
0
    }
3276
3277
0
    return conv;
3278
0
}
3279
3280
conversation_t *
3281
find_or_create_conversation_strat(const packet_info *pinfo)
3282
504
{
3283
504
    conversation_t *conv=NULL;
3284
3285
    /* deinterlacing is only supported for the Ethernet wtap for now */
3286
    // XXX - a Boolean returning function could be appropriate for this test
3287
504
    if( (pinfo->pseudo_header != NULL)
3288
504
        && (pinfo->rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_ETHERNET)
3289
504
        && (prefs.conversation_deinterlacing_key>0)) {
3290
3291
0
        conversation_t *underlying_conv = find_conversation_deinterlacer_pinfo(pinfo);
3292
0
        if(underlying_conv) {
3293
0
            conv = find_or_create_conversation_deinterlaced(pinfo, underlying_conv->conv_index);
3294
0
        }
3295
0
    }
3296
504
    else {
3297
504
        conv = find_or_create_conversation(pinfo);
3298
504
    }
3299
3300
504
    return conv;
3301
504
}
3302
3303
conversation_t *
3304
find_or_create_conversation_by_id(packet_info *pinfo, const conversation_type ctype, const uint32_t id)
3305
119
{
3306
119
    conversation_t *conv=NULL;
3307
3308
    /* Have we seen this conversation before? */
3309
119
    if ((conv = find_conversation_by_id(pinfo->num, ctype, id)) == NULL) {
3310
        /* No, this is a new conversation. */
3311
45
        DPRINT(("did not find previous conversation for frame #%u",
3312
45
                    pinfo->num));
3313
45
        DINDENT();
3314
45
        conv = conversation_new_by_id(pinfo->num, ctype, id);
3315
45
        DENDENT();
3316
45
    }
3317
3318
119
    return conv;
3319
119
}
3320
3321
void
3322
conversation_set_conv_addr_port_endpoints(struct _packet_info *pinfo, address* addr1, address* addr2,
3323
        conversation_type ctype, uint32_t port1, uint32_t port2)
3324
2.31k
{
3325
2.31k
    pinfo->conv_addr_port_endpoints = wmem_new0(pinfo->pool, struct conversation_addr_port_endpoints);
3326
3327
2.31k
    if (addr1 != NULL) {
3328
2.31k
        copy_address_wmem(pinfo->pool, &pinfo->conv_addr_port_endpoints->addr1, addr1);
3329
2.31k
    }
3330
2.31k
    if (addr2 != NULL) {
3331
2.31k
        copy_address_wmem(pinfo->pool, &pinfo->conv_addr_port_endpoints->addr2, addr2);
3332
2.31k
    }
3333
3334
2.31k
    pinfo->conv_addr_port_endpoints->ctype = ctype;
3335
2.31k
    pinfo->conv_addr_port_endpoints->port1 = port1;
3336
2.31k
    pinfo->conv_addr_port_endpoints->port2 = port2;
3337
3338
2.31k
    pinfo->use_conv_addr_port_endpoints = true;
3339
2.31k
}
3340
3341
void
3342
conversation_set_elements_by_id(struct _packet_info *pinfo, conversation_type ctype, uint32_t id)
3343
18.4k
{
3344
18.4k
    pinfo->conv_elements = wmem_alloc0(pinfo->pool, sizeof(conversation_element_t) * 2);
3345
18.4k
    pinfo->conv_elements[0].type = CE_UINT;
3346
18.4k
    pinfo->conv_elements[0].uint_val = id;
3347
18.4k
    pinfo->conv_elements[1].type = CE_CONVERSATION_TYPE;
3348
18.4k
    pinfo->conv_elements[1].conversation_type_val = ctype;
3349
18.4k
}
3350
3351
uint32_t
3352
conversation_get_id_from_elements(struct _packet_info *pinfo, conversation_type ctype, const unsigned options)
3353
20
{
3354
20
    if (pinfo->conv_elements == NULL) {
3355
0
        return 0;
3356
0
    }
3357
3358
20
    if (pinfo->conv_elements[0].type != CE_UINT || pinfo->conv_elements[1].type != CE_CONVERSATION_TYPE) {
3359
0
        return 0;
3360
0
    }
3361
3362
20
    if ((pinfo->conv_elements[1].conversation_type_val != ctype) && ((options & USE_LAST_ENDPOINT) != USE_LAST_ENDPOINT)) {
3363
0
        return 0;
3364
0
    }
3365
3366
20
    return pinfo->conv_elements[0].uint_val;
3367
20
}
3368
3369
wmem_map_t *
3370
get_conversation_hashtables(void)
3371
0
{
3372
0
    return conversation_hashtable_element_list;
3373
0
}
3374
3375
const address*
3376
conversation_key_addr1(const conversation_element_t *key)
3377
46.2k
{
3378
46.2k
    const address *addr = &null_address_;
3379
46.2k
    if (key[ADDR1_IDX].type == CE_ADDRESS) {
3380
46.2k
        addr = &key[ADDR1_IDX].addr_val;
3381
46.2k
    }
3382
46.2k
    return addr;
3383
46.2k
}
3384
3385
uint32_t
3386
conversation_key_port1(const conversation_element_t * key)
3387
347
{
3388
347
    uint32_t port = 0;
3389
347
    if (key[ADDR1_IDX].type == CE_ADDRESS && key[PORT1_IDX].type == CE_PORT) {
3390
347
        port = key[PORT1_IDX].port_val;
3391
347
    }
3392
347
    return port;
3393
347
}
3394
3395
const address*
3396
conversation_key_addr2(const conversation_element_t * key)
3397
347
{
3398
347
    const address *addr = &null_address_;
3399
347
    if (key[ADDR1_IDX].type == CE_ADDRESS && key[PORT1_IDX].type == CE_PORT && key[ADDR2_IDX].type == CE_ADDRESS) {
3400
347
        addr = &key[ADDR2_IDX].addr_val;
3401
347
    }
3402
347
    return addr;
3403
347
}
3404
3405
uint32_t
3406
conversation_key_port2(const conversation_element_t * key)
3407
347
{
3408
347
    uint32_t port = 0;
3409
347
    if (key[ADDR1_IDX].type == CE_ADDRESS && key[PORT1_IDX].type == CE_PORT) {
3410
347
        if (key[ADDR2_IDX].type == CE_ADDRESS && key[PORT2_IDX].type == CE_PORT) {
3411
            // Exact
3412
347
            port = key[PORT2_IDX].port_val;
3413
347
        } else if (key[PORT2_NO_ADDR2_IDX].type == CE_PORT) {
3414
            // No addr 2
3415
0
            port = key[PORT2_NO_ADDR2_IDX].port_val;
3416
0
        }
3417
347
    }
3418
347
    return port;
3419
347
}
3420
3421
WS_DLL_PUBLIC
3422
conversation_type conversation_pt_to_conversation_type(port_type pt)
3423
154k
{
3424
154k
    switch (pt)
3425
154k
    {
3426
23.7k
        case PT_NONE:
3427
23.7k
            return CONVERSATION_NONE;
3428
5.30k
        case PT_SCTP:
3429
5.30k
            return CONVERSATION_SCTP;
3430
55.0k
        case PT_TCP:
3431
55.0k
            return CONVERSATION_TCP;
3432
60.6k
        case PT_UDP:
3433
60.6k
            return CONVERSATION_UDP;
3434
1.78k
        case PT_DCCP:
3435
1.78k
            return CONVERSATION_DCCP;
3436
5.27k
        case PT_IPX:
3437
5.27k
            return CONVERSATION_IPX;
3438
753
        case PT_DDP:
3439
753
            return CONVERSATION_DDP;
3440
0
        case PT_IDP:
3441
0
            return CONVERSATION_IDP;
3442
104
        case PT_USB:
3443
104
            return CONVERSATION_USB;
3444
0
        case PT_I2C:
3445
            /* XXX - this doesn't currently have conversations */
3446
0
            return CONVERSATION_I2C;
3447
1.42k
        case PT_IBQP:
3448
1.42k
            return CONVERSATION_IBQP;
3449
0
        case PT_BLUETOOTH:
3450
0
            return CONVERSATION_BLUETOOTH;
3451
0
        case PT_IWARP_MPA:
3452
0
            return CONVERSATION_IWARP_MPA;
3453
0
        case PT_MCTP:
3454
0
            return CONVERSATION_MCTP;
3455
154k
    }
3456
3457
0
    DISSECTOR_ASSERT(false);
3458
0
    return CONVERSATION_NONE;
3459
154k
}
3460
3461
WS_DLL_PUBLIC
3462
endpoint_type conversation_pt_to_endpoint_type(port_type pt)
3463
65
{
3464
65
    switch (pt)
3465
65
    {
3466
0
        case PT_NONE:
3467
0
            return ENDPOINT_NONE;
3468
65
        case PT_SCTP:
3469
65
            return ENDPOINT_SCTP;
3470
0
        case PT_TCP:
3471
0
            return ENDPOINT_TCP;
3472
0
        case PT_UDP:
3473
0
            return ENDPOINT_UDP;
3474
0
        case PT_DCCP:
3475
0
            return ENDPOINT_DCCP;
3476
0
        case PT_IPX:
3477
0
            return ENDPOINT_IPX;
3478
0
        case PT_DDP:
3479
0
            return ENDPOINT_DDP;
3480
0
        case PT_IDP:
3481
0
            return ENDPOINT_IDP;
3482
0
        case PT_USB:
3483
0
            return ENDPOINT_USB;
3484
0
        case PT_I2C:
3485
            /* XXX - this doesn't have ports */
3486
0
            return ENDPOINT_I2C;
3487
0
        case PT_IBQP:
3488
0
            return ENDPOINT_IBQP;
3489
0
        case PT_BLUETOOTH:
3490
0
            return ENDPOINT_BLUETOOTH;
3491
0
        case PT_IWARP_MPA:
3492
0
            return ENDPOINT_IWARP_MPA;
3493
0
        case PT_MCTP:
3494
0
            return ENDPOINT_MCTP;
3495
65
    }
3496
3497
0
    DISSECTOR_ASSERT(false);
3498
0
    return ENDPOINT_NONE;
3499
65
}
3500
3501
/*
3502
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
3503
 *
3504
 * Local variables:
3505
 * c-basic-offset: 4
3506
 * tab-width: 8
3507
 * indent-tabs-mode: nil
3508
 * End:
3509
 *
3510
 * vi: set shiftwidth=4 tabstop=8 expandtab:
3511
 * :indentSize=4:tabSize=8:noTabs=true:
3512
 */