2 * Routines for building lists of packets that are part of a "conversation"
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
17 #include "conversation.h"
19 /* define DEBUG_CONVERSATION for pretty debug printing */
20 /* #define DEBUG_CONVERSATION */
21 #include "conversation_debug.h"
23 #ifdef DEBUG_CONVERSATION
24 int _debug_conversation_indent = 0;
36 struct conversation_key {
37 struct conversation_key *next;
46 * Hash table for conversations with no wildcards.
48 static wmem_map_t *conversation_hashtable_exact = NULL;
51 * Hash table for conversations with one wildcard address.
53 static wmem_map_t *conversation_hashtable_no_addr2 = NULL;
56 * Hash table for conversations with one wildcard port.
58 static wmem_map_t *conversation_hashtable_no_port2 = NULL;
61 * Hash table for conversations with one wildcard address and port.
63 static wmem_map_t *conversation_hashtable_no_addr2_or_port2 = NULL;
66 static guint32 new_index;
69 * Placeholder for address-less conversations.
71 static address null_address_ = ADDRESS_INIT_NONE;
75 * Creates a new conversation with known endpoints based on a conversation
76 * created with the CONVERSATION_TEMPLATE option while keeping the
77 * conversation created with the CONVERSATION_TEMPLATE option so it can still
78 * match future connections.
80 * Passing a pointer to a conversation whose options mask does not include
81 * CONVERSATION_TEMPLATE or where the conversation's protocol type (ptype)
82 * indicates a non-connnection oriented protocol will return the conversation
85 * addr2 and port2 are used in the function if their respective conversation
86 * options bits are set (NO_ADDR2 and NO_PORT2).
88 static conversation_t *
89 conversation_create_from_template(conversation_t *conversation, const address *addr2, const guint32 port2)
92 * Add a new conversation and keep the conversation template only if the
93 * CONVERSATION_TEMPLATE bit is set for a connection oriented protocol.
95 if (conversation->options & CONVERSATION_TEMPLATE &&
96 conversation->key_ptr->etype != ENDPOINT_UDP)
99 * Set up a new options mask where the conversation template bit and the
100 * bits for absence of a second address and port pair have been removed.
102 conversation_t *new_conversation_from_template;
103 guint options = conversation->options & ~(CONVERSATION_TEMPLATE | NO_ADDR2 | NO_PORT2);
106 * Are both the NO_ADDR2 and NO_PORT2 wildcards set in the options mask?
108 if (conversation->options & NO_ADDR2 &&
109 conversation->options & NO_PORT2)
112 * The conversation template was created without knowledge of both
113 * the second address as well as the second port. Create a new
114 * conversation with new 2nd address and 2nd port.
116 new_conversation_from_template =
117 conversation_new(conversation->setup_frame,
118 &conversation->key_ptr->addr1, addr2,
119 conversation->key_ptr->etype, conversation->key_ptr->port1,
122 else if (conversation->options & NO_PORT2)
125 * The conversation template was created without knowledge of port 2
126 * only. Create a new conversation with new 2nd port.
128 new_conversation_from_template =
129 conversation_new(conversation->setup_frame,
130 &conversation->key_ptr->addr1, &conversation->key_ptr->addr2,
131 conversation->key_ptr->etype, conversation->key_ptr->port1,
134 else if (conversation->options & NO_ADDR2)
137 * The conversation template was created without knowledge of address
138 * 2. Create a new conversation with new 2nd address.
140 new_conversation_from_template =
141 conversation_new(conversation->setup_frame,
142 &conversation->key_ptr->addr1, addr2,
143 conversation->key_ptr->etype, conversation->key_ptr->port1,
144 conversation->key_ptr->port2, options);
149 * The CONVERSATION_TEMPLATE bit was set, but no other bit that the
150 * CONVERSATION_TEMPLATE bit controls is active. Just return the old
157 * Set the protocol dissector used for the template conversation as
158 * the handler of the new conversation as well.
160 new_conversation_from_template->dissector_tree = conversation->dissector_tree;
162 return new_conversation_from_template;
171 * Compute the hash value for two given address/port pairs if the match
174 /* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx#existing
178 conversation_hash_exact(gconstpointer v)
180 const conversation_key_t key = (const conversation_key_t)v;
187 hash_val = add_address_to_hash(hash_val, &key->addr1);
189 tmp_addr.data = &key->port1;
190 hash_val = add_address_to_hash(hash_val, &tmp_addr);
192 hash_val = add_address_to_hash(hash_val, &key->addr2);
194 tmp_addr.data = &key->port2;
195 hash_val = add_address_to_hash(hash_val, &tmp_addr);
197 hash_val += ( hash_val << 3 );
198 hash_val ^= ( hash_val >> 11 );
199 hash_val += ( hash_val << 15 );
205 * Compare two conversation keys for an exact match.
208 conversation_match_exact(gconstpointer v, gconstpointer w)
210 const conversation_key_t v1 = (const conversation_key_t)v;
211 const conversation_key_t v2 = (const conversation_key_t)w;
213 if (v1->etype != v2->etype)
214 return 0; /* different types of port */
217 * Are the first and second port 1 values the same, the first and
218 * second port 2 values the same, the first and second address
219 * 1 values the same, and the first and second address 2 values
222 if (v1->port1 == v2->port1 &&
223 v1->port2 == v2->port2 &&
224 addresses_equal(&v1->addr1, &v2->addr1) &&
225 addresses_equal(&v1->addr2, &v2->addr2)) {
227 * Yes. It's the same conversation, and the two
228 * address/port pairs are going in the same direction.
234 * Is the first port 2 the same as the second port 1, the first
235 * port 1 the same as the second port 2, the first address 2
236 * the same as the second address 1, and the first address 1
237 * the same as the second address 2?
239 if (v1->port2 == v2->port1 &&
240 v1->port1 == v2->port2 &&
241 addresses_equal(&v1->addr2, &v2->addr1) &&
242 addresses_equal(&v1->addr1, &v2->addr2)) {
244 * Yes. It's the same conversation, and the two
245 * address/port pairs are going in opposite directions.
251 * The addresses or the ports don't match.
257 * Compute the hash value for two given address/port pairs if the match
258 * has a wildcard address 2.
261 conversation_hash_no_addr2(gconstpointer v)
263 const conversation_key_t key = (const conversation_key_t)v;
270 hash_val = add_address_to_hash(hash_val, &key->addr1);
272 tmp_addr.data = &key->port1;
273 hash_val = add_address_to_hash(hash_val, &tmp_addr);
275 tmp_addr.data = &key->port2;
276 hash_val = add_address_to_hash(hash_val, &tmp_addr);
278 hash_val += ( hash_val << 3 );
279 hash_val ^= ( hash_val >> 11 );
280 hash_val += ( hash_val << 15 );
286 * Compare two conversation keys, except for the address 2 value.
287 * We don't check both directions of the conversation - the routine
288 * doing the hash lookup has to do two searches, as the hash key
289 * will be different for the two directions.
292 conversation_match_no_addr2(gconstpointer v, gconstpointer w)
294 const conversation_key_t v1 = (const conversation_key_t)v;
295 const conversation_key_t v2 = (const conversation_key_t)w;
297 if (v1->etype != v2->etype)
298 return 0; /* different types of port */
301 * Are the first and second port 1 values the same, the first and
302 * second port 2 valuess the same, and the first and second
303 * address 1 values the same?
305 if (v1->port1 == v2->port1 &&
306 v1->port2 == v2->port2 &&
307 addresses_equal(&v1->addr1, &v2->addr1)) {
309 * Yes. It's the same conversation, and the two
310 * address/port pairs are going in the same direction.
316 * The addresses or the ports don't match.
322 * Compute the hash value for two given address/port pairs if the match
323 * has a wildcard port 2.
326 conversation_hash_no_port2(gconstpointer v)
328 const conversation_key_t key = (const conversation_key_t)v;
335 hash_val = add_address_to_hash(hash_val, &key->addr1);
337 tmp_addr.data = &key->port1;
338 hash_val = add_address_to_hash(hash_val, &tmp_addr);
340 hash_val = add_address_to_hash(hash_val, &key->addr2);
342 hash_val += ( hash_val << 3 );
343 hash_val ^= ( hash_val >> 11 );
344 hash_val += ( hash_val << 15 );
350 * Compare two conversation keys, except for the port 2 value.
351 * We don't check both directions of the conversation - the routine
352 * doing the hash lookup has to do two searches, as the hash key
353 * will be different for the two directions.
356 conversation_match_no_port2(gconstpointer v, gconstpointer w)
358 const conversation_key_t v1 = (const conversation_key_t)v;
359 const conversation_key_t v2 = (const conversation_key_t)w;
361 if (v1->etype != v2->etype)
362 return 0; /* different types of port */
365 * Are the first and second port 1 values the same, the first and
366 * second address 1 values the same, and the first and second
367 * address 2 values the same?
369 if (v1->port1 == v2->port1 &&
370 addresses_equal(&v1->addr1, &v2->addr1) &&
371 addresses_equal(&v1->addr2, &v2->addr2)) {
373 * Yes. It's the same conversation, and the two
374 * address/port pairs are going in the same direction.
380 * The addresses or the ports don't match.
386 * Compute the hash value for two given address/port pairs if the match
387 * has a wildcard address 2 and port 2.
390 conversation_hash_no_addr2_or_port2(gconstpointer v)
392 const conversation_key_t key = (const conversation_key_t)v;
399 hash_val = add_address_to_hash(hash_val, &key->addr1);
401 tmp_addr.data = &key->port1;
402 hash_val = add_address_to_hash(hash_val, &tmp_addr);
404 hash_val += ( hash_val << 3 );
405 hash_val ^= ( hash_val >> 11 );
406 hash_val += ( hash_val << 15 );
412 * Compare the address 1 and port 1 in the two conversation keys.
413 * We don't check both directions of the conversation - the routine
414 * doing the hash lookup has to do two searches, as the hash key
415 * will be different for the two directions.
418 conversation_match_no_addr2_or_port2(gconstpointer v, gconstpointer w)
420 const conversation_key_t v1 = (const conversation_key_t)v;
421 const conversation_key_t v2 = (const conversation_key_t)w;
423 if (v1->etype != v2->etype)
424 return 0; /* different types of port */
427 * Are the first and second port 1 values the same and the first
428 * and second address 1 values the same?
430 if (v1->port1 == v2->port1 &&
431 addresses_equal(&v1->addr1, &v2->addr1)) {
433 * Yes. It's the same conversation, and the two
434 * address/port pairs are going in the same direction.
440 * The addresses or the ports don't match.
446 * Create a new hash tables for conversations.
449 conversation_init(void)
452 * Free up any space allocated for conversation protocol data
455 * We can free the space, as the structures it contains are
456 * pointed to by conversation data structures that were freed
459 conversation_hashtable_exact =
460 wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), conversation_hash_exact,
461 conversation_match_exact);
462 conversation_hashtable_no_addr2 =
463 wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), conversation_hash_no_addr2,
464 conversation_match_no_addr2);
465 conversation_hashtable_no_port2 =
466 wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), conversation_hash_no_port2,
467 conversation_match_no_port2);
468 conversation_hashtable_no_addr2_or_port2 =
469 wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), conversation_hash_no_addr2_or_port2,
470 conversation_match_no_addr2_or_port2);
475 * Initialize some variables every time a file is loaded or re-loaded.
477 void conversation_epan_reset(void)
480 * Start the conversation indices over at 0.
486 * Does the right thing when inserting into one of the conversation hash tables,
487 * taking into account ordering and hash chains and all that good stuff.
489 * Mostly adapted from the old conversation_new().
492 conversation_insert_into_hashtable(wmem_map_t *hashtable, conversation_t *conv)
494 conversation_t *chain_head, *chain_tail, *cur, *prev;
496 chain_head = (conversation_t *)wmem_map_lookup(hashtable, conv->key_ptr);
498 if (NULL==chain_head) {
502 wmem_map_insert(hashtable, conv->key_ptr, conv);
503 DPRINT(("created a new conversation chain"));
506 /* There's an existing chain for this key */
507 DPRINT(("there's an existing conversation chain"));
509 chain_tail = chain_head->last;
511 if (conv->setup_frame >= chain_tail->setup_frame) {
512 /* This convo belongs at the end of the chain */
515 chain_tail->next = conv;
516 chain_head->last = conv;
519 /* Loop through the chain to find the right spot */
523 for (; (conv->setup_frame > cur->setup_frame) && cur->next; prev=cur, cur=cur->next)
527 /* Changing the head of the chain */
528 conv->next = chain_head;
529 conv->last = chain_tail;
530 chain_head->last = NULL;
531 wmem_map_insert(hashtable, conv->key_ptr, conv);
534 /* Inserting into the middle of the chain */
544 * Does the right thing when removing from one of the conversation hash tables,
545 * taking into account ordering and hash chains and all that good stuff.
548 conversation_remove_from_hashtable(wmem_map_t *hashtable, conversation_t *conv)
550 conversation_t *chain_head, *cur, *prev;
552 chain_head = (conversation_t *)wmem_map_lookup(hashtable, conv->key_ptr);
554 if (conv == chain_head) {
555 /* We are currently the front of the chain */
556 if (NULL == conv->next) {
557 /* We are the only conversation in the chain, no need to
558 * update next pointer, but do not call
559 * wmem_map_remove() either because the conv data
560 * will be re-inserted. */
561 wmem_map_steal(hashtable, conv->key_ptr);
564 /* Update the head of the chain */
565 chain_head = conv->next;
566 chain_head->last = conv->last;
568 if (conv->latest_found == conv)
569 chain_head->latest_found = NULL;
571 chain_head->latest_found = conv->latest_found;
573 wmem_map_insert(hashtable, chain_head->key_ptr, chain_head);
577 /* We are not the front of the chain. Loop through to find us.
578 * Start loop at chain_head->next rather than chain_head because
579 * we already know we're not at the head. */
580 cur = chain_head->next;
583 for (; (cur != conv) && cur->next; prev=cur, cur=cur->next)
587 /* XXX: Conversation not found. Wrong hashtable? */
591 prev->next = conv->next;
593 if (NULL == conv->next) {
594 /* We're at the very end of the list. */
595 chain_head->last = prev;
598 if (chain_head->latest_found == conv)
599 chain_head->latest_found = prev;
604 * Given two address/port pairs for a packet, create a new conversation
605 * to contain packets between those address/port pairs.
607 * The options field is used to specify whether the address 2 value
608 * and/or port 2 value are not given and any value is acceptable
609 * when searching for this conversation.
612 conversation_new(const guint32 setup_frame, const address *addr1, const address *addr2,
613 const endpoint_type etype, const guint32 port1, const guint32 port2, const guint options)
616 DISSECTOR_ASSERT(!(options | CONVERSATION_TEMPLATE) || ((options | (NO_ADDR2 | NO_PORT2 | NO_PORT2_FORCE))) &&
617 "A conversation template may not be constructed without wildcard options");
619 wmem_map_t* hashtable;
620 conversation_t *conversation=NULL;
621 conversation_key_t new_key;
623 #ifdef DEBUG_CONVERSATION
628 if (options & NO_ADDR2) {
630 * Neither address 1 nor address 2.
632 if (options & NO_PORT2) {
634 * Port 1 but not port 2.
636 DPRINT(("creating conversation for frame #%u: ID %u (etype=%d)",
637 setup_frame, port1, etype));
642 DPRINT(("creating conversation for frame #%u: %u -> %u (etype=%d)",
643 setup_frame, port1, port2, etype));
647 * Address 2 but not address 1.
649 if (options & NO_PORT2) {
651 * Port 1 but not port 2.
653 DPRINT(("creating conversation for frame #%u: ID %u, address %s (etype=%d)",
655 address_to_str(wmem_packet_scope(), addr2), etype));
660 DPRINT(("creating conversation for frame #%u: %u -> %s:%u (etype=%d)",
662 address_to_str(wmem_packet_scope(), addr2), port2, etype));
669 if (options & NO_ADDR2) {
671 * Address 1 but no address 2.
673 if (options & NO_PORT2) {
675 * Port 1 but not port 2.
677 DPRINT(("creating conversation for frame #%u: %s:%u (etype=%d)",
678 setup_frame, address_to_str(wmem_packet_scope(), addr1), port1,
684 DPRINT(("creating conversation for frame #%u: %s:%u -> %u (etype=%d)",
685 setup_frame, address_to_str(wmem_packet_scope(), addr1), port1,
692 if (options & NO_PORT2) {
694 * Port 1 but not port 2.
696 DPRINT(("creating conversation for frame #%u: %s:%u -> %s (etype=%d)",
697 setup_frame, address_to_str(wmem_packet_scope(), addr1), port1,
698 address_to_str(wmem_packet_scope(), addr2), etype));
703 DPRINT(("creating conversation for frame #%u: %s:%u -> %s:%u (etype=%d)",
704 setup_frame, address_to_str(wmem_packet_scope(), addr1), port1,
705 address_to_str(wmem_packet_scope(), addr2), port2, etype));
711 if (options & NO_ADDR2) {
712 if (options & (NO_PORT2|NO_PORT2_FORCE)) {
713 hashtable = conversation_hashtable_no_addr2_or_port2;
715 hashtable = conversation_hashtable_no_addr2;
718 if (options & (NO_PORT2|NO_PORT2_FORCE)) {
719 hashtable = conversation_hashtable_no_port2;
721 hashtable = conversation_hashtable_exact;
725 new_key = wmem_new(wmem_file_scope(), struct conversation_key);
727 copy_address_wmem(wmem_file_scope(), &new_key->addr1, addr1);
729 clear_address(&new_key->addr1);
732 copy_address_wmem(wmem_file_scope(), &new_key->addr2, addr2);
734 clear_address(&new_key->addr2);
736 new_key->etype = etype;
737 new_key->port1 = port1;
738 new_key->port2 = port2;
740 conversation = wmem_new(wmem_file_scope(), conversation_t);
741 memset(conversation, 0, sizeof(conversation_t));
743 conversation->conv_index = new_index;
744 conversation->setup_frame = conversation->last_frame = setup_frame;
745 conversation->data_list = NULL;
747 conversation->dissector_tree = wmem_tree_new(wmem_file_scope());
749 /* set the options and key pointer */
750 conversation->options = options;
751 conversation->key_ptr = new_key;
756 conversation_insert_into_hashtable(hashtable, conversation);
762 conversation_t *conversation_new_by_id(const guint32 setup_frame, const endpoint_type etype, const guint32 id, const guint options)
764 /* Force the lack of an address or port 2 */
765 return conversation_new(setup_frame, NULL, NULL, etype, id, 0, options | NO_ADDR2 | NO_PORT2);
769 * Set the port 2 value in a key. Remove the original from table,
770 * update the options and port values, insert the updated key.
773 conversation_set_port2(conversation_t *conv, const guint32 port)
775 DISSECTOR_ASSERT_HINT(!(conv->options & CONVERSATION_TEMPLATE),
776 "Use the conversation_create_from_template function when the CONVERSATION_TEMPLATE bit is set in the options mask");
778 DPRINT(("called for port=%d", port));
781 * If the port 2 value is not wildcarded, don't set it.
783 if ((!(conv->options & NO_PORT2)) || (conv->options & NO_PORT2_FORCE))
787 if (conv->options & NO_ADDR2) {
788 conversation_remove_from_hashtable(conversation_hashtable_no_addr2_or_port2, conv);
790 conversation_remove_from_hashtable(conversation_hashtable_no_port2, conv);
792 conv->options &= ~NO_PORT2;
793 conv->key_ptr->port2 = port;
794 if (conv->options & NO_ADDR2) {
795 conversation_insert_into_hashtable(conversation_hashtable_no_addr2, conv);
797 conversation_insert_into_hashtable(conversation_hashtable_exact, conv);
803 * Set the address 2 value in a key. Remove the original from
804 * table, update the options and port values, insert the updated key.
807 conversation_set_addr2(conversation_t *conv, const address *addr)
810 DISSECTOR_ASSERT_HINT(!(conv->options & CONVERSATION_TEMPLATE),
811 "Use the conversation_create_from_template function when the CONVERSATION_TEMPLATE bit is set in the options mask");
813 addr_str = address_to_str(NULL, addr);
814 DPRINT(("called for addr=%s", addr_str));
815 wmem_free(NULL, addr_str);
818 * If the address 2 value is not wildcarded, don't set it.
820 if (!(conv->options & NO_ADDR2))
824 if (conv->options & NO_PORT2) {
825 conversation_remove_from_hashtable(conversation_hashtable_no_addr2_or_port2, conv);
827 conversation_remove_from_hashtable(conversation_hashtable_no_port2, conv);
829 conv->options &= ~NO_ADDR2;
830 copy_address_wmem(wmem_file_scope(), &conv->key_ptr->addr2, addr);
831 if (conv->options & NO_PORT2) {
832 conversation_insert_into_hashtable(conversation_hashtable_no_port2, conv);
834 conversation_insert_into_hashtable(conversation_hashtable_exact, conv);
840 * Search a particular hash table for a conversation with the specified
841 * {addr1, port1, addr2, port2} and set up before frame_num.
843 static conversation_t *
844 conversation_lookup_hashtable(wmem_map_t *hashtable, const guint32 frame_num, const address *addr1, const address *addr2,
845 const endpoint_type etype, const guint32 port1, const guint32 port2)
847 conversation_t* convo=NULL;
848 conversation_t* match=NULL;
849 conversation_t* chain_head=NULL;
850 struct conversation_key key;
853 * We don't make a copy of the address data, we just copy the
854 * pointer to it, as "key" disappears when we return.
859 clear_address(&key.addr1);
864 clear_address(&key.addr2);
870 chain_head = (conversation_t *)wmem_map_lookup(hashtable, &key);
872 if (chain_head && (chain_head->setup_frame <= frame_num)) {
875 if ((chain_head->last)&&(chain_head->last->setup_frame<=frame_num))
876 return chain_head->last;
878 if ((chain_head->latest_found)&&(chain_head->latest_found->setup_frame<=frame_num))
879 match = chain_head->latest_found;
881 for (convo = match; convo && convo->setup_frame <= frame_num; convo = convo->next) {
882 if (convo->setup_frame > match->setup_frame) {
889 chain_head->latest_found = match;
896 * Given two address/port pairs for a packet, search for a conversation
897 * containing packets between those address/port pairs. Returns NULL if
900 * We try to find the most exact match that we can, and then proceed to
901 * try wildcard matches on the "addr_b" and/or "port_b" argument if a more
902 * exact match failed.
904 * Either or both of the "addr_b" and "port_b" arguments may be specified as
905 * a wildcard by setting the NO_ADDR_B or NO_PORT_B flags in the "options"
906 * argument. We do only wildcard matches on addresses and ports specified
911 * if neither "addr_b" nor "port_b" were specified as wildcards, we
912 * do an exact match (addr_a/port_a and addr_b/port_b) and, if that
913 * succeeds, we return a pointer to the matched conversation;
915 * otherwise, if "port_b" wasn't specified as a wildcard, we try to
916 * match any address 2 with the specified port 2 (addr_a/port_a and
917 * {any}/port_b) and, if that succeeds, we return a pointer to the
918 * matched conversation;
920 * otherwise, if "addr_b" wasn't specified as a wildcard, we try to
921 * match any port 2 with the specified address 2 (addr_a/port_a and
922 * addr_b/{any}) and, if that succeeds, we return a pointer to the
923 * matched conversation;
925 * otherwise, we try to match any address 2 and any port 2
926 * (addr_a/port_a and {any}/{any}) and, if that succeeds, we return
927 * a pointer to the matched conversation;
929 * otherwise, we found no matching conversation, and return NULL.
932 find_conversation(const guint32 frame_num, const address *addr_a, const address *addr_b, const endpoint_type etype,
933 const guint32 port_a, const guint32 port_b, const guint options)
935 conversation_t *conversation;
938 * First try an exact match, if we have two addresses and ports.
940 if (!(options & (NO_ADDR_B|NO_PORT_B))) {
942 * Neither search address B nor search port B are wildcarded,
943 * start out with an exact match.
945 DPRINT(("trying exact match: %s:%d -> %s:%d",
946 address_to_str(wmem_packet_scope(), addr_a), port_a,
947 address_to_str(wmem_packet_scope(), addr_b), port_b));
949 conversation_lookup_hashtable(conversation_hashtable_exact,
950 frame_num, addr_a, addr_b, etype,
952 /* Didn't work, try the other direction */
953 if (conversation == NULL) {
954 DPRINT(("trying exact match: %s:%d -> %s:%d",
955 address_to_str(wmem_packet_scope(), addr_b), port_b,
956 address_to_str(wmem_packet_scope(), addr_a), port_a));
958 conversation_lookup_hashtable(conversation_hashtable_exact,
959 frame_num, addr_b, addr_a, etype,
962 if ((conversation == NULL) && (addr_a->type == AT_FC)) {
963 /* In Fibre channel, OXID & RXID are never swapped as
964 * TCP/UDP ports are in TCP/IP.
966 DPRINT(("trying exact match: %s:%d -> %s:%d",
967 address_to_str(wmem_packet_scope(), addr_b), port_a,
968 address_to_str(wmem_packet_scope(), addr_a), port_b));
970 conversation_lookup_hashtable(conversation_hashtable_exact,
971 frame_num, addr_b, addr_a, etype,
974 DPRINT(("exact match %sfound",conversation?"":"not "));
975 if (conversation != NULL)
980 * Well, that didn't find anything. Try matches that wildcard
981 * one of the addresses, if we have two ports.
983 if (!(options & NO_PORT_B)) {
985 * Search port B isn't wildcarded.
987 * First try looking for a conversation with the specified
988 * address A and port A as the first address and port, and
989 * with any address and the specified port B as the second
991 * ("addr_b" doesn't take part in this lookup.)
993 DPRINT(("trying wildcarded match: %s:%d -> *:%d",
994 address_to_str(wmem_packet_scope(), addr_a), port_a,
997 conversation_lookup_hashtable(conversation_hashtable_no_addr2,
998 frame_num, addr_a, addr_b, etype, port_a, port_b);
999 if ((conversation == NULL) && (addr_a->type == AT_FC)) {
1000 /* In Fibre channel, OXID & RXID are never swapped as
1001 * TCP/UDP ports are in TCP/IP.
1003 DPRINT(("trying wildcarded match: %s:%d -> *:%d",
1004 address_to_str(wmem_packet_scope(), addr_b), port_a,
1007 conversation_lookup_hashtable(conversation_hashtable_no_addr2,
1008 frame_num, addr_b, addr_a, etype,
1011 if (conversation != NULL) {
1013 * If search address B isn't wildcarded, and this is for a
1014 * connection-oriented protocol, set the second address for this
1015 * conversation to address B, as that's the address that matched the
1016 * wildcarded second address for this conversation.
1018 * (This assumes that, for all connection oriented protocols, the
1019 * endpoints of a connection have only one address each, i.e. you
1020 * don't get packets in a given direction coming from more than one
1021 * address, unless the CONVERSATION_TEMPLATE option is set.)
1023 DPRINT(("wildcarded dest address match found"));
1024 if (!(conversation->options & NO_ADDR_B) && etype != ENDPOINT_UDP)
1026 if (!(conversation->options & CONVERSATION_TEMPLATE))
1028 conversation_set_addr2(conversation, addr_b);
1033 conversation_create_from_template(conversation, addr_b, 0);
1036 return conversation;
1040 * Well, that didn't find anything.
1041 * If search address B was specified, try looking for a
1042 * conversation with the specified address B and port B as
1043 * the first address and port, and with any address and the
1044 * specified port A as the second address and port (this
1045 * packet may be going in the opposite direction from the
1046 * first packet in the conversation).
1047 * ("addr_a" doesn't take part in this lookup.)
1049 if (!(options & NO_ADDR_B)) {
1050 DPRINT(("trying wildcarded match: %s:%d -> *:%d",
1051 address_to_str(wmem_packet_scope(), addr_b), port_b,
1054 conversation_lookup_hashtable(conversation_hashtable_no_addr2,
1055 frame_num, addr_b, addr_a, etype, port_b, port_a);
1056 if (conversation != NULL) {
1058 * If this is for a connection-oriented
1059 * protocol, set the second address for
1060 * this conversation to address A, as
1061 * that's the address that matched the
1062 * wildcarded second address for this
1065 DPRINT(("match found"));
1066 if (etype != ENDPOINT_UDP) {
1067 if (!(conversation->options & CONVERSATION_TEMPLATE))
1069 conversation_set_addr2(conversation, addr_a);
1074 conversation_create_from_template(conversation, addr_a, 0);
1077 return conversation;
1083 * Well, that didn't find anything. Try matches that wildcard
1084 * one of the ports, if we have two addresses.
1086 if (!(options & NO_ADDR_B)) {
1088 * Search address B isn't wildcarded.
1090 * First try looking for a conversation with the specified
1091 * address A and port A as the first address and port, and
1092 * with the specified address B and any port as the second
1094 * ("port_b" doesn't take part in this lookup.)
1096 DPRINT(("trying wildcarded match: %s:%d -> %s:*",
1097 address_to_str(wmem_packet_scope(), addr_a), port_a,
1098 address_to_str(wmem_packet_scope(), addr_b)));
1100 conversation_lookup_hashtable(conversation_hashtable_no_port2,
1101 frame_num, addr_a, addr_b, etype, port_a, port_b);
1102 if ((conversation == NULL) && (addr_a->type == AT_FC)) {
1103 /* In Fibre channel, OXID & RXID are never swapped as
1104 * TCP/UDP ports are in TCP/IP
1106 DPRINT(("trying wildcarded match: %s:%d -> %s:*",
1107 address_to_str(wmem_packet_scope(), addr_b), port_a,
1108 address_to_str(wmem_packet_scope(), addr_a)));
1110 conversation_lookup_hashtable(conversation_hashtable_no_port2,
1111 frame_num, addr_b, addr_a, etype, port_a, port_b);
1113 if (conversation != NULL) {
1115 * If search port B isn't wildcarded, and this is for a connection-
1116 * oriented protocol, set the second port for this conversation to
1117 * port B, as that's the port that matched the wildcarded second port
1118 * for this conversation.
1120 * (This assumes that, for all connection oriented protocols, the
1121 * endpoints of a connection have only one port each, i.e. you don't
1122 * get packets in a given direction coming from more than one port,
1123 * unless the CONVERSATION_TEMPLATE option is set.)
1125 DPRINT(("match found"));
1126 if (!(conversation->options & NO_PORT_B) && etype != ENDPOINT_UDP)
1128 if (!(conversation->options & CONVERSATION_TEMPLATE))
1130 conversation_set_port2(conversation, port_b);
1135 conversation_create_from_template(conversation, 0, port_b);
1138 return conversation;
1142 * Well, that didn't find anything.
1143 * If search port B was specified, try looking for a
1144 * conversation with the specified address B and port B
1145 * as the first address and port, and with the specified
1146 * address A and any port as the second address and port
1147 * (this packet may be going in the opposite direction
1148 * from the first packet in the conversation).
1149 * ("port_a" doesn't take part in this lookup.)
1151 if (!(options & NO_PORT_B)) {
1152 DPRINT(("trying wildcarded match: %s:%d -> %s:*",
1153 address_to_str(wmem_packet_scope(), addr_b), port_b,
1154 address_to_str(wmem_packet_scope(), addr_a)));
1156 conversation_lookup_hashtable(conversation_hashtable_no_port2,
1157 frame_num, addr_b, addr_a, etype, port_b, port_a);
1158 if (conversation != NULL) {
1160 * If this is for a connection-oriented
1161 * protocol, set the second port for
1162 * this conversation to port A, as
1163 * that's the address that matched the
1164 * wildcarded second address for this
1167 DPRINT(("match found"));
1168 if (etype != ENDPOINT_UDP)
1170 if (!(conversation->options & CONVERSATION_TEMPLATE))
1172 conversation_set_port2(conversation, port_a);
1177 conversation_create_from_template(conversation, 0, port_a);
1180 return conversation;
1186 * Well, that didn't find anything. Try matches that wildcard
1187 * one address/port pair.
1189 * First try looking for a conversation with the specified address A
1190 * and port A as the first address and port.
1191 * (Neither "addr_b" nor "port_b" take part in this lookup.)
1193 DPRINT(("trying wildcarded match: %s:%d -> *:*",
1194 address_to_str(wmem_packet_scope(), addr_a), port_a));
1196 conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2,
1197 frame_num, addr_a, addr_b, etype, port_a, port_b);
1198 if (conversation != NULL) {
1200 * If this is for a connection-oriented protocol:
1202 * if search address B isn't wildcarded, set the
1203 * second address for this conversation to address
1204 * B, as that's the address that matched the
1205 * wildcarded second address for this conversation;
1207 * if search port B isn't wildcarded, set the
1208 * second port for this conversation to port B,
1209 * as that's the port that matched the wildcarded
1210 * second port for this conversation.
1212 DPRINT(("match found"));
1213 if (etype != ENDPOINT_UDP)
1215 if (!(conversation->options & CONVERSATION_TEMPLATE))
1217 if (!(conversation->options & NO_ADDR_B))
1218 conversation_set_addr2(conversation, addr_b);
1219 if (!(conversation->options & NO_PORT_B))
1220 conversation_set_port2(conversation, port_b);
1225 conversation_create_from_template(conversation, addr_b, port_b);
1228 return conversation;
1230 /* for Infiniband, don't try to look in addresses of reverse
1231 * direction, because it could be another different
1232 * valid conversation than what is being searched using
1235 if (etype != ENDPOINT_IBQP)
1239 * Well, that didn't find anything.
1240 * If search address and port B were specified, try looking for a
1241 * conversation with the specified address B and port B as the
1242 * first address and port, and with any second address and port
1243 * (this packet may be going in the opposite direction from the
1244 * first packet in the conversation).
1245 * (Neither "addr_a" nor "port_a" take part in this lookup.)
1247 if ((addr_a != NULL) && (addr_a->type == AT_FC)) {
1248 DPRINT(("trying wildcarded match: %s:%d -> *:*",
1249 address_to_str(wmem_packet_scope(), addr_b), port_a));
1251 conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2,
1252 frame_num, addr_b, addr_a, etype, port_a, port_b);
1254 DPRINT(("trying wildcarded match: %s:%d -> *:*",
1255 address_to_str(wmem_packet_scope(), addr_b), port_b));
1257 conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2,
1258 frame_num, addr_b, addr_a, etype, port_b, port_a);
1260 if (conversation != NULL) {
1262 * If this is for a connection-oriented protocol, set the
1263 * second address for this conversation to address A, as
1264 * that's the address that matched the wildcarded second
1265 * address for this conversation, and set the second port
1266 * for this conversation to port A, as that's the port
1267 * that matched the wildcarded second port for this
1270 DPRINT(("match found"));
1271 if (etype != ENDPOINT_UDP)
1273 if (!(conversation->options & CONVERSATION_TEMPLATE))
1275 conversation_set_addr2(conversation, addr_a);
1276 conversation_set_port2(conversation, port_a);
1280 conversation = conversation_create_from_template(conversation, addr_a, port_a);
1283 return conversation;
1286 DPRINT(("no matches found"));
1289 * We found no conversation.
1294 conversation_t *find_conversation_by_id(const guint32 frame, const endpoint_type etype, const guint32 id, const guint options)
1296 /* Force the lack of a address or port B */
1297 return find_conversation(frame, &null_address_, &null_address_, etype, id, 0, options|NO_ADDR_B|NO_PORT_B);
1301 conversation_add_proto_data(conversation_t *conv, const int proto, void *proto_data)
1303 /* Add it to the list of items for this conversation. */
1304 if (conv->data_list == NULL)
1305 conv->data_list = wmem_tree_new(wmem_file_scope());
1307 wmem_tree_insert32(conv->data_list, proto, proto_data);
1311 conversation_get_proto_data(const conversation_t *conv, const int proto)
1313 /* No tree created yet */
1314 if (conv->data_list == NULL)
1317 return wmem_tree_lookup32(conv->data_list, proto);
1321 conversation_delete_proto_data(conversation_t *conv, const int proto)
1323 if (conv->data_list != NULL)
1324 wmem_tree_remove32(conv->data_list, proto);
1328 conversation_set_dissector_from_frame_number(conversation_t *conversation,
1329 const guint32 starting_frame_num, const dissector_handle_t handle)
1331 wmem_tree_insert32(conversation->dissector_tree, starting_frame_num, (void *)handle);
1335 conversation_set_dissector(conversation_t *conversation, const dissector_handle_t handle)
1337 conversation_set_dissector_from_frame_number(conversation, 0, handle);
1341 conversation_get_dissector(conversation_t *conversation, const guint32 frame_num)
1343 return (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, frame_num);
1346 static gboolean try_conversation_call_dissector_helper(conversation_t *conversation, gboolean* dissector_success,
1347 tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1350 dissector_handle_t handle = (dissector_handle_t)wmem_tree_lookup32_le(
1351 conversation->dissector_tree, pinfo->num);
1355 ret = call_dissector_only(handle, tvb, pinfo, tree, data);
1357 /* Let the caller decide what to do with success or rejection */
1358 (*dissector_success) = (ret != 0);
1364 * Given two address/port pairs for a packet, search for a matching
1365 * conversation and, if found and it has a conversation dissector,
1366 * call that dissector and return TRUE, otherwise return FALSE.
1368 * This helper uses call_dissector_only which will NOT call the default
1369 * "data" dissector if the packet was rejected.
1370 * Our caller is responsible to call the data dissector explicitly in case
1371 * this function returns FALSE.
1374 try_conversation_dissector(const address *addr_a, const address *addr_b, const endpoint_type etype,
1375 const guint32 port_a, const guint32 port_b, tvbuff_t *tvb, packet_info *pinfo,
1376 proto_tree *tree, void* data, const guint options)
1378 conversation_t *conversation;
1379 gboolean dissector_success;
1381 /* Try each mode based on option flags */
1383 conversation = find_conversation(pinfo->num, addr_a, addr_b, etype, port_a, port_b, 0);
1384 if (conversation != NULL) {
1385 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
1386 return dissector_success;
1389 if (options & NO_ADDR_B) {
1390 conversation = find_conversation(pinfo->num, addr_a, addr_b, etype, port_a, port_b, NO_ADDR_B);
1391 if (conversation != NULL) {
1392 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
1393 return dissector_success;
1397 if (options & NO_PORT_B) {
1398 conversation = find_conversation(pinfo->num, addr_a, addr_b, etype, port_a, port_b, NO_PORT_B);
1399 if (conversation != NULL) {
1400 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
1401 return dissector_success;
1405 if (options & (NO_ADDR_B|NO_PORT_B)) {
1406 conversation = find_conversation(pinfo->num, addr_a, addr_b, etype, port_a, port_b, NO_ADDR_B|NO_PORT_B);
1407 if (conversation != NULL) {
1408 if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data))
1409 return dissector_success;
1417 try_conversation_dissector_by_id(const endpoint_type etype, const guint32 id, tvbuff_t *tvb,
1418 packet_info *pinfo, proto_tree *tree, void* data)
1420 conversation_t *conversation;
1422 conversation = find_conversation_by_id(pinfo->num, etype, id, 0);
1424 if (conversation != NULL) {
1427 dissector_handle_t handle = (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, pinfo->num);
1430 ret = call_dissector_only(handle, tvb, pinfo, tree, data);
1432 /* this packet was rejected by the dissector
1433 * so return FALSE in case our caller wants
1434 * to do some cleaning up.
1443 /** A helper function that calls find_conversation() using data from pinfo
1444 * The frame number and addresses are taken from pinfo.
1447 find_conversation_pinfo(packet_info *pinfo, const guint options)
1449 conversation_t *conv=NULL;
1451 DPRINT(("called for frame #%u: %s:%d -> %s:%d (ptype=%d)",
1452 pinfo->num, address_to_str(wmem_packet_scope(), &pinfo->src), pinfo->srcport,
1453 address_to_str(wmem_packet_scope(), &pinfo->dst), pinfo->destport, pinfo->ptype));
1456 /* Have we seen this conversation before? */
1457 if (pinfo->use_endpoint) {
1458 DISSECTOR_ASSERT(pinfo->conv_endpoint);
1459 if ((conv = find_conversation(pinfo->num, &pinfo->conv_endpoint->addr1, &pinfo->conv_endpoint->addr2,
1460 pinfo->conv_endpoint->etype, pinfo->conv_endpoint->port1,
1461 pinfo->conv_endpoint->port2, pinfo->conv_endpoint->options)) != NULL) {
1462 DPRINT(("found previous conversation for frame #%u (last_frame=%d)",
1463 pinfo->num, conv->last_frame));
1464 if (pinfo->num > conv->last_frame) {
1465 conv->last_frame = pinfo->num;
1469 if ((conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
1470 conversation_pt_to_endpoint_type(pinfo->ptype), pinfo->srcport,
1471 pinfo->destport, options)) != NULL) {
1472 DPRINT(("found previous conversation for frame #%u (last_frame=%d)",
1473 pinfo->num, conv->last_frame));
1474 if (pinfo->num > conv->last_frame) {
1475 conv->last_frame = pinfo->num;
1483 /* A helper function that calls find_conversation() and, if a conversation is
1484 * not found, calls conversation_new().
1485 * The frame number and addresses are taken from pinfo.
1486 * No options are used, though we could extend this API to include an options
1490 find_or_create_conversation(packet_info *pinfo)
1492 conversation_t *conv=NULL;
1494 /* Have we seen this conversation before? */
1495 if ((conv = find_conversation_pinfo(pinfo, 0)) == NULL) {
1496 /* No, this is a new conversation. */
1497 DPRINT(("did not find previous conversation for frame #%u",
1500 conv = conversation_new(pinfo->num, &pinfo->src,
1501 &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype),
1502 pinfo->srcport, pinfo->destport, 0);
1512 find_or_create_conversation_by_id(packet_info *pinfo, const endpoint_type etype, const guint32 id)
1514 conversation_t *conv=NULL;
1516 /* Have we seen this conversation before? */
1517 if ((conv = find_conversation_by_id(pinfo->num, etype, id, 0)) == NULL) {
1518 /* No, this is a new conversation. */
1519 DPRINT(("did not find previous conversation for frame #%u",
1522 conv = conversation_new_by_id(pinfo->num, etype, id, 0);
1531 void conversation_create_endpoint(struct _packet_info *pinfo, address* addr1, address* addr2,
1532 endpoint_type etype, guint32 port1, guint32 port2, const guint options)
1534 pinfo->conv_endpoint = wmem_new0(pinfo->pool, struct endpoint);
1535 pinfo->use_endpoint = TRUE;
1538 copy_address_wmem(pinfo->pool, &pinfo->conv_endpoint->addr1, addr1);
1541 copy_address_wmem(pinfo->pool, &pinfo->conv_endpoint->addr2, addr2);
1543 pinfo->conv_endpoint->etype = etype;
1544 pinfo->conv_endpoint->port1 = port1;
1545 pinfo->conv_endpoint->port2 = port2;
1546 pinfo->conv_endpoint->options = options;
1549 void conversation_create_endpoint_by_id(struct _packet_info *pinfo,
1550 endpoint_type etype, guint32 id, const guint options)
1552 /* Force the lack of a address or port B */
1553 conversation_create_endpoint(pinfo, &null_address_, &null_address_, etype, id, 0, options|NO_ADDR_B|NO_PORT_B);
1556 guint32 conversation_get_endpoint_by_id(struct _packet_info *pinfo, endpoint_type etype, const guint options)
1558 if (pinfo->conv_endpoint == NULL)
1561 if ((pinfo->conv_endpoint->etype != etype) &&
1562 ((options & USE_LAST_ENDPOINT) != USE_LAST_ENDPOINT))
1565 return pinfo->conv_endpoint->port1;
1569 get_conversation_hashtable_exact(void)
1571 return conversation_hashtable_exact;
1575 get_conversation_hashtable_no_addr2(void)
1577 return conversation_hashtable_no_addr2;
1581 get_conversation_hashtable_no_port2(void)
1583 return conversation_hashtable_no_port2;
1587 get_conversation_hashtable_no_addr2_or_port2(void)
1589 return conversation_hashtable_no_addr2_or_port2;
1593 conversation_key_addr1(const conversation_key_t key)
1599 conversation_key_addr2(const conversation_key_t key)
1605 conversation_key_port1(const conversation_key_t key)
1611 conversation_key_port2(const conversation_key_t key)
1617 endpoint_type conversation_pt_to_endpoint_type(port_type pt)
1622 return ENDPOINT_NONE;
1624 return ENDPOINT_SCTP;
1626 return ENDPOINT_TCP;
1628 return ENDPOINT_UDP;
1630 return ENDPOINT_DCCP;
1632 return ENDPOINT_IPX;
1634 return ENDPOINT_DDP;
1636 return ENDPOINT_IDP;
1638 return ENDPOINT_USB;
1640 return ENDPOINT_I2C;
1642 return ENDPOINT_IBQP;
1644 return ENDPOINT_BLUETOOTH;
1647 DISSECTOR_ASSERT(FALSE);
1648 return ENDPOINT_NONE;
1652 conversation_get_html_hash(const conversation_key_t key)
1654 gchar *hash, *addr1, *addr2;
1656 addr1 = address_to_str(NULL, &key->addr1);
1657 addr2 = address_to_str(NULL, &key->addr2);
1658 hash = wmem_strdup_printf(NULL, "<tr><td>%s</td><td>%d</td><td>%s</td><td>%d</td></tr>\n",
1659 addr1, key->port1, addr2, key->port2);
1660 wmem_free(NULL, addr1);
1661 wmem_free(NULL, addr2);
1667 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1672 * indent-tabs-mode: t
1675 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1676 * :indentSize=8:tabSize=8:noTabs=false: