pico_fragments.c 35.5 KB
Newer Older
1 2 3 4
/*********************************************************************
   PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
   See LICENSE and COPYING for usage.

5
   Authors: Ludo Mondelaers, Laurens Miers
6 7 8
 *********************************************************************/


9
#include "pico_config.h"
10 11 12 13
#ifdef PICO_SUPPORT_IPV6
#include "pico_ipv6.h"
#include "pico_icmp6.h"
#endif
14 15 16 17
#ifdef PICO_SUPPORT_IPV4
#include "pico_ipv4.h"
#include "pico_icmp4.h"
#endif
18 19 20 21 22 23 24
#include "pico_stack.h"
#include "pico_eth.h"
#include "pico_udp.h"
#include "pico_tcp.h"
#include "pico_socket.h"
#include "pico_device.h"
#include "pico_tree.h"
25
#include "pico_constants.h"
26
#include "pico_fragments.h"
27 28 29

/*** macros ***/

30
#define PICO_IP_FRAG_TIMEOUT          60000
31
#define PICO_IP_LAST_FRAG_RECV        1
32 33
#define PICO_IP_FIRST_FRAG_RECV       2
#define PICO_IP_FIRST_FRAG_NOT_RECV   3
34

35
//#define IPFRAG_DEBUG
Ludo Mondelaers's avatar
Ludo Mondelaers committed
36
#ifdef IPFRAG_DEBUG
37
#  define frag_dbg dbg 
Ludo Mondelaers's avatar
Ludo Mondelaers committed
38 39 40
#else
# define frag_dbg(...) do{}while(0);
#endif
41 42 43 44 45 46


//PICO_IPV4_MTU

/*** Type definitions ***/

Laurens Miers's avatar
Laurens Miers committed
47
typedef struct
48
{
49
    // uniquely identify fragments by: (RFC 791 & RFC 2460)
50
    uint32_t            frag_id;
51
    uint8_t             proto; //
Laurens Miers's avatar
Laurens Miers committed
52
    union pico_address  src;
53 54
    union pico_address  dst;

Laurens Miers's avatar
Laurens Miers committed
55
//    PICO_TREE_DECLARE(holes, hole_compare); // this macro contains an initialisation to a global variable: can not use it here
56
    struct pico_tree    holes;
Laurens Miers's avatar
Laurens Miers committed
57

58
    struct pico_frame * frame;
59
    pico_time           expire;
Laurens Miers's avatar
Laurens Miers committed
60

61 62
    uint32_t 			net_hdr_offset;
    uint32_t 			transport_hdr_offset;
Laurens Miers's avatar
Laurens Miers committed
63

64 65 66 67
}pico_fragment_t;

typedef     struct
{
68 69
    uint16_t first;
    uint16_t last;
70 71 72 73 74 75
}pico_hole_t;

/***  Prototypes ***/

static int fragments_compare(void *fa, void *fb);   /*pico_fragment_t*/
static int hole_compare(void *a, void *b);          /*pico_hole_t*/
76 77
static int first_fragment_received(struct pico_tree *holes);

78
// alloc and free of fragment tree
Laurens Miers's avatar
Laurens Miers committed
79
static pico_fragment_t *pico_fragment_alloc( uint16_t iphdrsize, uint32_t bufsize);
80 81
static pico_fragment_t *pico_fragment_free(pico_fragment_t * fragment);

82
static int pico_fragment_arrived(pico_fragment_t* fragment, struct pico_frame* frame, uint16_t byte_offset, uint16_t more_flag );
83 84
// alloc and free for the hole tree
static pico_hole_t* pico_hole_free(pico_hole_t *hole);
85
static pico_hole_t* pico_hole_alloc(uint16_t first,uint16_t last);
86

87
static void pico_ip_frag_expired(pico_time now, void *arg);
88 89
static int copy_eth_hdr(struct pico_frame* dst, struct pico_frame* src);
static int copy_ipv6_hdrs_nofrag(struct pico_frame* dst, struct pico_frame* src);
90

91 92
/*** static declarations ***/
//static     PICO_TREE_DECLARE(ip_fragments, fragments_compare);
93
static struct pico_tree    pico_fragments = { &LEAF, fragments_compare};
94 95
// our timer: allocoate one instance
static struct pico_timer*      pico_fragment_timer = NULL;
96 97 98 99 100 101



/*** global function called from pico_ipv6.c ***/

#ifdef PICO_SUPPORT_IPV6
102 103
// byte offset and more flag from exthdr (RFC2460)
#define IP6FRAG_OFF(frag)  ((frag & 0xFFF8))
Ludo Mondelaers's avatar
Ludo Mondelaers committed
104
#define IP6FRAG_MORE(frag) ((frag & 0x0001) ? 1 : 0)
105 106 107 108 109 110

#define IP6FRAG_ID(exthdr) ((uint32_t)((exthdr->ext.frag.id[0] << 24)   |   \
                                       (exthdr->ext.frag.id[1] << 16)   |   \
                                       (exthdr->ext.frag.id[2] << 8)    |   \
                                        exthdr->ext.frag.id[3]))

111
static int copy_eth_hdr(struct pico_frame* dst, struct pico_frame* src)
112
{
113 114 115
    struct pico_eth_hdr *srchdr = NULL;
    struct pico_eth_hdr *dsthdr = NULL;

116 117 118 119 120
    if (!dst || !src)
    {
        return -1;
    }

121 122
    srchdr = (struct pico_eth_hdr *)src->datalink_hdr;
    dsthdr = (struct pico_eth_hdr *)dst->datalink_hdr;
123

124 125 126 127 128
    if (!srchdr || !dsthdr)
    {
        return -1;
    }

129
    memcpy(dsthdr, srchdr, PICO_SIZE_ETHHDR);
130
    return 0;
131
}
132

