From Alexis La Goutte:
[obnox/wireshark/wip.git] / epan / reassemble_test.c
1 /* Standalone program to test functionality of reassemble.h API
2  *
3  * These aren't particularly complete - they just test a few corners of
4  * functionality which I was interested in. In particular, they only test the
5  * fragment_add_seq_* (ie, FD_BLOCKSEQUENCE) family of routines. However,
6  * hopefully they will inspire people to write additional tests, and provide a
7  * useful basis on which to do so.
8  *
9  * December 2010:
10  * 1. 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  *        WIRESHARK_DEBUG_EP_NO_CHUNKS=1  \
20  *        WIRESHARK_DEBUG_SE_NO_CHUNKS=1  \
21  *        WIRESHARK_DEBUG_SE_USE_CANARY=1 \
22  *        WIRESHARK_EP_VERIFY_POINTERS=1  \
23  *        WIRESHARK_SE_VERIFY_POINTERS=1  \
24  *      valgrind --leak-check=full --show-reachable=yes ./reassemble_test
25  *
26  *  2. Debug functions have been added which will print information
27  *     about the fd-chains associated with the fragment_table and the
28  *     reassembled table.
29  *     #define debug  to enable the code.
30  *
31  * $Id$
32  *
33  * Copyright (c) 2007 MX Telecom Ltd. <richardv@mxtelecom.com>
34  *
35  * Wireshark - Network traffic analyzer
36  * By Gerald Combs <gerald@wireshark.org>
37  * Copyright 1998
38  *
39  * This program is free software; you can redistribute it and/or
40  * modify it under the terms of the GNU General Public License
41  * as published by the Free Software Foundation; either version 2
42  * of the License, or (at your option) any later version.
43  *
44  * This program is distributed in the hope that it will be useful,
45  * but WITHOUT ANY WARRANTY; without even the implied warranty of
46  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
47  * GNU General Public License for more details.
48  *
49  * You should have received a copy of the GNU General Public License
50  * along with this program; if not, write to the Free Software
51  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
52  */
53
54 #include <stdarg.h>
55 #include <stdlib.h>
56 #include <stdio.h>
57 #include <string.h>
58
59 #include <glib.h>
60
61 #ifdef HAVE_CONFIG_H
62 # include "config.h"
63 #endif
64
65 #include <epan/emem.h>
66 #include <epan/packet.h>
67 #include <epan/packet_info.h>
68 #include <epan/proto.h>
69 #include <epan/tvbuff.h>
70 #include <epan/reassemble.h>
71
72 #include <epan/dissectors/packet-dcerpc.h>
73
74 #define ASSERT(b) do_test((b),"Assertion failed at line %i: %s\n", __LINE__, #b)
75 #define ASSERT_EQ(exp,act) do_test((exp)==(act),"Assertion failed at line %i: %s==%s (%i==%i)\n", __LINE__, #exp, #act, exp, act)
76 #define ASSERT_NE(exp,act) do_test((exp)!=(act),"Assertion failed at line %i: %s!=%s (%i!=%i)\n", __LINE__, #exp, #act, exp, act)
77
78 static int failure = 0;
79
80 static void
81 do_test(gboolean condition, const char *format, ...)
82 {
83     va_list ap;
84
85     if (condition)
86         return;
87
88     va_start(ap, format);
89     vfprintf(stderr, format, ap);
90     va_end(ap);
91     failure = 1;
92
93     /* many of the tests assume this routine doesn't return on failure; if we
94      * do, it may provide more information, but may cause a segfault. Uncomment
95      * this line if you wish.
96      */
97     exit(1);
98 }
99
100 #define DATA_LEN 256
101
102 static char *data;
103 static tvbuff_t *tvb;
104 static packet_info pinfo;
105
106 /* fragment_table maps from datagram ids to head of fragment_data list
107    reassembled_table maps from <packet number,datagram id> to head of
108    fragment_data list */
109 static GHashTable *fragment_table = NULL;
110 static GHashTable *reassembled_table = NULL;
111
112 #ifdef debug
113 /*************************************************
114  * Util fcns to display
115  *   fragment_table & reassembled_table fd-chains
116  ************************************************/
117
118 /* Must match the typedef in reassemble.c */
119 typedef struct _fragment_key {
120         address src;
121         address dst;
122         guint32 id;
123 } fragment_key;
124
125 /* Must match the typedef in reassemble.c */
126 typedef struct _reassembled_key {
127         guint32 id;
128         guint32 frame;
129 } reassembled_key;
130
131 static struct _fd_flags {
132     guint32 flag;
133     gchar  *flag_name;
134 } fd_flags[] = {
135     {FD_DEFRAGMENTED         ,"DF"},
136     {FD_DATALEN_SET          ,"DS"},
137     {FD_NOT_MALLOCED         ,"NM"},
138     {FD_BLOCKSEQUENCE        ,"BS"},
139     {FD_DATA_NOT_PRESENT     ,"NP"},
140     {FD_PARTIAL_REASSEMBLY   ,"PR"},
141     {FD_OVERLAP              ,"OL"},
142     {FD_OVERLAPCONFLICT      ,"OC"},
143     {FD_MULTIPLETAILS        ,"MT"},
144     {FD_TOOLONGFRAGMENT      ,"TL"},
145 };
146 #define N_FD_FLAGS (signed)(sizeof(fd_flags)/sizeof(struct _fd_flags))
147
148 static void
149 print_fd(fragment_data *fd, gboolean is_head) {
150     int i;
151
152     g_assert(fd != NULL);
153     printf("        %08x %08x %3d %3d %3d", fd, fd->next, fd->frame, fd->offset, fd->len);
154     if (is_head) {
155         printf(" %3d %3d", fd->datalen, fd->reassembled_in);
156     } else {
157         printf( "        ");
158     }
159     printf(" 0x%08x", fd->data);
160     for (i=0; i<N_FD_FLAGS; i++) {
161         printf(" %s", (fd->flags & fd_flags[i].flag) ? fd_flags[i].flag_name : "  ");
162     }
163     printf("\n");
164 }
165
166 static void
167 print_fd_chain(fragment_data *fd_head) {
168     fragment_data *fdp;
169
170     g_assert(fd_head != NULL);
171     print_fd(fd_head, TRUE);
172     for (fdp=fd_head->next; fdp != NULL; fdp=fdp->next) {
173         print_fd(fdp, FALSE);
174     }
175 }
176
177 static void
178 print_fragment_table_chain(gpointer k, gpointer v, gpointer ud) {
179     fragment_key  *key     = (fragment_key*)k;
180     fragment_data *fd_head = (fragment_data *)v;
181     printf("  --> FT: %3d 0x%08x 0x%08x\n", key->id, *(guint32 *)(key->src.data), *(guint32 *)(key->dst.data));
182     print_fd_chain(fd_head);
183 }
184
185 static void
186 print_fragment_table(void) {
187     printf("\n Fragment Table -------\n");
188     g_hash_table_foreach(fragment_table, print_fragment_table_chain, NULL);
189 }
190
191 static void
192 print_reassembled_table_chain(gpointer k, gpointer v, gpointer ud) {
193     reassembled_key  *key  = (reassembled_key*)k;
194     fragment_data *fd_head = (fragment_data *)v;
195     printf("  --> RT: %5d %5d\n", key->id, key->frame);
196     print_fd_chain(fd_head);
197 }
198
199 static void
200 print_reassembled_table(void) {
201     printf("\n Reassembled Table ----\n");
202     g_hash_table_foreach(reassembled_table, print_reassembled_table_chain, NULL);
203 }
204
205 static void
206 print_tables(void) {
207     print_fragment_table();
208     print_reassembled_table();
209 }
210 #endif
211
212 /**********************************************************************************
213  *
214  * fragment_add_seq
215  *
216  *********************************************************************************/
217
218 /* Simple test case for fragment_add_seq.
219  * Adds three fragments (out of order, with one for a different datagram in between),
220  * and checks that they are reassembled correctly.
221  */
222 /*   visit  id  frame  frag  len  more  tvb_offset
223        0    12     1     0    50   T      10
224        1    12     1     0    60   T       5
225        0    13     2     0    60   T      15
226        0    12     3     2    60   F       5
227        0    12     4     1    60   F      15
228 */
229 static void
230 test_simple_fragment_add_seq(void)
231 {
232     fragment_data *fd_head, *fdh0;
233
234     printf("Starting test test_simple_fragment_add_seq\n");
235
236     pinfo.fd->num = 1;
237     fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
238                              0, 50, TRUE);
239
240     ASSERT_EQ(1,g_hash_table_size(fragment_table));
241     ASSERT_EQ(NULL,fd_head);
242
243     /* adding the same fragment again should do nothing, even with different
244      * offset etc */
245     pinfo.fd->flags.visited = 1;
246     fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
247                              0, 60, TRUE);
248     ASSERT_EQ(1,g_hash_table_size(fragment_table));
249     ASSERT_EQ(NULL,fd_head);
250
251     /* start another pdu (just to confuse things) */
252     pinfo.fd->flags.visited = 0;
253     pinfo.fd->num = 2;
254     fd_head=fragment_add_seq(tvb, 15, &pinfo, 13, fragment_table,
255                              0, 60, TRUE);
256     ASSERT_EQ(2,g_hash_table_size(fragment_table));
257     ASSERT_EQ(NULL,fd_head);
258
259     /* now we add the terminal fragment of the first datagram */
260     pinfo.fd->num = 3;
261     fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
262                              2, 60, FALSE);
263
264     /* we haven't got all the fragments yet ... */
265     ASSERT_EQ(2,g_hash_table_size(fragment_table));
266     ASSERT_EQ(NULL,fd_head);
267
268     /* finally, add the missing fragment */
269     pinfo.fd->num = 4;
270     fd_head=fragment_add_seq(tvb, 15, &pinfo, 12, fragment_table,
271                              1, 60, TRUE);
272
273     ASSERT_EQ(2,g_hash_table_size(fragment_table));
274     ASSERT_NE(NULL,fd_head);
275
276     /* check the contents of the structure */
277     ASSERT_EQ(0,fd_head->frame);  /* unused */
278     ASSERT_EQ(0,fd_head->offset); /* unused */
279     ASSERT_EQ(170,fd_head->len); /* the length of data we have */
280     ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
281     ASSERT_EQ(4,fd_head->reassembled_in);
282     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
283     ASSERT_NE(NULL,fd_head->data);
284     ASSERT_NE(NULL,fd_head->next);
285
286     ASSERT_EQ(1,fd_head->next->frame);
287     ASSERT_EQ(0,fd_head->next->offset);  /* seqno */
288     ASSERT_EQ(50,fd_head->next->len);    /* segment length */
289     ASSERT_EQ(0,fd_head->next->flags);
290     ASSERT_EQ(NULL,fd_head->next->data);
291     ASSERT_NE(NULL,fd_head->next->next);
292
293     ASSERT_EQ(4,fd_head->next->next->frame);
294     ASSERT_EQ(1,fd_head->next->next->offset);  /* seqno */
295     ASSERT_EQ(60,fd_head->next->next->len);    /* segment length */
296     ASSERT_EQ(0,fd_head->next->next->flags);
297     ASSERT_EQ(NULL,fd_head->next->next->data);
298     ASSERT_NE(NULL,fd_head->next->next->next);
299
300     ASSERT_EQ(3,fd_head->next->next->next->frame);
301     ASSERT_EQ(2,fd_head->next->next->next->offset);  /* seqno */
302     ASSERT_EQ(60,fd_head->next->next->next->len);    /* segment length */
303     ASSERT_EQ(0,fd_head->next->next->next->flags);
304     ASSERT_EQ(NULL,fd_head->next->next->next->data);
305     ASSERT_EQ(NULL,fd_head->next->next->next->next);
306
307     /* test the actual reassembly */
308     ASSERT(!memcmp(fd_head->data,data+10,50));
309     ASSERT(!memcmp(fd_head->data+50,data+15,60));
310     ASSERT(!memcmp(fd_head->data+110,data+5,60));
311
312 #if 0
313     print_fragment_table();
314 #endif
315
316     /* what happens if we revisit the packets now? */
317     fdh0 = fd_head;
318     pinfo.fd->flags.visited = 1;
319     pinfo.fd->num = 1;
320     fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
321                              0, 50, TRUE);
322     /*
323      * this api relies on the caller to check fd_head -> reassembled_in
324      *
325      * Redoing all the tests seems like overkill - just check the pointer
326      */
327     ASSERT_EQ(fdh0,fd_head);
328
329     pinfo.fd->num = 3;
330     fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
331                              2, 60, FALSE);
332     ASSERT_EQ(fdh0,fd_head);
333
334     pinfo.fd->num = 4;
335     fd_head=fragment_add_seq(tvb, 15, &pinfo, 12, fragment_table,
336                              1, 60, TRUE);
337     ASSERT_EQ(fdh0,fd_head);
338
339 #if 0
340     print_fragment_table();
341 #endif
342 }
343
344 /* XXX ought to have some tests for overlapping fragments */
345
346 /* This tests the functionality of fragment_set_partial_reassembly for
347  * FD_BLOCKSEQUENCE reassembly.
348  *
349  * We add a sequence of fragments thus:
350  *    seqno   frame  offset   len   (initial) more_frags
351  *    -----   -----  ------   ---   --------------------
352  *      0       1       10       50   false
353  *      1       2        0       40   true
354  *      1       3        0       40   true (a duplicate fragment)
355  *      2       4       20      100   false
356  *      3       5        0       40   false
357  */
358 static void
359 test_fragment_add_seq_partial_reassembly(void)
360 {
361     fragment_data *fd_head, *fd;
362
363     printf("Starting test test_fragment_add_seq_partial_reassembly\n");
364
365     /* generally it's probably fair to assume that we will be called with
366      * more_frags=FALSE.
367      */
368     pinfo.fd->num = 1;
369     fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
370                              0, 50, FALSE);
371
372     ASSERT_EQ(1,g_hash_table_size(fragment_table));
373     ASSERT_NE(NULL,fd_head);
374
375     /* check the contents of the structure */
376     ASSERT_EQ(0,fd_head->frame);  /* unused */
377     ASSERT_EQ(0,fd_head->offset); /* unused */
378     ASSERT_EQ(50,fd_head->len); /* the length of data we have */
379     ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
380     ASSERT_EQ(1,fd_head->reassembled_in);
381     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
382     ASSERT_NE(NULL,fd_head->data);
383     ASSERT_NE(NULL,fd_head->next);
384
385     ASSERT_EQ(1,fd_head->next->frame);
386     ASSERT_EQ(0,fd_head->next->offset);  /* seqno */
387     ASSERT_EQ(50,fd_head->next->len);    /* segment length */
388     ASSERT_EQ(0,fd_head->next->flags);
389     ASSERT_EQ(NULL,fd_head->next->data);
390     ASSERT_EQ(NULL,fd_head->next->next);
391
392     /* test the actual reassembly */
393     ASSERT(!memcmp(fd_head->data,data+10,50));
394
395     /* now we announce that the reassembly wasn't complete after all. */
396     fragment_set_partial_reassembly(&pinfo,12,fragment_table);
397
398     /* and add another segment. To mix things up slightly (and so that we can
399      * check on the state of things), we're going to set the more_frags flag
400      * here
401      */
402     pinfo.fd->num = 2;
403     fd_head=fragment_add_seq(tvb, 0, &pinfo, 12, fragment_table,
404                              1, 40, TRUE);
405
406     ASSERT_EQ(1,g_hash_table_size(fragment_table));
407     ASSERT_EQ(NULL,fd_head);
408
409     fd_head=fragment_get(&pinfo,12,fragment_table);
410     ASSERT_NE(NULL,fd_head);
411
412     /* check the contents of the structure */
413     ASSERT_EQ(0,fd_head->frame);   /* unused */
414     ASSERT_EQ(0,fd_head->offset);  /* unused */
415     /* ASSERT_EQ(50,fd_head->len);     the length of data we have */
416     ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
417     ASSERT_EQ(0,fd_head->reassembled_in);
418     ASSERT_EQ(FD_BLOCKSEQUENCE,fd_head->flags);
419     ASSERT_NE(NULL,fd_head->data);
420     ASSERT_NE(NULL,fd_head->next);
421
422     fd=fd_head->next;
423     ASSERT_EQ(1,fd->frame);
424     ASSERT_EQ(0,fd->offset);  /* seqno */
425     ASSERT_EQ(50,fd->len);    /* segment length */
426     ASSERT_EQ(FD_NOT_MALLOCED,fd->flags);
427     ASSERT_EQ(fd_head->data,fd->data);
428     ASSERT_NE(NULL,fd->next);
429
430     fd=fd->next;
431     ASSERT_EQ(2,fd->frame);
432     ASSERT_EQ(1,fd->offset);  /* seqno */
433     ASSERT_EQ(40,fd->len);    /* segment length */
434     ASSERT_EQ(0,fd->flags);
435     ASSERT_NE(NULL,fd->data);
436     ASSERT_EQ(NULL,fd->next);
437
438     /* Another copy of the second segment.
439      */
440     pinfo.fd->num = 3;
441     fd_head=fragment_add_seq(tvb, 0, &pinfo, 12, fragment_table,
442                              1, 40, TRUE);
443
444     ASSERT_EQ(1,g_hash_table_size(fragment_table));
445     ASSERT_EQ(NULL,fd_head);
446     fd_head=fragment_get(&pinfo,12,fragment_table);
447     ASSERT_NE(NULL,fd_head);
448     ASSERT_EQ(0,fd_head->frame);   /* unused */
449     ASSERT_EQ(0,fd_head->offset);  /* unused */
450     /* ASSERT_EQ(50,fd_head->len);     the length of data we have */
451     ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
452     ASSERT_EQ(0,fd_head->reassembled_in);
453     ASSERT_EQ(FD_BLOCKSEQUENCE,fd_head->flags);
454     ASSERT_NE(NULL,fd_head->data);
455     ASSERT_NE(NULL,fd_head->next);
456
457     fd=fd_head->next;
458     ASSERT_EQ(1,fd->frame);
459     ASSERT_EQ(0,fd->offset);  /* seqno */
460     ASSERT_EQ(50,fd->len);    /* segment length */
461     ASSERT_EQ(FD_NOT_MALLOCED,fd->flags);
462     ASSERT_EQ(fd_head->data,fd->data);
463     ASSERT_NE(NULL,fd->next);
464
465     fd=fd->next;
466     ASSERT_EQ(2,fd->frame);
467     ASSERT_EQ(1,fd->offset);  /* seqno */
468     ASSERT_EQ(40,fd->len);    /* segment length */
469     ASSERT_EQ(0,fd->flags);
470     ASSERT_NE(NULL,fd->data);
471     ASSERT_NE(NULL,fd->next);
472
473     fd=fd->next;
474     ASSERT_EQ(3,fd->frame);
475     ASSERT_EQ(1,fd->offset);  /* seqno */
476     ASSERT_EQ(40,fd->len);    /* segment length */
477     ASSERT_EQ(0,fd->flags);
478     ASSERT_NE(NULL,fd->data);
479     ASSERT_EQ(NULL,fd->next);
480
481
482
483     /* have another go at wrapping things up */
484     pinfo.fd->num = 4;
485     fd_head=fragment_add_seq(tvb, 20, &pinfo, 12, fragment_table,
486                              2, 100, FALSE);
487
488     ASSERT_EQ(1,g_hash_table_size(fragment_table));
489     ASSERT_NE(NULL,fd_head);
490
491     /* check the contents of the structure */
492     ASSERT_EQ(0,fd_head->frame);  /* unused */
493     ASSERT_EQ(0,fd_head->offset); /* unused */
494     ASSERT_EQ(190,fd_head->len); /* the length of data we have */
495     ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
496     ASSERT_EQ(4,fd_head->reassembled_in);
497     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
498     ASSERT_NE(NULL,fd_head->data);
499     ASSERT_NE(NULL,fd_head->next);
500
501     fd=fd_head->next;
502     ASSERT_EQ(1,fd->frame);
503     ASSERT_EQ(0,fd->offset);  /* seqno */
504     ASSERT_EQ(50,fd->len);    /* segment length */
505     ASSERT_EQ(0,fd->flags);
506     ASSERT_EQ(NULL,fd->data);
507     ASSERT_NE(NULL,fd->next);
508
509     fd=fd->next;
510     ASSERT_EQ(2,fd->frame);
511     ASSERT_EQ(1,fd->offset);  /* seqno */
512     ASSERT_EQ(40,fd->len);    /* segment length */
513     ASSERT_EQ(0,fd->flags);
514     ASSERT_EQ(NULL,fd->data);
515     ASSERT_NE(NULL,fd->next);
516
517     fd=fd->next;
518     ASSERT_EQ(3,fd->frame);
519     ASSERT_EQ(1,fd->offset);  /* seqno */
520     ASSERT_EQ(40,fd->len);    /* segment length */
521     ASSERT_EQ(FD_OVERLAP,fd->flags);
522     ASSERT_EQ(NULL,fd->data);
523     ASSERT_NE(NULL,fd->next);
524
525     fd=fd->next;
526     ASSERT_EQ(4,fd->frame);
527     ASSERT_EQ(2,fd->offset);  /* seqno */
528     ASSERT_EQ(100,fd->len);    /* segment length */
529     ASSERT_EQ(0,fd->flags);
530     ASSERT_EQ(NULL,fd->data);
531     ASSERT_EQ(NULL,fd->next);
532
533     /* test the actual reassembly */
534     ASSERT(!memcmp(fd_head->data,data+10,50));
535     ASSERT(!memcmp(fd_head->data+50,data,40));
536     ASSERT(!memcmp(fd_head->data+90,data+20,100));
537
538
539     /* do it again (this time it is more complicated, with an overlap in the
540      * reassembly) */
541
542     fragment_set_partial_reassembly(&pinfo,12,fragment_table);
543
544     pinfo.fd->num = 5;
545     fd_head=fragment_add_seq(tvb, 0, &pinfo, 12, fragment_table,
546                              3, 40, FALSE);
547
548     fd_head=fragment_get(&pinfo,12,fragment_table);
549     ASSERT_NE(NULL,fd_head);
550     ASSERT_EQ(0,fd_head->frame);   /* unused */
551     ASSERT_EQ(0,fd_head->offset);  /* unused */
552     ASSERT_EQ(230,fd_head->len);   /* the length of data we have */
553     ASSERT_EQ(3,fd_head->datalen); /* seqno of the last fragment we have */
554     ASSERT_EQ(5,fd_head->reassembled_in);
555     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
556     ASSERT_NE(NULL,fd_head->data);
557     ASSERT_NE(NULL,fd_head->next);
558
559     fd=fd_head->next;
560     ASSERT_EQ(1,fd->frame);
561     ASSERT_EQ(0,fd->offset);  /* seqno */
562     ASSERT_EQ(50,fd->len);    /* segment length */
563     ASSERT_EQ(0,fd->flags);
564     ASSERT_EQ(NULL,fd->data);
565     ASSERT_NE(NULL,fd->next);
566
567     fd=fd->next;
568     ASSERT_EQ(2,fd->frame);
569     ASSERT_EQ(1,fd->offset);  /* seqno */
570     ASSERT_EQ(40,fd->len);    /* segment length */
571     ASSERT_EQ(0,fd->flags);
572     ASSERT_EQ(NULL,fd->data);
573     ASSERT_NE(NULL,fd->next);
574
575     fd=fd->next;
576     ASSERT_EQ(3,fd->frame);
577     ASSERT_EQ(1,fd->offset);  /* seqno */
578     ASSERT_EQ(40,fd->len);    /* segment length */
579     ASSERT_EQ(FD_OVERLAP,fd->flags);
580     ASSERT_EQ(NULL,fd->data);
581     ASSERT_NE(NULL,fd->next);
582
583     fd=fd->next;
584     ASSERT_EQ(4,fd->frame);
585     ASSERT_EQ(2,fd->offset);  /* seqno */
586     ASSERT_EQ(100,fd->len);   /* segment length */
587     ASSERT_EQ(0,fd->flags);
588     ASSERT_EQ(NULL,fd->data);
589     ASSERT_NE(NULL,fd->next);
590
591     fd=fd->next;
592     ASSERT_EQ(5,fd->frame);
593     ASSERT_EQ(3,fd->offset);  /* seqno */
594     ASSERT_EQ(40,fd->len);    /* segment length */
595     ASSERT_EQ(0,fd->flags);
596     ASSERT_EQ(NULL,fd->data);
597     ASSERT_EQ(NULL,fd->next);
598
599     /* test the actual reassembly */
600     ASSERT(!memcmp(fd_head->data,data+10,50));
601     ASSERT(!memcmp(fd_head->data+50,data,40));
602     ASSERT(!memcmp(fd_head->data+90,data+20,100));
603     ASSERT(!memcmp(fd_head->data+190,data,40));
604 }
605
606 /**********************************************************************************
607  *
608  * fragment_add_dcerpc_dg
609  *
610  *********************************************************************************/
611
612 /* This can afford to be reasonably minimal, as it's just the same logic with a
613  * different hash key to fragment_add_seq
614  */
615 static void
616 test_fragment_add_dcerpc_dg(void)
617 {
618     e_uuid_t act_id = {1,2,3,{4,5,6,7,8,9,10,11}};
619
620     fragment_data *fd_head, *fdh0;
621     GHashTable *fragment_table = NULL;
622
623     printf("Starting test test_fragment_add_dcerpc_dg\n");
624
625     /* we need our own fragment table */
626     dcerpc_fragment_table_init(&fragment_table);
627     fd_head=fragment_add_dcerpc_dg(tvb, 10, &pinfo, 12, &act_id, fragment_table,
628                                    0, 50, TRUE);
629
630     ASSERT_EQ(1,g_hash_table_size(fragment_table));
631     ASSERT_EQ(NULL,fd_head);
632
633     /* start another pdu (just to confuse things) */
634     pinfo.fd->num = 2;
635     fd_head=fragment_add_dcerpc_dg(tvb, 15, &pinfo, 13, &act_id, fragment_table,
636                              0, 60, TRUE);
637     ASSERT_EQ(2,g_hash_table_size(fragment_table));
638     ASSERT_EQ(NULL,fd_head);
639
640     /* another pdu, with the same fragment_id, but a different act_id, to the
641      * first one */
642     pinfo.fd->num = 3;
643     act_id.Data1=2;
644     fd_head=fragment_add_dcerpc_dg(tvb, 15, &pinfo, 12, &act_id, fragment_table,
645                                    0, 60, TRUE);
646     ASSERT_EQ(3,g_hash_table_size(fragment_table));
647     ASSERT_EQ(NULL,fd_head);
648     act_id.Data1=1;
649
650     /* now we add the terminal fragment of the first datagram */
651     pinfo.fd->num = 4;
652     fd_head=fragment_add_dcerpc_dg(tvb, 5, &pinfo, 12, &act_id, fragment_table,
653                                    1, 60, FALSE);
654
655     ASSERT_EQ(3,g_hash_table_size(fragment_table));
656     ASSERT_NE(NULL,fd_head);
657
658     /* check the contents of the structure */
659     ASSERT_EQ(0,fd_head->frame);  /* unused */
660     ASSERT_EQ(0,fd_head->offset); /* unused */
661     ASSERT_EQ(110,fd_head->len); /* the length of data we have */
662     ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */
663     ASSERT_EQ(4,fd_head->reassembled_in);
664     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
665     ASSERT_NE(NULL,fd_head->data);
666     ASSERT_NE(NULL,fd_head->next);
667
668     /* test the actual reassembly */
669     ASSERT(!memcmp(fd_head->data,data+10,50));
670     ASSERT(!memcmp(fd_head->data+50,data+5,60));
671
672     /* what happens if we revisit the packets now? */
673     fdh0 = fd_head;
674     pinfo.fd->flags.visited = 1;
675     pinfo.fd->num = 1;
676     fd_head=fragment_add_dcerpc_dg(tvb, 10, &pinfo, 12, &act_id, fragment_table,
677                                    0, 50, TRUE);
678     /*
679      * this api relies on the caller to check fd_head -> reassembled_in
680      *
681      * Redoing all the tests seems like overkill - just check the pointer
682      */
683     ASSERT_EQ(fdh0,fd_head);
684 }
685
686 /**********************************************************************************
687  *
688  * fragment_add_seq_check
689  *
690  *********************************************************************************/
691
692
693 /* This routine is used for both fragment_add_seq_802_11 and
694  * fragment_add_seq_check.
695  *
696  * Adds a couple of out-of-order fragments and checks their reassembly.
697  */
698
699 /*   visit  id  frame  frag  len  more  tvb_offset
700        0    12     1     0    50   T      10
701        0    13     2     0    60   T      15
702        0    12     3     2    60   F       5
703        0    12     4     1    60   F      15
704 */
705
706
707 static void
708 test_fragment_add_seq_check_work(fragment_data *(*fn)(tvbuff_t *, const int,
709                                  const packet_info *, const guint32, GHashTable *,
710                                  GHashTable *, const guint32, const guint32, const gboolean))
711 {
712     fragment_data *fd_head;
713
714     pinfo.fd -> num = 1;
715     fd_head=fn(tvb, 10, &pinfo, 12, fragment_table,
716                reassembled_table, 0, 50, TRUE);
717
718     ASSERT_EQ(1,g_hash_table_size(fragment_table));
719     ASSERT_EQ(0,g_hash_table_size(reassembled_table));
720     ASSERT_EQ(NULL,fd_head);
721
722     /* start another pdu (just to confuse things) */
723     pinfo.fd->num = 2;
724     fd_head=fn(tvb, 15, &pinfo, 13, fragment_table,
725                reassembled_table, 0, 60, TRUE);
726     ASSERT_EQ(2,g_hash_table_size(fragment_table));
727     ASSERT_EQ(0,g_hash_table_size(reassembled_table));
728     ASSERT_EQ(NULL,fd_head);
729
730     /* add the terminal fragment of the first datagram */
731     pinfo.fd->num = 3;
732     fd_head=fn(tvb, 5, &pinfo, 12, fragment_table,
733                reassembled_table, 2, 60, FALSE);
734
735     /* we haven't got all the fragments yet ... */
736     ASSERT_EQ(2,g_hash_table_size(fragment_table));
737     ASSERT_EQ(0,g_hash_table_size(reassembled_table));
738     ASSERT_EQ(NULL,fd_head);
739
740     /* finally, add the missing fragment */
741     pinfo.fd->num = 4;
742     fd_head=fn(tvb, 15, &pinfo, 12, fragment_table,
743                reassembled_table, 1, 60, TRUE);
744
745     ASSERT_EQ(1,g_hash_table_size(fragment_table));
746     ASSERT_EQ(3,g_hash_table_size(reassembled_table));
747     ASSERT_NE(NULL,fd_head);
748
749     /* check the contents of the structure */
750     ASSERT_EQ(0,fd_head->frame);  /* unused */
751     ASSERT_EQ(0,fd_head->offset); /* unused */
752     ASSERT_EQ(170,fd_head->len); /* the length of data we have */
753     ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
754     ASSERT_EQ(4,fd_head->reassembled_in);
755     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
756     ASSERT_NE(NULL,fd_head->data);
757     ASSERT_NE(NULL,fd_head->next);
758
759     ASSERT_EQ(1,fd_head->next->frame);
760     ASSERT_EQ(0,fd_head->next->offset);  /* seqno */
761     ASSERT_EQ(50,fd_head->next->len);    /* segment length */
762     ASSERT_EQ(0,fd_head->next->flags);
763     ASSERT_EQ(NULL,fd_head->next->data);
764     ASSERT_NE(NULL,fd_head->next->next);
765
766     ASSERT_EQ(4,fd_head->next->next->frame);
767     ASSERT_EQ(1,fd_head->next->next->offset);  /* seqno */
768     ASSERT_EQ(60,fd_head->next->next->len);    /* segment length */
769     ASSERT_EQ(0,fd_head->next->next->flags);
770     ASSERT_EQ(NULL,fd_head->next->next->data);
771     ASSERT_NE(NULL,fd_head->next->next->next);
772
773     ASSERT_EQ(3,fd_head->next->next->next->frame);
774     ASSERT_EQ(2,fd_head->next->next->next->offset);  /* seqno */
775     ASSERT_EQ(60,fd_head->next->next->next->len);    /* segment length */
776     ASSERT_EQ(0,fd_head->next->next->next->flags);
777     ASSERT_EQ(NULL,fd_head->next->next->next->data);
778     ASSERT_EQ(NULL,fd_head->next->next->next->next);
779
780     /* test the actual reassembly */
781     ASSERT(!memcmp(fd_head->data,data+10,50));
782     ASSERT(!memcmp(fd_head->data+50,data+15,60));
783     ASSERT(!memcmp(fd_head->data+110,data+5,60));
784
785 #if 0
786     print_tables();
787 #endif
788 }
789
790 /* Simple test case for fragment_add_seq_check
791  */
792 static void
793 test_fragment_add_seq_check(void)
794 {
795     printf("Starting test test_fragment_add_seq_check\n");
796
797     test_fragment_add_seq_check_work(fragment_add_seq_check);
798 }
799
800
801 /* This tests the case that the 802.11 hack does something different for: when
802  * the terminal segment in a fragmented datagram arrives first.
803  */
804 static void
805 test_fragment_add_seq_check_1(void)
806 {
807     fragment_data *fd_head;
808
809     printf("Starting test test_fragment_add_seq_check_1\n");
810
811     pinfo.fd->num = 1;
812     fd_head=fragment_add_seq_check(tvb, 10, &pinfo, 12, fragment_table,
813                                    reassembled_table, 1, 50, FALSE);
814
815     ASSERT_EQ(1,g_hash_table_size(fragment_table));
816     ASSERT_EQ(0,g_hash_table_size(reassembled_table));
817     ASSERT_EQ(NULL,fd_head);
818
819     /* Now add the missing segment */
820     pinfo.fd->num = 2;
821     fd_head=fragment_add_seq_check(tvb, 5, &pinfo, 12, fragment_table,
822                                    reassembled_table, 0, 60, TRUE);
823
824     ASSERT_EQ(0,g_hash_table_size(fragment_table));
825     ASSERT_EQ(2,g_hash_table_size(reassembled_table));
826     ASSERT_NE(NULL,fd_head);
827
828     /* check the contents of the structure */
829     ASSERT_EQ(0,fd_head->frame);  /* unused */
830     ASSERT_EQ(0,fd_head->offset); /* unused */
831     ASSERT_EQ(110,fd_head->len); /* the length of data we have */
832     ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */
833     ASSERT_EQ(2,fd_head->reassembled_in);
834     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
835     ASSERT_NE(NULL,fd_head->data);
836     ASSERT_NE(NULL,fd_head->next);
837
838     ASSERT_EQ(2,fd_head->next->frame);
839     ASSERT_EQ(0,fd_head->next->offset);  /* seqno */
840     ASSERT_EQ(60,fd_head->next->len);    /* segment length */
841     ASSERT_EQ(0,fd_head->next->flags);
842     ASSERT_EQ(NULL,fd_head->next->data);
843     ASSERT_NE(NULL,fd_head->next->next);
844
845     ASSERT_EQ(1,fd_head->next->next->frame);
846     ASSERT_EQ(1,fd_head->next->next->offset);  /* seqno */
847     ASSERT_EQ(50,fd_head->next->next->len);    /* segment length */
848     ASSERT_EQ(0,fd_head->next->next->flags);
849     ASSERT_EQ(NULL,fd_head->next->next->data);
850     ASSERT_EQ(NULL,fd_head->next->next->next);
851
852     /* test the actual reassembly */
853     ASSERT(!memcmp(fd_head->data,data+5,60));
854     ASSERT(!memcmp(fd_head->data+60,data+10,50));
855 }
856
857 /**********************************************************************************
858  *
859  * fragment_add_seq_802_11
860  *
861  *********************************************************************************/
862
863 /* Tests the 802.11 hack.
864  */
865 static void
866 test_fragment_add_seq_802_11_0(void)
867 {
868     fragment_data *fd_head;
869
870     printf("Starting test test_fragment_add_seq_802_11_0\n");
871
872     /* the 802.11 hack is that some non-fragmented datagrams have non-zero
873      * fragment_number; test for this. */
874
875     pinfo.fd->num = 1;
876     fd_head=fragment_add_seq_802_11(tvb, 10, &pinfo, 12, fragment_table,
877                                     reassembled_table, 10, 50, FALSE);
878
879     ASSERT_EQ(0,g_hash_table_size(fragment_table));
880     ASSERT_EQ(1,g_hash_table_size(reassembled_table));
881     ASSERT_NE(NULL,fd_head);
882
883     /* check the contents of the structure */
884     ASSERT_EQ(0,fd_head->frame);  /* unused */
885     ASSERT_EQ(0,fd_head->offset); /* unused */
886     ASSERT_EQ(0,fd_head->len);    /* unused */
887     ASSERT_EQ(0,fd_head->datalen); /* unused */
888     ASSERT_EQ(1,fd_head->reassembled_in);
889     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE,fd_head->flags);
890     ASSERT_EQ(NULL,fd_head->data);
891     ASSERT_EQ(NULL,fd_head->next);
892 }
893
894 /* Reuse the fragment_add_seq_check testcases */
895 static void test_fragment_add_seq_802_11_1(void)
896 {
897     printf("Starting test test_fragment_add_seq_802_11_1\n");
898     test_fragment_add_seq_check_work(fragment_add_seq_802_11);
899 }
900
901 /**********************************************************************************
902  *
903  * fragment_add_seq_check_multiple
904  *
905  *********************************************************************************/
906
907 /* Test 2 partial frags from 2 diff datagrams in the same frame */
908 /*
909    datagram #1: frame 1 + first part of frame 2
910    datagram #1: last part of frame 2 + frame 3
911
912    Is this a valid scenario ?
913
914    The result of calling fragment_add_seq_check() for these
915    fragments is a reassembled_table with:
916     id, frame 1 => first_datagram;  ["reassembled in" frame 2]
917     id, frame 2 => second_datagram; ["reassembled in" frame 3]
918     id, frame 3 => second_datagram;
919
920     Note that the id, frame 2 => first datagram was overwritten
921      by the entry for the second datagram.
922    Is this OK ? IE: When dissected/displayed
923       will the reassembled datagram 1 appear with frame 2 ??
924 */
925
926 /*   visit  id  frame  frag  len  more  tvb_offset
927        0    12     1     0    50   T      10
928        0    12     2     1    20   F       5
929        0    12     2     0    25   T      25
930        0    12     3     1    60   F       0
931 */
932
933 /*
934    Is this a valid scenario ?
935    Is this OK ? IE: When dissected/displayed:
936       Will the reassembled datagram 1 appear with frame 2 ??
937 */
938 #if 0
939 static void
940 test_fragment_add_seq_check_multiple(void) {
941     fragment_data *fd_head;
942
943     pinfo.fd -> num = 1;
944     fd_head=fragment_add_seq_check(tvb, 10, &pinfo, 12, fragment_table,
945                                    reassembled_table, 0, 50, TRUE);
946
947     /* add the terminal fragment of the first datagram */
948     pinfo.fd->num = 2;
949     fd_head=fragment_add_seq_check(tvb, 5, &pinfo, 12, fragment_table,
950                                    reassembled_table, 1, 20, FALSE);
951
952     print_tables();
953
954     /* Now: start a second datagram with the first fragment in frame #2 */
955     pinfo.fd->num = 2;
956     fd_head=fragment_add_seq_check(tvb, 25, &pinfo, 12, fragment_table,
957                reassembled_table, 0, 25, TRUE);
958
959     /* add the terminal fragment of the second datagram */
960     pinfo.fd->num = 3;
961     fd_head=fragment_add_seq_check(tvb, 0, &pinfo, 12, fragment_table,
962                                    reassembled_table, 1, 60, FALSE);
963
964     print_tables();
965 }
966 #endif
967
968 /**********************************************************************************
969  *
970  * fragment_add_seq_next
971  *
972  *********************************************************************************/
973
974 /* Simple test case for fragment_add_seq_next.
975  * Adds a couple of fragments (with one for a different datagram in between),
976  * and checks that they are reassembled correctly.
977  */
978 static void
979 test_simple_fragment_add_seq_next(void)
980 {
981     fragment_data *fd_head;
982
983     printf("Starting test test_simple_fragment_add_seq_next\n");
984
985     pinfo.fd->num = 1;
986     fd_head= fragment_add_seq_next(tvb, 10, &pinfo, 12, fragment_table,
987                                   reassembled_table, 50, TRUE);
988
989     ASSERT_EQ(1,g_hash_table_size(fragment_table));
990     ASSERT_EQ(0,g_hash_table_size(reassembled_table));
991     ASSERT_EQ(NULL,fd_head);
992
993     /* adding the same fragment again should do nothing, even with different
994      * offset etc */
995     pinfo.fd->flags.visited = 1;
996     fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
997                                   reassembled_table, 60, TRUE);
998     ASSERT_EQ(1,g_hash_table_size(fragment_table));
999     ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1000     ASSERT_EQ(NULL,fd_head);
1001
1002     /* start another pdu (just to confuse things) */
1003     pinfo.fd->flags.visited = 0;
1004     pinfo.fd->num = 2;
1005     fd_head=fragment_add_seq_next(tvb, 15, &pinfo, 13, fragment_table,
1006                                   reassembled_table, 60, TRUE);
1007     ASSERT_EQ(2,g_hash_table_size(fragment_table));
1008     ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1009     ASSERT_EQ(NULL,fd_head);
1010
1011
1012     /* now we add the terminal fragment of the first datagram */
1013     pinfo.fd->num = 3;
1014     fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
1015                                   reassembled_table, 60, FALSE);
1016
1017     ASSERT_EQ(1,g_hash_table_size(fragment_table));
1018     ASSERT_EQ(2,g_hash_table_size(reassembled_table));
1019     ASSERT_NE(NULL,fd_head);
1020
1021     /* check the contents of the structure */
1022     ASSERT_EQ(0,fd_head->frame);  /* unused */
1023     ASSERT_EQ(0,fd_head->offset); /* unused */
1024     ASSERT_EQ(110,fd_head->len); /* the length of data we have */
1025     ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */
1026     ASSERT_EQ(3,fd_head->reassembled_in);
1027     ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
1028     ASSERT_NE(NULL,fd_head->data);
1029     ASSERT_NE(NULL,fd_head->next);
1030
1031     ASSERT_EQ(1,fd_head->next->frame);
1032     ASSERT_EQ(0,fd_head->next->offset);  /* seqno */
1033     ASSERT_EQ(50,fd_head->next->len);    /* segment length */
1034     ASSERT_EQ(0,fd_head->next->flags);
1035     ASSERT_EQ(NULL,fd_head->next->data);
1036     ASSERT_NE(NULL,fd_head->next->next);
1037
1038     ASSERT_EQ(3,fd_head->next->next->frame);
1039     ASSERT_EQ(1,fd_head->next->next->offset);  /* seqno */
1040     ASSERT_EQ(60,fd_head->next->next->len);    /* segment length */
1041     ASSERT_EQ(0,fd_head->next->next->flags);
1042     ASSERT_EQ(NULL,fd_head->next->next->data);
1043     ASSERT_EQ(NULL,fd_head->next->next->next);
1044
1045     /* test the actual reassembly */
1046     ASSERT(!memcmp(fd_head->data,data+10,50));
1047     ASSERT(!memcmp(fd_head->data+50,data+5,60));
1048 }
1049
1050
1051 /* This tests the case where some data is missing from one of the fragments.
1052  * It should prevent reassembly.
1053  */
1054 static void
1055 test_missing_data_fragment_add_seq_next(void)
1056 {
1057     fragment_data *fd_head;
1058
1059     printf("Starting test test_missing_data_fragment_add_seq_next\n");
1060
1061     /* attempt to add a fragment which is longer than the data available */
1062     pinfo.fd->num = 1;
1063     fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 12, fragment_table,
1064                                   reassembled_table, DATA_LEN-9, TRUE);
1065
1066     ASSERT_EQ(1,g_hash_table_size(fragment_table));
1067     ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1068     ASSERT_NE(NULL,fd_head);
1069
1070     /* check the contents of the structure. Reassembly failed so everything
1071      * should be null (meaning, just use the original tvb)  */
1072     ASSERT_EQ(0,fd_head->frame);  /* unused */
1073     ASSERT_EQ(0,fd_head->offset); /* unused */
1074     ASSERT_EQ(0,fd_head->len); /* the length of data we have */
1075     ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
1076     ASSERT_EQ(0,fd_head->reassembled_in);
1077     ASSERT_EQ(FD_BLOCKSEQUENCE,fd_head->flags & 0x1ff);
1078     ASSERT_EQ(NULL,fd_head->data);
1079     ASSERT_EQ(NULL,fd_head->next);
1080
1081     /* add another fragment (with all data present) */
1082     pinfo.fd->num = 4;
1083     fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
1084                                   reassembled_table, 60, FALSE);
1085
1086     /* XXX: it's not clear that this is the right result; however it's what the
1087      * code does...
1088      */
1089     ASSERT_EQ(1,g_hash_table_size(fragment_table));
1090     ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1091     ASSERT_EQ(NULL,fd_head);
1092
1093
1094     /* check what happens when we revisit the packets */
1095     pinfo.fd->flags.visited = TRUE;
1096     pinfo.fd->num = 1;
1097
1098     fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 12, fragment_table,
1099                                   reassembled_table, DATA_LEN-9, TRUE);
1100
1101     /* We just look in the reassembled_table for this packet. It never got put
1102      * there, so this always returns null.
1103      *
1104      * That's crazy, because it means that the subdissector will see the data
1105      * exactly once - on the first pass through the capture (well, assuming it
1106      * doesn't bother to check fd_head->reassembled_in); however, that's
1107      * what the code does...
1108      */
1109     ASSERT_EQ(1,g_hash_table_size(fragment_table));
1110     ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1111     ASSERT_EQ(NULL,fd_head);
1112
1113     pinfo.fd->num = 4;
1114     fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
1115                                   reassembled_table, 60, FALSE);
1116     ASSERT_EQ(1,g_hash_table_size(fragment_table));
1117     ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1118     ASSERT_EQ(NULL,fd_head);
1119 }
1120
1121
1122 /*
1123  * we're going to do something similar now, but this time it is the second
1124  * fragment which has something missing.
1125  */
1126 static void
1127 test_missing_data_fragment_add_seq_next_2(void)
1128 {
1129     fragment_data *fd_head;
1130
1131     printf("Starting test test_missing_data_fragment_add_seq_next_2\n");
1132
1133     pinfo.fd->num = 11;
1134     fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 24, fragment_table,
1135                                   reassembled_table, 50, TRUE);
1136
1137     ASSERT_EQ(1,g_hash_table_size(fragment_table));
1138     ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1139     ASSERT_EQ(NULL,fd_head);
1140
1141     pinfo.fd->num = 12;
1142     fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 24, fragment_table,
1143                                   reassembled_table, DATA_LEN-4, FALSE);
1144
1145     /* XXX: again, i'm really dubious about this. Surely this should return all
1146      * the data we had, for a best-effort attempt at dissecting it?
1147      * And it ought to go into the reassembled table?
1148      */
1149     ASSERT_EQ(0,g_hash_table_size(fragment_table));
1150     ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1151     ASSERT_EQ(NULL,fd_head);
1152
1153     /* check what happens when we revisit the packets */
1154     pinfo.fd->flags.visited = TRUE;
1155     pinfo.fd->num = 11;
1156
1157     fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 24, fragment_table,
1158                                   reassembled_table, 50, TRUE);
1159
1160     /* As before, this returns NULL because the fragment isn't in the
1161      * reassembled_table. At least this is a bit more consistent than before.
1162      */
1163     ASSERT_EQ(0,g_hash_table_size(fragment_table));
1164     ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1165     ASSERT_EQ(NULL,fd_head);
1166
1167     pinfo.fd->num = 12;
1168     fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 24, fragment_table,
1169                                   reassembled_table, DATA_LEN-4, FALSE);
1170     ASSERT_EQ(0,g_hash_table_size(fragment_table));
1171     ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1172     ASSERT_EQ(NULL,fd_head);
1173
1174 }
1175
1176 /*
1177  * This time, our datagram only has one segment, but it has data missing.
1178  */
1179 static void
1180 test_missing_data_fragment_add_seq_next_3(void)
1181 {
1182     fragment_data *fd_head;
1183
1184     printf("Starting test test_missing_data_fragment_add_seq_next_3\n");
1185
1186     pinfo.fd->num = 20;
1187     fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 30, fragment_table,
1188                                   reassembled_table, DATA_LEN-4, FALSE);
1189
1190     ASSERT_EQ(0,g_hash_table_size(fragment_table));
1191     ASSERT_EQ(1,g_hash_table_size(reassembled_table));
1192     ASSERT_NE(NULL,fd_head);
1193
1194     /* check the contents of the structure. */
1195     ASSERT_EQ(0,fd_head->frame);  /* unused */
1196     ASSERT_EQ(0,fd_head->offset); /* unused */
1197     ASSERT_EQ(0,fd_head->len); /* the length of data we have */
1198     ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
1199     ASSERT_EQ(20,fd_head->reassembled_in);
1200     ASSERT_EQ(FD_BLOCKSEQUENCE|FD_DEFRAGMENTED,fd_head->flags);
1201     ASSERT_EQ(NULL,fd_head->data);
1202     ASSERT_EQ(NULL,fd_head->next);
1203
1204     /* revisiting the packet ought to produce the same result. */
1205     pinfo.fd->flags.visited = TRUE;
1206
1207     pinfo.fd->num = 20;
1208     fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 30, fragment_table,
1209                                   reassembled_table, DATA_LEN-4, FALSE);
1210
1211     ASSERT_EQ(0,g_hash_table_size(fragment_table));
1212     ASSERT_EQ(1,g_hash_table_size(reassembled_table));
1213     ASSERT_NE(NULL,fd_head);
1214     ASSERT_EQ(0,fd_head->frame);  /* unused */
1215     ASSERT_EQ(0,fd_head->offset); /* unused */
1216     ASSERT_EQ(0,fd_head->len); /* the length of data we have */
1217     ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
1218     ASSERT_EQ(20,fd_head->reassembled_in);
1219     ASSERT_EQ(FD_BLOCKSEQUENCE|FD_DEFRAGMENTED,fd_head->flags);
1220     ASSERT_EQ(NULL,fd_head->data);
1221     ASSERT_EQ(NULL,fd_head->next);
1222 }
1223
1224
1225 /**********************************************************************************
1226  *
1227  * main
1228  *
1229  *********************************************************************************/
1230
1231 int
1232 main(int argc _U_, char **argv _U_)
1233 {
1234     frame_data fd;
1235     char src[] = {1,2,3,4}, dst[] = {5,6,7,8};
1236     unsigned int i;
1237     void (*tests[])(void) = {
1238         test_simple_fragment_add_seq,              /* frag table only   */
1239         test_fragment_add_seq_partial_reassembly,
1240         test_fragment_add_dcerpc_dg,
1241         test_fragment_add_seq_check,               /* frag + reassemble */
1242         test_fragment_add_seq_check_1,
1243         test_fragment_add_seq_802_11_0,
1244         test_fragment_add_seq_802_11_1,
1245         test_simple_fragment_add_seq_next,
1246         test_missing_data_fragment_add_seq_next,
1247         test_missing_data_fragment_add_seq_next_2,
1248         test_missing_data_fragment_add_seq_next_3,
1249 #if 0
1250         test_fragment_add_seq_check_multiple
1251 #endif
1252     };
1253
1254     /* initialise stuff */
1255     emem_init();
1256     tvbuff_init();
1257     reassemble_init();
1258
1259     /* a tvbuff for testing with */
1260     data = g_malloc(DATA_LEN);
1261     /* make sure it's full of stuff */
1262     for(i=0; i<DATA_LEN; i++) {
1263         data[i]=i & 0xFF;
1264     }
1265     tvb = tvb_new_real_data(data, DATA_LEN, DATA_LEN*2);
1266
1267     /* other test stuff */
1268     pinfo.fd = &fd;
1269     fd.flags.visited = 0;
1270     SET_ADDRESS(&pinfo.src,AT_IPv4,4,src);
1271     SET_ADDRESS(&pinfo.dst,AT_IPv4,4,dst);
1272
1273     /*************************************************************************/
1274     for(i=0; i < sizeof(tests)/sizeof(tests[0]); i++ ) {
1275         /* re-init the fragment tables */
1276         fragment_table_init(&fragment_table);
1277         ASSERT(fragment_table != NULL);
1278
1279         reassembled_table_init(&reassembled_table);
1280         ASSERT(reassembled_table != NULL);
1281
1282         pinfo.fd->flags.visited = FALSE;
1283
1284         tests[i]();
1285
1286         /* Free memory used by the tables */
1287         fragment_table_init(&fragment_table);
1288         g_hash_table_destroy(fragment_table);
1289         fragment_table = NULL;
1290
1291         reassembled_table_init(&reassembled_table);
1292         g_hash_table_destroy(reassembled_table);
1293         reassembled_table = NULL;
1294     }
1295
1296     tvb_free(tvb);
1297     tvb = NULL;
1298     g_free(data);
1299     data = NULL;
1300
1301     printf(failure?"FAILURE\n":"SUCCESS\n");
1302     return failure;
1303 }
1304
1305
1306 /* stubs */
1307 void add_new_data_source(packet_info *pinfo _U_, tvbuff_t *tvb _U_,
1308                         const char *name _U_)
1309 {}
1310
1311 proto_item *
1312 proto_tree_add_uint(proto_tree *tree _U_, int hfindex _U_, tvbuff_t *tvb _U_,
1313                     gint start _U_, gint length _U_, guint32 value _U_)
1314 { return NULL; }
1315
1316 void proto_item_prepend_text(proto_item *ti _U_, const char *format _U_, ...)
1317 {}
1318
1319 void proto_item_append_text(proto_item *ti _U_, const char *format _U_, ...)
1320 {}
1321
1322 proto_item *proto_tree_add_uint_format(proto_tree *tree _U_, int hfindex _U_,
1323                                        tvbuff_t *tvb _U_, gint start _U_,
1324                                        gint length _U_, guint32 value _U_,
1325                                        const char *format _U_, ...)
1326 { return NULL; }
1327
1328 proto_tree* proto_item_add_subtree(proto_item *ti _U_, const gint idx _U_)
1329 { return NULL; }
1330
1331 proto_item *proto_tree_add_boolean(proto_tree *tree _U_, int hfindex _U_,
1332                                    tvbuff_t *tvb _U_, gint start _U_,
1333                                    gint length _U_, guint32 value _U_)
1334 { return NULL; }
1335
1336 proto_item *proto_tree_add_item(proto_tree *tree _U_, const int hfindex _U_,
1337                                 tvbuff_t *tvb _U_, const gint start _U_,
1338                                 gint length _U_,
1339                                 const guint encoding _U_)
1340 { return NULL; }
1341
1342 gint check_col(column_info *cinfo _U_, const gint col _U_)
1343 { return 0; }
1344
1345 void col_add_fstr(column_info *cinfo _U_, const gint col _U_, const gchar *format _U_,
1346                        ...)
1347 {}
1348
1349 const char* proto_registrar_get_name(const int n _U_)
1350 { return ""; }
1351
1352 void proto_item_set_text(proto_item *ti _U_, const char *format _U_, ...)
1353 { }