use DISSECTOR_ASSERT instead of g_assert
[obnox/wireshark/wip.git] / epan / conversation.c
1 /* conversation.c
2  * Routines for building lists of packets that are part of a "conversation"
3  *
4  * $Id$
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <stdio.h>
30
31 #include <string.h>
32 #include <glib.h>
33 #include "packet.h"
34 #include "conversation.h"
35
36 /*
37  * Hash table for conversations with no wildcards.
38  */
39 static GHashTable *conversation_hashtable_exact = NULL;
40
41 /*
42  * Hash table for conversations with one wildcard address.
43  */
44 static GHashTable *conversation_hashtable_no_addr2 = NULL;
45
46 /*
47  * Hash table for conversations with one wildcard port.
48  */
49 static GHashTable *conversation_hashtable_no_port2 = NULL;
50
51 /*
52  * Hash table for conversations with one wildcard address and port.
53  */
54 static GHashTable *conversation_hashtable_no_addr2_or_port2 = NULL;
55
56 static GMemChunk *conversation_key_chunk = NULL;
57 static GMemChunk *conversation_chunk = NULL;
58
59 #ifdef __NOT_USED__
60 typedef struct conversation_key {
61         struct conversation_key *next;
62         address addr1;
63         address addr2;
64         port_type ptype;
65         guint32 port1;
66         guint32 port2;
67 } conversation_key;
68 #endif
69 /*
70  * Linked list of conversation keys, so we can, before freeing them all,
71  * free the address data allocations associated with them.
72  */
73 static conversation_key *conversation_keys;
74
75 static guint32 new_index;
76
77 static int conversation_init_count = 200;
78
79 /*
80  * Protocol-specific data attached to a conversation_t structure - protocol
81  * index and opaque pointer.
82  */
83 typedef struct _conv_proto_data {
84         int     proto;
85         void    *proto_data;
86 } conv_proto_data;
87
88 static GMemChunk *conv_proto_data_area = NULL;
89
90 /*
91  * Creates a new conversation with known endpoints based on a conversation
92  * created with the CONVERSATION_TEMPLATE option while keeping the
93  * conversation created with the CONVERSATION_TEMPLATE option so it can still
94  * match future connections.
95  *
96  * Passing a pointer to a conversation whose options mask does not include
97  * CONVERSATION_TEMPLATE or where the conversation's protocol type (ptype)
98  * indicates a non-connnection oriented protocol will return the conversation
99  * without changes.
100  *
101  * addr2 and port2 are used in the function if their respective conversation
102  * options bits are set (NO_ADDR2 and NO_PORT2).
103  */
104 conversation_t *
105 conversation_create_from_template(conversation_t *conversation, address *addr2, guint32 port2)
106 {
107    /*
108     * Add a new conversation and keep the conversation template only if the
109     * CONVERSATION_TEMPLATE bit is set for a connection oriented protocol.
110     */
111    if(conversation->options & CONVERSATION_TEMPLATE &&
112       conversation->key_ptr->ptype != PT_UDP)
113    {
114       /*
115        * Set up a new options mask where the conversation template bit and the
116        * bits for absence of a second address and port pair have been removed.
117        */
118       conversation_t *new_conversation_from_template;
119       guint options = conversation->options & ~(CONVERSATION_TEMPLATE | NO_ADDR2 | NO_PORT2);
120
121       /*
122        * Are both the NO_ADDR2 and NO_PORT2 wildcards set in the options mask?
123        */
124       if(conversation->options & NO_ADDR2 &&
125          conversation->options & NO_PORT2)
126       {
127          /*
128           * The conversation template was created without knowledge of both
129           * the second address as well as the second port. Create a new
130           * conversation with new 2nd address and 2nd port.
131           */
132          new_conversation_from_template =
133             conversation_new(conversation->setup_frame,
134                              &conversation->key_ptr->addr1, addr2,
135                              conversation->key_ptr->ptype, conversation->key_ptr->port1,
136                              port2, options);
137       }
138       else if(conversation->options & NO_PORT2)
139       {
140          /*
141           * The conversation template was created without knowledge of port 2
142           * only. Create a new conversation with new 2nd port.
143           */
144          new_conversation_from_template =
145             conversation_new(conversation->setup_frame,
146                              &conversation->key_ptr->addr1, &conversation->key_ptr->addr2,
147                              conversation->key_ptr->ptype, conversation->key_ptr->port1,
148                              port2, options);
149       }
150       else if(conversation->options & NO_ADDR2)
151       {
152          /*
153           * The conversation template was created without knowledge of address
154           * 2. Create a new conversation with new 2nd address.
155           */
156          new_conversation_from_template =
157             conversation_new(conversation->setup_frame,
158                              &conversation->key_ptr->addr1, addr2,
159                              conversation->key_ptr->ptype, conversation->key_ptr->port1,
160                              conversation->key_ptr->port2, options);
161       }
162       else
163       {
164          /*
165           * The CONVERSATION_TEMPLATE bit was set, but no other bit that the
166           * CONVERSATION_TEMPLATE bit controls is active. Just return the old
167           * conversation.
168           */
169          return conversation;
170       }
171
172       /*
173        * Set the protocol dissector used for the template conversation as
174        * the handler of the new conversation as well.
175        */
176       new_conversation_from_template->dissector_handle = conversation->dissector_handle;
177
178       return new_conversation_from_template;
179    }
180    else
181    {
182       return conversation;
183    }
184 }
185
186 /*
187  * Compute the hash value for two given address/port pairs if the match
188  * is to be exact.
189  */
190 static guint
191 conversation_hash_exact(gconstpointer v)
192 {
193         const conversation_key *key = (const conversation_key *)v;
194         guint hash_val;
195         int i;
196
197         hash_val = 0;
198         for (i = 0; i < key->addr1.len; i++)
199                 hash_val += key->addr1.data[i];
200
201         hash_val += key->port1;
202
203         for (i = 0; i < key->addr2.len; i++)
204                 hash_val += key->addr2.data[i];
205
206         hash_val += key->port2;
207
208         return hash_val;
209 }
210
211 /*
212  * Compare two conversation keys for an exact match.
213  */
214 static gint
215 conversation_match_exact(gconstpointer v, gconstpointer w)
216 {
217         const conversation_key *v1 = (const conversation_key *)v;
218         const conversation_key *v2 = (const conversation_key *)w;
219
220         if (v1->ptype != v2->ptype)
221                 return 0;       /* different types of port */
222
223         /*
224          * Are the first and second port 1 values the same, the first and
225          * second port 2 values the same, the first and second address
226          * 1 values the same, and the first and second address 2 values
227          * the same?
228          */
229         if (v1->port1 == v2->port1 &&
230             v1->port2 == v2->port2 &&
231             ADDRESSES_EQUAL(&v1->addr1, &v2->addr1) &&
232             ADDRESSES_EQUAL(&v1->addr2, &v2->addr2)) {
233                 /*
234                  * Yes.  It's the same conversation, and the two
235                  * address/port pairs are going in the same direction.
236                  */
237                 return 1;
238         }
239
240         /*
241          * Is the first port 2 the same as the second port 1, the first
242          * port 1 the same as the second port 2, the first address 2
243          * the same as the second address 1, and the first address 1
244          * the same as the second address 2?
245          */
246         if (v1->port2 == v2->port1 &&
247             v1->port1 == v2->port2 &&
248             ADDRESSES_EQUAL(&v1->addr2, &v2->addr1) &&
249             ADDRESSES_EQUAL(&v1->addr1, &v2->addr2)) {
250                 /*
251                  * Yes.  It's the same conversation, and the two
252                  * address/port pairs are going in opposite directions.
253                  */
254                 return 1;
255         }
256
257         /*
258          * The addresses or the ports don't match.
259          */
260         return 0;
261 }
262
263 /*
264  * Compute the hash value for two given address/port pairs if the match
265  * has a wildcard address 2.
266  */
267 static guint
268 conversation_hash_no_addr2(gconstpointer v)
269 {
270         const conversation_key *key = (const conversation_key *)v;
271         guint hash_val;
272         int i;
273
274         hash_val = 0;
275         for (i = 0; i < key->addr1.len; i++)
276                 hash_val += key->addr1.data[i];
277
278         hash_val += key->port1;
279
280         hash_val += key->port2;
281
282         return hash_val;
283 }
284
285 /*
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.
290  */
291 static gint
292 conversation_match_no_addr2(gconstpointer v, gconstpointer w)
293 {
294         const conversation_key *v1 = (const conversation_key *)v;
295         const conversation_key *v2 = (const conversation_key *)w;
296
297         if (v1->ptype != v2->ptype)
298                 return 0;       /* different types of port */
299
300         /*
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?
304          */
305         if (v1->port1 == v2->port1 &&
306             v1->port2 == v2->port2 &&
307             ADDRESSES_EQUAL(&v1->addr1, &v2->addr1)) {
308                 /*
309                  * Yes.  It's the same conversation, and the two
310                  * address/port pairs are going in the same direction.
311                  */
312                 return 1;
313         }
314
315         /*
316          * The addresses or the ports don't match.
317          */
318         return 0;
319 }
320
321 /*
322  * Compute the hash value for two given address/port pairs if the match
323  * has a wildcard port 2.
324  */
325 static guint
326 conversation_hash_no_port2(gconstpointer v)
327 {
328         const conversation_key *key = (const conversation_key *)v;
329         guint hash_val;
330         int i;
331
332         hash_val = 0;
333         for (i = 0; i < key->addr1.len; i++)
334                 hash_val += key->addr1.data[i];
335
336         hash_val += key->port1;
337
338         for (i = 0; i < key->addr2.len; i++)
339                 hash_val += key->addr2.data[i];
340
341         return hash_val;
342 }
343
344 /*
345  * Compare two conversation keys, except for the port 2 value.
346  * We don't check both directions of the conversation - the routine
347  * doing the hash lookup has to do two searches, as the hash key
348  * will be different for the two directions.
349  */
350 static gint
351 conversation_match_no_port2(gconstpointer v, gconstpointer w)
352 {
353         const conversation_key *v1 = (const conversation_key *)v;
354         const conversation_key *v2 = (const conversation_key *)w;
355
356         if (v1->ptype != v2->ptype)
357                 return 0;       /* different types of port */
358
359         /*
360          * Are the first and second port 1 values the same, the first and
361          * second address 1 values the same, and the first and second
362          * address 2 values the same?
363          */
364         if (v1->port1 == v2->port1 &&
365             ADDRESSES_EQUAL(&v1->addr1, &v2->addr1) &&
366             ADDRESSES_EQUAL(&v1->addr2, &v2->addr2)) {
367                 /*
368                  * Yes.  It's the same conversation, and the two
369                  * address/port pairs are going in the same direction.
370                  */
371                 return 1;
372         }
373
374         /*
375          * The addresses or the ports don't match.
376          */
377         return 0;
378 }
379
380 /*
381  * Compute the hash value for two given address/port pairs if the match
382  * has a wildcard address 2 and port 2.
383  */
384 static guint
385 conversation_hash_no_addr2_or_port2(gconstpointer v)
386 {
387         const conversation_key *key = (const conversation_key *)v;
388         guint hash_val;
389         int i;
390
391         hash_val = 0;
392         for (i = 0; i < key->addr1.len; i++)
393                 hash_val += key->addr1.data[i];
394
395         hash_val += key->port1;
396
397         return hash_val;
398 }
399
400 /*
401  * Compare the address 1 and port 1 in the two conversation keys.
402  * We don't check both directions of the conversation - the routine
403  * doing the hash lookup has to do two searches, as the hash key
404  * will be different for the two directions.
405  */
406 static gint
407 conversation_match_no_addr2_or_port2(gconstpointer v, gconstpointer w)
408 {
409         const conversation_key *v1 = (const conversation_key *)v;
410         const conversation_key *v2 = (const conversation_key *)w;
411
412         if (v1->ptype != v2->ptype)
413                 return 0;       /* different types of port */
414
415         /*
416          * Are the first and second port 1 values the same and the first
417          * and second address 1 values the same?
418          */
419         if (v1->port1 == v2->port1 &&
420             ADDRESSES_EQUAL(&v1->addr1, &v2->addr1)) {
421                 /*
422                  * Yes.  It's the same conversation, and the two
423                  * address/port pairs are going in the same direction.
424                  */
425                 return 1;
426         }
427
428         /*
429          * The addresses or the ports don't match.
430          */
431         return 0;
432 }
433
434 /*
435  * Initialize some variables every time a file is loaded or re-loaded.
436  * Destroy all existing conversations, and create a new hash table
437  * for the conversations in the new file.
438  */
439 void
440 conversation_init(void)
441 {
442         conversation_key *key;
443
444         /*
445          * Free the addresses associated with the conversation keys.
446          */
447         for (key = conversation_keys; key != NULL; key = key->next) {
448                 /*
449                  * Grr.  I guess the theory here is that freeing
450                  * something sure as heck modifies it, so you
451                  * want to ban attempts to free it, but, alas,
452                  * if we make the "data" field of an "address"
453                  * structure not a "const", the compiler whines if
454                  * we try to make it point into the data for a packet,
455                  * as that's a "const" array (and should be, as dissectors
456                  * shouldn't trash it).
457                  *
458                  * So we cast the complaint into oblivion, and rely on
459                  * the fact that these addresses are known to have had
460                  * their data mallocated, i.e. they don't point into,
461                  * say, the middle of the data for a packet.
462                  */
463                 g_free((gpointer)key->addr1.data);
464                 g_free((gpointer)key->addr2.data);
465         }
466         conversation_keys = NULL;
467         if (conversation_hashtable_exact != NULL)
468                 g_hash_table_destroy(conversation_hashtable_exact);
469         if (conversation_hashtable_no_addr2 != NULL)
470                 g_hash_table_destroy(conversation_hashtable_no_addr2);
471         if (conversation_hashtable_no_port2 != NULL)
472                 g_hash_table_destroy(conversation_hashtable_no_port2);
473         if (conversation_hashtable_no_addr2_or_port2 != NULL)
474                 g_hash_table_destroy(conversation_hashtable_no_addr2_or_port2);
475         if (conversation_key_chunk != NULL)
476                 g_mem_chunk_destroy(conversation_key_chunk);
477         if (conversation_chunk != NULL)
478                 g_mem_chunk_destroy(conversation_chunk);
479
480         /*
481          * Free up any space allocated for conversation protocol data
482          * areas.
483          *
484          * We can free the space, as the structures it contains are
485          * pointed to by conversation data structures that were freed
486          * above.
487          */
488         if (conv_proto_data_area != NULL)
489                 g_mem_chunk_destroy(conv_proto_data_area);
490
491         conversation_hashtable_exact =
492             g_hash_table_new(conversation_hash_exact,
493               conversation_match_exact);
494         conversation_hashtable_no_addr2 =
495             g_hash_table_new(conversation_hash_no_addr2,
496               conversation_match_no_addr2);
497         conversation_hashtable_no_port2 =
498             g_hash_table_new(conversation_hash_no_port2,
499               conversation_match_no_port2);
500         conversation_hashtable_no_addr2_or_port2 =
501             g_hash_table_new(conversation_hash_no_addr2_or_port2,
502               conversation_match_no_addr2_or_port2);
503         conversation_key_chunk = g_mem_chunk_new("conversation_key_chunk",
504             sizeof(conversation_key),
505             conversation_init_count * sizeof(struct conversation_key),
506             G_ALLOC_AND_FREE);
507         conversation_chunk = g_mem_chunk_new("conversation_chunk",
508             sizeof(conversation_t),
509             conversation_init_count * sizeof(conversation_t),
510             G_ALLOC_AND_FREE);
511
512         /*
513          * Allocate a new area for conversation protocol data items.
514          */
515         conv_proto_data_area = g_mem_chunk_new("conv_proto_data_area",
516             sizeof(conv_proto_data), 20 * sizeof(conv_proto_data), /* FIXME*/
517             G_ALLOC_ONLY);
518
519         /*
520          * Start the conversation indices over at 0.
521          */
522         new_index = 0;
523 }
524
525 /*
526  * Given two address/port pairs for a packet, create a new conversation
527  * to contain packets between those address/port pairs.
528  *
529  * The options field is used to specify whether the address 2 value
530  * and/or port 2 value are not given and any value is acceptable
531  * when searching for this conversation.
532  */
533 conversation_t *
534 conversation_new(guint32 setup_frame, address *addr1, address *addr2, port_type ptype,
535     guint32 port1, guint32 port2, guint options)
536 {
537 /*
538         DISSECTOR_ASSERT(!(options | CONVERSATION_TEMPLATE) || ((options | (NO_ADDR2 | NO_PORT2 | NO_PORT2_FORCE))) &&
539                                 "A conversation template may not be constructed without wildcard options");
540 */
541         GHashTable* hashtable;
542         conversation_t *conversation;
543         conversation_t *tc;
544         conversation_key existing_key;
545         conversation_key *new_key;
546
547         if (options & NO_ADDR2) {
548                 if (options & (NO_PORT2|NO_PORT2_FORCE)) {
549                         hashtable = conversation_hashtable_no_addr2_or_port2;
550                 } else {
551                         hashtable = conversation_hashtable_no_addr2;
552                 }
553         } else {
554                 if (options & (NO_PORT2|NO_PORT2_FORCE)) {
555                         hashtable = conversation_hashtable_no_port2;
556                 } else {
557                         hashtable = conversation_hashtable_exact;
558                 }
559         }
560
561         existing_key.addr1 = *addr1;
562         existing_key.addr2 = *addr2;
563         existing_key.ptype = ptype;
564         existing_key.port1 = port1;
565         existing_key.port2 = port2;
566
567         conversation = g_hash_table_lookup(hashtable, &existing_key);
568         tc = conversation; /* Remember if lookup was successful */
569
570         new_key = g_mem_chunk_alloc(conversation_key_chunk);
571         new_key->next = conversation_keys;
572         conversation_keys = new_key;
573         COPY_ADDRESS(&new_key->addr1, addr1);
574         COPY_ADDRESS(&new_key->addr2, addr2);
575         new_key->ptype = ptype;
576         new_key->port1 = port1;
577         new_key->port2 = port2;
578
579         if (conversation) {
580                 for (; conversation->next; conversation = conversation->next)
581                         ;
582                 conversation->next = g_mem_chunk_alloc(conversation_chunk);
583                 conversation = conversation->next;
584         } else {
585                 conversation = g_mem_chunk_alloc(conversation_chunk);
586         }
587
588         conversation->next = NULL;
589         conversation->index = new_index;
590         conversation->setup_frame = setup_frame;
591         conversation->data_list = NULL;
592
593         /* clear dissector handle */
594         conversation->dissector_handle = NULL;
595
596         /* set the options and key pointer */
597         conversation->options = options;
598         conversation->key_ptr = new_key;
599
600         new_index++;
601
602         /* only insert a hash table entry if this
603          * is the first conversation with this key */
604         if (!tc)
605                 g_hash_table_insert(hashtable, new_key, conversation);
606
607         return conversation;
608 }
609
610 /*
611  * Set the port 2 value in a key.  Remove the original from table,
612  * update the options and port values, insert the updated key.
613  */
614 void
615 conversation_set_port2(conversation_t *conv, guint32 port)
616 {
617    DISSECTOR_ASSERT(!(conv->options & CONVERSATION_TEMPLATE) &&
618             "Use the conversation_create_from_template function when the CONVERSATION_TEMPLATE bit is set in the options mask");
619
620         /*
621          * If the port 2 value is not wildcarded, don't set it.
622          */
623         if ((!(conv->options & NO_PORT2)) || (conv->options & NO_PORT2_FORCE))
624                 return;
625
626         if (conv->options & NO_ADDR2) {
627                 g_hash_table_remove(conversation_hashtable_no_addr2_or_port2,
628                     conv->key_ptr);
629         } else {
630                 g_hash_table_remove(conversation_hashtable_no_port2,
631                     conv->key_ptr);
632         }
633         conv->options &= ~NO_PORT2;
634         conv->key_ptr->port2  = port;
635         if (conv->options & NO_ADDR2) {
636                 g_hash_table_insert(conversation_hashtable_no_addr2,
637                     conv->key_ptr, conv);
638         } else {
639                 g_hash_table_insert(conversation_hashtable_exact,
640                     conv->key_ptr, conv);
641         }
642 }
643
644 /*
645  * Set the address 2 value in a key.  Remove the original from
646  * table, update the options and port values, insert the updated key.
647  */
648 void
649 conversation_set_addr2(conversation_t *conv, address *addr)
650 {
651    DISSECTOR_ASSERT(!(conv->options & CONVERSATION_TEMPLATE) &&
652             "Use the conversation_create_from_template function when the CONVERSATION_TEMPLATE bit is set in the options mask");
653    
654         /*
655          * If the address 2 value is not wildcarded, don't set it.
656          */
657         if (!(conv->options & NO_ADDR2))
658                 return;
659
660         if (conv->options & NO_PORT2) {
661                 g_hash_table_remove(conversation_hashtable_no_addr2_or_port2,
662                     conv->key_ptr);
663         } else {
664                 g_hash_table_remove(conversation_hashtable_no_addr2,
665                     conv->key_ptr);
666         }
667         conv->options &= ~NO_ADDR2;
668         COPY_ADDRESS(&conv->key_ptr->addr2, addr);
669         if (conv->options & NO_PORT2) {
670                 g_hash_table_insert(conversation_hashtable_no_port2,
671                     conv->key_ptr, conv);
672         } else {
673                 g_hash_table_insert(conversation_hashtable_exact,
674                     conv->key_ptr, conv);
675         }
676 }
677
678 /*
679  * Search a particular hash table for a conversaton with the specified
680  * addr1, port1, addr2, and port2.
681  */
682 static conversation_t *
683 conversation_lookup_hashtable(GHashTable *hashtable, guint32 frame_num, address *addr1, address *addr2,
684     port_type ptype, guint32 port1, guint32 port2)
685 {
686         conversation_t* conversation;
687         conversation_t* match;
688         conversation_key key;
689
690         /*
691          * We don't make a copy of the address data, we just copy the
692          * pointer to it, as "key" disappears when we return.
693          */
694         key.addr1 = *addr1;
695         key.addr2 = *addr2;
696         key.ptype = ptype;
697         key.port1 = port1;
698         key.port2 = port2;
699
700         match = g_hash_table_lookup(hashtable, &key);
701
702         if (match) {
703                 for (conversation = match->next; conversation; conversation = conversation->next) {
704                         if ((conversation->setup_frame < frame_num)
705                                 && (conversation->setup_frame > match->setup_frame))
706                                 match = conversation;
707                 }
708         }
709
710         return match;
711 }
712
713
714 /*
715  * Given two address/port pairs for a packet, search for a conversation
716  * containing packets between those address/port pairs.  Returns NULL if
717  * not found.
718  *
719  * We try to find the most exact match that we can, and then proceed to
720  * try wildcard matches on the "addr_b" and/or "port_b" argument if a more
721  * exact match failed.
722  *
723  * Either or both of the "addr_b" and "port_b" arguments may be specified as
724  * a wildcard by setting the NO_ADDR_B or NO_PORT_B flags in the "options"
725  * argument.  We do only wildcard matches on addresses and ports specified
726  * as wildcards.
727  *
728  * I.e.:
729  *
730  *      if neither "addr_b" nor "port_b" were specified as wildcards, we
731  *      do an exact match (addr_a/port_a and addr_b/port_b) and, if that
732  *      succeeds, we return a pointer to the matched conversation;
733  *
734  *      otherwise, if "port_b" wasn't specified as a wildcard, we try to
735  *      match any address 2 with the specified port 2 (addr_a/port_a and
736  *      {any}/addr_b) and, if that succeeds, we return a pointer to the
737  *      matched conversation;
738  *
739  *      otherwise, if "addr_b" wasn't specified as a wildcard, we try to
740  *      match any port 2 with the specified address 2 (addr_a/port_a and
741  *      addr_b/{any}) and, if that succeeds, we return a pointer to the
742  *      matched conversation;
743  *
744  *      otherwise, we try to match any address 2 and any port 2
745  *      (addr_a/port_a and {any}/{any}) and, if that succeeds, we return
746  *      a pointer to the matched conversation;
747  *
748  *      otherwise, we found no matching conversation, and return NULL.
749  */
750 conversation_t *
751 find_conversation(guint32 frame_num, address *addr_a, address *addr_b, port_type ptype,
752     guint32 port_a, guint32 port_b, guint options)
753 {
754    conversation_t *conversation;
755
756    /*
757     * First try an exact match, if we have two addresses and ports.
758     */
759    if (!(options & (NO_ADDR_B|NO_PORT_B))) {
760       /*
761        * Neither search address B nor search port B are wildcarded,
762        * start out with an exact match.
763        * Exact matches check both directions.
764        */
765       conversation =
766          conversation_lookup_hashtable(conversation_hashtable_exact,
767          frame_num, addr_a, addr_b, ptype,
768          port_a, port_b);
769       if ((conversation == NULL) && (addr_a->type == AT_FC)) {
770          /* In Fibre channel, OXID & RXID are never swapped as
771           * TCP/UDP ports are in TCP/IP.
772           */
773          conversation =
774             conversation_lookup_hashtable(conversation_hashtable_exact,
775             frame_num, addr_b, addr_a, ptype,
776             port_a, port_b);
777       }
778       if (conversation != NULL)
779          return conversation;
780    }
781
782    /*
783     * Well, that didn't find anything.  Try matches that wildcard
784     * one of the addresses, if we have two ports.
785     */
786    if (!(options & NO_PORT_B)) {
787       /*
788        * Search port B isn't wildcarded.
789        *
790        * First try looking for a conversation with the specified
791        * address A and port A as the first address and port, and
792        * with any address and the specified port B as the second
793        * address and port.
794        * ("addr_b" doesn't take part in this lookup.)
795        */
796       conversation =
797          conversation_lookup_hashtable(conversation_hashtable_no_addr2,
798          frame_num, addr_a, addr_b, ptype, port_a, port_b);
799       if ((conversation == NULL) && (addr_a->type == AT_FC)) {
800          /* In Fibre channel, OXID & RXID are never swapped as
801           * TCP/UDP ports are in TCP/IP.
802           */
803          conversation =
804             conversation_lookup_hashtable(conversation_hashtable_no_addr2,
805             frame_num, addr_b, addr_a, ptype,
806             port_a, port_b);
807       }
808       if (conversation != NULL) {
809          /*
810           * If search address B isn't wildcarded, and this is for a
811           * connection-oriented protocol, set the second address for this
812           * conversation to address B, as that's the address that matched the
813           * wildcarded second address for this conversation.
814           *
815           * (This assumes that, for all connection oriented protocols, the
816           * endpoints of a connection have only one address each, i.e. you
817           * don't get packets in a given direction coming from more than one
818           * address, unless the CONVERSATION_TEMPLATE option is set.)
819           */
820          if (!(options & NO_ADDR_B) && ptype != PT_UDP)
821          {
822             if(!(options & CONVERSATION_TEMPLATE))
823             {
824                conversation_set_addr2(conversation, addr_b);
825             }
826             else
827             {
828                conversation =
829                   conversation_create_from_template(conversation, addr_b, 0);
830             }
831          }
832          return conversation;
833       }
834
835       /*
836        * Well, that didn't find anything.
837        * If search address B was specified, try looking for a
838        * conversation with the specified address B and port B as
839        * the first address and port, and with any address and the
840        * specified port A as the second address and port (this
841        * packet may be going in the opposite direction from the
842        * first packet in the conversation).
843        * ("addr_a" doesn't take part in this lookup.)
844        */
845       if (!(options & NO_ADDR_B)) {
846          conversation =
847             conversation_lookup_hashtable(conversation_hashtable_no_addr2,
848             frame_num, addr_b, addr_a, ptype, port_b, port_a);
849          if (conversation != NULL) {
850             /*
851              * If this is for a connection-oriented
852              * protocol, set the second address for
853              * this conversation to address A, as
854              * that's the address that matched the
855              * wildcarded second address for this
856              * conversation.
857              */
858             if (ptype != PT_UDP) {
859                if(!(options & CONVERSATION_TEMPLATE))
860                {
861                   conversation_set_addr2(conversation, addr_a);
862                }
863                else
864                {
865                   conversation =
866                      conversation_create_from_template(conversation, addr_a, 0);
867                }
868             }
869             return conversation;
870          }
871       }
872    }
873
874    /*
875     * Well, that didn't find anything.  Try matches that wildcard
876     * one of the ports, if we have two addresses.
877    */
878    if (!(options & NO_ADDR_B)) {
879       /*
880        * Search address B isn't wildcarded.
881        *
882        * First try looking for a conversation with the specified
883        * address A and port A as the first address and port, and
884        * with the specified address B and any port as the second
885        * address and port.
886        * ("port_b" doesn't take part in this lookup.)
887        */
888       conversation =
889          conversation_lookup_hashtable(conversation_hashtable_no_port2,
890          frame_num, addr_a, addr_b, ptype, port_a, port_b);
891       if ((conversation == NULL) && (addr_a->type == AT_FC)) {
892          /* In Fibre channel, OXID & RXID are never swapped as
893           * TCP/UDP ports are in TCP/IP
894           */
895          conversation =
896             conversation_lookup_hashtable(conversation_hashtable_no_port2,
897             frame_num, addr_b, addr_a, ptype, port_a, port_b);
898       }
899       if (conversation != NULL) {
900          /*
901           * If search port B isn't wildcarded, and this is for a connection-
902           * oriented protocol, set the second port for this conversation to
903           * port B, as that's the port that matched the wildcarded second port
904           * for this conversation.
905           *
906           * (This assumes that, for all connection oriented protocols, the
907           * endpoints of a connection have only one port each, i.e. you don't
908           * get packets in a given direction coming from more than one port,
909           * unless the CONVERSATION_TEMPLATE option is set.)
910           */
911          if (!(options & NO_PORT_B) && ptype != PT_UDP)
912          {
913             if(!(options & CONVERSATION_TEMPLATE))
914             {
915                conversation_set_port2(conversation, port_b);
916             }
917             else
918             {
919                conversation =
920                   conversation_create_from_template(conversation, 0, port_b);
921             }
922          }
923          return conversation;
924       }
925
926       /*
927        * Well, that didn't find anything.
928        * If search port B was specified, try looking for a
929        * conversation with the specified address B and port B
930        * as the first address and port, and with the specified
931        * address A and any port as the second address and port
932        * (this packet may be going in the opposite direction
933        * from the first packet in the conversation).
934        * ("port_a" doesn't take part in this lookup.)
935        */
936       if (!(options & NO_PORT_B)) {
937          conversation =
938             conversation_lookup_hashtable(conversation_hashtable_no_port2,
939             frame_num, addr_b, addr_a, ptype, port_b, port_a);
940          if (conversation != NULL) {
941             /*
942              * If this is for a connection-oriented
943              * protocol, set the second port for
944              * this conversation to port A, as
945              * that's the address that matched the
946              * wildcarded second address for this
947              * conversation.
948              */
949             if (ptype != PT_UDP)
950             {
951                if(!(options & CONVERSATION_TEMPLATE))
952                {
953                   conversation_set_port2(conversation, port_a);
954                }
955                else
956                {
957                   conversation =
958                      conversation_create_from_template(conversation, 0, port_a);
959                }
960             }
961             return conversation;
962          }
963       }
964    }
965
966    /*
967     * Well, that didn't find anything.  Try matches that wildcard
968     * one address/port pair.
969     *
970     * First try looking for a conversation with the specified address A
971     * and port A as the first address and port.
972     * (Neither "addr_b" nor "port_b" take part in this lookup.)
973     */
974    conversation =
975       conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2,
976       frame_num, addr_a, addr_b, ptype, port_a, port_b);
977    if (conversation != NULL) {
978       /*
979        * If this is for a connection-oriented protocol:
980        *
981        * if search address B isn't wildcarded, set the
982        * second address for this conversation to address
983        * B, as that's the address that matched the
984        * wildcarded second address for this conversation;
985        *
986        * if search port B isn't wildcarded, set the
987        * second port for this conversation to port B,
988        * as that's the port that matched the wildcarded
989        * second port for this conversation.
990        */
991       if (ptype != PT_UDP)
992       {
993          if(!(options & CONVERSATION_TEMPLATE))
994          {
995             if (!(options & NO_ADDR_B))
996                conversation_set_addr2(conversation, addr_b);
997             if (!(options & NO_PORT_B))
998                conversation_set_port2(conversation, port_b);
999          }
1000          else
1001          {
1002             conversation =
1003                conversation_create_from_template(conversation, addr_b, port_b);
1004          }
1005       }
1006       return conversation;
1007    }
1008
1009    /*
1010     * Well, that didn't find anything.
1011     * If search address and port B were specified, try looking for a
1012     * conversation with the specified address B and port B as the
1013     * first address and port, and with any second address and port
1014     * (this packet may be going in the opposite direction from the
1015     * first packet in the conversation).
1016     * (Neither "addr_a" nor "port_a" take part in this lookup.)
1017     */
1018    if (addr_a->type == AT_FC)
1019       conversation =
1020       conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2,
1021       frame_num, addr_b, addr_a, ptype, port_a, port_b);
1022    else 
1023       conversation =
1024       conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2,
1025       frame_num, addr_b, addr_a, ptype, port_b, port_a);
1026    if (conversation != NULL) {
1027       /*
1028        * If this is for a connection-oriented protocol, set the
1029        * second address for this conversation to address A, as
1030        * that's the address that matched the wildcarded second
1031        * address for this conversation, and set the second port
1032        * for this conversation to port A, as that's the port
1033        * that matched the wildcarded second port for this
1034        * conversation.
1035        */
1036       if (ptype != PT_UDP)
1037       {
1038          if(!(conversation->options & CONVERSATION_TEMPLATE))
1039          {
1040             conversation_set_addr2(conversation, addr_a);
1041             conversation_set_port2(conversation, port_a);
1042          }
1043          else
1044          {
1045             conversation = conversation_create_from_template(conversation, addr_a, port_a);
1046          }
1047       }
1048       return conversation;
1049    }
1050
1051    /*
1052     * We found no conversation.
1053     */
1054    return NULL;
1055 }
1056
1057 static gint
1058 p_compare(gconstpointer a, gconstpointer b)
1059 {
1060         const conv_proto_data *ap = (const conv_proto_data *)a;
1061         const conv_proto_data *bp = (const conv_proto_data *)b;
1062
1063         if (ap->proto > bp->proto)
1064                 return 1;
1065         else if (ap->proto == bp->proto)
1066                 return 0;
1067         else
1068                 return -1;
1069 }
1070
1071 void
1072 conversation_add_proto_data(conversation_t *conv, int proto, void *proto_data)
1073 {
1074         conv_proto_data *p1 = g_mem_chunk_alloc(conv_proto_data_area);
1075
1076         p1->proto = proto;
1077         p1->proto_data = proto_data;
1078
1079         /* Add it to the list of items for this conversation. */
1080
1081         conv->data_list = g_slist_insert_sorted(conv->data_list, (gpointer *)p1,
1082             p_compare);
1083 }
1084
1085 void *
1086 conversation_get_proto_data(conversation_t *conv, int proto)
1087 {
1088         conv_proto_data temp, *p1;
1089         GSList *item;
1090
1091         temp.proto = proto;
1092         temp.proto_data = NULL;
1093
1094         item = g_slist_find_custom(conv->data_list, (gpointer *)&temp,
1095             p_compare);
1096
1097         if (item != NULL) {
1098                 p1 = (conv_proto_data *)item->data;
1099                 return p1->proto_data;
1100         }
1101
1102         return NULL;
1103 }
1104
1105 void
1106 conversation_delete_proto_data(conversation_t *conv, int proto)
1107 {
1108         conv_proto_data temp;
1109         GSList *item;
1110
1111         temp.proto = proto;
1112         temp.proto_data = NULL;
1113
1114         item = g_slist_find_custom(conv->data_list, (gpointer *)&temp,
1115             p_compare);
1116
1117         if (item != NULL)
1118                 conv->data_list = g_slist_remove(conv->data_list, item);
1119 }
1120
1121 void
1122 conversation_set_dissector(conversation_t *conversation,
1123     dissector_handle_t handle)
1124 {
1125         conversation->dissector_handle = handle;
1126 }
1127
1128 /*
1129  * Given two address/port pairs for a packet, search for a matching
1130  * conversation and, if found and it has a conversation dissector,
1131  * call that dissector and return TRUE, otherwise return FALSE.
1132  */
1133 gboolean
1134 try_conversation_dissector(address *addr_a, address *addr_b, port_type ptype,
1135     guint32 port_a, guint32 port_b, tvbuff_t *tvb, packet_info *pinfo,
1136     proto_tree *tree)
1137 {
1138         conversation_t *conversation;
1139
1140         conversation = find_conversation(pinfo->fd->num, addr_a, addr_b, ptype, port_a,
1141             port_b, 0);
1142
1143         if (conversation != NULL) {
1144                 if (conversation->dissector_handle == NULL)
1145                         return FALSE;
1146                 call_dissector(conversation->dissector_handle, tvb, pinfo,
1147                     tree);
1148                 return TRUE;
1149         }
1150         return FALSE;
1151 }