133
static int copy_ipv6_hdrs_nofrag(struct pico_frame* dst, struct pico_frame* src)
134 135
{
    int done = 0;
136 137
    struct pico_ipv6_hdr *srchdr = NULL;
    struct pico_ipv6_hdr *dsthdr = NULL;
138
    int srcidx = 0;
Laurens Miers's avatar
Laurens Miers committed
139 140
    uint16_t dstidx = 0;
    uint16_t retval = 0;
141 142
    uint8_t nxthdr = 0;
    uint8_t* pdstnxthdr = NULL;
Laurens Miers's avatar
Laurens Miers committed
143

144
    if (!dst || !src)
Laurens Miers's avatar
Laurens Miers committed
145
    {
146 147
        return -1;
    }
gentci's avatar
gentci committed
148

149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
    srchdr = (struct pico_ipv6_hdr *)src->net_hdr;
    dsthdr = (struct pico_ipv6_hdr *)dst->net_hdr;

    if (!srchdr || !dsthdr)
    {
        return -1;
    }


    nxthdr = srchdr->nxthdr;
    pdstnxthdr = &dsthdr->nxthdr;

    frag_dbg("[LUM:%s:%d] begin offset for pdstnxthdr:%d\n", __FILE__,__LINE__, (uint32_t)(pdstnxthdr - (uint8_t*)dsthdr));
    // copy ethernet header + IPv6 header
    memcpy(dst->buffer + PICO_SIZE_ETHHDR, src->buffer + PICO_SIZE_ETHHDR, PICO_SIZE_IP6HDR);

    retval = src->net_len;

    // parse ext hdrs
    while(!done)
    {
        frag_dbg("[LUM:%s:%d] nxthdr:%d %s\n", __FILE__,__LINE__,nxthdr,
                 nxthdr == PICO_IPV6_EXTHDR_DESTOPT  ? "PICO_IPV6_EXTHDR_DESTOPT":
                 nxthdr == PICO_IPV6_EXTHDR_ROUTING	? "PICO_IPV6_EXTHDR_ROUTING":
                 nxthdr == PICO_IPV6_EXTHDR_HOPBYHOP ? "PICO_IPV6_EXTHDR_HOPBYHOP":
                 nxthdr == PICO_IPV6_EXTHDR_ESP      ? "PICO_IPV6_EXTHDR_ESP":
                 nxthdr == PICO_IPV6_EXTHDR_AUTH		? "PICO_IPV6_EXTHDR_AUTH":
                 nxthdr == PICO_IPV6_EXTHDR_FRAG     ? "PICO_IPV6_EXTHDR_FRAG":
                 nxthdr == PICO_IPV6_EXTHDR_NONE		? "PICO_IPV6_EXTHDR_NONE":
                 nxthdr == PICO_PROTO_TCP			? "PICO_PROTO_TCP":
                 nxthdr == PICO_PROTO_UDP			? "PICO_PROTO_UDP":
                 nxthdr == PICO_PROTO_ICMP6			? "PICO_PROTO_ICMP6":
                 nxthdr == PICO_ICMP6_ECHO_REQUEST	? "PICO_ICMP6_ECHO_REQUEST":
                 nxthdr == PICO_ICMP6_DEST_UNREACH	? "PICO_ICMP6_DEST_UNREACH":
                 nxthdr == PICO_ICMP6_PKT_TOO_BIG	? "PICO_ICMP6_PKT_TOO_BIG":
                 nxthdr == PICO_ICMP6_ECHO_REPLY		? "PICO_ICMP6_ECHO_REPLY":
                 nxthdr == PICO_ICMP6_ROUTER_SOL		? "PICO_ICMP6_ROUTER_SOL":
                 nxthdr == PICO_ICMP6_ROUTER_ADV		? "PICO_ICMP6_ROUTER_ADV":
                 nxthdr == PICO_ICMP6_NEIGH_SOL		? "PICO_ICMP6_NEIGH_SOL":
                 nxthdr == PICO_ICMP6_NEIGH_ADV		? "PICO_ICMP6_NEIGH_ADV":
                 nxthdr == PICO_ICMP6_REDIRECT		? "PICO_ICMP6_REDIRECT":
                 "unknown");

        switch(nxthdr)
        {
        case PICO_IPV6_EXTHDR_DESTOPT:
        case PICO_IPV6_EXTHDR_ROUTING:
        case PICO_IPV6_EXTHDR_HOPBYHOP:
        case PICO_IPV6_EXTHDR_ESP:
        case PICO_IPV6_EXTHDR_AUTH:
        {
            uint8_t len = (uint8_t)(srchdr->extensions[srcidx+1] << 3);
            frag_dbg("[LUM:%s:%d] nxthdr:%d len:%d pdstnxthdr:%p\n", __FILE__,__LINE__,nxthdr,len,pdstnxthdr);
            memcpy(&dsthdr->extensions[dstidx],&srchdr->extensions[srcidx],(size_t)len);
            srcidx += len;
            dstidx = (uint16_t)(dstidx + len);
            *pdstnxthdr = nxthdr;
            pdstnxthdr = &dsthdr->extensions[dstidx];
            frag_dbg("[LUM:%s:%d] offset voor pdstnxthdr:%d\n", __FILE__,__LINE__, (uint32_t)(pdstnxthdr - (uint8_t*)dsthdr));
        }
        break;
        case PICO_IPV6_EXTHDR_FRAG:
            srcidx += 8;            // remove frag field from dsthdr
212
            retval = (uint16_t)(retval - 8u);
213
			break;
214 215 216 217 218 219 220 221
        case PICO_IPV6_EXTHDR_NONE:
        case PICO_PROTO_TCP:
        case PICO_PROTO_UDP:
        case PICO_PROTO_ICMP6:
        case PICO_ICMP6_ECHO_REQUEST:
            *pdstnxthdr = nxthdr;
            frag_dbg("[LUM:%s:%d] offset for pdstnxthdr:%d\n", __FILE__,__LINE__, (uint32_t)(pdstnxthdr - (uint8_t*)dsthdr));
            done=1;
222
			break;
223
        default:
224
			/* Invalid next header */
225 226 227
            frag_dbg("[LUM:%s:%d] unrecognised nxthdr:%d \n",__FILE__,__LINE__,nxthdr);
            pico_icmp6_parameter_problem(src, PICO_ICMP6_PARAMPROB_NXTHDR, (uint32_t)nxthdr);
            done=1;
228
			break;
229 230
        }
        nxthdr = srchdr->extensions[srcidx];   // advance pointer
231
    }
232 233
    dst->payload = &dsthdr->extensions[dstidx];
    dst->transport_hdr = dst->payload;
Laurens Miers's avatar
Laurens Miers committed
234

235 236 237
	frag_dbg("[LUM:%s:%d] ipv6 hdr without frag len:%d \n",__FILE__,__LINE__, retval);

    return retval;
238 239
}

