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.
63 #include <epan/emem.h>
64 #include <epan/packet.h>
65 #include <epan/packet_info.h>
66 #include <epan/proto.h>
67 #include <epan/tvbuff.h>
68 #include <epan/reassemble.h>
70 #include <epan/dissectors/packet-dcerpc.h>
72 #define ASSERT(b) do_test((b),"Assertion failed at line %i: %s\n", __LINE__, #b)
73 #define ASSERT_EQ(exp,act) do_test((exp)==(act),"Assertion failed at line %i: %s==%s (%i==%i)\n", __LINE__, #exp, #act, exp, act)
74 #define ASSERT_NE(exp,act) do_test((exp)!=(act),"Assertion failed at line %i: %s!=%s (%i!=%i)\n", __LINE__, #exp, #act, exp, act)
76 static int failure = 0;
79 do_test(gboolean condition, const char *format, ...)
87 vfprintf(stderr, format, ap);
91 /* many of the tests assume this routine doesn't return on failure; if we
92 * do, it may provide more information, but may cause a segfault. Uncomment
93 * this line if you wish.
101 static tvbuff_t *tvb;
102 static packet_info pinfo;
104 /* fragment_table maps from datagram ids to head of fragment_data list
105 reassembled_table maps from <packet number,datagram id> to head of
106 fragment_data list */
107 static GHashTable *fragment_table = NULL;
108 static GHashTable *reassembled_table = NULL;
111 /*************************************************
112 * Util fcns to display
113 * fragment_table & reassembled_table fd-chains
114 ************************************************/
116 /* Must match the typedef in reassemble.c */
117 typedef struct _fragment_key {
123 /* Must match the typedef in reassemble.c */
124 typedef struct _reassembled_key {
129 static struct _fd_flags {
133 {FD_DEFRAGMENTED ,"DF"},
134 {FD_DATALEN_SET ,"DS"},
135 {FD_NOT_MALLOCED ,"NM"},
136 {FD_BLOCKSEQUENCE ,"BS"},
137 {FD_DATA_NOT_PRESENT ,"NP"},
138 {FD_PARTIAL_REASSEMBLY ,"PR"},
140 {FD_OVERLAPCONFLICT ,"OC"},
141 {FD_MULTIPLETAILS ,"MT"},
142 {FD_TOOLONGFRAGMENT ,"TL"},
144 #define N_FD_FLAGS (signed)(sizeof(fd_flags)/sizeof(struct _fd_flags))
147 print_fd(fragment_data *fd, gboolean is_head) {
150 g_assert(fd != NULL);
151 printf(" %08x %08x %3d %3d %3d", fd, fd->next, fd->frame, fd->offset, fd->len);
153 printf(" %3d %3d", fd->datalen, fd->reassembled_in);
157 printf(" 0x%08x", fd->data);
158 for (i=0; i<N_FD_FLAGS; i++) {
159 printf(" %s", (fd->flags & fd_flags[i].flag) ? fd_flags[i].flag_name : " ");
165 print_fd_chain(fragment_data *fd_head) {
168 g_assert(fd_head != NULL);
169 print_fd(fd_head, TRUE);
170 for (fdp=fd_head->next; fdp != NULL; fdp=fdp->next) {
171 print_fd(fdp, FALSE);
176 print_fragment_table_chain(gpointer k, gpointer v, gpointer ud) {
177 fragment_key *key = (fragment_key*)k;
178 fragment_data *fd_head = (fragment_data *)v;
179 printf(" --> FT: %3d 0x%08x 0x%08x\n", key->id, *(guint32 *)(key->src.data), *(guint32 *)(key->dst.data));
180 print_fd_chain(fd_head);
184 print_fragment_table(void) {
185 printf("\n Fragment Table -------\n");
186 g_hash_table_foreach(fragment_table, print_fragment_table_chain, NULL);
190 print_reassembled_table_chain(gpointer k, gpointer v, gpointer ud) {
191 reassembled_key *key = (reassembled_key*)k;
192 fragment_data *fd_head = (fragment_data *)v;
193 printf(" --> RT: %5d %5d\n", key->id, key->frame);
194 print_fd_chain(fd_head);
198 print_reassembled_table(void) {
199 printf("\n Reassembled Table ----\n");
200 g_hash_table_foreach(reassembled_table, print_reassembled_table_chain, NULL);
205 print_fragment_table();
206 print_reassembled_table();
210 /**********************************************************************************
214 *********************************************************************************/
216 /* Simple test case for fragment_add_seq.
217 * Adds three fragments (out of order, with one for a different datagram in between),
218 * and checks that they are reassembled correctly.
220 /* visit id frame frag len more tvb_offset
228 test_simple_fragment_add_seq(void)
230 fragment_data *fd_head, *fdh0;
232 printf("Starting test test_simple_fragment_add_seq\n");
235 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
238 ASSERT_EQ(1,g_hash_table_size(fragment_table));
239 ASSERT_EQ(NULL,fd_head);
241 /* adding the same fragment again should do nothing, even with different
243 pinfo.fd->flags.visited = 1;
244 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
246 ASSERT_EQ(1,g_hash_table_size(fragment_table));
247 ASSERT_EQ(NULL,fd_head);
249 /* start another pdu (just to confuse things) */
250 pinfo.fd->flags.visited = 0;
252 fd_head=fragment_add_seq(tvb, 15, &pinfo, 13, fragment_table,
254 ASSERT_EQ(2,g_hash_table_size(fragment_table));
255 ASSERT_EQ(NULL,fd_head);
257 /* now we add the terminal fragment of the first datagram */
259 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
262 /* we haven't got all the fragments yet ... */
263 ASSERT_EQ(2,g_hash_table_size(fragment_table));
264 ASSERT_EQ(NULL,fd_head);
266 /* finally, add the missing fragment */
268 fd_head=fragment_add_seq(tvb, 15, &pinfo, 12, fragment_table,
271 ASSERT_EQ(2,g_hash_table_size(fragment_table));
272 ASSERT_NE(NULL,fd_head);
274 /* check the contents of the structure */
275 ASSERT_EQ(0,fd_head->frame); /* unused */
276 ASSERT_EQ(0,fd_head->offset); /* unused */
277 ASSERT_EQ(170,fd_head->len); /* the length of data we have */
278 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
279 ASSERT_EQ(4,fd_head->reassembled_in);
280 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
281 ASSERT_NE(NULL,fd_head->data);
282 ASSERT_NE(NULL,fd_head->next);
284 ASSERT_EQ(1,fd_head->next->frame);
285 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
286 ASSERT_EQ(50,fd_head->next->len); /* segment length */
287 ASSERT_EQ(0,fd_head->next->flags);
288 ASSERT_EQ(NULL,fd_head->next->data);
289 ASSERT_NE(NULL,fd_head->next->next);
291 ASSERT_EQ(4,fd_head->next->next->frame);
292 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
293 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
294 ASSERT_EQ(0,fd_head->next->next->flags);
295 ASSERT_EQ(NULL,fd_head->next->next->data);
296 ASSERT_NE(NULL,fd_head->next->next->next);
298 ASSERT_EQ(3,fd_head->next->next->next->frame);
299 ASSERT_EQ(2,fd_head->next->next->next->offset); /* seqno */
300 ASSERT_EQ(60,fd_head->next->next->next->len); /* segment length */
301 ASSERT_EQ(0,fd_head->next->next->next->flags);
302 ASSERT_EQ(NULL,fd_head->next->next->next->data);
303 ASSERT_EQ(NULL,fd_head->next->next->next->next);
305 /* test the actual reassembly */
306 ASSERT(!memcmp(fd_head->data,data+10,50));
307 ASSERT(!memcmp(fd_head->data+50,data+15,60));
308 ASSERT(!memcmp(fd_head->data+110,data+5,60));
311 print_fragment_table();
314 /* what happens if we revisit the packets now? */
316 pinfo.fd->flags.visited = 1;
318 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
321 * this api relies on the caller to check fd_head -> reassembled_in
323 * Redoing all the tests seems like overkill - just check the pointer
325 ASSERT_EQ(fdh0,fd_head);
328 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
330 ASSERT_EQ(fdh0,fd_head);
333 fd_head=fragment_add_seq(tvb, 15, &pinfo, 12, fragment_table,
335 ASSERT_EQ(fdh0,fd_head);
338 print_fragment_table();
342 /* XXX ought to have some tests for overlapping fragments */
344 /* This tests the functionality of fragment_set_partial_reassembly for
345 * FD_BLOCKSEQUENCE reassembly.
347 * We add a sequence of fragments thus:
348 * seqno frame offset len (initial) more_frags
349 * ----- ----- ------ --- --------------------
352 * 1 3 0 40 true (a duplicate fragment)
357 test_fragment_add_seq_partial_reassembly(void)
359 fragment_data *fd_head, *fd;
361 printf("Starting test test_fragment_add_seq_partial_reassembly\n");
363 /* generally it's probably fair to assume that we will be called with
367 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
370 ASSERT_EQ(1,g_hash_table_size(fragment_table));
371 ASSERT_NE(NULL,fd_head);
373 /* check the contents of the structure */
374 ASSERT_EQ(0,fd_head->frame); /* unused */
375 ASSERT_EQ(0,fd_head->offset); /* unused */
376 ASSERT_EQ(50,fd_head->len); /* the length of data we have */
377 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
378 ASSERT_EQ(1,fd_head->reassembled_in);
379 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
380 ASSERT_NE(NULL,fd_head->data);
381 ASSERT_NE(NULL,fd_head->next);
383 ASSERT_EQ(1,fd_head->next->frame);
384 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
385 ASSERT_EQ(50,fd_head->next->len); /* segment length */
386 ASSERT_EQ(0,fd_head->next->flags);
387 ASSERT_EQ(NULL,fd_head->next->data);
388 ASSERT_EQ(NULL,fd_head->next->next);
390 /* test the actual reassembly */
391 ASSERT(!memcmp(fd_head->data,data+10,50));
393 /* now we announce that the reassembly wasn't complete after all. */
394 fragment_set_partial_reassembly(&pinfo,12,fragment_table);
396 /* and add another segment. To mix things up slightly (and so that we can
397 * check on the state of things), we're going to set the more_frags flag
401 fd_head=fragment_add_seq(tvb, 0, &pinfo, 12, fragment_table,
404 ASSERT_EQ(1,g_hash_table_size(fragment_table));
405 ASSERT_EQ(NULL,fd_head);
407 fd_head=fragment_get(&pinfo,12,fragment_table);
408 ASSERT_NE(NULL,fd_head);
410 /* check the contents of the structure */
411 ASSERT_EQ(0,fd_head->frame); /* unused */
412 ASSERT_EQ(0,fd_head->offset); /* unused */
413 /* ASSERT_EQ(50,fd_head->len); the length of data we have */
414 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
415 ASSERT_EQ(0,fd_head->reassembled_in);
416 ASSERT_EQ(FD_BLOCKSEQUENCE,fd_head->flags);
417 ASSERT_NE(NULL,fd_head->data);
418 ASSERT_NE(NULL,fd_head->next);
421 ASSERT_EQ(1,fd->frame);
422 ASSERT_EQ(0,fd->offset); /* seqno */
423 ASSERT_EQ(50,fd->len); /* segment length */
424 ASSERT_EQ(FD_NOT_MALLOCED,fd->flags);
425 ASSERT_EQ(fd_head->data,fd->data);
426 ASSERT_NE(NULL,fd->next);
429 ASSERT_EQ(2,fd->frame);
430 ASSERT_EQ(1,fd->offset); /* seqno */
431 ASSERT_EQ(40,fd->len); /* segment length */
432 ASSERT_EQ(0,fd->flags);
433 ASSERT_NE(NULL,fd->data);
434 ASSERT_EQ(NULL,fd->next);
436 /* Another copy of the second segment.
439 fd_head=fragment_add_seq(tvb, 0, &pinfo, 12, fragment_table,
442 ASSERT_EQ(1,g_hash_table_size(fragment_table));
443 ASSERT_EQ(NULL,fd_head);
444 fd_head=fragment_get(&pinfo,12,fragment_table);
445 ASSERT_NE(NULL,fd_head);
446 ASSERT_EQ(0,fd_head->frame); /* unused */
447 ASSERT_EQ(0,fd_head->offset); /* unused */
448 /* ASSERT_EQ(50,fd_head->len); the length of data we have */
449 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
450 ASSERT_EQ(0,fd_head->reassembled_in);
451 ASSERT_EQ(FD_BLOCKSEQUENCE,fd_head->flags);
452 ASSERT_NE(NULL,fd_head->data);
453 ASSERT_NE(NULL,fd_head->next);
456 ASSERT_EQ(1,fd->frame);
457 ASSERT_EQ(0,fd->offset); /* seqno */
458 ASSERT_EQ(50,fd->len); /* segment length */
459 ASSERT_EQ(FD_NOT_MALLOCED,fd->flags);
460 ASSERT_EQ(fd_head->data,fd->data);
461 ASSERT_NE(NULL,fd->next);
464 ASSERT_EQ(2,fd->frame);
465 ASSERT_EQ(1,fd->offset); /* seqno */
466 ASSERT_EQ(40,fd->len); /* segment length */
467 ASSERT_EQ(0,fd->flags);
468 ASSERT_NE(NULL,fd->data);
469 ASSERT_NE(NULL,fd->next);
472 ASSERT_EQ(3,fd->frame);
473 ASSERT_EQ(1,fd->offset); /* seqno */
474 ASSERT_EQ(40,fd->len); /* segment length */
475 ASSERT_EQ(0,fd->flags);
476 ASSERT_NE(NULL,fd->data);
477 ASSERT_EQ(NULL,fd->next);
481 /* have another go at wrapping things up */
483 fd_head=fragment_add_seq(tvb, 20, &pinfo, 12, fragment_table,
486 ASSERT_EQ(1,g_hash_table_size(fragment_table));
487 ASSERT_NE(NULL,fd_head);
489 /* check the contents of the structure */
490 ASSERT_EQ(0,fd_head->frame); /* unused */
491 ASSERT_EQ(0,fd_head->offset); /* unused */
492 ASSERT_EQ(190,fd_head->len); /* the length of data we have */
493 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
494 ASSERT_EQ(4,fd_head->reassembled_in);
495 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
496 ASSERT_NE(NULL,fd_head->data);
497 ASSERT_NE(NULL,fd_head->next);
500 ASSERT_EQ(1,fd->frame);
501 ASSERT_EQ(0,fd->offset); /* seqno */
502 ASSERT_EQ(50,fd->len); /* segment length */
503 ASSERT_EQ(0,fd->flags);
504 ASSERT_EQ(NULL,fd->data);
505 ASSERT_NE(NULL,fd->next);
508 ASSERT_EQ(2,fd->frame);
509 ASSERT_EQ(1,fd->offset); /* seqno */
510 ASSERT_EQ(40,fd->len); /* segment length */
511 ASSERT_EQ(0,fd->flags);
512 ASSERT_EQ(NULL,fd->data);
513 ASSERT_NE(NULL,fd->next);
516 ASSERT_EQ(3,fd->frame);
517 ASSERT_EQ(1,fd->offset); /* seqno */
518 ASSERT_EQ(40,fd->len); /* segment length */
519 ASSERT_EQ(FD_OVERLAP,fd->flags);
520 ASSERT_EQ(NULL,fd->data);
521 ASSERT_NE(NULL,fd->next);
524 ASSERT_EQ(4,fd->frame);
525 ASSERT_EQ(2,fd->offset); /* seqno */
526 ASSERT_EQ(100,fd->len); /* segment length */
527 ASSERT_EQ(0,fd->flags);
528 ASSERT_EQ(NULL,fd->data);
529 ASSERT_EQ(NULL,fd->next);
531 /* test the actual reassembly */
532 ASSERT(!memcmp(fd_head->data,data+10,50));
533 ASSERT(!memcmp(fd_head->data+50,data,40));
534 ASSERT(!memcmp(fd_head->data+90,data+20,100));
537 /* do it again (this time it is more complicated, with an overlap in the
540 fragment_set_partial_reassembly(&pinfo,12,fragment_table);
543 fd_head=fragment_add_seq(tvb, 0, &pinfo, 12, fragment_table,
546 fd_head=fragment_get(&pinfo,12,fragment_table);
547 ASSERT_NE(NULL,fd_head);
548 ASSERT_EQ(0,fd_head->frame); /* unused */
549 ASSERT_EQ(0,fd_head->offset); /* unused */
550 ASSERT_EQ(230,fd_head->len); /* the length of data we have */
551 ASSERT_EQ(3,fd_head->datalen); /* seqno of the last fragment we have */
552 ASSERT_EQ(5,fd_head->reassembled_in);
553 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
554 ASSERT_NE(NULL,fd_head->data);
555 ASSERT_NE(NULL,fd_head->next);
558 ASSERT_EQ(1,fd->frame);
559 ASSERT_EQ(0,fd->offset); /* seqno */
560 ASSERT_EQ(50,fd->len); /* segment length */
561 ASSERT_EQ(0,fd->flags);
562 ASSERT_EQ(NULL,fd->data);
563 ASSERT_NE(NULL,fd->next);
566 ASSERT_EQ(2,fd->frame);
567 ASSERT_EQ(1,fd->offset); /* seqno */
568 ASSERT_EQ(40,fd->len); /* segment length */
569 ASSERT_EQ(0,fd->flags);
570 ASSERT_EQ(NULL,fd->data);
571 ASSERT_NE(NULL,fd->next);
574 ASSERT_EQ(3,fd->frame);
575 ASSERT_EQ(1,fd->offset); /* seqno */
576 ASSERT_EQ(40,fd->len); /* segment length */
577 ASSERT_EQ(FD_OVERLAP,fd->flags);
578 ASSERT_EQ(NULL,fd->data);
579 ASSERT_NE(NULL,fd->next);
582 ASSERT_EQ(4,fd->frame);
583 ASSERT_EQ(2,fd->offset); /* seqno */
584 ASSERT_EQ(100,fd->len); /* segment length */
585 ASSERT_EQ(0,fd->flags);
586 ASSERT_EQ(NULL,fd->data);
587 ASSERT_NE(NULL,fd->next);
590 ASSERT_EQ(5,fd->frame);
591 ASSERT_EQ(3,fd->offset); /* seqno */
592 ASSERT_EQ(40,fd->len); /* segment length */
593 ASSERT_EQ(0,fd->flags);
594 ASSERT_EQ(NULL,fd->data);
595 ASSERT_EQ(NULL,fd->next);
597 /* test the actual reassembly */
598 ASSERT(!memcmp(fd_head->data,data+10,50));
599 ASSERT(!memcmp(fd_head->data+50,data,40));
600 ASSERT(!memcmp(fd_head->data+90,data+20,100));
601 ASSERT(!memcmp(fd_head->data+190,data,40));
604 /* Test case for fragment_add_seq with duplicated (e.g., retransmitted) data.
605 * Adds three fragments--adding the 1st one twice--
606 * and checks that they are reassembled correctly.
608 /* visit id frame frag len more tvb_offset
615 test_fragment_add_seq_duplicate_first(void)
617 fragment_data *fd_head;
619 printf("Starting test test_fragment_add_seq_duplicate_first\n");
622 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
625 ASSERT_EQ(1,g_hash_table_size(fragment_table));
626 ASSERT_EQ(NULL,fd_head);
628 /* Add the 2nd segment */
630 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
633 /* we haven't got all the fragments yet ... */
634 ASSERT_EQ(1,g_hash_table_size(fragment_table));
635 ASSERT_EQ(NULL,fd_head);
637 /* Add the last fragment */
639 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
642 ASSERT_EQ(1,g_hash_table_size(fragment_table));
643 ASSERT_NE(NULL,fd_head);
645 /* Add the first fragment again */
647 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
650 /* Reassembly should have still succeeded */
651 ASSERT_EQ(1,g_hash_table_size(fragment_table));
652 ASSERT_NE(NULL,fd_head);
654 /* check the contents of the structure */
655 ASSERT_EQ(0,fd_head->frame); /* unused */
656 ASSERT_EQ(0,fd_head->offset); /* unused */
657 ASSERT_EQ(150,fd_head->len); /* the length of data we have */
658 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
659 ASSERT_EQ(3,fd_head->reassembled_in);
660 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
661 ASSERT_NE(NULL,fd_head->data);
662 ASSERT_NE(NULL,fd_head->next);
664 ASSERT_EQ(1,fd_head->next->frame);
665 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
666 ASSERT_EQ(50,fd_head->next->len); /* segment length */
667 ASSERT_EQ(0,fd_head->next->flags);
668 ASSERT_EQ(NULL,fd_head->next->data);
669 ASSERT_NE(NULL,fd_head->next->next);
671 ASSERT_EQ(4,fd_head->next->next->frame);
672 ASSERT_EQ(0,fd_head->next->next->offset); /* seqno */
673 ASSERT_EQ(50,fd_head->next->next->len); /* segment length */
674 ASSERT_EQ(FD_OVERLAP,fd_head->next->next->flags);
675 ASSERT_EQ(NULL,fd_head->next->next->data);
676 ASSERT_NE(NULL,fd_head->next->next->next);
678 ASSERT_EQ(2,fd_head->next->next->next->frame);
679 ASSERT_EQ(1,fd_head->next->next->next->offset); /* seqno */
680 ASSERT_EQ(60,fd_head->next->next->next->len); /* segment length */
681 ASSERT_EQ(0,fd_head->next->next->next->flags);
682 ASSERT_EQ(NULL,fd_head->next->next->next->data);
683 ASSERT_NE(NULL,fd_head->next->next->next->next);
685 ASSERT_EQ(3,fd_head->next->next->next->next->frame);
686 ASSERT_EQ(2,fd_head->next->next->next->next->offset); /* seqno */
687 ASSERT_EQ(40,fd_head->next->next->next->next->len); /* segment length */
688 ASSERT_EQ(0,fd_head->next->next->next->next->flags);
689 ASSERT_EQ(NULL,fd_head->next->next->next->next->data);
690 ASSERT_EQ(NULL,fd_head->next->next->next->next->next);
692 /* test the actual reassembly */
693 ASSERT(!memcmp(fd_head->data,data+10,50));
694 ASSERT(!memcmp(fd_head->data+50,data+5,60));
695 ASSERT(!memcmp(fd_head->data+110,data+5,40));
698 print_fragment_table();
703 /* Test case for fragment_add_seq with duplicated (e.g., retransmitted) data.
704 * Adds three fragments--adding the 2nd one twice--
705 * and checks that they are reassembled correctly.
707 /* visit id frame frag len more tvb_offset
714 test_fragment_add_seq_duplicate_middle(void)
716 fragment_data *fd_head;
718 printf("Starting test test_fragment_add_seq_duplicate_middle\n");
721 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
724 ASSERT_EQ(1,g_hash_table_size(fragment_table));
725 ASSERT_EQ(NULL,fd_head);
727 /* Add the 2nd segment */
729 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
732 /* we haven't got all the fragments yet ... */
733 ASSERT_EQ(1,g_hash_table_size(fragment_table));
734 ASSERT_EQ(NULL,fd_head);
736 /* Now, add the 2nd segment again (but in a different frame) */
738 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
741 /* This duplicate fragment should have been ignored */
742 ASSERT_EQ(1,g_hash_table_size(fragment_table));
743 ASSERT_EQ(NULL,fd_head);
745 /* finally, add the last fragment */
747 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
750 ASSERT_EQ(1,g_hash_table_size(fragment_table));
751 ASSERT_NE(NULL,fd_head);
753 /* check the contents of the structure */
754 ASSERT_EQ(0,fd_head->frame); /* unused */
755 ASSERT_EQ(0,fd_head->offset); /* unused */
756 ASSERT_EQ(150,fd_head->len); /* the length of data we have */
757 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
758 ASSERT_EQ(4,fd_head->reassembled_in);
759 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
760 ASSERT_NE(NULL,fd_head->data);
761 ASSERT_NE(NULL,fd_head->next);
763 ASSERT_EQ(1,fd_head->next->frame);
764 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
765 ASSERT_EQ(50,fd_head->next->len); /* segment length */
766 ASSERT_EQ(0,fd_head->next->flags);
767 ASSERT_EQ(NULL,fd_head->next->data);
768 ASSERT_NE(NULL,fd_head->next->next);
770 ASSERT_EQ(2,fd_head->next->next->frame);
771 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
772 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
773 ASSERT_EQ(0,fd_head->next->next->flags);
774 ASSERT_EQ(NULL,fd_head->next->next->data);
775 ASSERT_NE(NULL,fd_head->next->next->next);
777 ASSERT_EQ(3,fd_head->next->next->next->frame);
778 ASSERT_EQ(1,fd_head->next->next->next->offset); /* seqno */
779 ASSERT_EQ(60,fd_head->next->next->next->len); /* segment length */
780 ASSERT_EQ(FD_OVERLAP,fd_head->next->next->next->flags);
781 ASSERT_EQ(NULL,fd_head->next->next->next->data);
782 ASSERT_NE(NULL,fd_head->next->next->next->next);
784 ASSERT_EQ(4,fd_head->next->next->next->next->frame);
785 ASSERT_EQ(2,fd_head->next->next->next->next->offset); /* seqno */
786 ASSERT_EQ(40,fd_head->next->next->next->next->len); /* segment length */
787 ASSERT_EQ(0,fd_head->next->next->next->next->flags);
788 ASSERT_EQ(NULL,fd_head->next->next->next->next->data);
789 ASSERT_EQ(NULL,fd_head->next->next->next->next->next);
791 /* test the actual reassembly */
792 ASSERT(!memcmp(fd_head->data,data+10,50));
793 ASSERT(!memcmp(fd_head->data+50,data+5,60));
794 ASSERT(!memcmp(fd_head->data+110,data+5,40));
797 print_fragment_table();
801 /* Test case for fragment_add_seq with duplicated (e.g., retransmitted) data.
802 * Adds three fragments--adding the 3rd one twice--
803 * and checks that they are reassembled correctly.
805 /* visit id frame frag len more tvb_offset
812 test_fragment_add_seq_duplicate_last(void)
814 fragment_data *fd_head;
816 printf("Starting test test_fragment_add_seq_duplicate_last\n");
819 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
822 ASSERT_EQ(1,g_hash_table_size(fragment_table));
823 ASSERT_EQ(NULL,fd_head);
825 /* Add the 2nd segment */
827 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
830 /* we haven't got all the fragments yet ... */
831 ASSERT_EQ(1,g_hash_table_size(fragment_table));
832 ASSERT_EQ(NULL,fd_head);
834 /* Add the last fragment */
836 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
839 ASSERT_EQ(1,g_hash_table_size(fragment_table));
840 ASSERT_NE(NULL,fd_head);
842 /* Add the last fragment again */
844 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
847 /* Reassembly should have still succeeded */
848 ASSERT_EQ(1,g_hash_table_size(fragment_table));
849 ASSERT_NE(NULL,fd_head);
851 /* check the contents of the structure */
852 ASSERT_EQ(0,fd_head->frame); /* unused */
853 ASSERT_EQ(0,fd_head->offset); /* unused */
854 ASSERT_EQ(150,fd_head->len); /* the length of data we have */
855 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
856 ASSERT_EQ(3,fd_head->reassembled_in);
857 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
858 ASSERT_NE(NULL,fd_head->data);
859 ASSERT_NE(NULL,fd_head->next);
861 ASSERT_EQ(1,fd_head->next->frame);
862 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
863 ASSERT_EQ(50,fd_head->next->len); /* segment length */
864 ASSERT_EQ(0,fd_head->next->flags);
865 ASSERT_EQ(NULL,fd_head->next->data);
866 ASSERT_NE(NULL,fd_head->next->next);
868 ASSERT_EQ(2,fd_head->next->next->frame);
869 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
870 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
871 ASSERT_EQ(0,fd_head->next->next->flags);
872 ASSERT_EQ(NULL,fd_head->next->next->data);
873 ASSERT_NE(NULL,fd_head->next->next->next);
875 ASSERT_EQ(3,fd_head->next->next->next->frame);
876 ASSERT_EQ(2,fd_head->next->next->next->offset); /* seqno */
877 ASSERT_EQ(40,fd_head->next->next->next->len); /* segment length */
878 ASSERT_EQ(0,fd_head->next->next->next->flags);
879 ASSERT_EQ(NULL,fd_head->next->next->next->data);
880 ASSERT_NE(NULL,fd_head->next->next->next->next);
882 ASSERT_EQ(4,fd_head->next->next->next->next->frame);
883 ASSERT_EQ(2,fd_head->next->next->next->next->offset); /* seqno */
884 ASSERT_EQ(40,fd_head->next->next->next->next->len); /* segment length */
885 ASSERT_EQ(FD_OVERLAP,fd_head->next->next->next->next->flags);
886 ASSERT_EQ(NULL,fd_head->next->next->next->next->data);
887 ASSERT_EQ(NULL,fd_head->next->next->next->next->next);
889 /* test the actual reassembly */
890 ASSERT(!memcmp(fd_head->data,data+10,50));
891 ASSERT(!memcmp(fd_head->data+50,data+5,60));
892 ASSERT(!memcmp(fd_head->data+110,data+5,40));
895 print_fragment_table();
899 /* Test case for fragment_add_seq with duplicated (e.g., retransmitted) data
900 * where the retransmission "conflicts" with the original transmission
901 * (contents are different).
902 * Adds three fragments--adding the 2nd one twice--
903 * and checks that they are reassembled correctly.
905 /* visit id frame frag len more tvb_offset
912 test_fragment_add_seq_duplicate_conflict(void)
914 fragment_data *fd_head;
916 printf("Starting test test_fragment_add_seq_duplicate_conflict\n");
919 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
922 ASSERT_EQ(1,g_hash_table_size(fragment_table));
923 ASSERT_EQ(NULL,fd_head);
925 /* Add the 2nd segment */
927 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
930 /* we haven't got all the fragments yet ... */
931 ASSERT_EQ(1,g_hash_table_size(fragment_table));
932 ASSERT_EQ(NULL,fd_head);
934 /* Now, add the 2nd segment again (but in a different frame and with
938 fd_head=fragment_add_seq(tvb, 15, &pinfo, 12, fragment_table,
941 /* This duplicate fragment should have been ignored */
942 ASSERT_EQ(1,g_hash_table_size(fragment_table));
943 ASSERT_EQ(NULL,fd_head);
945 /* finally, add the last fragment */
947 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
950 ASSERT_EQ(1,g_hash_table_size(fragment_table));
951 ASSERT_NE(NULL,fd_head);
953 /* check the contents of the structure */
954 ASSERT_EQ(0,fd_head->frame); /* unused */
955 ASSERT_EQ(0,fd_head->offset); /* unused */
956 ASSERT_EQ(150,fd_head->len); /* the length of data we have */
957 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
958 ASSERT_EQ(4,fd_head->reassembled_in);
959 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP|FD_OVERLAPCONFLICT,fd_head->flags);
960 ASSERT_NE(NULL,fd_head->data);
961 ASSERT_NE(NULL,fd_head->next);
963 ASSERT_EQ(1,fd_head->next->frame);
964 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
965 ASSERT_EQ(50,fd_head->next->len); /* segment length */
966 ASSERT_EQ(0,fd_head->next->flags);
967 ASSERT_EQ(NULL,fd_head->next->data);
968 ASSERT_NE(NULL,fd_head->next->next);
970 ASSERT_EQ(2,fd_head->next->next->frame);
971 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
972 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
973 ASSERT_EQ(0,fd_head->next->next->flags);
974 ASSERT_EQ(NULL,fd_head->next->next->data);
975 ASSERT_NE(NULL,fd_head->next->next->next);
977 ASSERT_EQ(3,fd_head->next->next->next->frame);
978 ASSERT_EQ(1,fd_head->next->next->next->offset); /* seqno */
979 ASSERT_EQ(60,fd_head->next->next->next->len); /* segment length */
980 ASSERT_EQ(FD_OVERLAP|FD_OVERLAPCONFLICT,fd_head->next->next->next->flags);
981 ASSERT_EQ(NULL,fd_head->next->next->next->data);
982 ASSERT_NE(NULL,fd_head->next->next->next->next);
984 ASSERT_EQ(4,fd_head->next->next->next->next->frame);
985 ASSERT_EQ(2,fd_head->next->next->next->next->offset); /* seqno */
986 ASSERT_EQ(40,fd_head->next->next->next->next->len); /* segment length */
987 ASSERT_EQ(0,fd_head->next->next->next->next->flags);
988 ASSERT_EQ(NULL,fd_head->next->next->next->next->data);
989 ASSERT_EQ(NULL,fd_head->next->next->next->next->next);
991 /* test the actual reassembly */
992 ASSERT(!memcmp(fd_head->data,data+10,50));
993 ASSERT(!memcmp(fd_head->data+50,data+5,60));
994 ASSERT(!memcmp(fd_head->data+110,data+5,40));
997 print_fragment_table();
1001 /**********************************************************************************
1003 * fragment_add_dcerpc_dg
1005 *********************************************************************************/
1007 /* This can afford to be reasonably minimal, as it's just the same logic with a
1008 * different hash key to fragment_add_seq
1011 test_fragment_add_dcerpc_dg(void)
1013 e_uuid_t act_id = {1,2,3,{4,5,6,7,8,9,10,11}};
1015 fragment_data *fd_head, *fdh0;
1016 GHashTable *fragment_table = NULL;
1018 printf("Starting test test_fragment_add_dcerpc_dg\n");
1020 /* we need our own fragment table */
1021 dcerpc_fragment_table_init(&fragment_table);
1022 fd_head=fragment_add_dcerpc_dg(tvb, 10, &pinfo, 12, &act_id, fragment_table,
1025 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1026 ASSERT_EQ(NULL,fd_head);
1028 /* start another pdu (just to confuse things) */
1030 fd_head=fragment_add_dcerpc_dg(tvb, 15, &pinfo, 13, &act_id, fragment_table,
1032 ASSERT_EQ(2,g_hash_table_size(fragment_table));
1033 ASSERT_EQ(NULL,fd_head);
1035 /* another pdu, with the same fragment_id, but a different act_id, to the
1039 fd_head=fragment_add_dcerpc_dg(tvb, 15, &pinfo, 12, &act_id, fragment_table,
1041 ASSERT_EQ(3,g_hash_table_size(fragment_table));
1042 ASSERT_EQ(NULL,fd_head);
1045 /* now we add the terminal fragment of the first datagram */
1047 fd_head=fragment_add_dcerpc_dg(tvb, 5, &pinfo, 12, &act_id, fragment_table,
1050 ASSERT_EQ(3,g_hash_table_size(fragment_table));
1051 ASSERT_NE(NULL,fd_head);
1053 /* check the contents of the structure */
1054 ASSERT_EQ(0,fd_head->frame); /* unused */
1055 ASSERT_EQ(0,fd_head->offset); /* unused */
1056 ASSERT_EQ(110,fd_head->len); /* the length of data we have */
1057 ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */
1058 ASSERT_EQ(4,fd_head->reassembled_in);
1059 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
1060 ASSERT_NE(NULL,fd_head->data);
1061 ASSERT_NE(NULL,fd_head->next);
1063 /* test the actual reassembly */
1064 ASSERT(!memcmp(fd_head->data,data+10,50));
1065 ASSERT(!memcmp(fd_head->data+50,data+5,60));
1067 /* what happens if we revisit the packets now? */
1069 pinfo.fd->flags.visited = 1;
1071 fd_head=fragment_add_dcerpc_dg(tvb, 10, &pinfo, 12, &act_id, fragment_table,
1074 * this api relies on the caller to check fd_head -> reassembled_in
1076 * Redoing all the tests seems like overkill - just check the pointer
1078 ASSERT_EQ(fdh0,fd_head);
1081 /**********************************************************************************
1083 * fragment_add_seq_check
1085 *********************************************************************************/
1088 /* This routine is used for both fragment_add_seq_802_11 and
1089 * fragment_add_seq_check.
1091 * Adds a couple of out-of-order fragments and checks their reassembly.
1094 /* visit id frame frag len more tvb_offset
1103 test_fragment_add_seq_check_work(fragment_data *(*fn)(tvbuff_t *, const int,
1104 const packet_info *, const guint32, GHashTable *,
1105 GHashTable *, const guint32, const guint32, const gboolean))
1107 fragment_data *fd_head;
1109 pinfo.fd -> num = 1;
1110 fd_head=fn(tvb, 10, &pinfo, 12, fragment_table,
1111 reassembled_table, 0, 50, TRUE);
1113 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1114 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1115 ASSERT_EQ(NULL,fd_head);
1117 /* start another pdu (just to confuse things) */
1119 fd_head=fn(tvb, 15, &pinfo, 13, fragment_table,
1120 reassembled_table, 0, 60, TRUE);
1121 ASSERT_EQ(2,g_hash_table_size(fragment_table));
1122 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1123 ASSERT_EQ(NULL,fd_head);
1125 /* add the terminal fragment of the first datagram */
1127 fd_head=fn(tvb, 5, &pinfo, 12, fragment_table,
1128 reassembled_table, 2, 60, FALSE);
1130 /* we haven't got all the fragments yet ... */
1131 ASSERT_EQ(2,g_hash_table_size(fragment_table));
1132 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1133 ASSERT_EQ(NULL,fd_head);
1135 /* finally, add the missing fragment */
1137 fd_head=fn(tvb, 15, &pinfo, 12, fragment_table,
1138 reassembled_table, 1, 60, TRUE);
1140 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1141 ASSERT_EQ(3,g_hash_table_size(reassembled_table));
1142 ASSERT_NE(NULL,fd_head);
1144 /* check the contents of the structure */
1145 ASSERT_EQ(0,fd_head->frame); /* unused */
1146 ASSERT_EQ(0,fd_head->offset); /* unused */
1147 ASSERT_EQ(170,fd_head->len); /* the length of data we have */
1148 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
1149 ASSERT_EQ(4,fd_head->reassembled_in);
1150 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
1151 ASSERT_NE(NULL,fd_head->data);
1152 ASSERT_NE(NULL,fd_head->next);
1154 ASSERT_EQ(1,fd_head->next->frame);
1155 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
1156 ASSERT_EQ(50,fd_head->next->len); /* segment length */
1157 ASSERT_EQ(0,fd_head->next->flags);
1158 ASSERT_EQ(NULL,fd_head->next->data);
1159 ASSERT_NE(NULL,fd_head->next->next);
1161 ASSERT_EQ(4,fd_head->next->next->frame);
1162 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
1163 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
1164 ASSERT_EQ(0,fd_head->next->next->flags);
1165 ASSERT_EQ(NULL,fd_head->next->next->data);
1166 ASSERT_NE(NULL,fd_head->next->next->next);
1168 ASSERT_EQ(3,fd_head->next->next->next->frame);
1169 ASSERT_EQ(2,fd_head->next->next->next->offset); /* seqno */
1170 ASSERT_EQ(60,fd_head->next->next->next->len); /* segment length */
1171 ASSERT_EQ(0,fd_head->next->next->next->flags);
1172 ASSERT_EQ(NULL,fd_head->next->next->next->data);
1173 ASSERT_EQ(NULL,fd_head->next->next->next->next);
1175 /* test the actual reassembly */
1176 ASSERT(!memcmp(fd_head->data,data+10,50));
1177 ASSERT(!memcmp(fd_head->data+50,data+15,60));
1178 ASSERT(!memcmp(fd_head->data+110,data+5,60));
1185 /* Simple test case for fragment_add_seq_check
1188 test_fragment_add_seq_check(void)
1190 printf("Starting test test_fragment_add_seq_check\n");
1192 test_fragment_add_seq_check_work(fragment_add_seq_check);
1196 /* This tests the case that the 802.11 hack does something different for: when
1197 * the terminal segment in a fragmented datagram arrives first.
1200 test_fragment_add_seq_check_1(void)
1202 fragment_data *fd_head;
1204 printf("Starting test test_fragment_add_seq_check_1\n");
1207 fd_head=fragment_add_seq_check(tvb, 10, &pinfo, 12, fragment_table,
1208 reassembled_table, 1, 50, FALSE);
1210 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1211 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1212 ASSERT_EQ(NULL,fd_head);
1214 /* Now add the missing segment */
1216 fd_head=fragment_add_seq_check(tvb, 5, &pinfo, 12, fragment_table,
1217 reassembled_table, 0, 60, TRUE);
1219 ASSERT_EQ(0,g_hash_table_size(fragment_table));
1220 ASSERT_EQ(2,g_hash_table_size(reassembled_table));
1221 ASSERT_NE(NULL,fd_head);
1223 /* check the contents of the structure */
1224 ASSERT_EQ(0,fd_head->frame); /* unused */
1225 ASSERT_EQ(0,fd_head->offset); /* unused */
1226 ASSERT_EQ(110,fd_head->len); /* the length of data we have */
1227 ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */
1228 ASSERT_EQ(2,fd_head->reassembled_in);
1229 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
1230 ASSERT_NE(NULL,fd_head->data);
1231 ASSERT_NE(NULL,fd_head->next);
1233 ASSERT_EQ(2,fd_head->next->frame);
1234 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
1235 ASSERT_EQ(60,fd_head->next->len); /* segment length */
1236 ASSERT_EQ(0,fd_head->next->flags);
1237 ASSERT_EQ(NULL,fd_head->next->data);
1238 ASSERT_NE(NULL,fd_head->next->next);
1240 ASSERT_EQ(1,fd_head->next->next->frame);
1241 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
1242 ASSERT_EQ(50,fd_head->next->next->len); /* segment length */
1243 ASSERT_EQ(0,fd_head->next->next->flags);
1244 ASSERT_EQ(NULL,fd_head->next->next->data);
1245 ASSERT_EQ(NULL,fd_head->next->next->next);
1247 /* test the actual reassembly */
1248 ASSERT(!memcmp(fd_head->data,data+5,60));
1249 ASSERT(!memcmp(fd_head->data+60,data+10,50));
1252 /**********************************************************************************
1254 * fragment_add_seq_802_11
1256 *********************************************************************************/
1258 /* Tests the 802.11 hack.
1261 test_fragment_add_seq_802_11_0(void)
1263 fragment_data *fd_head;
1265 printf("Starting test test_fragment_add_seq_802_11_0\n");
1267 /* the 802.11 hack is that some non-fragmented datagrams have non-zero
1268 * fragment_number; test for this. */
1271 fd_head=fragment_add_seq_802_11(tvb, 10, &pinfo, 12, fragment_table,
1272 reassembled_table, 10, 50, FALSE);
1274 ASSERT_EQ(0,g_hash_table_size(fragment_table));
1275 ASSERT_EQ(1,g_hash_table_size(reassembled_table));
1276 ASSERT_NE(NULL,fd_head);
1278 /* check the contents of the structure */
1279 ASSERT_EQ(0,fd_head->frame); /* unused */
1280 ASSERT_EQ(0,fd_head->offset); /* unused */
1281 ASSERT_EQ(0,fd_head->len); /* unused */
1282 ASSERT_EQ(0,fd_head->datalen); /* unused */
1283 ASSERT_EQ(1,fd_head->reassembled_in);
1284 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE,fd_head->flags);
1285 ASSERT_EQ(NULL,fd_head->data);
1286 ASSERT_EQ(NULL,fd_head->next);
1289 /* Reuse the fragment_add_seq_check testcases */
1290 static void test_fragment_add_seq_802_11_1(void)
1292 printf("Starting test test_fragment_add_seq_802_11_1\n");
1293 test_fragment_add_seq_check_work(fragment_add_seq_802_11);
1296 /**********************************************************************************
1298 * fragment_add_seq_check_multiple
1300 *********************************************************************************/
1302 /* Test 2 partial frags from 2 diff datagrams in the same frame */
1304 datagram #1: frame 1 + first part of frame 2
1305 datagram #1: last part of frame 2 + frame 3
1307 Is this a valid scenario ?
1309 The result of calling fragment_add_seq_check() for these
1310 fragments is a reassembled_table with:
1311 id, frame 1 => first_datagram; ["reassembled in" frame 2]
1312 id, frame 2 => second_datagram; ["reassembled in" frame 3]
1313 id, frame 3 => second_datagram;
1315 Note that the id, frame 2 => first datagram was overwritten
1316 by the entry for the second datagram.
1317 Is this OK ? IE: When dissected/displayed
1318 will the reassembled datagram 1 appear with frame 2 ??
1321 /* visit id frame frag len more tvb_offset
1329 Is this a valid scenario ?
1330 Is this OK ? IE: When dissected/displayed:
1331 Will the reassembled datagram 1 appear with frame 2 ??
1335 test_fragment_add_seq_check_multiple(void) {
1336 fragment_data *fd_head;
1338 pinfo.fd -> num = 1;
1339 fd_head=fragment_add_seq_check(tvb, 10, &pinfo, 12, fragment_table,
1340 reassembled_table, 0, 50, TRUE);
1342 /* add the terminal fragment of the first datagram */
1344 fd_head=fragment_add_seq_check(tvb, 5, &pinfo, 12, fragment_table,
1345 reassembled_table, 1, 20, FALSE);
1349 /* Now: start a second datagram with the first fragment in frame #2 */
1351 fd_head=fragment_add_seq_check(tvb, 25, &pinfo, 12, fragment_table,
1352 reassembled_table, 0, 25, TRUE);
1354 /* add the terminal fragment of the second datagram */
1356 fd_head=fragment_add_seq_check(tvb, 0, &pinfo, 12, fragment_table,
1357 reassembled_table, 1, 60, FALSE);
1363 /**********************************************************************************
1365 * fragment_add_seq_next
1367 *********************************************************************************/
1369 /* Simple test case for fragment_add_seq_next.
1370 * Adds a couple of fragments (with one for a different datagram in between),
1371 * and checks that they are reassembled correctly.
1374 test_simple_fragment_add_seq_next(void)
1376 fragment_data *fd_head;
1378 printf("Starting test test_simple_fragment_add_seq_next\n");
1381 fd_head= fragment_add_seq_next(tvb, 10, &pinfo, 12, fragment_table,
1382 reassembled_table, 50, TRUE);
1384 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1385 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1386 ASSERT_EQ(NULL,fd_head);
1388 /* adding the same fragment again should do nothing, even with different
1390 pinfo.fd->flags.visited = 1;
1391 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
1392 reassembled_table, 60, TRUE);
1393 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1394 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1395 ASSERT_EQ(NULL,fd_head);
1397 /* start another pdu (just to confuse things) */
1398 pinfo.fd->flags.visited = 0;
1400 fd_head=fragment_add_seq_next(tvb, 15, &pinfo, 13, fragment_table,
1401 reassembled_table, 60, TRUE);
1402 ASSERT_EQ(2,g_hash_table_size(fragment_table));
1403 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1404 ASSERT_EQ(NULL,fd_head);
1407 /* now we add the terminal fragment of the first datagram */
1409 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
1410 reassembled_table, 60, FALSE);
1412 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1413 ASSERT_EQ(2,g_hash_table_size(reassembled_table));
1414 ASSERT_NE(NULL,fd_head);
1416 /* check the contents of the structure */
1417 ASSERT_EQ(0,fd_head->frame); /* unused */
1418 ASSERT_EQ(0,fd_head->offset); /* unused */
1419 ASSERT_EQ(110,fd_head->len); /* the length of data we have */
1420 ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */
1421 ASSERT_EQ(3,fd_head->reassembled_in);
1422 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
1423 ASSERT_NE(NULL,fd_head->data);
1424 ASSERT_NE(NULL,fd_head->next);
1426 ASSERT_EQ(1,fd_head->next->frame);
1427 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
1428 ASSERT_EQ(50,fd_head->next->len); /* segment length */
1429 ASSERT_EQ(0,fd_head->next->flags);
1430 ASSERT_EQ(NULL,fd_head->next->data);
1431 ASSERT_NE(NULL,fd_head->next->next);
1433 ASSERT_EQ(3,fd_head->next->next->frame);
1434 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
1435 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
1436 ASSERT_EQ(0,fd_head->next->next->flags);
1437 ASSERT_EQ(NULL,fd_head->next->next->data);
1438 ASSERT_EQ(NULL,fd_head->next->next->next);
1440 /* test the actual reassembly */
1441 ASSERT(!memcmp(fd_head->data,data+10,50));
1442 ASSERT(!memcmp(fd_head->data+50,data+5,60));
1446 /* This tests the case where some data is missing from one of the fragments.
1447 * It should prevent reassembly.
1450 test_missing_data_fragment_add_seq_next(void)
1452 fragment_data *fd_head;
1454 printf("Starting test test_missing_data_fragment_add_seq_next\n");
1456 /* attempt to add a fragment which is longer than the data available */
1458 fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 12, fragment_table,
1459 reassembled_table, DATA_LEN-9, TRUE);
1461 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1462 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1463 ASSERT_NE(NULL,fd_head);
1465 /* check the contents of the structure. Reassembly failed so everything
1466 * should be null (meaning, just use the original tvb) */
1467 ASSERT_EQ(0,fd_head->frame); /* unused */
1468 ASSERT_EQ(0,fd_head->offset); /* unused */
1469 ASSERT_EQ(0,fd_head->len); /* the length of data we have */
1470 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
1471 ASSERT_EQ(0,fd_head->reassembled_in);
1472 ASSERT_EQ(FD_BLOCKSEQUENCE,fd_head->flags & 0x1ff);
1473 ASSERT_EQ(NULL,fd_head->data);
1474 ASSERT_EQ(NULL,fd_head->next);
1476 /* add another fragment (with all data present) */
1478 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
1479 reassembled_table, 60, FALSE);
1481 /* XXX: it's not clear that this is the right result; however it's what the
1484 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1485 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1486 ASSERT_EQ(NULL,fd_head);
1489 /* check what happens when we revisit the packets */
1490 pinfo.fd->flags.visited = TRUE;
1493 fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 12, fragment_table,
1494 reassembled_table, DATA_LEN-9, TRUE);
1496 /* We just look in the reassembled_table for this packet. It never got put
1497 * there, so this always returns null.
1499 * That's crazy, because it means that the subdissector will see the data
1500 * exactly once - on the first pass through the capture (well, assuming it
1501 * doesn't bother to check fd_head->reassembled_in); however, that's
1502 * what the code does...
1504 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1505 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1506 ASSERT_EQ(NULL,fd_head);
1509 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
1510 reassembled_table, 60, FALSE);
1511 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1512 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1513 ASSERT_EQ(NULL,fd_head);
1518 * we're going to do something similar now, but this time it is the second
1519 * fragment which has something missing.
1522 test_missing_data_fragment_add_seq_next_2(void)
1524 fragment_data *fd_head;
1526 printf("Starting test test_missing_data_fragment_add_seq_next_2\n");
1529 fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 24, fragment_table,
1530 reassembled_table, 50, TRUE);
1532 ASSERT_EQ(1,g_hash_table_size(fragment_table));
1533 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1534 ASSERT_EQ(NULL,fd_head);
1537 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 24, fragment_table,
1538 reassembled_table, DATA_LEN-4, FALSE);
1540 /* XXX: again, i'm really dubious about this. Surely this should return all
1541 * the data we had, for a best-effort attempt at dissecting it?
1542 * And it ought to go into the reassembled table?
1544 ASSERT_EQ(0,g_hash_table_size(fragment_table));
1545 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1546 ASSERT_EQ(NULL,fd_head);
1548 /* check what happens when we revisit the packets */
1549 pinfo.fd->flags.visited = TRUE;
1552 fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 24, fragment_table,
1553 reassembled_table, 50, TRUE);
1555 /* As before, this returns NULL because the fragment isn't in the
1556 * reassembled_table. At least this is a bit more consistent than before.
1558 ASSERT_EQ(0,g_hash_table_size(fragment_table));
1559 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1560 ASSERT_EQ(NULL,fd_head);
1563 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 24, fragment_table,
1564 reassembled_table, DATA_LEN-4, FALSE);
1565 ASSERT_EQ(0,g_hash_table_size(fragment_table));
1566 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
1567 ASSERT_EQ(NULL,fd_head);
1572 * This time, our datagram only has one segment, but it has data missing.
1575 test_missing_data_fragment_add_seq_next_3(void)
1577 fragment_data *fd_head;
1579 printf("Starting test test_missing_data_fragment_add_seq_next_3\n");
1582 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 30, fragment_table,
1583 reassembled_table, DATA_LEN-4, FALSE);
1585 ASSERT_EQ(0,g_hash_table_size(fragment_table));
1586 ASSERT_EQ(1,g_hash_table_size(reassembled_table));
1587 ASSERT_NE(NULL,fd_head);
1589 /* check the contents of the structure. */
1590 ASSERT_EQ(0,fd_head->frame); /* unused */
1591 ASSERT_EQ(0,fd_head->offset); /* unused */
1592 ASSERT_EQ(0,fd_head->len); /* the length of data we have */
1593 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
1594 ASSERT_EQ(20,fd_head->reassembled_in);
1595 ASSERT_EQ(FD_BLOCKSEQUENCE|FD_DEFRAGMENTED,fd_head->flags);
1596 ASSERT_EQ(NULL,fd_head->data);
1597 ASSERT_EQ(NULL,fd_head->next);
1599 /* revisiting the packet ought to produce the same result. */
1600 pinfo.fd->flags.visited = TRUE;
1603 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 30, fragment_table,
1604 reassembled_table, DATA_LEN-4, FALSE);
1606 ASSERT_EQ(0,g_hash_table_size(fragment_table));
1607 ASSERT_EQ(1,g_hash_table_size(reassembled_table));
1608 ASSERT_NE(NULL,fd_head);
1609 ASSERT_EQ(0,fd_head->frame); /* unused */
1610 ASSERT_EQ(0,fd_head->offset); /* unused */
1611 ASSERT_EQ(0,fd_head->len); /* the length of data we have */
1612 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
1613 ASSERT_EQ(20,fd_head->reassembled_in);
1614 ASSERT_EQ(FD_BLOCKSEQUENCE|FD_DEFRAGMENTED,fd_head->flags);
1615 ASSERT_EQ(NULL,fd_head->data);
1616 ASSERT_EQ(NULL,fd_head->next);
1620 /**********************************************************************************
1624 *********************************************************************************/
1627 main(int argc _U_, char **argv _U_)
1630 char src[] = {1,2,3,4}, dst[] = {5,6,7,8};
1632 void (*tests[])(void) = {
1633 test_simple_fragment_add_seq, /* frag table only */
1634 test_fragment_add_seq_partial_reassembly,
1635 test_fragment_add_seq_duplicate_first,
1636 test_fragment_add_seq_duplicate_middle,
1637 test_fragment_add_seq_duplicate_last,
1638 test_fragment_add_seq_duplicate_conflict,
1639 test_fragment_add_dcerpc_dg,
1640 test_fragment_add_seq_check, /* frag + reassemble */
1641 test_fragment_add_seq_check_1,
1642 test_fragment_add_seq_802_11_0,
1643 test_fragment_add_seq_802_11_1,
1644 test_simple_fragment_add_seq_next,
1645 test_missing_data_fragment_add_seq_next,
1646 test_missing_data_fragment_add_seq_next_2,
1647 test_missing_data_fragment_add_seq_next_3,
1649 test_fragment_add_seq_check_multiple
1653 /* initialise stuff */
1656 /* a tvbuff for testing with */
1657 data = g_malloc(DATA_LEN);
1658 /* make sure it's full of stuff */
1659 for(i=0; i<DATA_LEN; i++) {
1662 tvb = tvb_new_real_data(data, DATA_LEN, DATA_LEN*2);
1664 /* other test stuff */
1666 fd.flags.visited = 0;
1667 SET_ADDRESS(&pinfo.src,AT_IPv4,4,src);
1668 SET_ADDRESS(&pinfo.dst,AT_IPv4,4,dst);
1670 /*************************************************************************/
1671 for(i=0; i < sizeof(tests)/sizeof(tests[0]); i++ ) {
1672 /* re-init the fragment tables */
1673 fragment_table_init(&fragment_table);
1674 ASSERT(fragment_table != NULL);
1676 reassembled_table_init(&reassembled_table);
1677 ASSERT(reassembled_table != NULL);
1679 pinfo.fd->flags.visited = FALSE;
1683 /* Free memory used by the tables */
1684 fragment_table_init(&fragment_table);
1685 g_hash_table_destroy(fragment_table);
1686 fragment_table = NULL;
1688 reassembled_table_init(&reassembled_table);
1689 g_hash_table_destroy(reassembled_table);
1690 reassembled_table = NULL;
1698 printf(failure?"FAILURE\n":"SUCCESS\n");