Bug Summary

File:epan/conversation.c
Warning:line 3300, column 5
Null returned from a function that is expected to return a non-null value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name conversation.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-20/lib/clang/20 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/epan -isystem /builds/wireshark/wireshark/build/epan -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /usr/include/lua5.4 -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -D epan_EXPORTS -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/wiretap -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-20/lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-truncation -Wno-format-nonliteral -Wno-pointer-sign -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2025-09-12-100405-3933-1 -x c /builds/wireshark/wireshark/epan/conversation.c
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 <[email protected]>
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
42int _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 */
49struct 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 */
58enum {
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 */
78enum {
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 */
88enum {
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. */
103static 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 */
118static wmem_map_t *conversation_hashtable_element_list;
119
120/*
121 * Hash table for conversations based on addresses only
122 */
123static wmem_map_t *conversation_hashtable_exact_addr;
124
125/*
126 * Hash table for conversations with no wildcards.
127 */
128static wmem_map_t *conversation_hashtable_exact_addr_port;
129
130/*
131 * Hash table for conversations with one wildcard address.
132 */
133static wmem_map_t *conversation_hashtable_no_addr2;
134
135/*
136 * Hash table for conversations with one wildcard port.
137 */
138static wmem_map_t *conversation_hashtable_no_port2;
139
140/*
141 * Hash table for conversations with one wildcard address and port.
142 */
143static wmem_map_t *conversation_hashtable_no_addr2_or_port2;
144
145/*
146 * Hash table for conversations with a single unsigned ID number.
147 */
148static wmem_map_t *conversation_hashtable_id;
149
150/*
151 * Hash table for conversations with no wildcards, and an anchor
152 */
153static wmem_map_t *conversation_hashtable_exact_addr_port_anc = NULL((void*)0);
154
155/*
156 * Hash table for conversations based on addresses only, and an anchor
157 */
158static wmem_map_t *conversation_hashtable_exact_addr_anc = NULL((void*)0);
159
160/*
161 * Hash table for conversations with one wildcard address, and an anchor
162 */
163static wmem_map_t *conversation_hashtable_no_addr2_anc = NULL((void*)0);
164
165/*
166 * Hash table for conversations with one wildcard port, and an anchor
167 */
168static wmem_map_t *conversation_hashtable_no_port2_anc = NULL((void*)0);
169
170/*
171 * Hash table for conversations with one wildcard address and port, and an anchor.
172 */
173static wmem_map_t *conversation_hashtable_no_addr2_or_port2_anc;
174
175/*
176 * Hash table for deinterlacing conversations (typically L1 or L2)
177 */
178static wmem_map_t *conversation_hashtable_deinterlacer = NULL((void*)0);
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 */
192static wmem_map_t *conversation_hashtable_err_pkts = NULL((void*)0);
193
194static uint32_t new_index;
195
196/*
197 * Placeholder for address-less conversations.
198 */
199static address null_address_ = ADDRESS_INIT_NONE{AT_NONE, 0, ((void*)0), ((void*)0)};
200
201
202/* Element count including the terminating CE_CONVERSATION_TYPE */
203#define MAX_CONVERSATION_ELEMENTS8 8 // Arbitrary.
204static size_t
205conversation_element_count(conversation_element_t *elements)
206{
207 size_t count = 0;
208 while (elements[count].type != CE_CONVERSATION_TYPE) {
209 count++;
210 DISSECTOR_ASSERT(count < MAX_CONVERSATION_ELEMENTS)((void) ((count < 8) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/conversation.c", 210
, "count < 8"))))
;
211 }
212 count++;
213 // Keying on the endpoint type alone isn't very useful.
214 DISSECTOR_ASSERT(count > 1)((void) ((count > 1) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/conversation.c", 214
, "count > 1"))))
;
215 return count;
216}
217
218static conversation_type
219conversation_get_key_type(conversation_element_t *elements)
220{
221 size_t count = 0;
222 while (elements[count].type != CE_CONVERSATION_TYPE) {
223 count++;
224 DISSECTOR_ASSERT(count < MAX_CONVERSATION_ELEMENTS)((void) ((count < 8) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/conversation.c", 224
, "count < 8"))))
;
225 }
226 return elements[count].conversation_type_val;
227}
228
229/* Create a string based on element types. */
230static char*
231conversation_element_list_name(wmem_allocator_t *allocator, conversation_element_t *elements) {
232 char *sep = "";
233 wmem_strbuf_t *conv_hash_group = wmem_strbuf_new(allocator, "");
234 size_t element_count = conversation_element_count(elements);
235 for (size_t i = 0; i < element_count; i++) {
236 conversation_element_t *cur_el = &elements[i];
237 DISSECTOR_ASSERT(cur_el->type < array_length(type_names))((void) ((cur_el->type < (sizeof (type_names) / sizeof (
type_names)[0])) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/conversation.c", 237, "cur_el->type < (sizeof (type_names) / sizeof (type_names)[0])"
))))
;
238 wmem_strbuf_append_printf(conv_hash_group, "%s%s", sep, type_names[cur_el->type]);
239 sep = ",";
240 }
241 return wmem_strbuf_finalize(conv_hash_group);
242}
243
244#if 0 // debugging
245static 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((void*)0), &cur_el->addr_val);
260 g_string_append(value_str, as)(__builtin_constant_p (as) ? __extension__ ({ const char * const
__val = (as); g_string_append_len_inline (value_str, __val, (
__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val)))
: (gssize) -1); }) : g_string_append_len_inline (value_str, as
, (gssize) -1))
;
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)(__builtin_constant_p (cur_el->str_val) ? __extension__ ({
const char * const __val = (cur_el->str_val); g_string_append_len_inline
(value_str, __val, (__val != ((void*)0)) ? (gssize) strlen (
((__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(value_str, cur_el->str_val, (gssize) -1))
;
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"l" "u", 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"l" "d", 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)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((value_str
), ((0))) : g_string_free_and_steal (value_str)) : (g_string_free
) ((value_str), ((0))))
;
293}
294#endif
295
296static bool_Bool
297is_no_addr2_key(conversation_element_t *key)
298{
299 if (key[ADDR1_IDX].type == CE_ADDRESS && key[PORT1_IDX].type == CE_PORT
300 && key[PORT2_NO_ADDR2_IDX].type == CE_PORT && key[ENDP_NO_ADDR2_IDX].type == CE_CONVERSATION_TYPE) {
301 return true1;
302 }
303 return false0;
304}
305
306static bool_Bool
307is_no_port2_key(conversation_element_t *key)
308{
309 if (key[ADDR1_IDX].type == CE_ADDRESS && key[PORT1_IDX].type == CE_PORT
310 && key[ADDR2_IDX].type == CE_ADDRESS && key[ENDP_NO_PORT2_IDX].type == CE_CONVERSATION_TYPE) {
311 return true1;
312 }
313 return false0;
314}
315
316static bool_Bool
317is_no_addr2_port2_key(conversation_element_t *key)
318{
319 if (key[ADDR1_IDX].type == CE_ADDRESS && key[PORT1_IDX].type == CE_PORT
320 && key[ENDP_NO_ADDR2_PORT2_IDX].type == CE_CONVERSATION_TYPE) {
321 return true1;
322 }
323 return false0;
324}
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 */
340static conversation_t *
341conversation_create_from_template(conversation_t *conversation, const address *addr2, const uint32_t port2)
342{
343 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 if (conversation->options & CONVERSATION_TEMPLATE0x08 && ctype != CONVERSATION_UDP)
349 {
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 conversation_t *new_conversation_from_template;
355 unsigned options = conversation->options & ~(CONVERSATION_TEMPLATE0x08 | NO_ADDR20x01 | NO_PORT20x02);
356
357 /*
358 * Are both the NO_ADDR2 and NO_PORT2 wildcards set in the options mask?
359 */
360 if (conversation->options & NO_ADDR20x01 && conversation->options & NO_PORT20x02
361 && is_no_addr2_port2_key(conversation->key_ptr))
362 {
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 new_conversation_from_template =
369 conversation_new(conversation->setup_frame,
370 &conversation->key_ptr[ADDR1_IDX].addr_val, addr2,
371 ctype, conversation->key_ptr[PORT1_IDX].port_val,
372 port2, options);
373 }
374 else if (conversation->options & NO_PORT20x02 && is_no_port2_key(conversation->key_ptr))
375 {
376 /*
377 * The conversation template was created without knowledge of port 2
378 * only. Create a new conversation with new 2nd port.
379 */
380 new_conversation_from_template =
381 conversation_new(conversation->setup_frame,
382 &conversation->key_ptr[ADDR1_IDX].addr_val, &conversation->key_ptr[ADDR2_IDX].addr_val,
383 ctype, conversation->key_ptr[PORT1_IDX].port_val,
384 port2, options);
385 }
386 else if (conversation->options & NO_ADDR20x01 && is_no_addr2_key(conversation->key_ptr))
387 {
388 /*
389 * The conversation template was created without knowledge of address
390 * 2. Create a new conversation with new 2nd address.
391 */
392 new_conversation_from_template =
393 conversation_new(conversation->setup_frame,
394 &conversation->key_ptr[ADDR1_IDX].addr_val, addr2,
395 ctype, conversation->key_ptr[PORT1_IDX].port_val,
396 conversation->key_ptr[PORT2_NO_ADDR2_IDX].port_val, options);
397 }
398 else
399 {
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 return conversation;
406 }
407
408 /*
409 * Set the protocol dissector used for the template conversation as
410 * the handler of the new conversation as well.
411 */
412 new_conversation_from_template->dissector_tree = conversation->dissector_tree;
413
414 return new_conversation_from_template;
415 }
416 else
417 {
418 return conversation;
419 }
420}
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 */
430static unsigned
431conversation_hash_element_list(const void *v)
432{
433 const conversation_element_t *element = (const conversation_element_t*)v;
434 unsigned hash_val = 0;
435
436 for (;;) {
437 // XXX We could use a hash_arbitrary_bytes routine. Abuse add_address_to_hash in the mean time.
438 address tmp_addr;
439 switch (element->type) {
440 case CE_ADDRESS:
441 hash_val = add_address_to_hash(hash_val, &element->addr_val);
442 break;
443 case CE_PORT:
444 tmp_addr.len = (int) sizeof(element->port_val);
445 tmp_addr.data = &element->port_val;
446 hash_val = add_address_to_hash(hash_val, &tmp_addr);
447 break;
448 case CE_STRING:
449 tmp_addr.len = (int) strlen(element->str_val);
450 tmp_addr.data = element->str_val;
451 hash_val = add_address_to_hash(hash_val, &tmp_addr);
452 break;
453 case CE_UINT:
454 tmp_addr.len = (int) sizeof(element->uint_val);
455 tmp_addr.data = &element->uint_val;
456 hash_val = add_address_to_hash(hash_val, &tmp_addr);
457 break;
458 case CE_UINT64:
459 tmp_addr.len = (int) sizeof(element->uint64_val);
460 tmp_addr.data = &element->uint64_val;
461 hash_val = add_address_to_hash(hash_val, &tmp_addr);
462 break;
463 case CE_INT:
464 tmp_addr.len = (int) sizeof(element->int_val);
465 tmp_addr.data = &element->int_val;
466 hash_val = add_address_to_hash(hash_val, &tmp_addr);
467 break;
468 case CE_INT64:
469 tmp_addr.len = (int) sizeof(element->int64_val);
470 tmp_addr.data = &element->int64_val;
471 hash_val = add_address_to_hash(hash_val, &tmp_addr);
472 break;
473 case CE_BLOB:
474 tmp_addr.len = (int) element->blob.len;
475 tmp_addr.data = element->blob.val;
476 hash_val = add_address_to_hash(hash_val, &tmp_addr);
477 break;
478 case CE_CONVERSATION_TYPE:
479 tmp_addr.len = (int) sizeof(element->conversation_type_val);
480 tmp_addr.data = &element->conversation_type_val;
481 hash_val = add_address_to_hash(hash_val, &tmp_addr);
482 goto done;
483 break;
484 }
485 element++;
486 }
487
488done:
489 hash_val += ( hash_val << 3 );
490 hash_val ^= ( hash_val >> 11 );
491 hash_val += ( hash_val << 15 );
492
493 return hash_val;
494}
495
496/*
497 * Compare two conversation keys for an exact match.
498 */
499static gboolean
500conversation_match_element_list(const void *v1, const void *v2)
501{
502 const conversation_element_t *element1 = (const conversation_element_t*)v1;
503 const conversation_element_t *element2 = (const conversation_element_t*)v2;
504
505 for (;;) {
506 if (element1->type != element2->type) {
507 return FALSE(0);
508 }
509
510 switch (element1->type) {
511 case CE_ADDRESS:
512 if (!addresses_equal(&element1->addr_val, &element2->addr_val)) {
513 return FALSE(0);
514 }
515 break;
516 case CE_PORT:
517 if (element1->port_val != element2->port_val) {
518 return FALSE(0);
519 }
520 break;
521 case CE_STRING:
522 if (strcmp(element1->str_val, element2->str_val)) {
523 return FALSE(0);
524 }
525 break;
526 case CE_UINT:
527 if (element1->uint_val != element2->uint_val) {
528 return FALSE(0);
529 }
530 break;
531 case CE_UINT64:
532 if (element1->uint64_val != element2->uint64_val) {
533 return FALSE(0);
534 }
535 break;
536 case CE_INT:
537 if (element1->int_val != element2->int_val) {
538 return FALSE(0);
539 }
540 break;
541 case CE_INT64:
542 if (element1->int64_val != element2->int64_val) {
543 return FALSE(0);
544 }
545 break;
546 case CE_BLOB:
547 if (element1->blob.len != element2->blob.len ||
548 (element1->blob.len > 0 && memcmp(element1->blob.val, element2->blob.val, element1->blob.len) != 0)) {
549 return FALSE(0);
550 }
551 break;
552 case CE_CONVERSATION_TYPE:
553 if (element1->conversation_type_val != element2->conversation_type_val) {
554 return FALSE(0);
555 }
556 goto done;
557 break;
558 }
559 element1++;
560 element2++;
561 }
562
563 done:
564 // Everything matched so far.
565 return TRUE(!(0));
566}
567
568/**
569 * Create a new hash tables for conversations.
570 */
571void
572conversation_init(void)
573{
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 conversation_hashtable_element_list = wmem_map_new(wmem_epan_scope(), wmem_str_hash, g_str_equal);
583
584 conversation_element_t exact_elements[EXACT_IDX_COUNT] = {
585 { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE{AT_NONE, 0, ((void*)0), ((void*)0)} },
586 { CE_PORT, .port_val = 0 },
587 { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE{AT_NONE, 0, ((void*)0), ((void*)0)} },
588 { CE_PORT, .port_val = 0 },
589 { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
590 };
591 char *exact_map_key = conversation_element_list_name(wmem_epan_scope(), exact_elements);
592 conversation_hashtable_exact_addr_port = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
593 conversation_hash_element_list,
594 conversation_match_element_list);
595 wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), exact_map_key),
596 conversation_hashtable_exact_addr_port);
597
598 conversation_element_t addrs_elements[ADDRS_IDX_COUNT] = {
599 { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE{AT_NONE, 0, ((void*)0), ((void*)0)} },
600 { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE{AT_NONE, 0, ((void*)0), ((void*)0)} },
601 { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
602 };
603 char *addrs_map_key = conversation_element_list_name(wmem_epan_scope(), addrs_elements);
604 conversation_hashtable_exact_addr = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
605 conversation_hash_element_list,
606 conversation_match_element_list);
607 wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), addrs_map_key),
608 conversation_hashtable_exact_addr);
609
610 conversation_element_t no_addr2_elements[NO_ADDR2_IDX_COUNT] = {
611 { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE{AT_NONE, 0, ((void*)0), ((void*)0)} },
612 { CE_PORT, .port_val = 0 },
613 { CE_PORT, .port_val = 0 },
614 { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
615 };
616 char *no_addr2_map_key = conversation_element_list_name(wmem_epan_scope(), no_addr2_elements);
617 conversation_hashtable_no_addr2 = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
618 conversation_hash_element_list,
619 conversation_match_element_list);
620 wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), no_addr2_map_key),
621 conversation_hashtable_no_addr2);
622
623 conversation_element_t no_port2_elements[NO_PORT2_IDX_COUNT] = {
624 { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE{AT_NONE, 0, ((void*)0), ((void*)0)} },
625 { CE_PORT, .port_val = 0 },
626 { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE{AT_NONE, 0, ((void*)0), ((void*)0)} },
627 { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
628 };
629 char *no_port2_map_key = conversation_element_list_name(wmem_epan_scope(), no_port2_elements);
630 conversation_hashtable_no_port2 = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
631 conversation_hash_element_list,
632 conversation_match_element_list);
633 wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), no_port2_map_key),
634 conversation_hashtable_no_port2);
635
636 conversation_element_t no_addr2_or_port2_elements[NO_ADDR2_PORT2_IDX_COUNT] = {
637 { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE{AT_NONE, 0, ((void*)0), ((void*)0)} },
638 { CE_PORT, .port_val = 0 },
639 { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
640 };
641 char *no_addr2_or_port2_map_key = conversation_element_list_name(wmem_epan_scope(), no_addr2_or_port2_elements);
642 conversation_hashtable_no_addr2_or_port2 = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
643 conversation_hash_element_list,
644 conversation_match_element_list);
645 wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), no_addr2_or_port2_map_key),
646 conversation_hashtable_no_addr2_or_port2);
647
648 conversation_element_t id_elements[2] = {
649 { CE_UINT, .uint_val = 0 },
650 { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
651 };
652 char *id_map_key = conversation_element_list_name(wmem_epan_scope(), id_elements);
653 conversation_hashtable_id = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
654 conversation_hash_element_list,
655 conversation_match_element_list);
656 wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), id_map_key),
657 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 conversation_element_t deinterlacer_elements[EXACT_IDX_COUNT+1] = {
674 { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE{AT_NONE, 0, ((void*)0), ((void*)0)} },
675 { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE{AT_NONE, 0, ((void*)0), ((void*)0)} },
676 { CE_UINT, .port_val = 0 },
677 { CE_UINT, .port_val = 0 },
678 { CE_UINT, .uint_val = 0 },
679 { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
680 };
681 char *deinterlacer_map_key = conversation_element_list_name(wmem_epan_scope(), deinterlacer_elements);
682 conversation_hashtable_deinterlacer = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
683 conversation_hash_element_list,
684 conversation_match_element_list);
685 wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), deinterlacer_map_key),
686 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 conversation_element_t exact_elements_anc[EXACT_IDX_COUNT+1] = {
698 { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE{AT_NONE, 0, ((void*)0), ((void*)0)} },
699 { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE{AT_NONE, 0, ((void*)0), ((void*)0)} },
700 { CE_PORT, .port_val = 0 },
701 { CE_PORT, .port_val = 0 },
702 { CE_UINT, .uint_val = 0 },
703 { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
704 };
705 char *exact_anc_map_key = conversation_element_list_name(wmem_epan_scope(), exact_elements_anc);
706 conversation_hashtable_exact_addr_port_anc = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
707 conversation_hash_element_list,
708 conversation_match_element_list);
709 wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), exact_anc_map_key),
710 conversation_hashtable_exact_addr_port_anc);
711
712 conversation_element_t addrs_elements_anc[ADDRS_IDX_COUNT+1] = {
713 { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE{AT_NONE, 0, ((void*)0), ((void*)0)} },
714 { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE{AT_NONE, 0, ((void*)0), ((void*)0)} },
715 { CE_UINT, .uint_val = 0 },
716 { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
717 };
718 char *addrs_anc_map_key = conversation_element_list_name(wmem_epan_scope(), addrs_elements_anc);
719 conversation_hashtable_exact_addr_anc = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
720 conversation_hash_element_list,
721 conversation_match_element_list);
722 wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), addrs_anc_map_key),
723 conversation_hashtable_exact_addr_anc);
724
725 conversation_element_t no_addr2_elements_anc[DEINTD_NO_PORT2_IDX_COUNT] = {
726 { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE{AT_NONE, 0, ((void*)0), ((void*)0)} },
727 { CE_PORT, .port_val = 0 },
728 { CE_PORT, .port_val = 0 },
729 { CE_UINT, .uint_val = 0 },
730 { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
731 };
732 char *no_addr2_anc_map_key = conversation_element_list_name(wmem_epan_scope(), no_addr2_elements_anc);
733 conversation_hashtable_no_addr2_anc = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
734 conversation_hash_element_list,
735 conversation_match_element_list);
736 wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), no_addr2_anc_map_key),
737 conversation_hashtable_no_addr2_anc);
738
739 conversation_element_t no_port2_elements_anc[DEINTD_NO_PORT2_IDX_COUNT] = {
740 { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE{AT_NONE, 0, ((void*)0), ((void*)0)} },
741 { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE{AT_NONE, 0, ((void*)0), ((void*)0)} },
742 { CE_PORT, .port_val = 0 },
743 { CE_UINT, .uint_val = 0 },
744 { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
745 };
746 char *no_port2_anc_map_key = conversation_element_list_name(wmem_epan_scope(), no_port2_elements_anc);
747 conversation_hashtable_no_port2_anc = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
748 conversation_hash_element_list,
749 conversation_match_element_list);
750 wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), no_port2_anc_map_key),
751 conversation_hashtable_no_port2_anc);
752
753 conversation_element_t no_addr2_or_port2_elements_anc[DEINTD_NO_ADDR2_PORT2_IDX_COUNT] = {
754 { CE_ADDRESS, .addr_val = ADDRESS_INIT_NONE{AT_NONE, 0, ((void*)0), ((void*)0)} },
755 { CE_PORT, .port_val = 0 },
756 { CE_UINT, .uint_val = 0 },
757 { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
758 };
759 char *no_addr2_or_port2_anc_map_key = conversation_element_list_name(wmem_epan_scope(), no_addr2_or_port2_elements_anc);
760 conversation_hashtable_no_addr2_or_port2_anc = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
761 conversation_hash_element_list,
762 conversation_match_element_list);
763 wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), no_addr2_or_port2_anc_map_key),
764 conversation_hashtable_no_addr2_or_port2_anc);
765
766 conversation_element_t err_pkts_elements[ERR_PKTS_COUNT] = {
767 { CE_UINT, .uint_val = 0 },
768 { CE_UINT, .uint_val = 0 },
769 { CE_CONVERSATION_TYPE, .conversation_type_val = CONVERSATION_NONE }
770 };
771 char *err_pkts_map_key = conversation_element_list_name(wmem_epan_scope(), err_pkts_elements);
772 conversation_hashtable_err_pkts = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
773 conversation_hash_element_list,
774 conversation_match_element_list);
775 wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), err_pkts_map_key),
776 conversation_hashtable_err_pkts);
777
778}
779
780/**
781 * Initialize some variables every time a file is loaded or re-loaded.
782 */
783void
784conversation_epan_reset(void)
785{
786 /*
787 * Start the conversation indices over at 0.
788 */
789 new_index = 0;
790}
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 */
798static void
799conversation_insert_into_hashtable(wmem_map_t *hashtable, conversation_t *conv)
800{
801 conversation_t *chain_head, *chain_tail, *cur, *prev;
802
803 chain_head = (conversation_t *)wmem_map_lookup(hashtable, conv->key_ptr);
804
805 if (NULL((void*)0)==chain_head) {
806 /* New entry */
807 conv->next = NULL((void*)0);
808 conv->last = conv;
809
810 wmem_map_insert(hashtable, conv->key_ptr, conv);
811 DPRINT(("created a new conversation chain"))(void)0;
812 }
813 else {
814 /* There's an existing chain for this key */
815 DPRINT(("there's an existing conversation chain"))(void)0;
816
817 chain_tail = chain_head->last;
818
819 if (conv->setup_frame >= chain_tail->setup_frame) {
820 /* This convo belongs at the end of the chain */
821 conv->next = NULL((void*)0);
822 conv->last = NULL((void*)0);
823 chain_tail->next = conv;
824 chain_head->last = conv;
825 }
826 else {
827 /* Loop through the chain to find the right spot */
828 cur = chain_head;
829 prev = NULL((void*)0);
830
831 for (; (conv->setup_frame > cur->setup_frame) && cur->next; prev=cur, cur=cur->next)
832 ;
833
834 if (NULL((void*)0)==prev) {
835 /* Changing the head of the chain */
836 conv->next = chain_head;
837 conv->last = chain_tail;
838 chain_head->last = NULL((void*)0);
839 wmem_map_insert(hashtable, conv->key_ptr, conv);
840 }
841 else {
842 /* Inserting into the middle of the chain */
843 conv->next = cur;
844 conv->last = NULL((void*)0);
845 prev->next = conv;
846 }
847 }
848 }
849}
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 */
855static void
856conversation_remove_from_hashtable(wmem_map_t *hashtable, conversation_t *conv)
857{
858 conversation_t *chain_head, *cur, *prev;
859
860 chain_head = (conversation_t *)wmem_map_lookup(hashtable, conv->key_ptr);
861
862 if (conv == chain_head) {
863 /* We are currently the front of the chain */
864 if (NULL((void*)0) == 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 wmem_map_steal(hashtable, conv->key_ptr);
870 }
871 else {
872 /* Update the head of the chain */
873 chain_head = conv->next;
874 chain_head->last = conv->last;
875
876 if (conv->latest_found == conv)
877 chain_head->latest_found = NULL((void*)0);
878 else
879 chain_head->latest_found = conv->latest_found;
880
881 wmem_map_insert(hashtable, chain_head->key_ptr, chain_head);
882 }
883 }
884 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 cur = chain_head->next;
889 prev = chain_head;
890
891 for (; (cur != conv) && cur->next; prev=cur, cur=cur->next)
892 ;
893
894 if (cur != conv) {
895 /* XXX: Conversation not found. Wrong hashtable? */
896 return;
897 }
898
899 prev->next = conv->next;
900
901 if (NULL((void*)0) == conv->next) {
902 /* We're at the very end of the list. */
903 chain_head->last = prev;
904 }
905
906 if (chain_head->latest_found == conv)
907 chain_head->latest_found = prev;
908 }
909}
910
911conversation_t *conversation_new_full(const uint32_t setup_frame, conversation_element_t *elements)
912{
913 DISSECTOR_ASSERT(elements)((void) ((elements) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/conversation.c", 913, "elements"))))
;
914
915 char *el_list_map_key = conversation_element_list_name(wmem_epan_scope(), elements);
916 wmem_map_t *el_list_map = (wmem_map_t *) wmem_map_lookup(conversation_hashtable_element_list, el_list_map_key);
917 if (!el_list_map) {
918 el_list_map = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), conversation_hash_element_list,
919 conversation_match_element_list);
920 wmem_map_insert(conversation_hashtable_element_list, wmem_strdup(wmem_epan_scope(), el_list_map_key), el_list_map);
921 }
922
923 size_t element_count = conversation_element_count(elements);
924 conversation_element_t *conv_key = wmem_memdup(wmem_file_scope(), elements, sizeof(conversation_element_t) * element_count);
925 for (size_t i = 0; i < element_count; i++) {
926 if (conv_key[i].type == CE_ADDRESS) {
927 copy_address_wmem(wmem_file_scope(), &conv_key[i].addr_val, &elements[i].addr_val);
928 } else if (conv_key[i].type == CE_STRING) {
929 conv_key[i].str_val = wmem_strdup(wmem_file_scope(), elements[i].str_val);
930 } else if (conv_key[i].type == CE_BLOB) {
931 conv_key[i].blob.val = wmem_memdup(wmem_file_scope(), elements[i].blob.val, elements[i].blob.len);
932 }
933 }
934
935 conversation_t *conversation = wmem_new0(wmem_file_scope(), conversation_t)((conversation_t*)wmem_alloc0((wmem_file_scope()), sizeof(conversation_t
)))
;
936 conversation->conv_index = new_index;
937 conversation->setup_frame = conversation->last_frame = setup_frame;
938
939 new_index++;
940
941 conversation->key_ptr = conv_key;
942 conversation_insert_into_hashtable(el_list_map, conversation);
943 return conversation;
944}
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 */
954conversation_t *
955conversation_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{
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 wmem_map_t* hashtable;
963 conversation_t *conversation = NULL((void*)0);
964 /*
965 * Verify that the correct options are used, if any.
966 */
967 DISSECTOR_ASSERT_HINT(!(options & NO_MASK_B), "Use NO_ADDR2 and/or NO_PORT2 or NO_PORT2_FORCE as option")((void) ((!(options & 0xFFFF0000)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\" (%s)", "epan/conversation.c"
, 967, "!(options & 0xFFFF0000)", "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((void*)0)) {
972 /*
973 * No address 1.
974 */
975 if (options & NO_ADDR20x01) {
976 /*
977 * Neither address 1 nor address 2.
978 */
979 if (options & NO_PORT20x02) {
980 /*
981 * Port 1 but not port 2.
982 */
983 DPRINT(("creating conversation for frame #%u: ID %u (ctype=%d)",(void)0
984 setup_frame, port1, ctype))(void)0;
985 } else {
986 /*
987 * Ports 1 and 2.
988 */
989 DPRINT(("creating conversation for frame #%u: %u -> %u (ctype=%d)",(void)0
990 setup_frame, port1, port2, ctype))(void)0;
991 }
992 } else {
993 /*
994 * Address 2 but not address 1.
995 */
996 addr2_str = address_to_str(NULL((void*)0), addr2);
997 if (options & NO_PORT20x02) {
998 /*
999 * Port 1 but not port 2.
1000 */
1001 DPRINT(("creating conversation for frame #%u: ID %u, address %s (ctype=%d)",(void)0
1002 setup_frame, port1, addr2_str, ctype))(void)0;
1003 } else {
1004 /*
1005 * Ports 1 and 2.
1006 */
1007 DPRINT(("creating conversation for frame #%u: %u -> %s:%u (ctype=%d)",(void)0
1008 setup_frame, port1, addr2_str, port2, ctype))(void)0;
1009 }
1010 wmem_free(NULL((void*)0), addr2_str);
1011 }
1012 } else {
1013 /*
1014 * Address 1.
1015 */
1016 addr1_str = address_to_str(NULL((void*)0), addr1);
1017 if (options & NO_ADDR20x01) {
1018 /*
1019 * Address 1 but no address 2.
1020 */
1021 if (options & NO_PORT20x02) {
1022 /*
1023 * Port 1 but not port 2.
1024 */
1025 DPRINT(("creating conversation for frame #%u: %s:%u (ctype=%d)",(void)0
1026 setup_frame, addr1_str, port1, ctype))(void)0;
1027 } else {
1028 /*
1029 * Ports 1 and 2.
1030 */
1031 DPRINT(("creating conversation for frame #%u: %s:%u -> %u (ctype=%d)",(void)0
1032 setup_frame, addr1_str, port1, port2, ctype))(void)0;
1033 }
1034 } else {
1035 /*
1036 * Addresses 1 and 2.
1037 */
1038 addr2_str = address_to_str(NULL((void*)0), addr2);
1039 if (options & NO_PORT20x02) {
1040 /*
1041 * Port 1 but not port 2.
1042 */
1043 DPRINT(("creating conversation for frame #%u: %s:%u -> %s (ctype=%d)",(void)0
1044 setup_frame, addr1_str, port1, addr2_str, ctype))(void)0;
1045 } else if (options & NO_PORTS0x010) {
1046 /*
1047 * No Ports.
1048 */
1049 DPRINT(("creating conversation for frame #%u: %s -> %s (ctype=%d)",(void)0
1050 setup_frame, addr1_str, addr2_str, ctype))(void)0;
1051 } else {
1052 /*
1053 * Ports 1 and 2.
1054 */
1055 DPRINT(("creating conversation for frame #%u: %s:%u -> %s:%u (ctype=%d)",(void)0
1056 setup_frame, addr1_str, port1, addr2_str, port2, ctype))(void)0;
1057 }
1058 wmem_free(NULL((void*)0), addr2_str);
1059 }
1060 wmem_free(NULL((void*)0), 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 conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * EXACT_IDX_COUNT);
1067 size_t addr2_idx = 0;
1068 size_t port2_idx = 0;
1069 size_t endp_idx;
1070
1071 new_key[ADDR1_IDX].type = CE_ADDRESS;
1072 if (addr1 != NULL((void*)0)) {
1073 copy_address_wmem(wmem_file_scope(), &new_key[ADDR1_IDX].addr_val, addr1);
1074 } else {
1075 clear_address(&new_key[ADDR1_IDX].addr_val);
1076 }
1077
1078 if (!(options & NO_PORTS0x010)) {
1079 new_key[PORT1_IDX].type = CE_PORT;
1080 new_key[PORT1_IDX].port_val = port1;
1081 }
1082
1083 if (options & NO_ADDR20x01) {
1084 if (options & (NO_PORT20x02|NO_PORT2_FORCE0x04)) {
1085 hashtable = conversation_hashtable_no_addr2_or_port2;
1086 endp_idx = ENDP_NO_ADDR2_PORT2_IDX;
1087 } else {
1088 hashtable = conversation_hashtable_no_addr2;
1089 port2_idx = PORT2_NO_ADDR2_IDX;
1090 endp_idx = ENDP_NO_ADDR2_IDX;
1091 }
1092 } else {
1093 if (options & (NO_PORT20x02|NO_PORT2_FORCE0x04)) {
1094 hashtable = conversation_hashtable_no_port2;
1095 addr2_idx = ADDR2_IDX;
1096 endp_idx = ENDP_NO_PORT2_IDX;
1097 } else if (options & NO_PORTS0x010) {
1098 hashtable = conversation_hashtable_exact_addr;
1099 addr2_idx = PORT1_IDX;
1100 endp_idx = ENDP_NO_PORTS_IDX;
1101 } else {
1102 hashtable = conversation_hashtable_exact_addr_port;
1103 addr2_idx = ADDR2_IDX;
1104 port2_idx = PORT2_IDX;
1105 endp_idx = ENDP_EXACT_IDX;
1106 }
1107 }
1108
1109 if (addr2_idx) {
1110 new_key[addr2_idx].type = CE_ADDRESS;
1111 if (addr2 != NULL((void*)0)) {
1112 copy_address_wmem(wmem_file_scope(), &new_key[addr2_idx].addr_val, addr2);
1113 } else {
1114 clear_address(&new_key[addr2_idx].addr_val);
1115 }
1116 }
1117
1118 if (port2_idx) {
1119 new_key[port2_idx].type = CE_PORT;
1120 new_key[port2_idx].port_val = port2;
1121 }
1122
1123 new_key[endp_idx].type = CE_CONVERSATION_TYPE;
1124 new_key[endp_idx].conversation_type_val = ctype;
1125
1126 conversation = wmem_new0(wmem_file_scope(), conversation_t)((conversation_t*)wmem_alloc0((wmem_file_scope()), sizeof(conversation_t
)))
;
1127
1128 conversation->conv_index = new_index;
1129 conversation->setup_frame = conversation->last_frame = setup_frame;
1130
1131 /* set the options and key pointer */
1132 conversation->options = options;
1133 conversation->key_ptr = new_key;
1134
1135 new_index++;
1136
1137 DINDENT()(void)0;
1138 conversation_insert_into_hashtable(hashtable, conversation);
1139 DENDENT()(void)0;
1140
1141 return conversation;
1142}
1143
1144conversation_t *
1145conversation_new_strat(const packet_info *pinfo, const conversation_type ctype, const unsigned options)
1146{
1147 conversation_t *conversation = NULL((void*)0);
1148 bool_Bool is_ordinary_conv = true1;
1149
1150 /* deinterlacing is only supported for the Ethernet wtap for now */
1151 if( (pinfo->pseudo_header != NULL((void*)0))
1152 && (pinfo->rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_ETHERNET1)
1153 && (prefs.conversation_deinterlacing_key>0)) {
1154 conversation_t *underlying_conv = find_conversation_deinterlacer_pinfo(pinfo);
1155 if(underlying_conv) {
1156 is_ordinary_conv = false0;
1157 conversation = conversation_new_deinterlaced(pinfo->num, &pinfo->src, &pinfo->dst, ctype,
1158 pinfo->srcport, pinfo->destport, underlying_conv->conv_index, options);
1159 }
1160 }
1161
1162 if(is_ordinary_conv) {
1163 conversation = conversation_new(pinfo->num, &pinfo->src, &pinfo->dst, ctype, pinfo->srcport, pinfo->destport, options);
1164 }
1165
1166 return conversation;
1167}
1168
1169conversation_t *
1170conversation_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{
1173 conversation_t *conversation = NULL((void*)0);
1174 bool_Bool is_ordinary_conv = true1;
1175
1176 /* deinterlacing is only supported for the Ethernet wtap for now */
1177 if( (pinfo->pseudo_header != NULL((void*)0))
1178 && (pinfo->rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_ETHERNET1)
1179 && (prefs.conversation_deinterlacing_key>0)) {
1180 conversation_t *underlying_conv = find_conversation_deinterlacer_pinfo(pinfo);
1181 if(underlying_conv) {
1182 is_ordinary_conv = false0;
1183 conversation = conversation_new_deinterlaced(setup_frame, addr1, addr2, ctype,
1184 port1, port2, underlying_conv->conv_index, options);
1185 }
1186 }
1187
1188 if(is_ordinary_conv) {
1189 conversation = conversation_new(setup_frame, addr1, addr2, ctype, port1, port2, options);
1190 }
1191
1192 return conversation;
1193}
1194
1195conversation_t *
1196conversation_new_by_id(const uint32_t setup_frame, const conversation_type ctype, const uint32_t id)
1197{
1198 conversation_t *conversation = wmem_new0(wmem_file_scope(), conversation_t)((conversation_t*)wmem_alloc0((wmem_file_scope()), sizeof(conversation_t
)))
;
1199 conversation->conv_index = new_index;
1200 conversation->setup_frame = conversation->last_frame = setup_frame;
1201
1202 new_index++;
1203
1204 conversation_element_t *elements = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * 2);
1205 elements[0].type = CE_UINT;
1206 elements[0].uint_val = id;
1207 elements[1].type = CE_CONVERSATION_TYPE;
1208 elements[1].conversation_type_val = ctype;
1209 conversation->key_ptr = elements;
1210 conversation_insert_into_hashtable(conversation_hashtable_id, conversation);
1211
1212 return conversation;
1213}
1214
1215conversation_t *
1216conversation_new_err_pkts(const uint32_t setup_frame, const conversation_type ctype, const uint32_t id, const uint32_t rid)
1217{
1218 conversation_t *conversation = wmem_new0(wmem_file_scope(), conversation_t)((conversation_t*)wmem_alloc0((wmem_file_scope()), sizeof(conversation_t
)))
;
1219 conversation->conv_index = new_index;
1220 conversation->setup_frame = conversation->last_frame = setup_frame;
1221
1222 new_index++;
1223
1224 conversation_element_t *elements = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * 3);
1225 elements[0].type = CE_UINT;
1226 elements[0].uint_val = id;
1227 elements[1].type = CE_UINT;
1228 elements[1].uint_val = rid;
1229 elements[2].type = CE_CONVERSATION_TYPE;
1230 elements[2].conversation_type_val = ctype;
1231 conversation->key_ptr = elements;
1232 conversation_insert_into_hashtable(conversation_hashtable_err_pkts, conversation);
1233
1234 return conversation;
1235}
1236
1237conversation_t *
1238conversation_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{
1241
1242 conversation_t *conversation = wmem_new0(wmem_file_scope(), conversation_t)((conversation_t*)wmem_alloc0((wmem_file_scope()), sizeof(conversation_t
)))
;
1243 conversation->conv_index = new_index;
1244 conversation->setup_frame = conversation->last_frame = setup_frame;
1245
1246 conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * (DEINTR_ENDP_IDX+1));
1247
1248 new_key[DEINTR_ADDR1_IDX].type = CE_ADDRESS;
1249 if (addr1 != NULL((void*)0)) {
1250 copy_address_wmem(wmem_file_scope(), &new_key[DEINTR_ADDR1_IDX].addr_val, addr1);
1251 }
1252 else {
1253 clear_address(&new_key[DEINTR_ADDR1_IDX].addr_val);
1254 }
1255
1256 new_key[DEINTR_ADDR2_IDX].type = CE_ADDRESS;
1257 if (addr2 != NULL((void*)0)) {
1258 copy_address_wmem(wmem_file_scope(), &new_key[DEINTR_ADDR2_IDX].addr_val, addr2);
1259 }
1260 else {
1261 clear_address(&new_key[DEINTR_ADDR2_IDX].addr_val);
1262 }
1263
1264 new_key[DEINTR_KEY1_IDX].type = CE_UINT;
1265 new_key[DEINTR_KEY1_IDX].uint_val = key1;
1266
1267 new_key[DEINTR_KEY2_IDX].type = CE_UINT;
1268 new_key[DEINTR_KEY2_IDX].uint_val = key2;
1269
1270 new_key[DEINTR_KEY3_IDX].type = CE_UINT;
1271 new_key[DEINTR_KEY3_IDX].uint_val = key3;
1272
1273 new_key[DEINTR_ENDP_IDX].type = CE_CONVERSATION_TYPE;
1274 new_key[DEINTR_ENDP_IDX].conversation_type_val = ctype;
1275
1276 conversation->key_ptr = new_key;
1277
1278 new_index++;
1279
1280 conversation_insert_into_hashtable(conversation_hashtable_deinterlacer, conversation);
1281
1282 return conversation;
1283}
1284
1285conversation_t *
1286conversation_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{
1289
1290 conversation_t *conversation = wmem_new0(wmem_file_scope(), conversation_t)((conversation_t*)wmem_alloc0((wmem_file_scope()), sizeof(conversation_t
)))
;
1291 conversation->conv_index = new_index;
1292 conversation->setup_frame = conversation->last_frame = setup_frame;
1293
1294 if (options & NO_PORTS0x010) {
1295 conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * (DEINTD_ENDP_NO_PORTS_IDX+2));
1296
1297 new_key[DEINTD_ADDR1_IDX].type = CE_ADDRESS;
1298 if (addr1 != NULL((void*)0)) {
1299 copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR1_IDX].addr_val, addr1);
1300 }
1301 else {
1302 clear_address(&new_key[DEINTD_ADDR1_IDX].addr_val);
1303 }
1304
1305 new_key[DEINTD_ADDR2_IDX].type = CE_ADDRESS;
1306 if (addr2 != NULL((void*)0)) {
1307 copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR2_IDX].addr_val, addr2);
1308 }
1309 else {
1310 clear_address(&new_key[DEINTD_ADDR2_IDX].addr_val);
1311 }
1312
1313 new_key[DEINTD_ENDP_NO_PORTS_IDX].type = CE_UINT;
1314 new_key[DEINTD_ENDP_NO_PORTS_IDX].uint_val = anchor;
1315
1316 new_key[DEINTD_ENDP_NO_PORTS_IDX+ 1].type = CE_CONVERSATION_TYPE;
1317 new_key[DEINTD_ENDP_NO_PORTS_IDX+ 1].conversation_type_val = ctype;
1318
1319 // set the options and key pointer
1320 conversation->options = options;
1321 conversation->key_ptr = new_key;
1322
1323 new_index++;
1324
1325 conversation_insert_into_hashtable(conversation_hashtable_exact_addr_anc, conversation);
1326
1327 return conversation;
1328 }
1329 else if (options & NO_ADDR20x01) {
1330 if (options & NO_PORT20x02) {
1331
1332 conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * (DEINTD_NO_ADDR2_PORT2_IDX_COUNT+1));
1333
1334 new_key[DEINTD_ADDR1_IDX].type = CE_ADDRESS;
1335 if (addr1 != NULL((void*)0)) {
1336 copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR1_IDX].addr_val, addr1);
1337 }
1338 else {
1339 clear_address(&new_key[DEINTD_ADDR1_IDX].addr_val);
1340 }
1341
1342 new_key[DEINTD_PORT1_IDX-1].type = CE_PORT;
1343 new_key[DEINTD_PORT1_IDX-1].port_val = port1;
1344
1345 new_key[DEINTD_NO_ADDR2_PORT2_IDX_COUNT-2].type = CE_UINT;
1346 new_key[DEINTD_NO_ADDR2_PORT2_IDX_COUNT-2].uint_val = anchor;
1347
1348 new_key[DEINTD_NO_ADDR2_PORT2_IDX_COUNT-1].type = CE_CONVERSATION_TYPE;
1349 new_key[DEINTD_NO_ADDR2_PORT2_IDX_COUNT-1].conversation_type_val = ctype;
1350
1351 // set the options and key pointer
1352 conversation->options = options;
1353 conversation->key_ptr = new_key;
1354
1355 new_index++;
1356
1357 conversation_insert_into_hashtable(conversation_hashtable_no_addr2_or_port2_anc, conversation);
1358
1359 return conversation;
1360 }
1361
1362 else {
1363 conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * (DEINTD_NO_ADDR2_IDX_COUNT+1));
1364
1365 new_key[DEINTD_ADDR1_IDX].type = CE_ADDRESS;
1366 if (addr1 != NULL((void*)0)) {
1367 copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR1_IDX].addr_val, addr1);
1368 }
1369 else {
1370 clear_address(&new_key[DEINTD_ADDR1_IDX].addr_val);
1371 }
1372
1373 new_key[DEINTD_PORT1_IDX-1].type = CE_PORT;
1374 new_key[DEINTD_PORT1_IDX-1].port_val = port1;
1375
1376 new_key[DEINTD_PORT2_IDX-1].type = CE_PORT;
1377 new_key[DEINTD_PORT2_IDX-1].port_val = port2;
1378
1379 new_key[DEINTD_NO_ADDR2_IDX_COUNT-2].type = CE_UINT;
1380 new_key[DEINTD_NO_ADDR2_IDX_COUNT-2].uint_val = anchor;
1381
1382 new_key[DEINTD_NO_ADDR2_IDX_COUNT-1].type = CE_CONVERSATION_TYPE;
1383 new_key[DEINTD_NO_ADDR2_IDX_COUNT-1].conversation_type_val = ctype;
1384
1385 // set the options and key pointer
1386 conversation->options = options;
1387 conversation->key_ptr = new_key;
1388
1389 new_index++;
1390
1391 conversation_insert_into_hashtable(conversation_hashtable_no_addr2_anc, conversation);
1392
1393 return conversation;
1394 }
1395 }
1396 else if (options & NO_PORT20x02) {
1397 conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * (DEINTD_EXACT_IDX_COUNT+1));
1398
1399 new_key[DEINTD_ADDR1_IDX].type = CE_ADDRESS;
1400 if (addr1 != NULL((void*)0)) {
1401 copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR1_IDX].addr_val, addr1);
1402 }
1403 else {
1404 clear_address(&new_key[DEINTD_ADDR1_IDX].addr_val);
1405 }
1406
1407 new_key[DEINTD_ADDR2_IDX].type = CE_ADDRESS;
1408 if (addr2 != NULL((void*)0)) {
1409 copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR2_IDX].addr_val, addr2);
1410 }
1411 else {
1412 clear_address(&new_key[DEINTD_ADDR2_IDX].addr_val);
1413 }
1414
1415 new_key[DEINTD_PORT1_IDX].type = CE_PORT;
1416 new_key[DEINTD_PORT1_IDX].port_val = port1;
1417
1418 new_key[DEINTD_PORT1_IDX + 1].type = CE_UINT;
1419 new_key[DEINTD_PORT1_IDX + 1].uint_val = anchor;
1420
1421 new_key[DEINTD_PORT1_IDX + 2].type = CE_CONVERSATION_TYPE;
1422 new_key[DEINTD_PORT1_IDX + 2].conversation_type_val = ctype;
1423
1424 // set the options and key pointer
1425 conversation->options = options;
1426 conversation->key_ptr = new_key;
1427
1428 new_index++;
1429
1430 conversation_insert_into_hashtable(conversation_hashtable_exact_addr_port_anc, conversation);
1431
1432 return conversation;
1433 }
1434 else {
1435 conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * (DEINTD_EXACT_IDX_COUNT+2));
1436
1437 new_key[DEINTD_ADDR1_IDX].type = CE_ADDRESS;
1438 if (addr1 != NULL((void*)0)) {
1439 copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR1_IDX].addr_val, addr1);
1440 }
1441 else {
1442 clear_address(&new_key[DEINTD_ADDR1_IDX].addr_val);
1443 }
1444
1445 new_key[DEINTD_ADDR2_IDX].type = CE_ADDRESS;
1446 if (addr2 != NULL((void*)0)) {
1447 copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR2_IDX].addr_val, addr2);
1448 }
1449 else {
1450 clear_address(&new_key[DEINTD_ADDR2_IDX].addr_val);
1451 }
1452
1453 new_key[DEINTD_PORT1_IDX].type = CE_PORT;
1454 new_key[DEINTD_PORT1_IDX].port_val = port1;
1455
1456 new_key[DEINTD_PORT2_IDX].type = CE_PORT;
1457 new_key[DEINTD_PORT2_IDX].port_val = port2;
1458
1459 new_key[DEINTD_ENDP_EXACT_IDX].type = CE_UINT;
1460 new_key[DEINTD_ENDP_EXACT_IDX].uint_val = anchor;
1461
1462 new_key[DEINTD_ENDP_EXACT_IDX + 1].type = CE_CONVERSATION_TYPE;
1463 new_key[DEINTD_ENDP_EXACT_IDX + 1].conversation_type_val = ctype;
1464
1465 // set the options and key pointer
1466 conversation->options = options;
1467 conversation->key_ptr = new_key;
1468
1469 new_index++;
1470
1471 conversation_insert_into_hashtable(conversation_hashtable_exact_addr_port_anc, conversation);
1472
1473 return conversation;
1474 }
1475}
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 */
1481void
1482conversation_set_port2(conversation_t *conv, const uint32_t port)
1483{
1484 DISSECTOR_ASSERT_HINT(!(conv->options & CONVERSATION_TEMPLATE),((void) ((!(conv->options & 0x08)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\" (%s)", "epan/conversation.c"
, 1485, "!(conv->options & 0x08)", "Use the conversation_create_from_template function when the CONVERSATION_TEMPLATE bit is set in the options mask"
))))
1485 "Use the conversation_create_from_template function when the CONVERSATION_TEMPLATE bit is set in the options mask")((void) ((!(conv->options & 0x08)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\" (%s)", "epan/conversation.c"
, 1485, "!(conv->options & 0x08)", "Use the conversation_create_from_template function when the CONVERSATION_TEMPLATE bit is set in the options mask"
))))
;
1486
1487 DPRINT(("called for port=%d", port))(void)0;
1488
1489 /*
1490 * If the port 2 value is not wildcarded, don't set it.
1491 */
1492 if ((!(conv->options & NO_PORT20x02)) || (conv->options & NO_PORT2_FORCE0x04))
1493 return;
1494
1495 DINDENT()(void)0;
1496 if (conv->options & NO_ADDR20x01) {
1497 conversation_remove_from_hashtable(conversation_hashtable_no_addr2_or_port2, conv);
1498 } else {
1499 conversation_remove_from_hashtable(conversation_hashtable_no_port2, conv);
1500 }
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 conv->options &= ~NO_PORT20x02;
1505 if (conv->options & NO_ADDR20x01) {
1506 // addr1,port1,endp -> addr1,port1,port2,endp
1507 conv->key_ptr[ENDP_NO_ADDR2_IDX] = conv->key_ptr[ENDP_NO_ADDR2_PORT2_IDX];
1508 conv->key_ptr[PORT2_NO_ADDR2_IDX].type = CE_PORT;
1509 conv->key_ptr[PORT2_NO_ADDR2_IDX].port_val = port;
1510 conversation_insert_into_hashtable(conversation_hashtable_no_addr2, conv);
1511 } else {
1512 // addr1,port1,addr2,endp -> addr1,port1,addr2,port2,endp
1513 conv->key_ptr[ENDP_EXACT_IDX] = conv->key_ptr[ENDP_NO_PORT2_IDX];
1514 conv->key_ptr[PORT2_IDX].type = CE_PORT;
1515 conv->key_ptr[PORT2_IDX].port_val = port;
1516 conversation_insert_into_hashtable(conversation_hashtable_exact_addr_port, conv);
1517 }
1518 DENDENT()(void)0;
1519}
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 */
1525void
1526conversation_set_addr2(conversation_t *conv, const address *addr)
1527{
1528 char* addr_str;
1529 DISSECTOR_ASSERT_HINT(!(conv->options & CONVERSATION_TEMPLATE),((void) ((!(conv->options & 0x08)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\" (%s)", "epan/conversation.c"
, 1530, "!(conv->options & 0x08)", "Use the conversation_create_from_template function when the CONVERSATION_TEMPLATE bit is set in the options mask"
))))
1530 "Use the conversation_create_from_template function when the CONVERSATION_TEMPLATE bit is set in the options mask")((void) ((!(conv->options & 0x08)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\" (%s)", "epan/conversation.c"
, 1530, "!(conv->options & 0x08)", "Use the conversation_create_from_template function when the CONVERSATION_TEMPLATE bit is set in the options mask"
))))
;
1531
1532 addr_str = address_to_str(NULL((void*)0), addr);
1533 DPRINT(("called for addr=%s", addr_str))(void)0;
1534 wmem_free(NULL((void*)0), addr_str);
1535
1536 /*
1537 * If the address 2 value is not wildcarded, don't set it.
1538 */
1539 if (!(conv->options & NO_ADDR20x01))
1540 return;
1541
1542 DINDENT()(void)0;
1543 if (conv->options & NO_PORT20x02) {
1544 conversation_remove_from_hashtable(conversation_hashtable_no_addr2_or_port2, conv);
1545 } else {
1546 conversation_remove_from_hashtable(conversation_hashtable_no_addr2, conv);
1547 }
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 conv->options &= ~NO_ADDR20x01;
1553 wmem_map_t *hashtable;
1554 if (conv->options & NO_PORT20x02) {
1555 // addr1,port1,endp -> addr1,port1,addr2,endp
1556 conv->key_ptr[ENDP_NO_PORT2_IDX] = conv->key_ptr[ENDP_NO_ADDR2_PORT2_IDX];
1557 hashtable = conversation_hashtable_no_port2;
1558 } else {
1559 // addr1,port1,port2,endp -> addr1,port1,addr2,port2,endp
1560 conv->key_ptr[ENDP_EXACT_IDX] = conv->key_ptr[ENDP_NO_ADDR2_IDX];
1561 conv->key_ptr[PORT2_IDX] = conv->key_ptr[PORT2_NO_ADDR2_IDX];
1562 hashtable = conversation_hashtable_exact_addr_port;
1563 }
1564 conv->key_ptr[ADDR2_IDX].type = CE_ADDRESS;
1565 copy_address_wmem(wmem_file_scope(), &conv->key_ptr[ADDR2_IDX].addr_val, addr);
1566 conversation_insert_into_hashtable(hashtable, conv);
1567 DENDENT()(void)0;
1568}
1569
1570static conversation_t *conversation_lookup_hashtable(wmem_map_t *conversation_hashtable, const uint32_t frame_num, conversation_element_t *conv_key)
1571{
1572 conversation_t* convo = NULL((void*)0);
1573 conversation_t* match = NULL((void*)0);
1574 conversation_t* chain_head = NULL((void*)0);
1575 chain_head = (conversation_t *)wmem_map_lookup(conversation_hashtable, conv_key);
1576
1577 if (chain_head && (chain_head->setup_frame <= frame_num)) {
1578 match = chain_head;
1579
1580 if (chain_head->last && (chain_head->last->setup_frame <= frame_num))
1581 return chain_head->last;
1582
1583 if (chain_head->latest_found && (chain_head->latest_found->setup_frame <= frame_num))
1584 match = chain_head->latest_found;
1585
1586 for (convo = match; convo && convo->setup_frame <= frame_num; convo = convo->next) {
1587 if (convo->setup_frame > match->setup_frame) {
1588 match = convo;
1589 }
1590 }
1591 }
1592
1593 if (match) {
1594 chain_head->latest_found = match;
1595 }
1596
1597 return match;
1598}
1599
1600conversation_t *find_conversation_full(const uint32_t frame_num, conversation_element_t *elements)
1601{
1602 char *el_list_map_key = conversation_element_list_name(NULL((void*)0), elements);
1603 wmem_map_t *el_list_map = (wmem_map_t *) wmem_map_lookup(conversation_hashtable_element_list, el_list_map_key);
1604 g_free(el_list_map_key);
1605 if (!el_list_map) {
1606 return NULL((void*)0);
1607 }
1608
1609 return conversation_lookup_hashtable(el_list_map, frame_num, elements);
1610}
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 */
1616static conversation_t *
1617conversation_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{
1620 conversation_element_t key[EXACT_IDX_COUNT] = {
1621 { CE_ADDRESS, .addr_val = *addr1 },
1622 { CE_PORT, .port_val = port1 },
1623 { CE_ADDRESS, .addr_val = *addr2 },
1624 { CE_PORT, .port_val = port2 },
1625 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1626 };
1627 return conversation_lookup_hashtable(conversation_hashtable_exact_addr_port, frame_num, key);
1628}
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 */
1634static conversation_t *
1635conversation_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{
1638 conversation_element_t key[NO_ADDR2_IDX_COUNT] = {
1639 { CE_ADDRESS, .addr_val = *addr1 },
1640 { CE_PORT, .port_val = port1 },
1641 { CE_PORT, .port_val = port2 },
1642 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1643 };
1644 return conversation_lookup_hashtable(conversation_hashtable_no_addr2, frame_num, key);
1645}
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 */
1651static conversation_t *
1652conversation_lookup_no_port2(const uint32_t frame_num, const address *addr1, const uint32_t port1,
1653 const address *addr2, const conversation_type ctype)
1654{
1655 conversation_element_t key[NO_PORT2_IDX_COUNT] = {
1656 { CE_ADDRESS, .addr_val = *addr1 },
1657 { CE_PORT, .port_val = port1 },
1658 { CE_ADDRESS, .addr_val = *addr2 },
1659 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1660 };
1661 return conversation_lookup_hashtable(conversation_hashtable_no_port2, frame_num, key);
1662}
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 */
1668static conversation_t *
1669conversation_lookup_no_addr2_or_port2(const uint32_t frame_num, const address *addr1, const uint32_t port1,
1670 const conversation_type ctype)
1671{
1672 conversation_element_t key[NO_ADDR2_PORT2_IDX_COUNT] = {
1673 { CE_ADDRESS, .addr_val = *addr1 },
1674 { CE_PORT, .port_val = port1 },
1675 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1676 };
1677 return conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2, frame_num, key);
1678}
1679
1680/*
1681 * Search a particular hash table for a conversation with the specified
1682 * {addr1, addr2} and set up before frame_num.
1683 */
1684static conversation_t *
1685conversation_lookup_no_ports(const uint32_t frame_num, const address *addr1,
1686 const address *addr2, const conversation_type ctype)
1687{
1688 conversation_element_t key[ADDRS_IDX_COUNT] = {
1689 { CE_ADDRESS, .addr_val = *addr1 },
1690 { CE_ADDRESS, .addr_val = *addr2 },
1691 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1692 };
1693 return conversation_lookup_hashtable(conversation_hashtable_exact_addr, frame_num, key);
1694}
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 */
1700static conversation_t *
1701conversation_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{
1705 conversation_element_t key[DEINTD_EXACT_IDX_COUNT+1] = {
1706 { CE_ADDRESS, .addr_val = *addr1 },
1707 { CE_ADDRESS, .addr_val = *addr2 },
1708 { CE_PORT, .port_val = port1 },
1709 { CE_PORT, .port_val = port2 },
1710 { CE_UINT, .uint_val = anchor },
1711 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1712 };
1713 return conversation_lookup_hashtable(conversation_hashtable_exact_addr_port_anc, frame_num, key);
1714}
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 */
1720static conversation_t *
1721conversation_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{
1724 conversation_element_t key[DEINTD_ADDRS_IDX_COUNT+1] = {
1725 { CE_ADDRESS, .addr_val = *addr1 },
1726 { CE_ADDRESS, .addr_val = *addr2 },
1727 { CE_UINT, .uint_val = anchor },
1728 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1729 };
1730 return conversation_lookup_hashtable(conversation_hashtable_exact_addr_anc, frame_num, key);
1731}
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 */
1737static conversation_t *
1738conversation_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{
1742 conversation_element_t key[DEINTD_NO_ADDR2_IDX_COUNT] = {
1743 { CE_ADDRESS, .addr_val = *addr1 },
1744 { CE_PORT, .port_val = port1 },
1745 { CE_PORT, .port_val = port2 },
1746 { CE_UINT, .uint_val = anchor },
1747 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1748 };
1749 return conversation_lookup_hashtable(conversation_hashtable_no_addr2_anc , frame_num, key);
1750}
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 */
1756static conversation_t *
1757conversation_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{
1761 conversation_element_t key[DEINTD_NO_PORT2_IDX_COUNT] = {
1762 { CE_ADDRESS, .addr_val = *addr1 },
1763 { CE_ADDRESS, .addr_val = *addr2 },
1764 { CE_PORT, .port_val = port1 },
1765 { CE_UINT, .uint_val = anchor },
1766 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1767 };
1768 return conversation_lookup_hashtable(conversation_hashtable_exact_addr_port_anc, frame_num, key);
1769}
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 */
1775static conversation_t *
1776conversation_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{
1779 conversation_element_t key[DEINTD_NO_ADDR2_PORT2_IDX_COUNT] = {
1780 { CE_ADDRESS, .addr_val = *addr1 },
1781 { CE_PORT, .port_val = port1 },
1782 { CE_UINT, .uint_val = anchor },
1783 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1784 };
1785 return conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2_anc, frame_num, key);
1786}
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 */
1793static conversation_t *
1794conversation_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{
1798 conversation_element_t key[DEINTR_ENDP_IDX+1] = {
1799 { CE_ADDRESS, .addr_val = *addr1 },
1800 { CE_ADDRESS, .addr_val = *addr2 },
1801 { CE_UINT, .uint_val = key1 },
1802 { CE_UINT, .uint_val = key2 },
1803 { CE_UINT, .uint_val = key3 },
1804 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1805 };
1806 return conversation_lookup_hashtable(conversation_hashtable_deinterlacer, frame_num, key);
1807}
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 */
1845conversation_t *
1846find_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{
1849 conversation_t *conversation, *other_conv;
1850
1851 if (!addr_a) {
1852 addr_a = &null_address_;
1853 }
1854
1855 if (!addr_b) {
1856 addr_b = &null_address_;
1857 }
1858
1859 DINSTR(char *addr_a_str = address_to_str(NULL, addr_a))(void)0;
1860 DINSTR(char *addr_b_str = address_to_str(NULL, addr_b))(void)0;
1861 /*
1862 * Verify that the correct options are used, if any.
1863 */
1864 DISSECTOR_ASSERT_HINT((options == 0) || (options & NO_MASK_B), "Use NO_ADDR_B and/or NO_PORT_B as option")((void) (((options == 0) || (options & 0xFFFF0000)) ? (void
)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\" (%s)"
, "epan/conversation.c", 1864, "(options == 0) || (options & 0xFFFF0000)"
, "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 if (!(options & (NO_ADDR_B0x00010000|NO_PORT_B0x00020000|NO_PORT_X0x00040000|EXACT_EXCLUDED0x00200000))) {
1869 /*
1870 * Neither search address B nor search port B are wildcarded,
1871 * start out with an exact match.
1872 */
1873 DPRINT(("trying exact match: %s:%d -> %s:%d",(void)0
1874 addr_a_str, port_a, addr_b_str, port_b))(void)0;
1875 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 DPRINT(("trying exact match: %s:%d -> %s:%d",(void)0
1886 addr_b_str, port_b, addr_a_str, port_a))(void)0;
1887 other_conv = conversation_lookup_exact(frame_num, addr_b, port_b, addr_a, port_a, ctype);
1888 if (other_conv != NULL((void*)0)) {
1889 if (conversation != NULL((void*)0)) {
1890 if(other_conv->conv_index > conversation->conv_index) {
1891 conversation = other_conv;
1892 }
1893 }
1894 else {
1895 conversation = other_conv;
1896 }
1897 }
1898 if ((conversation == NULL((void*)0)) && (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 DPRINT(("trying exact match: %s:%d -> %s:%d",(void)0
1903 addr_b_str, port_a, addr_a_str, port_b))(void)0;
1904 conversation = conversation_lookup_exact(frame_num, addr_b, port_a, addr_a, port_b, ctype);
1905 }
1906 DPRINT(("exact match %sfound",conversation?"":"not "))(void)0;
1907 if (conversation != NULL((void*)0))
1908 goto end;
1909 else if(options & NO_GREEDY0x00100000)
1910 goto end;
1911 }
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 if (!(options & (NO_PORT_B0x00020000|NO_PORT_X0x00040000))) {
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 DPRINT(("trying wildcarded match: %s:%d -> *:%d",(void)0
1928 addr_a_str, port_a, port_b))(void)0;
1929 conversation = conversation_lookup_no_addr2(frame_num, addr_a, port_a, port_b, ctype);
1930 if ((conversation == NULL((void*)0)) && (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 DPRINT(("trying wildcarded match: %s:%d -> *:%d",(void)0
1935 addr_b_str, port_a, port_b))(void)0;
1936 conversation = conversation_lookup_no_addr2(frame_num, addr_b, port_a, port_b, ctype);
1937 }
1938 if (conversation != NULL((void*)0)) {
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 DPRINT(("wildcarded dest address match found"))(void)0;
1951 if (!(conversation->options & NO_ADDR20x01) && ctype != CONVERSATION_UDP)
1952 {
1953 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
1954 {
1955 conversation_set_addr2(conversation, addr_b);
1956 }
1957 else
1958 {
1959 conversation =
1960 conversation_create_from_template(conversation, addr_b, 0);
1961 }
1962 }
1963 goto end;
1964 }
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 if (!(options & NO_ADDR_B0x00010000)) {
1977 DPRINT(("trying wildcarded match: %s:%d -> *:%d",(void)0
1978 addr_b_str, port_b, port_a))(void)0;
1979 conversation = conversation_lookup_no_addr2(frame_num, addr_b, port_b, port_a, ctype);
1980 if (conversation != NULL((void*)0)) {
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 DPRINT(("match found"))(void)0;
1990 if (ctype != CONVERSATION_UDP) {
1991 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
1992 {
1993 conversation_set_addr2(conversation, addr_a);
1994 }
1995 else
1996 {
1997 conversation =
1998 conversation_create_from_template(conversation, addr_a, 0);
1999 }
2000 }
2001 goto end;
2002 }
2003 }
2004 }
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 if (!(options & (NO_ADDR_B0x00010000|NO_PORT_X0x00040000))) {
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 DPRINT(("trying wildcarded match: %s:%d -> %s:*",(void)0
2021 addr_a_str, port_a, addr_b_str))(void)0;
2022 conversation = conversation_lookup_no_port2(frame_num, addr_a, port_a, addr_b, ctype);
2023 if ((conversation == NULL((void*)0)) && (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 DPRINT(("trying wildcarded match: %s:%d -> %s:*", addr_b_str, port_a, addr_a_str))(void)0;
2028 conversation = conversation_lookup_no_port2(frame_num, addr_b, port_a, addr_a, ctype);
2029 }
2030 if (conversation != NULL((void*)0)) {
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 DPRINT(("match found"))(void)0;
2043 if (!(conversation->options & NO_PORT20x02) && ctype != CONVERSATION_UDP)
2044 {
2045 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2046 {
2047 conversation_set_port2(conversation, port_b);
2048 }
2049 else
2050 {
2051 conversation =
2052 conversation_create_from_template(conversation, 0, port_b);
2053 }
2054 }
2055 goto end;
2056 }
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 if (!(options & NO_PORT_B0x00020000)) {
2069 DPRINT(("trying wildcarded match: %s:%d -> %s:*",(void)0
2070 addr_b_str, port_b, addr_a_str))(void)0;
2071 conversation = conversation_lookup_no_port2(frame_num, addr_b, port_b, addr_a, ctype);
2072 if (conversation != NULL((void*)0)) {
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 DPRINT(("match found"))(void)0;
2082 if (ctype != CONVERSATION_UDP)
2083 {
2084 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2085 {
2086 conversation_set_port2(conversation, port_a);
2087 }
2088 else
2089 {
2090 conversation =
2091 conversation_create_from_template(conversation, 0, port_a);
2092 }
2093 }
2094 goto end;
2095 }
2096 }
2097 if(options & NO_GREEDY0x00100000) {
2098 goto end;
2099 }
2100 }
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 if (!(options & NO_PORT_X0x00040000)) {
2111 DPRINT(("trying wildcarded match: %s:%d -> *:*", addr_a_str, port_a))(void)0;
2112 conversation = conversation_lookup_no_addr2_or_port2(frame_num, addr_a, port_a, ctype);
2113 if (conversation != NULL((void*)0)) {
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 DPRINT(("match found"))(void)0;
2128 if (ctype != CONVERSATION_UDP)
2129 {
2130 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2131 {
2132 if (!(conversation->options & NO_ADDR20x01))
2133 conversation_set_addr2(conversation, addr_b);
2134 if (!(conversation->options & NO_PORT20x02))
2135 conversation_set_port2(conversation, port_b);
2136 }
2137 else
2138 {
2139 conversation =
2140 conversation_create_from_template(conversation, addr_b, port_b);
2141 }
2142 }
2143 goto end;
2144 }
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 if (ctype != CONVERSATION_IBQP)
2151 {
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 if (addr_a->type == AT_FC) {
2163 DPRINT(("trying wildcarded match: %s:%d -> *:*",(void)0
2164 addr_b_str, port_a))(void)0;
2165 conversation = conversation_lookup_no_addr2_or_port2(frame_num, addr_b, port_a, ctype);
2166 } else {
2167 DPRINT(("trying wildcarded match: %s:%d -> *:*",(void)0
2168 addr_b_str, port_b))(void)0;
2169 conversation = conversation_lookup_no_addr2_or_port2(frame_num, addr_b, port_b, ctype);
2170 }
2171 if (conversation != NULL((void*)0)) {
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 DPRINT(("match found"))(void)0;
2182 if (ctype != CONVERSATION_UDP)
2183 {
2184 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2185 {
2186 conversation_set_addr2(conversation, addr_a);
2187 conversation_set_port2(conversation, port_a);
2188 }
2189 else
2190 {
2191 conversation = conversation_create_from_template(conversation, addr_a, port_a);
2192 }
2193 }
2194 goto end;
2195 }
2196 }
2197 }
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 if (options & NO_PORT_X0x00040000) {
2209 /*
2210 * Search for conversations between two addresses, strictly
2211 */
2212 DPRINT(("trying exact match: %s -> %s",(void)0
2213 addr_a_str, addr_b_str))(void)0;
2214 conversation = conversation_lookup_no_ports(frame_num, addr_a, addr_b, ctype);
2215
2216 if (conversation != NULL((void*)0)) {
2217 DPRINT(("match found"))(void)0;
2218 goto end;
2219 }
2220 /*
2221 * Look for a conversation in the opposite direction.
2222 */
2223 else {
2224 DPRINT(("trying exact match: %s -> %s",(void)0
2225 addr_b_str, addr_a_str))(void)0;
2226 conversation = conversation_lookup_no_ports(frame_num, addr_b, addr_a, ctype);
2227 if (conversation != NULL((void*)0)) {
2228 DPRINT(("match found"))(void)0;
2229 goto end;
2230 }
2231 }
2232 }
2233
2234 DPRINT(("no matches found"))(void)0;
2235
2236 /*
2237 * We found no conversation.
2238 */
2239 conversation = NULL((void*)0);
2240
2241end:
2242 DINSTR(wmem_free(NULL, addr_a_str))(void)0;
2243 DINSTR(wmem_free(NULL, addr_b_str))(void)0;
2244 return conversation;
2245}
2246
2247conversation_t *
2248find_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{
2251 conversation_t *conversation, *other_conv;
2252
2253 if (!addr_a) {
2254 addr_a = &null_address_;
2255 }
2256
2257 if (!addr_b) {
2258 addr_b = &null_address_;
2259 }
2260
2261 DINSTR(char *addr_a_str = address_to_str(NULL, addr_a))(void)0;
2262 DINSTR(char *addr_b_str = address_to_str(NULL, addr_b))(void)0;
2263
2264 /*
2265 * First try an exact match, if we have two addresses and ports.
2266 */
2267 if (!(options & (NO_ADDR_B0x00010000|NO_PORT_B0x00020000|NO_PORTS0x010|EXACT_EXCLUDED0x00200000) )) {
2268 /*
2269 * Neither search address B nor search port B are wildcarded,
2270 * start out with an exact match.
2271 */
2272 DPRINT(("trying exact match: %s:%d -> %s:%d",(void)0
2273 addr_a_str, port_a, addr_b_str, port_b))(void)0;
2274 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 DPRINT(("trying exact match: %s:%d -> %s:%d",(void)0
2285 addr_b_str, port_b, addr_a_str, port_a))(void)0;
2286 other_conv = conversation_lookup_exact_anc(frame_num, addr_b, port_b, addr_a, port_a, ctype, anchor);
2287 if (other_conv != NULL((void*)0)) {
2288 if (conversation != NULL((void*)0)) {
2289 if(other_conv->conv_index > conversation->conv_index) {
2290 conversation = other_conv;
2291 }
2292 }
2293 else {
2294 conversation = other_conv;
2295 }
2296 }
2297 if ((conversation == NULL((void*)0)) && (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 DPRINT(("trying exact match: %s:%d -> %s:%d",(void)0
2302 addr_b_str, port_a, addr_a_str, port_b))(void)0;
2303 conversation = conversation_lookup_exact_anc(frame_num, addr_b, port_a, addr_a, port_b, ctype, anchor);
2304 }
2305 DPRINT(("exact match %sfound",conversation?"":"not "))(void)0;
2306 if (conversation != NULL((void*)0)) {
2307 goto end;
2308 }
2309 else if(options & NO_GREEDY0x00100000) {
2310 goto end;
2311 }
2312 }
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 if (!(options & (NO_PORT_B0x00020000|NO_PORTS0x010))) {
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 DPRINT(("trying wildcarded match: %s:%d -> *:%d",(void)0
2329 addr_a_str, port_a, port_b))(void)0;
2330 conversation = conversation_lookup_no_addr2_anc(frame_num, addr_a, port_a, port_b, ctype, anchor);
2331 if ((conversation == NULL((void*)0)) && (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 DPRINT(("trying wildcarded match: %s:%d -> *:%d",(void)0
2336 addr_b_str, port_a, port_b))(void)0;
2337 conversation = conversation_lookup_no_addr2_anc(frame_num, addr_b, port_a, port_b, ctype, anchor);
2338 }
2339 if (conversation != NULL((void*)0)) {
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 DPRINT(("wildcarded dest address match found"))(void)0;
2352 if (!(conversation->options & NO_ADDR20x01) && ctype != CONVERSATION_UDP)
2353 {
2354 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2355 {
2356 conversation_set_addr2(conversation, addr_b);
2357 }
2358 else
2359 {
2360 conversation =
2361 conversation_create_from_template(conversation, addr_b, 0);
2362 }
2363 }
2364 goto end;
2365 }
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 if (!(options & NO_ADDR_B0x00010000)) {
2378 DPRINT(("trying wildcarded match: %s:%d -> *:%d",(void)0
2379 addr_b_str, port_b, port_a))(void)0;
2380 conversation = conversation_lookup_no_addr2_anc(frame_num, addr_b, port_b, port_a, ctype, anchor);
2381 if (conversation != NULL((void*)0)) {
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 DPRINT(("match found"))(void)0;
2391 if (ctype != CONVERSATION_UDP) {
2392 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2393 {
2394 conversation_set_addr2(conversation, addr_a);
2395 }
2396 else
2397 {
2398 conversation =
2399 conversation_create_from_template(conversation, addr_a, 0);
2400 }
2401 }
2402 goto end;
2403 }
2404 }
2405 }
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 if (!(options & (NO_ADDR_B0x00010000|NO_PORTS0x010))) {
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 DPRINT(("trying wildcarded match: %s:%d -> %s:*",(void)0
2422 addr_a_str, port_a, addr_b_str))(void)0;
2423 conversation = conversation_lookup_no_port2_anc(frame_num, addr_a, port_a, addr_b, ctype, anchor);
2424 if ((conversation == NULL((void*)0)) && (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 DPRINT(("trying wildcarded match: %s:%d -> %s:*", addr_b_str, port_a, addr_a_str))(void)0;
2429 conversation = conversation_lookup_no_port2_anc(frame_num, addr_b, port_a, addr_a, ctype, anchor);
2430 }
2431 if (conversation != NULL((void*)0)) {
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 DPRINT(("match found"))(void)0;
2444 if (!(conversation->options & NO_PORT20x02) && ctype != CONVERSATION_UDP)
2445 {
2446 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2447 {
2448 conversation_set_port2(conversation, port_b);
2449 }
2450 else
2451 {
2452 conversation =
2453 conversation_create_from_template(conversation, 0, port_b);
2454 }
2455 }
2456 goto end;
2457 }
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 if (!(options & NO_PORT_B0x00020000)) {
2470 DPRINT(("trying wildcarded match: %s:%d -> %s:*",(void)0
2471 addr_b_str, port_b, addr_a_str))(void)0;
2472 conversation = conversation_lookup_no_port2_anc(frame_num, addr_b, port_b, addr_a, ctype, anchor);
2473 if (conversation != NULL((void*)0)) {
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 DPRINT(("match found"))(void)0;
2483 if (ctype != CONVERSATION_UDP)
2484 {
2485 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2486 {
2487 conversation_set_port2(conversation, port_a);
2488 }
2489 else
2490 {
2491 conversation =
2492 conversation_create_from_template(conversation, 0, port_a);
2493 }
2494 }
2495 goto end;
2496 }
2497 }
2498 if(options & NO_GREEDY0x00100000) {
2499 goto end;
2500 }
2501 }
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 DPRINT(("trying wildcarded match: %s:%d -> *:*", addr_a_str, port_a))(void)0;
2512 conversation = conversation_lookup_no_addr2_or_port2_anc(frame_num, addr_a, port_a, ctype, anchor);
2513 if (conversation != NULL((void*)0)) {
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 DPRINT(("match found"))(void)0;
2528 if (ctype != CONVERSATION_UDP)
2529 {
2530 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2531 {
2532 if (!(conversation->options & NO_ADDR20x01))
2533 conversation_set_addr2(conversation, addr_b);
2534 if (!(conversation->options & NO_PORT20x02))
2535 conversation_set_port2(conversation, port_b);
2536 }
2537 else
2538 {
2539 conversation =
2540 conversation_create_from_template(conversation, addr_b, port_b);
2541 }
2542 }
2543 goto end;
2544 }
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 if (ctype != CONVERSATION_IBQP)
2552 {
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 if (addr_a->type == AT_FC) {
2564 DPRINT(("trying wildcarded match: %s:%d -> *:*",(void)0
2565 addr_b_str, port_a))(void)0;
2566 conversation = conversation_lookup_no_addr2_or_port2_anc(frame_num, addr_b, port_a, ctype, anchor);
2567 } else {
2568 DPRINT(("trying wildcarded match: %s:%d -> *:*",(void)0
2569 addr_b_str, port_b))(void)0;
2570 conversation = conversation_lookup_no_addr2_or_port2_anc(frame_num, addr_b, port_b, ctype, anchor);
2571 }
2572 if (conversation != NULL((void*)0)) {
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 DPRINT(("match found"))(void)0;
2583 if (ctype != CONVERSATION_UDP)
2584 {
2585 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2586 {
2587 conversation_set_addr2(conversation, addr_a);
2588 conversation_set_port2(conversation, port_a);
2589 }
2590 else
2591 {
2592 conversation = conversation_create_from_template(conversation, addr_a, port_a);
2593 }
2594 }
2595 goto end;
2596 }
2597 }
2598
2599 if (options & NO_PORT_X0x00040000) {
2600 /*
2601 * Search for conversations between two addresses, strictly
2602 */
2603 DPRINT(("trying exact match: %s -> %s",(void)0
2604 addr_a_str, addr_b_str))(void)0;
2605 conversation = conversation_lookup_no_ports_anc(frame_num, addr_a, addr_b, ctype, anchor);
2606
2607 if (conversation != NULL((void*)0)) {
2608 DPRINT(("match found"))(void)0;
2609 goto end;
2610 }
2611 else {
2612 conversation = conversation_lookup_no_ports_anc(frame_num, addr_b, addr_a, ctype, anchor);
2613 if (conversation != NULL((void*)0)) {
2614 DPRINT(("match found"))(void)0;
2615 goto end;
2616 }
2617 }
2618 }
2619
2620 DPRINT(("no matches found"))(void)0;
2621
2622 /*
2623 * We found no conversation.
2624 */
2625 conversation = NULL((void*)0);
2626
2627end:
2628
2629 DINSTR(wmem_free(NULL, addr_a_str))(void)0;
2630 DINSTR(wmem_free(NULL, addr_b_str))(void)0;
2631 return conversation;
2632}
2633
2634conversation_t *
2635find_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{
2638 conversation_t *conversation, *other_conv;
2639
2640 conversation = conversation_lookup_deinterlacer(frame_num, addr_a, addr_b, ctype, key_a, key_b, key_c);
2641
2642 other_conv = conversation_lookup_deinterlacer(frame_num, addr_b, addr_a, ctype, key_a, key_b, key_c);
2643 if (other_conv != NULL((void*)0)) {
2644 if (conversation != NULL((void*)0)) {
2645 if(other_conv->conv_index > conversation->conv_index) {
2646 conversation = other_conv;
2647 }
2648 }
2649 else {
2650 conversation = other_conv;
2651 }
2652 }
2653
2654 return conversation;
2655}
2656
2657conversation_t *
2658find_conversation_deinterlacer_pinfo(const packet_info *pinfo)
2659{
2660 conversation_t *conv=NULL((void*)0);
2661 unsigned dr_conv_type; /* deinterlacer conv type */
2662 uint32_t dtlc_iface = 0;
2663 uint32_t dtlc_vlan = 0;
2664
2665 /* evaluate the execution context: user pref, interface, VLAN */
2666 if(prefs.conversation_deinterlacing_key>0) {
2667 if(prefs.conversation_deinterlacing_key&CONV_DEINT_KEY_INTERFACE0x02 &&
2668 pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID0x00000004) {
2669
2670 if(prefs.conversation_deinterlacing_key&CONV_DEINT_KEY_VLAN0x08 &&
2671 pinfo->vlan_id>0) {
2672
2673 dr_conv_type = CONVERSATION_ETH_IV;
2674 dtlc_vlan = pinfo->vlan_id;
2675 }
2676 else {
2677 dr_conv_type = CONVERSATION_ETH_IN;
2678 }
2679 dtlc_iface = pinfo->rec->rec_header.packet_header.interface_id;
2680 }
2681 else {
2682 if(prefs.conversation_deinterlacing_key&CONV_DEINT_KEY_VLAN0x08 &&
2683 pinfo->vlan_id>0) {
2684
2685 dr_conv_type = CONVERSATION_ETH_NV;
2686 dtlc_vlan = pinfo->vlan_id;
2687 }
2688 else {
2689 dr_conv_type = CONVERSATION_ETH_NN;
2690 }
2691 }
2692
2693 conv = find_conversation_deinterlacer(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, dr_conv_type, dtlc_iface, dtlc_vlan , 0);
2694 }
2695
2696 return conv;
2697}
2698
2699conversation_t *
2700find_conversation_by_id(const uint32_t frame, const conversation_type ctype, const uint32_t id)
2701{
2702 conversation_element_t elements[2] = {
2703 { CE_UINT, .uint_val = id },
2704 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype }
2705 };
2706
2707 return conversation_lookup_hashtable(conversation_hashtable_id, frame, elements);
2708}
2709
2710static gboolean
2711find_conversation_by_index(void *key _U___attribute__((unused)), void *value, void *user_data)
2712{
2713 uint32_t convid = GPOINTER_TO_UINT(user_data)((guint) (gulong) (user_data));
2714 conversation_t *conv = (conversation_t*)value;
2715 if (conv->conv_index == convid) {
2716 return true1;
2717 }
2718 return false0;
2719}
2720
2721conversation_t *
2722find_conversation_err_pkts(const uint32_t frame, const conversation_type ctype, const uint32_t id, const uint32_t rid)
2723{
2724 conversation_element_t elements[3] = {
2725 { CE_UINT, .uint_val = id },
2726 { CE_UINT, .uint_val = rid },
2727 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype }
2728 };
2729
2730 return conversation_lookup_hashtable(conversation_hashtable_err_pkts, frame, elements);
2731}
2732
2733void
2734conversation_add_proto_data(conversation_t *conv, const int proto, void *proto_data)
2735{
2736 if (conv == NULL((void*)0)) {
2737 REPORT_DISSECTOR_BUG("%s: Can't add proto data to a NULL conversation.", proto_get_protocol_name(proto))proto_report_dissector_bug("%s: Can't add proto data to a NULL conversation."
, proto_get_protocol_name(proto))
;
2738 }
2739 /* Add it to the list of items for this conversation. */
2740 if (conv->data_list == NULL((void*)0))
2741 conv->data_list = wmem_tree_new(wmem_file_scope());
2742
2743 wmem_tree_insert32(conv->data_list, proto, proto_data);
2744}
2745
2746void *
2747conversation_get_proto_data(const conversation_t *conv, const int proto)
2748{
2749 if (conv == NULL((void*)0)) {
2750 REPORT_DISSECTOR_BUG("%s: Can't get proto from a NULL conversation.", proto_get_protocol_name(proto))proto_report_dissector_bug("%s: Can't get proto from a NULL conversation."
, proto_get_protocol_name(proto))
;
2751 }
2752 /* No tree created yet */
2753 if (conv->data_list == NULL((void*)0)) {
2754 return NULL((void*)0);
2755 }
2756
2757 return wmem_tree_lookup32(conv->data_list, proto);
2758}
2759
2760void
2761conversation_delete_proto_data(conversation_t *conv, const int proto)
2762{
2763 if (conv == NULL((void*)0)) {
2764 REPORT_DISSECTOR_BUG("%s: Can't delete a NULL conversation.", proto_get_protocol_name(proto))proto_report_dissector_bug("%s: Can't delete a NULL conversation."
, proto_get_protocol_name(proto))
;
2765 }
2766 if (conv->data_list != NULL((void*)0))
2767 wmem_tree_remove32(conv->data_list, proto);
2768}
2769
2770void
2771conversation_set_dissector_from_frame_number(conversation_t *conversation,
2772 const uint32_t starting_frame_num, const dissector_handle_t handle)
2773{
2774 if (!conversation->dissector_tree) {
2775 conversation->dissector_tree = wmem_tree_new(wmem_file_scope());
2776 }
2777 wmem_tree_insert32(conversation->dissector_tree, starting_frame_num, (void *)handle);
2778}
2779
2780void
2781conversation_set_dissector(conversation_t *conversation, const dissector_handle_t handle)
2782{
2783 conversation_set_dissector_from_frame_number(conversation, 0, handle);
2784}
2785
2786dissector_handle_t
2787conversation_get_dissector(conversation_t *conversation, const uint32_t frame_num)
2788{
2789 if (!conversation->dissector_tree) {
2790 return NULL((void*)0);
2791 }
2792 return (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, frame_num);
2793}
2794
2795static bool_Bool
2796try_conversation_call_dissector_helper(conversation_t *conversation, bool_Bool* dissector_success,
2797 tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
2798{
2799 if (!conversation->dissector_tree) {
2800 return false0;
2801 }
2802
2803 int ret;
2804 dissector_handle_t handle = (dissector_handle_t)wmem_tree_lookup32_le(
2805 conversation->dissector_tree, pinfo->num);
2806 if (handle == NULL((void*)0)) {
2807 return false0;
2808 }
2809
2810 ret = call_dissector_only(handle, tvb, pinfo, tree, data);
2811
2812 /* Let the caller decide what to do with success or rejection */
2813 (*dissector_success) = (ret != 0);
2814
2815 return true1;
2816}
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 */
2828bool_Bool
2829try_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{
2833 conversation_t *conversation;
2834 bool_Bool dissector_success;
2835
2836 /*
2837 * Verify that the correct options are used, if any.
2838 */
2839 DISSECTOR_ASSERT_HINT((options == 0) || (options & NO_MASK_B), "Use NO_ADDR_B and/or NO_PORT_B as option")((void) (((options == 0) || (options & 0xFFFF0000)) ? (void
)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\" (%s)"
, "epan/conversation.c", 2839, "(options == 0) || (options & 0xFFFF0000)"
, "Use NO_ADDR_B and/or NO_PORT_B as option"))))
;
2840
2841 /* Try each mode based on option flags */
2842 conversation = find_conversation(pinfo->num, addr_a, addr_b, ctype, port_a, port_b, 0);
2843 if (conversation != NULL((void*)0)) {
2844 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
2845 return dissector_success;
2846 }
2847
2848 if (options & NO_ADDR_B0x00010000) {
2849 conversation = find_conversation(pinfo->num, addr_a, addr_b, ctype, port_a, port_b, NO_ADDR_B0x00010000);
2850 if (conversation != NULL((void*)0)) {
2851 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
2852 return dissector_success;
2853 }
2854 }
2855
2856 if (options & NO_PORT_B0x00020000) {
2857 conversation = find_conversation(pinfo->num, addr_a, addr_b, ctype, port_a, port_b, NO_PORT_B0x00020000);
2858 if (conversation != NULL((void*)0)) {
2859 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
2860 return dissector_success;
2861 }
2862 }
2863
2864 if (options & (NO_ADDR_B0x00010000|NO_PORT_B0x00020000)) {
2865 conversation = find_conversation(pinfo->num, addr_a, addr_b, ctype, port_a, port_b, NO_ADDR_B0x00010000|NO_PORT_B0x00020000);
2866 if (conversation != NULL((void*)0)) {
2867 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
2868 return dissector_success;
2869 }
2870 }
2871
2872 return false0;
2873}
2874
2875/*
2876 * Similar to try_conversation_dissector() with the particularity of calling
2877 * find_conversation_strat() in place of find_conversation() everywhere.
2878 */
2879bool_Bool
2880try_conversation_dissector_strat(packet_info *pinfo, const conversation_type ctype,
2881 tvbuff_t *tvb, proto_tree *tree, void* data, const unsigned options)
2882{
2883 conversation_t *conversation;
2884 bool_Bool dissector_success;
2885
2886 /*
2887 * Verify that the correct options are used, if any.
2888 */
2889 DISSECTOR_ASSERT_HINT((options == 0) || (options & NO_MASK_B), "Use NO_ADDR_B and/or NO_PORT_B as option")((void) (((options == 0) || (options & 0xFFFF0000)) ? (void
)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\" (%s)"
, "epan/conversation.c", 2889, "(options == 0) || (options & 0xFFFF0000)"
, "Use NO_ADDR_B and/or NO_PORT_B as option"))))
;
2890
2891 /* Try each mode based on option flags */
2892 conversation = find_conversation_strat(pinfo, ctype, 0, false0);
2893 if (conversation != NULL((void*)0)) {
2894 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
2895 return dissector_success;
2896 }
2897
2898 if (options & NO_ADDR_B0x00010000) {
2899 conversation = find_conversation_strat(pinfo, ctype, NO_ADDR_B0x00010000, false0);
2900 if (conversation != NULL((void*)0)) {
2901 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
2902 return dissector_success;
2903 }
2904 }
2905
2906 if (options & NO_PORT_B0x00020000) {
2907 conversation = find_conversation_strat(pinfo, ctype, NO_PORT_B0x00020000, false0);
2908 if (conversation != NULL((void*)0)) {
2909 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data)) {
2910 return dissector_success;
2911 }
2912 }
2913
2914 }
2915
2916 if (options & (NO_ADDR_B0x00010000|NO_PORT_B0x00020000)) {
2917 conversation = find_conversation_strat(pinfo, ctype, NO_ADDR_B0x00010000|NO_PORT_B0x00020000, false0);
2918 if (conversation != NULL((void*)0)) {
2919 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data)) {
2920 return dissector_success;
2921 }
2922 }
2923 }
2924
2925 return false0;
2926}
2927
2928bool_Bool
2929try_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{
2932 conversation_t *conversation;
2933
2934 conversation = find_conversation_by_id(pinfo->num, ctype, id);
2935
2936 if (conversation != NULL((void*)0)) {
2937 if (!conversation->dissector_tree) {
2938 return false0;
2939 }
2940
2941 int ret;
2942 dissector_handle_t handle = (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, pinfo->num);
2943
2944 if (handle == NULL((void*)0)) {
2945 return false0;
2946 }
2947
2948 ret = call_dissector_only(handle, tvb, pinfo, tree, data);
2949 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 return false0;
2955 }
2956 return true1;
2957 }
2958 return false0;
2959}
2960
2961/* Identifies a conversation ("classic" or deinterlaced) */
2962conversation_t *
2963find_conversation_strat(const packet_info *pinfo, const conversation_type ctype, const unsigned options, const bool_Bool direction)
2964{
2965 conversation_t *conv=NULL((void*)0);
2966 /* deinterlacing is only supported for the Ethernet wtap for now */
2967 if( (pinfo->pseudo_header != NULL((void*)0))
2968 && (pinfo->rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_ETHERNET1)
2969 && (prefs.conversation_deinterlacing_key>0)) {
2970 conversation_t *underlying_conv = find_conversation_deinterlacer_pinfo(pinfo);
2971 if(underlying_conv) {
2972 if(direction) { // reverse flow (dst to src)
2973 conv = find_conversation_deinterlaced(pinfo->num, &pinfo->dst, &pinfo->src, ctype, pinfo->destport, pinfo->srcport, underlying_conv->conv_index, options);
2974 }
2975 else {
2976 conv = find_conversation_deinterlaced(pinfo->num, &pinfo->src, &pinfo->dst, ctype, pinfo->srcport, pinfo->destport, underlying_conv->conv_index, options);
2977 }
2978 }
2979 }
2980 else {
2981 if(direction) { // reverse flow (dst to src)
2982 conv = find_conversation(pinfo->num, &pinfo->dst, &pinfo->src, ctype, pinfo->destport, pinfo->srcport, options);
2983 }
2984 else { // default (src to dst)
2985 conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, ctype, pinfo->srcport, pinfo->destport, options);
2986 }
2987 }
2988 return conv;
2989}
2990
2991/* Identifies a conversation ("classic" or deinterlaced) */
2992conversation_t *
2993find_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{
2996 conversation_t *conv=NULL((void*)0);
2997 /* deinterlacing is only supported for the Ethernet wtap for now */
2998 if( (pinfo->pseudo_header != NULL((void*)0))
2999 && (pinfo->rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_ETHERNET1)
3000 && (prefs.conversation_deinterlacing_key>0)) {
3001 conversation_t *underlying_conv = find_conversation_deinterlacer_pinfo(pinfo);
3002 if(underlying_conv) {
3003 conv = find_conversation_deinterlaced(frame_num, addr_a, addr_b, ctype, port_a, port_b, underlying_conv->conv_index, options);
3004 }
3005 }
3006 else {
3007 conv = find_conversation(frame_num, addr_a, addr_b, ctype, port_a, port_b, options);
3008 }
3009 return conv;
3010}
3011
3012/** A helper function that calls find_conversation() using data from pinfo
3013 * The frame number and addresses are taken from pinfo.
3014 */
3015conversation_t *
3016find_conversation_pinfo(const packet_info *pinfo, const unsigned options)
3017{
3018 conversation_t *conv = NULL((void*)0);
3019
3020 DINSTR(char *src_str = address_to_str(NULL, &pinfo->src))(void)0;
3021 DINSTR(char *dst_str = address_to_str(NULL, &pinfo->dst))(void)0;
3022 DPRINT(("called for frame #%u: %s:%d -> %s:%d (ptype=%d)",(void)0
3023 pinfo->num, src_str, pinfo->srcport,(void)0
3024 dst_str, pinfo->destport, pinfo->ptype))(void)0;
3025 DINDENT()(void)0;
3026 DINSTR(wmem_free(NULL, src_str))(void)0;
3027 DINSTR(wmem_free(NULL, dst_str))(void)0;
3028
3029 /* Have we seen this conversation before? */
3030 if (pinfo->use_conv_addr_port_endpoints) {
3031 DISSECTOR_ASSERT(pinfo->conv_addr_port_endpoints)((void) ((pinfo->conv_addr_port_endpoints) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/conversation.c", 3031
, "pinfo->conv_addr_port_endpoints"))))
;
3032 if ((conv = find_conversation(pinfo->num, &pinfo->conv_addr_port_endpoints->addr1, &pinfo->conv_addr_port_endpoints->addr2,
3033 pinfo->conv_addr_port_endpoints->ctype, pinfo->conv_addr_port_endpoints->port1,
3034 pinfo->conv_addr_port_endpoints->port2, 0)) != NULL((void*)0)) {
3035 DPRINT(("found previous conversation for frame #%u (last_frame=%d)",(void)0
3036 pinfo->num, conv->last_frame))(void)0;
3037 if (pinfo->num > conv->last_frame) {
3038 conv->last_frame = pinfo->num;
3039 }
3040 }
3041 } else if (pinfo->conv_elements) {
3042 if ((conv = find_conversation_full(pinfo->num, pinfo->conv_elements)) != NULL((void*)0)) {
3043 DPRINT(("found previous conversation elements for frame #%u (last_frame=%d)",(void)0
3044 pinfo->num, conv->last_frame))(void)0;
3045 if (pinfo->num > conv->last_frame) {
3046 conv->last_frame = pinfo->num;
3047 }
3048 }
3049 } else {
3050 if ((conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
3051 conversation_pt_to_conversation_type(pinfo->ptype), pinfo->srcport,
3052 pinfo->destport, options)) != NULL((void*)0)) {
3053 DPRINT(("found previous conversation for frame #%u (last_frame=%d)",(void)0
3054 pinfo->num, conv->last_frame))(void)0;
3055 if (pinfo->num > conv->last_frame) {
3056 conv->last_frame = pinfo->num;
3057 }
3058 }
3059 }
3060
3061 DENDENT()(void)0;
3062
3063 return conv;
3064}
3065
3066conversation_t *
3067find_conversation_pinfo_deinterlaced(const packet_info *pinfo, const uint32_t anchor, const unsigned options)
3068{
3069 conversation_t *conv = NULL((void*)0);
3070
3071 DINSTR(char *src_str = address_to_str(NULL, &pinfo->src))(void)0;
3072 DINSTR(char *dst_str = address_to_str(NULL, &pinfo->dst))(void)0;
3073 DPRINT(("called for frame #%u: %s:%d -> %s:%d (ptype=%d)",(void)0
3074 pinfo->num, src_str, pinfo->srcport,(void)0
3075 dst_str, pinfo->destport, pinfo->ptype))(void)0;
3076 DINDENT()(void)0;
3077 DINSTR(wmem_free(NULL, src_str))(void)0;
3078 DINSTR(wmem_free(NULL, dst_str))(void)0;
3079
3080 /* Have we seen this conversation before? */
3081 if (pinfo->use_conv_addr_port_endpoints) {
3082 // XXX - not implemented yet. Necessary ?
3083 } else if (pinfo->conv_elements) {
3084 // XXX - not implemented yet. Necessary ?
3085 } else {
3086 if ((conv = find_conversation_deinterlaced(pinfo->num, &pinfo->src, &pinfo->dst,
3087 conversation_pt_to_conversation_type(pinfo->ptype), pinfo->srcport,
3088 pinfo->destport, anchor, options)) != NULL((void*)0)) {
3089 DPRINT(("found previous conversation for frame #%u (last_frame=%d)",(void)0
3090 pinfo->num, conv->last_frame))(void)0;
3091 if (pinfo->num > conv->last_frame) {
3092 conv->last_frame = pinfo->num;
3093 }
3094 }
3095 }
3096
3097 DENDENT()(void)0;
3098
3099 return conv;
3100}
3101
3102conversation_t *
3103find_conversation_pinfo_strat(const packet_info *pinfo, const unsigned options)
3104{
3105 conversation_t *conv=NULL((void*)0);
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 if( (pinfo->pseudo_header != NULL((void*)0))
3110 && (pinfo->rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_ETHERNET1)
3111 && (prefs.conversation_deinterlacing_key>0)) {
3112
3113 conversation_t *underlying_conv = find_conversation_deinterlacer_pinfo(pinfo);
3114
3115 if(underlying_conv) {
3116 conv = find_conversation_pinfo_deinterlaced(pinfo, underlying_conv->conv_index, options);
3117 }
3118 }
3119 else {
3120 conv = find_conversation_pinfo(pinfo, options);
3121 }
3122
3123 return conv;
3124}
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 */
3130conversation_t *
3131find_conversation_pinfo_ro(const packet_info *pinfo, const unsigned options)
3132{
3133 conversation_t *conv = NULL((void*)0);
3134
3135 DINSTR(char *src_str = address_to_str(NULL, &pinfo->src))(void)0;
3136 DINSTR(char *dst_str = address_to_str(NULL, &pinfo->dst))(void)0;
3137 DPRINT(("called for frame #%u: %s:%d -> %s:%d (ptype=%d)",(void)0
3138 pinfo->num, src_str, pinfo->srcport,(void)0
3139 dst_str, pinfo->destport, pinfo->ptype))(void)0;
3140 DINDENT()(void)0;
3141 DINSTR(wmem_free(NULL, src_str))(void)0;
3142 DINSTR(wmem_free(NULL, dst_str))(void)0;
3143
3144 /* Have we seen this conversation before? */
3145 if (pinfo->use_conv_addr_port_endpoints) {
3146 DISSECTOR_ASSERT(pinfo->conv_addr_port_endpoints)((void) ((pinfo->conv_addr_port_endpoints) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/conversation.c", 3146
, "pinfo->conv_addr_port_endpoints"))))
;
3147 if ((conv = find_conversation(pinfo->num, &pinfo->conv_addr_port_endpoints->addr1, &pinfo->conv_addr_port_endpoints->addr2,
3148 pinfo->conv_addr_port_endpoints->ctype, pinfo->conv_addr_port_endpoints->port1,
3149 pinfo->conv_addr_port_endpoints->port2, 0)) != NULL((void*)0)) {
3150 DPRINT(("found previous conversation for frame #%u (last_frame=%d)",(void)0
3151 pinfo->num, conv->last_frame))(void)0;
3152 }
3153 } else if (pinfo->conv_elements) {
3154 if ((conv = find_conversation_full(pinfo->num, pinfo->conv_elements)) != NULL((void*)0)) {
3155 DPRINT(("found previous conversation elements for frame #%u (last_frame=%d)",(void)0
3156 pinfo->num, conv->last_frame))(void)0;
3157 }
3158 } else if ((conv = find_conversation_strat(pinfo, conversation_pt_to_conversation_type(pinfo->ptype), options, false0)) != NULL((void*)0)) {
3159 DPRINT(("found previous conversation for frame #%u (last_frame=%d)",(void)0
3160 pinfo->num, conv->last_frame))(void)0;
3161 }
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 else if( (pinfo->track_ctype>0) ) {
3168
3169 /* reference id */
3170 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 wmem_list_t *err_pkts_keys = wmem_map_get_keys(NULL((void*)0), conversation_hashtable_err_pkts);
3176 for (wmem_list_frame_t *cur_frame = wmem_list_head(err_pkts_keys ); cur_frame; cur_frame = wmem_list_frame_next(cur_frame)) {
3177 conversation_element_t *cet = (conversation_element_t *)wmem_list_frame_data(cur_frame);
3178 if(cet) {
3179 if( (cet[2].conversation_type_val == pinfo->track_ctype) && (cet[0].uint_val == pinfo->stream_id) ) {
3180 conv_index = cet[1].uint_val;
3181 break;
3182 }
3183 }
3184 }
3185 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 if(conv_index>0) {
3194 conversation_t *tsconv = NULL((void*)0);
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 if( (pinfo->pseudo_header != NULL((void*)0))
3201 && (pinfo->rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_ETHERNET1)
3202 && (prefs.conversation_deinterlacing_key>0)) {
3203 tsconv = wmem_map_find(conversation_hashtable_exact_addr_port_anc, find_conversation_by_index, GUINT_TO_POINTER(conv_index)((gpointer) (gulong) (conv_index)));
3204 }
3205 else {
3206 tsconv = wmem_map_find(conversation_hashtable_exact_addr_port, find_conversation_by_index, GUINT_TO_POINTER(conv_index)((gpointer) (gulong) (conv_index)));
3207 }
3208 if(tsconv) {
3209 conv = tsconv;
3210 }
3211 }
3212 }
3213 /* else: something is either not implemented or not handled */
3214
3215 DENDENT()(void)0;
3216
3217 return conv;
3218}
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 */
3226conversation_t *
3227find_or_create_conversation(const packet_info *pinfo)
3228{
3229 conversation_t *conv=NULL((void*)0);
3230
3231 /* Have we seen this conversation before? */
3232 if ((conv = find_conversation_pinfo(pinfo, 0)) == NULL((void*)0)) {
3233 /* No, this is a new conversation. */
3234 DPRINT(("did not find previous conversation for frame #%u",(void)0
3235 pinfo->num))(void)0;
3236 DINDENT()(void)0;
3237 if (pinfo->use_conv_addr_port_endpoints) {
3238 conv = conversation_new(pinfo->num, &pinfo->conv_addr_port_endpoints->addr1, &pinfo->conv_addr_port_endpoints->addr2,
3239 pinfo->conv_addr_port_endpoints->ctype, pinfo->conv_addr_port_endpoints->port1,
3240 pinfo->conv_addr_port_endpoints->port2, 0);
3241 } else if (pinfo->conv_elements) {
3242 conv = conversation_new_full(pinfo->num, pinfo->conv_elements);
3243 } else {
3244 conv = conversation_new(pinfo->num, &pinfo->src,
3245 &pinfo->dst, conversation_pt_to_conversation_type(pinfo->ptype),
3246 pinfo->srcport, pinfo->destport, 0);
3247 }
3248 DENDENT()(void)0;
3249 }
3250
3251 return conv;
3252}
3253
3254conversation_t *
3255find_or_create_conversation_deinterlaced(const packet_info *pinfo, const uint32_t conv_index)
3256{
3257 conversation_t *conv=NULL((void*)0);
3258
3259 /* Have we seen this conversation before? */
3260 if ((conv = find_conversation_pinfo_deinterlaced(pinfo, conv_index, 0)) == NULL((void*)0)) {
3261 /* No, this is a new conversation. */
3262 DPRINT(("did not find previous conversation for frame #%u",(void)0
3263 pinfo->num))(void)0;
3264 DINDENT()(void)0;
3265 if (pinfo->use_conv_addr_port_endpoints) {
3266 conv = conversation_new_strat(pinfo, pinfo->conv_addr_port_endpoints->ctype, 0);
3267 } else if (pinfo->conv_elements) {
3268 conv = conversation_new_full(pinfo->num, pinfo->conv_elements);
3269 } else {
3270 conv = conversation_new_deinterlaced(pinfo->num, &pinfo->src, &pinfo->dst,
3271 conversation_pt_to_conversation_type(pinfo->ptype),
3272 pinfo->srcport, pinfo->destport, conv_index, 0);
3273 }
3274 DENDENT()(void)0;
3275 }
3276
3277 return conv;
3278}
3279
3280conversation_t *
3281find_or_create_conversation_strat(const packet_info *pinfo)
3282{
3283 conversation_t *conv=NULL((void*)0);
1
'conv' initialized to a null pointer value
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 if( (pinfo->pseudo_header != NULL((void*)0))
2
Assuming field 'pseudo_header' is not equal to NULL
5
Taking true branch
3288 && (pinfo->rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_ETHERNET1)
3
Assuming field 'pkt_encap' is equal to WTAP_ENCAP_ETHERNET
3289 && (prefs.conversation_deinterlacing_key>0)) {
4
Assuming field 'conversation_deinterlacing_key' is > 0
3290
3291 conversation_t *underlying_conv = find_conversation_deinterlacer_pinfo(pinfo);
3292 if(underlying_conv) {
6
Assuming 'underlying_conv' is null
7
Taking false branch
3293 conv = find_or_create_conversation_deinterlaced(pinfo, underlying_conv->conv_index);
3294 }
3295 }
3296 else {
3297 conv = find_or_create_conversation(pinfo);
3298 }
3299
3300 return conv;
8
Null returned from a function that is expected to return a non-null value
3301}
3302
3303conversation_t *
3304find_or_create_conversation_by_id(packet_info *pinfo, const conversation_type ctype, const uint32_t id)
3305{
3306 conversation_t *conv=NULL((void*)0);
3307
3308 /* Have we seen this conversation before? */
3309 if ((conv = find_conversation_by_id(pinfo->num, ctype, id)) == NULL((void*)0)) {
3310 /* No, this is a new conversation. */
3311 DPRINT(("did not find previous conversation for frame #%u",(void)0
3312 pinfo->num))(void)0;
3313 DINDENT()(void)0;
3314 conv = conversation_new_by_id(pinfo->num, ctype, id);
3315 DENDENT()(void)0;
3316 }
3317
3318 return conv;
3319}
3320
3321void
3322conversation_set_conv_addr_port_endpoints(struct _packet_info *pinfo, address* addr1, address* addr2,
3323 conversation_type ctype, uint32_t port1, uint32_t port2)
3324{
3325 pinfo->conv_addr_port_endpoints = wmem_new0(pinfo->pool, struct conversation_addr_port_endpoints)((struct conversation_addr_port_endpoints*)wmem_alloc0((pinfo
->pool), sizeof(struct conversation_addr_port_endpoints)))
;
3326
3327 if (addr1 != NULL((void*)0)) {
3328 copy_address_wmem(pinfo->pool, &pinfo->conv_addr_port_endpoints->addr1, addr1);
3329 }
3330 if (addr2 != NULL((void*)0)) {
3331 copy_address_wmem(pinfo->pool, &pinfo->conv_addr_port_endpoints->addr2, addr2);
3332 }
3333
3334 pinfo->conv_addr_port_endpoints->ctype = ctype;
3335 pinfo->conv_addr_port_endpoints->port1 = port1;
3336 pinfo->conv_addr_port_endpoints->port2 = port2;
3337
3338 pinfo->use_conv_addr_port_endpoints = true1;
3339}
3340
3341void
3342conversation_set_elements_by_id(struct _packet_info *pinfo, conversation_type ctype, uint32_t id)
3343{
3344 pinfo->conv_elements = wmem_alloc0(pinfo->pool, sizeof(conversation_element_t) * 2);
3345 pinfo->conv_elements[0].type = CE_UINT;
3346 pinfo->conv_elements[0].uint_val = id;
3347 pinfo->conv_elements[1].type = CE_CONVERSATION_TYPE;
3348 pinfo->conv_elements[1].conversation_type_val = ctype;
3349}
3350
3351uint32_t
3352conversation_get_id_from_elements(struct _packet_info *pinfo, conversation_type ctype, const unsigned options)
3353{
3354 if (pinfo->conv_elements == NULL((void*)0)) {
3355 return 0;
3356 }
3357
3358 if (pinfo->conv_elements[0].type != CE_UINT || pinfo->conv_elements[1].type != CE_CONVERSATION_TYPE) {
3359 return 0;
3360 }
3361
3362 if ((pinfo->conv_elements[1].conversation_type_val != ctype) && ((options & USE_LAST_ENDPOINT0x08) != USE_LAST_ENDPOINT0x08)) {
3363 return 0;
3364 }
3365
3366 return pinfo->conv_elements[0].uint_val;
3367}
3368
3369wmem_map_t *
3370get_conversation_hashtables(void)
3371{
3372 return conversation_hashtable_element_list;
3373}
3374
3375const address*
3376conversation_key_addr1(const conversation_element_t *key)
3377{
3378 const address *addr = &null_address_;
3379 if (key[ADDR1_IDX].type == CE_ADDRESS) {
3380 addr = &key[ADDR1_IDX].addr_val;
3381 }
3382 return addr;
3383}
3384
3385uint32_t
3386conversation_key_port1(const conversation_element_t * key)
3387{
3388 uint32_t port = 0;
3389 if (key[ADDR1_IDX].type == CE_ADDRESS && key[PORT1_IDX].type == CE_PORT) {
3390 port = key[PORT1_IDX].port_val;
3391 }
3392 return port;
3393}
3394
3395const address*
3396conversation_key_addr2(const conversation_element_t * key)
3397{
3398 const address *addr = &null_address_;
3399 if (key[ADDR1_IDX].type == CE_ADDRESS && key[PORT1_IDX].type == CE_PORT && key[ADDR2_IDX].type == CE_ADDRESS) {
3400 addr = &key[ADDR2_IDX].addr_val;
3401 }
3402 return addr;
3403}
3404
3405uint32_t
3406conversation_key_port2(const conversation_element_t * key)
3407{
3408 uint32_t port = 0;
3409 if (key[ADDR1_IDX].type == CE_ADDRESS && key[PORT1_IDX].type == CE_PORT) {
3410 if (key[ADDR2_IDX].type == CE_ADDRESS && key[PORT2_IDX].type == CE_PORT) {
3411 // Exact
3412 port = key[PORT2_IDX].port_val;
3413 } else if (key[PORT2_NO_ADDR2_IDX].type == CE_PORT) {
3414 // No addr 2
3415 port = key[PORT2_NO_ADDR2_IDX].port_val;
3416 }
3417 }
3418 return port;
3419}
3420
3421WS_DLL_PUBLIC__attribute__ ((visibility ("default"))) extern
3422conversation_type conversation_pt_to_conversation_type(port_type pt)
3423{
3424 switch (pt)
3425 {
3426 case PT_NONE:
3427 return CONVERSATION_NONE;
3428 case PT_SCTP:
3429 return CONVERSATION_SCTP;
3430 case PT_TCP:
3431 return CONVERSATION_TCP;
3432 case PT_UDP:
3433 return CONVERSATION_UDP;
3434 case PT_DCCP:
3435 return CONVERSATION_DCCP;
3436 case PT_IPX:
3437 return CONVERSATION_IPX;
3438 case PT_DDP:
3439 return CONVERSATION_DDP;
3440 case PT_IDP:
3441 return CONVERSATION_IDP;
3442 case PT_USB:
3443 return CONVERSATION_USB;
3444 case PT_I2C:
3445 /* XXX - this doesn't currently have conversations */
3446 return CONVERSATION_I2C;
3447 case PT_IBQP:
3448 return CONVERSATION_IBQP;
3449 case PT_BLUETOOTH:
3450 return CONVERSATION_BLUETOOTH;
3451 case PT_IWARP_MPA:
3452 return CONVERSATION_IWARP_MPA;
3453 case PT_MCTP:
3454 return CONVERSATION_MCTP;
3455 }
3456
3457 DISSECTOR_ASSERT(false)((void) ((0) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/conversation.c", 3457, "0"))))
;
3458 return CONVERSATION_NONE;
3459}
3460
3461WS_DLL_PUBLIC__attribute__ ((visibility ("default"))) extern
3462endpoint_type conversation_pt_to_endpoint_type(port_type pt)
3463{
3464 switch (pt)
3465 {
3466 case PT_NONE:
3467 return ENDPOINT_NONECONVERSATION_NONE;
3468 case PT_SCTP:
3469 return ENDPOINT_SCTPCONVERSATION_SCTP;
3470 case PT_TCP:
3471 return ENDPOINT_TCPCONVERSATION_TCP;
3472 case PT_UDP:
3473 return ENDPOINT_UDPCONVERSATION_UDP;
3474 case PT_DCCP:
3475 return ENDPOINT_DCCPCONVERSATION_DCCP;
3476 case PT_IPX:
3477 return ENDPOINT_IPXCONVERSATION_IPX;
3478 case PT_DDP:
3479 return ENDPOINT_DDPCONVERSATION_DDP;
3480 case PT_IDP:
3481 return ENDPOINT_IDPCONVERSATION_IDP;
3482 case PT_USB:
3483 return ENDPOINT_USBCONVERSATION_USB;
3484 case PT_I2C:
3485 /* XXX - this doesn't have ports */
3486 return ENDPOINT_I2CCONVERSATION_I2C;
3487 case PT_IBQP:
3488 return ENDPOINT_IBQPCONVERSATION_IBQP;
3489 case PT_BLUETOOTH:
3490 return ENDPOINT_BLUETOOTHCONVERSATION_BLUETOOTH;
3491 case PT_IWARP_MPA:
3492 return ENDPOINT_IWARP_MPACONVERSATION_IWARP_MPA;
3493 case PT_MCTP:
3494 return ENDPOINT_MCTPCONVERSATION_MCTP;
3495 }
3496
3497 DISSECTOR_ASSERT(false)((void) ((0) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/conversation.c", 3497, "0"))))
;
3498 return ENDPOINT_NONECONVERSATION_NONE;
3499}
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 */