240 241 242 243 244 245 246 247 248 249 250 251 252 253
static void pico_fragment_tree_mempressure_cleanup(void)
{
    pico_fragment_t * fragment = NULL;
    struct pico_tree_node *idx = NULL;
    struct pico_tree_node *tmp = NULL;

    dbg("Frag module: under memory pressure. Discarding all fragments.\n");

    pico_tree_foreach_safe(idx, &pico_fragments, tmp) {
        fragment = idx->keyValue;
        pico_fragment_free(fragment);
    }
}

254

255
void pico_ipv6_process_frag(struct pico_ipv6_exthdr *exthdr, struct pico_frame *f, uint8_t proto /* see pico_addressing.h */)
256
{
Ludo Mondelaers's avatar
Ludo Mondelaers committed
257
    int retval = 0;
Laurens Miers's avatar
Laurens Miers committed
258
    uint16_t netlen_without_frag = 0;
Laurens Miers's avatar
Laurens Miers committed
259

260 261
    if(exthdr && f)
    {
laurens's avatar
laurens committed
262 263 264 265 266 267
        struct pico_ipv6_hdr *ip6hdr=(struct pico_ipv6_hdr*)f->net_hdr;
        /* Double braces to get rid of (gcc) compiler warning
         * is a bug in gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119
         */
        union pico_address src = { {0} };
        union pico_address dst = { {0} };
gentci's avatar
gentci committed
268

Laurens Miers's avatar
Laurens Miers committed
269
        // does the fragment already have its fragment tree?
270
        pico_fragment_t key;
271 272
        pico_fragment_t *fragment = NULL;

gentci's avatar
gentci committed
273 274 275
		src.ip6 = ip6hdr->src;
        dst.ip6 = ip6hdr->dst;

276
        memset(&key,0,sizeof(pico_fragment_t));
277 278
        key.frag_id = IP6FRAG_ID(exthdr);
        key.proto = proto;
gentci's avatar
gentci committed
279 280 281

        key.src = src; //src ip6
        key.dst = dst;   // dst ip6
Laurens Miers's avatar
Laurens Miers committed
282 283

        fragment = pico_tree_findKey( &pico_fragments,  &key);
284 285 286
        if(!fragment)  // this is a new frag_id
        {
            // allocate fragment tree
287
            fragment = pico_fragment_alloc( PICO_SIZE_ETHHDR + PICO_SIZE_IP6HDR, f->buffer_len);
gentci's avatar
gentci committed
288

Ludo Mondelaers's avatar
Ludo Mondelaers committed
289
			frag_dbg("[LUM:%s:%d] frag_id not found in fragment tree. frag_id:0x%X \n",__FILE__,__LINE__,IP6FRAG_ID(exthdr));
gentci's avatar
gentci committed
290

291 292
            if(fragment)
            {
Laurens Miers's avatar
Laurens Miers committed
293
                /* TODO:  options are not being handled now */
Ludo Mondelaers's avatar
Ludo Mondelaers committed
294

295
                if(IP6FRAG_OFF(f->frag) == 0)  // offset is 0
296 297 298
                {
                    // if first frame: copy options  see RFC815
                }
Laurens Miers's avatar
Laurens Miers committed
299
                else
300 301 302
                {
                    //fragment is not the first fragment: assume no options, and add them later
                }
Laurens Miers's avatar
Laurens Miers committed
303

304
                // copy headers to reassambled package (but delete the fragment header)
305 306 307 308 309 310 311 312 313 314
                if (copy_eth_hdr(fragment->frame, f) != 0)
                {
                    pico_fragment_free(fragment);
                    return;
                }

                retval = copy_ipv6_hdrs_nofrag(fragment->frame, f);

                if (retval <= 0)
                {
315
                    pico_fragment_free(fragment);
316 317 318 319
                    return;
                }

                netlen_without_frag = (uint16_t)(retval - PICO_SIZE_ETHHDR);
320 321
                // copy payload
                memcpy(fragment->frame->transport_hdr,f->transport_hdr,f->transport_len);
322
                // TODO: this is done in pico_fragment_arrived, but if the packet is not fragmented, it may be lost (I think), further investigate
Laurens Miers's avatar
Laurens Miers committed
323

324 325
                // Update netlen
                fragment->frame->net_len = netlen_without_frag;
Laurens Miers's avatar
Laurens Miers committed
326 327


328

329 330
                fragment->frag_id = IP6FRAG_ID(exthdr);
                fragment->proto = proto;
gentci's avatar
gentci committed
331 332
				fragment->src.ip6 = src.ip6;
				fragment->dst.ip6 = dst.ip6;
Laurens Miers's avatar
Laurens Miers committed
333

334 335
                /* fragment->holes.compare = hole_compare; */
                /* fragment->holes.root = &LEAF; */
Laurens Miers's avatar
Laurens Miers committed
336

337
                pico_tree_insert(&pico_fragments, fragment);
338

339 340 341 342
            }
        }
        if(fragment)
        {
343 344 345
			uint16_t offset = IP6FRAG_OFF(f->frag);
            uint16_t more   = IP6FRAG_MORE(f->frag);

346 347 348 349
            retval = pico_fragment_arrived(fragment, f, offset, more);

            if (retval == PICO_IP_LAST_FRAG_RECV)
            {
Laurens Miers's avatar
Laurens Miers committed
350
                // This was the last packet
351 352 353 354
                // all done with this fragment: send it up and free it
                pico_transport_receive(fragment->frame, fragment->proto);
                // picoTCP still needs the fragment->frame, but we don't
                // make fragment->frame NULL so that the fragment_free does not clean it up (else we lost the packet)
355 356
                fragment->frame = NULL;
                pico_fragment_free(fragment);
357 358
            }
            else
359
            {
360
                pico_fragment_tree_mempressure_cleanup();
361
            }
362 363 364 365 366 367 368 369
        }
    }
}
#endif

#ifdef PICO_SUPPORT_IPV4


370 371 372
#define IP4FRAG_ID(hdr) (hdr->id)

// byte offset and more flag from iphdr (RFC791)
373
#define IP4FRAG_OFF(frag)  (((uint32_t)frag & PICO_IPV4_FRAG_MASK) << 3ul)
Ludo Mondelaers's avatar
Ludo Mondelaers committed
374
#define IP4FRAG_MORE(frag) ((frag & PICO_IPV4_MOREFRAG) ? 1 : 0)
375

376

