1 /* reassemble_test.c
2  * Standalone program to test functionality of reassemble.h API
3  *
4  * These aren't particularly complete - they just test a few corners of
5  * functionality which I was interested in. In particular, they only test the
6  * fragment_add_seq_* (ie, FD_BLOCKSEQUENCE) family of routines. However,
7  * hopefully they will inspire people to write additional tests, and provide a
8  * useful basis on which to do so.
9  *
10  * reassemble_test can be run under valgrind to detect any memory leaks in the
11  * Wireshark reassembly code.
12  *    Specifically: code has been added to free dynamically allocated memory
13  *     after each test (or at program completion) so that valgrind will report
14  *     only actual memory leaks.
15  *    The following command can be used to run reassemble_test under valgrind:
16  *      env                               \
17  *        G_DEBUG=gc-friendly             \
18  *        G_SLICE=always-malloc           \
19  *      valgrind --leak-check=full --show-reachable=yes ./reassemble_test
20  *
21  * Copyright (c) 2007 MX Telecom Ltd. <richardv@mxtelecom.com>
22  *
23  * Wireshark - Network traffic analyzer
24  * By Gerald Combs <gerald@wireshark.org>
25  * Copyright 1998
26  *
27  * SPDX-License-Identifier: GPL-2.0-or-later
28  */
29 
from_string(const char * str)30 #include <stdarg.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 
35 #include <glib.h>
36 
37 #include "config.h"
38 
39 #include <epan/packet.h>
40 #include <epan/packet_info.h>
41 #include <epan/proto.h>
42 #include <epan/tvbuff.h>
43 #include <epan/reassemble.h>
44 
45 #include "exceptions.h"
46 
47 static int failure = 0;
48 static const gboolean debug = FALSE; /* Set to TRUE to dump tables. */
49 
50 #define ASSERT(b)           \
51     if (!(b)) {             \
52         failure = 1;        \
53         printf("Assertion failed at line %i: %s\n", __LINE__, #b);  \
54         exit(1);            \
operator <<(std::basic_ostream<Elem,Traits> & os,const address & addr)55     }
56 
57 #define ASSERT_EQ(exp,act)  \
58     if ((exp)!=(act)) {     \
59         failure = 1;        \
60         printf("Assertion failed at line %i: %s==%s (%u==%u)\n", __LINE__, #exp, #act, (guint)exp, (guint)act);  \
61         exit(1);            \
62     }
63 
64 #define ASSERT_EQ_POINTER(exp,act)  \
65     if ((exp)!=(act)) {     \
66         failure = 1;        \
67         printf("Assertion failed at line %i: %s==%s (%p==%p)\n", __LINE__, #exp, #act, (const void *)exp, (const void *)act);  \
68         exit(1);            \
69     }
70 
71 #define ASSERT_NE_POINTER(exp,act)  \
72     if ((exp)==(act)) {     \
73         failure = 1;        \
74         printf("Assertion failed at line %i: %s!=%s (%p!=%p)\n", __LINE__, #exp, #act, (const void *)exp, (const void *)act);  \
75         exit(1);            \
76     }
77 
78 #define DATA_LEN 256
79 
80 static guint8 *data;
81 static tvbuff_t *tvb;
82 static packet_info pinfo;
83 
84 /* fragment_table maps from datagram ids to fragment_head
85    reassembled_table maps from <packet number,datagram id> to
86    fragment_head */
87 static reassembly_table test_reassembly_table;
88 
89 /*************************************************
90  * Util fcns to display
91  *   fragment_table & reassembled_table fd-chains
92  ************************************************/
93 
94 static struct _fd_flags {
95     guint32 flag;
96     gchar  *flag_name;
97 } fd_flags[] = {
98     {FD_DEFRAGMENTED         ,"DF"},
99     {FD_DATALEN_SET          ,"DS"},
100     {FD_SUBSET_TVB           ,"ST"},
101     {FD_BLOCKSEQUENCE        ,"BS"},
102     {FD_PARTIAL_REASSEMBLY   ,"PR"},
103     {FD_OVERLAP              ,"OL"},
104     {FD_OVERLAPCONFLICT      ,"OC"},
105     {FD_MULTIPLETAILS        ,"MT"},
106     {FD_TOOLONGFRAGMENT      ,"TL"},
107 };
108 #define N_FD_FLAGS (signed)(sizeof(fd_flags)/sizeof(struct _fd_flags))
109 
110 static void
111 print_fd(fragment_head *fd, gboolean is_head) {
112     int i;
113 
114     g_assert_true(fd != NULL);
115     printf("        %16p %16p %3u %3u %3u", (void *)fd, (void *)(fd->next), fd->frame, fd->offset, fd->len);
116     if (is_head) {
117         printf(" %3u %3u", fd->datalen, fd->reassembled_in);
118     } else {
119         printf( "        ");
120     }
121     if (fd->tvb_data != NULL) {
122         printf(" %16p", tvb_get_ptr(fd->tvb_data, 0, 1)); /* Address of first byte only... */
123     } else {
124         printf(" %16s", "<null tvb_data>");
125     }
126     for (i=0; i < N_FD_FLAGS; i++) {
127         printf(" %s", (fd->flags & fd_flags[i].flag) ? fd_flags[i].flag_name : "  ");
128     }
129     printf("\n");
130 }
131 
132 static void
133 print_fd_chain(fragment_head *fd_head) {
134     fragment_item *fdp;
135 
136     g_assert_true(fd_head != NULL);
137     print_fd(fd_head, TRUE);
138     for (fdp=fd_head->next; fdp != NULL; fdp=fdp->next) {
139         print_fd(fdp, FALSE);
140     }
141 }
142 
143 static void
144 print_fragment_table_chain(gpointer k _U_, gpointer v, gpointer ud _U_) {
145 #ifdef DUMP_KEYS
146     fragment_key  *key     = (fragment_key*)k;
147 #endif
148     fragment_head *fd_head = (fragment_head *)v;
149 #ifdef DUMP_KEYS
150     printf("  --> FT: %3d 0x%08x 0x%08x\n", key->id, *(guint32 *)(key->src.data), *(guint32 *)(key->dst.data));
151 #endif
152     print_fd_chain(fd_head);
153 }
154 
155 static void
156 print_fragment_table(void) {
157     printf("\n Fragment Table -------\n");
158     g_hash_table_foreach(test_reassembly_table.fragment_table, print_fragment_table_chain, NULL);
159 }
160 
161 static void
162 print_reassembled_table_chain(gpointer k _U_, gpointer v, gpointer ud _U_) {
163 #ifdef DUMP_KEYS
164     reassembled_key  *key  = (reassembled_key*)k;
165 #endif
166     fragment_head *fd_head = (fragment_head *)v;
167 #ifdef DUMP_KEYS
168     printf("  --> RT: %5d %5d\n", key->id, key->frame);
169 #endif
170     print_fd_chain(fd_head);
171 }
172 
173 static void
174 print_reassembled_table(void) {
175     printf("\n Reassembled Table ----\n");
176     g_hash_table_foreach(test_reassembly_table.reassembled_table, print_reassembled_table_chain, NULL);
177 }
178 
179 static void
180 print_tables(void) {
181     print_fragment_table();
182     print_reassembled_table();
183 }
184 
185 /**********************************************************************************
186  *
187  * fragment_add_seq
188  *
189  *********************************************************************************/
190 
191 /* Simple test case for fragment_add_seq.
192  * Adds three fragments (out of order, with one for a different datagram in between),
193  * and checks that they are reassembled correctly.
194  */
195 /*   visit  id  frame  frag  len  more  tvb_offset
196        0    12     1     0    50   T      10
197        1    12     1     0    60   T       5
198        0    13     2     0    60   T      15
199        0    12     3     2    60   F       5
200        0    12     4     1    60   T      15
201 */
202 static void
203 test_simple_fragment_add_seq(void)
204 {
205     fragment_head *fd_head, *fdh0;
206 
207     printf("Starting test test_simple_fragment_add_seq\n");
208 
209     pinfo.num = 1;
210     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
211                              0, 50, TRUE, 0);
212 
213     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
214     ASSERT_EQ_POINTER(NULL,fd_head);
215 
216     /* adding the same fragment again should do nothing, even with different
217      * offset etc */
218     pinfo.fd->visited = 1;
219     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
220                              0, 60, TRUE, 0);
221     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
222     ASSERT_EQ_POINTER(NULL,fd_head);
223 
224     /* start another pdu (just to confuse things) */
225     pinfo.fd->visited = 0;
226     pinfo.num = 2;
227     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 15, &pinfo, 13, NULL,
228                              0, 60, TRUE, 0);
229     ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.fragment_table));
230     ASSERT_EQ_POINTER(NULL,fd_head);
231 
232     /* now we add the terminal fragment of the first datagram */
233     pinfo.num = 3;
234     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
235                              2, 60, FALSE, 0);
236 
237     /* we haven't got all the fragments yet ... */
238     ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.fragment_table));
239     ASSERT_EQ_POINTER(NULL,fd_head);
240 
241     /* finally, add the missing fragment */
242     pinfo.num = 4;
243     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 15, &pinfo, 12, NULL,
244                              1, 60, TRUE, 0);
245 
246     ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.fragment_table));
247     ASSERT_NE_POINTER(NULL,fd_head);
248 
249     /* check the contents of the structure */
250     ASSERT_EQ(4,fd_head->frame);  /* max frame number of fragment in assembly */
251     ASSERT_EQ(0,fd_head->offset); /* unused */
252     ASSERT_EQ(170,fd_head->len); /* the length of data we have */
253     ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
254     ASSERT_EQ(4,fd_head->reassembled_in);
255     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
256     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
257     ASSERT_NE_POINTER(NULL,fd_head->next);
258 
259     ASSERT_EQ(1,fd_head->next->frame);
260     ASSERT_EQ(0,fd_head->next->offset);  /* seqno */
261     ASSERT_EQ(50,fd_head->next->len);    /* segment length */
262     ASSERT_EQ(0,fd_head->next->flags);
263     ASSERT_EQ_POINTER(NULL,fd_head->next->tvb_data);
264     ASSERT_NE_POINTER(NULL,fd_head->next->next);
265 
266     ASSERT_EQ(4,fd_head->next->next->frame);
267     ASSERT_EQ(1,fd_head->next->next->offset);  /* seqno */
268     ASSERT_EQ(60,fd_head->next->next->len);    /* segment length */
269     ASSERT_EQ(0,fd_head->next->next->flags);
270     ASSERT_EQ_POINTER(NULL,fd_head->next->next->tvb_data);
271     ASSERT_NE_POINTER(NULL,fd_head->next->next->next);
272 
273     ASSERT_EQ(3,fd_head->next->next->next->frame);
274     ASSERT_EQ(2,fd_head->next->next->next->offset);  /* seqno */
275     ASSERT_EQ(60,fd_head->next->next->next->len);    /* segment length */
276     ASSERT_EQ(0,fd_head->next->next->next->flags);
277     ASSERT_EQ_POINTER(NULL,fd_head->next->next->next->tvb_data);
278     ASSERT_EQ_POINTER(NULL,fd_head->next->next->next->next);
279 
280     /* test the actual reassembly */
281     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
282     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+15,60));
283     ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,60));
284 
285     if (debug) {
286         print_fragment_table();
287     }
288 
289     /* what happens if we revisit the packets now? */
290     fdh0 = fd_head;
291     pinfo.fd->visited = 1;
292     pinfo.num = 1;
293     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
294                              0, 50, TRUE, 0);
295     /*
296      * this api relies on the caller to check fd_head -> reassembled_in
297      *
298      * Redoing all the tests seems like overkill - just check the pointer
299      */
300     ASSERT_EQ_POINTER(fdh0,fd_head);
301 
302     pinfo.num = 3;
303     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
304                              2, 60, FALSE, 0);
305     ASSERT_EQ_POINTER(fdh0,fd_head);
306 
307     pinfo.num = 4;
308     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 15, &pinfo, 12, NULL,
309                              1, 60, TRUE, 0);
310     ASSERT_EQ_POINTER(fdh0,fd_head);
311 
312     if (debug) {
313         print_fragment_table();
314     }
315 }
316 
317 /* XXX ought to have some tests for overlapping fragments */
318 
319 /* This tests the functionality of fragment_set_partial_reassembly for
320  * FD_BLOCKSEQUENCE reassembly.
321  *
322  * We add a sequence of fragments thus:
323  *    seqno   frame  offset   len   (initial) more_frags
324  *    -----   -----  ------   ---   --------------------
325  *      0       1       10       50   false
326  *      1       2        0       40   true
327  *      1       3        0       40   true (a duplicate fragment)
328  *      2       4       20      100   false
329  *      3       5        0       40   false
330  */
331 static void
332 test_fragment_add_seq_partial_reassembly(void)
333 {
334     fragment_head *fd_head;
335     fragment_item *fd;
336 
337     printf("Starting test test_fragment_add_seq_partial_reassembly\n");
338 
339     /* generally it's probably fair to assume that we will be called with
340      * more_frags=FALSE.
341      */
342     pinfo.num = 1;
343     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
344                              0, 50, FALSE, 0);
345 
346     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
347     ASSERT_NE_POINTER(NULL,fd_head);
348 
349     /* check the contents of the structure */
350     ASSERT_EQ(1,fd_head->frame);  /* max frame in reassembly */
351     ASSERT_EQ(0,fd_head->offset); /* unused */
352     ASSERT_EQ(50,fd_head->len); /* the length of data we have */
353     ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
354     ASSERT_EQ(1,fd_head->reassembled_in);
355     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
356     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
357     ASSERT_NE_POINTER(NULL,fd_head->next);
358 
359     ASSERT_EQ(1,fd_head->next->frame);
360     ASSERT_EQ(0,fd_head->next->offset);  /* seqno */
361     ASSERT_EQ(50,fd_head->next->len);    /* segment length */
362     ASSERT_EQ(0,fd_head->next->flags);
363     ASSERT_EQ_POINTER(NULL,fd_head->next->tvb_data);
364     ASSERT_EQ_POINTER(NULL,fd_head->next->next);
365 
366     /* test the actual reassembly */
367     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
368 
369     /* now we announce that the reassembly wasn't complete after all. */
370     fragment_set_partial_reassembly(&test_reassembly_table, &pinfo, 12, NULL);
371 
372     /* and add another segment. To mix things up slightly (and so that we can
373      * check on the state of things), we're going to set the more_frags flag
374      * here
375      */
376     pinfo.num = 2;
377     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 0, &pinfo, 12, NULL,
378                              1, 40, TRUE, 0);
379 
380     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
381     ASSERT_EQ_POINTER(NULL,fd_head);
382 
383     fd_head=fragment_get(&test_reassembly_table, &pinfo, 12, NULL);
384     ASSERT_NE_POINTER(NULL,fd_head);
385 
386     /* check the contents of the structure */
387     ASSERT_EQ(2,fd_head->frame);   /* max frame in reassembly */
388     ASSERT_EQ(0,fd_head->offset);  /* unused */
389     /* ASSERT_EQ(50,fd_head->len);     the length of data we have */
390     ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
391     ASSERT_EQ(0,fd_head->reassembled_in);
392     ASSERT_EQ(FD_BLOCKSEQUENCE,fd_head->flags);
393     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
394     ASSERT_NE_POINTER(NULL,fd_head->next);
395 
396     fd=fd_head->next;
397     ASSERT_EQ(1,fd->frame);
398     ASSERT_EQ(0,fd->offset);  /* seqno */
399     ASSERT_EQ(50,fd->len);    /* segment length */
400     ASSERT_EQ(FD_SUBSET_TVB,fd->flags);
401     ASSERT_EQ_POINTER(tvb_get_ptr(fd_head->tvb_data,0,0),tvb_get_ptr(fd->tvb_data,0,0));
402     ASSERT_NE_POINTER(NULL,fd->next);
403 
404     fd=fd->next;
405     ASSERT_EQ(2,fd->frame);
406     ASSERT_EQ(1,fd->offset);  /* seqno */
407     ASSERT_EQ(40,fd->len);    /* segment length */
408     ASSERT_EQ(0,fd->flags);
409     ASSERT_NE_POINTER(NULL,fd->tvb_data);
410     ASSERT_EQ_POINTER(NULL,fd->next);
411 
412     /* Another copy of the second segment.
413      */
414     pinfo.num = 3;
415     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 0, &pinfo, 12, NULL,
416                              1, 40, TRUE, 0);
417 
418     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
419     ASSERT_EQ_POINTER(NULL,fd_head);
420     fd_head=fragment_get(&test_reassembly_table, &pinfo, 12, NULL);
421     ASSERT_NE_POINTER(NULL,fd_head);
422     ASSERT_EQ(3,fd_head->frame);   /* max frame we have */
423     ASSERT_EQ(0,fd_head->offset);  /* unused */
424     /* ASSERT_EQ(50,fd_head->len);     the length of data we have */
425     ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
426     ASSERT_EQ(0,fd_head->reassembled_in);
427     ASSERT_EQ(FD_BLOCKSEQUENCE,fd_head->flags);
428     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
429     ASSERT_NE_POINTER(NULL,fd_head->next);
430 
431     fd=fd_head->next;
432     ASSERT_EQ(1,fd->frame);
433     ASSERT_EQ(0,fd->offset);  /* seqno */
434     ASSERT_EQ(50,fd->len);    /* segment length */
435     ASSERT_EQ(FD_SUBSET_TVB,fd->flags);
436     ASSERT_EQ_POINTER(tvb_get_ptr(fd_head->tvb_data,0,0),tvb_get_ptr(fd->tvb_data,0,0));
437     ASSERT_NE_POINTER(NULL,fd->next);
438 
439     fd=fd->next;
440     ASSERT_EQ(2,fd->frame);
441     ASSERT_EQ(1,fd->offset);  /* seqno */
442     ASSERT_EQ(40,fd->len);    /* segment length */
443     ASSERT_EQ(0,fd->flags);
444     ASSERT_NE_POINTER(NULL,fd->tvb_data);
445     ASSERT_NE_POINTER(NULL,fd->next);
446 
447     fd=fd->next;
448     ASSERT_EQ(3,fd->frame);
449     ASSERT_EQ(1,fd->offset);  /* seqno */
450     ASSERT_EQ(40,fd->len);    /* segment length */
451     ASSERT_EQ(0,fd->flags);
452     ASSERT_NE_POINTER(NULL,fd->tvb_data);
453     ASSERT_EQ_POINTER(NULL,fd->next);
454 
455 
456 
457     /* have another go at wrapping things up */
458     pinfo.num = 4;
459     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 20, &pinfo, 12, NULL,
460                              2, 100, FALSE, 0);
461 
462     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
463     ASSERT_NE_POINTER(NULL,fd_head);
464 
465     /* check the contents of the structure */
466     ASSERT_EQ(4,fd_head->frame);  /* max frame we have */
467     ASSERT_EQ(0,fd_head->offset); /* unused */
468     ASSERT_EQ(190,fd_head->len); /* the length of data we have */
469     ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
470     ASSERT_EQ(4,fd_head->reassembled_in);
471     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
472     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
473     ASSERT_NE_POINTER(NULL,fd_head->next);
474 
475     fd=fd_head->next;
476     ASSERT_EQ(1,fd->frame);
477     ASSERT_EQ(0,fd->offset);  /* seqno */
478     ASSERT_EQ(50,fd->len);    /* segment length */
479     ASSERT_EQ(0,fd->flags);
480     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
481     ASSERT_NE_POINTER(NULL,fd->next);
482 
483     fd=fd->next;
484     ASSERT_EQ(2,fd->frame);
485     ASSERT_EQ(1,fd->offset);  /* seqno */
486     ASSERT_EQ(40,fd->len);    /* segment length */
487     ASSERT_EQ(0,fd->flags);
488     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
489     ASSERT_NE_POINTER(NULL,fd->next);
490 
491     fd=fd->next;
492     ASSERT_EQ(3,fd->frame);
493     ASSERT_EQ(1,fd->offset);  /* seqno */
494     ASSERT_EQ(40,fd->len);    /* segment length */
495     ASSERT_EQ(FD_OVERLAP,fd->flags);
496     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
497     ASSERT_NE_POINTER(NULL,fd->next);
498 
499     fd=fd->next;
500     ASSERT_EQ(4,fd->frame);
501     ASSERT_EQ(2,fd->offset);  /* seqno */
502     ASSERT_EQ(100,fd->len);    /* segment length */
503     ASSERT_EQ(0,fd->flags);
504     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
505     ASSERT_EQ_POINTER(NULL,fd->next);
506 
507     /* test the actual reassembly */
508     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
509     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data,40));
510     ASSERT(!tvb_memeql(fd_head->tvb_data,90,data+20,100));
511 
512 
513     /* do it again (this time it is more complicated, with an overlap in the
514      * reassembly) */
515 
516     fragment_set_partial_reassembly(&test_reassembly_table, &pinfo, 12, NULL);
517 
518     pinfo.num = 5;
519     fragment_add_seq(&test_reassembly_table, tvb, 0, &pinfo, 12, NULL,
520                              3, 40, FALSE, 0);
521 
522     fd_head=fragment_get(&test_reassembly_table, &pinfo, 12, NULL);
523     ASSERT_NE_POINTER(NULL,fd_head);
524     ASSERT_EQ(5,fd_head->frame);   /* max frame we have */
525     ASSERT_EQ(0,fd_head->offset);  /* unused */
526     ASSERT_EQ(230,fd_head->len);   /* the length of data we have */
527     ASSERT_EQ(3,fd_head->datalen); /* seqno of the last fragment we have */
528     ASSERT_EQ(5,fd_head->reassembled_in);
529     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
530     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
531     ASSERT_NE_POINTER(NULL,fd_head->next);
532 
533     fd=fd_head->next;
534     ASSERT_EQ(1,fd->frame);
535     ASSERT_EQ(0,fd->offset);  /* seqno */
536     ASSERT_EQ(50,fd->len);    /* segment length */
537     ASSERT_EQ(0,fd->flags);
538     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
539     ASSERT_NE_POINTER(NULL,fd->next);
540 
541     fd=fd->next;
542     ASSERT_EQ(2,fd->frame);
543     ASSERT_EQ(1,fd->offset);  /* seqno */
544     ASSERT_EQ(40,fd->len);    /* segment length */
545     ASSERT_EQ(0,fd->flags);
546     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
547     ASSERT_NE_POINTER(NULL,fd->next);
548 
549     fd=fd->next;
550     ASSERT_EQ(3,fd->frame);
551     ASSERT_EQ(1,fd->offset);  /* seqno */
552     ASSERT_EQ(40,fd->len);    /* segment length */
553     ASSERT_EQ(FD_OVERLAP,fd->flags);
554     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
555     ASSERT_NE_POINTER(NULL,fd->next);
556 
557     fd=fd->next;
558     ASSERT_EQ(4,fd->frame);
559     ASSERT_EQ(2,fd->offset);  /* seqno */
560     ASSERT_EQ(100,fd->len);   /* segment length */
561     ASSERT_EQ(0,fd->flags);
562     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
563     ASSERT_NE_POINTER(NULL,fd->next);
564 
565     fd=fd->next;
566     ASSERT_EQ(5,fd->frame);
567     ASSERT_EQ(3,fd->offset);  /* seqno */
568     ASSERT_EQ(40,fd->len);    /* segment length */
569     ASSERT_EQ(0,fd->flags);
570     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
571     ASSERT_EQ_POINTER(NULL,fd->next);
572 
573     /* test the actual reassembly */
574     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
575     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data,40));
576     ASSERT(!tvb_memeql(fd_head->tvb_data,90,data+20,100));
577     ASSERT(!tvb_memeql(fd_head->tvb_data,190,data,40));
578 }
579 
580 /* Test case for fragment_add_seq with duplicated (e.g., retransmitted) data.
581  * Adds three fragments--adding the 1st one twice--
582  * and checks that they are reassembled correctly.
583  */
584 /*   visit  id  frame  frag  len  more  tvb_offset
585        0    12     1     0    50   T      10
586        0    12     2     1    60   T      5
587        0    12     3     2    40   F      5
588        0    12     4     0    50   T      10
589 */
590 static void
591 test_fragment_add_seq_duplicate_first(void)
592 {
593     fragment_head *fd_head;
594 
595     printf("Starting test test_fragment_add_seq_duplicate_first\n");
596 
597     pinfo.num = 1;
598     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
599                              0, 50, TRUE, 0);
600 
601     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
602     ASSERT_EQ_POINTER(NULL,fd_head);
603 
604     /* Add the 2nd segment */
605     pinfo.num = 2;
606     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
607                              1, 60, TRUE, 0);
608 
609     /* we haven't got all the fragments yet ... */
610     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
611     ASSERT_EQ_POINTER(NULL,fd_head);
612 
613     /* Add the last fragment */
614     pinfo.num = 3;
615     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
616                              2, 40, FALSE, 0);
617 
618     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
619     ASSERT_NE_POINTER(NULL,fd_head);
620 
621     /* Add the first fragment again */
622     pinfo.num = 4;
623     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
624                              0, 50, TRUE, 0);
625 
626     /* Reassembly should have still succeeded */
627     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
628     ASSERT_NE_POINTER(NULL,fd_head);
629 
630     /* check the contents of the structure */
631     ASSERT_EQ(4,fd_head->frame);  /* max frame we have */
632     ASSERT_EQ(0,fd_head->offset); /* unused */
633     ASSERT_EQ(150,fd_head->len); /* the length of data we have */
634     ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
635     ASSERT_EQ(3,fd_head->reassembled_in);
636     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
637     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
638     ASSERT_NE_POINTER(NULL,fd_head->next);
639 
640     ASSERT_EQ(1,fd_head->next->frame);
641     ASSERT_EQ(0,fd_head->next->offset);  /* seqno */
642     ASSERT_EQ(50,fd_head->next->len);    /* segment length */
643     ASSERT_EQ(0,fd_head->next->flags);
644     ASSERT_EQ_POINTER(NULL,fd_head->next->tvb_data);
645     ASSERT_NE_POINTER(NULL,fd_head->next->next);
646 
647     ASSERT_EQ(4,fd_head->next->next->frame);
648     ASSERT_EQ(0,fd_head->next->next->offset);  /* seqno */
649     ASSERT_EQ(50,fd_head->next->next->len);    /* segment length */
650     ASSERT_EQ(FD_OVERLAP,fd_head->next->next->flags);
651     ASSERT_EQ_POINTER(NULL,fd_head->next->next->tvb_data);
652     ASSERT_NE_POINTER(NULL,fd_head->next->next->next);
653 
654     ASSERT_EQ(2,fd_head->next->next->next->frame);
655     ASSERT_EQ(1,fd_head->next->next->next->offset);  /* seqno */
656     ASSERT_EQ(60,fd_head->next->next->next->len);    /* segment length */
657     ASSERT_EQ(0,fd_head->next->next->next->flags);
658     ASSERT_EQ_POINTER(NULL,fd_head->next->next->next->tvb_data);
659     ASSERT_NE_POINTER(NULL,fd_head->next->next->next->next);
660 
661     ASSERT_EQ(3,fd_head->next->next->next->next->frame);
662     ASSERT_EQ(2,fd_head->next->next->next->next->offset);  /* seqno */
663     ASSERT_EQ(40,fd_head->next->next->next->next->len);    /* segment length */
664     ASSERT_EQ(0,fd_head->next->next->next->next->flags);
665     ASSERT_EQ_POINTER(NULL,fd_head->next->next->next->next->tvb_data);
666     ASSERT_EQ_POINTER(NULL,fd_head->next->next->next->next->next);
667 
668     /* test the actual reassembly */
669     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
670     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+5,60));
671     ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,40));
672 
673     if (debug) {
674         print_fragment_table();
675     }
676 }
677 
678 
679 /* Test case for fragment_add_seq with duplicated (e.g., retransmitted) data.
680  * Adds three fragments--adding the 2nd one twice--
681  * and checks that they are reassembled correctly.
682  */
683 /*   visit  id  frame  frag  len  more  tvb_offset
684        0    12     1     0    50   T      10
685        0    12     2     1    60   T      5
686        0    12     3     1    60   T      5
687        0    12     4     3    40   F      5
688 */
689 static void
690 test_fragment_add_seq_duplicate_middle(void)
691 {
692     fragment_head *fd_head;
693 
694     printf("Starting test test_fragment_add_seq_duplicate_middle\n");
695 
696     pinfo.num = 1;
697     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
698                              0, 50, TRUE, 0);
699 
700     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
701     ASSERT_EQ_POINTER(NULL,fd_head);
702 
703     /* Add the 2nd segment */
704     pinfo.num = 2;
705     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
706                              1, 60, TRUE, 0);
707 
708     /* we haven't got all the fragments yet ... */
709     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
710     ASSERT_EQ_POINTER(NULL,fd_head);
711 
712     /* Now, add the 2nd segment again (but in a different frame) */
713     pinfo.num = 3;
714     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
715                              1, 60, TRUE, 0);
716 
717     /* This duplicate fragment should have been ignored */
718     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
719     ASSERT_EQ_POINTER(NULL,fd_head);
720 
721     /* finally, add the last fragment */
722     pinfo.num = 4;
723     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
724                              2, 40, FALSE, 0);
725 
726     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
727     ASSERT_NE_POINTER(NULL,fd_head);
728 
729     /* check the contents of the structure */
730     ASSERT_EQ(4,fd_head->frame);  /* max frame we have */
731     ASSERT_EQ(0,fd_head->offset); /* unused */
732     ASSERT_EQ(150,fd_head->len); /* the length of data we have */
733     ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
734     ASSERT_EQ(4,fd_head->reassembled_in);
735     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
736     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
737     ASSERT_NE_POINTER(NULL,fd_head->next);
738 
739     ASSERT_EQ(1,fd_head->next->frame);
740     ASSERT_EQ(0,fd_head->next->offset);  /* seqno */
741     ASSERT_EQ(50,fd_head->next->len);    /* segment length */
742     ASSERT_EQ(0,fd_head->next->flags);
743     ASSERT_EQ_POINTER(NULL,fd_head->next->tvb_data);
744     ASSERT_NE_POINTER(NULL,fd_head->next->next);
745 
746     ASSERT_EQ(2,fd_head->next->next->frame);
747     ASSERT_EQ(1,fd_head->next->next->offset);  /* seqno */
748     ASSERT_EQ(60,fd_head->next->next->len);    /* segment length */
749     ASSERT_EQ(0,fd_head->next->next->flags);
750     ASSERT_EQ_POINTER(NULL,fd_head->next->next->tvb_data);
751     ASSERT_NE_POINTER(NULL,fd_head->next->next->next);
752 
753     ASSERT_EQ(3,fd_head->next->next->next->frame);
754     ASSERT_EQ(1,fd_head->next->next->next->offset);  /* seqno */
755     ASSERT_EQ(60,fd_head->next->next->next->len);    /* segment length */
756     ASSERT_EQ(FD_OVERLAP,fd_head->next->next->next->flags);
757     ASSERT_EQ_POINTER(NULL,fd_head->next->next->next->tvb_data);
758     ASSERT_NE_POINTER(NULL,fd_head->next->next->next->next);
759 
760     ASSERT_EQ(4,fd_head->next->next->next->next->frame);
761     ASSERT_EQ(2,fd_head->next->next->next->next->offset);  /* seqno */
762     ASSERT_EQ(40,fd_head->next->next->next->next->len);    /* segment length */
763     ASSERT_EQ(0,fd_head->next->next->next->next->flags);
764     ASSERT_EQ_POINTER(NULL,fd_head->next->next->next->next->tvb_data);
765     ASSERT_EQ_POINTER(NULL,fd_head->next->next->next->next->next);
766 
767     /* test the actual reassembly */
768     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
769     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+5,60));
770     ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,40));
771 
772     if (debug) {
773         print_fragment_table();
774     }
775 }
776 
777 /* Test case for fragment_add_seq with duplicated (e.g., retransmitted) data.
778  * Adds three fragments--adding the 3rd one twice--
779  * and checks that they are reassembled correctly.
780  */
781 /*   visit  id  frame  frag  len  more  tvb_offset
782        0    12     1     0    50   T      10
783        0    12     2     1    60   T      5
784        0    12     3     2    40   F      5
785        0    12     4     2    40   F      5
786 */
787 static void
788 test_fragment_add_seq_duplicate_last(void)
789 {
790     fragment_head *fd_head;
791 
792     printf("Starting test test_fragment_add_seq_duplicate_last\n");
793 
794     pinfo.num = 1;
795     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
796                              0, 50, TRUE, 0);
797 
798     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
799     ASSERT_EQ_POINTER(NULL,fd_head);
800 
801     /* Add the 2nd segment */
802     pinfo.num = 2;
803     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
804                              1, 60, TRUE, 0);
805 
806     /* we haven't got all the fragments yet ... */
807     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
808     ASSERT_EQ_POINTER(NULL,fd_head);
809 
810     /* Add the last fragment */
811     pinfo.num = 3;
812     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
813                              2, 40, FALSE, 0);
814 
815     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
816     ASSERT_NE_POINTER(NULL,fd_head);
817 
818     /* Add the last fragment again */
819     pinfo.num = 4;
820     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
821                              2, 40, FALSE, 0);
822 
823     /* Reassembly should have still succeeded */
824     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
825     ASSERT_NE_POINTER(NULL,fd_head);
826 
827     /* check the contents of the structure */
828     ASSERT_EQ(4,fd_head->frame);  /* max frame we have */
829     ASSERT_EQ(0,fd_head->offset); /* unused */
830     ASSERT_EQ(150,fd_head->len); /* the length of data we have */
831     ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
832     ASSERT_EQ(3,fd_head->reassembled_in);
833     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
834     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
835     ASSERT_NE_POINTER(NULL,fd_head->next);
836 
837     ASSERT_EQ(1,fd_head->next->frame);
838     ASSERT_EQ(0,fd_head->next->offset);  /* seqno */
839     ASSERT_EQ(50,fd_head->next->len);    /* segment length */
840     ASSERT_EQ(0,fd_head->next->flags);
841     ASSERT_EQ_POINTER(NULL,fd_head->next->tvb_data);
842     ASSERT_NE_POINTER(NULL,fd_head->next->next);
843 
844     ASSERT_EQ(2,fd_head->next->next->frame);
845     ASSERT_EQ(1,fd_head->next->next->offset);  /* seqno */
846     ASSERT_EQ(60,fd_head->next->next->len);    /* segment length */
847     ASSERT_EQ(0,fd_head->next->next->flags);
848     ASSERT_EQ_POINTER(NULL,fd_head->next->next->tvb_data);
849     ASSERT_NE_POINTER(NULL,fd_head->next->next->next);
850 
851     ASSERT_EQ(3,fd_head->next->next->next->frame);
852     ASSERT_EQ(2,fd_head->next->next->next->offset);  /* seqno */
853     ASSERT_EQ(40,fd_head->next->next->next->len);    /* segment length */
854     ASSERT_EQ(0,fd_head->next->next->next->flags);
855     ASSERT_EQ_POINTER(NULL,fd_head->next->next->next->tvb_data);
856     ASSERT_NE_POINTER(NULL,fd_head->next->next->next->next);
857 
858     ASSERT_EQ(4,fd_head->next->next->next->next->frame);
859     ASSERT_EQ(2,fd_head->next->next->next->next->offset);  /* seqno */
860     ASSERT_EQ(40,fd_head->next->next->next->next->len);    /* segment length */
861     ASSERT_EQ(FD_OVERLAP,fd_head->next->next->next->next->flags);
862     ASSERT_EQ_POINTER(NULL,fd_head->next->next->next->next->tvb_data);
863     ASSERT_EQ_POINTER(NULL,fd_head->next->next->next->next->next);
864 
865     /* test the actual reassembly */
866     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
867     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+5,60));
868     ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,40));
869 
870     if (debug) {
871         print_fragment_table();
872     }
873 }
874 
875 /* Test case for fragment_add_seq with duplicated (e.g., retransmitted) data
876  * where the retransmission "conflicts" with the original transmission
877  * (contents are different).
878  * Adds three fragments--adding the 2nd one twice--
879  * and checks that they are reassembled correctly.
880  */
881 /*   visit  id  frame  frag  len  more  tvb_offset
882        0    12     1     0    50   T      10
883        0    12     2     1    60   T      5
884        0    12     3     1    60   T      15
885        0    12     4     2    40   F      5
886 */
887 static void
888 test_fragment_add_seq_duplicate_conflict(void)
889 {
890     fragment_head *fd_head;
891 
892     printf("Starting test test_fragment_add_seq_duplicate_conflict\n");
893 
894     pinfo.num = 1;
895     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
896                              0, 50, TRUE, 0);
897 
898     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
899     ASSERT_EQ_POINTER(NULL,fd_head);
900 
901     /* Add the 2nd segment */
902     pinfo.num = 2;
903     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
904                              1, 60, TRUE, 0);
905 
906     /* we haven't got all the fragments yet ... */
907     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
908     ASSERT_EQ_POINTER(NULL,fd_head);
909 
910     /* Now, add the 2nd segment again (but in a different frame and with
911      * different data)
912      */
913     pinfo.num = 3;
914     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 15, &pinfo, 12, NULL,
915                              1, 60, TRUE, 0);
916 
917     /* This duplicate fragment should have been ignored */
918     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
919     ASSERT_EQ_POINTER(NULL,fd_head);
920 
921     /* finally, add the last fragment */
922     pinfo.num = 4;
923     fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
924                              2, 40, FALSE, 0);
925 
926     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
927     ASSERT_NE_POINTER(NULL,fd_head);
928 
929     /* check the contents of the structure */
930     ASSERT_EQ(4,fd_head->frame);  /* max frame we have */
931     ASSERT_EQ(0,fd_head->offset); /* unused */
932     ASSERT_EQ(150,fd_head->len); /* the length of data we have */
933     ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
934     ASSERT_EQ(4,fd_head->reassembled_in);
935     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP|FD_OVERLAPCONFLICT,fd_head->flags);
936     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
937     ASSERT_NE_POINTER(NULL,fd_head->next);
938 
939     ASSERT_EQ(1,fd_head->next->frame);
940     ASSERT_EQ(0,fd_head->next->offset);  /* seqno */
941     ASSERT_EQ(50,fd_head->next->len);    /* segment length */
942     ASSERT_EQ(0,fd_head->next->flags);
943     ASSERT_EQ_POINTER(NULL,fd_head->next->tvb_data);
944     ASSERT_NE_POINTER(NULL,fd_head->next->next);
945 
946     ASSERT_EQ(2,fd_head->next->next->frame);
947     ASSERT_EQ(1,fd_head->next->next->offset);  /* seqno */
948     ASSERT_EQ(60,fd_head->next->next->len);    /* segment length */
949     ASSERT_EQ(0,fd_head->next->next->flags);
950     ASSERT_EQ_POINTER(NULL,fd_head->next->next->tvb_data);
951     ASSERT_NE_POINTER(NULL,fd_head->next->next->next);
952 
953     ASSERT_EQ(3,fd_head->next->next->next->frame);
954     ASSERT_EQ(1,fd_head->next->next->next->offset);  /* seqno */
955     ASSERT_EQ(60,fd_head->next->next->next->len);    /* segment length */
956     ASSERT_EQ(FD_OVERLAP|FD_OVERLAPCONFLICT,fd_head->next->next->next->flags);
957     ASSERT_EQ_POINTER(NULL,fd_head->next->next->next->tvb_data);
958     ASSERT_NE_POINTER(NULL,fd_head->next->next->next->next);
959 
960     ASSERT_EQ(4,fd_head->next->next->next->next->frame);
961     ASSERT_EQ(2,fd_head->next->next->next->next->offset);  /* seqno */
962     ASSERT_EQ(40,fd_head->next->next->next->next->len);    /* segment length */
963     ASSERT_EQ(0,fd_head->next->next->next->next->flags);
964     ASSERT_EQ_POINTER(NULL,fd_head->next->next->next->next->tvb_data);
965     ASSERT_EQ_POINTER(NULL,fd_head->next->next->next->next->next);
966 
967     /* test the actual reassembly */
968     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
969     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+5,60));
970     ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,40));
971 
972     if (debug) {
973         print_fragment_table();
974     }
975 }
976 
977 /**********************************************************************************
978  *
979  * fragment_add_seq_check
980  *
981  *********************************************************************************/
982 
983 
984 /* This routine is used for both fragment_add_seq_802_11 and
985  * fragment_add_seq_check.
986  *
987  * Adds a couple of out-of-order fragments and checks their reassembly.
988  */
989 
990 /*   visit  id  frame  frag  len  more  tvb_offset
991        0    12     1     0    50   T      10
992        0    13     2     0    60   T      15
993        0    12     3     2    60   F       5
994        0    12     4     1    60   F      15
995 */
996 
997 
998 static void
999 test_fragment_add_seq_check_work(fragment_head *(*fn)(reassembly_table *,
1000                                  tvbuff_t *, const int, const packet_info *,
1001                                  const guint32, const void *, const guint32,
1002                                  const guint32, const gboolean))
1003 {
1004     fragment_head *fd_head;
1005 
1006     pinfo.num = 1;
1007     fd_head=fn(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
1008                0, 50, TRUE);
1009 
1010     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1011     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1012     ASSERT_EQ_POINTER(NULL,fd_head);
1013 
1014     /* start another pdu (just to confuse things) */
1015     pinfo.num = 2;
1016     fd_head=fn(&test_reassembly_table, tvb, 15, &pinfo, 13, NULL,
1017                0, 60, TRUE);
1018     ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.fragment_table));
1019     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1020     ASSERT_EQ_POINTER(NULL,fd_head);
1021 
1022     /* add the terminal fragment of the first datagram */
1023     pinfo.num = 3;
1024     fd_head=fn(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
1025                2, 60, FALSE);
1026 
1027     /* we haven't got all the fragments yet ... */
1028     ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.fragment_table));
1029     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1030     ASSERT_EQ_POINTER(NULL,fd_head);
1031 
1032     /* finally, add the missing fragment */
1033     pinfo.num = 4;
1034     fd_head=fn(&test_reassembly_table, tvb, 15, &pinfo, 12, NULL,
1035                1, 60, TRUE);
1036 
1037     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1038     ASSERT_EQ(3,g_hash_table_size(test_reassembly_table.reassembled_table));
1039     ASSERT_NE_POINTER(NULL,fd_head);
1040 
1041     /* check the contents of the structure */
1042     ASSERT_EQ(4,fd_head->frame);  /* max frame we have */
1043     ASSERT_EQ(0,fd_head->offset); /* unused */
1044     ASSERT_EQ(170,fd_head->len); /* the length of data we have */
1045     ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
1046     ASSERT_EQ(4,fd_head->reassembled_in);
1047     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
1048     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
1049     ASSERT_NE_POINTER(NULL,fd_head->next);
1050 
1051     ASSERT_EQ(1,fd_head->next->frame);
1052     ASSERT_EQ(0,fd_head->next->offset);  /* seqno */
1053     ASSERT_EQ(50,fd_head->next->len);    /* segment length */
1054     ASSERT_EQ(0,fd_head->next->flags);
1055     ASSERT_EQ_POINTER(NULL,fd_head->next->tvb_data);
1056     ASSERT_NE_POINTER(NULL,fd_head->next->next);
1057 
1058     ASSERT_EQ(4,fd_head->next->next->frame);
1059     ASSERT_EQ(1,fd_head->next->next->offset);  /* seqno */
1060     ASSERT_EQ(60,fd_head->next->next->len);    /* segment length */
1061     ASSERT_EQ(0,fd_head->next->next->flags);
1062     ASSERT_EQ_POINTER(NULL,fd_head->next->next->tvb_data);
1063     ASSERT_NE_POINTER(NULL,fd_head->next->next->next);
1064 
1065     ASSERT_EQ(3,fd_head->next->next->next->frame);
1066     ASSERT_EQ(2,fd_head->next->next->next->offset);  /* seqno */
1067     ASSERT_EQ(60,fd_head->next->next->next->len);    /* segment length */
1068     ASSERT_EQ(0,fd_head->next->next->next->flags);
1069     ASSERT_EQ_POINTER(NULL,fd_head->next->next->next->tvb_data);
1070     ASSERT_EQ_POINTER(NULL,fd_head->next->next->next->next);
1071 
1072     /* test the actual reassembly */
1073     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
1074     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+15,60));
1075     ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,60));
1076 
1077     if (debug) {
1078         print_tables();
1079     }
1080 }
1081 
1082 /* Simple test case for fragment_add_seq_check
1083  */
1084 static void
1085 test_fragment_add_seq_check(void)
1086 {
1087     printf("Starting test test_fragment_add_seq_check\n");
1088 
1089     test_fragment_add_seq_check_work(fragment_add_seq_check);
1090 }
1091 
1092 
1093 /* This tests the case that the 802.11 hack does something different for: when
1094  * the terminal segment in a fragmented datagram arrives first.
1095  */
1096 static void
1097 test_fragment_add_seq_check_1(void)
1098 {
1099     fragment_head *fd_head;
1100 
1101     printf("Starting test test_fragment_add_seq_check_1\n");
1102 
1103     pinfo.num = 1;
1104     fd_head=fragment_add_seq_check(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
1105                                    1, 50, FALSE);
1106 
1107     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1108     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1109     ASSERT_EQ_POINTER(NULL,fd_head);
1110 
1111     /* Now add the missing segment */
1112     pinfo.num = 2;
1113     fd_head=fragment_add_seq_check(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
1114                                    0, 60, TRUE);
1115 
1116     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.fragment_table));
1117     ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.reassembled_table));
1118     ASSERT_NE_POINTER(NULL,fd_head);
1119 
1120     /* check the contents of the structure */
1121     ASSERT_EQ(2,fd_head->frame);  /* max frame of fragment in structure */
1122     ASSERT_EQ(0,fd_head->offset); /* unused */
1123     ASSERT_EQ(110,fd_head->len); /* the length of data we have */
1124     ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */
1125     ASSERT_EQ(2,fd_head->reassembled_in);
1126     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
1127     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
1128     ASSERT_NE_POINTER(NULL,fd_head->next);
1129 
1130     ASSERT_EQ(2,fd_head->next->frame);
1131     ASSERT_EQ(0,fd_head->next->offset);  /* seqno */
1132     ASSERT_EQ(60,fd_head->next->len);    /* segment length */
1133     ASSERT_EQ(0,fd_head->next->flags);
1134     ASSERT_EQ_POINTER(NULL,fd_head->next->tvb_data);
1135     ASSERT_NE_POINTER(NULL,fd_head->next->next);
1136 
1137     ASSERT_EQ(1,fd_head->next->next->frame);
1138     ASSERT_EQ(1,fd_head->next->next->offset);  /* seqno */
1139     ASSERT_EQ(50,fd_head->next->next->len);    /* segment length */
1140     ASSERT_EQ(0,fd_head->next->next->flags);
1141     ASSERT_EQ_POINTER(NULL,fd_head->next->next->tvb_data);
1142     ASSERT_EQ_POINTER(NULL,fd_head->next->next->next);
1143 
1144     /* test the actual reassembly */
1145     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+5,60));
1146     ASSERT(!tvb_memeql(fd_head->tvb_data,60,data+10,50));
1147 }
1148 
1149 /**********************************************************************************
1150  *
1151  * fragment_add_seq_802_11
1152  *
1153  *********************************************************************************/
1154 
1155 /* Tests the 802.11 hack.
1156  */
1157 static void
1158 test_fragment_add_seq_802_11_0(void)
1159 {
1160     fragment_head *fd_head;
1161 
1162     printf("Starting test test_fragment_add_seq_802_11_0\n");
1163 
1164     /* the 802.11 hack is that some non-fragmented datagrams have non-zero
1165      * fragment_number; test for this. */
1166 
1167     pinfo.num = 1;
1168     fd_head=fragment_add_seq_802_11(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
1169                                     10, 50, FALSE);
1170 
1171     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.fragment_table));
1172     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.reassembled_table));
1173     ASSERT_NE_POINTER(NULL,fd_head);
1174 
1175     /* check the contents of the structure */
1176     ASSERT_EQ(0,fd_head->frame);  /* unused */
1177     ASSERT_EQ(0,fd_head->offset); /* unused */
1178     ASSERT_EQ(0,fd_head->len);    /* unused */
1179     ASSERT_EQ(0,fd_head->datalen); /* unused */
1180     ASSERT_EQ(1,fd_head->reassembled_in);
1181     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE,fd_head->flags);
1182     ASSERT_EQ_POINTER(NULL,fd_head->tvb_data);
1183     ASSERT_EQ_POINTER(NULL,fd_head->next);
1184 }
1185 
1186 /* Reuse the fragment_add_seq_check testcases */
1187 static void test_fragment_add_seq_802_11_1(void)
1188 {
1189     printf("Starting test test_fragment_add_seq_802_11_1\n");
1190     test_fragment_add_seq_check_work(fragment_add_seq_802_11);
1191 }
1192 
1193 /**********************************************************************************
1194  *
1195  * fragment_add_seq_check_multiple
1196  *
1197  *********************************************************************************/
1198 
1199 /* Test 2 partial frags from 2 diff datagrams in the same frame */
1200 /*
1201    datagram #1: frame 1 + first part of frame 2
1202    datagram #1: last part of frame 2 + frame 3
1203 
1204    Is this a valid scenario ?
1205 
1206    The result of calling fragment_add_seq_check(&test_reassembly_table, ) for these
1207    fragments is a reassembled_table with:
1208     id, frame 1 => first_datagram;  ["reassembled in" frame 2]
1209     id, frame 2 => second_datagram; ["reassembled in" frame 3]
1210     id, frame 3 => second_datagram;
1211 
1212     Note that the id, frame 2 => first datagram was overwritten
1213      by the entry for the second datagram.
1214    Is this OK ? IE: When dissected/displayed
1215       will the reassembled datagram 1 appear with frame 2 ??
1216 */
1217 
1218 /*   visit  id  frame  frag  len  more  tvb_offset
1219        0    12     1     0    50   T      10
1220        0    12     2     1    20   F       5
1221        0    12     2     0    25   T      25
1222        0    12     3     1    60   F       0
1223 */
1224 
1225 /*
1226    Is this a valid scenario ?
1227    Is this OK ? IE: When dissected/displayed:
1228       Will the reassembled datagram 1 appear with frame 2 ??
1229 */
1230 #if 0
1231 static void
1232 test_fragment_add_seq_check_multiple(void) {
1233     fragment_head *fd_head;
1234 
1235     pinfo.num = 1;
1236     fd_head=fragment_add_seq_check(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
1237                                    0, 50, TRUE);
1238 
1239     /* add the terminal fragment of the first datagram */
1240     pinfo.num = 2;
1241     fd_head=fragment_add_seq_check(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
1242                                    1, 20, FALSE);
1243 
1244     print_tables();
1245 
1246     /* Now: start a second datagram with the first fragment in frame #2 */
1247     pinfo.num = 2;
1248     fd_head=fragment_add_seq_check(&test_reassembly_table, tvb, 25, &pinfo, 12, NULL,
1249                0, 25, TRUE);
1250 
1251     /* add the terminal fragment of the second datagram */
1252     pinfo.num = 3;
1253     fd_head=fragment_add_seq_check(&test_reassembly_table, tvb, 0, &pinfo, 12, NULL,
1254                                    1, 60, FALSE);
1255 
1256     print_tables();
1257 }
1258 #endif
1259 
1260 /**********************************************************************************
1261  *
1262  * fragment_add_seq_next
1263  *
1264  *********************************************************************************/
1265 
1266 /* Simple test case for fragment_add_seq_next.
1267  * Adds a couple of fragments (with one for a different datagram in between),
1268  * and checks that they are reassembled correctly.
1269  */
1270 static void
1271 test_simple_fragment_add_seq_next(void)
1272 {
1273     fragment_head *fd_head;
1274 
1275     printf("Starting test test_simple_fragment_add_seq_next\n");
1276 
1277     pinfo.num = 1;
1278     fd_head= fragment_add_seq_next(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
1279                                   50, TRUE);
1280 
1281     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1282     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1283     ASSERT_EQ_POINTER(NULL,fd_head);
1284 
1285     /* adding the same fragment again should do nothing, even with different
1286      * offset etc */
1287     pinfo.fd->visited = 1;
1288     fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
1289                                   60, TRUE);
1290     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1291     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1292     ASSERT_EQ_POINTER(NULL,fd_head);
1293 
1294     /* start another pdu (just to confuse things) */
1295     pinfo.fd->visited = 0;
1296     pinfo.num = 2;
1297     fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 15, &pinfo, 13, NULL,
1298                                   60, TRUE);
1299     ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.fragment_table));
1300     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1301     ASSERT_EQ_POINTER(NULL,fd_head);
1302 
1303 
1304     /* now we add the terminal fragment of the first datagram */
1305     pinfo.num = 3;
1306     fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
1307                                   60, FALSE);
1308 
1309     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1310     ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.reassembled_table));
1311     ASSERT_NE_POINTER(NULL,fd_head);
1312 
1313     /* check the contents of the structure */
1314     ASSERT_EQ(3,fd_head->frame);  /* max frame we have */
1315     ASSERT_EQ(0,fd_head->offset); /* unused */
1316     ASSERT_EQ(110,fd_head->len); /* the length of data we have */
1317     ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */
1318     ASSERT_EQ(3,fd_head->reassembled_in);
1319     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
1320     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
1321     ASSERT_NE_POINTER(NULL,fd_head->next);
1322 
1323     ASSERT_EQ(1,fd_head->next->frame);
1324     ASSERT_EQ(0,fd_head->next->offset);  /* seqno */
1325     ASSERT_EQ(50,fd_head->next->len);    /* segment length */
1326     ASSERT_EQ(0,fd_head->next->flags);
1327     ASSERT_EQ_POINTER(NULL,fd_head->next->tvb_data);
1328     ASSERT_NE_POINTER(NULL,fd_head->next->next);
1329 
1330     ASSERT_EQ(3,fd_head->next->next->frame);
1331     ASSERT_EQ(1,fd_head->next->next->offset);  /* seqno */
1332     ASSERT_EQ(60,fd_head->next->next->len);    /* segment length */
1333     ASSERT_EQ(0,fd_head->next->next->flags);
1334     ASSERT_EQ_POINTER(NULL,fd_head->next->next->tvb_data);
1335     ASSERT_EQ_POINTER(NULL,fd_head->next->next->next);
1336 
1337     /* test the actual reassembly */
1338     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
1339     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+5,60));
1340 }
1341 
1342 
1343 #if 0
1344 /* XXX remove this? fragment_add_seq does not have the special case for
1345  * fragments having truncated tvbs anymore! */
1346 /* This tests the case where some data is missing from one of the fragments.
1347  * It should prevent reassembly.
1348  */
1349 static void
1350 test_missing_data_fragment_add_seq_next(void)
1351 {
1352     fragment_head *fd_head;
1353 
1354     printf("Starting test test_missing_data_fragment_add_seq_next\n");
1355 
1356     /* attempt to add a fragment which is longer than the data available */
1357     pinfo.num = 1;
1358     fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
1359                                   DATA_LEN-9, TRUE);
1360 
1361     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1362     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1363     ASSERT_NE_POINTER(NULL,fd_head);
1364 
1365     /* check the contents of the structure. Reassembly failed so everything
1366      * should be null (meaning, just use the original tvb)  */
1367     ASSERT_EQ(0,fd_head->frame);  /* unused */
1368     ASSERT_EQ(0,fd_head->offset); /* unused */
1369     ASSERT_EQ(0,fd_head->len); /* the length of data we have */
1370     ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
1371     ASSERT_EQ(0,fd_head->reassembled_in);
1372     ASSERT_EQ(FD_BLOCKSEQUENCE,fd_head->flags & 0x1ff);
1373     ASSERT_EQ_POINTER(NULL,fd_head->tvb_data);
1374     ASSERT_EQ_POINTER(NULL,fd_head->next);
1375 
1376     /* add another fragment (with all data present) */
1377     pinfo.num = 4;
1378     fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
1379                                   60, FALSE);
1380 
1381     /* XXX: it's not clear that this is the right result; however it's what the
1382      * code does...
1383      */
1384     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1385     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1386     ASSERT_EQ_POINTER(NULL,fd_head);
1387 
1388 
1389     /* check what happens when we revisit the packets */
1390     pinfo.fd->visited = TRUE;
1391     pinfo.num = 1;
1392 
1393     fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
1394                                   DATA_LEN-9, TRUE);
1395 
1396     /* We just look in the reassembled_table for this packet. It never got put
1397      * there, so this always returns null.
1398      *
1399      * That's crazy, because it means that the subdissector will see the data
1400      * exactly once - on the first pass through the capture (well, assuming it
1401      * doesn't bother to check fd_head->reassembled_in); however, that's
1402      * what the code does...
1403      */
1404     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1405     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1406     ASSERT_EQ_POINTER(NULL,fd_head);
1407 
1408     pinfo.num = 4;
1409     fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
1410                                   60, FALSE);
1411     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1412     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1413     ASSERT_EQ_POINTER(NULL,fd_head);
1414 }
1415 
1416 
1417 /*
1418  * we're going to do something similar now, but this time it is the second
1419  * fragment which has something missing.
1420  */
1421 static void
1422 test_missing_data_fragment_add_seq_next_2(void)
1423 {
1424     fragment_head *fd_head;
1425 
1426     printf("Starting test test_missing_data_fragment_add_seq_next_2\n");
1427 
1428     pinfo.num = 11;
1429     fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 10, &pinfo, 24, NULL,
1430                                   50, TRUE);
1431 
1432     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1433     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1434     ASSERT_EQ_POINTER(NULL,fd_head);
1435 
1436     pinfo.num = 12;
1437     fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 5, &pinfo, 24, NULL,
1438                                   DATA_LEN-4, FALSE);
1439 
1440     /* XXX: again, i'm really dubious about this. Surely this should return all
1441      * the data we had, for a best-effort attempt at dissecting it?
1442      * And it ought to go into the reassembled table?
1443      */
1444     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.fragment_table));
1445     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1446     ASSERT_EQ_POINTER(NULL,fd_head);
1447 
1448     /* check what happens when we revisit the packets */
1449     pinfo.fd->visited = TRUE;
1450     pinfo.num = 11;
1451 
1452     fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 10, &pinfo, 24, NULL,
1453                                   50, TRUE);
1454 
1455     /* As before, this returns NULL because the fragment isn't in the
1456      * reassembled_table. At least this is a bit more consistent than before.
1457      */
1458     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.fragment_table));
1459     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1460     ASSERT_EQ_POINTER(NULL,fd_head);
1461 
1462     pinfo.num = 12;
1463     fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 5, &pinfo, 24, NULL,
1464                                   DATA_LEN-4, FALSE);
1465     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.fragment_table));
1466     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1467     ASSERT_EQ_POINTER(NULL,fd_head);
1468 
1469 }
1470 
1471 /*
1472  * This time, our datagram only has one segment, but it has data missing.
1473  */
1474 static void
1475 test_missing_data_fragment_add_seq_next_3(void)
1476 {
1477     fragment_head *fd_head;
1478 
1479     printf("Starting test test_missing_data_fragment_add_seq_next_3\n");
1480 
1481     pinfo.num = 20;
1482     fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 5, &pinfo, 30, NULL,
1483                                   DATA_LEN-4, FALSE);
1484 
1485     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.fragment_table));
1486     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.reassembled_table));
1487     ASSERT_NE_POINTER(NULL,fd_head);
1488 
1489     /* check the contents of the structure. */
1490     ASSERT_EQ(0,fd_head->frame);  /* max frame we have */
1491     ASSERT_EQ(0,fd_head->offset); /* unused */
1492     ASSERT_EQ(0,fd_head->len); /* the length of data we have */
1493     ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
1494     ASSERT_EQ(20,fd_head->reassembled_in);
1495     ASSERT_EQ(FD_BLOCKSEQUENCE|FD_DEFRAGMENTED,fd_head->flags);
1496     ASSERT_EQ_POINTER(NULL,fd_head->tvb_data);
1497     ASSERT_EQ_POINTER(NULL,fd_head->next);
1498 
1499     /* revisiting the packet ought to produce the same result. */
1500     pinfo.fd->visited = TRUE;
1501 
1502     pinfo.num = 20;
1503     fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 5, &pinfo, 30, NULL,
1504                                   DATA_LEN-4, FALSE);
1505 
1506     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.fragment_table));
1507     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.reassembled_table));
1508     ASSERT_NE_POINTER(NULL,fd_head);
1509     ASSERT_EQ(0,fd_head->frame);  /* unused */
1510     ASSERT_EQ(0,fd_head->offset); /* unused */
1511     ASSERT_EQ(0,fd_head->len); /* the length of data we have */
1512     ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
1513     ASSERT_EQ(20,fd_head->reassembled_in);
1514     ASSERT_EQ(FD_BLOCKSEQUENCE|FD_DEFRAGMENTED,fd_head->flags);
1515     ASSERT_EQ_POINTER(NULL,fd_head->tvb_data);
1516     ASSERT_EQ_POINTER(NULL,fd_head->next);
1517 }
1518 #endif
1519 
1520 /**********************************************************************************
1521  *
1522  * fragment_add
1523  *
1524  *********************************************************************************/
1525 
1526 /* Simple test case for fragment_add.
1527  * Adds three fragments (out of order, with one for a different datagram in between),
1528  * and checks that they are reassembled correctly.
1529  */
1530 /*   visit  id  frame  frag_offset  len  more  tvb_offset
1531        0    12     1       0        50   T      10
1532        1    12     1       0        60   T       5
1533        0    13     2       0        60   T      15
1534        0    12     3     110        60   F       5
1535        0    12     4      50        60   T      15
1536 */
1537 static void
1538 test_simple_fragment_add(void)
1539 {
1540     fragment_head *fd_head, *fdh0;
1541     fragment_item *fd;
1542 
1543     printf("Starting test test_simple_fragment_add\n");
1544 
1545     pinfo.num = 1;
1546     fd_head=fragment_add(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
1547                          0, 50, TRUE);
1548 
1549     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1550     ASSERT_EQ_POINTER(NULL,fd_head);
1551 
1552     /* adding the same fragment again should do nothing, even with different
1553      * offset etc */
1554     pinfo.fd->visited = 1;
1555     fd_head=fragment_add(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
1556                          0, 60, TRUE);
1557     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1558     ASSERT_EQ_POINTER(NULL,fd_head);
1559 
1560     /* start another pdu (just to confuse things) */
1561     pinfo.fd->visited = 0;
1562     pinfo.num = 2;
1563     fd_head=fragment_add(&test_reassembly_table, tvb, 15, &pinfo, 13, NULL,
1564                          0, 60, TRUE);
1565     ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.fragment_table));
1566     ASSERT_EQ_POINTER(NULL,fd_head);
1567 
1568     /* now we add the terminal fragment of the first datagram */
1569     pinfo.num = 3;
1570     fd_head=fragment_add(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
1571                          110, 60, FALSE);
1572 
1573     /* we haven't got all the fragments yet ... */
1574     ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.fragment_table));
1575     ASSERT_EQ_POINTER(NULL,fd_head);
1576 
1577     /* finally, add the missing fragment */
1578     pinfo.num = 4;
1579     fd_head=fragment_add(&test_reassembly_table, tvb, 15, &pinfo, 12, NULL,
1580                          50, 60, TRUE);
1581 
1582     ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.fragment_table));
1583     ASSERT_NE_POINTER(NULL,fd_head);
1584 
1585     /* check the contents of the structure */
1586     ASSERT_EQ(4,fd_head->frame);  /* max frame number of fragment in assembly */
1587     ASSERT_EQ(0,fd_head->offset); /* unused */
1588     ASSERT_EQ(0,fd_head->len); /* unused in fragment_add */
1589     ASSERT_EQ(170,fd_head->datalen); /* total datalen of assembly */
1590     ASSERT_EQ(4,fd_head->reassembled_in);
1591     ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET,fd_head->flags);
1592     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
1593     ASSERT_NE_POINTER(NULL,fd_head->next);
1594 
1595     fd = fd_head->next;
1596     ASSERT_EQ(1,fd->frame);
1597     ASSERT_EQ(0,fd->offset);  /* offset */
1598     ASSERT_EQ(50,fd->len);    /* segment length */
1599     ASSERT_EQ(0,fd->flags);
1600     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
1601     ASSERT_NE_POINTER(NULL,fd->next);
1602 
1603     fd = fd->next;
1604     ASSERT_EQ(4,fd->frame);
1605     ASSERT_EQ(50,fd->offset); /* offset */
1606     ASSERT_EQ(60,fd->len);    /* segment length */
1607     ASSERT_EQ(0,fd->flags);
1608     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
1609     ASSERT_NE_POINTER(NULL,fd->next);
1610 
1611     fd = fd->next;
1612     ASSERT_EQ(3,fd->frame);
1613     ASSERT_EQ(110,fd->offset); /* offset */
1614     ASSERT_EQ(60,fd->len);     /* segment length */
1615     ASSERT_EQ(0,fd->flags);
1616     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
1617     ASSERT_EQ_POINTER(NULL,fd->next);
1618 
1619     /* test the actual reassembly */
1620     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
1621     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+15,60));
1622     ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,60));
1623 
1624     if (debug) {
1625         print_fragment_table();
1626     }
1627 
1628     /* what happens if we revisit the packets now? */
1629     fdh0 = fd_head;
1630     pinfo.fd->visited = 1;
1631     pinfo.num = 1;
1632     fd_head=fragment_add(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
1633                          0, 50, TRUE);
1634     /*
1635      * this api relies on the caller to check fd_head -> reassembled_in
1636      *
1637      * Redoing all the tests seems like overkill - just check the pointer
1638      */
1639     ASSERT_EQ_POINTER(fdh0,fd_head);
1640 
1641     pinfo.num = 3;
1642     fd_head=fragment_add(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
1643                          110, 60, FALSE);
1644     ASSERT_EQ_POINTER(fdh0,fd_head);
1645 
1646     pinfo.num = 4;
1647     fd_head=fragment_add(&test_reassembly_table, tvb, 15, &pinfo, 12, NULL,
1648                          50, 60, TRUE);
1649     ASSERT_EQ_POINTER(fdh0,fd_head);
1650 
1651     if (debug) {
1652         print_fragment_table();
1653     }
1654 }
1655 
1656 /* This tests the functionality of fragment_set_partial_reassembly for
1657  * fragment_add based reassembly.
1658  *
1659  * We add a sequence of fragments thus:
1660  *    seq_off   frame  tvb_off   len   (initial) more_frags
1661  *    -------   -----  -------   ---   --------------------
1662  *        0       1       10      50   false
1663  *       50       2        0      40   true
1664  *       50       3        0      40   true (a duplicate fragment)
1665  *       90       4       20     100   false
1666  *      190       5        0      40   false
1667  */
1668 static void
1669 test_fragment_add_partial_reassembly(void)
1670 {
1671     fragment_head *fd_head;
1672     fragment_item *fd;
1673 
1674     printf("Starting test test_fragment_add_partial_reassembly\n");
1675 
1676     /* generally it's probably fair to assume that we will be called with
1677      * more_frags=FALSE.
1678      */
1679     pinfo.num = 1;
1680     fd_head=fragment_add(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
1681                              0, 50, FALSE);
1682 
1683     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1684     ASSERT_NE_POINTER(NULL,fd_head);
1685 
1686     /* check the contents of the structure */
1687     ASSERT_EQ(1,fd_head->frame);  /* max frame in reassembly */
1688     ASSERT_EQ(0,fd_head->offset); /* unused */
1689     ASSERT_EQ(0,fd_head->len); /* unused */
1690     ASSERT_EQ(50,fd_head->datalen); /* the length of data we we have */
1691     ASSERT_EQ(1,fd_head->reassembled_in);
1692     ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET,fd_head->flags);
1693     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
1694     ASSERT_NE_POINTER(NULL,fd_head->next);
1695 
1696     ASSERT_EQ(1,fd_head->next->frame);
1697     ASSERT_EQ(0,fd_head->next->offset);  /* offset */
1698     ASSERT_EQ(50,fd_head->next->len);    /* segment length */
1699     ASSERT_EQ(0,fd_head->next->flags);
1700     ASSERT_EQ_POINTER(NULL,fd_head->next->tvb_data);
1701     ASSERT_EQ_POINTER(NULL,fd_head->next->next);
1702 
1703     /* test the actual reassembly */
1704     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
1705 
1706     /* now we announce that the reassembly wasn't complete after all. */
1707     fragment_set_partial_reassembly(&test_reassembly_table, &pinfo, 12, NULL);
1708 
1709     /* and add another segment. To mix things up slightly (and so that we can
1710      * check on the state of things), we're going to set the more_frags flag
1711      * here
1712      */
1713     pinfo.num = 2;
1714     fd_head=fragment_add(&test_reassembly_table, tvb, 0, &pinfo, 12, NULL,
1715                          50, 40, TRUE);
1716 
1717     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1718     ASSERT_EQ_POINTER(NULL,fd_head);
1719 
1720     fd_head=fragment_get(&test_reassembly_table, &pinfo, 12, NULL);
1721     ASSERT_NE_POINTER(NULL,fd_head);
1722 
1723     /* check the contents of the structure */
1724     ASSERT_EQ(2,fd_head->frame);   /* max frame in reassembly */
1725     ASSERT_EQ(0,fd_head->offset);  /* unused */
1726     ASSERT_EQ(0,fd_head->len);     /* unused */
1727     /* ASSERT_EQ(0,fd_head->datalen);
1728      * reassembly not finished; datalen not well defined.
1729      * Current implemenation has it as 0, could change to 90 without issues */
1730     ASSERT_EQ(0,fd_head->reassembled_in);
1731     ASSERT_EQ(0,fd_head->flags);
1732     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
1733     ASSERT_NE_POINTER(NULL,fd_head->next);
1734 
1735     fd=fd_head->next;
1736     ASSERT_EQ(1,fd->frame);
1737     ASSERT_EQ(0,fd->offset);  /* offset */
1738     ASSERT_EQ(50,fd->len);    /* segment length */
1739     ASSERT_EQ(FD_SUBSET_TVB,fd->flags);
1740     ASSERT_EQ_POINTER(tvb_get_ptr(fd_head->tvb_data,0,0),tvb_get_ptr(fd->tvb_data,0,0));
1741     ASSERT_NE_POINTER(NULL,fd->next);
1742 
1743     fd=fd->next;
1744     ASSERT_EQ(2,fd->frame);
1745     ASSERT_EQ(50,fd->offset); /* offset */
1746     ASSERT_EQ(40,fd->len);    /* segment length */
1747     ASSERT_EQ(0,fd->flags);
1748     ASSERT_NE_POINTER(NULL,fd->tvb_data);
1749     ASSERT_EQ_POINTER(NULL,fd->next);
1750 
1751     /* Another copy of the second segment.
1752      */
1753     pinfo.num = 3;
1754     fd_head=fragment_add(&test_reassembly_table, tvb, 0, &pinfo, 12, NULL,
1755                          50, 40, TRUE);
1756 
1757     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1758     ASSERT_EQ_POINTER(NULL,fd_head);
1759     fd_head=fragment_get(&test_reassembly_table, &pinfo, 12, NULL);
1760     ASSERT_NE_POINTER(NULL,fd_head);
1761     ASSERT_EQ(3,fd_head->frame);   /* max frame we have */
1762     ASSERT_EQ(0,fd_head->offset);  /* unused */
1763     ASSERT_EQ(0,fd_head->len);     /* unused */
1764     /* ASSERT_EQ(0,fd_head->datalen);
1765      * reassembly not finished; datalen not well defined.
1766      * Current implemenation has it as 0, could change to 90 without issues */
1767     ASSERT_EQ(0,fd_head->reassembled_in);
1768     ASSERT_EQ(0,fd_head->flags);
1769     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
1770     ASSERT_NE_POINTER(NULL,fd_head->next);
1771 
1772     fd=fd_head->next;
1773     ASSERT_EQ(1,fd->frame);
1774     ASSERT_EQ(0,fd->offset);
1775     ASSERT_EQ(50,fd->len);    /* segment length */
1776     ASSERT_EQ(FD_SUBSET_TVB,fd->flags);
1777     ASSERT_EQ_POINTER(tvb_get_ptr(fd_head->tvb_data,0,0),tvb_get_ptr(fd->tvb_data,0,0));
1778     ASSERT_NE_POINTER(NULL,fd->next);
1779 
1780     fd=fd->next;
1781     ASSERT_EQ(2,fd->frame);
1782     ASSERT_EQ(50,fd->offset);
1783     ASSERT_EQ(40,fd->len);    /* segment length */
1784     ASSERT_EQ(0,fd->flags);
1785     ASSERT_NE_POINTER(NULL,fd->tvb_data);
1786     ASSERT_NE_POINTER(NULL,fd->next);
1787 
1788     fd=fd->next;
1789     ASSERT_EQ(3,fd->frame);
1790     ASSERT_EQ(50,fd->offset);
1791     ASSERT_EQ(40,fd->len);    /* segment length */
1792     ASSERT_EQ(0,fd->flags);
1793     ASSERT_NE_POINTER(NULL,fd->tvb_data);
1794     ASSERT_EQ_POINTER(NULL,fd->next);
1795 
1796 
1797 
1798     /* have another go at wrapping things up */
1799     pinfo.num = 4;
1800     fd_head=fragment_add(&test_reassembly_table, tvb, 20, &pinfo, 12, NULL,
1801                          90, 100, FALSE);
1802 
1803     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1804     ASSERT_NE_POINTER(NULL,fd_head);
1805 
1806     /* check the contents of the structure */
1807     ASSERT_EQ(4,fd_head->frame);  /* max frame we have */
1808     ASSERT_EQ(0,fd_head->offset); /* unused */
1809     ASSERT_EQ(0,fd_head->len); /* unused */
1810     ASSERT_EQ(190,fd_head->datalen); /* the length of data we have */
1811     ASSERT_EQ(4,fd_head->reassembled_in);
1812     ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
1813     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
1814     ASSERT_NE_POINTER(NULL,fd_head->next);
1815 
1816     fd=fd_head->next;
1817     ASSERT_EQ(1,fd->frame);
1818     ASSERT_EQ(0,fd->offset);
1819     ASSERT_EQ(50,fd->len);    /* segment length */
1820     ASSERT_EQ(0,fd->flags);
1821     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
1822     ASSERT_NE_POINTER(NULL,fd->next);
1823 
1824     fd=fd->next;
1825     ASSERT_EQ(2,fd->frame);
1826     ASSERT_EQ(50,fd->offset);
1827     ASSERT_EQ(40,fd->len);    /* segment length */
1828     ASSERT_EQ(0,fd->flags);
1829     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
1830     ASSERT_NE_POINTER(NULL,fd->next);
1831 
1832     fd=fd->next;
1833     ASSERT_EQ(3,fd->frame);
1834     ASSERT_EQ(50,fd->offset);
1835     ASSERT_EQ(40,fd->len);    /* segment length */
1836     ASSERT_EQ(FD_OVERLAP,fd->flags);
1837     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
1838     ASSERT_NE_POINTER(NULL,fd->next);
1839 
1840     fd=fd->next;
1841     ASSERT_EQ(4,fd->frame);
1842     ASSERT_EQ(90,fd->offset);
1843     ASSERT_EQ(100,fd->len);    /* segment length */
1844     ASSERT_EQ(0,fd->flags);
1845     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
1846     ASSERT_EQ_POINTER(NULL,fd->next);
1847 
1848     /* test the actual reassembly */
1849     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
1850     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data,40));
1851     ASSERT(!tvb_memeql(fd_head->tvb_data,90,data+20,100));
1852 
1853 
1854     /* do it again (this time it is more complicated, with an overlap in the
1855      * reassembly) */
1856 
1857     fragment_set_partial_reassembly(&test_reassembly_table, &pinfo, 12, NULL);
1858 
1859     pinfo.num = 5;
1860     fragment_add(&test_reassembly_table, tvb, 0, &pinfo, 12, NULL,
1861                  190, 40, FALSE);
1862 
1863     fd_head=fragment_get(&test_reassembly_table, &pinfo, 12, NULL);
1864     ASSERT_NE_POINTER(NULL,fd_head);
1865     ASSERT_EQ(5,fd_head->frame);   /* max frame we have */
1866     ASSERT_EQ(0,fd_head->offset);  /* unused */
1867     ASSERT_EQ(0,fd_head->len);   /* unused */
1868     ASSERT_EQ(230,fd_head->datalen); /* the length of data we have */
1869     ASSERT_EQ(5,fd_head->reassembled_in);
1870     ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
1871     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
1872     ASSERT_NE_POINTER(NULL,fd_head->next);
1873 
1874     fd=fd_head->next;
1875     ASSERT_EQ(1,fd->frame);
1876     ASSERT_EQ(0,fd->offset);
1877     ASSERT_EQ(50,fd->len);    /* segment length */
1878     ASSERT_EQ(0,fd->flags);
1879     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
1880     ASSERT_NE_POINTER(NULL,fd->next);
1881 
1882     fd=fd->next;
1883     ASSERT_EQ(2,fd->frame);
1884     ASSERT_EQ(50,fd->offset);
1885     ASSERT_EQ(40,fd->len);    /* segment length */
1886     ASSERT_EQ(0,fd->flags);
1887     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
1888     ASSERT_NE_POINTER(NULL,fd->next);
1889 
1890     fd=fd->next;
1891     ASSERT_EQ(3,fd->frame);
1892     ASSERT_EQ(50,fd->offset);
1893     ASSERT_EQ(40,fd->len);    /* segment length */
1894     ASSERT_EQ(FD_OVERLAP,fd->flags);
1895     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
1896     ASSERT_NE_POINTER(NULL,fd->next);
1897 
1898     fd=fd->next;
1899     ASSERT_EQ(4,fd->frame);
1900     ASSERT_EQ(90,fd->offset);
1901     ASSERT_EQ(100,fd->len);   /* segment length */
1902     ASSERT_EQ(0,fd->flags);
1903     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
1904     ASSERT_NE_POINTER(NULL,fd->next);
1905 
1906     fd=fd->next;
1907     ASSERT_EQ(5,fd->frame);
1908     ASSERT_EQ(190,fd->offset);
1909     ASSERT_EQ(40,fd->len);    /* segment length */
1910     ASSERT_EQ(0,fd->flags);
1911     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
1912     ASSERT_EQ_POINTER(NULL,fd->next);
1913 
1914     /* test the actual reassembly */
1915     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
1916     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data,40));
1917     ASSERT(!tvb_memeql(fd_head->tvb_data,90,data+20,100));
1918     ASSERT(!tvb_memeql(fd_head->tvb_data,190,data,40));
1919 }
1920 
1921 /* XXX: Is the proper behavior here really throwing an exception instead
1922  * of setting FD_OVERLAP?
1923  */
1924 /* Test case for fragment_add with duplicated (e.g., retransmitted) data.
1925  * Adds three fragments--adding the 1st one twice at the end--
1926  * and checks that they are reassembled correctly.
1927  */
1928 /*   visit  id  frame  frag_off  len  more  tvb_offset
1929        0    12     1        0    50   T      10
1930        0    12     2       50    60   T      5
1931        0    12     3      110    40   F      5
1932        0    12     4        0    50   T      10
1933 */
1934 static void
1935 test_fragment_add_duplicate_first(void)
1936 {
1937     fragment_head *fd_head;
1938     fragment_item *fd;
1939     volatile gboolean ex_thrown;
1940 
1941     printf("Starting test test_fragment_add_duplicate_first\n");
1942 
1943     pinfo.num = 1;
1944     fd_head=fragment_add(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
1945                          0, 50, TRUE);
1946 
1947     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1948     ASSERT_EQ_POINTER(NULL,fd_head);
1949 
1950     /* Add the 2nd segment */
1951     pinfo.num = 2;
1952     fd_head=fragment_add(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
1953                          50, 60, TRUE);
1954 
1955     /* we haven't got all the fragments yet ... */
1956     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1957     ASSERT_EQ_POINTER(NULL,fd_head);
1958 
1959     /* Add the last fragment */
1960     pinfo.num = 3;
1961     fd_head=fragment_add(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
1962                          110, 40, FALSE);
1963 
1964     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1965     ASSERT_NE_POINTER(NULL,fd_head);
1966 
1967     /* Add the first fragment again */
1968     pinfo.num = 4;
1969     /* XXX: The current reassemble.c code for fragment_add() throws an
1970      * exception and doesn't try to add a duplicate if and only if the
1971      * assembly is already completed. This means that it doesn't get
1972      * put in the linked list. This is counter to how the _seq functions
1973      * work, as well as to how this code works if a duplicate comes in the
1974      * middle instead of at the end. Test matches current code, but the
1975      * current code should perhaps be changed. */
1976     ex_thrown = FALSE;
1977     TRY {
1978     fd_head=fragment_add(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
1979                          0, 50, TRUE);
1980     }
1981     CATCH(ReassemblyError) {
1982         ex_thrown = TRUE;
1983     }
1984     ENDTRY;
1985 
1986     ASSERT_EQ(TRUE, ex_thrown);
1987 
1988     /* Reassembly should have still succeeded */
1989     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1990     ASSERT_NE_POINTER(NULL,fd_head);
1991 
1992     /* check the contents of the structure */
1993     /*ASSERT_EQ(4,fd_head->frame);  max frame we have */
1994     ASSERT_EQ(3,fd_head->frame);  /* never add the duplicate frame */
1995     ASSERT_EQ(0,fd_head->offset); /* unused */
1996     ASSERT_EQ(0,fd_head->len); /* unused */
1997     ASSERT_EQ(150,fd_head->datalen);
1998     ASSERT_EQ(3,fd_head->reassembled_in);
1999     /* ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags); */
2000     /* FD_OVERLAP doesn't get set because we hit the exception early */
2001     ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET,fd_head->flags);
2002     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
2003     ASSERT_NE_POINTER(NULL,fd_head->next);
2004 
2005     fd = fd_head->next;
2006 
2007     ASSERT_EQ(1,fd->frame);
2008     ASSERT_EQ(0,fd->offset);
2009     ASSERT_EQ(50,fd->len);    /* segment length */
2010     ASSERT_EQ(0,fd->flags);
2011     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2012     ASSERT_NE_POINTER(NULL,fd->next);
2013 
2014     /*
2015     fd = fd_head->next;
2016     ASSERT_EQ(4,fd->frame);
2017     ASSERT_EQ(0,fd->offset);
2018     ASSERT_EQ(50,fd->len);
2019     ASSERT_EQ(FD_OVERLAP,fd->flags);
2020     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2021     ASSERT_NE_POINTER(NULL,fd->next); */
2022 
2023     fd = fd->next;
2024     ASSERT_EQ(2,fd->frame);
2025     ASSERT_EQ(50,fd->offset);
2026     ASSERT_EQ(60,fd->len);    /* segment length */
2027     ASSERT_EQ(0,fd->flags);
2028     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2029     ASSERT_NE_POINTER(NULL,fd->next);
2030 
2031     fd = fd->next;
2032     ASSERT_EQ(3,fd->frame);
2033     ASSERT_EQ(110,fd->offset);
2034     ASSERT_EQ(40,fd->len);    /* segment length */
2035     ASSERT_EQ(0,fd->flags);
2036     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2037     ASSERT_EQ_POINTER(NULL,fd->next);
2038 
2039     /* test the actual reassembly */
2040     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
2041     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+5,60));
2042     ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,40));
2043 
2044     if (debug) {
2045         print_fragment_table();
2046     }
2047 }
2048 
2049 
2050 /* Test case for fragment_add with duplicated (e.g., retransmitted) data.
2051  * Adds three fragments--adding the 2nd one twice--
2052  * and checks that they are reassembled correctly.
2053  */
2054 /*   visit  id  frame  frag_off  len  more  tvb_offset
2055        0    12     1       0     50   T      10
2056        0    12     2      50     60   T      5
2057        0    12     3      50     60   T      5
2058        0    12     4     110     40   F      5
2059 */
2060 static void
2061 test_fragment_add_duplicate_middle(void)
2062 {
2063     fragment_head *fd_head;
2064     fragment_item *fd;
2065 
2066     printf("Starting test test_fragment_add_duplicate_middle\n");
2067 
2068     pinfo.num = 1;
2069     fd_head=fragment_add(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
2070                          0, 50, TRUE);
2071 
2072     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2073     ASSERT_EQ_POINTER(NULL,fd_head);
2074 
2075     /* Add the 2nd segment */
2076     pinfo.num = 2;
2077     fd_head=fragment_add(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
2078                          50, 60, TRUE);
2079 
2080     /* we haven't got all the fragments yet ... */
2081     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2082     ASSERT_EQ_POINTER(NULL,fd_head);
2083 
2084     /* Now, add the 2nd segment again (but in a different frame) */
2085     pinfo.num = 3;
2086     fd_head=fragment_add(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
2087                          50, 60, TRUE);
2088 
2089     /* This duplicate fragment should have been ignored */
2090     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2091     ASSERT_EQ_POINTER(NULL,fd_head);
2092 
2093     /* finally, add the last fragment */
2094     pinfo.num = 4;
2095     fd_head=fragment_add(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
2096                          110, 40, FALSE);
2097 
2098     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2099     ASSERT_NE_POINTER(NULL,fd_head);
2100 
2101     /* check the contents of the structure */
2102     ASSERT_EQ(4,fd_head->frame);  /* max frame we have */
2103     ASSERT_EQ(0,fd_head->offset); /* unused */
2104     ASSERT_EQ(0,fd_head->len); /* unused */
2105     ASSERT_EQ(150,fd_head->datalen);
2106     ASSERT_EQ(4,fd_head->reassembled_in);
2107     ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
2108     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
2109     ASSERT_NE_POINTER(NULL,fd_head->next);
2110 
2111     fd = fd_head->next;
2112     ASSERT_EQ(1,fd->frame);
2113     ASSERT_EQ(0,fd->offset);
2114     ASSERT_EQ(50,fd->len);    /* segment length */
2115     ASSERT_EQ(0,fd->flags);
2116     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2117     ASSERT_NE_POINTER(NULL,fd->next);
2118 
2119     fd = fd->next;
2120     ASSERT_EQ(2,fd->frame);
2121     ASSERT_EQ(50,fd->offset);
2122     ASSERT_EQ(60,fd->len);    /* segment length */
2123     ASSERT_EQ(0,fd->flags);
2124     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2125     ASSERT_NE_POINTER(NULL,fd->next);
2126 
2127     fd = fd->next;
2128     ASSERT_EQ(3,fd->frame);
2129     ASSERT_EQ(50,fd->offset);
2130     ASSERT_EQ(60,fd->len);    /* segment length */
2131     ASSERT_EQ(FD_OVERLAP,fd->flags);
2132     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2133     ASSERT_NE_POINTER(NULL,fd->next);
2134 
2135     fd = fd->next;
2136     ASSERT_EQ(4,fd->frame);
2137     ASSERT_EQ(110,fd->offset);
2138     ASSERT_EQ(40,fd->len);    /* segment length */
2139     ASSERT_EQ(0,fd->flags);
2140     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2141     ASSERT_EQ_POINTER(NULL,fd->next);
2142 
2143     /* test the actual reassembly */
2144     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
2145     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+5,60));
2146     ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,40));
2147 
2148     if (debug) {
2149         print_fragment_table();
2150     }
2151 }
2152 
2153 /* XXX: Is the proper behavior here really throwing an exception instead
2154  * of setting FD_OVERLAP?
2155  */
2156 /* Test case for fragment_add with duplicated (e.g., retransmitted) data.
2157  * Adds three fragments--adding the 3rd one twice--
2158  * and checks that they are reassembled correctly.
2159  */
2160 /*   visit  id  frame  frag  len  more  tvb_offset
2161        0    12     1     0    50   T      10
2162        0    12     2     1    60   T      5
2163        0    12     3     2    40   F      5
2164        0    12     4     2    40   F      5
2165 */
2166 static void
2167 test_fragment_add_duplicate_last(void)
2168 {
2169     fragment_head *fd_head;
2170     fragment_item *fd;
2171     volatile gboolean ex_thrown;
2172 
2173     printf("Starting test test_fragment_add_duplicate_last\n");
2174 
2175     pinfo.num = 1;
2176     fd_head=fragment_add(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
2177                          0, 50, TRUE);
2178 
2179     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2180     ASSERT_EQ_POINTER(NULL,fd_head);
2181 
2182     /* Add the 2nd segment */
2183     pinfo.num = 2;
2184     fd_head=fragment_add(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
2185                          50, 60, TRUE);
2186 
2187     /* we haven't got all the fragments yet ... */
2188     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2189     ASSERT_EQ_POINTER(NULL,fd_head);
2190 
2191     /* Add the last fragment */
2192     pinfo.num = 3;
2193     fd_head=fragment_add(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
2194                          110, 40, FALSE);
2195 
2196     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2197     ASSERT_NE_POINTER(NULL,fd_head);
2198 
2199     /* Add the last fragment again */
2200     pinfo.num = 4;
2201     /* XXX: The current reassemble.c code for fragment_add() throws an
2202      * exception and doesn't try to add a duplicate if and only if the
2203      * assembly is already completed. This means that it doesn't get
2204      * put in the linked list. This is counter to how the _seq functions
2205      * work, as well as to how this code works if a duplicate comes in the
2206      * middle instead of at the end. Test matches current code, but the
2207      * current code should perhaps be changed. */
2208     ex_thrown = FALSE;
2209     TRY {
2210     fd_head=fragment_add(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
2211                          110, 40, FALSE);
2212     }
2213     CATCH(ReassemblyError) {
2214         ex_thrown = TRUE;
2215     }
2216     ENDTRY;
2217 
2218     ASSERT_EQ(TRUE, ex_thrown);
2219 
2220     /* Reassembly should have still succeeded */
2221     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2222     ASSERT_NE_POINTER(NULL,fd_head);
2223 
2224     /* check the contents of the structure */
2225     /* ASSERT_EQ(4,fd_head->frame); never add the last frame again */
2226     ASSERT_EQ(3,fd_head->frame);  /* max frame we have */
2227     ASSERT_EQ(0,fd_head->offset); /* unused */
2228     ASSERT_EQ(0,fd_head->len); /* unused */
2229     ASSERT_EQ(150,fd_head->datalen);
2230     ASSERT_EQ(3,fd_head->reassembled_in);
2231     /* ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
2232      * FD_OVERLAP doesn't get set since we don't add a fragment after the
2233      * end but throw an exception instead. */
2234     ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET,fd_head->flags);
2235     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
2236     ASSERT_NE_POINTER(NULL,fd_head->next);
2237 
2238     fd = fd_head->next;
2239     ASSERT_EQ(1,fd->frame);
2240     ASSERT_EQ(0,fd->offset);
2241     ASSERT_EQ(50,fd->len);    /* segment length */
2242     ASSERT_EQ(0,fd->flags);
2243     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2244     ASSERT_NE_POINTER(NULL,fd->next);
2245 
2246     fd = fd->next;
2247     ASSERT_EQ(2,fd->frame);
2248     ASSERT_EQ(50,fd->offset);
2249     ASSERT_EQ(60,fd->len);    /* segment length */
2250     ASSERT_EQ(0,fd->flags);
2251     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2252     ASSERT_NE_POINTER(NULL,fd->next);
2253 
2254     fd = fd->next;
2255     ASSERT_EQ(3,fd->frame);
2256     ASSERT_EQ(110,fd->offset);
2257     ASSERT_EQ(40,fd->len);    /* segment length */
2258     ASSERT_EQ(0,fd->flags);
2259     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2260 
2261     /* Duplicate packet never gets added
2262     ASSERT_NE_POINTER(NULL,fd->next);
2263 
2264     fd = fd->next;
2265     ASSERT_EQ(4,fd->frame);
2266     ASSERT_EQ(110,fd->offset);
2267     ASSERT_EQ(40,fd->len);
2268     ASSERT_EQ(FD_OVERLAP,fd->flags);
2269     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2270     ASSERT_EQ_POINTER(NULL,fd->next); */
2271 
2272     /* test the actual reassembly */
2273     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
2274     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+5,60));
2275     ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,40));
2276 
2277     if (debug) {
2278         print_fragment_table();
2279     }
2280 }
2281 
2282 /* Test case for fragment_add with duplicated (e.g., retransmitted) data
2283  * where the retransmission "conflicts" with the original transmission
2284  * (contents are different).
2285  * Adds three fragments--adding the 2nd one twice--
2286  * and checks that they are reassembled correctly.
2287  */
2288 /*   visit  id  frame  frag_off  len  more  tvb_offset
2289        0    12     1       0     50   T      10
2290        0    12     2      50     60   T      5
2291        0    12     3      50     60   T      15
2292        0    12     4     110     40   F      5
2293 */
2294 static void
2295 test_fragment_add_duplicate_conflict(void)
2296 {
2297     fragment_head *fd_head;
2298     fragment_item *fd;
2299 
2300     printf("Starting test test_fragment_add_duplicate_conflict\n");
2301 
2302     pinfo.num = 1;
2303     fd_head=fragment_add(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
2304                          0, 50, TRUE);
2305 
2306     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2307     ASSERT_EQ_POINTER(NULL,fd_head);
2308 
2309     /* Add the 2nd segment */
2310     pinfo.num = 2;
2311     fd_head=fragment_add(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
2312                          50, 60, TRUE);
2313 
2314     /* we haven't got all the fragments yet ... */
2315     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2316     ASSERT_EQ_POINTER(NULL,fd_head);
2317 
2318     /* Now, add the 2nd segment again (but in a different frame and with
2319      * different data)
2320      */
2321     pinfo.num = 3;
2322     fd_head=fragment_add(&test_reassembly_table, tvb, 15, &pinfo, 12, NULL,
2323                          50, 60, TRUE);
2324 
2325     /* This duplicate fragment should have been ignored */
2326     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2327     ASSERT_EQ_POINTER(NULL,fd_head);
2328 
2329     /* finally, add the last fragment */
2330     pinfo.num = 4;
2331     fd_head=fragment_add(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
2332                          110, 40, FALSE);
2333 
2334     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2335     ASSERT_NE_POINTER(NULL,fd_head);
2336 
2337     /* check the contents of the structure */
2338     ASSERT_EQ(4,fd_head->frame);  /* max frame we have */
2339     ASSERT_EQ(0,fd_head->offset); /* unused */
2340     ASSERT_EQ(0,fd_head->len); /* unused */
2341     ASSERT_EQ(150,fd_head->datalen);
2342     ASSERT_EQ(4,fd_head->reassembled_in);
2343     ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET|FD_OVERLAP|FD_OVERLAPCONFLICT,fd_head->flags);
2344     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
2345     ASSERT_NE_POINTER(NULL,fd_head->next);
2346 
2347     fd = fd_head->next;
2348     ASSERT_EQ(1,fd->frame);
2349     ASSERT_EQ(0,fd->offset);
2350     ASSERT_EQ(50,fd->len);    /* segment length */
2351     ASSERT_EQ(0,fd->flags);
2352     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2353     ASSERT_NE_POINTER(NULL,fd->next);
2354 
2355     fd = fd->next;
2356     ASSERT_EQ(2,fd->frame);
2357     ASSERT_EQ(50,fd->offset);
2358     ASSERT_EQ(60,fd->len);    /* segment length */
2359     ASSERT_EQ(0,fd->flags);
2360     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2361     ASSERT_NE_POINTER(NULL,fd->next);
2362 
2363     fd = fd->next;
2364     ASSERT_EQ(3,fd->frame);
2365     ASSERT_EQ(50,fd->offset);
2366     ASSERT_EQ(60,fd->len);    /* segment length */
2367     ASSERT_EQ(FD_OVERLAP|FD_OVERLAPCONFLICT,fd->flags);
2368     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2369     ASSERT_NE_POINTER(NULL,fd->next);
2370 
2371     fd = fd->next;
2372     ASSERT_EQ(4,fd->frame);
2373     ASSERT_EQ(110,fd->offset);
2374     ASSERT_EQ(40,fd->len);    /* segment length */
2375     ASSERT_EQ(0,fd->flags);
2376     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2377     ASSERT_EQ_POINTER(NULL,fd->next);
2378 
2379     /* test the actual reassembly */
2380     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
2381     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+5,60));
2382     ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,40));
2383 
2384     if (debug) {
2385         print_fragment_table();
2386     }
2387 }
2388 
2389 /**********************************************************************************
2390  *
2391  * fragment_add_check
2392  *
2393  *********************************************************************************/
2394 
2395 /* Simple test case for fragment_add_check.
2396  * Adds three fragments (out of order, with one for a different datagram in between),
2397  * and checks that they are reassembled correctly.
2398  */
2399 /*   visit  id  frame  frag_offset  len  more  tvb_offset
2400        0    12     1       0        50   T      10
2401        1    12     1       0        60   T       5
2402        0    13     2       0        60   T      15
2403        0    12     3     110        60   F       5
2404        0    12     4      50        60   T      15
2405 */
2406 static void
2407 test_simple_fragment_add_check(void)
2408 {
2409     fragment_head *fd_head, *fdh0;
2410     fragment_item *fd;
2411 
2412     printf("Starting test test_simple_fragment_add_check\n");
2413 
2414     pinfo.num = 1;
2415     fd_head=fragment_add_check(&test_reassembly_table, tvb, 10, &pinfo, 12,
2416                                NULL, 0, 50, TRUE);
2417 
2418     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2419     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
2420     ASSERT_EQ_POINTER(NULL,fd_head);
2421 
2422     /* adding the same fragment again should do nothing, even with different
2423      * offset etc */
2424     pinfo.fd->visited = 1;
2425     fd_head=fragment_add_check(&test_reassembly_table, tvb, 5, &pinfo, 12,
2426                                NULL, 0, 60, TRUE);
2427     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2428     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
2429     ASSERT_EQ_POINTER(NULL,fd_head);
2430 
2431     /* start another pdu (just to confuse things) */
2432     pinfo.fd->visited = 0;
2433     pinfo.num = 2;
2434     fd_head=fragment_add_check(&test_reassembly_table, tvb, 15, &pinfo, 13,
2435                                NULL, 0, 60, TRUE);
2436     ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.fragment_table));
2437     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
2438     ASSERT_EQ_POINTER(NULL,fd_head);
2439 
2440     /* now we add the terminal fragment of the first datagram */
2441     pinfo.num = 3;
2442     fd_head=fragment_add_check(&test_reassembly_table, tvb, 5, &pinfo, 12,
2443                                NULL, 110, 60, FALSE);
2444 
2445     /* we haven't got all the fragments yet ... */
2446     ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.fragment_table));
2447     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
2448     ASSERT_EQ_POINTER(NULL,fd_head);
2449 
2450     /* finally, add the missing fragment */
2451     pinfo.num = 4;
2452     fd_head=fragment_add_check(&test_reassembly_table, tvb, 15, &pinfo, 12,
2453                                NULL, 50, 60, TRUE);
2454 
2455     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2456     ASSERT_EQ(3,g_hash_table_size(test_reassembly_table.reassembled_table));
2457     ASSERT_NE_POINTER(NULL,fd_head);
2458 
2459     /* check the contents of the structure */
2460     ASSERT_EQ(4,fd_head->frame);  /* max frame number of fragment in assembly */
2461     ASSERT_EQ(0,fd_head->offset); /* unused */
2462     ASSERT_EQ(0,fd_head->len); /* unused in fragment_add */
2463     ASSERT_EQ(170,fd_head->datalen); /* total datalen of assembly */
2464     ASSERT_EQ(4,fd_head->reassembled_in);
2465     ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET,fd_head->flags);
2466     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
2467     ASSERT_NE_POINTER(NULL,fd_head->next);
2468 
2469     fd = fd_head->next;
2470     ASSERT_EQ(1,fd->frame);
2471     ASSERT_EQ(0,fd->offset);
2472     ASSERT_EQ(50,fd->len);    /* segment length */
2473     ASSERT_EQ(0,fd->flags);
2474     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2475     ASSERT_NE_POINTER(NULL,fd->next);
2476 
2477     fd = fd->next;
2478     ASSERT_EQ(4,fd->frame);
2479     ASSERT_EQ(50,fd->offset);
2480     ASSERT_EQ(60,fd->len);    /* segment length */
2481     ASSERT_EQ(0,fd->flags);
2482     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2483     ASSERT_NE_POINTER(NULL,fd->next);
2484 
2485     fd = fd->next;
2486     ASSERT_EQ(3,fd->frame);
2487     ASSERT_EQ(110,fd->offset);
2488     ASSERT_EQ(60,fd->len);     /* segment length */
2489     ASSERT_EQ(0,fd->flags);
2490     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2491     ASSERT_EQ_POINTER(NULL,fd->next);
2492 
2493     /* test the actual reassembly */
2494     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
2495     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+15,60));
2496     ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,60));
2497 
2498     if (debug) {
2499         print_fragment_table();
2500     }
2501 
2502     /* what happens if we revisit the packets now? */
2503     fdh0 = fd_head;
2504     pinfo.fd->visited = 1;
2505     pinfo.num = 1;
2506     fd_head=fragment_add_check(&test_reassembly_table, tvb, 10, &pinfo, 12,
2507                                NULL, 0, 50, TRUE);
2508     /*
2509      * this api relies on the caller to check fd_head -> reassembled_in
2510      *
2511      * Redoing all the tests seems like overkill - just check the pointer
2512      */
2513     ASSERT_EQ_POINTER(fdh0,fd_head);
2514 
2515     pinfo.num = 3;
2516     fd_head=fragment_add_check(&test_reassembly_table, tvb, 5, &pinfo, 12,
2517                                NULL, 110, 60, FALSE);
2518     ASSERT_EQ_POINTER(fdh0,fd_head);
2519 
2520     pinfo.num = 4;
2521     fd_head=fragment_add_check(&test_reassembly_table, tvb, 15, &pinfo, 12,
2522                                NULL, 50, 60, TRUE);
2523     ASSERT_EQ_POINTER(fdh0,fd_head);
2524 
2525     if (debug) {
2526         print_fragment_table();
2527     }
2528 }
2529 
2530 #if 0
2531 /* XXX: fragment_set_partial_reassembly() does not work for fragment_add_check
2532  * because it doesn't remove the previously completed reassembly from
2533  * reassembled_table (and lookup_fd_head() only looks in the fragment
2534  * table, not the reassembled_table) */
2535 /* This tests the functionality of fragment_set_partial_reassembly for
2536  * fragment_add_check based reassembly.
2537  *
2538  * We add a sequence of fragments thus:
2539  *    seq_off   frame  tvb_off   len   (initial) more_frags
2540  *    -------   -----  -------   ---   --------------------
2541  *        0       1       10      50   false
2542  *       50       2        0      40   true
2543  *       50       3        0      40   true (a duplicate fragment)
2544  *       90       4       20     100   false
2545  *      190       5        0      40   false
2546  */
2547 static void
2548 test_fragment_add_check_partial_reassembly(void)
2549 {
2550     fragment_head *fd_head;
2551     fragment_item *fd;
2552 
2553     printf("Starting test test_fragment_add_check_partial_reassembly\n");
2554 
2555     /* generally it's probably fair to assume that we will be called with
2556      * more_frags=FALSE.
2557      */
2558     pinfo.num = 1;
2559     fd_head=fragment_add_check(&test_reassembly_table, tvb, 10, &pinfo, 12,
2560                                NULL, 0, 50, FALSE);
2561 
2562     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.fragment_table));
2563     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.reassembled_table));
2564     ASSERT_NE_POINTER(NULL,fd_head);
2565 
2566     /* check the contents of the structure */
2567     ASSERT_EQ(1,fd_head->frame);  /* max frame in reassembly */
2568     ASSERT_EQ(0,fd_head->offset); /* unused */
2569     ASSERT_EQ(0,fd_head->len); /* unused */
2570     ASSERT_EQ(50,fd_head->datalen); /* the length of data we we have */
2571     ASSERT_EQ(1,fd_head->reassembled_in);
2572     ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET,fd_head->flags);
2573     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
2574     ASSERT_NE_POINTER(NULL,fd_head->next);
2575 
2576     ASSERT_EQ(1,fd_head->next->frame);
2577     ASSERT_EQ(0,fd_head->next->offset);  /* offset */
2578     ASSERT_EQ(50,fd_head->next->len);    /* segment length */
2579     ASSERT_EQ(0,fd_head->next->flags);
2580     ASSERT_EQ_POINTER(NULL,fd_head->next->tvb_data);
2581     ASSERT_EQ_POINTER(NULL,fd_head->next->next);
2582 
2583     /* test the actual reassembly */
2584     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
2585 
2586     /* now we announce that the reassembly wasn't complete after all. */
2587     fragment_set_partial_reassembly(&test_reassembly_table, &pinfo, 12, NULL);
2588 
2589     /* and add another segment. To mix things up slightly (and so that we can
2590      * check on the state of things), we're going to set the more_frags flag
2591      * here
2592      */
2593     pinfo.num = 2;
2594     fd_head=fragment_add_check(&test_reassembly_table, tvb, 0, &pinfo, 12,
2595                                NULL, 50, 40, TRUE);
2596 
2597     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2598     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.reassembled_table));
2599     ASSERT_EQ_POINTER(NULL,fd_head);
2600 
2601     fd_head=fragment_get(&test_reassembly_table, &pinfo, 12, NULL);
2602     ASSERT_NE_POINTER(NULL,fd_head);
2603 
2604     /* check the contents of the structure */
2605     ASSERT_EQ(2,fd_head->frame);   /* max frame in reassembly */
2606     ASSERT_EQ(0,fd_head->offset);  /* unused */
2607     ASSERT_EQ(0,fd_head->len);     /* unused */
2608     /* ASSERT_EQ(0,fd_head->datalen);
2609      * reassembly not finished; datalen not well defined.
2610      * Current implemenation has it as 0, could change to 90 without issues */
2611     ASSERT_EQ(0,fd_head->reassembled_in);
2612     ASSERT_EQ(0,fd_head->flags);
2613     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
2614     ASSERT_NE_POINTER(NULL,fd_head->next);
2615 
2616     fd=fd_head->next;
2617     ASSERT_EQ(1,fd->frame);
2618     ASSERT_EQ(0,fd->offset);  /* offset */
2619     ASSERT_EQ(50,fd->len);    /* segment length */
2620     ASSERT_EQ(FD_SUBSET_TVB,fd->flags);
2621     ASSERT_EQ_POINTER(tvb_get_ptr(fd_head->tvb_data,0,0),tvb_get_ptr(fd->tvb_data,0,0));
2622     ASSERT_NE_POINTER(NULL,fd->next);
2623 
2624     fd=fd->next;
2625     ASSERT_EQ(2,fd->frame);
2626     ASSERT_EQ(50,fd->offset); /* offset */
2627     ASSERT_EQ(40,fd->len);    /* segment length */
2628     ASSERT_EQ(0,fd->flags);
2629     ASSERT_NE_POINTER(NULL,fd->tvb_data);
2630     ASSERT_EQ_POINTER(NULL,fd->next);
2631 
2632     /* Another copy of the second segment.
2633      */
2634     pinfo.num = 3;
2635     fd_head=fragment_add_check(&test_reassembly_table, tvb, 0, &pinfo, 12,
2636                                NULL, 50, 40, TRUE);
2637 
2638     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2639     ASSERT_EQ_POINTER(NULL,fd_head);
2640     fd_head=fragment_get(&test_reassembly_table, &pinfo, 12, NULL);
2641     ASSERT_NE_POINTER(NULL,fd_head);
2642     ASSERT_EQ(3,fd_head->frame);   /* max frame we have */
2643     ASSERT_EQ(0,fd_head->offset);  /* unused */
2644     ASSERT_EQ(0,fd_head->len);     /* unused */
2645     /* ASSERT_EQ(0,fd_head->datalen);
2646      * reassembly not finished; datalen not well defined.
2647      * Current implemenation has it as 0, could change to 90 without issues */
2648     ASSERT_EQ(0,fd_head->reassembled_in);
2649     ASSERT_EQ(0,fd_head->flags);
2650     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
2651     ASSERT_NE_POINTER(NULL,fd_head->next);
2652 
2653     fd=fd_head->next;
2654     ASSERT_EQ(1,fd->frame);
2655     ASSERT_EQ(0,fd->offset);
2656     ASSERT_EQ(50,fd->len);    /* segment length */
2657     ASSERT_EQ(FD_SUBSET_TVB,fd->flags);
2658     ASSERT_EQ_POINTER(tvb_get_ptr(fd_head->tvb_data,0,0),tvb_get_ptr(fd->tvb_data,0,0));
2659     ASSERT_NE_POINTER(NULL,fd->next);
2660 
2661     fd=fd->next;
2662     ASSERT_EQ(2,fd->frame);
2663     ASSERT_EQ(50,fd->offset);
2664     ASSERT_EQ(40,fd->len);    /* segment length */
2665     ASSERT_EQ(0,fd->flags);
2666     ASSERT_NE_POINTER(NULL,fd->tvb_data);
2667     ASSERT_NE_POINTER(NULL,fd->next);
2668 
2669     fd=fd->next;
2670     ASSERT_EQ(3,fd->frame);
2671     ASSERT_EQ(50,fd->offset);
2672     ASSERT_EQ(40,fd->len);    /* segment length */
2673     ASSERT_EQ(0,fd->flags);
2674     ASSERT_NE_POINTER(NULL,fd->tvb_data);
2675     ASSERT_EQ_POINTER(NULL,fd->next);
2676 
2677 
2678 
2679     /* have another go at wrapping things up */
2680     pinfo.num = 4;
2681     fd_head=fragment_add_check(&test_reassembly_table, tvb, 20, &pinfo, 12,
2682                                NULL, 90, 100, FALSE);
2683 
2684     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2685     ASSERT_NE_POINTER(NULL,fd_head);
2686 
2687     /* check the contents of the structure */
2688     ASSERT_EQ(4,fd_head->frame);  /* max frame we have */
2689     ASSERT_EQ(0,fd_head->offset); /* unused */
2690     ASSERT_EQ(0,fd_head->len); /* unused */
2691     ASSERT_EQ(190,fd_head->datalen); /* the length of data we have */
2692     ASSERT_EQ(4,fd_head->reassembled_in);
2693     ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
2694     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
2695     ASSERT_NE_POINTER(NULL,fd_head->next);
2696 
2697     fd=fd_head->next;
2698     ASSERT_EQ(1,fd->frame);
2699     ASSERT_EQ(0,fd->offset);
2700     ASSERT_EQ(50,fd->len);    /* segment length */
2701     ASSERT_EQ(0,fd->flags);
2702     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2703     ASSERT_NE_POINTER(NULL,fd->next);
2704 
2705     fd=fd->next;
2706     ASSERT_EQ(2,fd->frame);
2707     ASSERT_EQ(50,fd->offset);
2708     ASSERT_EQ(40,fd->len);    /* segment length */
2709     ASSERT_EQ(0,fd->flags);
2710     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2711     ASSERT_NE_POINTER(NULL,fd->next);
2712 
2713     fd=fd->next;
2714     ASSERT_EQ(3,fd->frame);
2715     ASSERT_EQ(50,fd->offset);
2716     ASSERT_EQ(40,fd->len);    /* segment length */
2717     ASSERT_EQ(FD_OVERLAP,fd->flags);
2718     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2719     ASSERT_NE_POINTER(NULL,fd->next);
2720 
2721     fd=fd->next;
2722     ASSERT_EQ(4,fd->frame);
2723     ASSERT_EQ(90,fd->offset);
2724     ASSERT_EQ(100,fd->len);    /* segment length */
2725     ASSERT_EQ(0,fd->flags);
2726     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2727     ASSERT_EQ_POINTER(NULL,fd->next);
2728 
2729     /* test the actual reassembly */
2730     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
2731     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data,40));
2732     ASSERT(!tvb_memeql(fd_head->tvb_data,90,data+20,100));
2733 
2734 
2735     /* do it again (this time it is more complicated, with an overlap in the
2736      * reassembly) */
2737 
2738     fragment_set_partial_reassembly(&test_reassembly_table, &pinfo, 12, NULL);
2739 
2740     pinfo.num = 5;
2741     fragment_add_check(&test_reassembly_table, tvb, 0, &pinfo, 12, NULL,
2742                        190, 40, FALSE);
2743 
2744     fd_head=fragment_get(&test_reassembly_table, &pinfo, 12, NULL);
2745     ASSERT_NE_POINTER(NULL,fd_head);
2746     ASSERT_EQ(5,fd_head->frame);   /* max frame we have */
2747     ASSERT_EQ(0,fd_head->offset);  /* unused */
2748     ASSERT_EQ(0,fd_head->len);   /* unused */
2749     ASSERT_EQ(230,fd_head->datalen); /* the length of data we have */
2750     ASSERT_EQ(5,fd_head->reassembled_in);
2751     ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
2752     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
2753     ASSERT_NE_POINTER(NULL,fd_head->next);
2754 
2755     fd=fd_head->next;
2756     ASSERT_EQ(1,fd->frame);
2757     ASSERT_EQ(0,fd->offset);
2758     ASSERT_EQ(50,fd->len);    /* segment length */
2759     ASSERT_EQ(0,fd->flags);
2760     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2761     ASSERT_NE_POINTER(NULL,fd->next);
2762 
2763     fd=fd->next;
2764     ASSERT_EQ(2,fd->frame);
2765     ASSERT_EQ(50,fd->offset);
2766     ASSERT_EQ(40,fd->len);    /* segment length */
2767     ASSERT_EQ(0,fd->flags);
2768     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2769     ASSERT_NE_POINTER(NULL,fd->next);
2770 
2771     fd=fd->next;
2772     ASSERT_EQ(3,fd->frame);
2773     ASSERT_EQ(50,fd->offset);
2774     ASSERT_EQ(40,fd->len);    /* segment length */
2775     ASSERT_EQ(FD_OVERLAP,fd->flags);
2776     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2777     ASSERT_NE_POINTER(NULL,fd->next);
2778 
2779     fd=fd->next;
2780     ASSERT_EQ(4,fd->frame);
2781     ASSERT_EQ(90,fd->offset);
2782     ASSERT_EQ(100,fd->len);   /* segment length */
2783     ASSERT_EQ(0,fd->flags);
2784     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2785     ASSERT_NE_POINTER(NULL,fd->next);
2786 
2787     fd=fd->next;
2788     ASSERT_EQ(5,fd->frame);
2789     ASSERT_EQ(190,fd->offset);
2790     ASSERT_EQ(40,fd->len);    /* segment length */
2791     ASSERT_EQ(0,fd->flags);
2792     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2793     ASSERT_EQ_POINTER(NULL,fd->next);
2794 
2795     /* test the actual reassembly */
2796     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
2797     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data,40));
2798     ASSERT(!tvb_memeql(fd_head->tvb_data,90,data+20,100));
2799     ASSERT(!tvb_memeql(fd_head->tvb_data,190,data,40));
2800 }
2801 #endif
2802 
2803 #if 0
2804 /* XXX: fragment_add_check moves completed reassemblies to the
2805  * reassembled_table, so adding a duplicated fragment after the end doesn't
2806  * get marked as duplicate, but starts a new reassembly. This is the correct
2807  * thing for very long captures where the identification field gets reused,
2808  * somewhat wrong when it is retransmitted data (it won't get marked as such
2809  * but doesn't interfere with defragmentation too much), and very wrong when
2810  * there is both retransmitted data and later on the identification field
2811  * gets reused (the dangling data will get added to the wrong reassembly.)
2812  *
2813  * Not sure what behavior to check. Possibly both behaviors should be supported,
2814  * perhaps being affected by how close pinfo.num is to the reassembly, though
2815  * that gets complicated.
2816  */
2817 /* Test case for fragment_add_check with duplicated (e.g., retransmitted) data.
2818  * Adds three fragments--adding the 1st one twice at the end--
2819  * and checks that they are reassembled correctly.
2820  */
2821 /*   visit  id  frame  frag_off  len  more  tvb_offset
2822        0    12     1        0    50   T      10
2823        0    12     2       50    60   T      5
2824        0    12     3      110    40   F      5
2825        0    12     4        0    50   T      10
2826 */
2827 static void
2828 test_fragment_add_check_duplicate_first(void)
2829 {
2830     fragment_head *fd_head;
2831     fragment_item *fd;
2832     volatile gboolean ex_thrown;
2833 
2834     printf("Starting test test_fragment_add_check_duplicate_first\n");
2835 
2836     pinfo.num = 1;
2837     fd_head=fragment_add_check(&test_reassembly_table, tvb, 10, &pinfo, 12,
2838                                NULL, 0, 50, TRUE);
2839 
2840     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2841     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
2842     ASSERT_EQ_POINTER(NULL,fd_head);
2843 
2844     /* Add the 2nd segment */
2845     pinfo.num = 2;
2846     fd_head=fragment_add_check(&test_reassembly_table, tvb, 5, &pinfo, 12,
2847                                NULL, 50, 60, TRUE);
2848 
2849     /* we haven't got all the fragments yet ... */
2850     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2851     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
2852     ASSERT_EQ_POINTER(NULL,fd_head);
2853 
2854     /* Add the last fragment */
2855     pinfo.num = 3;
2856     fd_head=fragment_add_check(&test_reassembly_table, tvb, 5, &pinfo, 12,
2857                                NULL, 110, 40, FALSE);
2858 
2859     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.fragment_table));
2860     ASSERT_EQ(3,g_hash_table_size(test_reassembly_table.reassembled_table));
2861     ASSERT_NE_POINTER(NULL,fd_head);
2862 
2863     /* Add the first fragment again */
2864     pinfo.num = 4;
2865     fd_head=fragment_add_check(&test_reassembly_table, tvb, 10, &pinfo, 12,
2866                                NULL, 0, 50, TRUE);
2867 
2868     /* Reassembly should have still succeeded */
2869     /* XXX: Current behavior is to start a new reassembly - which is
2870      * the proper behavior in a long capture that reuses the id, but the
2871      * wrong thing when it's actually a retransmission. Should the distinction
2872      * be made by analyzing pinfo.num to see if it is nearby? Or is that the
2873      * dissector's job? */
2874     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2875     ASSERT_EQ(3,g_hash_table_size(test_reassembly_table.reassembled_table));
2876     ASSERT_NE_POINTER(NULL,fd_head);
2877 
2878     /* check the contents of the structure */
2879     /*ASSERT_EQ(4,fd_head->frame);  max frame we have */
2880     ASSERT_EQ(3,fd_head->frame);  /* never add the duplicate frame */
2881     ASSERT_EQ(0,fd_head->offset); /* unused */
2882     ASSERT_EQ(0,fd_head->len); /* unused */
2883     ASSERT_EQ(150,fd_head->datalen);
2884     ASSERT_EQ(3,fd_head->reassembled_in);
2885     /* ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags); */
2886     /* FD_OVERLAP doesn't get set because we hit the exception early */
2887     ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET,fd_head->flags);
2888     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
2889     ASSERT_NE_POINTER(NULL,fd_head->next);
2890 
2891     fd = fd_head->next;
2892 
2893     ASSERT_EQ(1,fd->frame);
2894     ASSERT_EQ(0,fd->offset);
2895     ASSERT_EQ(50,fd->len);    /* segment length */
2896     ASSERT_EQ(0,fd->flags);
2897     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2898     ASSERT_NE_POINTER(NULL,fd->next);
2899 
2900     /*
2901     fd = fd_head->next;
2902     ASSERT_EQ(4,fd->frame);
2903     ASSERT_EQ(0,fd->offset);
2904     ASSERT_EQ(50,fd->len);
2905     ASSERT_EQ(FD_OVERLAP,fd->flags);
2906     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2907     ASSERT_NE_POINTER(NULL,fd->next); */
2908 
2909     fd = fd->next;
2910     ASSERT_EQ(2,fd->frame);
2911     ASSERT_EQ(50,fd->offset);
2912     ASSERT_EQ(60,fd->len);    /* segment length */
2913     ASSERT_EQ(0,fd->flags);
2914     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2915     ASSERT_NE_POINTER(NULL,fd->next);
2916 
2917     fd = fd->next;
2918     ASSERT_EQ(3,fd->frame);
2919     ASSERT_EQ(110,fd->offset);
2920     ASSERT_EQ(40,fd->len);    /* segment length */
2921     ASSERT_EQ(0,fd->flags);
2922     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
2923     ASSERT_EQ_POINTER(NULL,fd->next);
2924 
2925     /* test the actual reassembly */
2926     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
2927     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+5,60));
2928     ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,40));
2929 
2930     if (debug) {
2931         print_fragment_table();
2932     }
2933 }
2934 #endif
2935 
2936 /* Test case for fragment_add_check with duplicated (e.g., retransmitted) data.
2937  * Adds three fragments--adding the 2nd one twice--
2938  * and checks that they are reassembled correctly.
2939  */
2940 /*   visit  id  frame  frag_off  len  more  tvb_offset
2941        0    12     1       0     50   T      10
2942        0    12     2      50     60   T      5
2943        0    12     3      50     60   T      5
2944        0    12     4     110     40   F      5
2945 */
2946 static void
2947 test_fragment_add_check_duplicate_middle(void)
2948 {
2949     fragment_head *fd_head;
2950     fragment_item *fd;
2951 
2952     printf("Starting test test_fragment_add_check_duplicate_middle\n");
2953 
2954     pinfo.num = 1;
2955     fd_head=fragment_add_check(&test_reassembly_table, tvb, 10, &pinfo, 12,
2956                                NULL, 0, 50, TRUE);
2957 
2958     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2959     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
2960     ASSERT_EQ_POINTER(NULL,fd_head);
2961 
2962     /* Add the 2nd segment */
2963     pinfo.num = 2;
2964     fd_head=fragment_add_check(&test_reassembly_table, tvb, 5, &pinfo, 12,
2965                                NULL, 50, 60, TRUE);
2966 
2967     /* we haven't got all the fragments yet ... */
2968     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2969     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
2970     ASSERT_EQ_POINTER(NULL,fd_head);
2971 
2972     /* Now, add the 2nd segment again (but in a different frame) */
2973     pinfo.num = 3;
2974     fd_head=fragment_add_check(&test_reassembly_table, tvb, 5, &pinfo, 12,
2975                                NULL, 50, 60, TRUE);
2976 
2977     /* This duplicate fragment should have been ignored */
2978     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
2979     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
2980     ASSERT_EQ_POINTER(NULL,fd_head);
2981 
2982     /* finally, add the last fragment */
2983     pinfo.num = 4;
2984     fd_head=fragment_add_check(&test_reassembly_table, tvb, 5, &pinfo, 12,
2985                                NULL, 110, 40, FALSE);
2986 
2987     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.fragment_table));
2988     ASSERT_EQ(4,g_hash_table_size(test_reassembly_table.reassembled_table));
2989     ASSERT_NE_POINTER(NULL,fd_head);
2990 
2991     /* check the contents of the structure */
2992     ASSERT_EQ(4,fd_head->frame);  /* max frame we have */
2993     ASSERT_EQ(0,fd_head->offset); /* unused */
2994     ASSERT_EQ(0,fd_head->len); /* unused */
2995     ASSERT_EQ(150,fd_head->datalen);
2996     ASSERT_EQ(4,fd_head->reassembled_in);
2997     ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
2998     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
2999     ASSERT_NE_POINTER(NULL,fd_head->next);
3000 
3001     fd = fd_head->next;
3002     ASSERT_EQ(1,fd->frame);
3003     ASSERT_EQ(0,fd->offset);
3004     ASSERT_EQ(50,fd->len);    /* segment length */
3005     ASSERT_EQ(0,fd->flags);
3006     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
3007     ASSERT_NE_POINTER(NULL,fd->next);
3008 
3009     fd = fd->next;
3010     ASSERT_EQ(2,fd->frame);
3011     ASSERT_EQ(50,fd->offset);
3012     ASSERT_EQ(60,fd->len);    /* segment length */
3013     ASSERT_EQ(0,fd->flags);
3014     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
3015     ASSERT_NE_POINTER(NULL,fd->next);
3016 
3017     fd = fd->next;
3018     ASSERT_EQ(3,fd->frame);
3019     ASSERT_EQ(50,fd->offset);
3020     ASSERT_EQ(60,fd->len);    /* segment length */
3021     ASSERT_EQ(FD_OVERLAP,fd->flags);
3022     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
3023     ASSERT_NE_POINTER(NULL,fd->next);
3024 
3025     fd = fd->next;
3026     ASSERT_EQ(4,fd->frame);
3027     ASSERT_EQ(110,fd->offset);
3028     ASSERT_EQ(40,fd->len);    /* segment length */
3029     ASSERT_EQ(0,fd->flags);
3030     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
3031     ASSERT_EQ_POINTER(NULL,fd->next);
3032 
3033     /* test the actual reassembly */
3034     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
3035     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+5,60));
3036     ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,40));
3037 
3038     if (debug) {
3039         print_fragment_table();
3040     }
3041 }
3042 
3043 #if 0
3044 /* XXX: same issue as test_fragment_add_check_duplicate_first, above.
3045  */
3046 /* Test case for fragment_add_check with duplicated (e.g., retransmitted) data.
3047  * Adds three fragments--adding the 3rd one twice--
3048  * and checks that they are reassembled correctly.
3049  */
3050 /*   visit  id  frame  frag  len  more  tvb_offset
3051        0    12     1     0    50   T      10
3052        0    12     2     1    60   T      5
3053        0    12     3     2    40   F      5
3054        0    12     4     2    40   F      5
3055 */
3056 static void
3057 test_fragment_add_check_duplicate_last(void)
3058 {
3059     fragment_head *fd_head;
3060     fragment_item *fd;
3061 
3062     printf("Starting test test_fragment_add_check_duplicate_last\n");
3063 
3064     pinfo.num = 1;
3065     fd_head=fragment_add_check(&test_reassembly_table, tvb, 10, &pinfo, 12,
3066                                NULL, 0, 50, TRUE);
3067 
3068     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
3069     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
3070     ASSERT_EQ_POINTER(NULL,fd_head);
3071 
3072     /* Add the 2nd segment */
3073     pinfo.num = 2;
3074     fd_head=fragment_add_check(&test_reassembly_table, tvb, 5, &pinfo, 12,
3075                                NULL, 50, 60, TRUE);
3076 
3077     /* we haven't got all the fragments yet ... */
3078     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
3079     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
3080     ASSERT_EQ_POINTER(NULL,fd_head);
3081 
3082     /* Add the last fragment */
3083     pinfo.num = 3;
3084     fd_head=fragment_add_check(&test_reassembly_table, tvb, 5, &pinfo, 12,
3085                                NULL, 110, 40, FALSE);
3086 
3087     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.fragment_table));
3088     ASSERT_EQ(3,g_hash_table_size(test_reassembly_table.reassembled_table));
3089     ASSERT_NE_POINTER(NULL,fd_head);
3090 
3091     /* Add the last fragment again */
3092     pinfo.num = 4;
3093     fd_head=fragment_add_check(&test_reassembly_table, tvb, 5, &pinfo, 12,
3094                                NULL, 110, 40, FALSE);
3095 
3096     /* Reassembly should have still succeeded */
3097     /* XXX: Current behavior is to start a new reassembly */
3098     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
3099     ASSERT_EQ(3,g_hash_table_size(test_reassembly_table.reassembled_table));
3100     ASSERT_NE_POINTER(NULL,fd_head);
3101 
3102     /* check the contents of the structure */
3103     /* ASSERT_EQ(4,fd_head->frame); never add the last frame again */
3104     ASSERT_EQ(3,fd_head->frame);  /* max frame we have */
3105     ASSERT_EQ(0,fd_head->offset); /* unused */
3106     ASSERT_EQ(0,fd_head->len); /* unused */
3107     ASSERT_EQ(150,fd_head->datalen);
3108     ASSERT_EQ(3,fd_head->reassembled_in);
3109     /* ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
3110      * FD_OVERLAP doesn't get set since we don't add a fragment after the
3111      * end but start a new assembly instead. */
3112     ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET,fd_head->flags);
3113     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
3114     ASSERT_NE_POINTER(NULL,fd_head->next);
3115 
3116     fd = fd_head->next;
3117     ASSERT_EQ(1,fd->frame);
3118     ASSERT_EQ(0,fd->offset);
3119     ASSERT_EQ(50,fd->len);    /* segment length */
3120     ASSERT_EQ(0,fd->flags);
3121     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
3122     ASSERT_NE_POINTER(NULL,fd->next);
3123 
3124     fd = fd->next;
3125     ASSERT_EQ(2,fd->frame);
3126     ASSERT_EQ(50,fd->offset);
3127     ASSERT_EQ(60,fd->len);    /* segment length */
3128     ASSERT_EQ(0,fd->flags);
3129     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
3130     ASSERT_NE_POINTER(NULL,fd->next);
3131 
3132     fd = fd->next;
3133     ASSERT_EQ(3,fd->frame);
3134     ASSERT_EQ(110,fd->offset);
3135     ASSERT_EQ(40,fd->len);    /* segment length */
3136     ASSERT_EQ(0,fd->flags);
3137     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
3138 
3139     /* Duplicate packet never gets added
3140     ASSERT_NE_POINTER(NULL,fd->next);
3141 
3142     fd = fd->next;
3143     ASSERT_EQ(4,fd->frame);
3144     ASSERT_EQ(110,fd->offset);
3145     ASSERT_EQ(40,fd->len);
3146     ASSERT_EQ(FD_OVERLAP,fd->flags);
3147     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
3148     ASSERT_EQ_POINTER(NULL,fd->next); */
3149 
3150     /* test the actual reassembly */
3151     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
3152     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+5,60));
3153     ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,40));
3154 
3155     if (debug) {
3156         print_fragment_table();
3157     }
3158 }
3159 #endif
3160 
3161 /* Test case for fragment_add_check with duplicated (e.g., retransmitted) data
3162  * where the retransmission "conflicts" with the original transmission
3163  * (contents are different).
3164  * Adds three fragments--adding the 2nd one twice--
3165  * and checks that they are reassembled correctly.
3166  */
3167 /*   visit  id  frame  frag_off  len  more  tvb_offset
3168        0    12     1       0     50   T      10
3169        0    12     2      50     60   T      5
3170        0    12     3      50     60   T      15
3171        0    12     4     110     40   F      5
3172 */
3173 static void
3174 test_fragment_add_check_duplicate_conflict(void)
3175 {
3176     fragment_head *fd_head;
3177     fragment_item *fd;
3178 
3179     printf("Starting test test_fragment_add_check_duplicate_conflict\n");
3180 
3181     pinfo.num = 1;
3182     fd_head=fragment_add_check(&test_reassembly_table, tvb, 10, &pinfo, 12,
3183                                NULL, 0, 50, TRUE);
3184 
3185     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
3186     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
3187     ASSERT_EQ_POINTER(NULL,fd_head);
3188 
3189     /* Add the 2nd segment */
3190     pinfo.num = 2;
3191     fd_head=fragment_add_check(&test_reassembly_table, tvb, 5, &pinfo, 12,
3192                                NULL, 50, 60, TRUE);
3193 
3194     /* we haven't got all the fragments yet ... */
3195     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
3196     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
3197     ASSERT_EQ_POINTER(NULL,fd_head);
3198 
3199     /* Now, add the 2nd segment again (but in a different frame and with
3200      * different data)
3201      */
3202     pinfo.num = 3;
3203     fd_head=fragment_add_check(&test_reassembly_table, tvb, 15, &pinfo, 12,
3204                                NULL, 50, 60, TRUE);
3205 
3206     ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
3207     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
3208     ASSERT_EQ_POINTER(NULL,fd_head);
3209 
3210     /* finally, add the last fragment */
3211     pinfo.num = 4;
3212     fd_head=fragment_add_check(&test_reassembly_table, tvb, 5, &pinfo, 12,
3213                                NULL, 110, 40, FALSE);
3214 
3215     ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.fragment_table));
3216     ASSERT_EQ(4,g_hash_table_size(test_reassembly_table.reassembled_table));
3217     ASSERT_NE_POINTER(NULL,fd_head);
3218 
3219     /* check the contents of the structure */
3220     ASSERT_EQ(4,fd_head->frame);  /* max frame we have */
3221     ASSERT_EQ(0,fd_head->offset); /* unused */
3222     ASSERT_EQ(0,fd_head->len); /* unused */
3223     ASSERT_EQ(150,fd_head->datalen);
3224     ASSERT_EQ(4,fd_head->reassembled_in);
3225     ASSERT_EQ(FD_DEFRAGMENTED|FD_DATALEN_SET|FD_OVERLAP|FD_OVERLAPCONFLICT,fd_head->flags);
3226     ASSERT_NE_POINTER(NULL,fd_head->tvb_data);
3227     ASSERT_NE_POINTER(NULL,fd_head->next);
3228 
3229     fd = fd_head->next;
3230     ASSERT_EQ(1,fd->frame);
3231     ASSERT_EQ(0,fd->offset);
3232     ASSERT_EQ(50,fd->len);    /* segment length */
3233     ASSERT_EQ(0,fd->flags);
3234     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
3235     ASSERT_NE_POINTER(NULL,fd->next);
3236 
3237     fd = fd->next;
3238     ASSERT_EQ(2,fd->frame);
3239     ASSERT_EQ(50,fd->offset);
3240     ASSERT_EQ(60,fd->len);    /* segment length */
3241     ASSERT_EQ(0,fd->flags);
3242     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
3243     ASSERT_NE_POINTER(NULL,fd->next);
3244 
3245     fd = fd->next;
3246     ASSERT_EQ(3,fd->frame);
3247     ASSERT_EQ(50,fd->offset);
3248     ASSERT_EQ(60,fd->len);    /* segment length */
3249     ASSERT_EQ(FD_OVERLAP|FD_OVERLAPCONFLICT,fd->flags);
3250     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
3251     ASSERT_NE_POINTER(NULL,fd->next);
3252 
3253     fd = fd->next;
3254     ASSERT_EQ(4,fd->frame);
3255     ASSERT_EQ(110,fd->offset);
3256     ASSERT_EQ(40,fd->len);    /* segment length */
3257     ASSERT_EQ(0,fd->flags);
3258     ASSERT_EQ_POINTER(NULL,fd->tvb_data);
3259     ASSERT_EQ_POINTER(NULL,fd->next);
3260 
3261     /* test the actual reassembly */
3262     ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
3263     ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+5,60));
3264     ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,40));
3265 
3266     if (debug) {
3267         print_fragment_table();
3268     }
3269 }
3270 /**********************************************************************************
3271  *
3272  * main
3273  *
3274  *********************************************************************************/
3275 
3276 int
3277 main(int argc _U_, char **argv _U_)
3278 {
3279     frame_data fd;
3280     static const guint8 src[] = {1,2,3,4}, dst[] = {5,6,7,8};
3281     unsigned int i;
3282     static void (*tests[])(void) = {
3283         test_simple_fragment_add_seq,              /* frag table only   */
3284         test_fragment_add_seq_partial_reassembly,
3285         test_fragment_add_seq_duplicate_first,
3286         test_fragment_add_seq_duplicate_middle,
3287         test_fragment_add_seq_duplicate_last,
3288         test_fragment_add_seq_duplicate_conflict,
3289         test_fragment_add_seq_check,               /* frag + reassemble */
3290         test_fragment_add_seq_check_1,
3291         test_fragment_add_seq_802_11_0,
3292         test_fragment_add_seq_802_11_1,
3293         test_simple_fragment_add_seq_next,
3294 #if 0
3295         test_missing_data_fragment_add_seq_next,
3296         test_missing_data_fragment_add_seq_next_2,
3297         test_missing_data_fragment_add_seq_next_3,
3298 #endif
3299 #if 0
3300         test_fragment_add_seq_check_multiple
3301 #endif
3302         test_simple_fragment_add,              /* frag table only   */
3303         test_fragment_add_partial_reassembly,
3304         test_fragment_add_duplicate_first,
3305         test_fragment_add_duplicate_middle,
3306         test_fragment_add_duplicate_last,
3307         test_fragment_add_duplicate_conflict,
3308         test_simple_fragment_add_check,              /* frag table only   */
3309 #if 0
3310         test_fragment_add_check_partial_reassembly,
3311         test_fragment_add_check_duplicate_first,
3312 #endif
3313         test_fragment_add_check_duplicate_middle,
3314 #if 0
3315         test_fragment_add_check_duplicate_last,
3316 #endif
3317         test_fragment_add_check_duplicate_conflict,
3318     };
3319 
3320     /* a tvbuff for testing with */
3321     data = (guint8 *)g_malloc(DATA_LEN);
3322     /* make sure it's full of stuff */
3323     for(i=0; i<DATA_LEN; i++) {
3324         data[i]=i & 0xFF;
3325     }
3326     tvb = tvb_new_real_data(data, DATA_LEN, DATA_LEN*2);
3327 
3328     /* other test stuff */
3329     pinfo.fd = &fd;
3330     fd.visited = 0;
3331     set_address(&pinfo.src,AT_IPv4,4,src);
3332     set_address(&pinfo.dst,AT_IPv4,4,dst);
3333 
3334     /*************************************************************************/
3335     for(i=0; i < sizeof(tests)/sizeof(tests[0]); i++ ) {
3336         /* re-init the fragment tables */
3337         reassembly_table_init(&test_reassembly_table,
3338                               &addresses_reassembly_table_functions);
3339         ASSERT(test_reassembly_table.fragment_table != NULL);
3340         ASSERT(test_reassembly_table.reassembled_table != NULL);
3341 
3342         pinfo.fd->visited = FALSE;
3343 
3344         tests[i]();
3345 
3346         /* Free memory used by the tables */
3347         reassembly_table_destroy(&test_reassembly_table);
3348     }
3349 
3350     tvb_free(tvb);
3351     tvb = NULL;
3352     g_free(data);
3353     data = NULL;
3354 
3355     printf(failure?"FAILURE\n":"SUCCESS\n");
3356     return failure;
3357 }
3358 
3359 /*
3360  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
3361  *
3362  * Local variables:
3363  * c-basic-offset: 4
3364  * tab-width: 8
3365  * indent-tabs-mode: nil
3366  * End:
3367  *
3368  * vi: set shiftwidth=4 tabstop=8 expandtab:
3369  * :indentSize=4:tabSize=8:noTabs=true:
3370  */
3371