HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / reassemble_test.c
blobafa3a3f3af5b97ad8f0799194275ec010624094b
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.
9 * December 2010:
10 * 1. reassemble_test can be run under valgrind to detect any memory leaks in the
11 * Wireshark reassembly code.
12 * Specifically: code has been added to free dynamically allocated memory
13 * after each test (or at program completion) so that valgrind will report
14 * only actual memory leaks.
15 * The following command can be used to run reassemble_test under valgrind:
16 * env \
17 * G_DEBUG=gc-friendly \
18 * G_SLICE=always-malloc \
19 * WIRESHARK_DEBUG_EP_NO_CHUNKS=1 \
20 * WIRESHARK_DEBUG_SE_NO_CHUNKS=1 \
21 * WIRESHARK_DEBUG_SE_USE_CANARY=1 \
22 * WIRESHARK_EP_VERIFY_POINTERS=1 \
23 * WIRESHARK_SE_VERIFY_POINTERS=1 \
24 * valgrind --leak-check=full --show-reachable=yes ./reassemble_test
26 * 2. Debug functions have been added which will print information
27 * about the fd-chains associated with the fragment_table and the
28 * reassembled table.
29 * #define debug to enable the code.
31 * $Id$
33 * Copyright (c) 2007 MX Telecom Ltd. <richardv@mxtelecom.com>
35 * Wireshark - Network traffic analyzer
36 * By Gerald Combs <gerald@wireshark.org>
37 * Copyright 1998
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.
54 #include <stdarg.h>
55 #include <stdlib.h>
56 #include <stdio.h>
57 #include <string.h>
59 #include <glib.h>
61 #include "config.h"
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 #define ASSERT(b) do_test((b),"Assertion failed at line %i: %s\n", __LINE__, #b)
71 #define ASSERT_EQ(exp,act) do_test((exp)==(act),"Assertion failed at line %i: %s==%s (%i==%i)\n", __LINE__, #exp, #act, exp, act)
72 #define ASSERT_NE(exp,act) do_test((exp)!=(act),"Assertion failed at line %i: %s!=%s (%i!=%i)\n", __LINE__, #exp, #act, exp, act)
74 static int failure = 0;
76 static void
77 do_test(gboolean condition, const char *format, ...)
79 va_list ap;
81 if (condition)
82 return;
84 va_start(ap, format);
85 vfprintf(stderr, format, ap);
86 va_end(ap);
87 failure = 1;
89 /* many of the tests assume this routine doesn't return on failure; if we
90 * do, it may provide more information, but may cause a segfault. Uncomment
91 * this line if you wish.
93 exit(1);
96 #define DATA_LEN 256
98 static char *data;
99 static tvbuff_t *tvb;
100 static packet_info pinfo;
102 /* fragment_table maps from datagram ids to fragment_head
103 reassembled_table maps from <packet number,datagram id> to
104 fragment_head */
105 static reassembly_table test_reassembly_table;
107 #ifdef debug
108 /*************************************************
109 * Util fcns to display
110 * fragment_table & reassembled_table fd-chains
111 ************************************************/
113 static struct _fd_flags {
114 guint32 flag;
115 gchar *flag_name;
116 } fd_flags[] = {
117 {FD_DEFRAGMENTED ,"DF"},
118 {FD_DATALEN_SET ,"DS"},
119 {FD_SUBSET_TVB, ,"ST"},
120 {FD_BLOCKSEQUENCE ,"BS"},
121 {FD_DATA_NOT_PRESENT ,"NP"},
122 {FD_PARTIAL_REASSEMBLY ,"PR"},
123 {FD_OVERLAP ,"OL"},
124 {FD_OVERLAPCONFLICT ,"OC"},
125 {FD_MULTIPLETAILS ,"MT"},
126 {FD_TOOLONGFRAGMENT ,"TL"},
128 #define N_FD_FLAGS (signed)(sizeof(fd_flags)/sizeof(struct _fd_flags))
130 static void
131 print_fd(fragment_head *fd, gboolean is_head) {
132 int i;
134 g_assert(fd != NULL);
135 printf(" %08x %08x %3d %3d %3d", fd, fd->next, fd->frame, fd->offset, fd->len);
136 if (is_head) {
137 printf(" %3d %3d", fd->datalen, fd->reassembled_in);
138 } else {
139 printf( " ");
141 printf(" 0x%08x", fd->data);
142 for (i=0; i<N_FD_FLAGS; i++) {
143 printf(" %s", (fd->flags & fd_flags[i].flag) ? fd_flags[i].flag_name : " ");
145 printf("\n");
148 static void
149 print_fd_chain(fragment_head *fd_head) {
150 fragment_item *fdp;
152 g_assert(fd_head != NULL);
153 print_fd(fd_head, TRUE);
154 for (fdp=fd_head->next; fdp != NULL; fdp=fdp->next) {
155 print_fd(fdp, FALSE);
159 static void
160 print_fragment_table_chain(gpointer k, gpointer v, gpointer ud) {
161 fragment_key *key = (fragment_key*)k;
162 fragment_head *fd_head = (fragment_head *)v;
163 printf(" --> FT: %3d 0x%08x 0x%08x\n", key->id, *(guint32 *)(key->src.data), *(guint32 *)(key->dst.data));
164 print_fd_chain(fd_head);
167 static void
168 print_fragment_table(void) {
169 printf("\n Fragment Table -------\n");
170 g_hash_table_foreach(fragment_table, print_fragment_table_chain, NULL);
173 static void
174 print_reassembled_table_chain(gpointer k, gpointer v, gpointer ud) {
175 reassembled_key *key = (reassembled_key*)k;
176 fragment_head *fd_head = (fragment_head *)v;
177 printf(" --> RT: %5d %5d\n", key->id, key->frame);
178 print_fd_chain(fd_head);
181 static void
182 print_reassembled_table(void) {
183 printf("\n Reassembled Table ----\n");
184 g_hash_table_foreach(test_reassembly_table.reassembled_table, print_reassembled_table_chain, NULL);
187 static void
188 print_tables(void) {
189 print_fragment_table();
190 print_reassembled_table();
192 #endif
194 /**********************************************************************************
196 * fragment_add_seq
198 *********************************************************************************/
200 /* Simple test case for fragment_add_seq.
201 * Adds three fragments (out of order, with one for a different datagram in between),
202 * and checks that they are reassembled correctly.
204 /* visit id frame frag len more tvb_offset
205 0 12 1 0 50 T 10
206 1 12 1 0 60 T 5
207 0 13 2 0 60 T 15
208 0 12 3 2 60 F 5
209 0 12 4 1 60 F 15
211 static void
212 test_simple_fragment_add_seq(void)
214 fragment_head *fd_head, *fdh0;
216 printf("Starting test test_simple_fragment_add_seq\n");
218 pinfo.fd->num = 1;
219 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
220 0, 50, TRUE, 0);
222 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
223 ASSERT_EQ(NULL,fd_head);
225 /* adding the same fragment again should do nothing, even with different
226 * offset etc */
227 pinfo.fd->flags.visited = 1;
228 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
229 0, 60, TRUE, 0);
230 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
231 ASSERT_EQ(NULL,fd_head);
233 /* start another pdu (just to confuse things) */
234 pinfo.fd->flags.visited = 0;
235 pinfo.fd->num = 2;
236 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 15, &pinfo, 13, NULL,
237 0, 60, TRUE, 0);
238 ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.fragment_table));
239 ASSERT_EQ(NULL,fd_head);
241 /* now we add the terminal fragment of the first datagram */
242 pinfo.fd->num = 3;
243 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
244 2, 60, FALSE, 0);
246 /* we haven't got all the fragments yet ... */
247 ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.fragment_table));
248 ASSERT_EQ(NULL,fd_head);
250 /* finally, add the missing fragment */
251 pinfo.fd->num = 4;
252 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 15, &pinfo, 12, NULL,
253 1, 60, TRUE, 0);
255 ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.fragment_table));
256 ASSERT_NE(NULL,fd_head);
258 /* check the contents of the structure */
259 ASSERT_EQ(0,fd_head->frame); /* unused */
260 ASSERT_EQ(0,fd_head->offset); /* unused */
261 ASSERT_EQ(170,fd_head->len); /* the length of data we have */
262 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
263 ASSERT_EQ(4,fd_head->reassembled_in);
264 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
265 ASSERT_NE(NULL,fd_head->tvb_data);
266 ASSERT_NE(NULL,fd_head->next);
268 ASSERT_EQ(1,fd_head->next->frame);
269 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
270 ASSERT_EQ(50,fd_head->next->len); /* segment length */
271 ASSERT_EQ(0,fd_head->next->flags);
272 ASSERT_EQ(NULL,fd_head->next->tvb_data);
273 ASSERT_NE(NULL,fd_head->next->next);
275 ASSERT_EQ(4,fd_head->next->next->frame);
276 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
277 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
278 ASSERT_EQ(0,fd_head->next->next->flags);
279 ASSERT_EQ(NULL,fd_head->next->next->tvb_data);
280 ASSERT_NE(NULL,fd_head->next->next->next);
282 ASSERT_EQ(3,fd_head->next->next->next->frame);
283 ASSERT_EQ(2,fd_head->next->next->next->offset); /* seqno */
284 ASSERT_EQ(60,fd_head->next->next->next->len); /* segment length */
285 ASSERT_EQ(0,fd_head->next->next->next->flags);
286 ASSERT_EQ(NULL,fd_head->next->next->next->tvb_data);
287 ASSERT_EQ(NULL,fd_head->next->next->next->next);
289 /* test the actual reassembly */
290 ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
291 ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+15,60));
292 ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,60));
294 #if 0
295 print_fragment_table();
296 #endif
298 /* what happens if we revisit the packets now? */
299 fdh0 = fd_head;
300 pinfo.fd->flags.visited = 1;
301 pinfo.fd->num = 1;
302 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
303 0, 50, TRUE, 0);
305 * this api relies on the caller to check fd_head -> reassembled_in
307 * Redoing all the tests seems like overkill - just check the pointer
309 ASSERT_EQ(fdh0,fd_head);
311 pinfo.fd->num = 3;
312 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
313 2, 60, FALSE, 0);
314 ASSERT_EQ(fdh0,fd_head);
316 pinfo.fd->num = 4;
317 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 15, &pinfo, 12, NULL,
318 1, 60, TRUE, 0);
319 ASSERT_EQ(fdh0,fd_head);
321 #if 0
322 print_fragment_table();
323 #endif
326 /* XXX ought to have some tests for overlapping fragments */
328 /* This tests the functionality of fragment_set_partial_reassembly for
329 * FD_BLOCKSEQUENCE reassembly.
331 * We add a sequence of fragments thus:
332 * seqno frame offset len (initial) more_frags
333 * ----- ----- ------ --- --------------------
334 * 0 1 10 50 false
335 * 1 2 0 40 true
336 * 1 3 0 40 true (a duplicate fragment)
337 * 2 4 20 100 false
338 * 3 5 0 40 false
340 static void
341 test_fragment_add_seq_partial_reassembly(void)
343 fragment_head *fd_head;
344 fragment_item *fd;
346 printf("Starting test test_fragment_add_seq_partial_reassembly\n");
348 /* generally it's probably fair to assume that we will be called with
349 * more_frags=FALSE.
351 pinfo.fd->num = 1;
352 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
353 0, 50, FALSE, 0);
355 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
356 ASSERT_NE(NULL,fd_head);
358 /* check the contents of the structure */
359 ASSERT_EQ(0,fd_head->frame); /* unused */
360 ASSERT_EQ(0,fd_head->offset); /* unused */
361 ASSERT_EQ(50,fd_head->len); /* the length of data we have */
362 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
363 ASSERT_EQ(1,fd_head->reassembled_in);
364 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
365 ASSERT_NE(NULL,fd_head->tvb_data);
366 ASSERT_NE(NULL,fd_head->next);
368 ASSERT_EQ(1,fd_head->next->frame);
369 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
370 ASSERT_EQ(50,fd_head->next->len); /* segment length */
371 ASSERT_EQ(0,fd_head->next->flags);
372 ASSERT_EQ(NULL,fd_head->next->tvb_data);
373 ASSERT_EQ(NULL,fd_head->next->next);
375 /* test the actual reassembly */
376 ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
378 /* now we announce that the reassembly wasn't complete after all. */
379 fragment_set_partial_reassembly(&test_reassembly_table, &pinfo, 12, NULL);
381 /* and add another segment. To mix things up slightly (and so that we can
382 * check on the state of things), we're going to set the more_frags flag
383 * here
385 pinfo.fd->num = 2;
386 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 0, &pinfo, 12, NULL,
387 1, 40, TRUE, 0);
389 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
390 ASSERT_EQ(NULL,fd_head);
392 fd_head=fragment_get(&test_reassembly_table, &pinfo, 12, NULL);
393 ASSERT_NE(NULL,fd_head);
395 /* check the contents of the structure */
396 ASSERT_EQ(0,fd_head->frame); /* unused */
397 ASSERT_EQ(0,fd_head->offset); /* unused */
398 /* ASSERT_EQ(50,fd_head->len); the length of data we have */
399 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
400 ASSERT_EQ(0,fd_head->reassembled_in);
401 ASSERT_EQ(FD_BLOCKSEQUENCE,fd_head->flags);
402 ASSERT_NE(NULL,fd_head->tvb_data);
403 ASSERT_NE(NULL,fd_head->next);
405 fd=fd_head->next;
406 ASSERT_EQ(1,fd->frame);
407 ASSERT_EQ(0,fd->offset); /* seqno */
408 ASSERT_EQ(50,fd->len); /* segment length */
409 ASSERT_EQ(FD_SUBSET_TVB,fd->flags);
410 ASSERT_EQ(tvb_get_ptr(fd_head->tvb_data,0,0),tvb_get_ptr(fd->tvb_data,0,0));
411 ASSERT_NE(NULL,fd->next);
413 fd=fd->next;
414 ASSERT_EQ(2,fd->frame);
415 ASSERT_EQ(1,fd->offset); /* seqno */
416 ASSERT_EQ(40,fd->len); /* segment length */
417 ASSERT_EQ(0,fd->flags);
418 ASSERT_NE(NULL,fd->tvb_data);
419 ASSERT_EQ(NULL,fd->next);
421 /* Another copy of the second segment.
423 pinfo.fd->num = 3;
424 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 0, &pinfo, 12, NULL,
425 1, 40, TRUE, 0);
427 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
428 ASSERT_EQ(NULL,fd_head);
429 fd_head=fragment_get(&test_reassembly_table, &pinfo, 12, NULL);
430 ASSERT_NE(NULL,fd_head);
431 ASSERT_EQ(0,fd_head->frame); /* unused */
432 ASSERT_EQ(0,fd_head->offset); /* unused */
433 /* ASSERT_EQ(50,fd_head->len); the length of data we have */
434 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
435 ASSERT_EQ(0,fd_head->reassembled_in);
436 ASSERT_EQ(FD_BLOCKSEQUENCE,fd_head->flags);
437 ASSERT_NE(NULL,fd_head->tvb_data);
438 ASSERT_NE(NULL,fd_head->next);
440 fd=fd_head->next;
441 ASSERT_EQ(1,fd->frame);
442 ASSERT_EQ(0,fd->offset); /* seqno */
443 ASSERT_EQ(50,fd->len); /* segment length */
444 ASSERT_EQ(FD_SUBSET_TVB,fd->flags);
445 ASSERT_EQ(tvb_get_ptr(fd_head->tvb_data,0,0),tvb_get_ptr(fd->tvb_data,0,0));
446 ASSERT_NE(NULL,fd->next);
448 fd=fd->next;
449 ASSERT_EQ(2,fd->frame);
450 ASSERT_EQ(1,fd->offset); /* seqno */
451 ASSERT_EQ(40,fd->len); /* segment length */
452 ASSERT_EQ(0,fd->flags);
453 ASSERT_NE(NULL,fd->tvb_data);
454 ASSERT_NE(NULL,fd->next);
456 fd=fd->next;
457 ASSERT_EQ(3,fd->frame);
458 ASSERT_EQ(1,fd->offset); /* seqno */
459 ASSERT_EQ(40,fd->len); /* segment length */
460 ASSERT_EQ(0,fd->flags);
461 ASSERT_NE(NULL,fd->tvb_data);
462 ASSERT_EQ(NULL,fd->next);
466 /* have another go at wrapping things up */
467 pinfo.fd->num = 4;
468 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 20, &pinfo, 12, NULL,
469 2, 100, FALSE, 0);
471 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
472 ASSERT_NE(NULL,fd_head);
474 /* check the contents of the structure */
475 ASSERT_EQ(0,fd_head->frame); /* unused */
476 ASSERT_EQ(0,fd_head->offset); /* unused */
477 ASSERT_EQ(190,fd_head->len); /* the length of data we have */
478 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
479 ASSERT_EQ(4,fd_head->reassembled_in);
480 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
481 ASSERT_NE(NULL,fd_head->tvb_data);
482 ASSERT_NE(NULL,fd_head->next);
484 fd=fd_head->next;
485 ASSERT_EQ(1,fd->frame);
486 ASSERT_EQ(0,fd->offset); /* seqno */
487 ASSERT_EQ(50,fd->len); /* segment length */
488 ASSERT_EQ(0,fd->flags);
489 ASSERT_EQ(NULL,fd->tvb_data);
490 ASSERT_NE(NULL,fd->next);
492 fd=fd->next;
493 ASSERT_EQ(2,fd->frame);
494 ASSERT_EQ(1,fd->offset); /* seqno */
495 ASSERT_EQ(40,fd->len); /* segment length */
496 ASSERT_EQ(0,fd->flags);
497 ASSERT_EQ(NULL,fd->tvb_data);
498 ASSERT_NE(NULL,fd->next);
500 fd=fd->next;
501 ASSERT_EQ(3,fd->frame);
502 ASSERT_EQ(1,fd->offset); /* seqno */
503 ASSERT_EQ(40,fd->len); /* segment length */
504 ASSERT_EQ(FD_OVERLAP,fd->flags);
505 ASSERT_EQ(NULL,fd->tvb_data);
506 ASSERT_NE(NULL,fd->next);
508 fd=fd->next;
509 ASSERT_EQ(4,fd->frame);
510 ASSERT_EQ(2,fd->offset); /* seqno */
511 ASSERT_EQ(100,fd->len); /* segment length */
512 ASSERT_EQ(0,fd->flags);
513 ASSERT_EQ(NULL,fd->tvb_data);
514 ASSERT_EQ(NULL,fd->next);
516 /* test the actual reassembly */
517 ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
518 ASSERT(!tvb_memeql(fd_head->tvb_data,50,data,40));
519 ASSERT(!tvb_memeql(fd_head->tvb_data,90,data+20,100));
522 /* do it again (this time it is more complicated, with an overlap in the
523 * reassembly) */
525 fragment_set_partial_reassembly(&test_reassembly_table, &pinfo, 12, NULL);
527 pinfo.fd->num = 5;
528 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 0, &pinfo, 12, NULL,
529 3, 40, FALSE, 0);
531 fd_head=fragment_get(&test_reassembly_table, &pinfo, 12, NULL);
532 ASSERT_NE(NULL,fd_head);
533 ASSERT_EQ(0,fd_head->frame); /* unused */
534 ASSERT_EQ(0,fd_head->offset); /* unused */
535 ASSERT_EQ(230,fd_head->len); /* the length of data we have */
536 ASSERT_EQ(3,fd_head->datalen); /* seqno of the last fragment we have */
537 ASSERT_EQ(5,fd_head->reassembled_in);
538 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
539 ASSERT_NE(NULL,fd_head->tvb_data);
540 ASSERT_NE(NULL,fd_head->next);
542 fd=fd_head->next;
543 ASSERT_EQ(1,fd->frame);
544 ASSERT_EQ(0,fd->offset); /* seqno */
545 ASSERT_EQ(50,fd->len); /* segment length */
546 ASSERT_EQ(0,fd->flags);
547 ASSERT_EQ(NULL,fd->tvb_data);
548 ASSERT_NE(NULL,fd->next);
550 fd=fd->next;
551 ASSERT_EQ(2,fd->frame);
552 ASSERT_EQ(1,fd->offset); /* seqno */
553 ASSERT_EQ(40,fd->len); /* segment length */
554 ASSERT_EQ(0,fd->flags);
555 ASSERT_EQ(NULL,fd->tvb_data);
556 ASSERT_NE(NULL,fd->next);
558 fd=fd->next;
559 ASSERT_EQ(3,fd->frame);
560 ASSERT_EQ(1,fd->offset); /* seqno */
561 ASSERT_EQ(40,fd->len); /* segment length */
562 ASSERT_EQ(FD_OVERLAP,fd->flags);
563 ASSERT_EQ(NULL,fd->tvb_data);
564 ASSERT_NE(NULL,fd->next);
566 fd=fd->next;
567 ASSERT_EQ(4,fd->frame);
568 ASSERT_EQ(2,fd->offset); /* seqno */
569 ASSERT_EQ(100,fd->len); /* segment length */
570 ASSERT_EQ(0,fd->flags);
571 ASSERT_EQ(NULL,fd->tvb_data);
572 ASSERT_NE(NULL,fd->next);
574 fd=fd->next;
575 ASSERT_EQ(5,fd->frame);
576 ASSERT_EQ(3,fd->offset); /* seqno */
577 ASSERT_EQ(40,fd->len); /* segment length */
578 ASSERT_EQ(0,fd->flags);
579 ASSERT_EQ(NULL,fd->tvb_data);
580 ASSERT_EQ(NULL,fd->next);
582 /* test the actual reassembly */
583 ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
584 ASSERT(!tvb_memeql(fd_head->tvb_data,50,data,40));
585 ASSERT(!tvb_memeql(fd_head->tvb_data,90,data+20,100));
586 ASSERT(!tvb_memeql(fd_head->tvb_data,190,data,40));
589 /* Test case for fragment_add_seq with duplicated (e.g., retransmitted) data.
590 * Adds three fragments--adding the 1st one twice--
591 * and checks that they are reassembled correctly.
593 /* visit id frame frag len more tvb_offset
594 0 12 1 0 50 T 10
595 0 12 2 1 60 T 5
596 0 12 3 2 40 F 5
597 0 12 4 0 50 T 10
599 static void
600 test_fragment_add_seq_duplicate_first(void)
602 fragment_head *fd_head;
604 printf("Starting test test_fragment_add_seq_duplicate_first\n");
606 pinfo.fd->num = 1;
607 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
608 0, 50, TRUE, 0);
610 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
611 ASSERT_EQ(NULL,fd_head);
613 /* Add the 2nd segment */
614 pinfo.fd->num = 2;
615 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
616 1, 60, TRUE, 0);
618 /* we haven't got all the fragments yet ... */
619 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
620 ASSERT_EQ(NULL,fd_head);
622 /* Add the last fragment */
623 pinfo.fd->num = 3;
624 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
625 2, 40, FALSE, 0);
627 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
628 ASSERT_NE(NULL,fd_head);
630 /* Add the first fragment again */
631 pinfo.fd->num = 4;
632 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
633 0, 50, TRUE, 0);
635 /* Reassembly should have still succeeded */
636 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
637 ASSERT_NE(NULL,fd_head);
639 /* check the contents of the structure */
640 ASSERT_EQ(0,fd_head->frame); /* unused */
641 ASSERT_EQ(0,fd_head->offset); /* unused */
642 ASSERT_EQ(150,fd_head->len); /* the length of data we have */
643 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
644 ASSERT_EQ(3,fd_head->reassembled_in);
645 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
646 ASSERT_NE(NULL,fd_head->tvb_data);
647 ASSERT_NE(NULL,fd_head->next);
649 ASSERT_EQ(1,fd_head->next->frame);
650 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
651 ASSERT_EQ(50,fd_head->next->len); /* segment length */
652 ASSERT_EQ(0,fd_head->next->flags);
653 ASSERT_EQ(NULL,fd_head->next->tvb_data);
654 ASSERT_NE(NULL,fd_head->next->next);
656 ASSERT_EQ(4,fd_head->next->next->frame);
657 ASSERT_EQ(0,fd_head->next->next->offset); /* seqno */
658 ASSERT_EQ(50,fd_head->next->next->len); /* segment length */
659 ASSERT_EQ(FD_OVERLAP,fd_head->next->next->flags);
660 ASSERT_EQ(NULL,fd_head->next->next->tvb_data);
661 ASSERT_NE(NULL,fd_head->next->next->next);
663 ASSERT_EQ(2,fd_head->next->next->next->frame);
664 ASSERT_EQ(1,fd_head->next->next->next->offset); /* seqno */
665 ASSERT_EQ(60,fd_head->next->next->next->len); /* segment length */
666 ASSERT_EQ(0,fd_head->next->next->next->flags);
667 ASSERT_EQ(NULL,fd_head->next->next->next->tvb_data);
668 ASSERT_NE(NULL,fd_head->next->next->next->next);
670 ASSERT_EQ(3,fd_head->next->next->next->next->frame);
671 ASSERT_EQ(2,fd_head->next->next->next->next->offset); /* seqno */
672 ASSERT_EQ(40,fd_head->next->next->next->next->len); /* segment length */
673 ASSERT_EQ(0,fd_head->next->next->next->next->flags);
674 ASSERT_EQ(NULL,fd_head->next->next->next->next->tvb_data);
675 ASSERT_EQ(NULL,fd_head->next->next->next->next->next);
677 /* test the actual reassembly */
678 ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
679 ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+5,60));
680 ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,40));
682 #if 0
683 print_fragment_table();
684 #endif
688 /* Test case for fragment_add_seq with duplicated (e.g., retransmitted) data.
689 * Adds three fragments--adding the 2nd one twice--
690 * and checks that they are reassembled correctly.
692 /* visit id frame frag len more tvb_offset
693 0 12 1 0 50 T 10
694 0 12 2 1 60 T 5
695 0 12 3 1 60 T 5
696 0 12 4 3 40 F 5
698 static void
699 test_fragment_add_seq_duplicate_middle(void)
701 fragment_head *fd_head;
703 printf("Starting test test_fragment_add_seq_duplicate_middle\n");
705 pinfo.fd->num = 1;
706 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
707 0, 50, TRUE, 0);
709 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
710 ASSERT_EQ(NULL,fd_head);
712 /* Add the 2nd segment */
713 pinfo.fd->num = 2;
714 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
715 1, 60, TRUE, 0);
717 /* we haven't got all the fragments yet ... */
718 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
719 ASSERT_EQ(NULL,fd_head);
721 /* Now, add the 2nd segment again (but in a different frame) */
722 pinfo.fd->num = 3;
723 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
724 1, 60, TRUE, 0);
726 /* This duplicate fragment should have been ignored */
727 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
728 ASSERT_EQ(NULL,fd_head);
730 /* finally, add the last fragment */
731 pinfo.fd->num = 4;
732 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
733 2, 40, FALSE, 0);
735 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
736 ASSERT_NE(NULL,fd_head);
738 /* check the contents of the structure */
739 ASSERT_EQ(0,fd_head->frame); /* unused */
740 ASSERT_EQ(0,fd_head->offset); /* unused */
741 ASSERT_EQ(150,fd_head->len); /* the length of data we have */
742 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
743 ASSERT_EQ(4,fd_head->reassembled_in);
744 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
745 ASSERT_NE(NULL,fd_head->tvb_data);
746 ASSERT_NE(NULL,fd_head->next);
748 ASSERT_EQ(1,fd_head->next->frame);
749 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
750 ASSERT_EQ(50,fd_head->next->len); /* segment length */
751 ASSERT_EQ(0,fd_head->next->flags);
752 ASSERT_EQ(NULL,fd_head->next->tvb_data);
753 ASSERT_NE(NULL,fd_head->next->next);
755 ASSERT_EQ(2,fd_head->next->next->frame);
756 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
757 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
758 ASSERT_EQ(0,fd_head->next->next->flags);
759 ASSERT_EQ(NULL,fd_head->next->next->tvb_data);
760 ASSERT_NE(NULL,fd_head->next->next->next);
762 ASSERT_EQ(3,fd_head->next->next->next->frame);
763 ASSERT_EQ(1,fd_head->next->next->next->offset); /* seqno */
764 ASSERT_EQ(60,fd_head->next->next->next->len); /* segment length */
765 ASSERT_EQ(FD_OVERLAP,fd_head->next->next->next->flags);
766 ASSERT_EQ(NULL,fd_head->next->next->next->tvb_data);
767 ASSERT_NE(NULL,fd_head->next->next->next->next);
769 ASSERT_EQ(4,fd_head->next->next->next->next->frame);
770 ASSERT_EQ(2,fd_head->next->next->next->next->offset); /* seqno */
771 ASSERT_EQ(40,fd_head->next->next->next->next->len); /* segment length */
772 ASSERT_EQ(0,fd_head->next->next->next->next->flags);
773 ASSERT_EQ(NULL,fd_head->next->next->next->next->tvb_data);
774 ASSERT_EQ(NULL,fd_head->next->next->next->next->next);
776 /* test the actual reassembly */
777 ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
778 ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+5,60));
779 ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,40));
781 #if 0
782 print_fragment_table();
783 #endif
786 /* Test case for fragment_add_seq with duplicated (e.g., retransmitted) data.
787 * Adds three fragments--adding the 3rd one twice--
788 * and checks that they are reassembled correctly.
790 /* visit id frame frag len more tvb_offset
791 0 12 1 0 50 T 10
792 0 12 2 1 60 T 5
793 0 12 3 2 40 F 5
794 0 12 4 2 40 F 5
796 static void
797 test_fragment_add_seq_duplicate_last(void)
799 fragment_head *fd_head;
801 printf("Starting test test_fragment_add_seq_duplicate_last\n");
803 pinfo.fd->num = 1;
804 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
805 0, 50, TRUE, 0);
807 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
808 ASSERT_EQ(NULL,fd_head);
810 /* Add the 2nd segment */
811 pinfo.fd->num = 2;
812 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
813 1, 60, TRUE, 0);
815 /* we haven't got all the fragments yet ... */
816 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
817 ASSERT_EQ(NULL,fd_head);
819 /* Add the last fragment */
820 pinfo.fd->num = 3;
821 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
822 2, 40, FALSE, 0);
824 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
825 ASSERT_NE(NULL,fd_head);
827 /* Add the last fragment again */
828 pinfo.fd->num = 4;
829 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
830 2, 40, FALSE, 0);
832 /* Reassembly should have still succeeded */
833 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
834 ASSERT_NE(NULL,fd_head);
836 /* check the contents of the structure */
837 ASSERT_EQ(0,fd_head->frame); /* unused */
838 ASSERT_EQ(0,fd_head->offset); /* unused */
839 ASSERT_EQ(150,fd_head->len); /* the length of data we have */
840 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
841 ASSERT_EQ(3,fd_head->reassembled_in);
842 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP,fd_head->flags);
843 ASSERT_NE(NULL,fd_head->tvb_data);
844 ASSERT_NE(NULL,fd_head->next);
846 ASSERT_EQ(1,fd_head->next->frame);
847 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
848 ASSERT_EQ(50,fd_head->next->len); /* segment length */
849 ASSERT_EQ(0,fd_head->next->flags);
850 ASSERT_EQ(NULL,fd_head->next->tvb_data);
851 ASSERT_NE(NULL,fd_head->next->next);
853 ASSERT_EQ(2,fd_head->next->next->frame);
854 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
855 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
856 ASSERT_EQ(0,fd_head->next->next->flags);
857 ASSERT_EQ(NULL,fd_head->next->next->tvb_data);
858 ASSERT_NE(NULL,fd_head->next->next->next);
860 ASSERT_EQ(3,fd_head->next->next->next->frame);
861 ASSERT_EQ(2,fd_head->next->next->next->offset); /* seqno */
862 ASSERT_EQ(40,fd_head->next->next->next->len); /* segment length */
863 ASSERT_EQ(0,fd_head->next->next->next->flags);
864 ASSERT_EQ(NULL,fd_head->next->next->next->tvb_data);
865 ASSERT_NE(NULL,fd_head->next->next->next->next);
867 ASSERT_EQ(4,fd_head->next->next->next->next->frame);
868 ASSERT_EQ(2,fd_head->next->next->next->next->offset); /* seqno */
869 ASSERT_EQ(40,fd_head->next->next->next->next->len); /* segment length */
870 ASSERT_EQ(FD_OVERLAP,fd_head->next->next->next->next->flags);
871 ASSERT_EQ(NULL,fd_head->next->next->next->next->tvb_data);
872 ASSERT_EQ(NULL,fd_head->next->next->next->next->next);
874 /* test the actual reassembly */
875 ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
876 ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+5,60));
877 ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,40));
879 #if 0
880 print_fragment_table();
881 #endif
884 /* Test case for fragment_add_seq with duplicated (e.g., retransmitted) data
885 * where the retransmission "conflicts" with the original transmission
886 * (contents are different).
887 * Adds three fragments--adding the 2nd one twice--
888 * and checks that they are reassembled correctly.
890 /* visit id frame frag len more tvb_offset
891 0 12 1 0 50 T 10
892 0 12 2 1 60 T 5
893 0 12 3 1 60 T 15
894 0 12 4 2 40 F 5
896 static void
897 test_fragment_add_seq_duplicate_conflict(void)
899 fragment_head *fd_head;
901 printf("Starting test test_fragment_add_seq_duplicate_conflict\n");
903 pinfo.fd->num = 1;
904 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
905 0, 50, TRUE, 0);
907 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
908 ASSERT_EQ(NULL,fd_head);
910 /* Add the 2nd segment */
911 pinfo.fd->num = 2;
912 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
913 1, 60, TRUE, 0);
915 /* we haven't got all the fragments yet ... */
916 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
917 ASSERT_EQ(NULL,fd_head);
919 /* Now, add the 2nd segment again (but in a different frame and with
920 * different data)
922 pinfo.fd->num = 3;
923 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 15, &pinfo, 12, NULL,
924 1, 60, TRUE, 0);
926 /* This duplicate fragment should have been ignored */
927 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
928 ASSERT_EQ(NULL,fd_head);
930 /* finally, add the last fragment */
931 pinfo.fd->num = 4;
932 fd_head=fragment_add_seq(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
933 2, 40, FALSE, 0);
935 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
936 ASSERT_NE(NULL,fd_head);
938 /* check the contents of the structure */
939 ASSERT_EQ(0,fd_head->frame); /* unused */
940 ASSERT_EQ(0,fd_head->offset); /* unused */
941 ASSERT_EQ(150,fd_head->len); /* the length of data we have */
942 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
943 ASSERT_EQ(4,fd_head->reassembled_in);
944 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET|FD_OVERLAP|FD_OVERLAPCONFLICT,fd_head->flags);
945 ASSERT_NE(NULL,fd_head->tvb_data);
946 ASSERT_NE(NULL,fd_head->next);
948 ASSERT_EQ(1,fd_head->next->frame);
949 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
950 ASSERT_EQ(50,fd_head->next->len); /* segment length */
951 ASSERT_EQ(0,fd_head->next->flags);
952 ASSERT_EQ(NULL,fd_head->next->tvb_data);
953 ASSERT_NE(NULL,fd_head->next->next);
955 ASSERT_EQ(2,fd_head->next->next->frame);
956 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
957 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
958 ASSERT_EQ(0,fd_head->next->next->flags);
959 ASSERT_EQ(NULL,fd_head->next->next->tvb_data);
960 ASSERT_NE(NULL,fd_head->next->next->next);
962 ASSERT_EQ(3,fd_head->next->next->next->frame);
963 ASSERT_EQ(1,fd_head->next->next->next->offset); /* seqno */
964 ASSERT_EQ(60,fd_head->next->next->next->len); /* segment length */
965 ASSERT_EQ(FD_OVERLAP|FD_OVERLAPCONFLICT,fd_head->next->next->next->flags);
966 ASSERT_EQ(NULL,fd_head->next->next->next->tvb_data);
967 ASSERT_NE(NULL,fd_head->next->next->next->next);
969 ASSERT_EQ(4,fd_head->next->next->next->next->frame);
970 ASSERT_EQ(2,fd_head->next->next->next->next->offset); /* seqno */
971 ASSERT_EQ(40,fd_head->next->next->next->next->len); /* segment length */
972 ASSERT_EQ(0,fd_head->next->next->next->next->flags);
973 ASSERT_EQ(NULL,fd_head->next->next->next->next->tvb_data);
974 ASSERT_EQ(NULL,fd_head->next->next->next->next->next);
976 /* test the actual reassembly */
977 ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
978 ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+5,60));
979 ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,40));
981 #if 0
982 print_fragment_table();
983 #endif
986 /**********************************************************************************
988 * fragment_add_seq_check
990 *********************************************************************************/
993 /* This routine is used for both fragment_add_seq_802_11 and
994 * fragment_add_seq_check.
996 * Adds a couple of out-of-order fragments and checks their reassembly.
999 /* visit id frame frag len more tvb_offset
1000 0 12 1 0 50 T 10
1001 0 13 2 0 60 T 15
1002 0 12 3 2 60 F 5
1003 0 12 4 1 60 F 15
1007 static void
1008 test_fragment_add_seq_check_work(fragment_head *(*fn)(reassembly_table *,
1009 tvbuff_t *, const int, const packet_info *,
1010 const guint32, const void *, const guint32,
1011 const guint32, const gboolean))
1013 fragment_head *fd_head;
1015 pinfo.fd -> num = 1;
1016 fd_head=fn(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
1017 0, 50, TRUE);
1019 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1020 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1021 ASSERT_EQ(NULL,fd_head);
1023 /* start another pdu (just to confuse things) */
1024 pinfo.fd->num = 2;
1025 fd_head=fn(&test_reassembly_table, tvb, 15, &pinfo, 13, NULL,
1026 0, 60, TRUE);
1027 ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.fragment_table));
1028 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1029 ASSERT_EQ(NULL,fd_head);
1031 /* add the terminal fragment of the first datagram */
1032 pinfo.fd->num = 3;
1033 fd_head=fn(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
1034 2, 60, FALSE);
1036 /* we haven't got all the fragments yet ... */
1037 ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.fragment_table));
1038 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1039 ASSERT_EQ(NULL,fd_head);
1041 /* finally, add the missing fragment */
1042 pinfo.fd->num = 4;
1043 fd_head=fn(&test_reassembly_table, tvb, 15, &pinfo, 12, NULL,
1044 1, 60, TRUE);
1046 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1047 ASSERT_EQ(3,g_hash_table_size(test_reassembly_table.reassembled_table));
1048 ASSERT_NE(NULL,fd_head);
1050 /* check the contents of the structure */
1051 ASSERT_EQ(0,fd_head->frame); /* unused */
1052 ASSERT_EQ(0,fd_head->offset); /* unused */
1053 ASSERT_EQ(170,fd_head->len); /* the length of data we have */
1054 ASSERT_EQ(2,fd_head->datalen); /* seqno of the last fragment we have */
1055 ASSERT_EQ(4,fd_head->reassembled_in);
1056 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
1057 ASSERT_NE(NULL,fd_head->tvb_data);
1058 ASSERT_NE(NULL,fd_head->next);
1060 ASSERT_EQ(1,fd_head->next->frame);
1061 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
1062 ASSERT_EQ(50,fd_head->next->len); /* segment length */
1063 ASSERT_EQ(0,fd_head->next->flags);
1064 ASSERT_EQ(NULL,fd_head->next->tvb_data);
1065 ASSERT_NE(NULL,fd_head->next->next);
1067 ASSERT_EQ(4,fd_head->next->next->frame);
1068 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
1069 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
1070 ASSERT_EQ(0,fd_head->next->next->flags);
1071 ASSERT_EQ(NULL,fd_head->next->next->tvb_data);
1072 ASSERT_NE(NULL,fd_head->next->next->next);
1074 ASSERT_EQ(3,fd_head->next->next->next->frame);
1075 ASSERT_EQ(2,fd_head->next->next->next->offset); /* seqno */
1076 ASSERT_EQ(60,fd_head->next->next->next->len); /* segment length */
1077 ASSERT_EQ(0,fd_head->next->next->next->flags);
1078 ASSERT_EQ(NULL,fd_head->next->next->next->tvb_data);
1079 ASSERT_EQ(NULL,fd_head->next->next->next->next);
1081 /* test the actual reassembly */
1082 ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
1083 ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+15,60));
1084 ASSERT(!tvb_memeql(fd_head->tvb_data,110,data+5,60));
1086 #if 0
1087 print_tables();
1088 #endif
1091 /* Simple test case for fragment_add_seq_check
1093 static void
1094 test_fragment_add_seq_check(void)
1096 printf("Starting test test_fragment_add_seq_check\n");
1098 test_fragment_add_seq_check_work(fragment_add_seq_check);
1102 /* This tests the case that the 802.11 hack does something different for: when
1103 * the terminal segment in a fragmented datagram arrives first.
1105 static void
1106 test_fragment_add_seq_check_1(void)
1108 fragment_head *fd_head;
1110 printf("Starting test test_fragment_add_seq_check_1\n");
1112 pinfo.fd->num = 1;
1113 fd_head=fragment_add_seq_check(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
1114 1, 50, FALSE);
1116 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1117 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1118 ASSERT_EQ(NULL,fd_head);
1120 /* Now add the missing segment */
1121 pinfo.fd->num = 2;
1122 fd_head=fragment_add_seq_check(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
1123 0, 60, TRUE);
1125 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.fragment_table));
1126 ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.reassembled_table));
1127 ASSERT_NE(NULL,fd_head);
1129 /* check the contents of the structure */
1130 ASSERT_EQ(0,fd_head->frame); /* unused */
1131 ASSERT_EQ(0,fd_head->offset); /* unused */
1132 ASSERT_EQ(110,fd_head->len); /* the length of data we have */
1133 ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */
1134 ASSERT_EQ(2,fd_head->reassembled_in);
1135 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
1136 ASSERT_NE(NULL,fd_head->tvb_data);
1137 ASSERT_NE(NULL,fd_head->next);
1139 ASSERT_EQ(2,fd_head->next->frame);
1140 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
1141 ASSERT_EQ(60,fd_head->next->len); /* segment length */
1142 ASSERT_EQ(0,fd_head->next->flags);
1143 ASSERT_EQ(NULL,fd_head->next->tvb_data);
1144 ASSERT_NE(NULL,fd_head->next->next);
1146 ASSERT_EQ(1,fd_head->next->next->frame);
1147 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
1148 ASSERT_EQ(50,fd_head->next->next->len); /* segment length */
1149 ASSERT_EQ(0,fd_head->next->next->flags);
1150 ASSERT_EQ(NULL,fd_head->next->next->tvb_data);
1151 ASSERT_EQ(NULL,fd_head->next->next->next);
1153 /* test the actual reassembly */
1154 ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+5,60));
1155 ASSERT(!tvb_memeql(fd_head->tvb_data,60,data+10,50));
1158 /**********************************************************************************
1160 * fragment_add_seq_802_11
1162 *********************************************************************************/
1164 /* Tests the 802.11 hack.
1166 static void
1167 test_fragment_add_seq_802_11_0(void)
1169 fragment_head *fd_head;
1171 printf("Starting test test_fragment_add_seq_802_11_0\n");
1173 /* the 802.11 hack is that some non-fragmented datagrams have non-zero
1174 * fragment_number; test for this. */
1176 pinfo.fd->num = 1;
1177 fd_head=fragment_add_seq_802_11(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
1178 10, 50, FALSE);
1180 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.fragment_table));
1181 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.reassembled_table));
1182 ASSERT_NE(NULL,fd_head);
1184 /* check the contents of the structure */
1185 ASSERT_EQ(0,fd_head->frame); /* unused */
1186 ASSERT_EQ(0,fd_head->offset); /* unused */
1187 ASSERT_EQ(0,fd_head->len); /* unused */
1188 ASSERT_EQ(0,fd_head->datalen); /* unused */
1189 ASSERT_EQ(1,fd_head->reassembled_in);
1190 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE,fd_head->flags);
1191 ASSERT_EQ(NULL,fd_head->tvb_data);
1192 ASSERT_EQ(NULL,fd_head->next);
1195 /* Reuse the fragment_add_seq_check testcases */
1196 static void test_fragment_add_seq_802_11_1(void)
1198 printf("Starting test test_fragment_add_seq_802_11_1\n");
1199 test_fragment_add_seq_check_work(fragment_add_seq_802_11);
1202 /**********************************************************************************
1204 * fragment_add_seq_check_multiple
1206 *********************************************************************************/
1208 /* Test 2 partial frags from 2 diff datagrams in the same frame */
1210 datagram #1: frame 1 + first part of frame 2
1211 datagram #1: last part of frame 2 + frame 3
1213 Is this a valid scenario ?
1215 The result of calling fragment_add_seq_check(&test_reassembly_table, ) for these
1216 fragments is a reassembled_table with:
1217 id, frame 1 => first_datagram; ["reassembled in" frame 2]
1218 id, frame 2 => second_datagram; ["reassembled in" frame 3]
1219 id, frame 3 => second_datagram;
1221 Note that the id, frame 2 => first datagram was overwritten
1222 by the entry for the second datagram.
1223 Is this OK ? IE: When dissected/displayed
1224 will the reassembled datagram 1 appear with frame 2 ??
1227 /* visit id frame frag len more tvb_offset
1228 0 12 1 0 50 T 10
1229 0 12 2 1 20 F 5
1230 0 12 2 0 25 T 25
1231 0 12 3 1 60 F 0
1235 Is this a valid scenario ?
1236 Is this OK ? IE: When dissected/displayed:
1237 Will the reassembled datagram 1 appear with frame 2 ??
1239 #if 0
1240 static void
1241 test_fragment_add_seq_check_multiple(void) {
1242 fragment_head *fd_head;
1244 pinfo.fd -> num = 1;
1245 fd_head=fragment_add_seq_check(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
1246 0, 50, TRUE);
1248 /* add the terminal fragment of the first datagram */
1249 pinfo.fd->num = 2;
1250 fd_head=fragment_add_seq_check(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
1251 1, 20, FALSE);
1253 print_tables();
1255 /* Now: start a second datagram with the first fragment in frame #2 */
1256 pinfo.fd->num = 2;
1257 fd_head=fragment_add_seq_check(&test_reassembly_table, tvb, 25, &pinfo, 12, NULL,
1258 0, 25, TRUE);
1260 /* add the terminal fragment of the second datagram */
1261 pinfo.fd->num = 3;
1262 fd_head=fragment_add_seq_check(&test_reassembly_table, tvb, 0, &pinfo, 12, NULL,
1263 1, 60, FALSE);
1265 print_tables();
1267 #endif
1269 /**********************************************************************************
1271 * fragment_add_seq_next
1273 *********************************************************************************/
1275 /* Simple test case for fragment_add_seq_next.
1276 * Adds a couple of fragments (with one for a different datagram in between),
1277 * and checks that they are reassembled correctly.
1279 static void
1280 test_simple_fragment_add_seq_next(void)
1282 fragment_head *fd_head;
1284 printf("Starting test test_simple_fragment_add_seq_next\n");
1286 pinfo.fd->num = 1;
1287 fd_head= fragment_add_seq_next(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
1288 50, TRUE);
1290 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1291 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1292 ASSERT_EQ(NULL,fd_head);
1294 /* adding the same fragment again should do nothing, even with different
1295 * offset etc */
1296 pinfo.fd->flags.visited = 1;
1297 fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
1298 60, TRUE);
1299 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1300 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1301 ASSERT_EQ(NULL,fd_head);
1303 /* start another pdu (just to confuse things) */
1304 pinfo.fd->flags.visited = 0;
1305 pinfo.fd->num = 2;
1306 fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 15, &pinfo, 13, NULL,
1307 60, TRUE);
1308 ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.fragment_table));
1309 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1310 ASSERT_EQ(NULL,fd_head);
1313 /* now we add the terminal fragment of the first datagram */
1314 pinfo.fd->num = 3;
1315 fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
1316 60, FALSE);
1318 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1319 ASSERT_EQ(2,g_hash_table_size(test_reassembly_table.reassembled_table));
1320 ASSERT_NE(NULL,fd_head);
1322 /* check the contents of the structure */
1323 ASSERT_EQ(0,fd_head->frame); /* unused */
1324 ASSERT_EQ(0,fd_head->offset); /* unused */
1325 ASSERT_EQ(110,fd_head->len); /* the length of data we have */
1326 ASSERT_EQ(1,fd_head->datalen); /* seqno of the last fragment we have */
1327 ASSERT_EQ(3,fd_head->reassembled_in);
1328 ASSERT_EQ(FD_DEFRAGMENTED|FD_BLOCKSEQUENCE|FD_DATALEN_SET,fd_head->flags);
1329 ASSERT_NE(NULL,fd_head->tvb_data);
1330 ASSERT_NE(NULL,fd_head->next);
1332 ASSERT_EQ(1,fd_head->next->frame);
1333 ASSERT_EQ(0,fd_head->next->offset); /* seqno */
1334 ASSERT_EQ(50,fd_head->next->len); /* segment length */
1335 ASSERT_EQ(0,fd_head->next->flags);
1336 ASSERT_EQ(NULL,fd_head->next->tvb_data);
1337 ASSERT_NE(NULL,fd_head->next->next);
1339 ASSERT_EQ(3,fd_head->next->next->frame);
1340 ASSERT_EQ(1,fd_head->next->next->offset); /* seqno */
1341 ASSERT_EQ(60,fd_head->next->next->len); /* segment length */
1342 ASSERT_EQ(0,fd_head->next->next->flags);
1343 ASSERT_EQ(NULL,fd_head->next->next->tvb_data);
1344 ASSERT_EQ(NULL,fd_head->next->next->next);
1346 /* test the actual reassembly */
1347 ASSERT(!tvb_memeql(fd_head->tvb_data,0,data+10,50));
1348 ASSERT(!tvb_memeql(fd_head->tvb_data,50,data+5,60));
1352 /* This tests the case where some data is missing from one of the fragments.
1353 * It should prevent reassembly.
1355 static void
1356 test_missing_data_fragment_add_seq_next(void)
1358 fragment_head *fd_head;
1360 printf("Starting test test_missing_data_fragment_add_seq_next\n");
1362 /* attempt to add a fragment which is longer than the data available */
1363 pinfo.fd->num = 1;
1364 fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
1365 DATA_LEN-9, TRUE);
1367 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1368 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1369 ASSERT_NE(NULL,fd_head);
1371 /* check the contents of the structure. Reassembly failed so everything
1372 * should be null (meaning, just use the original tvb) */
1373 ASSERT_EQ(0,fd_head->frame); /* unused */
1374 ASSERT_EQ(0,fd_head->offset); /* unused */
1375 ASSERT_EQ(0,fd_head->len); /* the length of data we have */
1376 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
1377 ASSERT_EQ(0,fd_head->reassembled_in);
1378 ASSERT_EQ(FD_BLOCKSEQUENCE,fd_head->flags & 0x1ff);
1379 ASSERT_EQ(NULL,fd_head->tvb_data);
1380 ASSERT_EQ(NULL,fd_head->next);
1382 /* add another fragment (with all data present) */
1383 pinfo.fd->num = 4;
1384 fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
1385 60, FALSE);
1387 /* XXX: it's not clear that this is the right result; however it's what the
1388 * code does...
1390 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1391 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1392 ASSERT_EQ(NULL,fd_head);
1395 /* check what happens when we revisit the packets */
1396 pinfo.fd->flags.visited = TRUE;
1397 pinfo.fd->num = 1;
1399 fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 10, &pinfo, 12, NULL,
1400 DATA_LEN-9, TRUE);
1402 /* We just look in the reassembled_table for this packet. It never got put
1403 * there, so this always returns null.
1405 * That's crazy, because it means that the subdissector will see the data
1406 * exactly once - on the first pass through the capture (well, assuming it
1407 * doesn't bother to check fd_head->reassembled_in); however, that's
1408 * what the code does...
1410 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1411 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1412 ASSERT_EQ(NULL,fd_head);
1414 pinfo.fd->num = 4;
1415 fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 5, &pinfo, 12, NULL,
1416 60, FALSE);
1417 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1418 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1419 ASSERT_EQ(NULL,fd_head);
1424 * we're going to do something similar now, but this time it is the second
1425 * fragment which has something missing.
1427 static void
1428 test_missing_data_fragment_add_seq_next_2(void)
1430 fragment_head *fd_head;
1432 printf("Starting test test_missing_data_fragment_add_seq_next_2\n");
1434 pinfo.fd->num = 11;
1435 fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 10, &pinfo, 24, NULL,
1436 50, TRUE);
1438 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.fragment_table));
1439 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1440 ASSERT_EQ(NULL,fd_head);
1442 pinfo.fd->num = 12;
1443 fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 5, &pinfo, 24, NULL,
1444 DATA_LEN-4, FALSE);
1446 /* XXX: again, i'm really dubious about this. Surely this should return all
1447 * the data we had, for a best-effort attempt at dissecting it?
1448 * And it ought to go into the reassembled table?
1450 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.fragment_table));
1451 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1452 ASSERT_EQ(NULL,fd_head);
1454 /* check what happens when we revisit the packets */
1455 pinfo.fd->flags.visited = TRUE;
1456 pinfo.fd->num = 11;
1458 fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 10, &pinfo, 24, NULL,
1459 50, TRUE);
1461 /* As before, this returns NULL because the fragment isn't in the
1462 * reassembled_table. At least this is a bit more consistent than before.
1464 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.fragment_table));
1465 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1466 ASSERT_EQ(NULL,fd_head);
1468 pinfo.fd->num = 12;
1469 fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 5, &pinfo, 24, NULL,
1470 DATA_LEN-4, FALSE);
1471 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.fragment_table));
1472 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.reassembled_table));
1473 ASSERT_EQ(NULL,fd_head);
1478 * This time, our datagram only has one segment, but it has data missing.
1480 static void
1481 test_missing_data_fragment_add_seq_next_3(void)
1483 fragment_head *fd_head;
1485 printf("Starting test test_missing_data_fragment_add_seq_next_3\n");
1487 pinfo.fd->num = 20;
1488 fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 5, &pinfo, 30, NULL,
1489 DATA_LEN-4, FALSE);
1491 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.fragment_table));
1492 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.reassembled_table));
1493 ASSERT_NE(NULL,fd_head);
1495 /* check the contents of the structure. */
1496 ASSERT_EQ(0,fd_head->frame); /* unused */
1497 ASSERT_EQ(0,fd_head->offset); /* unused */
1498 ASSERT_EQ(0,fd_head->len); /* the length of data we have */
1499 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
1500 ASSERT_EQ(20,fd_head->reassembled_in);
1501 ASSERT_EQ(FD_BLOCKSEQUENCE|FD_DEFRAGMENTED,fd_head->flags);
1502 ASSERT_EQ(NULL,fd_head->tvb_data);
1503 ASSERT_EQ(NULL,fd_head->next);
1505 /* revisiting the packet ought to produce the same result. */
1506 pinfo.fd->flags.visited = TRUE;
1508 pinfo.fd->num = 20;
1509 fd_head=fragment_add_seq_next(&test_reassembly_table, tvb, 5, &pinfo, 30, NULL,
1510 DATA_LEN-4, FALSE);
1512 ASSERT_EQ(0,g_hash_table_size(test_reassembly_table.fragment_table));
1513 ASSERT_EQ(1,g_hash_table_size(test_reassembly_table.reassembled_table));
1514 ASSERT_NE(NULL,fd_head);
1515 ASSERT_EQ(0,fd_head->frame); /* unused */
1516 ASSERT_EQ(0,fd_head->offset); /* unused */
1517 ASSERT_EQ(0,fd_head->len); /* the length of data we have */
1518 ASSERT_EQ(0,fd_head->datalen); /* seqno of the last fragment we have */
1519 ASSERT_EQ(20,fd_head->reassembled_in);
1520 ASSERT_EQ(FD_BLOCKSEQUENCE|FD_DEFRAGMENTED,fd_head->flags);
1521 ASSERT_EQ(NULL,fd_head->tvb_data);
1522 ASSERT_EQ(NULL,fd_head->next);
1526 /**********************************************************************************
1528 * main
1530 *********************************************************************************/
1533 main(int argc _U_, char **argv _U_)
1535 frame_data fd;
1536 static const guint8 src[] = {1,2,3,4}, dst[] = {5,6,7,8};
1537 unsigned int i;
1538 static void (*tests[])(void) = {
1539 test_simple_fragment_add_seq, /* frag table only */
1540 test_fragment_add_seq_partial_reassembly,
1541 test_fragment_add_seq_duplicate_first,
1542 test_fragment_add_seq_duplicate_middle,
1543 test_fragment_add_seq_duplicate_last,
1544 test_fragment_add_seq_duplicate_conflict,
1545 test_fragment_add_seq_check, /* frag + reassemble */
1546 test_fragment_add_seq_check_1,
1547 test_fragment_add_seq_802_11_0,
1548 test_fragment_add_seq_802_11_1,
1549 test_simple_fragment_add_seq_next,
1550 test_missing_data_fragment_add_seq_next,
1551 test_missing_data_fragment_add_seq_next_2,
1552 test_missing_data_fragment_add_seq_next_3,
1553 #if 0
1554 test_fragment_add_seq_check_multiple
1555 #endif
1558 /* initialise stuff */
1559 emem_init();
1561 /* a tvbuff for testing with */
1562 data = (char *)g_malloc(DATA_LEN);
1563 /* make sure it's full of stuff */
1564 for(i=0; i<DATA_LEN; i++) {
1565 data[i]=i & 0xFF;
1567 tvb = tvb_new_real_data(data, DATA_LEN, DATA_LEN*2);
1569 /* other test stuff */
1570 pinfo.fd = &fd;
1571 fd.flags.visited = 0;
1572 SET_ADDRESS(&pinfo.src,AT_IPv4,4,src);
1573 SET_ADDRESS(&pinfo.dst,AT_IPv4,4,dst);
1575 /*************************************************************************/
1576 for(i=0; i < sizeof(tests)/sizeof(tests[0]); i++ ) {
1577 /* re-init the fragment tables */
1578 reassembly_table_init(&test_reassembly_table,
1579 &addresses_reassembly_table_functions);
1580 ASSERT(test_reassembly_table.fragment_table != NULL);
1581 ASSERT(test_reassembly_table.reassembled_table != NULL);
1583 pinfo.fd->flags.visited = FALSE;
1585 tests[i]();
1587 /* Free memory used by the tables */
1588 reassembly_table_destroy(&test_reassembly_table);
1591 tvb_free(tvb);
1592 tvb = NULL;
1593 g_free(data);
1594 data = NULL;
1596 printf(failure?"FAILURE\n":"SUCCESS\n");
1597 return failure;