377
int pico_ipv4_process_frag(struct pico_ipv4_hdr *hdr, struct pico_frame *f, uint8_t proto /* see pico_addressing.h */)
378 379 380 381 382
{
    int retval = 0;
    if(hdr && f)
    {
        // does the fragment already has its fragment tree?
383
        pico_fragment_t key;
384 385
        pico_fragment_t *fragment = NULL;

386 387 388 389
        //  hdr is stored in network order !!! oh crap
        uint16_t offset = IP4FRAG_OFF(short_be(hdr->frag));
        uint16_t more   = IP4FRAG_MORE(short_be(hdr->frag));

390
        struct pico_ipv4_hdr *ip4hdr=(struct pico_ipv4_hdr*)f->net_hdr;
laurens's avatar
laurens committed
391 392 393 394 395
        /* Double braces to get rid of (gcc) compiler warning
         * is a bug in gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119
         */
        union pico_address src = { {0} };
        union pico_address dst = { {0} };
396 397 398 399 400 401 402 403 404 405

        src.ip4 = ip4hdr->src;
        dst.ip4 = ip4hdr->dst;

        memset(&key,0,sizeof(pico_fragment_t));

        key.src = src; //src ip4
        key.dst = dst;   // dst ip4
        key.frag_id = short_be(IP4FRAG_ID(hdr));
        key.proto = proto;
406 407 408 409 410 411 412 413

        if(!more &&  (offset == 0))
        {
            frag_dbg("[LUM:%s:%d] Not a fragmented packet, carry on.\n",__FILE__,__LINE__);
            // no need for reassemble packet
            return PICO_IP_LAST_FRAG_RECV;    // process orig packet (return 1)
        }

Laurens Miers's avatar
Laurens Miers committed
414
        fragment = pico_tree_findKey( &pico_fragments,  &key);
415

Ludo Mondelaers's avatar
Ludo Mondelaers committed
416
        frag_dbg("[LUM:%s:%d] Searching for frag_id:0x%X proto:%d(%s): %s \n",
417 418 419
                    __FILE__,__LINE__,
                    key.frag_id,
                    key.proto,
420
                        (proto == PICO_PROTO_IPV4)  ? "PICO_PROTO_IPV4" :
421
                        (proto == PICO_PROTO_ICMP4) ? "PICO_PROTO_ICMP4" :
422 423 424 425
                        (proto == PICO_PROTO_IGMP)  ? "PICO_PROTO_IGMP" :
                        (proto == PICO_PROTO_TCP)   ? "PICO_PROTO_TCP" :
                        (proto == PICO_PROTO_UDP)   ? "PICO_PROTO_UDP" :
                        (proto == PICO_PROTO_IPV6)  ? "PICO_PROTO_IPV6" :
426 427
                        (proto == PICO_PROTO_ICMP6) ? "PICO_PROTO_ICMP6" :  "unknown",
                    fragment?"FOUND":"NOT FOUND");
428 429 430

        if(!fragment)  // this is a new frag_id
        {
431
            frag_dbg("[LUM:%s:%d] frag_id:0x%X not found, allocate a new fragment.\n",__FILE__,__LINE__, key.frag_id);
432
            // allocate fragment tree
433
            fragment = pico_fragment_alloc( PICO_SIZE_ETHHDR + PICO_SIZE_IP4HDR, PICO_IPV4_MTU + 64 /*max length of options*/);
434 435
            if(fragment)
            {
Laurens Miers's avatar
Laurens Miers committed
436
                /* TODO: options are not being copied properly */
437
                if(IP4FRAG_OFF(f->frag) == 0)
438 439
                {
                    // if first frame: TODO copy options  see RFC815
440
                    //fragment->start_payload = PICO_SIZE_IP4HDR;
441
                }
Laurens Miers's avatar
Laurens Miers committed
442
                else
443 444
                {
                    //fragment is not the first fragment: assume no options, and add them later
445
                    //fragment->start_payload = PICO_SIZE_IP4HDR;
446
                }
Laurens Miers's avatar
Laurens Miers committed
447

Ludo Mondelaers's avatar
Ludo Mondelaers committed
448
                if(fragment->frame->net_hdr &&  f->net_hdr)
Ludo Mondelaers's avatar
Ludo Mondelaers committed
449
                {
450
                    memcpy(fragment->frame->net_hdr, f->net_hdr, f->net_len);
Ludo Mondelaers's avatar
Ludo Mondelaers committed
451 452 453
                }
                else
                {
454
                    frag_dbg("[%s:%d] fragment->frame->net_hdr:%p f->net_hdr:%p PICO_SIZE_ETHHDR + PICO_SIZE_IP4HDR:%d);\n",__FILE__,__LINE__,fragment->frame->net_hdr,f->net_hdr,PICO_SIZE_ETHHDR + PICO_SIZE_IP4HDR);
Ludo Mondelaers's avatar
Ludo Mondelaers committed
455
                }
456

457
                fragment->frag_id = key.frag_id;
Laurens Miers's avatar
Laurens Miers committed
458 459
                fragment->src.ip4 = key.src.ip4;
                fragment->dst.ip4 = key.dst.ip4;
460 461
                fragment->frame->frag = 0;  // remove frag options
                fragment->frame->proto = proto;
462
                fragment->proto = proto;
463 464
                /* fragment->holes.compare = hole_compare; */
                /* fragment->holes.root = &LEAF; */
Laurens Miers's avatar
Laurens Miers committed
465

466 467 468 469 470
                pico_tree_insert(&pico_fragments, fragment);
            }
        }
        if(fragment)
        {
471
            frag_dbg("[LUM:%s:%d] frag_id:0x%X found.\n",__FILE__,__LINE__, key.frag_id);
472 473 474 475 476 477 478
            frag_dbg("[LUM:%s:%d] recv a fragmented packet, handle it.\n",__FILE__,__LINE__);
            retval = pico_fragment_arrived(fragment, f, offset, more);

            if (retval == PICO_IP_LAST_FRAG_RECV)
            {
                //This was the last packet
                //Calculate crc of final reassambled packet
Laurens Miers's avatar
Laurens Miers committed
479

480
                struct pico_ipv4_hdr *net_hdr = (struct pico_ipv4_hdr *) fragment->frame->net_hdr;
Laurens Miers's avatar
Laurens Miers committed
481

482 483 484 485 486 487 488 489 490 491 492 493 494 495
                if(net_hdr)
                {
                    net_hdr->crc = 0;
                    net_hdr->crc = short_be(pico_checksum(net_hdr, fragment->frame->net_len));
                }
                else
                {
                    frag_dbg("[LUM:%s:%d] net_hdr NULL \n",__FILE__,__LINE__);
                }
                frag_dbg("[LUM:%s:%d] send the reassembled packet upstream \n",__FILE__,__LINE__);

                // all done with this fragment: send it up and free it
                pico_transport_receive(fragment->frame, fragment->proto);
                fragment->frame = NULL;
496
                pico_fragment_free(fragment);
Laurens Miers's avatar
Laurens Miers committed
497
            }
498 499
            else
            {
500
                pico_fragment_tree_mempressure_cleanup();
501
            }
502 503 504 505 506 507 508 509 510 511 512 513
        }
    }
    return retval;
}
#endif



