Bug Summary

File:epan/conversation.c
Warning:line 3292, 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-21/lib/clang/21 -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-21/lib/clang/21/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-10-27-100323-3623-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 <epan/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-connection 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 if(is_deinterlacing_supported(pinfo)) {
1151 conversation_t *underlying_conv = find_conversation_deinterlacer_pinfo(pinfo);
1152 if(underlying_conv) {
1153 is_ordinary_conv = false0;
1154 conversation = conversation_new_deinterlaced(pinfo->num, &pinfo->src, &pinfo->dst, ctype,
1155 pinfo->srcport, pinfo->destport, underlying_conv->conv_index, options);
1156 }
1157 }
1158
1159 if(is_ordinary_conv) {
1160 conversation = conversation_new(pinfo->num, &pinfo->src, &pinfo->dst, ctype, pinfo->srcport, pinfo->destport, options);
1161 }
1162
1163 return conversation;
1164}
1165
1166conversation_t *
1167conversation_new_strat_xtd(const packet_info *pinfo, const uint32_t setup_frame, const address *addr1, const address *addr2,
1168 const conversation_type ctype, const uint32_t port1, const uint32_t port2, const unsigned options)
1169{
1170 conversation_t *conversation = NULL((void*)0);
1171 bool_Bool is_ordinary_conv = true1;
1172
1173 if(is_deinterlacing_supported(pinfo)) {
1174 conversation_t *underlying_conv = find_conversation_deinterlacer_pinfo(pinfo);
1175 if(underlying_conv) {
1176 is_ordinary_conv = false0;
1177 conversation = conversation_new_deinterlaced(setup_frame, addr1, addr2, ctype,
1178 port1, port2, underlying_conv->conv_index, options);
1179 }
1180 }
1181
1182 if(is_ordinary_conv) {
1183 conversation = conversation_new(setup_frame, addr1, addr2, ctype, port1, port2, options);
1184 }
1185
1186 return conversation;
1187}
1188
1189conversation_t *
1190conversation_new_by_id(const uint32_t setup_frame, const conversation_type ctype, const uint32_t id)
1191{
1192 conversation_t *conversation = wmem_new0(wmem_file_scope(), conversation_t)((conversation_t*)wmem_alloc0((wmem_file_scope()), sizeof(conversation_t
)))
;
1193 conversation->conv_index = new_index;
1194 conversation->setup_frame = conversation->last_frame = setup_frame;
1195
1196 new_index++;
1197
1198 conversation_element_t *elements = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * 2);
1199 elements[0].type = CE_UINT;
1200 elements[0].uint_val = id;
1201 elements[1].type = CE_CONVERSATION_TYPE;
1202 elements[1].conversation_type_val = ctype;
1203 conversation->key_ptr = elements;
1204 conversation_insert_into_hashtable(conversation_hashtable_id, conversation);
1205
1206 return conversation;
1207}
1208
1209conversation_t *
1210conversation_new_err_pkts(const uint32_t setup_frame, const conversation_type ctype, const uint32_t id, const uint32_t rid)
1211{
1212 conversation_t *conversation = wmem_new0(wmem_file_scope(), conversation_t)((conversation_t*)wmem_alloc0((wmem_file_scope()), sizeof(conversation_t
)))
;
1213 conversation->conv_index = new_index;
1214 conversation->setup_frame = conversation->last_frame = setup_frame;
1215
1216 new_index++;
1217
1218 conversation_element_t *elements = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * 3);
1219 elements[0].type = CE_UINT;
1220 elements[0].uint_val = id;
1221 elements[1].type = CE_UINT;
1222 elements[1].uint_val = rid;
1223 elements[2].type = CE_CONVERSATION_TYPE;
1224 elements[2].conversation_type_val = ctype;
1225 conversation->key_ptr = elements;
1226 conversation_insert_into_hashtable(conversation_hashtable_err_pkts, conversation);
1227
1228 return conversation;
1229}
1230
1231conversation_t *
1232conversation_new_deinterlacer(const uint32_t setup_frame, const address *addr1, const address *addr2,
1233 const conversation_type ctype, const uint32_t key1, const uint32_t key2, const uint32_t key3)
1234{
1235
1236 conversation_t *conversation = wmem_new0(wmem_file_scope(), conversation_t)((conversation_t*)wmem_alloc0((wmem_file_scope()), sizeof(conversation_t
)))
;
1237 conversation->conv_index = new_index;
1238 conversation->setup_frame = conversation->last_frame = setup_frame;
1239
1240 conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * (DEINTR_ENDP_IDX+1));
1241
1242 new_key[DEINTR_ADDR1_IDX].type = CE_ADDRESS;
1243 if (addr1 != NULL((void*)0)) {
1244 copy_address_wmem(wmem_file_scope(), &new_key[DEINTR_ADDR1_IDX].addr_val, addr1);
1245 }
1246 else {
1247 clear_address(&new_key[DEINTR_ADDR1_IDX].addr_val);
1248 }
1249
1250 new_key[DEINTR_ADDR2_IDX].type = CE_ADDRESS;
1251 if (addr2 != NULL((void*)0)) {
1252 copy_address_wmem(wmem_file_scope(), &new_key[DEINTR_ADDR2_IDX].addr_val, addr2);
1253 }
1254 else {
1255 clear_address(&new_key[DEINTR_ADDR2_IDX].addr_val);
1256 }
1257
1258 new_key[DEINTR_KEY1_IDX].type = CE_UINT;
1259 new_key[DEINTR_KEY1_IDX].uint_val = key1;
1260
1261 new_key[DEINTR_KEY2_IDX].type = CE_UINT;
1262 new_key[DEINTR_KEY2_IDX].uint_val = key2;
1263
1264 new_key[DEINTR_KEY3_IDX].type = CE_UINT;
1265 new_key[DEINTR_KEY3_IDX].uint_val = key3;
1266
1267 new_key[DEINTR_ENDP_IDX].type = CE_CONVERSATION_TYPE;
1268 new_key[DEINTR_ENDP_IDX].conversation_type_val = ctype;
1269
1270 conversation->key_ptr = new_key;
1271
1272 new_index++;
1273
1274 conversation_insert_into_hashtable(conversation_hashtable_deinterlacer, conversation);
1275
1276 return conversation;
1277}
1278
1279conversation_t *
1280conversation_new_deinterlaced(const uint32_t setup_frame, const address *addr1, const address *addr2,
1281 const conversation_type ctype, const uint32_t port1, const uint32_t port2, const uint32_t anchor, const unsigned options)
1282{
1283
1284 conversation_t *conversation = wmem_new0(wmem_file_scope(), conversation_t)((conversation_t*)wmem_alloc0((wmem_file_scope()), sizeof(conversation_t
)))
;
1285 conversation->conv_index = new_index;
1286 conversation->setup_frame = conversation->last_frame = setup_frame;
1287
1288 if (options & NO_PORTS0x010) {
1289 conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * (DEINTD_ENDP_NO_PORTS_IDX+2));
1290
1291 new_key[DEINTD_ADDR1_IDX].type = CE_ADDRESS;
1292 if (addr1 != NULL((void*)0)) {
1293 copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR1_IDX].addr_val, addr1);
1294 }
1295 else {
1296 clear_address(&new_key[DEINTD_ADDR1_IDX].addr_val);
1297 }
1298
1299 new_key[DEINTD_ADDR2_IDX].type = CE_ADDRESS;
1300 if (addr2 != NULL((void*)0)) {
1301 copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR2_IDX].addr_val, addr2);
1302 }
1303 else {
1304 clear_address(&new_key[DEINTD_ADDR2_IDX].addr_val);
1305 }
1306
1307 new_key[DEINTD_ENDP_NO_PORTS_IDX].type = CE_UINT;
1308 new_key[DEINTD_ENDP_NO_PORTS_IDX].uint_val = anchor;
1309
1310 new_key[DEINTD_ENDP_NO_PORTS_IDX+ 1].type = CE_CONVERSATION_TYPE;
1311 new_key[DEINTD_ENDP_NO_PORTS_IDX+ 1].conversation_type_val = ctype;
1312
1313 // set the options and key pointer
1314 conversation->options = options;
1315 conversation->key_ptr = new_key;
1316
1317 new_index++;
1318
1319 conversation_insert_into_hashtable(conversation_hashtable_exact_addr_anc, conversation);
1320
1321 return conversation;
1322 }
1323 else if (options & NO_ADDR20x01) {
1324 if (options & NO_PORT20x02) {
1325
1326 conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * (DEINTD_NO_ADDR2_PORT2_IDX_COUNT+1));
1327
1328 new_key[DEINTD_ADDR1_IDX].type = CE_ADDRESS;
1329 if (addr1 != NULL((void*)0)) {
1330 copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR1_IDX].addr_val, addr1);
1331 }
1332 else {
1333 clear_address(&new_key[DEINTD_ADDR1_IDX].addr_val);
1334 }
1335
1336 new_key[DEINTD_PORT1_IDX-1].type = CE_PORT;
1337 new_key[DEINTD_PORT1_IDX-1].port_val = port1;
1338
1339 new_key[DEINTD_NO_ADDR2_PORT2_IDX_COUNT-2].type = CE_UINT;
1340 new_key[DEINTD_NO_ADDR2_PORT2_IDX_COUNT-2].uint_val = anchor;
1341
1342 new_key[DEINTD_NO_ADDR2_PORT2_IDX_COUNT-1].type = CE_CONVERSATION_TYPE;
1343 new_key[DEINTD_NO_ADDR2_PORT2_IDX_COUNT-1].conversation_type_val = ctype;
1344
1345 // set the options and key pointer
1346 conversation->options = options;
1347 conversation->key_ptr = new_key;
1348
1349 new_index++;
1350
1351 conversation_insert_into_hashtable(conversation_hashtable_no_addr2_or_port2_anc, conversation);
1352
1353 return conversation;
1354 }
1355
1356 else {
1357 conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * (DEINTD_NO_ADDR2_IDX_COUNT+1));
1358
1359 new_key[DEINTD_ADDR1_IDX].type = CE_ADDRESS;
1360 if (addr1 != NULL((void*)0)) {
1361 copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR1_IDX].addr_val, addr1);
1362 }
1363 else {
1364 clear_address(&new_key[DEINTD_ADDR1_IDX].addr_val);
1365 }
1366
1367 new_key[DEINTD_PORT1_IDX-1].type = CE_PORT;
1368 new_key[DEINTD_PORT1_IDX-1].port_val = port1;
1369
1370 new_key[DEINTD_PORT2_IDX-1].type = CE_PORT;
1371 new_key[DEINTD_PORT2_IDX-1].port_val = port2;
1372
1373 new_key[DEINTD_NO_ADDR2_IDX_COUNT-2].type = CE_UINT;
1374 new_key[DEINTD_NO_ADDR2_IDX_COUNT-2].uint_val = anchor;
1375
1376 new_key[DEINTD_NO_ADDR2_IDX_COUNT-1].type = CE_CONVERSATION_TYPE;
1377 new_key[DEINTD_NO_ADDR2_IDX_COUNT-1].conversation_type_val = ctype;
1378
1379 // set the options and key pointer
1380 conversation->options = options;
1381 conversation->key_ptr = new_key;
1382
1383 new_index++;
1384
1385 conversation_insert_into_hashtable(conversation_hashtable_no_addr2_anc, conversation);
1386
1387 return conversation;
1388 }
1389 }
1390 else if (options & NO_PORT20x02) {
1391 conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * (DEINTD_EXACT_IDX_COUNT+1));
1392
1393 new_key[DEINTD_ADDR1_IDX].type = CE_ADDRESS;
1394 if (addr1 != NULL((void*)0)) {
1395 copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR1_IDX].addr_val, addr1);
1396 }
1397 else {
1398 clear_address(&new_key[DEINTD_ADDR1_IDX].addr_val);
1399 }
1400
1401 new_key[DEINTD_ADDR2_IDX].type = CE_ADDRESS;
1402 if (addr2 != NULL((void*)0)) {
1403 copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR2_IDX].addr_val, addr2);
1404 }
1405 else {
1406 clear_address(&new_key[DEINTD_ADDR2_IDX].addr_val);
1407 }
1408
1409 new_key[DEINTD_PORT1_IDX].type = CE_PORT;
1410 new_key[DEINTD_PORT1_IDX].port_val = port1;
1411
1412 new_key[DEINTD_PORT1_IDX + 1].type = CE_UINT;
1413 new_key[DEINTD_PORT1_IDX + 1].uint_val = anchor;
1414
1415 new_key[DEINTD_PORT1_IDX + 2].type = CE_CONVERSATION_TYPE;
1416 new_key[DEINTD_PORT1_IDX + 2].conversation_type_val = ctype;
1417
1418 // set the options and key pointer
1419 conversation->options = options;
1420 conversation->key_ptr = new_key;
1421
1422 new_index++;
1423
1424 conversation_insert_into_hashtable(conversation_hashtable_exact_addr_port_anc, conversation);
1425
1426 return conversation;
1427 }
1428 else {
1429 conversation_element_t *new_key = wmem_alloc(wmem_file_scope(), sizeof(conversation_element_t) * (DEINTD_EXACT_IDX_COUNT+2));
1430
1431 new_key[DEINTD_ADDR1_IDX].type = CE_ADDRESS;
1432 if (addr1 != NULL((void*)0)) {
1433 copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR1_IDX].addr_val, addr1);
1434 }
1435 else {
1436 clear_address(&new_key[DEINTD_ADDR1_IDX].addr_val);
1437 }
1438
1439 new_key[DEINTD_ADDR2_IDX].type = CE_ADDRESS;
1440 if (addr2 != NULL((void*)0)) {
1441 copy_address_wmem(wmem_file_scope(), &new_key[DEINTD_ADDR2_IDX].addr_val, addr2);
1442 }
1443 else {
1444 clear_address(&new_key[DEINTD_ADDR2_IDX].addr_val);
1445 }
1446
1447 new_key[DEINTD_PORT1_IDX].type = CE_PORT;
1448 new_key[DEINTD_PORT1_IDX].port_val = port1;
1449
1450 new_key[DEINTD_PORT2_IDX].type = CE_PORT;
1451 new_key[DEINTD_PORT2_IDX].port_val = port2;
1452
1453 new_key[DEINTD_ENDP_EXACT_IDX].type = CE_UINT;
1454 new_key[DEINTD_ENDP_EXACT_IDX].uint_val = anchor;
1455
1456 new_key[DEINTD_ENDP_EXACT_IDX + 1].type = CE_CONVERSATION_TYPE;
1457 new_key[DEINTD_ENDP_EXACT_IDX + 1].conversation_type_val = ctype;
1458
1459 // set the options and key pointer
1460 conversation->options = options;
1461 conversation->key_ptr = new_key;
1462
1463 new_index++;
1464
1465 conversation_insert_into_hashtable(conversation_hashtable_exact_addr_port_anc, conversation);
1466
1467 return conversation;
1468 }
1469}
1470
1471/*
1472 * Set the port 2 value in a key. Remove the original from table,
1473 * update the options and port values, insert the updated key.
1474 */
1475void
1476conversation_set_port2(conversation_t *conv, const uint32_t port)
1477{
1478 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"
, 1479, "!(conv->options & 0x08)", "Use the conversation_create_from_template function when the CONVERSATION_TEMPLATE bit is set in the options mask"
))))
1479 "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"
, 1479, "!(conv->options & 0x08)", "Use the conversation_create_from_template function when the CONVERSATION_TEMPLATE bit is set in the options mask"
))))
;
1480
1481 DPRINT(("called for port=%d", port))(void)0;
1482
1483 /*
1484 * If the port 2 value is not wildcarded, don't set it.
1485 */
1486 if ((!(conv->options & NO_PORT20x02)) || (conv->options & NO_PORT2_FORCE0x04))
1487 return;
1488
1489 DINDENT()(void)0;
1490 if (conv->options & NO_ADDR20x01) {
1491 conversation_remove_from_hashtable(conversation_hashtable_no_addr2_or_port2, conv);
1492 } else {
1493 conversation_remove_from_hashtable(conversation_hashtable_no_port2, conv);
1494 }
1495
1496 // Shift our endpoint element over and set our port. We assume that conv->key_ptr
1497 // was created with conversation_new and that we have enough element slots.
1498 conv->options &= ~NO_PORT20x02;
1499 if (conv->options & NO_ADDR20x01) {
1500 // addr1,port1,endp -> addr1,port1,port2,endp
1501 conv->key_ptr[ENDP_NO_ADDR2_IDX] = conv->key_ptr[ENDP_NO_ADDR2_PORT2_IDX];
1502 conv->key_ptr[PORT2_NO_ADDR2_IDX].type = CE_PORT;
1503 conv->key_ptr[PORT2_NO_ADDR2_IDX].port_val = port;
1504 conversation_insert_into_hashtable(conversation_hashtable_no_addr2, conv);
1505 } else {
1506 // addr1,port1,addr2,endp -> addr1,port1,addr2,port2,endp
1507 conv->key_ptr[ENDP_EXACT_IDX] = conv->key_ptr[ENDP_NO_PORT2_IDX];
1508 conv->key_ptr[PORT2_IDX].type = CE_PORT;
1509 conv->key_ptr[PORT2_IDX].port_val = port;
1510 conversation_insert_into_hashtable(conversation_hashtable_exact_addr_port, conv);
1511 }
1512 DENDENT()(void)0;
1513}
1514
1515/*
1516 * Set the address 2 value in a key. Remove the original from
1517 * table, update the options and port values, insert the updated key.
1518 */
1519void
1520conversation_set_addr2(conversation_t *conv, const address *addr)
1521{
1522 char* addr_str;
1523 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"
, 1524, "!(conv->options & 0x08)", "Use the conversation_create_from_template function when the CONVERSATION_TEMPLATE bit is set in the options mask"
))))
1524 "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"
, 1524, "!(conv->options & 0x08)", "Use the conversation_create_from_template function when the CONVERSATION_TEMPLATE bit is set in the options mask"
))))
;
1525
1526 addr_str = address_to_str(NULL((void*)0), addr);
1527 DPRINT(("called for addr=%s", addr_str))(void)0;
1528 wmem_free(NULL((void*)0), addr_str);
1529
1530 /*
1531 * If the address 2 value is not wildcarded, don't set it.
1532 */
1533 if (!(conv->options & NO_ADDR20x01))
1534 return;
1535
1536 DINDENT()(void)0;
1537 if (conv->options & NO_PORT20x02) {
1538 conversation_remove_from_hashtable(conversation_hashtable_no_addr2_or_port2, conv);
1539 } else {
1540 conversation_remove_from_hashtable(conversation_hashtable_no_addr2, conv);
1541 }
1542
1543 // Shift our endpoint and, if needed, our port element over and set our address.
1544 // We assume that conv->key_ptr was created with conversation_new and that we have
1545 // enough element slots.
1546 conv->options &= ~NO_ADDR20x01;
1547 wmem_map_t *hashtable;
1548 if (conv->options & NO_PORT20x02) {
1549 // addr1,port1,endp -> addr1,port1,addr2,endp
1550 conv->key_ptr[ENDP_NO_PORT2_IDX] = conv->key_ptr[ENDP_NO_ADDR2_PORT2_IDX];
1551 hashtable = conversation_hashtable_no_port2;
1552 } else {
1553 // addr1,port1,port2,endp -> addr1,port1,addr2,port2,endp
1554 conv->key_ptr[ENDP_EXACT_IDX] = conv->key_ptr[ENDP_NO_ADDR2_IDX];
1555 conv->key_ptr[PORT2_IDX] = conv->key_ptr[PORT2_NO_ADDR2_IDX];
1556 hashtable = conversation_hashtable_exact_addr_port;
1557 }
1558 conv->key_ptr[ADDR2_IDX].type = CE_ADDRESS;
1559 copy_address_wmem(wmem_file_scope(), &conv->key_ptr[ADDR2_IDX].addr_val, addr);
1560 conversation_insert_into_hashtable(hashtable, conv);
1561 DENDENT()(void)0;
1562}
1563
1564static conversation_t *conversation_lookup_hashtable(wmem_map_t *conversation_hashtable, const uint32_t frame_num, conversation_element_t *conv_key)
1565{
1566 conversation_t* convo = NULL((void*)0);
1567 conversation_t* match = NULL((void*)0);
1568 conversation_t* chain_head = NULL((void*)0);
1569 chain_head = (conversation_t *)wmem_map_lookup(conversation_hashtable, conv_key);
1570
1571 if (chain_head && (chain_head->setup_frame <= frame_num)) {
1572 match = chain_head;
1573
1574 if (chain_head->last && (chain_head->last->setup_frame <= frame_num))
1575 return chain_head->last;
1576
1577 if (chain_head->latest_found && (chain_head->latest_found->setup_frame <= frame_num))
1578 match = chain_head->latest_found;
1579
1580 for (convo = match; convo && convo->setup_frame <= frame_num; convo = convo->next) {
1581 if (convo->setup_frame > match->setup_frame) {
1582 match = convo;
1583 }
1584 }
1585 }
1586
1587 if (match) {
1588 chain_head->latest_found = match;
1589 }
1590
1591 return match;
1592}
1593
1594conversation_t *find_conversation_full(const uint32_t frame_num, conversation_element_t *elements)
1595{
1596 char *el_list_map_key = conversation_element_list_name(NULL((void*)0), elements);
1597 wmem_map_t *el_list_map = (wmem_map_t *) wmem_map_lookup(conversation_hashtable_element_list, el_list_map_key);
1598 g_free(el_list_map_key);
1599 if (!el_list_map) {
1600 return NULL((void*)0);
1601 }
1602
1603 return conversation_lookup_hashtable(el_list_map, frame_num, elements);
1604}
1605
1606/*
1607 * Search a particular hash table for a conversation with the specified
1608 * {addr1, port1, addr2, port2} and set up before frame_num.
1609 */
1610static conversation_t *
1611conversation_lookup_exact(const uint32_t frame_num, const address *addr1, const uint32_t port1,
1612 const address *addr2, const uint32_t port2, const conversation_type ctype)
1613{
1614 conversation_element_t key[EXACT_IDX_COUNT] = {
1615 { CE_ADDRESS, .addr_val = *addr1 },
1616 { CE_PORT, .port_val = port1 },
1617 { CE_ADDRESS, .addr_val = *addr2 },
1618 { CE_PORT, .port_val = port2 },
1619 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1620 };
1621 return conversation_lookup_hashtable(conversation_hashtable_exact_addr_port, frame_num, key);
1622}
1623
1624/*
1625 * Search a particular hash table for a conversation with the specified
1626 * {addr1, port1, port2} and set up before frame_num.
1627 */
1628static conversation_t *
1629conversation_lookup_no_addr2(const uint32_t frame_num, const address *addr1, const uint32_t port1,
1630 const uint32_t port2, const conversation_type ctype)
1631{
1632 conversation_element_t key[NO_ADDR2_IDX_COUNT] = {
1633 { CE_ADDRESS, .addr_val = *addr1 },
1634 { CE_PORT, .port_val = port1 },
1635 { CE_PORT, .port_val = port2 },
1636 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1637 };
1638 return conversation_lookup_hashtable(conversation_hashtable_no_addr2, frame_num, key);
1639}
1640
1641/*
1642 * Search a particular hash table for a conversation with the specified
1643 * {addr1, port1, addr2} and set up before frame_num.
1644 */
1645static conversation_t *
1646conversation_lookup_no_port2(const uint32_t frame_num, const address *addr1, const uint32_t port1,
1647 const address *addr2, const conversation_type ctype)
1648{
1649 conversation_element_t key[NO_PORT2_IDX_COUNT] = {
1650 { CE_ADDRESS, .addr_val = *addr1 },
1651 { CE_PORT, .port_val = port1 },
1652 { CE_ADDRESS, .addr_val = *addr2 },
1653 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1654 };
1655 return conversation_lookup_hashtable(conversation_hashtable_no_port2, frame_num, key);
1656}
1657
1658/*
1659 * Search a particular hash table for a conversation with the specified
1660 * {addr1, port1, addr2} and set up before frame_num.
1661 */
1662static conversation_t *
1663conversation_lookup_no_addr2_or_port2(const uint32_t frame_num, const address *addr1, const uint32_t port1,
1664 const conversation_type ctype)
1665{
1666 conversation_element_t key[NO_ADDR2_PORT2_IDX_COUNT] = {
1667 { CE_ADDRESS, .addr_val = *addr1 },
1668 { CE_PORT, .port_val = port1 },
1669 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1670 };
1671 return conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2, frame_num, key);
1672}
1673
1674/*
1675 * Search a particular hash table for a conversation with the specified
1676 * {addr1, addr2} and set up before frame_num.
1677 */
1678static conversation_t *
1679conversation_lookup_no_ports(const uint32_t frame_num, const address *addr1,
1680 const address *addr2, const conversation_type ctype)
1681{
1682 conversation_element_t key[ADDRS_IDX_COUNT] = {
1683 { CE_ADDRESS, .addr_val = *addr1 },
1684 { CE_ADDRESS, .addr_val = *addr2 },
1685 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1686 };
1687 return conversation_lookup_hashtable(conversation_hashtable_exact_addr, frame_num, key);
1688}
1689
1690/*
1691 * Search a particular hash table for a conversation with the specified
1692 * {addr1, port1, addr2, port2, anchor} and set up before frame_num.
1693 */
1694static conversation_t *
1695conversation_lookup_exact_anc(const uint32_t frame_num, const address *addr1, const uint32_t port1,
1696 const address *addr2, const uint32_t port2, const conversation_type ctype,
1697 const uint32_t anchor)
1698{
1699 conversation_element_t key[DEINTD_EXACT_IDX_COUNT+1] = {
1700 { CE_ADDRESS, .addr_val = *addr1 },
1701 { CE_ADDRESS, .addr_val = *addr2 },
1702 { CE_PORT, .port_val = port1 },
1703 { CE_PORT, .port_val = port2 },
1704 { CE_UINT, .uint_val = anchor },
1705 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1706 };
1707 return conversation_lookup_hashtable(conversation_hashtable_exact_addr_port_anc, frame_num, key);
1708}
1709
1710/*
1711 * Search a particular hash table for a conversation with the specified
1712 * {addr1, addr2, anchor} and set up before frame_num.
1713 */
1714static conversation_t *
1715conversation_lookup_no_ports_anc(const uint32_t frame_num, const address *addr1,
1716 const address *addr2, const conversation_type ctype, const uint32_t anchor)
1717{
1718 conversation_element_t key[DEINTD_ADDRS_IDX_COUNT+1] = {
1719 { CE_ADDRESS, .addr_val = *addr1 },
1720 { CE_ADDRESS, .addr_val = *addr2 },
1721 { CE_UINT, .uint_val = anchor },
1722 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1723 };
1724 return conversation_lookup_hashtable(conversation_hashtable_exact_addr_anc, frame_num, key);
1725}
1726
1727/*
1728 * Search a particular hash table for a conversation with the specified
1729 * {addr1, port1, port2, anchor} and set up before frame_num.
1730 */
1731static conversation_t *
1732conversation_lookup_no_addr2_anc(const uint32_t frame_num, const address *addr1, const uint32_t port1,
1733 const uint32_t port2, const conversation_type ctype,
1734 const uint32_t anchor)
1735{
1736 conversation_element_t key[DEINTD_NO_ADDR2_IDX_COUNT] = {
1737 { CE_ADDRESS, .addr_val = *addr1 },
1738 { CE_PORT, .port_val = port1 },
1739 { CE_PORT, .port_val = port2 },
1740 { CE_UINT, .uint_val = anchor },
1741 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1742 };
1743 return conversation_lookup_hashtable(conversation_hashtable_no_addr2_anc , frame_num, key);
1744}
1745
1746/*
1747 * Search a particular hash table for a conversation with the specified
1748 * {addr1, port1, addr2, anchor} and set up before frame_num.
1749 */
1750static conversation_t *
1751conversation_lookup_no_port2_anc(const uint32_t frame_num, const address *addr1, const uint32_t port1,
1752 const address *addr2, const conversation_type ctype,
1753 const uint32_t anchor)
1754{
1755 conversation_element_t key[DEINTD_NO_PORT2_IDX_COUNT] = {
1756 { CE_ADDRESS, .addr_val = *addr1 },
1757 { CE_ADDRESS, .addr_val = *addr2 },
1758 { CE_PORT, .port_val = port1 },
1759 { CE_UINT, .uint_val = anchor },
1760 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1761 };
1762 return conversation_lookup_hashtable(conversation_hashtable_exact_addr_port_anc, frame_num, key);
1763}
1764
1765/*
1766 * Search a particular hash table for a conversation with the specified
1767 * {addr1, port1, addr2} and set up before frame_num.
1768 */
1769static conversation_t *
1770conversation_lookup_no_addr2_or_port2_anc(const uint32_t frame_num, const address *addr1, const uint32_t port1,
1771 const conversation_type ctype, const uint32_t anchor)
1772{
1773 conversation_element_t key[DEINTD_NO_ADDR2_PORT2_IDX_COUNT] = {
1774 { CE_ADDRESS, .addr_val = *addr1 },
1775 { CE_PORT, .port_val = port1 },
1776 { CE_UINT, .uint_val = anchor },
1777 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1778 };
1779 return conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2_anc, frame_num, key);
1780}
1781
1782/*
1783 * Search a particular hash table for a conversation with the specified
1784 * {addr1, addr2, key1, key2, key3} and set up before frame_num.
1785 * At this moment only the deinterlace table is likely to be called.
1786 */
1787static conversation_t *
1788conversation_lookup_deinterlacer(const uint32_t frame_num, const address *addr1,
1789 const address *addr2, const conversation_type ctype,
1790 const uint32_t key1, const uint32_t key2, const uint32_t key3)
1791{
1792 conversation_element_t key[DEINTR_ENDP_IDX+1] = {
1793 { CE_ADDRESS, .addr_val = *addr1 },
1794 { CE_ADDRESS, .addr_val = *addr2 },
1795 { CE_UINT, .uint_val = key1 },
1796 { CE_UINT, .uint_val = key2 },
1797 { CE_UINT, .uint_val = key3 },
1798 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype },
1799 };
1800 return conversation_lookup_hashtable(conversation_hashtable_deinterlacer, frame_num, key);
1801}
1802
1803/*
1804 * Given two address/port pairs for a packet, search for a conversation
1805 * containing packets between those address/port pairs. Returns NULL if
1806 * not found.
1807 *
1808 * We try to find the most exact match that we can, and then proceed to
1809 * try wildcard matches on the "addr_b" and/or "port_b" argument if a more
1810 * exact match failed.
1811 *
1812 * Either or both of the "addr_b" and "port_b" arguments may be specified as
1813 * a wildcard by setting the NO_ADDR_B or NO_PORT_B flags in the "options"
1814 * argument. We do only wildcard matches on addresses and ports specified
1815 * as wildcards.
1816 *
1817 * I.e.:
1818 *
1819 * if neither "addr_b" nor "port_b" were specified as wildcards, we
1820 * do an exact match (addr_a/port_a and addr_b/port_b) and, if that
1821 * succeeds, we return a pointer to the matched conversation;
1822 *
1823 * otherwise, if "port_b" wasn't specified as a wildcard, we try to
1824 * match any address 2 with the specified port 2 (addr_a/port_a and
1825 * {any}/port_b) and, if that succeeds, we return a pointer to the
1826 * matched conversation;
1827 *
1828 * otherwise, if "addr_b" wasn't specified as a wildcard, we try to
1829 * match any port 2 with the specified address 2 (addr_a/port_a and
1830 * addr_b/{any}) and, if that succeeds, we return a pointer to the
1831 * matched conversation;
1832 *
1833 * otherwise, we try to match any address 2 and any port 2
1834 * (addr_a/port_a and {any}/{any}) and, if that succeeds, we return
1835 * a pointer to the matched conversation;
1836 *
1837 * otherwise, we found no matching conversation, and return NULL.
1838 */
1839conversation_t *
1840find_conversation(const uint32_t frame_num, const address *addr_a, const address *addr_b, const conversation_type ctype,
1841 const uint32_t port_a, const uint32_t port_b, const unsigned options)
1842{
1843 conversation_t *conversation, *other_conv;
1844
1845 if (!addr_a) {
1846 addr_a = &null_address_;
1847 }
1848
1849 if (!addr_b) {
1850 addr_b = &null_address_;
1851 }
1852
1853 DINSTR(char *addr_a_str = address_to_str(NULL, addr_a))(void)0;
1854 DINSTR(char *addr_b_str = address_to_str(NULL, addr_b))(void)0;
1855 /*
1856 * Verify that the correct options are used, if any.
1857 */
1858 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", 1858, "(options == 0) || (options & 0xFFFF0000)"
, "Use NO_ADDR_B and/or NO_PORT_B as option"))))
;
1859 /*
1860 * First try an exact match, if we have two addresses and ports.
1861 */
1862 if (!(options & (NO_ADDR_B0x00010000|NO_PORT_B0x00020000|NO_PORT_X0x00040000|EXACT_EXCLUDED0x00200000))) {
1863 /*
1864 * Neither search address B nor search port B are wildcarded,
1865 * start out with an exact match.
1866 */
1867 DPRINT(("trying exact match: %s:%d -> %s:%d",(void)0
1868 addr_a_str, port_a, addr_b_str, port_b))(void)0;
1869 conversation = conversation_lookup_exact(frame_num, addr_a, port_a, addr_b, port_b, ctype);
1870 /*
1871 * Look for an alternate conversation in the opposite direction, which
1872 * might fit better. Note that using the helper functions such as
1873 * find_conversation_pinfo and find_or_create_conversation will finally
1874 * call this function and look for an orientation-agnostic conversation.
1875 * If oriented conversations had to be implemented, amend this code or
1876 * create new functions.
1877 */
1878
1879 DPRINT(("trying exact match: %s:%d -> %s:%d",(void)0
1880 addr_b_str, port_b, addr_a_str, port_a))(void)0;
1881 other_conv = conversation_lookup_exact(frame_num, addr_b, port_b, addr_a, port_a, ctype);
1882 if (other_conv != NULL((void*)0)) {
1883 if (conversation != NULL((void*)0)) {
1884 if(other_conv->conv_index > conversation->conv_index) {
1885 conversation = other_conv;
1886 }
1887 }
1888 else {
1889 conversation = other_conv;
1890 }
1891 }
1892 if ((conversation == NULL((void*)0)) && (addr_a->type == AT_FC)) {
1893 /* In Fibre channel, OXID & RXID are never swapped as
1894 * TCP/UDP ports are in TCP/IP.
1895 */
1896 DPRINT(("trying exact match: %s:%d -> %s:%d",(void)0
1897 addr_b_str, port_a, addr_a_str, port_b))(void)0;
1898 conversation = conversation_lookup_exact(frame_num, addr_b, port_a, addr_a, port_b, ctype);
1899 }
1900 DPRINT(("exact match %sfound",conversation?"":"not "))(void)0;
1901 if (conversation != NULL((void*)0))
1902 goto end;
1903 else if(options & NO_GREEDY0x00100000)
1904 goto end;
1905 }
1906
1907 /*
1908 * Well, that didn't find anything. Try matches that wildcard
1909 * one of the addresses, if we have two ports.
1910 */
1911 if (!(options & (NO_PORT_B0x00020000|NO_PORT_X0x00040000))) {
1912 /*
1913 * Search port B isn't wildcarded.
1914 *
1915 * First try looking for a conversation with the specified
1916 * address A and port A as the first address and port, and
1917 * with any address and the specified port B as the second
1918 * address and port.
1919 * ("addr_b" doesn't take part in this lookup.)
1920 */
1921 DPRINT(("trying wildcarded match: %s:%d -> *:%d",(void)0
1922 addr_a_str, port_a, port_b))(void)0;
1923 conversation = conversation_lookup_no_addr2(frame_num, addr_a, port_a, port_b, ctype);
1924 if ((conversation == NULL((void*)0)) && (addr_a->type == AT_FC)) {
1925 /* In Fibre channel, OXID & RXID are never swapped as
1926 * TCP/UDP ports are in TCP/IP.
1927 */
1928 DPRINT(("trying wildcarded match: %s:%d -> *:%d",(void)0
1929 addr_b_str, port_a, port_b))(void)0;
1930 conversation = conversation_lookup_no_addr2(frame_num, addr_b, port_a, port_b, ctype);
1931 }
1932 if (conversation != NULL((void*)0)) {
1933 /*
1934 * If search address B isn't wildcarded, and this is for a
1935 * connection-oriented protocol, set the second address for this
1936 * conversation to address B, as that's the address that matched the
1937 * wildcarded second address for this conversation.
1938 *
1939 * (This assumes that, for all connection oriented protocols, the
1940 * endpoints of a connection have only one address each, i.e. you
1941 * don't get packets in a given direction coming from more than one
1942 * address, unless the CONVERSATION_TEMPLATE option is set.)
1943 */
1944 DPRINT(("wildcarded dest address match found"))(void)0;
1945 if (!(conversation->options & NO_ADDR20x01) && ctype != CONVERSATION_UDP)
1946 {
1947 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
1948 {
1949 conversation_set_addr2(conversation, addr_b);
1950 }
1951 else
1952 {
1953 conversation =
1954 conversation_create_from_template(conversation, addr_b, 0);
1955 }
1956 }
1957 goto end;
1958 }
1959
1960 /*
1961 * Well, that didn't find anything.
1962 * If search address B was specified, try looking for a
1963 * conversation with the specified address B and port B as
1964 * the first address and port, and with any address and the
1965 * specified port A as the second address and port (this
1966 * packet may be going in the opposite direction from the
1967 * first packet in the conversation).
1968 * ("addr_a" doesn't take part in this lookup.)
1969 */
1970 if (!(options & NO_ADDR_B0x00010000)) {
1971 DPRINT(("trying wildcarded match: %s:%d -> *:%d",(void)0
1972 addr_b_str, port_b, port_a))(void)0;
1973 conversation = conversation_lookup_no_addr2(frame_num, addr_b, port_b, port_a, ctype);
1974 if (conversation != NULL((void*)0)) {
1975 /*
1976 * If this is for a connection-oriented
1977 * protocol, set the second address for
1978 * this conversation to address A, as
1979 * that's the address that matched the
1980 * wildcarded second address for this
1981 * conversation.
1982 */
1983 DPRINT(("match found"))(void)0;
1984 if (ctype != CONVERSATION_UDP) {
1985 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
1986 {
1987 conversation_set_addr2(conversation, addr_a);
1988 }
1989 else
1990 {
1991 conversation =
1992 conversation_create_from_template(conversation, addr_a, 0);
1993 }
1994 }
1995 goto end;
1996 }
1997 }
1998 }
1999
2000 /*
2001 * Well, that didn't find anything. Try matches that wildcard
2002 * one of the ports, if we have two addresses.
2003 */
2004 if (!(options & (NO_ADDR_B0x00010000|NO_PORT_X0x00040000))) {
2005 /*
2006 * Search address B isn't wildcarded.
2007 *
2008 * First try looking for a conversation with the specified
2009 * address A and port A as the first address and port, and
2010 * with the specified address B and any port as the second
2011 * address and port.
2012 * ("port_b" doesn't take part in this lookup.)
2013 */
2014 DPRINT(("trying wildcarded match: %s:%d -> %s:*",(void)0
2015 addr_a_str, port_a, addr_b_str))(void)0;
2016 conversation = conversation_lookup_no_port2(frame_num, addr_a, port_a, addr_b, ctype);
2017 if ((conversation == NULL((void*)0)) && (addr_a->type == AT_FC)) {
2018 /* In Fibre channel, OXID & RXID are never swapped as
2019 * TCP/UDP ports are in TCP/IP
2020 */
2021 DPRINT(("trying wildcarded match: %s:%d -> %s:*", addr_b_str, port_a, addr_a_str))(void)0;
2022 conversation = conversation_lookup_no_port2(frame_num, addr_b, port_a, addr_a, ctype);
2023 }
2024 if (conversation != NULL((void*)0)) {
2025 /*
2026 * If search port B isn't wildcarded, and this is for a connection-
2027 * oriented protocol, set the second port for this conversation to
2028 * port B, as that's the port that matched the wildcarded second port
2029 * for this conversation.
2030 *
2031 * (This assumes that, for all connection oriented protocols, the
2032 * endpoints of a connection have only one port each, i.e. you don't
2033 * get packets in a given direction coming from more than one port,
2034 * unless the CONVERSATION_TEMPLATE option is set.)
2035 */
2036 DPRINT(("match found"))(void)0;
2037 if (!(conversation->options & NO_PORT20x02) && ctype != CONVERSATION_UDP)
2038 {
2039 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2040 {
2041 conversation_set_port2(conversation, port_b);
2042 }
2043 else
2044 {
2045 conversation =
2046 conversation_create_from_template(conversation, 0, port_b);
2047 }
2048 }
2049 goto end;
2050 }
2051
2052 /*
2053 * Well, that didn't find anything.
2054 * If search port B was specified, try looking for a
2055 * conversation with the specified address B and port B
2056 * as the first address and port, and with the specified
2057 * address A and any port as the second address and port
2058 * (this packet may be going in the opposite direction
2059 * from the first packet in the conversation).
2060 * ("port_a" doesn't take part in this lookup.)
2061 */
2062 if (!(options & NO_PORT_B0x00020000)) {
2063 DPRINT(("trying wildcarded match: %s:%d -> %s:*",(void)0
2064 addr_b_str, port_b, addr_a_str))(void)0;
2065 conversation = conversation_lookup_no_port2(frame_num, addr_b, port_b, addr_a, ctype);
2066 if (conversation != NULL((void*)0)) {
2067 /*
2068 * If this is for a connection-oriented
2069 * protocol, set the second port for
2070 * this conversation to port A, as
2071 * that's the address that matched the
2072 * wildcarded second address for this
2073 * conversation.
2074 */
2075 DPRINT(("match found"))(void)0;
2076 if (ctype != CONVERSATION_UDP)
2077 {
2078 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2079 {
2080 conversation_set_port2(conversation, port_a);
2081 }
2082 else
2083 {
2084 conversation =
2085 conversation_create_from_template(conversation, 0, port_a);
2086 }
2087 }
2088 goto end;
2089 }
2090 }
2091 if(options & NO_GREEDY0x00100000) {
2092 goto end;
2093 }
2094 }
2095
2096 /*
2097 * Well, that didn't find anything. Try matches that wildcard
2098 * one address/port pair.
2099 *
2100 * First try looking for a conversation with the specified address A
2101 * and port A as the first address and port.
2102 * (Neither "addr_b" nor "port_b" take part in this lookup.)
2103 */
2104 if (!(options & NO_PORT_X0x00040000)) {
2105 DPRINT(("trying wildcarded match: %s:%d -> *:*", addr_a_str, port_a))(void)0;
2106 conversation = conversation_lookup_no_addr2_or_port2(frame_num, addr_a, port_a, ctype);
2107 if (conversation != NULL((void*)0)) {
2108 /*
2109 * If this is for a connection-oriented protocol:
2110 *
2111 * if search address B isn't wildcarded, set the
2112 * second address for this conversation to address
2113 * B, as that's the address that matched the
2114 * wildcarded second address for this conversation;
2115 *
2116 * if search port B isn't wildcarded, set the
2117 * second port for this conversation to port B,
2118 * as that's the port that matched the wildcarded
2119 * second port for this conversation.
2120 */
2121 DPRINT(("match found"))(void)0;
2122 if (ctype != CONVERSATION_UDP)
2123 {
2124 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2125 {
2126 if (!(conversation->options & NO_ADDR20x01))
2127 conversation_set_addr2(conversation, addr_b);
2128 if (!(conversation->options & NO_PORT20x02))
2129 conversation_set_port2(conversation, port_b);
2130 }
2131 else
2132 {
2133 conversation =
2134 conversation_create_from_template(conversation, addr_b, port_b);
2135 }
2136 }
2137 goto end;
2138 }
2139 /* for Infiniband, don't try to look in addresses of reverse
2140 * direction, because it could be another different
2141 * valid conversation than what is being searched using
2142 * addr_a, port_a.
2143 */
2144 if (ctype != CONVERSATION_IBQP)
2145 {
2146
2147 /*
2148 * Well, that didn't find anything.
2149 * If search address and port B were specified, try looking for a
2150 * conversation with the specified address B and port B as the
2151 * first address and port, and with any second address and port
2152 * (this packet may be going in the opposite direction from the
2153 * first packet in the conversation).
2154 * (Neither "addr_a" nor "port_a" take part in this lookup.)
2155 */
2156 if (addr_a->type == AT_FC) {
2157 DPRINT(("trying wildcarded match: %s:%d -> *:*",(void)0
2158 addr_b_str, port_a))(void)0;
2159 conversation = conversation_lookup_no_addr2_or_port2(frame_num, addr_b, port_a, ctype);
2160 } else {
2161 DPRINT(("trying wildcarded match: %s:%d -> *:*",(void)0
2162 addr_b_str, port_b))(void)0;
2163 conversation = conversation_lookup_no_addr2_or_port2(frame_num, addr_b, port_b, ctype);
2164 }
2165 if (conversation != NULL((void*)0)) {
2166 /*
2167 * If this is for a connection-oriented protocol, set the
2168 * second address for this conversation to address A, as
2169 * that's the address that matched the wildcarded second
2170 * address for this conversation, and set the second port
2171 * for this conversation to port A, as that's the port
2172 * that matched the wildcarded second port for this
2173 * conversation.
2174 */
2175 DPRINT(("match found"))(void)0;
2176 if (ctype != CONVERSATION_UDP)
2177 {
2178 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2179 {
2180 conversation_set_addr2(conversation, addr_a);
2181 conversation_set_port2(conversation, port_a);
2182 }
2183 else
2184 {
2185 conversation = conversation_create_from_template(conversation, addr_a, port_a);
2186 }
2187 }
2188 goto end;
2189 }
2190 }
2191 }
2192
2193 /*
2194 * Well, that didn't find anything. Try matches between two
2195 * addresses, but no ports. Typically ETH and IP protocols fall
2196 * into this category.
2197 *
2198 * First try looking for a conversation with the specified address A
2199 * and address B.
2200 * (Neither "port_a" nor "port_b" take part in this lookup.)
2201 */
2202 if (options & NO_PORT_X0x00040000) {
2203 /*
2204 * Search for conversations between two addresses, strictly
2205 */
2206 DPRINT(("trying exact match: %s -> %s",(void)0
2207 addr_a_str, addr_b_str))(void)0;
2208 conversation = conversation_lookup_no_ports(frame_num, addr_a, addr_b, ctype);
2209
2210 if (conversation != NULL((void*)0)) {
2211 DPRINT(("match found"))(void)0;
2212 goto end;
2213 }
2214 /*
2215 * Look for a conversation in the opposite direction.
2216 */
2217 else {
2218 DPRINT(("trying exact match: %s -> %s",(void)0
2219 addr_b_str, addr_a_str))(void)0;
2220 conversation = conversation_lookup_no_ports(frame_num, addr_b, addr_a, ctype);
2221 if (conversation != NULL((void*)0)) {
2222 DPRINT(("match found"))(void)0;
2223 goto end;
2224 }
2225 }
2226 }
2227
2228 DPRINT(("no matches found"))(void)0;
2229
2230 /*
2231 * We found no conversation.
2232 */
2233 conversation = NULL((void*)0);
2234
2235end:
2236 DINSTR(wmem_free(NULL, addr_a_str))(void)0;
2237 DINSTR(wmem_free(NULL, addr_b_str))(void)0;
2238 return conversation;
2239}
2240
2241conversation_t *
2242find_conversation_deinterlaced(const uint32_t frame_num, const address *addr_a, const address *addr_b, const conversation_type ctype,
2243 const uint32_t port_a, const uint32_t port_b, const uint32_t anchor, const unsigned options)
2244{
2245 conversation_t *conversation, *other_conv;
2246
2247 if (!addr_a) {
2248 addr_a = &null_address_;
2249 }
2250
2251 if (!addr_b) {
2252 addr_b = &null_address_;
2253 }
2254
2255 DINSTR(char *addr_a_str = address_to_str(NULL, addr_a))(void)0;
2256 DINSTR(char *addr_b_str = address_to_str(NULL, addr_b))(void)0;
2257
2258 /*
2259 * First try an exact match, if we have two addresses and ports.
2260 */
2261 if (!(options & (NO_ADDR_B0x00010000|NO_PORT_B0x00020000|NO_PORTS0x010|EXACT_EXCLUDED0x00200000) )) {
2262 /*
2263 * Neither search address B nor search port B are wildcarded,
2264 * start out with an exact match.
2265 */
2266 DPRINT(("trying exact match: %s:%d -> %s:%d",(void)0
2267 addr_a_str, port_a, addr_b_str, port_b))(void)0;
2268 conversation = conversation_lookup_exact_anc(frame_num, addr_a, port_a, addr_b, port_b, ctype, anchor);
2269 /*
2270 * Look for an alternate conversation in the opposite direction, which
2271 * might fit better. Note that using the helper functions such as
2272 * find_conversation_pinfo and find_or_create_conversation will finally
2273 * call this function and look for an orientation-agnostic conversation.
2274 * If oriented conversations had to be implemented, amend this code or
2275 * create new functions.
2276 */
2277
2278 DPRINT(("trying exact match: %s:%d -> %s:%d",(void)0
2279 addr_b_str, port_b, addr_a_str, port_a))(void)0;
2280 other_conv = conversation_lookup_exact_anc(frame_num, addr_b, port_b, addr_a, port_a, ctype, anchor);
2281 if (other_conv != NULL((void*)0)) {
2282 if (conversation != NULL((void*)0)) {
2283 if(other_conv->conv_index > conversation->conv_index) {
2284 conversation = other_conv;
2285 }
2286 }
2287 else {
2288 conversation = other_conv;
2289 }
2290 }
2291 if ((conversation == NULL((void*)0)) && (addr_a->type == AT_FC)) {
2292 /* In Fibre channel, OXID & RXID are never swapped as
2293 * TCP/UDP ports are in TCP/IP.
2294 */
2295 DPRINT(("trying exact match: %s:%d -> %s:%d",(void)0
2296 addr_b_str, port_a, addr_a_str, port_b))(void)0;
2297 conversation = conversation_lookup_exact_anc(frame_num, addr_b, port_a, addr_a, port_b, ctype, anchor);
2298 }
2299 DPRINT(("exact match %sfound",conversation?"":"not "))(void)0;
2300 if (conversation != NULL((void*)0)) {
2301 goto end;
2302 }
2303 else if(options & NO_GREEDY0x00100000) {
2304 goto end;
2305 }
2306 }
2307
2308 /*
2309 * Well, that didn't find anything. Try matches that wildcard
2310 * one of the addresses, if we have two ports.
2311 */
2312 if (!(options & (NO_PORT_B0x00020000|NO_PORTS0x010))) {
2313 /*
2314 * Search port B isn't wildcarded.
2315 *
2316 * First try looking for a conversation with the specified
2317 * address A and port A as the first address and port, and
2318 * with any address and the specified port B as the second
2319 * address and port.
2320 * ("addr_b" doesn't take part in this lookup.)
2321 */
2322 DPRINT(("trying wildcarded match: %s:%d -> *:%d",(void)0
2323 addr_a_str, port_a, port_b))(void)0;
2324 conversation = conversation_lookup_no_addr2_anc(frame_num, addr_a, port_a, port_b, ctype, anchor);
2325 if ((conversation == NULL((void*)0)) && (addr_a->type == AT_FC)) {
2326 /* In Fibre channel, OXID & RXID are never swapped as
2327 * TCP/UDP ports are in TCP/IP.
2328 */
2329 DPRINT(("trying wildcarded match: %s:%d -> *:%d",(void)0
2330 addr_b_str, port_a, port_b))(void)0;
2331 conversation = conversation_lookup_no_addr2_anc(frame_num, addr_b, port_a, port_b, ctype, anchor);
2332 }
2333 if (conversation != NULL((void*)0)) {
2334 /*
2335 * If search address B isn't wildcarded, and this is for a
2336 * connection-oriented protocol, set the second address for this
2337 * conversation to address B, as that's the address that matched the
2338 * wildcarded second address for this conversation.
2339 *
2340 * (This assumes that, for all connection oriented protocols, the
2341 * endpoints of a connection have only one address each, i.e. you
2342 * don't get packets in a given direction coming from more than one
2343 * address, unless the CONVERSATION_TEMPLATE option is set.)
2344 */
2345 DPRINT(("wildcarded dest address match found"))(void)0;
2346 if (!(conversation->options & NO_ADDR20x01) && ctype != CONVERSATION_UDP)
2347 {
2348 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2349 {
2350 conversation_set_addr2(conversation, addr_b);
2351 }
2352 else
2353 {
2354 conversation =
2355 conversation_create_from_template(conversation, addr_b, 0);
2356 }
2357 }
2358 goto end;
2359 }
2360
2361 /*
2362 * Well, that didn't find anything.
2363 * If search address B was specified, try looking for a
2364 * conversation with the specified address B and port B as
2365 * the first address and port, and with any address and the
2366 * specified port A as the second address and port (this
2367 * packet may be going in the opposite direction from the
2368 * first packet in the conversation).
2369 * ("addr_a" doesn't take part in this lookup.)
2370 */
2371 if (!(options & NO_ADDR_B0x00010000)) {
2372 DPRINT(("trying wildcarded match: %s:%d -> *:%d",(void)0
2373 addr_b_str, port_b, port_a))(void)0;
2374 conversation = conversation_lookup_no_addr2_anc(frame_num, addr_b, port_b, port_a, ctype, anchor);
2375 if (conversation != NULL((void*)0)) {
2376 /*
2377 * If this is for a connection-oriented
2378 * protocol, set the second address for
2379 * this conversation to address A, as
2380 * that's the address that matched the
2381 * wildcarded second address for this
2382 * conversation.
2383 */
2384 DPRINT(("match found"))(void)0;
2385 if (ctype != CONVERSATION_UDP) {
2386 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2387 {
2388 conversation_set_addr2(conversation, addr_a);
2389 }
2390 else
2391 {
2392 conversation =
2393 conversation_create_from_template(conversation, addr_a, 0);
2394 }
2395 }
2396 goto end;
2397 }
2398 }
2399 }
2400
2401 /*
2402 * Well, that didn't find anything. Try matches that wildcard
2403 * one of the ports, if we have two addresses.
2404 */
2405 if (!(options & (NO_ADDR_B0x00010000|NO_PORTS0x010))) {
2406 /*
2407 * Search address B isn't wildcarded.
2408 *
2409 * First try looking for a conversation with the specified
2410 * address A and port A as the first address and port, and
2411 * with the specified address B and any port as the second
2412 * address and port.
2413 * ("port_b" doesn't take part in this lookup.)
2414 */
2415 DPRINT(("trying wildcarded match: %s:%d -> %s:*",(void)0
2416 addr_a_str, port_a, addr_b_str))(void)0;
2417 conversation = conversation_lookup_no_port2_anc(frame_num, addr_a, port_a, addr_b, ctype, anchor);
2418 if ((conversation == NULL((void*)0)) && (addr_a->type == AT_FC)) {
2419 /* In Fibre channel, OXID & RXID are never swapped as
2420 * TCP/UDP ports are in TCP/IP
2421 */
2422 DPRINT(("trying wildcarded match: %s:%d -> %s:*", addr_b_str, port_a, addr_a_str))(void)0;
2423 conversation = conversation_lookup_no_port2_anc(frame_num, addr_b, port_a, addr_a, ctype, anchor);
2424 }
2425 if (conversation != NULL((void*)0)) {
2426 /*
2427 * If search port B isn't wildcarded, and this is for a connection-
2428 * oriented protocol, set the second port for this conversation to
2429 * port B, as that's the port that matched the wildcarded second port
2430 * for this conversation.
2431 *
2432 * (This assumes that, for all connection oriented protocols, the
2433 * endpoints of a connection have only one port each, i.e. you don't
2434 * get packets in a given direction coming from more than one port,
2435 * unless the CONVERSATION_TEMPLATE option is set.)
2436 */
2437 DPRINT(("match found"))(void)0;
2438 if (!(conversation->options & NO_PORT20x02) && ctype != CONVERSATION_UDP)
2439 {
2440 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2441 {
2442 conversation_set_port2(conversation, port_b);
2443 }
2444 else
2445 {
2446 conversation =
2447 conversation_create_from_template(conversation, 0, port_b);
2448 }
2449 }
2450 goto end;
2451 }
2452
2453 /*
2454 * Well, that didn't find anything.
2455 * If search port B was specified, try looking for a
2456 * conversation with the specified address B and port B
2457 * as the first address and port, and with the specified
2458 * address A and any port as the second address and port
2459 * (this packet may be going in the opposite direction
2460 * from the first packet in the conversation).
2461 * ("port_a" doesn't take part in this lookup.)
2462 */
2463 if (!(options & NO_PORT_B0x00020000)) {
2464 DPRINT(("trying wildcarded match: %s:%d -> %s:*",(void)0
2465 addr_b_str, port_b, addr_a_str))(void)0;
2466 conversation = conversation_lookup_no_port2_anc(frame_num, addr_b, port_b, addr_a, ctype, anchor);
2467 if (conversation != NULL((void*)0)) {
2468 /*
2469 * If this is for a connection-oriented
2470 * protocol, set the second port for
2471 * this conversation to port A, as
2472 * that's the address that matched the
2473 * wildcarded second address for this
2474 * conversation.
2475 */
2476 DPRINT(("match found"))(void)0;
2477 if (ctype != CONVERSATION_UDP)
2478 {
2479 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2480 {
2481 conversation_set_port2(conversation, port_a);
2482 }
2483 else
2484 {
2485 conversation =
2486 conversation_create_from_template(conversation, 0, port_a);
2487 }
2488 }
2489 goto end;
2490 }
2491 }
2492 if(options & NO_GREEDY0x00100000) {
2493 goto end;
2494 }
2495 }
2496
2497 /*
2498 * Well, that didn't find anything. Try matches that wildcard
2499 * one address/port pair.
2500 *
2501 * First try looking for a conversation with the specified address A
2502 * and port A as the first address and port.
2503 * (Neither "addr_b" nor "port_b" take part in this lookup.)
2504 */
2505 DPRINT(("trying wildcarded match: %s:%d -> *:*", addr_a_str, port_a))(void)0;
2506 conversation = conversation_lookup_no_addr2_or_port2_anc(frame_num, addr_a, port_a, ctype, anchor);
2507 if (conversation != NULL((void*)0)) {
2508 /*
2509 * If this is for a connection-oriented protocol:
2510 *
2511 * if search address B isn't wildcarded, set the
2512 * second address for this conversation to address
2513 * B, as that's the address that matched the
2514 * wildcarded second address for this conversation;
2515 *
2516 * if search port B isn't wildcarded, set the
2517 * second port for this conversation to port B,
2518 * as that's the port that matched the wildcarded
2519 * second port for this conversation.
2520 */
2521 DPRINT(("match found"))(void)0;
2522 if (ctype != CONVERSATION_UDP)
2523 {
2524 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2525 {
2526 if (!(conversation->options & NO_ADDR20x01))
2527 conversation_set_addr2(conversation, addr_b);
2528 if (!(conversation->options & NO_PORT20x02))
2529 conversation_set_port2(conversation, port_b);
2530 }
2531 else
2532 {
2533 conversation =
2534 conversation_create_from_template(conversation, addr_b, port_b);
2535 }
2536 }
2537 goto end;
2538 }
2539
2540 /* for Infiniband, don't try to look in addresses of reverse
2541 * direction, because it could be another different
2542 * valid conversation than what is being searched using
2543 * addr_a, port_a.
2544 */
2545 if (ctype != CONVERSATION_IBQP)
2546 {
2547
2548 /*
2549 * Well, that didn't find anything.
2550 * If search address and port B were specified, try looking for a
2551 * conversation with the specified address B and port B as the
2552 * first address and port, and with any second address and port
2553 * (this packet may be going in the opposite direction from the
2554 * first packet in the conversation).
2555 * (Neither "addr_a" nor "port_a" take part in this lookup.)
2556 */
2557 if (addr_a->type == AT_FC) {
2558 DPRINT(("trying wildcarded match: %s:%d -> *:*",(void)0
2559 addr_b_str, port_a))(void)0;
2560 conversation = conversation_lookup_no_addr2_or_port2_anc(frame_num, addr_b, port_a, ctype, anchor);
2561 } else {
2562 DPRINT(("trying wildcarded match: %s:%d -> *:*",(void)0
2563 addr_b_str, port_b))(void)0;
2564 conversation = conversation_lookup_no_addr2_or_port2_anc(frame_num, addr_b, port_b, ctype, anchor);
2565 }
2566 if (conversation != NULL((void*)0)) {
2567 /*
2568 * If this is for a connection-oriented protocol, set the
2569 * second address for this conversation to address A, as
2570 * that's the address that matched the wildcarded second
2571 * address for this conversation, and set the second port
2572 * for this conversation to port A, as that's the port
2573 * that matched the wildcarded second port for this
2574 * conversation.
2575 */
2576 DPRINT(("match found"))(void)0;
2577 if (ctype != CONVERSATION_UDP)
2578 {
2579 if (!(conversation->options & CONVERSATION_TEMPLATE0x08))
2580 {
2581 conversation_set_addr2(conversation, addr_a);
2582 conversation_set_port2(conversation, port_a);
2583 }
2584 else
2585 {
2586 conversation = conversation_create_from_template(conversation, addr_a, port_a);
2587 }
2588 }
2589 goto end;
2590 }
2591 }
2592
2593 if (options & NO_PORT_X0x00040000) {
2594 /*
2595 * Search for conversations between two addresses, strictly
2596 */
2597 DPRINT(("trying exact match: %s -> %s",(void)0
2598 addr_a_str, addr_b_str))(void)0;
2599 conversation = conversation_lookup_no_ports_anc(frame_num, addr_a, addr_b, ctype, anchor);
2600
2601 if (conversation != NULL((void*)0)) {
2602 DPRINT(("match found"))(void)0;
2603 goto end;
2604 }
2605 else {
2606 conversation = conversation_lookup_no_ports_anc(frame_num, addr_b, addr_a, ctype, anchor);
2607 if (conversation != NULL((void*)0)) {
2608 DPRINT(("match found"))(void)0;
2609 goto end;
2610 }
2611 }
2612 }
2613
2614 DPRINT(("no matches found"))(void)0;
2615
2616 /*
2617 * We found no conversation.
2618 */
2619 conversation = NULL((void*)0);
2620
2621end:
2622
2623 DINSTR(wmem_free(NULL, addr_a_str))(void)0;
2624 DINSTR(wmem_free(NULL, addr_b_str))(void)0;
2625 return conversation;
2626}
2627
2628conversation_t *
2629find_conversation_deinterlacer(const uint32_t frame_num, const address *addr_a, const address *addr_b,
2630 const conversation_type ctype, const uint32_t key_a, const uint32_t key_b, const uint32_t key_c)
2631{
2632 conversation_t *conversation, *other_conv;
2633
2634 conversation = conversation_lookup_deinterlacer(frame_num, addr_a, addr_b, ctype, key_a, key_b, key_c);
2635
2636 other_conv = conversation_lookup_deinterlacer(frame_num, addr_b, addr_a, ctype, key_a, key_b, key_c);
2637 if (other_conv != NULL((void*)0)) {
2638 if (conversation != NULL((void*)0)) {
2639 if(other_conv->conv_index > conversation->conv_index) {
2640 conversation = other_conv;
2641 }
2642 }
2643 else {
2644 conversation = other_conv;
2645 }
2646 }
2647
2648 return conversation;
2649}
2650
2651conversation_t *
2652find_conversation_deinterlacer_pinfo(const packet_info *pinfo)
2653{
2654 conversation_t *conv=NULL((void*)0);
2655 unsigned dr_conv_type; /* deinterlacer conv type */
2656 uint32_t dtlc_iface = 0;
2657 uint32_t dtlc_vlan = 0;
2658
2659 /* evaluate the execution context: user pref, interface, VLAN */
2660 if(prefs.conversation_deinterlacing_key>0) {
2661 if(prefs.conversation_deinterlacing_key&CONV_DEINT_KEY_INTERFACE0x02 &&
2662 pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID0x00000004) {
2663
2664 if(prefs.conversation_deinterlacing_key&CONV_DEINT_KEY_VLAN0x08 &&
2665 pinfo->vlan_id>0) {
2666
2667 dr_conv_type = CONVERSATION_ETH_IV;
2668 dtlc_vlan = pinfo->vlan_id;
2669 }
2670 else {
2671 dr_conv_type = CONVERSATION_ETH_IN;
2672 }
2673 dtlc_iface = pinfo->rec->rec_header.packet_header.interface_id;
2674 }
2675 else {
2676 if(prefs.conversation_deinterlacing_key&CONV_DEINT_KEY_VLAN0x08 &&
2677 pinfo->vlan_id>0) {
2678
2679 dr_conv_type = CONVERSATION_ETH_NV;
2680 dtlc_vlan = pinfo->vlan_id;
2681 }
2682 else {
2683 dr_conv_type = CONVERSATION_ETH_NN;
2684 }
2685 }
2686
2687 conv = find_conversation_deinterlacer(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, dr_conv_type, dtlc_iface, dtlc_vlan , 0);
2688 }
2689
2690 return conv;
2691}
2692
2693conversation_t *
2694find_conversation_by_id(const uint32_t frame, const conversation_type ctype, const uint32_t id)
2695{
2696 conversation_element_t elements[2] = {
2697 { CE_UINT, .uint_val = id },
2698 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype }
2699 };
2700
2701 return conversation_lookup_hashtable(conversation_hashtable_id, frame, elements);
2702}
2703
2704static gboolean
2705find_conversation_by_index(void *key _U___attribute__((unused)), void *value, void *user_data)
2706{
2707 uint32_t convid = GPOINTER_TO_UINT(user_data)((guint) (gulong) (user_data));
2708 conversation_t *conv = (conversation_t*)value;
2709 if (conv->conv_index == convid) {
2710 return true1;
2711 }
2712 return false0;
2713}
2714
2715conversation_t *
2716find_conversation_err_pkts(const uint32_t frame, const conversation_type ctype, const uint32_t id, const uint32_t rid)
2717{
2718 conversation_element_t elements[3] = {
2719 { CE_UINT, .uint_val = id },
2720 { CE_UINT, .uint_val = rid },
2721 { CE_CONVERSATION_TYPE, .conversation_type_val = ctype }
2722 };
2723
2724 return conversation_lookup_hashtable(conversation_hashtable_err_pkts, frame, elements);
2725}
2726
2727void
2728conversation_add_proto_data(conversation_t *conv, const int proto, void *proto_data)
2729{
2730 if (conv == NULL((void*)0)) {
2731 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))
;
2732 }
2733 /* Add it to the list of items for this conversation. */
2734 if (conv->data_list == NULL((void*)0))
2735 conv->data_list = wmem_tree_new(wmem_file_scope());
2736
2737 wmem_tree_insert32(conv->data_list, proto, proto_data);
2738}
2739
2740void *
2741conversation_get_proto_data(const conversation_t *conv, const int proto)
2742{
2743 if (conv == NULL((void*)0)) {
2744 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))
;
2745 }
2746 /* No tree created yet */
2747 if (conv->data_list == NULL((void*)0)) {
2748 return NULL((void*)0);
2749 }
2750
2751 return wmem_tree_lookup32(conv->data_list, proto);
2752}
2753
2754void
2755conversation_delete_proto_data(conversation_t *conv, const int proto)
2756{
2757 if (conv == NULL((void*)0)) {
2758 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))
;
2759 }
2760 if (conv->data_list != NULL((void*)0))
2761 wmem_tree_remove32(conv->data_list, proto);
2762}
2763
2764void
2765conversation_set_dissector_from_frame_number(conversation_t *conversation,
2766 const uint32_t starting_frame_num, const dissector_handle_t handle)
2767{
2768 if (!conversation->dissector_tree) {
2769 conversation->dissector_tree = wmem_tree_new(wmem_file_scope());
2770 }
2771 wmem_tree_insert32(conversation->dissector_tree, starting_frame_num, (void *)handle);
2772}
2773
2774void
2775conversation_set_dissector(conversation_t *conversation, const dissector_handle_t handle)
2776{
2777 conversation_set_dissector_from_frame_number(conversation, 0, handle);
2778}
2779
2780dissector_handle_t
2781conversation_get_dissector(conversation_t *conversation, const uint32_t frame_num)
2782{
2783 if (!conversation->dissector_tree) {
2784 return NULL((void*)0);
2785 }
2786 return (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, frame_num);
2787}
2788
2789static bool_Bool
2790try_conversation_call_dissector_helper(conversation_t *conversation, bool_Bool* dissector_success,
2791 tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
2792{
2793 if (!conversation->dissector_tree) {
2794 return false0;
2795 }
2796
2797 int ret;
2798 dissector_handle_t handle = (dissector_handle_t)wmem_tree_lookup32_le(
2799 conversation->dissector_tree, pinfo->num);
2800 if (handle == NULL((void*)0)) {
2801 return false0;
2802 }
2803
2804 ret = call_dissector_only(handle, tvb, pinfo, tree, data);
2805
2806 /* Let the caller decide what to do with success or rejection */
2807 (*dissector_success) = (ret != 0);
2808
2809 return true1;
2810}
2811
2812/*
2813 * Given two address/port pairs for a packet, search for a matching
2814 * conversation and, if found and it has a conversation dissector,
2815 * call that dissector and return true, otherwise return false.
2816 *
2817 * This helper uses call_dissector_only which will NOT call the default
2818 * "data" dissector if the packet was rejected.
2819 * Our caller is responsible to call the data dissector explicitly in case
2820 * this function returns false.
2821 */
2822bool_Bool
2823try_conversation_dissector(const address *addr_a, const address *addr_b, const conversation_type ctype,
2824 const uint32_t port_a, const uint32_t port_b, tvbuff_t *tvb, packet_info *pinfo,
2825 proto_tree *tree, void* data, const unsigned options)
2826{
2827 conversation_t *conversation;
2828 bool_Bool dissector_success;
2829
2830 /*
2831 * Verify that the correct options are used, if any.
2832 */
2833 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", 2833, "(options == 0) || (options & 0xFFFF0000)"
, "Use NO_ADDR_B and/or NO_PORT_B as option"))))
;
2834
2835 /* Try each mode based on option flags */
2836 conversation = find_conversation(pinfo->num, addr_a, addr_b, ctype, port_a, port_b, 0);
2837 if (conversation != NULL((void*)0)) {
2838 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
2839 return dissector_success;
2840 }
2841
2842 if (options & NO_ADDR_B0x00010000) {
2843 conversation = find_conversation(pinfo->num, addr_a, addr_b, ctype, port_a, port_b, NO_ADDR_B0x00010000);
2844 if (conversation != NULL((void*)0)) {
2845 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
2846 return dissector_success;
2847 }
2848 }
2849
2850 if (options & NO_PORT_B0x00020000) {
2851 conversation = find_conversation(pinfo->num, addr_a, addr_b, ctype, port_a, port_b, NO_PORT_B0x00020000);
2852 if (conversation != NULL((void*)0)) {
2853 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
2854 return dissector_success;
2855 }
2856 }
2857
2858 if (options & (NO_ADDR_B0x00010000|NO_PORT_B0x00020000)) {
2859 conversation = find_conversation(pinfo->num, addr_a, addr_b, ctype, port_a, port_b, NO_ADDR_B0x00010000|NO_PORT_B0x00020000);
2860 if (conversation != NULL((void*)0)) {
2861 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
2862 return dissector_success;
2863 }
2864 }
2865
2866 return false0;
2867}
2868
2869/*
2870 * Similar to try_conversation_dissector() with the particularity of calling
2871 * find_conversation_strat() in place of find_conversation() everywhere.
2872 */
2873bool_Bool
2874try_conversation_dissector_strat(packet_info *pinfo, const conversation_type ctype,
2875 tvbuff_t *tvb, proto_tree *tree, void* data, const unsigned options)
2876{
2877 conversation_t *conversation;
2878 bool_Bool dissector_success;
2879
2880 /*
2881 * Verify that the correct options are used, if any.
2882 */
2883 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", 2883, "(options == 0) || (options & 0xFFFF0000)"
, "Use NO_ADDR_B and/or NO_PORT_B as option"))))
;
2884
2885 /* Try each mode based on option flags */
2886 conversation = find_conversation_strat(pinfo, ctype, 0, false0);
2887 if (conversation != NULL((void*)0)) {
2888 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
2889 return dissector_success;
2890 }
2891
2892 if (options & NO_ADDR_B0x00010000) {
2893 conversation = find_conversation_strat(pinfo, ctype, NO_ADDR_B0x00010000, false0);
2894 if (conversation != NULL((void*)0)) {
2895 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
2896 return dissector_success;
2897 }
2898 }
2899
2900 if (options & NO_PORT_B0x00020000) {
2901 conversation = find_conversation_strat(pinfo, ctype, NO_PORT_B0x00020000, false0);
2902 if (conversation != NULL((void*)0)) {
2903 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data)) {
2904 return dissector_success;
2905 }
2906 }
2907
2908 }
2909
2910 if (options & (NO_ADDR_B0x00010000|NO_PORT_B0x00020000)) {
2911 conversation = find_conversation_strat(pinfo, ctype, NO_ADDR_B0x00010000|NO_PORT_B0x00020000, false0);
2912 if (conversation != NULL((void*)0)) {
2913 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data)) {
2914 return dissector_success;
2915 }
2916 }
2917 }
2918
2919 return false0;
2920}
2921
2922bool_Bool
2923try_conversation_dissector_by_id(const conversation_type ctype, const uint32_t id, tvbuff_t *tvb,
2924 packet_info *pinfo, proto_tree *tree, void* data)
2925{
2926 conversation_t *conversation;
2927
2928 conversation = find_conversation_by_id(pinfo->num, ctype, id);
2929
2930 if (conversation != NULL((void*)0)) {
2931 if (!conversation->dissector_tree) {
2932 return false0;
2933 }
2934
2935 int ret;
2936 dissector_handle_t handle = (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, pinfo->num);
2937
2938 if (handle == NULL((void*)0)) {
2939 return false0;
2940 }
2941
2942 ret = call_dissector_only(handle, tvb, pinfo, tree, data);
2943 if (!ret) {
2944 /* this packet was rejected by the dissector
2945 * so return false in case our caller wants
2946 * to do some cleaning up.
2947 */
2948 return false0;
2949 }
2950 return true1;
2951 }
2952 return false0;
2953}
2954
2955/* Identifies a conversation ("classic" or deinterlaced) */
2956conversation_t *
2957find_conversation_strat(const packet_info *pinfo, const conversation_type ctype, const unsigned options, const bool_Bool direction)
2958{
2959 conversation_t *conv=NULL((void*)0);
2960 if(is_deinterlacing_supported(pinfo)) {
2961 conversation_t *underlying_conv = find_conversation_deinterlacer_pinfo(pinfo);
2962 if(underlying_conv) {
2963 if(direction) { // reverse flow (dst to src)
2964 conv = find_conversation_deinterlaced(pinfo->num, &pinfo->dst, &pinfo->src, ctype, pinfo->destport, pinfo->srcport, underlying_conv->conv_index, options);
2965 }
2966 else {
2967 conv = find_conversation_deinterlaced(pinfo->num, &pinfo->src, &pinfo->dst, ctype, pinfo->srcport, pinfo->destport, underlying_conv->conv_index, options);
2968 }
2969 }
2970 }
2971 else {
2972 if(direction) { // reverse flow (dst to src)
2973 conv = find_conversation(pinfo->num, &pinfo->dst, &pinfo->src, ctype, pinfo->destport, pinfo->srcport, options);
2974 }
2975 else { // default (src to dst)
2976 conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, ctype, pinfo->srcport, pinfo->destport, options);
2977 }
2978 }
2979 return conv;
2980}
2981
2982/* Identifies a conversation ("classic" or deinterlaced) */
2983conversation_t *
2984find_conversation_strat_xtd(const packet_info *pinfo, const uint32_t frame_num, const address *addr_a, const address *addr_b,
2985 const conversation_type ctype, const uint32_t port_a, const uint32_t port_b, const unsigned options)
2986{
2987 conversation_t *conv=NULL((void*)0);
2988 if(is_deinterlacing_supported(pinfo)) {
2989 conversation_t *underlying_conv = find_conversation_deinterlacer_pinfo(pinfo);
2990 if(underlying_conv) {
2991 conv = find_conversation_deinterlaced(frame_num, addr_a, addr_b, ctype, port_a, port_b, underlying_conv->conv_index, options);
2992 }
2993 }
2994 else {
2995 conv = find_conversation(frame_num, addr_a, addr_b, ctype, port_a, port_b, options);
2996 }
2997 return conv;
2998}
2999
3000/** A helper function that calls find_conversation() using data from pinfo
3001 * The frame number and addresses are taken from pinfo.
3002 */
3003conversation_t *
3004find_conversation_pinfo(const packet_info *pinfo, const unsigned options)
3005{
3006 conversation_t *conv = NULL((void*)0);
3007
3008 DINSTR(char *src_str = address_to_str(NULL, &pinfo->src))(void)0;
3009 DINSTR(char *dst_str = address_to_str(NULL, &pinfo->dst))(void)0;
3010 DPRINT(("called for frame #%u: %s:%d -> %s:%d (ptype=%d)",(void)0
3011 pinfo->num, src_str, pinfo->srcport,(void)0
3012 dst_str, pinfo->destport, pinfo->ptype))(void)0;
3013 DINDENT()(void)0;
3014 DINSTR(wmem_free(NULL, src_str))(void)0;
3015 DINSTR(wmem_free(NULL, dst_str))(void)0;
3016
3017 /* Have we seen this conversation before? */
3018 if (pinfo->use_conv_addr_port_endpoints) {
3019 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", 3019
, "pinfo->conv_addr_port_endpoints"))))
;
3020 if ((conv = find_conversation(pinfo->num, &pinfo->conv_addr_port_endpoints->addr1, &pinfo->conv_addr_port_endpoints->addr2,
3021 pinfo->conv_addr_port_endpoints->ctype, pinfo->conv_addr_port_endpoints->port1,
3022 pinfo->conv_addr_port_endpoints->port2, 0)) != NULL((void*)0)) {
3023 DPRINT(("found previous conversation for frame #%u (last_frame=%d)",(void)0
3024 pinfo->num, conv->last_frame))(void)0;
3025 if (pinfo->num > conv->last_frame) {
3026 conv->last_frame = pinfo->num;
3027 }
3028 }
3029 } else if (pinfo->conv_elements) {
3030 if ((conv = find_conversation_full(pinfo->num, pinfo->conv_elements)) != NULL((void*)0)) {
3031 DPRINT(("found previous conversation elements for frame #%u (last_frame=%d)",(void)0
3032 pinfo->num, conv->last_frame))(void)0;
3033 if (pinfo->num > conv->last_frame) {
3034 conv->last_frame = pinfo->num;
3035 }
3036 }
3037 } else {
3038 if ((conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
3039 conversation_pt_to_conversation_type(pinfo->ptype), pinfo->srcport,
3040 pinfo->destport, options)) != NULL((void*)0)) {
3041 DPRINT(("found previous conversation for frame #%u (last_frame=%d)",(void)0
3042 pinfo->num, conv->last_frame))(void)0;
3043 if (pinfo->num > conv->last_frame) {
3044 conv->last_frame = pinfo->num;
3045 }
3046 }
3047 }
3048
3049 DENDENT()(void)0;
3050
3051 return conv;
3052}
3053
3054conversation_t *
3055find_conversation_pinfo_deinterlaced(const packet_info *pinfo, const uint32_t anchor, const unsigned options)
3056{
3057 conversation_t *conv = NULL((void*)0);
3058
3059 DINSTR(char *src_str = address_to_str(NULL, &pinfo->src))(void)0;
3060 DINSTR(char *dst_str = address_to_str(NULL, &pinfo->dst))(void)0;
3061 DPRINT(("called for frame #%u: %s:%d -> %s:%d (ptype=%d)",(void)0
3062 pinfo->num, src_str, pinfo->srcport,(void)0
3063 dst_str, pinfo->destport, pinfo->ptype))(void)0;
3064 DINDENT()(void)0;
3065 DINSTR(wmem_free(NULL, src_str))(void)0;
3066 DINSTR(wmem_free(NULL, dst_str))(void)0;
3067
3068 /* Have we seen this conversation before? */
3069 if (pinfo->use_conv_addr_port_endpoints) {
3070 // XXX - not implemented yet. Necessary ?
3071 } else if (pinfo->conv_elements) {
3072 // XXX - not implemented yet. Necessary ?
3073 } else {
3074 if ((conv = find_conversation_deinterlaced(pinfo->num, &pinfo->src, &pinfo->dst,
3075 conversation_pt_to_conversation_type(pinfo->ptype), pinfo->srcport,
3076 pinfo->destport, anchor, options)) != NULL((void*)0)) {
3077 DPRINT(("found previous conversation for frame #%u (last_frame=%d)",(void)0
3078 pinfo->num, conv->last_frame))(void)0;
3079 if (pinfo->num > conv->last_frame) {
3080 conv->last_frame = pinfo->num;
3081 }
3082 }
3083 }
3084
3085 DENDENT()(void)0;
3086
3087 return conv;
3088}
3089
3090/*
3091 * Returns true when deinterlacing is supported (file format) and enabled (user pref)
3092 * Deinterlacing is only supported for the Ethernet wtap for now.
3093 */
3094bool_Bool
3095is_deinterlacing_supported(const packet_info *pinfo)
3096{
3097 if( (pinfo->pseudo_header != NULL((void*)0))
3098 && (pinfo->rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_ETHERNET1)
3099 && (prefs.conversation_deinterlacing_key>0)) {
3100 return true1;
3101 }
3102 return false0;
3103}
3104
3105conversation_t *
3106find_conversation_pinfo_strat(const packet_info *pinfo, const unsigned options)
3107{
3108 conversation_t *conv=NULL((void*)0);
3109
3110 if(is_deinterlacing_supported(pinfo)) {
3111
3112 conversation_t *underlying_conv = find_conversation_deinterlacer_pinfo(pinfo);
3113
3114 if(underlying_conv) {
3115 conv = find_conversation_pinfo_deinterlaced(pinfo, underlying_conv->conv_index, options);
3116 }
3117 }
3118 else {
3119 conv = find_conversation_pinfo(pinfo, options);
3120 }
3121
3122 return conv;
3123}
3124
3125/** A helper function that calls find_conversation() using data from pinfo,
3126 * as above, but somewhat simplified for being accessed from packet_list.
3127 * The frame number and addresses are taken from pinfo.
3128 */
3129conversation_t *
3130find_conversation_pinfo_ro(const packet_info *pinfo, const unsigned options)
3131{
3132 conversation_t *conv = NULL((void*)0);
3133
3134 DINSTR(char *src_str = address_to_str(NULL, &pinfo->src))(void)0;
3135 DINSTR(char *dst_str = address_to_str(NULL, &pinfo->dst))(void)0;
3136 DPRINT(("called for frame #%u: %s:%d -> %s:%d (ptype=%d)",(void)0
3137 pinfo->num, src_str, pinfo->srcport,(void)0
3138 dst_str, pinfo->destport, pinfo->ptype))(void)0;
3139 DINDENT()(void)0;
3140 DINSTR(wmem_free(NULL, src_str))(void)0;
3141 DINSTR(wmem_free(NULL, dst_str))(void)0;
3142
3143 /* Have we seen this conversation before? */
3144 if (pinfo->use_conv_addr_port_endpoints) {
3145 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", 3145
, "pinfo->conv_addr_port_endpoints"))))
;
3146 if ((conv = find_conversation(pinfo->num, &pinfo->conv_addr_port_endpoints->addr1, &pinfo->conv_addr_port_endpoints->addr2,
3147 pinfo->conv_addr_port_endpoints->ctype, pinfo->conv_addr_port_endpoints->port1,
3148 pinfo->conv_addr_port_endpoints->port2, 0)) != NULL((void*)0)) {
3149 DPRINT(("found previous conversation for frame #%u (last_frame=%d)",(void)0
3150 pinfo->num, conv->last_frame))(void)0;
3151 }
3152 } else if (pinfo->conv_elements) {
3153 if ((conv = find_conversation_full(pinfo->num, pinfo->conv_elements)) != NULL((void*)0)) {
3154 DPRINT(("found previous conversation elements for frame #%u (last_frame=%d)",(void)0
3155 pinfo->num, conv->last_frame))(void)0;
3156 }
3157 } else if ((conv = find_conversation_strat(pinfo, conversation_pt_to_conversation_type(pinfo->ptype), options, false0)) != NULL((void*)0)) {
3158 DPRINT(("found previous conversation for frame #%u (last_frame=%d)",(void)0
3159 pinfo->num, conv->last_frame))(void)0;
3160 }
3161 /* If none of the above found any ordinary conversation,
3162 * we might be dealing with an error packet referencing/carrying a known conversation.
3163 * ICMP Type 3/11 are good examples, give them a chance to be identified.
3164 * Note, any Transport protocol might be updated to allow this mechanism to work.
3165 */
3166 else if( (pinfo->track_ctype>0) ) {
3167
3168 /* reference id */
3169 uint32_t conv_index = 0;
3170
3171 /* Parse all keys and find the one matching id and ctype,
3172 * the reference id is what we are looking for.
3173 */
3174 wmem_list_t *err_pkts_keys = wmem_map_get_keys(NULL((void*)0), conversation_hashtable_err_pkts);
3175 for (wmem_list_frame_t *cur_frame = wmem_list_head(err_pkts_keys ); cur_frame; cur_frame = wmem_list_frame_next(cur_frame)) {
3176 conversation_element_t *cet = (conversation_element_t *)wmem_list_frame_data(cur_frame);
3177 if(cet) {
3178 if( (cet[2].conversation_type_val == pinfo->track_ctype) && (cet[0].uint_val == pinfo->stream_id) ) {
3179 conv_index = cet[1].uint_val;
3180 break;
3181 }
3182 }
3183 }
3184 wmem_destroy_list(err_pkts_keys);
3185
3186 /* Now, bring the transport conversation as we know its conv_index.
3187 * Note: the way conversations are added (starting from lower layers),
3188 * it's currently not possible to see a transport conversation
3189 * with conv_index with value 0.
3190 * XXX - Check if that is also true for PDU.
3191 */
3192 if(conv_index>0) {
3193 conversation_t *tsconv = NULL((void*)0);
3194
3195 /* If a deinterlacing key was requested, search for the conversation
3196 * in the deinterlaced version of the "addr_port" table.
3197 * XXX - as this check is becoming redundant, isolate it in a function ?
3198 */
3199 if(is_deinterlacing_supported(pinfo)) {
3200 tsconv = wmem_map_find(conversation_hashtable_exact_addr_port_anc, find_conversation_by_index, GUINT_TO_POINTER(conv_index)((gpointer) (gulong) (conv_index)));
3201 }
3202 else {
3203 tsconv = wmem_map_find(conversation_hashtable_exact_addr_port, find_conversation_by_index, GUINT_TO_POINTER(conv_index)((gpointer) (gulong) (conv_index)));
3204 }
3205 if(tsconv) {
3206 conv = tsconv;
3207 }
3208 }
3209 }
3210 /* else: something is either not implemented or not handled */
3211
3212 DENDENT()(void)0;
3213
3214 return conv;
3215}
3216
3217/* A helper function that calls find_conversation() and, if a conversation is
3218 * not found, calls conversation_new().
3219 * The frame number and addresses are taken from pinfo.
3220 * No options are used, though we could extend this API to include an options
3221 * parameter.
3222 */
3223conversation_t *
3224find_or_create_conversation(const packet_info *pinfo)
3225{
3226 conversation_t *conv=NULL((void*)0);
3227
3228 /* Have we seen this conversation before? */
3229 if ((conv = find_conversation_pinfo(pinfo, 0)) == NULL((void*)0)) {
3230 /* No, this is a new conversation. */
3231 DPRINT(("did not find previous conversation for frame #%u",(void)0
3232 pinfo->num))(void)0;
3233 DINDENT()(void)0;
3234 if (pinfo->use_conv_addr_port_endpoints) {
3235 conv = conversation_new(pinfo->num, &pinfo->conv_addr_port_endpoints->addr1, &pinfo->conv_addr_port_endpoints->addr2,
3236 pinfo->conv_addr_port_endpoints->ctype, pinfo->conv_addr_port_endpoints->port1,
3237 pinfo->conv_addr_port_endpoints->port2, 0);
3238 } else if (pinfo->conv_elements) {
3239 conv = conversation_new_full(pinfo->num, pinfo->conv_elements);
3240 } else {
3241 conv = conversation_new(pinfo->num, &pinfo->src,
3242 &pinfo->dst, conversation_pt_to_conversation_type(pinfo->ptype),
3243 pinfo->srcport, pinfo->destport, 0);
3244 }
3245 DENDENT()(void)0;
3246 }
3247
3248 return conv;
3249}
3250
3251conversation_t *
3252find_or_create_conversation_deinterlaced(const packet_info *pinfo, const uint32_t conv_index)
3253{
3254 conversation_t *conv=NULL((void*)0);
3255
3256 /* Have we seen this conversation before? */
3257 if ((conv = find_conversation_pinfo_deinterlaced(pinfo, conv_index, 0)) == NULL((void*)0)) {
3258 /* No, this is a new conversation. */
3259 DPRINT(("did not find previous conversation for frame #%u",(void)0
3260 pinfo->num))(void)0;
3261 DINDENT()(void)0;
3262 if (pinfo->use_conv_addr_port_endpoints) {
3263 conv = conversation_new_strat(pinfo, pinfo->conv_addr_port_endpoints->ctype, 0);
3264 } else if (pinfo->conv_elements) {
3265 conv = conversation_new_full(pinfo->num, pinfo->conv_elements);
3266 } else {
3267 conv = conversation_new_deinterlaced(pinfo->num, &pinfo->src, &pinfo->dst,
3268 conversation_pt_to_conversation_type(pinfo->ptype),
3269 pinfo->srcport, pinfo->destport, conv_index, 0);
3270 }
3271 DENDENT()(void)0;
3272 }
3273
3274 return conv;
3275}
3276
3277conversation_t *
3278find_or_create_conversation_strat(const packet_info *pinfo)
3279{
3280 conversation_t *conv=NULL((void*)0);
1
'conv' initialized to a null pointer value
3281
3282 if(is_deinterlacing_supported(pinfo)) {
2
Taking true branch
3283 conversation_t *underlying_conv = find_conversation_deinterlacer_pinfo(pinfo);
3284 if(underlying_conv) {
3
Assuming 'underlying_conv' is null
4
Taking false branch
3285 conv = find_or_create_conversation_deinterlaced(pinfo, underlying_conv->conv_index);
3286 }
3287 }
3288 else {
3289 conv = find_or_create_conversation(pinfo);
3290 }
3291
3292 return conv;
5
Null returned from a function that is expected to return a non-null value
3293}
3294
3295conversation_t *
3296find_or_create_conversation_by_id(packet_info *pinfo, const conversation_type ctype, const uint32_t id)
3297{
3298 conversation_t *conv=NULL((void*)0);
3299
3300 /* Have we seen this conversation before? */
3301 if ((conv = find_conversation_by_id(pinfo->num, ctype, id)) == NULL((void*)0)) {
3302 /* No, this is a new conversation. */
3303 DPRINT(("did not find previous conversation for frame #%u",(void)0
3304 pinfo->num))(void)0;
3305 DINDENT()(void)0;
3306 conv = conversation_new_by_id(pinfo->num, ctype, id);
3307 DENDENT()(void)0;
3308 }
3309
3310 return conv;
3311}
3312
3313void
3314conversation_set_conv_addr_port_endpoints(struct _packet_info *pinfo, address* addr1, address* addr2,
3315 conversation_type ctype, uint32_t port1, uint32_t port2)
3316{
3317 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)))
;
3318
3319 if (addr1 != NULL((void*)0)) {
3320 copy_address_wmem(pinfo->pool, &pinfo->conv_addr_port_endpoints->addr1, addr1);
3321 }
3322 if (addr2 != NULL((void*)0)) {
3323 copy_address_wmem(pinfo->pool, &pinfo->conv_addr_port_endpoints->addr2, addr2);
3324 }
3325
3326 pinfo->conv_addr_port_endpoints->ctype = ctype;
3327 pinfo->conv_addr_port_endpoints->port1 = port1;
3328 pinfo->conv_addr_port_endpoints->port2 = port2;
3329
3330 pinfo->use_conv_addr_port_endpoints = true1;
3331}
3332
3333void
3334conversation_set_elements_by_id(struct _packet_info *pinfo, conversation_type ctype, uint32_t id)
3335{
3336 pinfo->conv_elements = wmem_alloc0(pinfo->pool, sizeof(conversation_element_t) * 2);
3337 pinfo->conv_elements[0].type = CE_UINT;
3338 pinfo->conv_elements[0].uint_val = id;
3339 pinfo->conv_elements[1].type = CE_CONVERSATION_TYPE;
3340 pinfo->conv_elements[1].conversation_type_val = ctype;
3341}
3342
3343uint32_t
3344conversation_get_id_from_elements(struct _packet_info *pinfo, conversation_type ctype, const unsigned options)
3345{
3346 if (pinfo->conv_elements == NULL((void*)0)) {
3347 return 0;
3348 }
3349
3350 if (pinfo->conv_elements[0].type != CE_UINT || pinfo->conv_elements[1].type != CE_CONVERSATION_TYPE) {
3351 return 0;
3352 }
3353
3354 if ((pinfo->conv_elements[1].conversation_type_val != ctype) && ((options & USE_LAST_ENDPOINT0x08) != USE_LAST_ENDPOINT0x08)) {
3355 return 0;
3356 }
3357
3358 return pinfo->conv_elements[0].uint_val;
3359}
3360
3361wmem_map_t *
3362get_conversation_hashtables(void)
3363{
3364 return conversation_hashtable_element_list;
3365}
3366
3367const address*
3368conversation_key_addr1(const conversation_element_t *key)
3369{
3370 const address *addr = &null_address_;
3371 if (key[ADDR1_IDX].type == CE_ADDRESS) {
3372 addr = &key[ADDR1_IDX].addr_val;
3373 }
3374 return addr;
3375}
3376
3377uint32_t
3378conversation_key_port1(const conversation_element_t * key)
3379{
3380 uint32_t port = 0;
3381 if (key[ADDR1_IDX].type == CE_ADDRESS && key[PORT1_IDX].type == CE_PORT) {
3382 port = key[PORT1_IDX].port_val;
3383 }
3384 return port;
3385}
3386
3387const address*
3388conversation_key_addr2(const conversation_element_t * key)
3389{
3390 const address *addr = &null_address_;
3391 if (key[ADDR1_IDX].type == CE_ADDRESS && key[PORT1_IDX].type == CE_PORT && key[ADDR2_IDX].type == CE_ADDRESS) {
3392 addr = &key[ADDR2_IDX].addr_val;
3393 }
3394 return addr;
3395}
3396
3397uint32_t
3398conversation_key_port2(const conversation_element_t * key)
3399{
3400 uint32_t port = 0;
3401 if (key[ADDR1_IDX].type == CE_ADDRESS && key[PORT1_IDX].type == CE_PORT) {
3402 if (key[ADDR2_IDX].type == CE_ADDRESS && key[PORT2_IDX].type == CE_PORT) {
3403 // Exact
3404 port = key[PORT2_IDX].port_val;
3405 } else if (key[PORT2_NO_ADDR2_IDX].type == CE_PORT) {
3406 // No addr 2
3407 port = key[PORT2_NO_ADDR2_IDX].port_val;
3408 }
3409 }
3410 return port;
3411}
3412
3413WS_DLL_PUBLIC__attribute__ ((visibility ("default"))) extern
3414conversation_type conversation_pt_to_conversation_type(port_type pt)
3415{
3416 switch (pt)
3417 {
3418 case PT_NONE:
3419 return CONVERSATION_NONE;
3420 case PT_SCTP:
3421 return CONVERSATION_SCTP;
3422 case PT_TCP:
3423 return CONVERSATION_TCP;
3424 case PT_UDP:
3425 return CONVERSATION_UDP;
3426 case PT_DCCP:
3427 return CONVERSATION_DCCP;
3428 case PT_IPX:
3429 return CONVERSATION_IPX;
3430 case PT_DDP:
3431 return CONVERSATION_DDP;
3432 case PT_IDP:
3433 return CONVERSATION_IDP;
3434 case PT_USB:
3435 return CONVERSATION_USB;
3436 case PT_I2C:
3437 /* XXX - this doesn't currently have conversations */
3438 return CONVERSATION_I2C;
3439 case PT_IBQP:
3440 return CONVERSATION_IBQP;
3441 case PT_BLUETOOTH:
3442 return CONVERSATION_BLUETOOTH;
3443 case PT_IWARP_MPA:
3444 return CONVERSATION_IWARP_MPA;
3445 case PT_MCTP:
3446 return CONVERSATION_MCTP;
3447 }
3448
3449 DISSECTOR_ASSERT(false)((void) ((0) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/conversation.c", 3449, "0"))))
;
3450 return CONVERSATION_NONE;
3451}
3452
3453WS_DLL_PUBLIC__attribute__ ((visibility ("default"))) extern
3454endpoint_type conversation_pt_to_endpoint_type(port_type pt)
3455{
3456 switch (pt)
3457 {
3458 case PT_NONE:
3459 return ENDPOINT_NONECONVERSATION_NONE;
3460 case PT_SCTP:
3461 return ENDPOINT_SCTPCONVERSATION_SCTP;
3462 case PT_TCP:
3463 return ENDPOINT_TCPCONVERSATION_TCP;
3464 case PT_UDP:
3465 return ENDPOINT_UDPCONVERSATION_UDP;
3466 case PT_DCCP:
3467 return ENDPOINT_DCCPCONVERSATION_DCCP;
3468 case PT_IPX:
3469 return ENDPOINT_IPXCONVERSATION_IPX;
3470 case PT_DDP:
3471 return ENDPOINT_DDPCONVERSATION_DDP;
3472 case PT_IDP:
3473 return ENDPOINT_IDPCONVERSATION_IDP;
3474 case PT_USB:
3475 return ENDPOINT_USBCONVERSATION_USB;
3476 case PT_I2C:
3477 /* XXX - this doesn't have ports */
3478 return ENDPOINT_I2CCONVERSATION_I2C;
3479 case PT_IBQP:
3480 return ENDPOINT_IBQPCONVERSATION_IBQP;
3481 case PT_BLUETOOTH:
3482 return ENDPOINT_BLUETOOTHCONVERSATION_BLUETOOTH;
3483 case PT_IWARP_MPA:
3484 return ENDPOINT_IWARP_MPACONVERSATION_IWARP_MPA;
3485 case PT_MCTP:
3486 return ENDPOINT_MCTPCONVERSATION_MCTP;
3487 }
3488
3489 DISSECTOR_ASSERT(false)((void) ((0) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/conversation.c", 3489, "0"))))
;
3490 return ENDPOINT_NONECONVERSATION_NONE;
3491}
3492
3493/*
3494 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3495 *
3496 * Local variables:
3497 * c-basic-offset: 4
3498 * tab-width: 8
3499 * indent-tabs-mode: nil
3500 * End:
3501 *
3502 * vi: set shiftwidth=4 tabstop=8 expandtab:
3503 * :indentSize=4:tabSize=8:noTabs=true:
3504 */