Bug Summary

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