static int fragments_compare(void *a, void *b)
{
    pico_fragment_t *fa = a;
    pico_fragment_t *fb = b;
514
    int retval=0;
515

516
    if(fa && fb)
Laurens Miers's avatar
Laurens Miers committed
517
    {
Laurens Miers's avatar
Laurens Miers committed
518
        if((retval = (int)(fa->frag_id - fb->frag_id)) == 0)    // fragid
519
        {
Laurens Miers's avatar
Laurens Miers committed
520
            if((retval = (int)(fa->proto - fb->proto)) == 0)  // and protocol
521
            {
Laurens Miers's avatar
Laurens Miers committed
522 523 524
#if 1
                if((fa->proto == PICO_PROTO_IPV4)  || (fa->proto == PICO_PROTO_ICMP4)  ||
                    (fa->proto == PICO_PROTO_IGMP) || (fa->proto == PICO_PROTO_TCP)    ||
525 526 527 528 529 530 531
                        (fa->proto == PICO_PROTO_UDP))
                {
                    if((retval = memcmp(&fa->src,&fb->src,sizeof(struct pico_ip4))) == 0) //src ip4
                    {
                        retval = memcmp(&fa->dst,&fb->dst,sizeof(struct pico_ip4));       //dst
                    }  //  source addr   & dest addr
                }
Laurens Miers's avatar
Laurens Miers committed
532
                else if ((fa->proto == PICO_PROTO_IPV6)  ||                  (fa->proto == PICO_PROTO_ICMP6))
533 534 535 536 537 538
                {
                    if((retval = memcmp(&fa->src,&fb->src,sizeof(struct pico_ip6))) == 0) //src ip6
                    {
                        retval = memcmp(&fa->dst,&fb->dst,sizeof(struct pico_ip6));   // dst ip6
                    }
                }
gentci's avatar
gentci committed
539 540
#else
     			frag_dbg("[LUM:%s:%d] src and dst ip not checked  \n",__FILE__,__LINE__);
Laurens Miers's avatar
Laurens Miers committed
541

gentci's avatar
gentci committed
542
#endif
543 544
            }
        }
545 546 547
    }
    else
    {
548
        retval = -1;
549
    }
550
    return retval;
551 552 553 554 555
}




laurens's avatar
laurens committed
556
static pico_fragment_t *pico_fragment_alloc( uint16_t iphdrsize, uint32_t bufsize )  // size = exthdr + payload (MTU)
557
{
558 559 560 561 562 563 564 565
    pico_fragment_t* fragment;

    if (iphdrsize <= 0 || bufsize<= 0)
    {
        return NULL;
    }

    fragment = PICO_ZALLOC(sizeof(pico_fragment_t) );
566 567 568

    if(fragment)
    {
Laurens Miers's avatar
Laurens Miers committed
569
        struct pico_frame* frame  = pico_frame_alloc((uint32_t)(bufsize + iphdrsize));
Laurens Miers's avatar
Laurens Miers committed
570

571 572
        if(frame)
        {
gentci's avatar
gentci committed
573
#ifdef IPFRAG_DEBUG
Laurens Miers's avatar
Laurens Miers committed
574
            memset(frame->buffer, 0x55, (size_t)(bufsize + iphdrsize));
gentci's avatar
gentci committed
575
#endif
576
            frame->net_hdr = frame->buffer + PICO_SIZE_ETHHDR;
577
            frame->net_len = iphdrsize;
578
            frag_dbg("[LUM:%s:%d] frame->net_len:%d  \n",__FILE__,__LINE__, frame->net_len);
gentci's avatar
gentci committed
579

580
            frame->transport_hdr = frame->net_hdr + iphdrsize;
laurens's avatar
laurens committed
581
            frame->transport_len = 0;
gentci's avatar
gentci committed
582 583

            frame->datalink_hdr = frame->buffer;
584

Ludo Mondelaers's avatar
Ludo Mondelaers committed
585
            fragment->net_hdr_offset = PICO_SIZE_ETHHDR;
Laurens Miers's avatar
Laurens Miers committed
586
            fragment->transport_hdr_offset = (uint32_t)(PICO_SIZE_ETHHDR + iphdrsize);
Ludo Mondelaers's avatar
Ludo Mondelaers committed
587 588


589
            fragment->frame = frame;
590 591 592

            fragment->holes.compare = hole_compare;
            fragment->holes.root = &LEAF;
593 594 595
        } else {
            PICO_FREE(fragment);
            fragment = NULL;
596 597
        }
    }
Laurens Miers's avatar
Laurens Miers committed
598
    return fragment;
599 600 601 602 603 604 605
}


static pico_fragment_t *pico_fragment_free(pico_fragment_t * fragment)
{
    if(fragment)
    {
606
        struct pico_tree_node *idx=NULL;
607
        struct pico_tree_node *tmp=NULL;
Laurens Miers's avatar
Laurens Miers committed
608

609 610 611
        /* cancel timer */
        if(fragment->expire)
        {
612
            fragment->expire = 0;
613
        }
Laurens Miers's avatar
Laurens Miers committed
614

615
        /*empty hole tree*/
Laurens Miers's avatar
Laurens Miers committed
616
        pico_tree_foreach_safe(idx, &fragment->holes, tmp)
617
        {
618
            pico_hole_t *hole = idx->keyValue;
Laurens Miers's avatar
Laurens Miers committed
619

620 621 622 623 624 625 626 627 628 629 630 631 632
            pico_tree_delete(&fragment->holes, hole);
            pico_hole_free(hole);
            hole = NULL;
        }

        if(fragment->frame)
        {
            /* discard frame*/
            pico_frame_discard(fragment->frame);
            fragment->frame = NULL;
        }
        pico_tree_delete(&pico_fragments, fragment);
        PICO_FREE(fragment);
633
        fragment = NULL;
634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651
    }
    return NULL;
}

/***
*
*  following functions use the hole algo as described in rfc815
*
***/



