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)
56 static int failure = 0;
59 do_test(gboolean condition, const char *format, ...)
67 vfprintf(stderr, format, ap);
71 /* many of the tests assume this routine doesn't return on failure; if we
72 * do, it may provide more information, but may cause a segfault. Uncomment
73 * this line if you wish.
82 static packet_info pinfo;
84 /* fragment_table maps from datagram ids to head of fragment_data list
85 reassembled_table maps from <packet number,datagram id> to head of
87 static GHashTable *fragment_table;
88 static GHashTable *reassembled_table;
90 /**********************************************************************************
94 *********************************************************************************/
96 /* Simple test case for fragment_add_seq.
97 * Adds three fragments (out of order, with one for a different datagram in between),
98 * and checks that they are reassembled correctly.
101 test_simple_fragment_add_seq(void)
103 fragment_data *fd_head, *fdh0;
105 printf("Starting test test_simple_fragment_add_seq\n");
108 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
111 ASSERT_EQ(1,g_hash_table_size(fragment_table));
112 ASSERT_EQ(NULL,fd_head);
114 /* adding the same fragment again should do nothing, even with different
116 pinfo.fd->flags.visited = 1;
117 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
119 ASSERT_EQ(1,g_hash_table_size(fragment_table));
120 ASSERT_EQ(NULL,fd_head);
122 /* start another pdu (just to confuse things) */
123 pinfo.fd->flags.visited = 0;
125 fd_head=fragment_add_seq(tvb, 15, &pinfo, 13, fragment_table,
127 ASSERT_EQ(2,g_hash_table_size(fragment_table));
128 ASSERT_EQ(NULL,fd_head);
130 /* now we add the terminal fragment of the first datagram */
132 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
135 /* we haven't got all the fragments yet ... */
136 ASSERT_EQ(2,g_hash_table_size(fragment_table));
137 ASSERT_EQ(NULL,fd_head);
139 /* finally, add the missing fragment */
141 fd_head=fragment_add_seq(tvb, 15, &pinfo, 12, fragment_table,
144 ASSERT_EQ(2,g_hash_table_size(fragment_table));
145 ASSERT_NE(NULL,fd_head);
147 /* check the contents of the structure */
148 ASSERT_EQ(0,fd_head->frame); /* unused */
149 ASSERT_EQ(0,fd_head->offset); /* unused */
150 ASSERT_EQ(170,fd_head->len); /* the length of data we have */
151 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
152 ASSERT_EQ(4,fd_head->reassembled_in);
153 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
154 ASSERT_NE(NULL,fd_head->data);
155 ASSERT_NE(NULL,fd_head->next);
157 ASSERT_EQ(1,fd_head->next->frame);
158 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
159 ASSERT_EQ(50,fd_head->next->len); /* segment length */
160 ASSERT_EQ(0,fd_head->next->flags);
161 ASSERT_EQ(NULL,fd_head->next->data);
162 ASSERT_NE(NULL,fd_head->next->next);
164 ASSERT_EQ(4,fd_head->next->next->frame);
165 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
166 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
167 ASSERT_EQ(0,fd_head->next->next->flags);
168 ASSERT_EQ(NULL,fd_head->next->next->data);
169 ASSERT_NE(NULL,fd_head->next->next->next);
171 ASSERT_EQ(3,fd_head->next->next->next->frame);
172 ASSERT_EQ(2,fd_head->next->next->next->offset); /* seqno */
173 ASSERT_EQ(60,fd_head->next->next->next->len); /* segment length */
174 ASSERT_EQ(0,fd_head->next->next->next->flags);
175 ASSERT_EQ(NULL,fd_head->next->next->next->data);
176 ASSERT_EQ(NULL,fd_head->next->next->next->next);
178 /* test the actual reassembly */
179 ASSERT(!memcmp(fd_head->data,data+10,50));
180 ASSERT(!memcmp(fd_head->data+50,data+15,60));
181 ASSERT(!memcmp(fd_head->data+110,data+5,60));
183 /* what happens if we revisit the packets now? */
185 pinfo.fd->flags.visited = 1;
187 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
190 * this api relies on the caller to check fd_head -> reassembled_in
192 * Redoing all the tests seems like overkill - just check the pointer
194 ASSERT_EQ(fdh0,fd_head);
197 fd_head=fragment_add_seq(tvb, 5, &pinfo, 12, fragment_table,
199 ASSERT_EQ(fdh0,fd_head);
202 fd_head=fragment_add_seq(tvb, 15, &pinfo, 12, fragment_table,
204 ASSERT_EQ(fdh0,fd_head);
207 /* XXX ought to have some tests for overlapping fragments */
209 /* This tests the functionality of fragment_set_partial_reassembly for
210 * FD_BLOCKSEQUENCE reassembly.
212 * We add a sequence of fragments thus:
213 * seqno frame offset len (initial) more_frags
214 * ----- ----- ------ --- --------------------
217 * 1 3 0 40 true (a duplicate fragment)
222 test_fragment_add_seq_partial_reassembly(void)
224 fragment_data *fd_head, *fd;
226 printf("Starting test test_fragment_add_seq_partial_reassembly\n");
228 /* generally it's probably fair to assume that we will be called with
232 fd_head=fragment_add_seq(tvb, 10, &pinfo, 12, fragment_table,
235 ASSERT_EQ(1,g_hash_table_size(fragment_table));
236 ASSERT_NE(NULL,fd_head);
238 /* check the contents of the structure */
239 ASSERT_EQ(0,fd_head->frame); /* unused */
240 ASSERT_EQ(0,fd_head->offset); /* unused */
241 ASSERT_EQ(50,fd_head->len); /* the length of data we have */
242 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
243 ASSERT_EQ(1,fd_head->reassembled_in);
244 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
245 ASSERT_NE(NULL,fd_head->data);
246 ASSERT_NE(NULL,fd_head->next);
248 ASSERT_EQ(1,fd_head->next->frame);
249 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
250 ASSERT_EQ(50,fd_head->next->len); /* segment length */
251 ASSERT_EQ(0,fd_head->next->flags);
252 ASSERT_EQ(NULL,fd_head->next->data);
253 ASSERT_EQ(NULL,fd_head->next->next);
255 /* test the actual reassembly */
256 ASSERT(!memcmp(fd_head->data,data+10,50));
258 /* now we announce that the reassembly wasn't complete after all. */
259 fragment_set_partial_reassembly(&pinfo,12,fragment_table);
261 /* and add another segment. To mix things up slightly (and so that we can
262 * check on the state of things), we're going to set the more_frags flag
266 fd_head=fragment_add_seq(tvb, 0, &pinfo, 12, fragment_table,
269 ASSERT_EQ(1,g_hash_table_size(fragment_table));
270 ASSERT_EQ(NULL,fd_head);
272 fd_head=fragment_get(&pinfo,12,fragment_table);
273 ASSERT_NE(NULL,fd_head);
275 /* check the contents of the structure */
276 ASSERT_EQ(0,fd_head->frame); /* unused */
277 ASSERT_EQ(0,fd_head->offset); /* unused */
278 /* ASSERT_EQ(50,fd_head->len); the length of data we have */
279 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
280 ASSERT_EQ(0,fd_head->reassembled_in);
281 ASSERT_EQ(FD_BLOCKSEQUENCE,fd_head->flags);
282 ASSERT_NE(NULL,fd_head->data);
283 ASSERT_NE(NULL,fd_head->next);
286 ASSERT_EQ(1,fd->frame);
287 ASSERT_EQ(0,fd->offset); /* seqno */
288 ASSERT_EQ(50,fd->len); /* segment length */
289 ASSERT_EQ(FD_NOT_MALLOCED,fd->flags);
290 ASSERT_EQ(fd_head->data,fd->data);
291 ASSERT_NE(NULL,fd->next);
294 ASSERT_EQ(2,fd->frame);
295 ASSERT_EQ(1,fd->offset); /* seqno */
296 ASSERT_EQ(40,fd->len); /* segment length */
297 ASSERT_EQ(0,fd->flags);
298 ASSERT_NE(NULL,fd->data);
299 ASSERT_EQ(NULL,fd->next);
301 /* Another copy of the second segment.
304 fd_head=fragment_add_seq(tvb, 0, &pinfo, 12, fragment_table,
307 ASSERT_EQ(1,g_hash_table_size(fragment_table));
308 ASSERT_EQ(NULL,fd_head);
309 fd_head=fragment_get(&pinfo,12,fragment_table);
310 ASSERT_NE(NULL,fd_head);
311 ASSERT_EQ(0,fd_head->frame); /* unused */
312 ASSERT_EQ(0,fd_head->offset); /* unused */
313 /* ASSERT_EQ(50,fd_head->len); the length of data we have */
314 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
315 ASSERT_EQ(0,fd_head->reassembled_in);
316 ASSERT_EQ(FD_BLOCKSEQUENCE,fd_head->flags);
317 ASSERT_NE(NULL,fd_head->data);
318 ASSERT_NE(NULL,fd_head->next);
321 ASSERT_EQ(1,fd->frame);
322 ASSERT_EQ(0,fd->offset); /* seqno */
323 ASSERT_EQ(50,fd->len); /* segment length */
324 ASSERT_EQ(FD_NOT_MALLOCED,fd->flags);
325 ASSERT_EQ(fd_head->data,fd->data);
326 ASSERT_NE(NULL,fd->next);
329 ASSERT_EQ(2,fd->frame);
330 ASSERT_EQ(1,fd->offset); /* seqno */
331 ASSERT_EQ(40,fd->len); /* segment length */
332 ASSERT_EQ(0,fd->flags);
333 ASSERT_NE(NULL,fd->data);
334 ASSERT_NE(NULL,fd->next);
337 ASSERT_EQ(3,fd->frame);
338 ASSERT_EQ(1,fd->offset); /* seqno */
339 ASSERT_EQ(40,fd->len); /* segment length */
340 ASSERT_EQ(0,fd->flags);
341 ASSERT_NE(NULL,fd->data);
342 ASSERT_EQ(NULL,fd->next);
346 /* have another go at wrapping things up */
348 fd_head=fragment_add_seq(tvb, 20, &pinfo, 12, fragment_table,
351 ASSERT_EQ(1,g_hash_table_size(fragment_table));
352 ASSERT_NE(NULL,fd_head);
354 /* check the contents of the structure */
355 ASSERT_EQ(0,fd_head->frame); /* unused */
356 ASSERT_EQ(0,fd_head->offset); /* unused */
357 ASSERT_EQ(190,fd_head->len); /* the length of data we have */
358 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
359 ASSERT_EQ(4,fd_head->reassembled_in);
360 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
361 ASSERT_NE(NULL,fd_head->data);
362 ASSERT_NE(NULL,fd_head->next);
365 ASSERT_EQ(1,fd->frame);
366 ASSERT_EQ(0,fd->offset); /* seqno */
367 ASSERT_EQ(50,fd->len); /* segment length */
368 ASSERT_EQ(0,fd->flags);
369 ASSERT_EQ(NULL,fd->data);
370 ASSERT_NE(NULL,fd->next);
373 ASSERT_EQ(2,fd->frame);
374 ASSERT_EQ(1,fd->offset); /* seqno */
375 ASSERT_EQ(40,fd->len); /* segment length */
376 ASSERT_EQ(0,fd->flags);
377 ASSERT_EQ(NULL,fd->data);
378 ASSERT_NE(NULL,fd->next);
381 ASSERT_EQ(3,fd->frame);
382 ASSERT_EQ(1,fd->offset); /* seqno */
383 ASSERT_EQ(40,fd->len); /* segment length */
384 ASSERT_EQ(FD_OVERLAP,fd->flags);
385 ASSERT_EQ(NULL,fd->data);
386 ASSERT_NE(NULL,fd->next);
389 ASSERT_EQ(4,fd->frame);
390 ASSERT_EQ(2,fd->offset); /* seqno */
391 ASSERT_EQ(100,fd->len); /* segment length */
392 ASSERT_EQ(0,fd->flags);
393 ASSERT_EQ(NULL,fd->data);
394 ASSERT_EQ(NULL,fd->next);
396 /* test the actual reassembly */
397 ASSERT(!memcmp(fd_head->data,data+10,50));
398 ASSERT(!memcmp(fd_head->data+50,data,40));
399 ASSERT(!memcmp(fd_head->data+90,data+20,100));
402 /* do it again (this time it is more complicated, with an overlap in the
405 fragment_set_partial_reassembly(&pinfo,12,fragment_table);
408 fd_head=fragment_add_seq(tvb, 0, &pinfo, 12, fragment_table,
411 fd_head=fragment_get(&pinfo,12,fragment_table);
412 ASSERT_NE(NULL,fd_head);
413 ASSERT_EQ(0,fd_head->frame); /* unused */
414 ASSERT_EQ(0,fd_head->offset); /* unused */
415 ASSERT_EQ(230,fd_head->len); /* the length of data we have */
416 ASSERT_EQ(3,fd_head->datalen); /* seqno of the last fragment we have */
417 ASSERT_EQ(5,fd_head->reassembled_in);
418 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,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(0,fd->flags);
427 ASSERT_EQ(NULL,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_EQ(NULL,fd->data);
436 ASSERT_NE(NULL,fd->next);
439 ASSERT_EQ(3,fd->frame);
440 ASSERT_EQ(1,fd->offset); /* seqno */
441 ASSERT_EQ(40,fd->len); /* segment length */
442 ASSERT_EQ(FD_OVERLAP,fd->flags);
443 ASSERT_EQ(NULL,fd->data);
444 ASSERT_NE(NULL,fd->next);
447 ASSERT_EQ(4,fd->frame);
448 ASSERT_EQ(2,fd->offset); /* seqno */
449 ASSERT_EQ(100,fd->len); /* segment length */
450 ASSERT_EQ(0,fd->flags);
451 ASSERT_EQ(NULL,fd->data);
452 ASSERT_NE(NULL,fd->next);
455 ASSERT_EQ(5,fd->frame);
456 ASSERT_EQ(3,fd->offset); /* seqno */
457 ASSERT_EQ(40,fd->len); /* segment length */
458 ASSERT_EQ(0,fd->flags);
459 ASSERT_EQ(NULL,fd->data);
460 ASSERT_EQ(NULL,fd->next);
462 /* test the actual reassembly */
463 ASSERT(!memcmp(fd_head->data,data+10,50));
464 ASSERT(!memcmp(fd_head->data+50,data,40));
465 ASSERT(!memcmp(fd_head->data+90,data+20,100));
466 ASSERT(!memcmp(fd_head->data+190,data,40));
469 /**********************************************************************************
471 * fragment_add_dcerpc_dg
473 *********************************************************************************/
475 /* This can afford to be reasonably minimal, as it's just the same logic with a
476 * different hash key to fragment_add_seq
479 test_fragment_add_dcerpc_dg(void)
481 e_uuid_t act_id = {1,2,3,{4,5,6,7,8,9,10,11}};
483 fragment_data *fd_head, *fdh0;
484 GHashTable *fragment_table = NULL;
486 printf("Starting test test_fragment_add_dcerpc_dg\n");
488 /* we need our own fragment table */
489 dcerpc_fragment_table_init(&fragment_table);
490 fd_head=fragment_add_dcerpc_dg(tvb, 10, &pinfo, 12, &act_id, fragment_table,
493 ASSERT_EQ(1,g_hash_table_size(fragment_table));
494 ASSERT_EQ(NULL,fd_head);
496 /* start another pdu (just to confuse things) */
498 fd_head=fragment_add_dcerpc_dg(tvb, 15, &pinfo, 13, &act_id, fragment_table,
500 ASSERT_EQ(2,g_hash_table_size(fragment_table));
501 ASSERT_EQ(NULL,fd_head);
503 /* another pdu, with the same fragment_id, but a different act_id, to the
507 fd_head=fragment_add_dcerpc_dg(tvb, 15, &pinfo, 12, &act_id, fragment_table,
509 ASSERT_EQ(3,g_hash_table_size(fragment_table));
510 ASSERT_EQ(NULL,fd_head);
513 /* now we add the terminal fragment of the first datagram */
515 fd_head=fragment_add_dcerpc_dg(tvb, 5, &pinfo, 12, &act_id, fragment_table,
518 ASSERT_EQ(3,g_hash_table_size(fragment_table));
519 ASSERT_NE(NULL,fd_head);
521 /* check the contents of the structure */
522 ASSERT_EQ(0,fd_head->frame); /* unused */
523 ASSERT_EQ(0,fd_head->offset); /* unused */
524 ASSERT_EQ(110,fd_head->len); /* the length of data we have */
525 ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */
526 ASSERT_EQ(4,fd_head->reassembled_in);
527 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
528 ASSERT_NE(NULL,fd_head->data);
529 ASSERT_NE(NULL,fd_head->next);
531 /* test the actual reassembly */
532 ASSERT(!memcmp(fd_head->data,data+10,50));
533 ASSERT(!memcmp(fd_head->data+50,data+5,60));
535 /* what happens if we revisit the packets now? */
537 pinfo.fd->flags.visited = 1;
539 fd_head=fragment_add_dcerpc_dg(tvb, 10, &pinfo, 12, &act_id, fragment_table,
542 * this api relies on the caller to check fd_head -> reassembled_in
544 * Redoing all the tests seems like overkill - just check the pointer
546 ASSERT_EQ(fdh0,fd_head);
549 /**********************************************************************************
551 * fragment_add_seq_check
553 *********************************************************************************/
556 /* This routine is used for both fragment_add_seq_802_11 and
557 * fragment_add_seq_check.
559 * Adds a couple of out-of-order fragments and checks their reassembly.
562 test_fragment_add_seq_check_work(fragment_data *(*fn)(tvbuff_t *, const int,
563 const packet_info *, const guint32, GHashTable *,
564 GHashTable *, const guint32, const guint32, const gboolean))
566 fragment_data *fd_head;
569 fd_head=fn(tvb, 10, &pinfo, 12, fragment_table,
570 reassembled_table, 0, 50, TRUE);
572 ASSERT_EQ(1,g_hash_table_size(fragment_table));
573 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
574 ASSERT_EQ(NULL,fd_head);
576 /* start another pdu (just to confuse things) */
578 fd_head=fn(tvb, 15, &pinfo, 13, fragment_table,
579 reassembled_table, 0, 60, TRUE);
580 ASSERT_EQ(2,g_hash_table_size(fragment_table));
581 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
582 ASSERT_EQ(NULL,fd_head);
584 /* add the terminal fragment of the first datagram */
586 fd_head=fn(tvb, 5, &pinfo, 12, fragment_table,
587 reassembled_table, 2, 60, FALSE);
589 /* we haven't got all the fragments yet ... */
590 ASSERT_EQ(2,g_hash_table_size(fragment_table));
591 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
592 ASSERT_EQ(NULL,fd_head);
594 /* finally, add the missing fragment */
596 fd_head=fn(tvb, 15, &pinfo, 12, fragment_table,
597 reassembled_table, 1, 60, TRUE);
599 ASSERT_EQ(1,g_hash_table_size(fragment_table));
600 ASSERT_EQ(3,g_hash_table_size(reassembled_table));
601 ASSERT_NE(NULL,fd_head);
603 /* check the contents of the structure */
604 ASSERT_EQ(0,fd_head->frame); /* unused */
605 ASSERT_EQ(0,fd_head->offset); /* unused */
606 ASSERT_EQ(170,fd_head->len); /* the length of data we have */
607 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
608 ASSERT_EQ(4,fd_head->reassembled_in);
609 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
610 ASSERT_NE(NULL,fd_head->data);
611 ASSERT_NE(NULL,fd_head->next);
613 ASSERT_EQ(1,fd_head->next->frame);
614 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
615 ASSERT_EQ(50,fd_head->next->len); /* segment length */
616 ASSERT_EQ(0,fd_head->next->flags);
617 ASSERT_EQ(NULL,fd_head->next->data);
618 ASSERT_NE(NULL,fd_head->next->next);
620 ASSERT_EQ(4,fd_head->next->next->frame);
621 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
622 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
623 ASSERT_EQ(0,fd_head->next->next->flags);
624 ASSERT_EQ(NULL,fd_head->next->next->data);
625 ASSERT_NE(NULL,fd_head->next->next->next);
627 ASSERT_EQ(3,fd_head->next->next->next->frame);
628 ASSERT_EQ(2,fd_head->next->next->next->offset); /* seqno */
629 ASSERT_EQ(60,fd_head->next->next->next->len); /* segment length */
630 ASSERT_EQ(0,fd_head->next->next->next->flags);
631 ASSERT_EQ(NULL,fd_head->next->next->next->data);
632 ASSERT_EQ(NULL,fd_head->next->next->next->next);
634 /* test the actual reassembly */
635 ASSERT(!memcmp(fd_head->data,data+10,50));
636 ASSERT(!memcmp(fd_head->data+50,data+15,60));
637 ASSERT(!memcmp(fd_head->data+110,data+5,60));
640 /* Simple test case for fragment_add_seq_check
643 test_fragment_add_seq_check(void)
645 printf("Starting test test_fragment_add_seq_check\n");
647 test_fragment_add_seq_check_work(fragment_add_seq_check);
651 /* This tests the case that the 802.11 hack does something different for: when
652 * the terminal segment in a fragmented datagram arrives first.
655 test_fragment_add_seq_check_1(void)
657 fragment_data *fd_head;
659 printf("Starting test test_fragment_add_seq_check_1\n");
662 fd_head=fragment_add_seq_check(tvb, 10, &pinfo, 12, fragment_table,
663 reassembled_table, 1, 50, FALSE);
665 ASSERT_EQ(1,g_hash_table_size(fragment_table));
666 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
667 ASSERT_EQ(NULL,fd_head);
669 /* Now add the missing segment */
671 fd_head=fragment_add_seq_check(tvb, 5, &pinfo, 12, fragment_table,
672 reassembled_table, 0, 60, TRUE);
674 ASSERT_EQ(0,g_hash_table_size(fragment_table));
675 ASSERT_EQ(2,g_hash_table_size(reassembled_table));
676 ASSERT_NE(NULL,fd_head);
678 /* check the contents of the structure */
679 ASSERT_EQ(0,fd_head->frame); /* unused */
680 ASSERT_EQ(0,fd_head->offset); /* unused */
681 ASSERT_EQ(110,fd_head->len); /* the length of data we have */
682 ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */
683 ASSERT_EQ(2,fd_head->reassembled_in);
684 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
685 ASSERT_NE(NULL,fd_head->data);
686 ASSERT_NE(NULL,fd_head->next);
688 ASSERT_EQ(2,fd_head->next->frame);
689 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
690 ASSERT_EQ(60,fd_head->next->len); /* segment length */
691 ASSERT_EQ(0,fd_head->next->flags);
692 ASSERT_EQ(NULL,fd_head->next->data);
693 ASSERT_NE(NULL,fd_head->next->next);
695 ASSERT_EQ(1,fd_head->next->next->frame);
696 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
697 ASSERT_EQ(50,fd_head->next->next->len); /* segment length */
698 ASSERT_EQ(0,fd_head->next->next->flags);
699 ASSERT_EQ(NULL,fd_head->next->next->data);
700 ASSERT_EQ(NULL,fd_head->next->next->next);
702 /* test the actual reassembly */
703 ASSERT(!memcmp(fd_head->data,data+5,60));
704 ASSERT(!memcmp(fd_head->data+60,data+10,50));
707 /**********************************************************************************
709 * fragment_add_seq_802_11
711 *********************************************************************************/
713 /* Tests the 802.11 hack.
716 test_fragment_add_seq_802_11_0(void)
718 fragment_data *fd_head;
720 printf("Starting test test_fragment_add_seq_802_11_0\n");
722 /* the 802.11 hack is that some non-fragmented datagrams have non-zero
723 * fragment_number; test for this. */
726 fd_head=fragment_add_seq_802_11(tvb, 10, &pinfo, 12, fragment_table,
727 reassembled_table, 10, 50, FALSE);
729 ASSERT_EQ(0,g_hash_table_size(fragment_table));
730 ASSERT_EQ(1,g_hash_table_size(reassembled_table));
731 ASSERT_NE(NULL,fd_head);
733 /* check the contents of the structure */
734 ASSERT_EQ(0,fd_head->frame); /* unused */
735 ASSERT_EQ(0,fd_head->offset); /* unused */
736 ASSERT_EQ(0,fd_head->len); /* unused */
737 ASSERT_EQ(0,fd_head->datalen); /* unused */
738 ASSERT_EQ(1,fd_head->reassembled_in);
739 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE,fd_head->flags);
740 ASSERT_EQ(NULL,fd_head->data);
741 ASSERT_EQ(NULL,fd_head->next);
744 /* Reuse the fragment_add_seq_check testcases */
745 static void test_fragment_add_seq_802_11_1(void)
747 printf("Starting test test_fragment_add_seq_802_11_1\n");
748 test_fragment_add_seq_check_work(fragment_add_seq_802_11);
751 /**********************************************************************************
753 * fragment_add_seq_next
755 *********************************************************************************/
757 /* Simple test case for fragment_add_seq_next.
758 * Adds a couple of fragments (with one for a different datagram in between),
759 * and checks that they are reassembled correctly.
762 test_simple_fragment_add_seq_next(void)
764 fragment_data *fd_head;
766 printf("Starting test test_simple_fragment_add_seq_next\n");
769 fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 12, fragment_table,
770 reassembled_table, 50, TRUE);
772 ASSERT_EQ(1,g_hash_table_size(fragment_table));
773 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
774 ASSERT_EQ(NULL,fd_head);
776 /* adding the same fragment again should do nothing, even with different
778 pinfo.fd->flags.visited = 1;
779 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
780 reassembled_table, 60, TRUE);
781 ASSERT_EQ(1,g_hash_table_size(fragment_table));
782 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
783 ASSERT_EQ(NULL,fd_head);
785 /* start another pdu (just to confuse things) */
786 pinfo.fd->flags.visited = 0;
788 fd_head=fragment_add_seq_next(tvb, 15, &pinfo, 13, fragment_table,
789 reassembled_table, 60, TRUE);
790 ASSERT_EQ(2,g_hash_table_size(fragment_table));
791 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
792 ASSERT_EQ(NULL,fd_head);
795 /* now we add the terminal fragment of the first datagram */
797 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
798 reassembled_table, 60, FALSE);
800 ASSERT_EQ(1,g_hash_table_size(fragment_table));
801 ASSERT_EQ(2,g_hash_table_size(reassembled_table));
802 ASSERT_NE(NULL,fd_head);
804 /* check the contents of the structure */
805 ASSERT_EQ(0,fd_head->frame); /* unused */
806 ASSERT_EQ(0,fd_head->offset); /* unused */
807 ASSERT_EQ(110,fd_head->len); /* the length of data we have */
808 ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */
809 ASSERT_EQ(3,fd_head->reassembled_in);
810 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
811 ASSERT_NE(NULL,fd_head->data);
812 ASSERT_NE(NULL,fd_head->next);
814 ASSERT_EQ(1,fd_head->next->frame);
815 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
816 ASSERT_EQ(50,fd_head->next->len); /* segment length */
817 ASSERT_EQ(0,fd_head->next->flags);
818 ASSERT_EQ(NULL,fd_head->next->data);
819 ASSERT_NE(NULL,fd_head->next->next);
821 ASSERT_EQ(3,fd_head->next->next->frame);
822 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
823 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
824 ASSERT_EQ(0,fd_head->next->next->flags);
825 ASSERT_EQ(NULL,fd_head->next->next->data);
826 ASSERT_EQ(NULL,fd_head->next->next->next);
828 /* test the actual reassembly */
829 ASSERT(!memcmp(fd_head->data,data+10,50));
830 ASSERT(!memcmp(fd_head->data+50,data+5,60));
834 /* This tests the case where some data is missing from one of the fragments.
835 * It should prevent reassembly.
838 test_missing_data_fragment_add_seq_next(void)
840 fragment_data *fd_head;
842 printf("Starting test test_missing_data_fragment_add_seq_next\n");
844 /* attempt to add a fragment which is longer than the data available */
846 fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 12, fragment_table,
847 reassembled_table, DATA_LEN-9, TRUE);
849 ASSERT_EQ(1,g_hash_table_size(fragment_table));
850 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
851 ASSERT_NE(NULL,fd_head);
853 /* check the contents of the structure. Reassembly failed so everything
854 * should be null (meaning, just use the original tvb) */
855 ASSERT_EQ(0,fd_head->frame); /* unused */
856 ASSERT_EQ(0,fd_head->offset); /* unused */
857 ASSERT_EQ(0,fd_head->len); /* the length of data we have */
858 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
859 ASSERT_EQ(0,fd_head->reassembled_in);
860 ASSERT_EQ(FD_BLOCKSEQUENCE,fd_head->flags & 0x1ff);
861 ASSERT_EQ(NULL,fd_head->data);
862 ASSERT_EQ(NULL,fd_head->next);
864 /* add another fragment (with all data present) */
866 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
867 reassembled_table, 60, FALSE);
869 /* XXX: it's not clear that this is the right result; however it's what the
872 ASSERT_EQ(1,g_hash_table_size(fragment_table));
873 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
874 ASSERT_EQ(NULL,fd_head);
877 /* check what happens when we revisit the packets */
878 pinfo.fd->flags.visited = TRUE;
881 fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 12, fragment_table,
882 reassembled_table, DATA_LEN-9, TRUE);
884 /* We just look in the reassembled_table for this packet. It never got put
885 * there, so this always returns null.
887 * That's crazy, because it means that the subdissector will see the data
888 * exactly once - on the first pass through the capture (well, assuming it
889 * doesn't bother to check fd_head->reassembled_in); however, that's
890 * what the code does...
892 ASSERT_EQ(1,g_hash_table_size(fragment_table));
893 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
894 ASSERT_EQ(NULL,fd_head);
897 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 12, fragment_table,
898 reassembled_table, 60, FALSE);
899 ASSERT_EQ(1,g_hash_table_size(fragment_table));
900 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
901 ASSERT_EQ(NULL,fd_head);
906 * we're going to do something similar now, but this time it is the second
907 * fragment which has something missing.
910 test_missing_data_fragment_add_seq_next_2(void)
912 fragment_data *fd_head;
914 printf("Starting test test_missing_data_fragment_add_seq_next_2\n");
917 fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 24, fragment_table,
918 reassembled_table, 50, TRUE);
920 ASSERT_EQ(1,g_hash_table_size(fragment_table));
921 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
922 ASSERT_EQ(NULL,fd_head);
925 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 24, fragment_table,
926 reassembled_table, DATA_LEN-4, FALSE);
928 /* XXX: again, i'm really dubious about this. Surely this should return all
929 * the data we had, for a best-effort attempt at dissecting it?
930 * And it ought to go into the reassembled table?
932 ASSERT_EQ(0,g_hash_table_size(fragment_table));
933 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
934 ASSERT_EQ(NULL,fd_head);
936 /* check what happens when we revisit the packets */
937 pinfo.fd->flags.visited = TRUE;
940 fd_head=fragment_add_seq_next(tvb, 10, &pinfo, 24, fragment_table,
941 reassembled_table, 50, TRUE);
943 /* As before, this returns NULL because the fragment isn't in the
944 * reassembled_table. At least this is a bit more consistent than before.
946 ASSERT_EQ(0,g_hash_table_size(fragment_table));
947 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
948 ASSERT_EQ(NULL,fd_head);
951 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 24, fragment_table,
952 reassembled_table, DATA_LEN-4, FALSE);
953 ASSERT_EQ(0,g_hash_table_size(fragment_table));
954 ASSERT_EQ(0,g_hash_table_size(reassembled_table));
955 ASSERT_EQ(NULL,fd_head);
960 * This time, our datagram only has one segment, but it has data missing.
963 test_missing_data_fragment_add_seq_next_3(void)
965 fragment_data *fd_head;
967 printf("Starting test test_missing_data_fragment_add_seq_next_3\n");
970 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 30, fragment_table,
971 reassembled_table, DATA_LEN-4, FALSE);
973 ASSERT_EQ(0,g_hash_table_size(fragment_table));
974 ASSERT_EQ(1,g_hash_table_size(reassembled_table));
975 ASSERT_NE(NULL,fd_head);
977 /* check the contents of the structure. */
978 ASSERT_EQ(0,fd_head->frame); /* unused */
979 ASSERT_EQ(0,fd_head->offset); /* unused */
980 ASSERT_EQ(0,fd_head->len); /* the length of data we have */
981 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
982 ASSERT_EQ(20,fd_head->reassembled_in);
983 ASSERT_EQ(FD_BLOCKSEQUENCE|FD_DEFRAGMENTED,fd_head->flags);
984 ASSERT_EQ(NULL,fd_head->data);
985 ASSERT_EQ(NULL,fd_head->next);
987 /* revisiting the packet ought to produce the same result. */
988 pinfo.fd->flags.visited = TRUE;
991 fd_head=fragment_add_seq_next(tvb, 5, &pinfo, 30, fragment_table,
992 reassembled_table, DATA_LEN-4, FALSE);
994 ASSERT_EQ(0,g_hash_table_size(fragment_table));
995 ASSERT_EQ(1,g_hash_table_size(reassembled_table));
996 ASSERT_NE(NULL,fd_head);
997 ASSERT_EQ(0,fd_head->frame); /* unused */
998 ASSERT_EQ(0,fd_head->offset); /* unused */
999 ASSERT_EQ(0,fd_head->len); /* the length of data we have */
1000 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
1001 ASSERT_EQ(20,fd_head->reassembled_in);
1002 ASSERT_EQ(FD_BLOCKSEQUENCE|FD_DEFRAGMENTED,fd_head->flags);
1003 ASSERT_EQ(NULL,fd_head->data);
1004 ASSERT_EQ(NULL,fd_head->next);
1008 /**********************************************************************************
1012 *********************************************************************************/
1015 main(int argc _U_, char **argv _U_)
1018 char src[] = {1,2,3,4}, dst[] = {5,6,7,8};
1020 void (*tests[])(void) = {
1021 test_simple_fragment_add_seq,
1022 test_fragment_add_seq_partial_reassembly,
1023 test_fragment_add_dcerpc_dg,
1024 test_fragment_add_seq_check,
1025 test_fragment_add_seq_check_1,
1026 test_fragment_add_seq_802_11_0,
1027 test_fragment_add_seq_802_11_1,
1028 test_simple_fragment_add_seq_next,
1029 test_missing_data_fragment_add_seq_next,
1030 test_missing_data_fragment_add_seq_next_2,
1031 test_missing_data_fragment_add_seq_next_3
1034 /* initialise stuff */
1039 /* a tvbuff for testing with */
1040 data = g_malloc(DATA_LEN);
1041 /* make sure it's full of stuff */
1042 for(i=0; i<DATA_LEN; i++) {
1045 tvb = tvb_new_real_data(data, DATA_LEN, DATA_LEN*2);
1047 /* other test stuff */
1049 fd.flags.visited = 0;
1050 SET_ADDRESS(&pinfo.src,AT_IPv4,4,src);
1051 SET_ADDRESS(&pinfo.dst,AT_IPv4,4,dst);
1053 /*************************************************************************/
1054 for(i=0; i < sizeof(tests)/sizeof(tests[0]); i++ ) {
1055 /* re-init the fragment tables */
1056 fragment_table_init(&fragment_table);
1057 ASSERT(fragment_table != NULL);
1059 reassembled_table_init(&reassembled_table);
1060 ASSERT(reassembled_table != NULL);
1062 pinfo.fd->flags.visited = FALSE;
1067 printf(failure?"FAILURE\n":"SUCCESS\n");
1073 void add_new_data_source(packet_info *pinfo _U_, tvbuff_t *tvb _U_,
1074 const char *name _U_)
1078 proto_tree_add_uint(proto_tree *tree _U_, int hfindex _U_, tvbuff_t *tvb _U_,
1079 gint start _U_, gint length _U_, guint32 value _U_)
1082 void proto_item_prepend_text(proto_item *ti _U_, const char *format _U_, ...)
1085 void proto_item_append_text(proto_item *ti _U_, const char *format _U_, ...)
1088 proto_item *proto_tree_add_uint_format(proto_tree *tree _U_, int hfindex _U_,
1089 tvbuff_t *tvb _U_, gint start _U_,
1090 gint length _U_, guint32 value _U_,
1091 const char *format _U_, ...)
1094 proto_tree* proto_item_add_subtree(proto_item *ti _U_, const gint idx _U_)
1097 proto_item *proto_tree_add_boolean(proto_tree *tree _U_, int hfindex _U_,
1098 tvbuff_t *tvb _U_, gint start _U_,
1099 gint length _U_, guint32 value _U_)
1102 proto_item *proto_tree_add_item(proto_tree *tree _U_, const int hfindex _U_,
1103 tvbuff_t *tvb _U_, const gint start _U_,
1105 const guint encoding _U_)
1108 gint check_col(column_info *cinfo _U_, const gint col _U_)
1111 void col_add_fstr(column_info *cinfo _U_, const gint col _U_, const gchar *format _U_,
1115 const char* proto_registrar_get_name(const int n _U_)
1118 void proto_item_set_text(proto_item *ti _U_, const char *format _U_, ...)