1 /* Standalone program to test functionality of reassemble.h API
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.
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:
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
26 * 2. Debug functions have been added which will print information
27 * about the fd-chains associated with the fragment_table and the
29 * #define debug to enable the code.
33 * Copyright (c) 2007 MX Telecom Ltd. <richardv@mxtelecom.com>
35 * Wireshark - Network traffic analyzer
36 * By Gerald Combs <gerald@wireshark.org>
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
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>
72 #include <epan/dissectors/packet-dcerpc.h>
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)
78 static int failure = 0;
81 do_test(gboolean condition, const char *format, ...)
89 vfprintf(stderr, format, ap);
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.
103 static tvbuff_t *tvb;
104 static packet_info pinfo;
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;
113 /*************************************************
114 * Util fcns to display
115 * fragment_table & reassembled_table fd-chains
116 ************************************************/
118 /* Must match the typedef in reassemble.c */
119 typedef struct _fragment_key {
125 /* Must match the typedef in reassemble.c */
126 typedef struct _reassembled_key {
131 static struct _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"},
142 {FD_OVERLAPCONFLICT ,"OC"},
143 {FD_MULTIPLETAILS ,"MT"},
144 {FD_TOOLONGFRAGMENT ,"TL"},
146 #define N_FD_FLAGS (signed)(sizeof(fd_flags)/sizeof(struct _fd_flags))
149 print_fd(fragment_data *fd, gboolean is_head) {
152 g_assert(fd != NULL);
153 printf(" %08x %08x %3d %3d %3d", fd, fd->next, fd->frame, fd->offset, fd->len);
155 printf(" %3d %3d", fd->datalen, fd->reassembled_in);
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 : " ");
167 print_fd_chain(fragment_data *fd_head) {
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);
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);
186 print_fragment_table(void) {
187 printf("\n Fragment Table -------\n");
188 g_hash_table_foreach(fragment_table, print_fragment_table_chain, NULL);
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);
200 print_reassembled_table(void) {
201 printf("\n Reassembled Table ----\n");
202 g_hash_table_foreach(reassembled_table, print_reassembled_table_chain, NULL);
207 print_fragment_table();
208 print_reassembled_table();
212 /**********************************************************************************
216 *********************************************************************************/
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.
222 /* visit id frame frag len more tvb_offset
230 test_simple_fragment_add_seq(void)
232 fragment_data *fd_head, *fdh0;
234 printf("Starting test test_simple_fragment_add_seq\n");
237 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
240 ASSERT_EQ(1,g_hash_table_size(fragment_table));
241 ASSERT_EQ(NULL,fd_head);
243 /* adding the same fragment again should do nothing, even with different
245 pinfo.fd->flags.visited = 1;
246 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
248 ASSERT_EQ(1,g_hash_table_size(fragment_table));
249 ASSERT_EQ(NULL,fd_head);
251 /* start another pdu (just to confuse things) */
252 pinfo.fd->flags.visited = 0;
254 fd_head=fragment_add_seq(tvb, 15, &pinfo, 13, fragment_table,
256 ASSERT_EQ(2,g_hash_table_size(fragment_table));
257 ASSERT_EQ(NULL,fd_head);
259 /* now we add the terminal fragment of the first datagram */
261 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
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);
268 /* finally, add the missing fragment */
270 fd_head=fragment_add_seq(tvb, 15, &pinfo, 12, fragment_table,
273 ASSERT_EQ(2,g_hash_table_size(fragment_table));
274 ASSERT_NE(NULL,fd_head);
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);
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);
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);
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);
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));
313 print_fragment_table();
316 /* what happens if we revisit the packets now? */
318 pinfo.fd->flags.visited = 1;
320 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
323 * this api relies on the caller to check fd_head -> reassembled_in
325 * Redoing all the tests seems like overkill - just check the pointer
327 ASSERT_EQ(fdh0,fd_head);
330 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
332 ASSERT_EQ(fdh0,fd_head);
335 fd_head=fragment_add_seq(tvb, 15, &pinfo, 12, fragment_table,
337 ASSERT_EQ(fdh0,fd_head);
340 print_fragment_table();
344 /* XXX ought to have some tests for overlapping fragments */
346 /* This tests the functionality of fragment_set_partial_reassembly for
347 * FD_BLOCKSEQUENCE reassembly.
349 * We add a sequence of fragments thus:
350 * seqno frame offset len (initial) more_frags
351 * ----- ----- ------ --- --------------------
354 * 1 3 0 40 true (a duplicate fragment)
359 test_fragment_add_seq_partial_reassembly(void)
361 fragment_data *fd_head, *fd;
363 printf("Starting test test_fragment_add_seq_partial_reassembly\n");
365 /* generally it's probably fair to assume that we will be called with
369 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
372 ASSERT_EQ(1,g_hash_table_size(fragment_table));
373 ASSERT_NE(NULL,fd_head);
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);
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);
392 /* test the actual reassembly */
393 ASSERT(!memcmp(fd_head->data,data+10,50));
395 /* now we announce that the reassembly wasn't complete after all. */
396 fragment_set_partial_reassembly(&pinfo,12,fragment_table);
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
403 fd_head=fragment_add_seq(tvb, 0, &pinfo, 12, fragment_table,
406 ASSERT_EQ(1,g_hash_table_size(fragment_table));
407 ASSERT_EQ(NULL,fd_head);
409 fd_head=fragment_get(&pinfo,12,fragment_table);
410 ASSERT_NE(NULL,fd_head);
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);
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);
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);
438 /* Another copy of the second segment.
441 fd_head=fragment_add_seq(tvb, 0, &pinfo, 12, fragment_table,
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);
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);
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);
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);
483 /* have another go at wrapping things up */
485 fd_head=fragment_add_seq(tvb, 20, &pinfo, 12, fragment_table,
488 ASSERT_EQ(1,g_hash_table_size(fragment_table));
489 ASSERT_NE(NULL,fd_head);
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);
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);
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);
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);
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);
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));
539 /* do it again (this time it is more complicated, with an overlap in the
542 fragment_set_partial_reassembly(&pinfo,12,fragment_table);
545 fd_head=fragment_add_seq(tvb, 0, &pinfo, 12, fragment_table,
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);
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);
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);
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);
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);
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);
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));
606 /* Test case for fragment_add_seq with duplicated (e.g., retransmitted) data.
607 * Adds three fragments--adding the 1st one twice--
608 * and checks that they are reassembled correctly.
610 /* visit id frame frag len more tvb_offset
617 test_fragment_add_seq_duplicate_first(void)
619 fragment_data *fd_head;
621 printf("Starting test test_fragment_add_seq_duplicate_first\n");
624 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
627 ASSERT_EQ(1,g_hash_table_size(fragment_table));
628 ASSERT_EQ(NULL,fd_head);
630 /* Add the 2nd segment */
632 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
635 /* we haven't got all the fragments yet ... */
636 ASSERT_EQ(1,g_hash_table_size(fragment_table));
637 ASSERT_EQ(NULL,fd_head);
639 /* Add the last fragment */
641 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
644 ASSERT_EQ(1,g_hash_table_size(fragment_table));
645 ASSERT_NE(NULL,fd_head);
647 /* Add the first fragment again */
649 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
652 /* Reassembly should have still succeeded */
653 ASSERT_EQ(1,g_hash_table_size(fragment_table));
654 ASSERT_NE(NULL,fd_head);
656 /* check the contents of the structure */
657 ASSERT_EQ(0,fd_head->frame); /* unused */
658 ASSERT_EQ(0,fd_head->offset); /* unused */
659 ASSERT_EQ(150,fd_head->len); /* the length of data we have */
660 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
661 ASSERT_EQ(3,fd_head->reassembled_in);
662 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
663 ASSERT_NE(NULL,fd_head->data);
664 ASSERT_NE(NULL,fd_head->next);
666 ASSERT_EQ(1,fd_head->next->frame);
667 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
668 ASSERT_EQ(50,fd_head->next->len); /* segment length */
669 ASSERT_EQ(0,fd_head->next->flags);
670 ASSERT_EQ(NULL,fd_head->next->data);
671 ASSERT_NE(NULL,fd_head->next->next);
673 ASSERT_EQ(4,fd_head->next->next->frame);
674 ASSERT_EQ(0,fd_head->next->next->offset); /* seqno */
675 ASSERT_EQ(50,fd_head->next->next->len); /* segment length */
676 ASSERT_EQ(FD_OVERLAP,fd_head->next->next->flags);
677 ASSERT_EQ(NULL,fd_head->next->next->data);
678 ASSERT_NE(NULL,fd_head->next->next->next);
680 ASSERT_EQ(2,fd_head->next->next->next->frame);
681 ASSERT_EQ(1,fd_head->next->next->next->offset); /* seqno */
682 ASSERT_EQ(60,fd_head->next->next->next->len); /* segment length */
683 ASSERT_EQ(0,fd_head->next->next->next->flags);
684 ASSERT_EQ(NULL,fd_head->next->next->next->data);
685 ASSERT_NE(NULL,fd_head->next->next->next->next);
687 ASSERT_EQ(3,fd_head->next->next->next->next->frame);
688 ASSERT_EQ(2,fd_head->next->next->next->next->offset); /* seqno */
689 ASSERT_EQ(40,fd_head->next->next->next->next->len); /* segment length */
690 ASSERT_EQ(0,fd_head->next->next->next->next->flags);
691 ASSERT_EQ(NULL,fd_head->next->next->next->next->data);
692 ASSERT_EQ(NULL,fd_head->next->next->next->next->next);
694 /* test the actual reassembly */
695 ASSERT(!memcmp(fd_head->data,data+10,50));
696 ASSERT(!memcmp(fd_head->data+50,data+5,60));
697 ASSERT(!memcmp(fd_head->data+110,data+5,40));
700 print_fragment_table();
705 /* Test case for fragment_add_seq with duplicated (e.g., retransmitted) data.
706 * Adds three fragments--adding the 2nd one twice--
707 * and checks that they are reassembled correctly.
709 /* visit id frame frag len more tvb_offset
716 test_fragment_add_seq_duplicate_middle(void)
718 fragment_data *fd_head;
720 printf("Starting test test_fragment_add_seq_duplicate_middle\n");
723 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
726 ASSERT_EQ(1,g_hash_table_size(fragment_table));
727 ASSERT_EQ(NULL,fd_head);
729 /* Add the 2nd segment */
731 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
734 /* we haven't got all the fragments yet ... */
735 ASSERT_EQ(1,g_hash_table_size(fragment_table));
736 ASSERT_EQ(NULL,fd_head);
738 /* Now, add the 2nd segment again (but in a different frame) */
740 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
743 /* This duplicate fragment should have been ignored */
744 ASSERT_EQ(1,g_hash_table_size(fragment_table));
745 ASSERT_EQ(NULL,fd_head);
747 /* finally, add the last fragment */
749 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
752 ASSERT_EQ(1,g_hash_table_size(fragment_table));
753 ASSERT_NE(NULL,fd_head);
755 /* check the contents of the structure */
756 ASSERT_EQ(0,fd_head->frame); /* unused */
757 ASSERT_EQ(0,fd_head->offset); /* unused */
758 ASSERT_EQ(150,fd_head->len); /* the length of data we have */
759 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
760 ASSERT_EQ(4,fd_head->reassembled_in);
761 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
762 ASSERT_NE(NULL,fd_head->data);
763 ASSERT_NE(NULL,fd_head->next);
765 ASSERT_EQ(1,fd_head->next->frame);
766 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
767 ASSERT_EQ(50,fd_head->next->len); /* segment length */
768 ASSERT_EQ(0,fd_head->next->flags);
769 ASSERT_EQ(NULL,fd_head->next->data);
770 ASSERT_NE(NULL,fd_head->next->next);
772 ASSERT_EQ(2,fd_head->next->next->frame);
773 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
774 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
775 ASSERT_EQ(0,fd_head->next->next->flags);
776 ASSERT_EQ(NULL,fd_head->next->next->data);
777 ASSERT_NE(NULL,fd_head->next->next->next);
779 ASSERT_EQ(3,fd_head->next->next->next->frame);
780 ASSERT_EQ(1,fd_head->next->next->next->offset); /* seqno */
781 ASSERT_EQ(60,fd_head->next->next->next->len); /* segment length */
782 ASSERT_EQ(FD_OVERLAP,fd_head->next->next->next->flags);
783 ASSERT_EQ(NULL,fd_head->next->next->next->data);
784 ASSERT_NE(NULL,fd_head->next->next->next->next);
786 ASSERT_EQ(4,fd_head->next->next->next->next->frame);
787 ASSERT_EQ(2,fd_head->next->next->next->next->offset); /* seqno */
788 ASSERT_EQ(40,fd_head->next->next->next->next->len); /* segment length */
789 ASSERT_EQ(0,fd_head->next->next->next->next->flags);
790 ASSERT_EQ(NULL,fd_head->next->next->next->next->data);
791 ASSERT_EQ(NULL,fd_head->next->next->next->next->next);
793 /* test the actual reassembly */
794 ASSERT(!memcmp(fd_head->data,data+10,50));
795 ASSERT(!memcmp(fd_head->data+50,data+5,60));
796 ASSERT(!memcmp(fd_head->data+110,data+5,40));
799 print_fragment_table();
803 /* Test case for fragment_add_seq with duplicated (e.g., retransmitted) data.
804 * Adds three fragments--adding the 3rd one twice--
805 * and checks that they are reassembled correctly.
807 /* visit id frame frag len more tvb_offset
814 test_fragment_add_seq_duplicate_last(void)
816 fragment_data *fd_head;
818 printf("Starting test test_fragment_add_seq_duplicate_last\n");
821 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
824 ASSERT_EQ(1,g_hash_table_size(fragment_table));
825 ASSERT_EQ(NULL,fd_head);
827 /* Add the 2nd segment */
829 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
832 /* we haven't got all the fragments yet ... */
833 ASSERT_EQ(1,g_hash_table_size(fragment_table));
834 ASSERT_EQ(NULL,fd_head);
836 /* Add the last fragment */
838 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
841 ASSERT_EQ(1,g_hash_table_size(fragment_table));
842 ASSERT_NE(NULL,fd_head);
844 /* Add the last fragment again */
846 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
849 /* Reassembly should have still succeeded */
850 ASSERT_EQ(1,g_hash_table_size(fragment_table));
851 ASSERT_NE(NULL,fd_head);
853 /* check the contents of the structure */
854 ASSERT_EQ(0,fd_head->frame); /* unused */
855 ASSERT_EQ(0,fd_head->offset); /* unused */
856 ASSERT_EQ(150,fd_head->len); /* the length of data we have */
857 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
858 ASSERT_EQ(3,fd_head->reassembled_in);
859 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
860 ASSERT_NE(NULL,fd_head->data);
861 ASSERT_NE(NULL,fd_head->next);
863 ASSERT_EQ(1,fd_head->next->frame);
864 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
865 ASSERT_EQ(50,fd_head->next->len); /* segment length */
866 ASSERT_EQ(0,fd_head->next->flags);
867 ASSERT_EQ(NULL,fd_head->next->data);
868 ASSERT_NE(NULL,fd_head->next->next);
870 ASSERT_EQ(2,fd_head->next->next->frame);
871 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
872 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
873 ASSERT_EQ(0,fd_head->next->next->flags);
874 ASSERT_EQ(NULL,fd_head->next->next->data);
875 ASSERT_NE(NULL,fd_head->next->next->next);
877 ASSERT_EQ(3,fd_head->next->next->next->frame);
878 ASSERT_EQ(2,fd_head->next->next->next->offset); /* seqno */
879 ASSERT_EQ(40,fd_head->next->next->next->len); /* segment length */
880 ASSERT_EQ(0,fd_head->next->next->next->flags);
881 ASSERT_EQ(NULL,fd_head->next->next->next->data);
882 ASSERT_NE(NULL,fd_head->next->next->next->next);
884 ASSERT_EQ(4,fd_head->next->next->next->next->frame);
885 ASSERT_EQ(2,fd_head->next->next->next->next->offset); /* seqno */
886 ASSERT_EQ(40,fd_head->next->next->next->next->len); /* segment length */
887 ASSERT_EQ(FD_OVERLAP,fd_head->next->next->next->next->flags);
888 ASSERT_EQ(NULL,fd_head->next->next->next->next->data);
889 ASSERT_EQ(NULL,fd_head->next->next->next->next->next);
891 /* test the actual reassembly */
892 ASSERT(!memcmp(fd_head->data,data+10,50));
893 ASSERT(!memcmp(fd_head->data+50,data+5,60));
894 ASSERT(!memcmp(fd_head->data+110,data+5,40));
897 print_fragment_table();
901 /* Test case for fragment_add_seq with duplicated (e.g., retransmitted) data
902 * where the retransmission "conflicts" with the original transmission
903 * (contents are different).
904 * Adds three fragments--adding the 2nd one twice--
905 * and checks that they are reassembled correctly.
907 /* visit id frame frag len more tvb_offset
914 test_fragment_add_seq_duplicate_conflict(void)
916 fragment_data *fd_head;
918 printf("Starting test test_fragment_add_seq_duplicate_conflict\n");
921 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
924 ASSERT_EQ(1,g_hash_table_size(fragment_table));
925 ASSERT_EQ(NULL,fd_head);
927 /* Add the 2nd segment */
929 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
932 /* we haven't got all the fragments yet ... */
933 ASSERT_EQ(1,g_hash_table_size(fragment_table));
934 ASSERT_EQ(NULL,fd_head);
936 /* Now, add the 2nd segment again (but in a different frame and with
940 fd_head=fragment_add_seq(tvb, 15, &pinfo, 12, fragment_table,
943 /* This duplicate fragment should have been ignored */
944 ASSERT_EQ(1,g_hash_table_size(fragment_table));
945 ASSERT_EQ(NULL,fd_head);
947 /* finally, add the last fragment */
949 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
952 ASSERT_EQ(1,g_hash_table_size(fragment_table));
953 ASSERT_NE(NULL,fd_head);
955 /* check the contents of the structure */
956 ASSERT_EQ(0,fd_head->frame); /* unused */
957 ASSERT_EQ(0,fd_head->offset); /* unused */
958 ASSERT_EQ(150,fd_head->len); /* the length of data we have */
959 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
960 ASSERT_EQ(4,fd_head->reassembled_in);
961 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP|FD_OVERLAPCONFLICT,fd_head->flags);
962 ASSERT_NE(NULL,fd_head->data);
963 ASSERT_NE(NULL,fd_head->next);
965 ASSERT_EQ(1,fd_head->next->frame);
966 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
967 ASSERT_EQ(50,fd_head->next->len); /* segment length */
968 ASSERT_EQ(0,fd_head->next->flags);
969 ASSERT_EQ(NULL,fd_head->next->data);
970 ASSERT_NE(NULL,fd_head->next->next);
972 ASSERT_EQ(2,fd_head->next->next->frame);
973 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
974 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
975 ASSERT_EQ(0,fd_head->next->next->flags);
976 ASSERT_EQ(NULL,fd_head->next->next->data);
977 ASSERT_NE(NULL,fd_head->next->next->next);
979 ASSERT_EQ(3,fd_head->next->next->next->frame);
980 ASSERT_EQ(1,fd_head->next->next->next->offset); /* seqno */
981 ASSERT_EQ(60,fd_head->next->next->next->len); /* segment length */
982 ASSERT_EQ(FD_OVERLAP|FD_OVERLAPCONFLICT,fd_head->next->next->next->flags);
983 ASSERT_EQ(NULL,fd_head->next->next->next->data);
984 ASSERT_NE(NULL,fd_head->next->next->next->next);
986 ASSERT_EQ(4,fd_head->next->next->next->next->frame);
987 ASSERT_EQ(2,fd_head->next->next->next->next->offset); /* seqno */
988 ASSERT_EQ(40,fd_head->next->next->next->next->len); /* segment length */
989 ASSERT_EQ(0,fd_head->next->next->next->next->flags);
990 ASSERT_EQ(NULL,fd_head->next->next->next->next->data);
991 ASSERT_EQ(NULL,fd_head->next->next->next->next->next);
993 /* test the actual reassembly */
994 ASSERT(!memcmp(fd_head->data,data+10,50));
995 ASSERT(!memcmp(fd_head->data+50,data+5,60));
996 ASSERT(!memcmp(fd_head->data+110,data+5,40));
999 print_fragment_table();
1003 /**********************************************************************************
1005 * fragment_add_dcerpc_dg
1007 *********************************************************************************/
1009 /* This can afford to be reasonably minimal, as it's just the same logic with a
1010 * different hash key to fragment_add_seq
1013 test_fragment_add_dcerpc_dg(void)
1015 e_uuid_t act_id = {1,2,3,{4,5,6,7,8,9,10,11}};
1017 fragment_data *fd_head, *fdh0;
1018 GHashTable *fragment_table = NULL;
1020 printf("Starting test test_fragment_add_dcerpc_dg\n");
1022 /* we need our own fragment table */
1023 dcerpc_fragment_table_init(&fragment_table);
1024 fd_head=fragment_add_dcerpc_dg(tvb, 10, &pinfo, 12, &act_id, fragment_table,
1027 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1028 ASSERT_EQ(NULL,fd_head);
1030 /* start another pdu (just to confuse things) */
1032 fd_head=fragment_add_dcerpc_dg(tvb, 15, &pinfo, 13, &act_id, fragment_table,
1034 ASSERT_EQ(2,g_hash_table_size(fragment_table));
1035 ASSERT_EQ(NULL,fd_head);
1037 /* another pdu, with the same fragment_id, but a different act_id, to the
1041 fd_head=fragment_add_dcerpc_dg(tvb, 15, &pinfo, 12, &act_id, fragment_table,
1043 ASSERT_EQ(3,g_hash_table_size(fragment_table));
1044 ASSERT_EQ(NULL,fd_head);
1047 /* now we add the terminal fragment of the first datagram */
1049 fd_head=fragment_add_dcerpc_dg(tvb, 5, &pinfo, 12, &act_id, fragment_table,
1052 ASSERT_EQ(3,g_hash_table_size(fragment_table));
1053 ASSERT_NE(NULL,fd_head);
1055 /* check the contents of the structure */
1056 ASSERT_EQ(0,fd_head->frame); /* unused */
1057 ASSERT_EQ(0,fd_head->offset); /* unused */
1058 ASSERT_EQ(110,fd_head->len); /* the length of data we have */
1059 ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */
1060 ASSERT_EQ(4,fd_head->reassembled_in);
1061 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
1062 ASSERT_NE(NULL,fd_head->data);
1063 ASSERT_NE(NULL,fd_head->next);
1065 /* test the actual reassembly */
1066 ASSERT(!memcmp(fd_head->data,data+10,50));
1067 ASSERT(!memcmp(fd_head->data+50,data+5,60));
1069 /* what happens if we revisit the packets now? */
1071 pinfo.fd->flags.visited = 1;
1073 fd_head=fragment_add_dcerpc_dg(tvb, 10, &pinfo, 12, &act_id, fragment_table,
1076 * this api relies on the caller to check fd_head -> reassembled_in
1078 * Redoing all the tests seems like overkill - just check the pointer
1080 ASSERT_EQ(fdh0,fd_head);
1083 /**********************************************************************************
1085 * fragment_add_seq_check
1087 *********************************************************************************/
1090 /* This routine is used for both fragment_add_seq_802_11 and
1091 * fragment_add_seq_check.
1093 * Adds a couple of out-of-order fragments and checks their reassembly.
1096 /* visit id frame frag len more tvb_offset
1105 test_fragment_add_seq_check_work(fragment_data *(*fn)(tvbuff_t *, const int,
1106 const packet_info *, const guint32, GHashTable *,
1107 GHashTable *, const guint32, const guint32, const gboolean))
1109 fragment_data *fd_head;
1111 pinfo.fd -> num = 1;
1112 fd_head=fn(tvb, 10, &pinfo, 12, fragment_table,
1113 reassembled_table, 0, 50, TRUE);
1115 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1116 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1117 ASSERT_EQ(NULL,fd_head);
1119 /* start another pdu (just to confuse things) */
1121 fd_head=fn(tvb, 15, &pinfo, 13, fragment_table,
1122 reassembled_table, 0, 60, TRUE);
1123 ASSERT_EQ(2,g_hash_table_size(fragment_table));
1124 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1125 ASSERT_EQ(NULL,fd_head);
1127 /* add the terminal fragment of the first datagram */
1129 fd_head=fn(tvb, 5, &pinfo, 12, fragment_table,
1130 reassembled_table, 2, 60, FALSE);
1132 /* we haven't got all the fragments yet ... */
1133 ASSERT_EQ(2,g_hash_table_size(fragment_table));
1134 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1135 ASSERT_EQ(NULL,fd_head);
1137 /* finally, add the missing fragment */
1139 fd_head=fn(tvb, 15, &pinfo, 12, fragment_table,
1140 reassembled_table, 1, 60, TRUE);
1142 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1143 ASSERT_EQ(3,g_hash_table_size(reassembled_table));
1144 ASSERT_NE(NULL,fd_head);
1146 /* check the contents of the structure */
1147 ASSERT_EQ(0,fd_head->frame); /* unused */
1148 ASSERT_EQ(0,fd_head->offset); /* unused */
1149 ASSERT_EQ(170,fd_head->len); /* the length of data we have */
1150 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
1151 ASSERT_EQ(4,fd_head->reassembled_in);
1152 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
1153 ASSERT_NE(NULL,fd_head->data);
1154 ASSERT_NE(NULL,fd_head->next);
1156 ASSERT_EQ(1,fd_head->next->frame);
1157 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
1158 ASSERT_EQ(50,fd_head->next->len); /* segment length */
1159 ASSERT_EQ(0,fd_head->next->flags);
1160 ASSERT_EQ(NULL,fd_head->next->data);
1161 ASSERT_NE(NULL,fd_head->next->next);
1163 ASSERT_EQ(4,fd_head->next->next->frame);
1164 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
1165 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
1166 ASSERT_EQ(0,fd_head->next->next->flags);
1167 ASSERT_EQ(NULL,fd_head->next->next->data);
1168 ASSERT_NE(NULL,fd_head->next->next->next);
1170 ASSERT_EQ(3,fd_head->next->next->next->frame);
1171 ASSERT_EQ(2,fd_head->next->next->next->offset); /* seqno */
1172 ASSERT_EQ(60,fd_head->next->next->next->len); /* segment length */
1173 ASSERT_EQ(0,fd_head->next->next->next->flags);
1174 ASSERT_EQ(NULL,fd_head->next->next->next->data);
1175 ASSERT_EQ(NULL,fd_head->next->next->next->next);
1177 /* test the actual reassembly */
1178 ASSERT(!memcmp(fd_head->data,data+10,50));
1179 ASSERT(!memcmp(fd_head->data+50,data+15,60));
1180 ASSERT(!memcmp(fd_head->data+110,data+5,60));
1187 /* Simple test case for fragment_add_seq_check
1190 test_fragment_add_seq_check(void)
1192 printf("Starting test test_fragment_add_seq_check\n");
1194 test_fragment_add_seq_check_work(fragment_add_seq_check);
1198 /* This tests the case that the 802.11 hack does something different for: when
1199 * the terminal segment in a fragmented datagram arrives first.
1202 test_fragment_add_seq_check_1(void)
1204 fragment_data *fd_head;
1206 printf("Starting test test_fragment_add_seq_check_1\n");
1209 fd_head=fragment_add_seq_check(tvb, 10, &pinfo, 12, fragment_table,
1210 reassembled_table, 1, 50, FALSE);
1212 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1213 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1214 ASSERT_EQ(NULL,fd_head);
1216 /* Now add the missing segment */
1218 fd_head=fragment_add_seq_check(tvb, 5, &pinfo, 12, fragment_table,
1219 reassembled_table, 0, 60, TRUE);
1221 ASSERT_EQ(0,g_hash_table_size(fragment_table));
1222 ASSERT_EQ(2,g_hash_table_size(reassembled_table));
1223 ASSERT_NE(NULL,fd_head);
1225 /* check the contents of the structure */
1226 ASSERT_EQ(0,fd_head->frame); /* unused */
1227 ASSERT_EQ(0,fd_head->offset); /* unused */
1228 ASSERT_EQ(110,fd_head->len); /* the length of data we have */
1229 ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */
1230 ASSERT_EQ(2,fd_head->reassembled_in);
1231 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
1232 ASSERT_NE(NULL,fd_head->data);
1233 ASSERT_NE(NULL,fd_head->next);
1235 ASSERT_EQ(2,fd_head->next->frame);
1236 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
1237 ASSERT_EQ(60,fd_head->next->len); /* segment length */
1238 ASSERT_EQ(0,fd_head->next->flags);
1239 ASSERT_EQ(NULL,fd_head->next->data);
1240 ASSERT_NE(NULL,fd_head->next->next);
1242 ASSERT_EQ(1,fd_head->next->next->frame);
1243 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
1244 ASSERT_EQ(50,fd_head->next->next->len); /* segment length */
1245 ASSERT_EQ(0,fd_head->next->next->flags);
1246 ASSERT_EQ(NULL,fd_head->next->next->data);
1247 ASSERT_EQ(NULL,fd_head->next->next->next);
1249 /* test the actual reassembly */
1250 ASSERT(!memcmp(fd_head->data,data+5,60));
1251 ASSERT(!memcmp(fd_head->data+60,data+10,50));
1254 /**********************************************************************************
1256 * fragment_add_seq_802_11
1258 *********************************************************************************/
1260 /* Tests the 802.11 hack.
1263 test_fragment_add_seq_802_11_0(void)
1265 fragment_data *fd_head;
1267 printf("Starting test test_fragment_add_seq_802_11_0\n");
1269 /* the 802.11 hack is that some non-fragmented datagrams have non-zero
1270 * fragment_number; test for this. */
1273 fd_head=fragment_add_seq_802_11(tvb, 10, &pinfo, 12, fragment_table,
1274 reassembled_table, 10, 50, FALSE);
1276 ASSERT_EQ(0,g_hash_table_size(fragment_table));
1277 ASSERT_EQ(1,g_hash_table_size(reassembled_table));
1278 ASSERT_NE(NULL,fd_head);
1280 /* check the contents of the structure */
1281 ASSERT_EQ(0,fd_head->frame); /* unused */
1282 ASSERT_EQ(0,fd_head->offset); /* unused */
1283 ASSERT_EQ(0,fd_head->len); /* unused */
1284 ASSERT_EQ(0,fd_head->datalen); /* unused */
1285 ASSERT_EQ(1,fd_head->reassembled_in);
1286 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE,fd_head->flags);
1287 ASSERT_EQ(NULL,fd_head->data);
1288 ASSERT_EQ(NULL,fd_head->next);
1291 /* Reuse the fragment_add_seq_check testcases */
1292 static void test_fragment_add_seq_802_11_1(void)
1294 printf("Starting test test_fragment_add_seq_802_11_1\n");
1295 test_fragment_add_seq_check_work(fragment_add_seq_802_11);
1298 /**********************************************************************************
1300 * fragment_add_seq_check_multiple
1302 *********************************************************************************/
1304 /* Test 2 partial frags from 2 diff datagrams in the same frame */
1306 datagram #1: frame 1 + first part of frame 2
1307 datagram #1: last part of frame 2 + frame 3
1309 Is this a valid scenario ?
1311 The result of calling fragment_add_seq_check() for these
1312 fragments is a reassembled_table with:
1313 id, frame 1 => first_datagram; ["reassembled in" frame 2]
1314 id, frame 2 => second_datagram; ["reassembled in" frame 3]
1315 id, frame 3 => second_datagram;
1317 Note that the id, frame 2 => first datagram was overwritten
1318 by the entry for the second datagram.
1319 Is this OK ? IE: When dissected/displayed
1320 will the reassembled datagram 1 appear with frame 2 ??
1323 /* visit id frame frag len more tvb_offset
1331 Is this a valid scenario ?
1332 Is this OK ? IE: When dissected/displayed:
1333 Will the reassembled datagram 1 appear with frame 2 ??
1337 test_fragment_add_seq_check_multiple(void) {
1338 fragment_data *fd_head;
1340 pinfo.fd -> num = 1;
1341 fd_head=fragment_add_seq_check(tvb, 10, &pinfo, 12, fragment_table,
1342 reassembled_table, 0, 50, TRUE);
1344 /* add the terminal fragment of the first datagram */
1346 fd_head=fragment_add_seq_check(tvb, 5, &pinfo, 12, fragment_table,
1347 reassembled_table, 1, 20, FALSE);
1351 /* Now: start a second datagram with the first fragment in frame #2 */
1353 fd_head=fragment_add_seq_check(tvb, 25, &pinfo, 12, fragment_table,
1354 reassembled_table, 0, 25, TRUE);
1356 /* add the terminal fragment of the second datagram */
1358 fd_head=fragment_add_seq_check(tvb, 0, &pinfo, 12, fragment_table,
1359 reassembled_table, 1, 60, FALSE);
1365 /**********************************************************************************
1367 * fragment_add_seq_next
1369 *********************************************************************************/
1371 /* Simple test case for fragment_add_seq_next.
1372 * Adds a couple of fragments (with one for a different datagram in between),
1373 * and checks that they are reassembled correctly.
1376 test_simple_fragment_add_seq_next(void)
1378 fragment_data *fd_head;
1380 printf("Starting test test_simple_fragment_add_seq_next\n");
1383 fd_head= fragment_add_seq_next(tvb, 10, &pinfo, 12, fragment_table,
1384 reassembled_table, 50, TRUE);
1386 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1387 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1388 ASSERT_EQ(NULL,fd_head);
1390 /* adding the same fragment again should do nothing, even with different
1392 pinfo.fd->flags.visited = 1;
1393 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
1394 reassembled_table, 60, TRUE);
1395 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1396 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1397 ASSERT_EQ(NULL,fd_head);
1399 /* start another pdu (just to confuse things) */
1400 pinfo.fd->flags.visited = 0;
1402 fd_head=fragment_add_seq_next(tvb, 15, &pinfo, 13, fragment_table,
1403 reassembled_table, 60, TRUE);
1404 ASSERT_EQ(2,g_hash_table_size(fragment_table));
1405 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1406 ASSERT_EQ(NULL,fd_head);
1409 /* now we add the terminal fragment of the first datagram */
1411 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
1412 reassembled_table, 60, FALSE);
1414 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1415 ASSERT_EQ(2,g_hash_table_size(reassembled_table));
1416 ASSERT_NE(NULL,fd_head);
1418 /* check the contents of the structure */
1419 ASSERT_EQ(0,fd_head->frame); /* unused */
1420 ASSERT_EQ(0,fd_head->offset); /* unused */
1421 ASSERT_EQ(110,fd_head->len); /* the length of data we have */
1422 ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */
1423 ASSERT_EQ(3,fd_head->reassembled_in);
1424 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
1425 ASSERT_NE(NULL,fd_head->data);
1426 ASSERT_NE(NULL,fd_head->next);
1428 ASSERT_EQ(1,fd_head->next->frame);
1429 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
1430 ASSERT_EQ(50,fd_head->next->len); /* segment length */
1431 ASSERT_EQ(0,fd_head->next->flags);
1432 ASSERT_EQ(NULL,fd_head->next->data);
1433 ASSERT_NE(NULL,fd_head->next->next);
1435 ASSERT_EQ(3,fd_head->next->next->frame);
1436 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
1437 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
1438 ASSERT_EQ(0,fd_head->next->next->flags);
1439 ASSERT_EQ(NULL,fd_head->next->next->data);
1440 ASSERT_EQ(NULL,fd_head->next->next->next);
1442 /* test the actual reassembly */
1443 ASSERT(!memcmp(fd_head->data,data+10,50));
1444 ASSERT(!memcmp(fd_head->data+50,data+5,60));
1448 /* This tests the case where some data is missing from one of the fragments.
1449 * It should prevent reassembly.
1452 test_missing_data_fragment_add_seq_next(void)
1454 fragment_data *fd_head;
1456 printf("Starting test test_missing_data_fragment_add_seq_next\n");
1458 /* attempt to add a fragment which is longer than the data available */
1460 fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 12, fragment_table,
1461 reassembled_table, DATA_LEN-9, TRUE);
1463 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1464 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1465 ASSERT_NE(NULL,fd_head);
1467 /* check the contents of the structure. Reassembly failed so everything
1468 * should be null (meaning, just use the original tvb) */
1469 ASSERT_EQ(0,fd_head->frame); /* unused */
1470 ASSERT_EQ(0,fd_head->offset); /* unused */
1471 ASSERT_EQ(0,fd_head->len); /* the length of data we have */
1472 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
1473 ASSERT_EQ(0,fd_head->reassembled_in);
1474 ASSERT_EQ(FD_BLOCKSEQUENCE,fd_head->flags & 0x1ff);
1475 ASSERT_EQ(NULL,fd_head->data);
1476 ASSERT_EQ(NULL,fd_head->next);
1478 /* add another fragment (with all data present) */
1480 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
1481 reassembled_table, 60, FALSE);
1483 /* XXX: it's not clear that this is the right result; however it's what the
1486 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1487 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1488 ASSERT_EQ(NULL,fd_head);
1491 /* check what happens when we revisit the packets */
1492 pinfo.fd->flags.visited = TRUE;
1495 fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 12, fragment_table,
1496 reassembled_table, DATA_LEN-9, TRUE);
1498 /* We just look in the reassembled_table for this packet. It never got put
1499 * there, so this always returns null.
1501 * That's crazy, because it means that the subdissector will see the data
1502 * exactly once - on the first pass through the capture (well, assuming it
1503 * doesn't bother to check fd_head->reassembled_in); however, that's
1504 * what the code does...
1506 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1507 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1508 ASSERT_EQ(NULL,fd_head);
1511 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
1512 reassembled_table, 60, FALSE);
1513 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1514 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1515 ASSERT_EQ(NULL,fd_head);
1520 * we're going to do something similar now, but this time it is the second
1521 * fragment which has something missing.
1524 test_missing_data_fragment_add_seq_next_2(void)
1526 fragment_data *fd_head;
1528 printf("Starting test test_missing_data_fragment_add_seq_next_2\n");
1531 fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 24, fragment_table,
1532 reassembled_table, 50, TRUE);
1534 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1535 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1536 ASSERT_EQ(NULL,fd_head);
1539 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 24, fragment_table,
1540 reassembled_table, DATA_LEN-4, FALSE);
1542 /* XXX: again, i'm really dubious about this. Surely this should return all
1543 * the data we had, for a best-effort attempt at dissecting it?
1544 * And it ought to go into the reassembled table?
1546 ASSERT_EQ(0,g_hash_table_size(fragment_table));
1547 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1548 ASSERT_EQ(NULL,fd_head);
1550 /* check what happens when we revisit the packets */
1551 pinfo.fd->flags.visited = TRUE;
1554 fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 24, fragment_table,
1555 reassembled_table, 50, TRUE);
1557 /* As before, this returns NULL because the fragment isn't in the
1558 * reassembled_table. At least this is a bit more consistent than before.
1560 ASSERT_EQ(0,g_hash_table_size(fragment_table));
1561 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1562 ASSERT_EQ(NULL,fd_head);
1565 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 24, fragment_table,
1566 reassembled_table, DATA_LEN-4, FALSE);
1567 ASSERT_EQ(0,g_hash_table_size(fragment_table));
1568 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1569 ASSERT_EQ(NULL,fd_head);
1574 * This time, our datagram only has one segment, but it has data missing.
1577 test_missing_data_fragment_add_seq_next_3(void)
1579 fragment_data *fd_head;
1581 printf("Starting test test_missing_data_fragment_add_seq_next_3\n");
1584 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 30, fragment_table,
1585 reassembled_table, DATA_LEN-4, FALSE);
1587 ASSERT_EQ(0,g_hash_table_size(fragment_table));
1588 ASSERT_EQ(1,g_hash_table_size(reassembled_table));
1589 ASSERT_NE(NULL,fd_head);
1591 /* check the contents of the structure. */
1592 ASSERT_EQ(0,fd_head->frame); /* unused */
1593 ASSERT_EQ(0,fd_head->offset); /* unused */
1594 ASSERT_EQ(0,fd_head->len); /* the length of data we have */
1595 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
1596 ASSERT_EQ(20,fd_head->reassembled_in);
1597 ASSERT_EQ(FD_BLOCKSEQUENCE|FD_DEFRAGMENTED,fd_head->flags);
1598 ASSERT_EQ(NULL,fd_head->data);
1599 ASSERT_EQ(NULL,fd_head->next);
1601 /* revisiting the packet ought to produce the same result. */
1602 pinfo.fd->flags.visited = TRUE;
1605 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 30, fragment_table,
1606 reassembled_table, DATA_LEN-4, FALSE);
1608 ASSERT_EQ(0,g_hash_table_size(fragment_table));
1609 ASSERT_EQ(1,g_hash_table_size(reassembled_table));
1610 ASSERT_NE(NULL,fd_head);
1611 ASSERT_EQ(0,fd_head->frame); /* unused */
1612 ASSERT_EQ(0,fd_head->offset); /* unused */
1613 ASSERT_EQ(0,fd_head->len); /* the length of data we have */
1614 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
1615 ASSERT_EQ(20,fd_head->reassembled_in);
1616 ASSERT_EQ(FD_BLOCKSEQUENCE|FD_DEFRAGMENTED,fd_head->flags);
1617 ASSERT_EQ(NULL,fd_head->data);
1618 ASSERT_EQ(NULL,fd_head->next);
1622 /**********************************************************************************
1626 *********************************************************************************/
1629 main(int argc _U_, char **argv _U_)
1632 char src[] = {1,2,3,4}, dst[] = {5,6,7,8};
1634 void (*tests[])(void) = {
1635 test_simple_fragment_add_seq, /* frag table only */
1636 test_fragment_add_seq_partial_reassembly,
1637 test_fragment_add_seq_duplicate_first,
1638 test_fragment_add_seq_duplicate_middle,
1639 test_fragment_add_seq_duplicate_last,
1640 test_fragment_add_seq_duplicate_conflict,
1641 test_fragment_add_dcerpc_dg,
1642 test_fragment_add_seq_check, /* frag + reassemble */
1643 test_fragment_add_seq_check_1,
1644 test_fragment_add_seq_802_11_0,
1645 test_fragment_add_seq_802_11_1,
1646 test_simple_fragment_add_seq_next,
1647 test_missing_data_fragment_add_seq_next,
1648 test_missing_data_fragment_add_seq_next_2,
1649 test_missing_data_fragment_add_seq_next_3,
1651 test_fragment_add_seq_check_multiple
1655 /* initialise stuff */
1658 /* a tvbuff for testing with */
1659 data = g_malloc(DATA_LEN);
1660 /* make sure it's full of stuff */
1661 for(i=0; i<DATA_LEN; i++) {
1664 tvb = tvb_new_real_data(data, DATA_LEN, DATA_LEN*2);
1666 /* other test stuff */
1668 fd.flags.visited = 0;
1669 SET_ADDRESS(&pinfo.src,AT_IPv4,4,src);
1670 SET_ADDRESS(&pinfo.dst,AT_IPv4,4,dst);
1672 /*************************************************************************/
1673 for(i=0; i < sizeof(tests)/sizeof(tests[0]); i++ ) {
1674 /* re-init the fragment tables */
1675 fragment_table_init(&fragment_table);
1676 ASSERT(fragment_table != NULL);
1678 reassembled_table_init(&reassembled_table);
1679 ASSERT(reassembled_table != NULL);
1681 pinfo.fd->flags.visited = FALSE;
1685 /* Free memory used by the tables */
1686 fragment_table_init(&fragment_table);
1687 g_hash_table_destroy(fragment_table);
1688 fragment_table = NULL;
1690 reassembled_table_init(&reassembled_table);
1691 g_hash_table_destroy(reassembled_table);
1692 reassembled_table = NULL;
1700 printf(failure?"FAILURE\n":"SUCCESS\n");