static int hole_compare(void* a,void* b)
{
    pico_hole_t *ha = (pico_hole_t *)a;
    pico_hole_t *hb = (pico_hole_t *)b;
    if(ha && hb)
    {
652
        return  (ha->first - hb->first);
653 654 655
    }
    else
    {
656
        return -1;
657 658 659 660
    }
}


661
static pico_hole_t* pico_hole_alloc(uint16_t first,uint16_t last)
662
{
663 664 665 666 667 668 669 670
    pico_hole_t* hole = NULL;

    if (first > last)
    {
        return NULL;
    }

    hole = PICO_ZALLOC(sizeof(pico_hole_t));
671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
    if(hole)
    {
        hole->first=first;
        hole->last=last;
    }
    return hole;
}


static pico_hole_t* pico_hole_free(pico_hole_t *hole)
{
    if(hole)
    {
        PICO_FREE(hole);
        hole=NULL;
    }
    return hole;
}

690 691 692 693 694 695
static int first_fragment_received(struct pico_tree *holes)
{
    pico_hole_t *hole = NULL;
    struct pico_tree_node *idx=NULL, *tmp=NULL;
    int retval = PICO_IP_FIRST_FRAG_RECV;

696 697
    frag_dbg("[LUM:%s:%d] Examine if first fragment was received. \n",__FILE__,__LINE__);

698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
    if (holes)
    {
        pico_tree_foreach_safe(idx, holes, tmp)
        {
            hole = idx->keyValue;
            frag_dbg("[LUM:%s:%d] examining hole:%d-%d \n",__FILE__,__LINE__,hole->first,hole->last);
            if (hole->first == 0)
            {
                /* We did not receive the first fragment, do not send notify*/
                frag_dbg("[LUM:%s:%d] we did not recv the first fragment, do not send notify \n",__FILE__,__LINE__);
                retval = PICO_IP_FIRST_FRAG_NOT_RECV;
                break;
            }
        }
    }
    else
    {
        retval = -1;
    }

    return retval;
}
720 721 722

static void pico_ip_frag_expired(pico_time now, void *arg)
{
Laurens Miers's avatar
Laurens Miers committed
723 724 725 726
    pico_fragment_t * fragment = NULL;
    struct pico_tree_node *idx = NULL;
    struct pico_tree_node *tmp = NULL;
    uint32_t empty = 1;
727

728 729
    (void)arg;
    pico_fragment_timer = NULL;  // timer expired
gentci's avatar
gentci committed
730
    //frag_dbg("[LUM:%s%d] inside pico_ip_frag_expired \n",__FILE__,__LINE__);
Laurens Miers's avatar
Laurens Miers committed
731 732

    pico_tree_foreach_safe(idx, &pico_fragments, tmp)
733 734 735 736
    {
        fragment = idx->keyValue;
        if(fragment->expire < now)
        {
Laurens Miers's avatar
Laurens Miers committed
737 738
            uint16_t ip_version = ((struct pico_eth_hdr *) fragment->frame->datalink_hdr)->proto;

Ludo Mondelaers's avatar
Ludo Mondelaers committed
739
            frag_dbg("[%s:%d] fragment expired:%p frag_id:0x%X \n",__FILE__,__LINE__,fragment, fragment->frag_id);
740
#ifdef PICO_SUPPORT_IPV6
741
            if (ip_version == PICO_IDETH_IPV6)
742
            {
743 744 745 746 747 748 749 750 751
                /* Check if we received the first fragment of the packet
                 * If so, we send a "frag expired". Else we don't.
                 */
                if (first_fragment_received(&fragment->holes) == PICO_IP_FIRST_FRAG_RECV)
                {
                    /* First fragment was recv, send notify */
                    frag_dbg("LUM[%s:%d] fragment expired:%p frag_id:0x%X, sending notify \n",__FILE__,__LINE__,fragment, fragment->frag_id);
                    pico_icmp6_frag_expired(fragment->frame);
                }
752
            }
753
#endif
754 755 756 757
            if (ip_version == PICO_IDETH_IPV4)
            {
                //TODO: what does IPV4 expect?
            }
758

759 760 761
            pico_fragment_free(fragment);
            fragment=NULL;
        }
gentci's avatar
gentci committed
762
        empty=0;
763
    }
gentci's avatar
gentci committed
764
    if(!empty)  // if still fragments in the tree...
765 766 767
    {
        // once the timer is expired, it is removed from the queue
        // if there are still fragments in the tree, restart the timer
gentci's avatar
gentci committed
768 769
        pico_fragment_timer = pico_timer_add(3000, /*cleanup expired fragments every x ms*/ pico_ip_frag_expired, NULL);
        //frag_dbg("[LUM:%s:%d] added timer %p \n",__FILE__,__LINE__,pico_fragment_timer);
770
    }
771 772 773
}


774
#define INFINITY 55555 /* just a big number <16bits*/
775

776
// note: offset and more flag are located differently in ipv4(iphdr) and ipv6(exthdr)
Laurens Miers's avatar
Laurens Miers committed
777
// offset is expressed in octets (bytes) (not the 8 byte unit used in ip)
778 779 780
//


781

