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.
11 * Copyright (c) 2007 MX Telecom Ltd. <richardv@mxtelecom.com>
13 * Wireshark - Network traffic analyzer
14 * By Gerald Combs <gerald@wireshark.org>
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
43 #include <epan/emem.h>
44 #include <epan/packet.h>
45 #include <epan/packet_info.h>
46 #include <epan/proto.h>
47 #include <epan/tvbuff.h>
48 #include <epan/reassemble.h>
50 #include <epan/dissectors/packet-dcerpc.h>
52 #define ASSERT(b) do_test((b),"Assertion failed at line %i: %s\n", __LINE__, #b)
53 #define ASSERT_EQ(exp,act) do_test((exp)==(act),"Assertion failed at line %i: %s==%s (%i==%i)\n", __LINE__, #exp, #act, exp, act)
54 #define ASSERT_NE(exp,act) do_test((exp)!=(act),"Assertion failed at line %i: %s!=%s (%i!=%i)\n", __LINE__, #exp, #act, exp, act)
58 void do_test(int condition, char *format, ...)
65 vfprintf(stderr, format, ap);
69 /* many of the tests assume this routine doesn't return on failure; if we
70 * do, it may provide more information, but may cause a segfault. Uncomment
71 * this line if you wish.
82 /* fragment_table maps from datagram ids to head of fragment_data list
83 reassembled_table maps from <packet number,datagram id> to head of
85 GHashTable *fragment_table = NULL, *reassembled_table = NULL;
87 /**********************************************************************************
91 *********************************************************************************/
93 /* Simple test case for fragment_add_seq.
94 * Adds three fragments (out of order, with one for a different datagram in between),
95 * and checks that they are reassembled correctly.
97 static void test_simple_fragment_add_seq(void)
99 fragment_data *fd_head, *fdh0;
101 printf("Starting test test_simple_fragment_add_seq\n");
104 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
107 ASSERT_EQ(1,g_hash_table_size(fragment_table));
108 ASSERT_EQ(NULL,fd_head);
110 /* adding the same fragment again should do nothing, even with different
112 pinfo.fd->flags.visited = 1;
113 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
115 ASSERT_EQ(1,g_hash_table_size(fragment_table));
116 ASSERT_EQ(NULL,fd_head);
118 /* start another pdu (just to confuse things) */
119 pinfo.fd->flags.visited = 0;
121 fd_head=fragment_add_seq(tvb, 15, &pinfo, 13, fragment_table,
123 ASSERT_EQ(2,g_hash_table_size(fragment_table));
124 ASSERT_EQ(NULL,fd_head);
126 /* now we add the terminal fragment of the first datagram */
128 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
131 /* we haven't got all the fragments yet ... */
132 ASSERT_EQ(2,g_hash_table_size(fragment_table));
133 ASSERT_EQ(NULL,fd_head);
135 /* finally, add the missing fragment */
137 fd_head=fragment_add_seq(tvb, 15, &pinfo, 12, fragment_table,
140 ASSERT_EQ(2,g_hash_table_size(fragment_table));
141 ASSERT_NE(NULL,fd_head);
143 /* check the contents of the structure */
144 ASSERT_EQ(0,fd_head->frame); /* unused */
145 ASSERT_EQ(0,fd_head->offset); /* unused */
146 ASSERT_EQ(170,fd_head->len); /* the length of data we have */
147 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
148 ASSERT_EQ(4,fd_head->reassembled_in);
149 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
150 ASSERT_NE(NULL,fd_head->data);
151 ASSERT_NE(NULL,fd_head->next);
153 ASSERT_EQ(1,fd_head->next->frame);
154 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
155 ASSERT_EQ(50,fd_head->next->len); /* segment length */
156 ASSERT_EQ(0,fd_head->next->flags);
157 ASSERT_EQ(NULL,fd_head->next->data);
158 ASSERT_NE(NULL,fd_head->next->next);
160 ASSERT_EQ(4,fd_head->next->next->frame);
161 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
162 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
163 ASSERT_EQ(0,fd_head->next->next->flags);
164 ASSERT_EQ(NULL,fd_head->next->next->data);
165 ASSERT_NE(NULL,fd_head->next->next->next);
167 ASSERT_EQ(3,fd_head->next->next->next->frame);
168 ASSERT_EQ(2,fd_head->next->next->next->offset); /* seqno */
169 ASSERT_EQ(60,fd_head->next->next->next->len); /* segment length */
170 ASSERT_EQ(0,fd_head->next->next->next->flags);
171 ASSERT_EQ(NULL,fd_head->next->next->next->data);
172 ASSERT_EQ(NULL,fd_head->next->next->next->next);
174 /* test the actual reassembly */
175 ASSERT(!memcmp(fd_head->data,data+10,50));
176 ASSERT(!memcmp(fd_head->data+50,data+15,60));
177 ASSERT(!memcmp(fd_head->data+110,data+5,60));
179 /* what happens if we revisit the packets now? */
181 pinfo.fd->flags.visited = 1;
183 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
186 * this api relies on the caller to check fd_head -> reassembled_in
188 * Redoing all the tests seems like overkill - just check the pointer
190 ASSERT_EQ(fdh0,fd_head);
193 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
195 ASSERT_EQ(fdh0,fd_head);
198 fd_head=fragment_add_seq(tvb, 15, &pinfo, 12, fragment_table,
200 ASSERT_EQ(fdh0,fd_head);
203 /* XXX ought to have some tests for overlapping fragments */
205 /* This tests the functionality of fragment_set_partial_reassembly for
206 * FD_BLOCKSEQUENCE reassembly.
208 * We add a sequence of fragments thus:
209 * seqno frame offset len (initial) more_frags
210 * ----- ----- ------ --- --------------------
213 * 1 3 0 40 true (a duplicate fragment)
217 static void test_fragment_add_seq_partial_reassembly(void)
219 fragment_data *fd_head, *fd;
221 printf("Starting test test_fragment_add_seq_partial_reassembly\n");
223 /* generally it's probably fair to assume that we will be called with
227 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
230 ASSERT_EQ(1,g_hash_table_size(fragment_table));
231 ASSERT_NE(NULL,fd_head);
233 /* check the contents of the structure */
234 ASSERT_EQ(0,fd_head->frame); /* unused */
235 ASSERT_EQ(0,fd_head->offset); /* unused */
236 ASSERT_EQ(50,fd_head->len); /* the length of data we have */
237 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
238 ASSERT_EQ(1,fd_head->reassembled_in);
239 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
240 ASSERT_NE(NULL,fd_head->data);
241 ASSERT_NE(NULL,fd_head->next);
243 ASSERT_EQ(1,fd_head->next->frame);
244 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
245 ASSERT_EQ(50,fd_head->next->len); /* segment length */
246 ASSERT_EQ(0,fd_head->next->flags);
247 ASSERT_EQ(NULL,fd_head->next->data);
248 ASSERT_EQ(NULL,fd_head->next->next);
250 /* test the actual reassembly */
251 ASSERT(!memcmp(fd_head->data,data+10,50));
253 /* now we announce that the reassembly wasn't complete after all. */
254 fragment_set_partial_reassembly(&pinfo,12,fragment_table);
256 /* and add another segment. To mix things up slightly (and so that we can
257 * check on the state of things), we're going to set the more_frags flag
261 fd_head=fragment_add_seq(tvb, 0, &pinfo, 12, fragment_table,
264 ASSERT_EQ(1,g_hash_table_size(fragment_table));
265 ASSERT_EQ(NULL,fd_head);
267 fd_head=fragment_get(&pinfo,12,fragment_table);
268 ASSERT_NE(NULL,fd_head);
270 /* check the contents of the structure */
271 ASSERT_EQ(0,fd_head->frame); /* unused */
272 ASSERT_EQ(0,fd_head->offset); /* unused */
273 /* ASSERT_EQ(50,fd_head->len); the length of data we have */
274 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
275 ASSERT_EQ(0,fd_head->reassembled_in);
276 ASSERT_EQ(FD_BLOCKSEQUENCE,fd_head->flags);
277 ASSERT_NE(NULL,fd_head->data);
278 ASSERT_NE(NULL,fd_head->next);
281 ASSERT_EQ(1,fd->frame);
282 ASSERT_EQ(0,fd->offset); /* seqno */
283 ASSERT_EQ(50,fd->len); /* segment length */
284 ASSERT_EQ(FD_NOT_MALLOCED,fd->flags);
285 ASSERT_EQ(fd_head->data,fd->data);
286 ASSERT_NE(NULL,fd->next);
289 ASSERT_EQ(2,fd->frame);
290 ASSERT_EQ(1,fd->offset); /* seqno */
291 ASSERT_EQ(40,fd->len); /* segment length */
292 ASSERT_EQ(0,fd->flags);
293 ASSERT_NE(NULL,fd->data);
294 ASSERT_EQ(NULL,fd->next);
296 /* Another copy of the second segment.
299 fd_head=fragment_add_seq(tvb, 0, &pinfo, 12, fragment_table,
302 ASSERT_EQ(1,g_hash_table_size(fragment_table));
303 ASSERT_EQ(NULL,fd_head);
304 fd_head=fragment_get(&pinfo,12,fragment_table);
305 ASSERT_NE(NULL,fd_head);
306 ASSERT_EQ(0,fd_head->frame); /* unused */
307 ASSERT_EQ(0,fd_head->offset); /* unused */
308 /* ASSERT_EQ(50,fd_head->len); the length of data we have */
309 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
310 ASSERT_EQ(0,fd_head->reassembled_in);
311 ASSERT_EQ(FD_BLOCKSEQUENCE,fd_head->flags);
312 ASSERT_NE(NULL,fd_head->data);
313 ASSERT_NE(NULL,fd_head->next);
316 ASSERT_EQ(1,fd->frame);
317 ASSERT_EQ(0,fd->offset); /* seqno */
318 ASSERT_EQ(50,fd->len); /* segment length */
319 ASSERT_EQ(FD_NOT_MALLOCED,fd->flags);
320 ASSERT_EQ(fd_head->data,fd->data);
321 ASSERT_NE(NULL,fd->next);
324 ASSERT_EQ(2,fd->frame);
325 ASSERT_EQ(1,fd->offset); /* seqno */
326 ASSERT_EQ(40,fd->len); /* segment length */
327 ASSERT_EQ(0,fd->flags);
328 ASSERT_NE(NULL,fd->data);
329 ASSERT_NE(NULL,fd->next);
332 ASSERT_EQ(3,fd->frame);
333 ASSERT_EQ(1,fd->offset); /* seqno */
334 ASSERT_EQ(40,fd->len); /* segment length */
335 ASSERT_EQ(0,fd->flags);
336 ASSERT_NE(NULL,fd->data);
337 ASSERT_EQ(NULL,fd->next);
341 /* have another go at wrapping things up */
343 fd_head=fragment_add_seq(tvb, 20, &pinfo, 12, fragment_table,
346 ASSERT_EQ(1,g_hash_table_size(fragment_table));
347 ASSERT_NE(NULL,fd_head);
349 /* check the contents of the structure */
350 ASSERT_EQ(0,fd_head->frame); /* unused */
351 ASSERT_EQ(0,fd_head->offset); /* unused */
352 ASSERT_EQ(190,fd_head->len); /* the length of data we have */
353 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
354 ASSERT_EQ(4,fd_head->reassembled_in);
355 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
356 ASSERT_NE(NULL,fd_head->data);
357 ASSERT_NE(NULL,fd_head->next);
360 ASSERT_EQ(1,fd->frame);
361 ASSERT_EQ(0,fd->offset); /* seqno */
362 ASSERT_EQ(50,fd->len); /* segment length */
363 ASSERT_EQ(0,fd->flags);
364 ASSERT_EQ(NULL,fd->data);
365 ASSERT_NE(NULL,fd->next);
368 ASSERT_EQ(2,fd->frame);
369 ASSERT_EQ(1,fd->offset); /* seqno */
370 ASSERT_EQ(40,fd->len); /* segment length */
371 ASSERT_EQ(0,fd->flags);
372 ASSERT_EQ(NULL,fd->data);
373 ASSERT_NE(NULL,fd->next);
376 ASSERT_EQ(3,fd->frame);
377 ASSERT_EQ(1,fd->offset); /* seqno */
378 ASSERT_EQ(40,fd->len); /* segment length */
379 ASSERT_EQ(FD_OVERLAP,fd->flags);
380 ASSERT_EQ(NULL,fd->data);
381 ASSERT_NE(NULL,fd->next);
384 ASSERT_EQ(4,fd->frame);
385 ASSERT_EQ(2,fd->offset); /* seqno */
386 ASSERT_EQ(100,fd->len); /* segment length */
387 ASSERT_EQ(0,fd->flags);
388 ASSERT_EQ(NULL,fd->data);
389 ASSERT_EQ(NULL,fd->next);
391 /* test the actual reassembly */
392 ASSERT(!memcmp(fd_head->data,data+10,50));
393 ASSERT(!memcmp(fd_head->data+50,data,40));
394 ASSERT(!memcmp(fd_head->data+90,data+20,100));
397 /* do it again (this time it is more complicated, with an overlap in the
400 fragment_set_partial_reassembly(&pinfo,12,fragment_table);
403 fd_head=fragment_add_seq(tvb, 0, &pinfo, 12, fragment_table,
406 fd_head=fragment_get(&pinfo,12,fragment_table);
407 ASSERT_NE(NULL,fd_head);
408 ASSERT_EQ(0,fd_head->frame); /* unused */
409 ASSERT_EQ(0,fd_head->offset); /* unused */
410 ASSERT_EQ(230,fd_head->len); /* the length of data we have */
411 ASSERT_EQ(3,fd_head->datalen); /* seqno of the last fragment we have */
412 ASSERT_EQ(5,fd_head->reassembled_in);
413 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
414 ASSERT_NE(NULL,fd_head->data);
415 ASSERT_NE(NULL,fd_head->next);
418 ASSERT_EQ(1,fd->frame);
419 ASSERT_EQ(0,fd->offset); /* seqno */
420 ASSERT_EQ(50,fd->len); /* segment length */
421 ASSERT_EQ(0,fd->flags);
422 ASSERT_EQ(NULL,fd->data);
423 ASSERT_NE(NULL,fd->next);
426 ASSERT_EQ(2,fd->frame);
427 ASSERT_EQ(1,fd->offset); /* seqno */
428 ASSERT_EQ(40,fd->len); /* segment length */
429 ASSERT_EQ(0,fd->flags);
430 ASSERT_EQ(NULL,fd->data);
431 ASSERT_NE(NULL,fd->next);
434 ASSERT_EQ(3,fd->frame);
435 ASSERT_EQ(1,fd->offset); /* seqno */
436 ASSERT_EQ(40,fd->len); /* segment length */
437 ASSERT_EQ(FD_OVERLAP,fd->flags);
438 ASSERT_EQ(NULL,fd->data);
439 ASSERT_NE(NULL,fd->next);
442 ASSERT_EQ(4,fd->frame);
443 ASSERT_EQ(2,fd->offset); /* seqno */
444 ASSERT_EQ(100,fd->len); /* segment length */
445 ASSERT_EQ(0,fd->flags);
446 ASSERT_EQ(NULL,fd->data);
447 ASSERT_NE(NULL,fd->next);
450 ASSERT_EQ(5,fd->frame);
451 ASSERT_EQ(3,fd->offset); /* seqno */
452 ASSERT_EQ(40,fd->len); /* segment length */
453 ASSERT_EQ(0,fd->flags);
454 ASSERT_EQ(NULL,fd->data);
455 ASSERT_EQ(NULL,fd->next);
457 /* test the actual reassembly */
458 ASSERT(!memcmp(fd_head->data,data+10,50));
459 ASSERT(!memcmp(fd_head->data+50,data,40));
460 ASSERT(!memcmp(fd_head->data+90,data+20,100));
461 ASSERT(!memcmp(fd_head->data+190,data,40));
464 /**********************************************************************************
466 * fragment_add_dcerpc_dg
468 *********************************************************************************/
470 /* This can afford to be reasonably minimal, as it's just the same logic with a
471 * different hash key to fragment_add_seq
473 static void test_fragment_add_dcerpc_dg(void)
475 e_uuid_t act_id = {1,2,3,{4,5,6,7,8,9,10,11}};
477 fragment_data *fd_head, *fdh0;
478 GHashTable *fragment_table = NULL;
480 printf("Starting test test_fragment_add_dcerpc_dg\n");
482 /* we need our own fragment table */
483 dcerpc_fragment_table_init(&fragment_table);
484 fd_head=fragment_add_dcerpc_dg(tvb, 10, &pinfo, 12, &act_id, fragment_table,
487 ASSERT_EQ(1,g_hash_table_size(fragment_table));
488 ASSERT_EQ(NULL,fd_head);
490 /* start another pdu (just to confuse things) */
492 fd_head=fragment_add_dcerpc_dg(tvb, 15, &pinfo, 13, &act_id, fragment_table,
494 ASSERT_EQ(2,g_hash_table_size(fragment_table));
495 ASSERT_EQ(NULL,fd_head);
497 /* another pdu, with the same fragment_id, but a different act_id, to the
501 fd_head=fragment_add_dcerpc_dg(tvb, 15, &pinfo, 12, &act_id, fragment_table,
503 ASSERT_EQ(3,g_hash_table_size(fragment_table));
504 ASSERT_EQ(NULL,fd_head);
507 /* now we add the terminal fragment of the first datagram */
509 fd_head=fragment_add_dcerpc_dg(tvb, 5, &pinfo, 12, &act_id, fragment_table,
512 ASSERT_EQ(3,g_hash_table_size(fragment_table));
513 ASSERT_NE(NULL,fd_head);
515 /* check the contents of the structure */
516 ASSERT_EQ(0,fd_head->frame); /* unused */
517 ASSERT_EQ(0,fd_head->offset); /* unused */
518 ASSERT_EQ(110,fd_head->len); /* the length of data we have */
519 ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */
520 ASSERT_EQ(4,fd_head->reassembled_in);
521 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
522 ASSERT_NE(NULL,fd_head->data);
523 ASSERT_NE(NULL,fd_head->next);
525 /* test the actual reassembly */
526 ASSERT(!memcmp(fd_head->data,data+10,50));
527 ASSERT(!memcmp(fd_head->data+50,data+5,60));
529 /* what happens if we revisit the packets now? */
531 pinfo.fd->flags.visited = 1;
533 fd_head=fragment_add_dcerpc_dg(tvb, 10, &pinfo, 12, &act_id, fragment_table,
536 * this api relies on the caller to check fd_head -> reassembled_in
538 * Redoing all the tests seems like overkill - just check the pointer
540 ASSERT_EQ(fdh0,fd_head);
543 /**********************************************************************************
545 * fragment_add_seq_check
547 *********************************************************************************/
550 /* This routine is used for both fragment_add_seq_802_11 and
551 * fragment_add_seq_check.
553 * Adds a couple of out-of-order fragments and checks their reassembly.
555 static void test_fragment_add_seq_check_work(
556 fragment_data *(*fn)(tvbuff_t *, int, packet_info *, guint32, GHashTable *,
557 GHashTable *, guint32, guint32, gboolean))
559 fragment_data *fd_head;
562 fd_head=fn(tvb, 10, &pinfo, 12, fragment_table,
563 reassembled_table, 0, 50, TRUE);
565 ASSERT_EQ(1,g_hash_table_size(fragment_table));
566 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
567 ASSERT_EQ(NULL,fd_head);
569 /* start another pdu (just to confuse things) */
571 fd_head=fn(tvb, 15, &pinfo, 13, fragment_table,
572 reassembled_table, 0, 60, TRUE);
573 ASSERT_EQ(2,g_hash_table_size(fragment_table));
574 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
575 ASSERT_EQ(NULL,fd_head);
577 /* add the terminal fragment of the first datagram */
579 fd_head=fn(tvb, 5, &pinfo, 12, fragment_table,
580 reassembled_table, 2, 60, FALSE);
582 /* we haven't got all the fragments yet ... */
583 ASSERT_EQ(2,g_hash_table_size(fragment_table));
584 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
585 ASSERT_EQ(NULL,fd_head);
587 /* finally, add the missing fragment */
589 fd_head=fn(tvb, 15, &pinfo, 12, fragment_table,
590 reassembled_table, 1, 60, TRUE);
592 ASSERT_EQ(1,g_hash_table_size(fragment_table));
593 ASSERT_EQ(3,g_hash_table_size(reassembled_table));
594 ASSERT_NE(NULL,fd_head);
596 /* check the contents of the structure */
597 ASSERT_EQ(0,fd_head->frame); /* unused */
598 ASSERT_EQ(0,fd_head->offset); /* unused */
599 ASSERT_EQ(170,fd_head->len); /* the length of data we have */
600 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
601 ASSERT_EQ(4,fd_head->reassembled_in);
602 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
603 ASSERT_NE(NULL,fd_head->data);
604 ASSERT_NE(NULL,fd_head->next);
606 ASSERT_EQ(1,fd_head->next->frame);
607 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
608 ASSERT_EQ(50,fd_head->next->len); /* segment length */
609 ASSERT_EQ(0,fd_head->next->flags);
610 ASSERT_EQ(NULL,fd_head->next->data);
611 ASSERT_NE(NULL,fd_head->next->next);
613 ASSERT_EQ(4,fd_head->next->next->frame);
614 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
615 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
616 ASSERT_EQ(0,fd_head->next->next->flags);
617 ASSERT_EQ(NULL,fd_head->next->next->data);
618 ASSERT_NE(NULL,fd_head->next->next->next);
620 ASSERT_EQ(3,fd_head->next->next->next->frame);
621 ASSERT_EQ(2,fd_head->next->next->next->offset); /* seqno */
622 ASSERT_EQ(60,fd_head->next->next->next->len); /* segment length */
623 ASSERT_EQ(0,fd_head->next->next->next->flags);
624 ASSERT_EQ(NULL,fd_head->next->next->next->data);
625 ASSERT_EQ(NULL,fd_head->next->next->next->next);
627 /* test the actual reassembly */
628 ASSERT(!memcmp(fd_head->data,data+10,50));
629 ASSERT(!memcmp(fd_head->data+50,data+15,60));
630 ASSERT(!memcmp(fd_head->data+110,data+5,60));
633 /* Simple test case for fragment_add_seq_check
635 static void test_fragment_add_seq_check(void)
637 printf("Starting test test_fragment_add_seq_check\n");
639 test_fragment_add_seq_check_work(fragment_add_seq_check);
643 /* This tests the case that the 802.11 hack does something different for: when
644 * the terminal segment in a fragmented datagram arrives first.
646 static void test_fragment_add_seq_check_1(void)
648 fragment_data *fd_head;
650 printf("Starting test test_fragment_add_seq_check_1\n");
653 fd_head=fragment_add_seq_check(tvb, 10, &pinfo, 12, fragment_table,
654 reassembled_table, 1, 50, FALSE);
656 ASSERT_EQ(1,g_hash_table_size(fragment_table));
657 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
658 ASSERT_EQ(NULL,fd_head);
660 /* Now add the missing segment */
662 fd_head=fragment_add_seq_check(tvb, 5, &pinfo, 12, fragment_table,
663 reassembled_table, 0, 60, TRUE);
665 ASSERT_EQ(0,g_hash_table_size(fragment_table));
666 ASSERT_EQ(2,g_hash_table_size(reassembled_table));
667 ASSERT_NE(NULL,fd_head);
669 /* check the contents of the structure */
670 ASSERT_EQ(0,fd_head->frame); /* unused */
671 ASSERT_EQ(0,fd_head->offset); /* unused */
672 ASSERT_EQ(110,fd_head->len); /* the length of data we have */
673 ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */
674 ASSERT_EQ(2,fd_head->reassembled_in);
675 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
676 ASSERT_NE(NULL,fd_head->data);
677 ASSERT_NE(NULL,fd_head->next);
679 ASSERT_EQ(2,fd_head->next->frame);
680 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
681 ASSERT_EQ(60,fd_head->next->len); /* segment length */
682 ASSERT_EQ(0,fd_head->next->flags);
683 ASSERT_EQ(NULL,fd_head->next->data);
684 ASSERT_NE(NULL,fd_head->next->next);
686 ASSERT_EQ(1,fd_head->next->next->frame);
687 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
688 ASSERT_EQ(50,fd_head->next->next->len); /* segment length */
689 ASSERT_EQ(0,fd_head->next->next->flags);
690 ASSERT_EQ(NULL,fd_head->next->next->data);
691 ASSERT_EQ(NULL,fd_head->next->next->next);
693 /* test the actual reassembly */
694 ASSERT(!memcmp(fd_head->data,data+5,60));
695 ASSERT(!memcmp(fd_head->data+60,data+10,50));
698 /**********************************************************************************
700 * fragment_add_seq_802_11
702 *********************************************************************************/
704 /* Tests the 802.11 hack.
706 static void test_fragment_add_seq_802_11_0(void)
708 fragment_data *fd_head;
710 printf("Starting test test_fragment_add_seq_802_11_0\n");
712 /* the 802.11 hack is that some non-fragmented datagrams have non-zero
713 * fragment_number; test for this. */
716 fd_head=fragment_add_seq_802_11(tvb, 10, &pinfo, 12, fragment_table,
717 reassembled_table, 10, 50, FALSE);
719 ASSERT_EQ(0,g_hash_table_size(fragment_table));
720 ASSERT_EQ(1,g_hash_table_size(reassembled_table));
721 ASSERT_NE(NULL,fd_head);
723 /* check the contents of the structure */
724 ASSERT_EQ(0,fd_head->frame); /* unused */
725 ASSERT_EQ(0,fd_head->offset); /* unused */
726 ASSERT_EQ(0,fd_head->len); /* unused */
727 ASSERT_EQ(0,fd_head->datalen); /* unused */
728 ASSERT_EQ(1,fd_head->reassembled_in);
729 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE,fd_head->flags);
730 ASSERT_EQ(NULL,fd_head->data);
731 ASSERT_EQ(NULL,fd_head->next);
734 /* Reuse the fragment_add_seq_check testcases */
735 static void test_fragment_add_seq_802_11_1(void)
737 printf("Starting test test_fragment_add_seq_802_11_1\n");
738 test_fragment_add_seq_check_work(fragment_add_seq_802_11);
741 /**********************************************************************************
743 * fragment_add_seq_next
745 *********************************************************************************/
747 /* Simple test case for fragment_add_seq_next.
748 * Adds a couple of fragments (with one for a different datagram in between),
749 * and checks that they are reassembled correctly.
751 static void test_simple_fragment_add_seq_next(void)
753 fragment_data *fd_head;
755 printf("Starting test test_simple_fragment_add_seq_next\n");
758 fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 12, fragment_table,
759 reassembled_table, 50, TRUE);
761 ASSERT_EQ(1,g_hash_table_size(fragment_table));
762 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
763 ASSERT_EQ(NULL,fd_head);
765 /* adding the same fragment again should do nothing, even with different
767 pinfo.fd->flags.visited = 1;
768 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
769 reassembled_table, 60, TRUE);
770 ASSERT_EQ(1,g_hash_table_size(fragment_table));
771 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
772 ASSERT_EQ(NULL,fd_head);
774 /* start another pdu (just to confuse things) */
775 pinfo.fd->flags.visited = 0;
777 fd_head=fragment_add_seq_next(tvb, 15, &pinfo, 13, fragment_table,
778 reassembled_table, 60, TRUE);
779 ASSERT_EQ(2,g_hash_table_size(fragment_table));
780 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
781 ASSERT_EQ(NULL,fd_head);
784 /* now we add the terminal fragment of the first datagram */
786 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
787 reassembled_table, 60, FALSE);
789 ASSERT_EQ(1,g_hash_table_size(fragment_table));
790 ASSERT_EQ(2,g_hash_table_size(reassembled_table));
791 ASSERT_NE(NULL,fd_head);
793 /* check the contents of the structure */
794 ASSERT_EQ(0,fd_head->frame); /* unused */
795 ASSERT_EQ(0,fd_head->offset); /* unused */
796 ASSERT_EQ(110,fd_head->len); /* the length of data we have */
797 ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */
798 ASSERT_EQ(3,fd_head->reassembled_in);
799 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
800 ASSERT_NE(NULL,fd_head->data);
801 ASSERT_NE(NULL,fd_head->next);
803 ASSERT_EQ(1,fd_head->next->frame);
804 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
805 ASSERT_EQ(50,fd_head->next->len); /* segment length */
806 ASSERT_EQ(0,fd_head->next->flags);
807 ASSERT_EQ(NULL,fd_head->next->data);
808 ASSERT_NE(NULL,fd_head->next->next);
810 ASSERT_EQ(3,fd_head->next->next->frame);
811 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
812 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
813 ASSERT_EQ(0,fd_head->next->next->flags);
814 ASSERT_EQ(NULL,fd_head->next->next->data);
815 ASSERT_EQ(NULL,fd_head->next->next->next);
817 /* test the actual reassembly */
818 ASSERT(!memcmp(fd_head->data,data+10,50));
819 ASSERT(!memcmp(fd_head->data+50,data+5,60));
823 /* This tests the case where some data is missing from one of the fragments.
824 * It should prevent reassembly.
826 static void test_missing_data_fragment_add_seq_next(void)
828 fragment_data *fd_head;
830 printf("Starting test test_missing_data_fragment_add_seq_next\n");
832 /* attempt to add a fragment which is longer than the data available */
834 fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 12, fragment_table,
835 reassembled_table, DATA_LEN-9, TRUE);
837 ASSERT_EQ(1,g_hash_table_size(fragment_table));
838 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
839 ASSERT_NE(NULL,fd_head);
841 /* check the contents of the structure. Reassembly failed so everything
842 * should be null (meaning, just use the original tvb) */
843 ASSERT_EQ(0,fd_head->frame); /* unused */
844 ASSERT_EQ(0,fd_head->offset); /* unused */
845 ASSERT_EQ(0,fd_head->len); /* the length of data we have */
846 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
847 ASSERT_EQ(0,fd_head->reassembled_in);
848 ASSERT_EQ(FD_BLOCKSEQUENCE,fd_head->flags & 0x1ff);
849 ASSERT_EQ(NULL,fd_head->data);
850 ASSERT_EQ(NULL,fd_head->next);
852 /* add another fragment (with all data present) */
854 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
855 reassembled_table, 60, FALSE);
857 /* XXX: it's not clear that this is the right result; however it's what the
860 ASSERT_EQ(1,g_hash_table_size(fragment_table));
861 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
862 ASSERT_EQ(NULL,fd_head);
865 /* check what happens when we revisit the packets */
866 pinfo.fd->flags.visited = TRUE;
869 fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 12, fragment_table,
870 reassembled_table, DATA_LEN-9, TRUE);
872 /* We just look in the reassembled_table for this packet. It never got put
873 * there, so this always returns null.
875 * That's crazy, because it means that the subdissector will see the data
876 * exactly once - on the first pass through the capture (well, assuming it
877 * doesn't bother to check fd_head->reassembled_in); however, that's
878 * what the code does...
880 ASSERT_EQ(1,g_hash_table_size(fragment_table));
881 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
882 ASSERT_EQ(NULL,fd_head);
885 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
886 reassembled_table, 60, FALSE);
887 ASSERT_EQ(1,g_hash_table_size(fragment_table));
888 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
889 ASSERT_EQ(NULL,fd_head);
894 * we're going to do something similar now, but this time it is the second
895 * fragment which has something missing.
897 static void test_missing_data_fragment_add_seq_next_2(void)
899 fragment_data *fd_head;
901 printf("Starting test test_missing_data_fragment_add_seq_next_2\n");
904 fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 24, fragment_table,
905 reassembled_table, 50, TRUE);
907 ASSERT_EQ(1,g_hash_table_size(fragment_table));
908 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
909 ASSERT_EQ(NULL,fd_head);
912 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 24, fragment_table,
913 reassembled_table, DATA_LEN-4, FALSE);
915 /* XXX: again, i'm really dubious about this. Surely this should return all
916 * the data we had, for a best-effort attempt at dissecting it?
917 * And it ought to go into the reassembled table?
919 ASSERT_EQ(0,g_hash_table_size(fragment_table));
920 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
921 ASSERT_EQ(NULL,fd_head);
923 /* check what happens when we revisit the packets */
924 pinfo.fd->flags.visited = TRUE;
927 fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 24, fragment_table,
928 reassembled_table, 50, TRUE);
930 /* As before, this returns NULL because the fragment isn't in the
931 * reassembled_table. At least this is a bit more consistent than before.
933 ASSERT_EQ(0,g_hash_table_size(fragment_table));
934 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
935 ASSERT_EQ(NULL,fd_head);
938 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 24, fragment_table,
939 reassembled_table, DATA_LEN-4, FALSE);
940 ASSERT_EQ(0,g_hash_table_size(fragment_table));
941 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
942 ASSERT_EQ(NULL,fd_head);
947 * This time, our datagram only has one segment, but it has data missing.
949 static void test_missing_data_fragment_add_seq_next_3(void)
951 fragment_data *fd_head;
953 printf("Starting test test_missing_data_fragment_add_seq_next_3\n");
956 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 30, fragment_table,
957 reassembled_table, DATA_LEN-4, FALSE);
959 ASSERT_EQ(0,g_hash_table_size(fragment_table));
960 ASSERT_EQ(1,g_hash_table_size(reassembled_table));
961 ASSERT_NE(NULL,fd_head);
963 /* check the contents of the structure. */
964 ASSERT_EQ(0,fd_head->frame); /* unused */
965 ASSERT_EQ(0,fd_head->offset); /* unused */
966 ASSERT_EQ(0,fd_head->len); /* the length of data we have */
967 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
968 ASSERT_EQ(20,fd_head->reassembled_in);
969 ASSERT_EQ(FD_BLOCKSEQUENCE|FD_DEFRAGMENTED,fd_head->flags);
970 ASSERT_EQ(NULL,fd_head->data);
971 ASSERT_EQ(NULL,fd_head->next);
973 /* revisiting the packet ought to produce the same result. */
974 pinfo.fd->flags.visited = TRUE;
977 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 30, fragment_table,
978 reassembled_table, DATA_LEN-4, FALSE);
980 ASSERT_EQ(0,g_hash_table_size(fragment_table));
981 ASSERT_EQ(1,g_hash_table_size(reassembled_table));
982 ASSERT_NE(NULL,fd_head);
983 ASSERT_EQ(0,fd_head->frame); /* unused */
984 ASSERT_EQ(0,fd_head->offset); /* unused */
985 ASSERT_EQ(0,fd_head->len); /* the length of data we have */
986 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
987 ASSERT_EQ(20,fd_head->reassembled_in);
988 ASSERT_EQ(FD_BLOCKSEQUENCE|FD_DEFRAGMENTED,fd_head->flags);
989 ASSERT_EQ(NULL,fd_head->data);
990 ASSERT_EQ(NULL,fd_head->next);
994 /**********************************************************************************
998 *********************************************************************************/
1000 int main(int argc, char **argv)
1003 char src[] = {1,2,3,4}, dst[] = {5,6,7,8};
1005 void (*tests[])(void) = {
1006 test_simple_fragment_add_seq,
1007 test_fragment_add_seq_partial_reassembly,
1008 test_fragment_add_dcerpc_dg,
1009 test_fragment_add_seq_check,
1010 test_fragment_add_seq_check_1,
1011 test_fragment_add_seq_802_11_0,
1012 test_fragment_add_seq_802_11_1,
1013 test_simple_fragment_add_seq_next,
1014 test_missing_data_fragment_add_seq_next,
1015 test_missing_data_fragment_add_seq_next_2,
1016 test_missing_data_fragment_add_seq_next_3
1019 /* we don't use our params */
1020 argc=argc; argv=argv;
1022 /* initialise stuff */
1027 /* a tvbuff for testing with */
1028 data = g_malloc(DATA_LEN);
1029 /* make sure it's full of stuff */
1030 for(i=0; i<DATA_LEN; i++) {
1033 tvb = tvb_new_real_data(data, DATA_LEN, DATA_LEN*2);
1035 /* other test stuff */
1037 fd.flags.visited = 0;
1038 SET_ADDRESS(&pinfo.src,AT_IPv4,4,src);
1039 SET_ADDRESS(&pinfo.dst,AT_IPv4,4,dst);
1041 /*************************************************************************/
1042 for(i=0; i < sizeof(tests)/sizeof(tests[0]); i++ ) {
1043 /* re-init the fragment tables */
1044 fragment_table_init(&fragment_table);
1045 ASSERT(fragment_table != NULL);
1047 reassembled_table_init(&reassembled_table);
1048 ASSERT(reassembled_table != NULL);
1050 pinfo.fd->flags.visited = FALSE;
1055 printf(failure?"FAILURE\n":"SUCCESS\n");
1060 /* the following are used by packet-mpeg-audio.c; define them here to avoid
1061 * pulling in libwiretap. */
1062 const int mpa_versions[4];
1063 const int mpa_layers[4];
1064 const unsigned mpa_samples[3][3];
1065 const unsigned mpa_bitrates[3][3][16];
1066 const unsigned mpa_frequencies[3][4];
1067 const unsigned mpa_padding[3];
1069 #include "wiretap/file_util.h"
1071 /* these are used by the wiretap file_util stuffs under win32 */
1072 int eth_stdio_stat (const gchar *filename _U_, struct stat *buf _U_)
1075 FILE *eth_stdio_fopen (const gchar *filename _U_, const gchar *mode _U_)
1078 int eth_stdio_mkdir (const gchar *filename _U_, int mode _U_)
1081 int eth_stdio_unlink (const gchar *filename _U_)