782
static int pico_fragment_arrived(pico_fragment_t* fragment, struct pico_frame* frame, uint16_t offset, uint16_t more )
783
{
784
    struct pico_frame* full=NULL;
785
    int retval = -1;
786
    pico_hole_t *first = NULL;
787 788 789

    if(fragment && frame)
    {
Ludo Mondelaers's avatar
Ludo Mondelaers committed
790 791

#ifdef IPFRAG_DEBUG
792 793 794 795 796 797 798 799 800 801 802
        frag_dbg("[LUM:%s:%d] content of fragmented packet: %p net_len:%d transport_len:%d\n",__FILE__,__LINE__,fragment->frame->buffer,fragment->frame->net_len,fragment->frame->transport_len);
        if(1)
        {
            int i;
            for(i=0;i < fragment->frame->net_len;i=i+8)
            {
                frag_dbg("0x%04X: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X \n",i,
                         frame->buffer[i+0],frame->buffer[i+1],frame->buffer[i+2],frame->buffer[i+3],
                         frame->buffer[i+4],frame->buffer[i+5],frame->buffer[i+6],frame->buffer[i+7]);
            }
        }
Ludo Mondelaers's avatar
Ludo Mondelaers committed
803 804
#endif

805
        first = pico_tree_first(&fragment->holes);
Laurens Miers's avatar
Laurens Miers committed
806

807
        if(first == NULL)   /*first fragment of packet arrived*/
808
        {
809
            pico_hole_t *hole = pico_hole_alloc((uint16_t)0,(uint16_t)INFINITY);
gentci's avatar
gentci committed
810
            frag_dbg("[LUM:%s:%d] first fragment of packet arrived:fragment:%p fragment->holes:%p \n",__FILE__,__LINE__,fragment,&fragment->holes);
Laurens Miers's avatar
Laurens Miers committed
811

812
            if(hole)
813
            {
814
                pico_tree_insert(&fragment->holes,hole);
815
            }
Ludo Mondelaers's avatar
Ludo Mondelaers committed
816
            fragment->expire = PICO_TIME_MS() + PICO_IP_FRAG_TIMEOUT;  // fragment expires when the packet is not complete after timeout
817
            if(pico_fragment_timer == NULL)
818
            {
819
                pico_fragment_timer = pico_timer_add(1000, /*cleanup expired fragments every sec*/ pico_ip_frag_expired, NULL);
820
            }
Laurens Miers's avatar
Laurens Miers committed
821

822 823 824
            // Update pico device
            // TODO: do we need a pico_frame_copy/deepcopy for the other parameters?
            fragment->frame->dev = frame->dev;
Laurens Miers's avatar
Laurens Miers committed
825

826
        }
827 828

        // copy the received frame into the reassembled packet
Ludo Mondelaers's avatar
Ludo Mondelaers committed
829
        frag_dbg("[LUM:%s:%d] offset:%d frame->transport_len:%d fragment->frame->buffer_len:%d\n",__FILE__,__LINE__,offset,frame->transport_len,fragment->frame->buffer_len);
830
        if( (offset + frame->transport_len) <= fragment->frame->transport_len ) // check for buffer space
831
        {
832
            if(fragment->frame->transport_hdr && frame->transport_hdr)
833
            {
gentci's avatar
gentci committed
834 835
                //frag_dbg("[LUM:%s:%d]  Reassemble packet:      fragment:%p fragment->frame:%p fragment->frame->transport_hdr:%p frame:%p frame->transport_hdr:%p frame->transport_len:%d\n",
                //            __FILE__,__LINE__, fragment,   fragment->frame,   fragment->frame->transport_hdr,   frame,   frame->transport_hdr,   frame->transport_len);
Ludo Mondelaers's avatar
Ludo Mondelaers committed
836
                memcpy(fragment->frame->transport_hdr + offset , frame->transport_hdr, frame->transport_len);
837
                retval = frame->transport_len;
838
            }
839
            else
840
            {
841
                frag_dbg("[LUM:%s:%d] TODO: notify ICMP, no transport_hdrs",__FILE__,__LINE__);
842 843 844
                // notify icmp
                pico_fragment_free(fragment);
                fragment=NULL;
845
            }
846
        }
847
        else
848
        {
849
            // frame->buffer is too small
850
            // grow frame and copy new recv frame
851
            uint32_t alloc_len= frame->transport_len + fragment->frame->buffer_len;
852

853
            frag_dbg("[LUM:%s:%d] frame->buffer is too small-> realloc", __FILE__,__LINE__);
854 855 856
            frag_dbg("[LUM:%s:%d] frame->buffer original size: %d \n",__FILE__,__LINE__,fragment->frame->buffer_len);
            frag_dbg("[LUM:%s:%d] frame->buffer new size: %d \n",__FILE__,__LINE__, alloc_len);
            frag_dbg("[LUM:%s:%d] recv frame size: %d \n",__FILE__,__LINE__, frame->buffer_len);
857
            // copy hdrs + options + data
858
            if(pico_frame_grow(fragment->frame, alloc_len) == 0)
859
            {
860

Ludo Mondelaers's avatar
Ludo Mondelaers committed
861
                frag_dbg("[LUM:%s:%d] net_hdr:%p transport_hdr:%p\n",__FILE__,__LINE__,fragment->frame->net_hdr,fragment->frame->transport_hdr);
Laurens Miers's avatar
Laurens Miers committed
862

863 864
                /* Copy new frame */
                memcpy(fragment->frame->transport_hdr + offset , frame->transport_hdr, frame->transport_len);
865
                /* Update transport len */
866
                fragment->frame->transport_len = (uint16_t)(fragment->frame->transport_len + frame->transport_len);
867
                retval = frame->transport_len;
868 869 870
            }
            else
            {
Ludo Mondelaers's avatar
Ludo Mondelaers committed
871
				frag_dbg("[LUM:%s:%d] Failed to allocate frame buffer \n",__FILE__,__LINE__ );
872 873
                // discard packet: no more memory
                pico_fragment_free(fragment);
874 875
                pico_fragment_tree_mempressure_cleanup();
                
876
                return -1;
877 878 879
                // notify icmp
            }
        }
880 881 882 883 884 885 886



        if(!more)    /*last fragment of packet arrived*/
        {
            // retrieve the size of the reassembled packet
            pico_hole_t* hole = pico_tree_last(&fragment->holes);
Laurens Miers's avatar
Laurens Miers committed
887
            uint16_t reassambled_payload_len = (uint16_t)(offset + frame->transport_len);
888 889 890 891 892 893 894

            if(hole /*&& IS_LEAF(hole)*/)
            {
                hole->last = reassambled_payload_len;
                frag_dbg("[LUM:%s:%d] reassembled packet size:%d \n",__FILE__,__LINE__,hole->last);
                // adjust transport len
                frag_dbg("[LUM:%s:%d] before adjusted transportlen:%d \n",__FILE__,__LINE__,fragment->frame->transport_len);
Laurens Miers's avatar
Laurens Miers committed
895
                fragment->frame->transport_len = (uint16_t)(offset + frame->transport_len);
896 897 898 899 900 901 902 903 904
                frag_dbg("[LUM:%s:%d] after adjusted transportlen:%d \n",__FILE__,__LINE__,fragment->frame->transport_len);

                if(hole->first == hole->last)
                {
                    pico_tree_delete(&fragment->holes,hole);    // all done!
                }
            }

            // Update net_len in hdr
Laurens Miers's avatar
Laurens Miers committed
905 906
            fragment->frame->net_hdr[4] = (uint8_t)((reassambled_payload_len >> 8) &  0xFF);
            fragment->frame->net_hdr[5] = (uint8_t)((reassambled_payload_len) & 0xFF);
907 908

            // Update total buffer len
Laurens Miers's avatar
Laurens Miers committed
909 910
            fragment->frame->buffer_len = (uint32_t)(reassambled_payload_len + fragment->frame->net_len + PICO_SIZE_ETHHDR);
            fragment->frame->len = (uint32_t)(reassambled_payload_len + fragment->frame->net_len + PICO_SIZE_ETHHDR);
911 912 913
        }


914 915
    }
    // do the administration of the missing holes
916
    if(fragment && (full=fragment->frame) && frame)
917 918 919
    {
        struct pico_tree_node *idx=NULL, *tmp=NULL;
        pico_hole_t *hole = NULL;
Laurens Miers's avatar
Laurens Miers committed
920
        uint16_t    frame_first = offset;
Laurens Miers's avatar
Laurens Miers committed
921
        uint16_t    frame_last  = (uint16_t)(frame_first + frame->transport_len);
Laurens Miers's avatar
Laurens Miers committed
922

923

gentci's avatar
gentci committed
924
        frag_dbg("[LUM:%s:%d] frame_first:%d frame_last:%d offset:%d more:%d fragment->holes:%p \n",__FILE__,__LINE__,frame_first,frame_last,offset,more,&fragment->holes );
925 926

        /*RFC 815 step 1*/
Laurens Miers's avatar
Laurens Miers committed
927
        pico_tree_foreach_safe(idx, &fragment->holes, tmp)
928 929 930 931
        {
            hole = idx->keyValue;
            /*RFC 815 step 2*/
            if(frame_first > hole->last)
932
            {
933 934 935
                continue;
            }
            /*RFC 815 step 3*/
gentci's avatar
gentci committed
936
            else if(frame_last < hole->first)
937 938 939 940
            {
                continue;
            }
            /*RFC 815 step 4*/
gentci's avatar
gentci committed
941
            frag_dbg("[LUM:%s:%d] deleting hole:%d-%d \n",__FILE__,__LINE__,hole->first,hole->last);
942 943 944 945
            pico_tree_delete(&fragment->holes, hole);
            /*RFC 815 step 5*/
            if(frame_first > hole->first)
            {
Laurens Miers's avatar
Laurens Miers committed
946
                pico_hole_t *new_hole =  pico_hole_alloc(hole->first,(uint16_t)(frame_first - 1u));
947
                if(new_hole)
948
                {
gentci's avatar
gentci committed
949
                    frag_dbg("[LUM:%s:%d] inserting new hole:%d-%d \n",__FILE__,__LINE__,new_hole->first,new_hole->last);
950
                    pico_tree_insert(&fragment->holes, new_hole);
951
                }
952 953
            }
            /*RFC 815 step 6*/
gentci's avatar
gentci committed
954
            else if(frame_last < hole->last)
955
            {
Laurens Miers's avatar
Laurens Miers committed
956
                pico_hole_t *new_hole =  pico_hole_alloc((uint16_t)(frame_last + 1u),hole->last);
957
                if(new_hole)
958
                {
gentci's avatar
gentci committed
959
                    frag_dbg("[LUM:%s:%d] inserting new hole:%d-%d \n",__FILE__,__LINE__,new_hole->first,new_hole->last);
960
                    pico_tree_insert(&fragment->holes, new_hole);
961 962
                }
            }
963 964 965
            /*RFC 815 step 7*/
            PICO_FREE(hole);
            hole=NULL;
Laurens Miers's avatar
Laurens Miers committed
966
        }
967

Ludo Mondelaers's avatar
Ludo Mondelaers committed
968
#if 0 //def IPFRAG_DEBUG
gentci's avatar
gentci committed
969 970 971 972 973
        if(fragment)
        {
            struct pico_tree_node *idx2=NULL, *tmp2=NULL;
            pico_hole_t *hole2 = NULL;
            uint32_t empty=1;
Laurens Miers's avatar
Laurens Miers committed
974

gentci's avatar
gentci committed
975
            frag_dbg("[LUM:%s:%d] printing hole tree for fragment:%p id:0x%X fragment->holes:%p\n",__FILE__,__LINE__,fragment,fragment->frag_id,fragment->holes);
Laurens Miers's avatar
Laurens Miers committed
976
            pico_tree_foreach_safe(idx2, &fragment->holes, tmp2)
gentci's avatar
gentci committed
977 978 979 980 981 982 983 984 985 986
            {
                hole2 = idx2->keyValue;
                empty=0;

                frag_dbg("[LUM:%s:%d] first:%d last:%d \n",__FILE__,__LINE__,hole2?hole2->first:0,hole2?hole2->last:0);
            }
            frag_dbg("[LUM:%s:%d] %s \n",__FILE__,__LINE__,empty?"empty":"done");
        }
#endif

987 988 989 990
        /*RFC 815 step 8*/
        if(pico_tree_empty(&fragment->holes))
        {
            /* now send the reassembled packet upstream*/
Ludo Mondelaers's avatar
Ludo Mondelaers committed
991 992

#ifdef IPFRAG_DEBUG
993
            /*complete packet arrived: send full frame*/
994
            frag_dbg("[LUM:%s:%d] content of reassembled packet:  %p net_len:%d transport_len:%d\n",__FILE__,__LINE__,full->buffer,full->net_len,full->transport_len);
Ludo Mondelaers's avatar
Ludo Mondelaers committed
995 996 997
            if(1)
            {
				int i;
998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008
				int s=full->net_len + PICO_SIZE_ETHHDR;

				frag_dbg("-----------------------------\n");
				frag_dbg("ETH hdr: \n");
				for(i=0;i < PICO_SIZE_ETHHDR;i=i+7)
				{
					frag_dbg("0x%04X: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",i,
						full->buffer[i+0],full->buffer[i+1],full->buffer[i+2],full->buffer[i+3],
						full->buffer[i+4],full->buffer[i+5],full->buffer[i+6]);
				}
				frag_dbg("-----------------------------\n");
Laurens Miers's avatar
Laurens Miers committed
1009

1010 1011
				frag_dbg("NET hdr: \n");
				for(i=PICO_SIZE_ETHHDR;i < full->net_len + PICO_SIZE_ETHHDR;i=i+8)
Ludo Mondelaers's avatar
Ludo Mondelaers committed
1012 1013 1014 1015 1016 1017
				{
					frag_dbg("0x%04X: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X \n",i,
						full->buffer[i+0],full->buffer[i+1],full->buffer[i+2],full->buffer[i+3],
						full->buffer[i+4],full->buffer[i+5],full->buffer[i+6],full->buffer[i+7]);
				}
				frag_dbg("-----------------------------\n");
1018