ipv4_frag.c
Go to the documentation of this file.
1 /**
2  * @file ipv4_frag.c
3  * @brief IPv4 fragmentation and reassembly
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneTCP Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @section Description
26  *
27  * The Internet Protocol (IP) implements datagram fragmentation, so that
28  * packets may be formed that can pass through a link with a smaller maximum
29  * transmission unit (MTU) than the original datagram size. Refer to the
30  * following RFCs for complete details:
31  * - RFC 791: Internet Protocol specification
32  * - RFC 815: IP datagram reassembly algorithms
33  *
34  * @author Oryx Embedded SARL (www.oryx-embedded.com)
35  * @version 1.9.0
36  **/
37 
38 //Switch to the appropriate trace level
39 #define TRACE_LEVEL IPV4_TRACE_LEVEL
40 
41 //Dependencies
42 #include "core/net.h"
43 #include "core/ip.h"
44 #include "ipv4/ipv4.h"
45 #include "ipv4/ipv4_frag.h"
46 #include "ipv4/icmp.h"
47 #include "mibs/mib2_module.h"
48 #include "mibs/ip_mib_module.h"
49 #include "debug.h"
50 
51 //Check TCP/IP stack configuration
52 #if (IPV4_SUPPORT == ENABLED && IPV4_FRAG_SUPPORT == ENABLED)
53 
54 //Tick counter to handle periodic operations
56 
57 
58 /**
59  * @brief Fragment an IPv4 datagram into smaller packets
60  * @param[in] interface Underlying network interface
61  * @param[in] pseudoHeader IPv4 pseudo header
62  * @param[in] id Fragment identification
63  * @param[in] payload Multi-part buffer containing the payload
64  * @param[in] payloadOffset Offset to the first payload byte
65  * @param[in] timeToLive TTL value
66  * @return Error code
67  **/
68 
70  uint16_t id, const NetBuffer *payload, size_t payloadOffset, uint8_t timeToLive)
71 {
72  error_t error;
73  size_t offset;
74  size_t length;
75  size_t payloadLen;
76  size_t fragmentOffset;
77  size_t maxFragmentSize;
78  NetBuffer *fragment;
79 
80  //Number of IP datagrams that would require fragmentation in order to be transmitted
81  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutFragReqds, 1);
82  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutFragReqds, 1);
83 
84  //Retrieve the length of the payload
85  payloadLen = netBufferGetLength(payload) - payloadOffset;
86 
87  //Allocate a memory buffer to hold IP fragments
88  fragment = ipAllocBuffer(0, &fragmentOffset);
89  //Failed to allocate memory?
90  if(!fragment)
91  return ERROR_OUT_OF_MEMORY;
92 
93  //Determine the maximum payload size for fragmented packets
94  maxFragmentSize = interface->ipv4Context.linkMtu - sizeof(Ipv4Header);
95  //The size shall be a multiple of 8-byte blocks
96  maxFragmentSize -= (maxFragmentSize % 8);
97 
98  //Initialize error code
99  error = NO_ERROR;
100 
101  //Split the payload into multiple IP fragments
102  for(offset = 0; offset < payloadLen; offset += length)
103  {
104  //Flush the contents of the fragment
105  error = netBufferSetLength(fragment, fragmentOffset);
106  //Sanity check
107  if(error)
108  break;
109 
110  //Process the last fragment?
111  if((payloadLen - offset) <= maxFragmentSize)
112  {
113  //Size of the current fragment
114  length = payloadLen - offset;
115  //Copy fragment data
116  netBufferConcat(fragment, payload, payloadOffset + offset, length);
117 
118  //Do not set the MF flag for the last fragment
119  error = ipv4SendPacket(interface, pseudoHeader, id,
120  offset / 8, fragment, fragmentOffset, timeToLive);
121  }
122  else
123  {
124  //Size of the current fragment (must be a multiple of 8-byte blocks)
125  length = maxFragmentSize;
126  //Copy fragment data
127  netBufferConcat(fragment, payload, payloadOffset + offset, length);
128 
129  //Fragmented packets must have the MF flag set
130  error = ipv4SendPacket(interface, pseudoHeader, id,
131  IPV4_FLAG_MF | (offset / 8), fragment, fragmentOffset, timeToLive);
132  }
133 
134  //Failed to send current IP packet?
135  if(error)
136  break;
137 
138  //Number of IP datagram fragments that have been generated as a result
139  //of fragmentation at this entity
140  MIB2_INC_COUNTER32(ipGroup.ipFragCreates, 1);
141  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutFragCreates, 1);
142  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutFragCreates, 1);
143  }
144 
145  //Check status code
146  if(error)
147  {
148  //Number of IP datagrams that have been discarded because they needed
149  //to be fragmented at this entity but could not be
150  MIB2_INC_COUNTER32(ipGroup.ipFragFails, 1);
151  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutFragFails, 1);
152  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutFragFails, 1);
153  }
154  else
155  {
156  //Number of IP datagrams that have been successfully fragmented at this entity
157  MIB2_INC_COUNTER32(ipGroup.ipFragOKs, 1);
158  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutFragOKs, 1);
159  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutFragOKs, 1);
160  }
161 
162  //Free previously allocated memory
163  netBufferFree(fragment);
164  //Return status code
165  return error;
166 }
167 
168 
169 /**
170  * @brief IPv4 datagram reassembly algorithm
171  * @param[in] interface Underlying network interface
172  * @param[in] packet Pointer to the IPv4 fragmented packet
173  * @param[in] length Packet length including header and payload
174  **/
175 
177  const Ipv4Header *packet, size_t length)
178 {
179  error_t error;
180  uint16_t offset;
181  uint16_t dataFirst;
182  uint16_t dataLast;
183  Ipv4FragDesc *frag;
184  Ipv4HoleDesc *hole;
185  Ipv4HoleDesc *prevHole;
186 
187  //Number of IP fragments received which needed to be reassembled
188  MIB2_INC_COUNTER32(ipGroup.ipReasmReqds, 1);
189  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmReqds, 1);
190  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmReqds, 1);
191 
192  //Get the length of the payload
193  length -= packet->headerLength * 4;
194  //Convert the fragment offset from network byte order
195  offset = ntohs(packet->fragmentOffset);
196 
197  //Every fragment except the last must contain a multiple of 8 bytes of data
198  if((offset & IPV4_FLAG_MF) && (length % 8))
199  {
200  //Number of failures detected by the IP reassembly algorithm
201  MIB2_INC_COUNTER32(ipGroup.ipReasmFails, 1);
202  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmFails, 1);
203  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmFails, 1);
204 
205  //Drop the incoming fragment
206  return;
207  }
208 
209  //Calculate the index of the first byte
210  dataFirst = (offset & IPV4_OFFSET_MASK) * 8;
211  //Calculate the index immediately following the last byte
212  dataLast = dataFirst + (uint16_t) length;
213 
214  //Search for a matching IP datagram being reassembled
215  frag = ipv4SearchFragQueue(interface, packet);
216 
217  //No matching entry in the reassembly queue?
218  if(frag == NULL)
219  {
220  //Number of failures detected by the IP reassembly algorithm
221  MIB2_INC_COUNTER32(ipGroup.ipReasmFails, 1);
222  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmFails, 1);
223  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmFails, 1);
224 
225  //Drop the incoming fragment
226  return;
227  }
228 
229  //The very first fragment requires special handling
230  if(!(offset & IPV4_OFFSET_MASK))
231  {
232  //Calculate the length of the IP header including options
233  frag->headerLength = packet->headerLength * 4;
234 
235  //Enforce the size of the reconstructed datagram
236  if((frag->headerLength + frag->dataLen) > IPV4_MAX_FRAG_DATAGRAM_SIZE)
237  {
238  //Number of failures detected by the IP reassembly algorithm
239  MIB2_INC_COUNTER32(ipGroup.ipReasmFails, 1);
240  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmFails, 1);
241  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmFails, 1);
242 
243  //Drop the reconstructed datagram
244  netBufferSetLength((NetBuffer *) &frag->buffer, 0);
245  //Exit immediately
246  return;
247  }
248 
249  //Make sure the IP header entirely fits in the first chunk
250  if(frag->headerLength > frag->buffer.chunk[0].size)
251  {
252  //Number of failures detected by the IP reassembly algorithm
253  MIB2_INC_COUNTER32(ipGroup.ipReasmFails, 1);
254  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmFails, 1);
255  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmFails, 1);
256 
257  //Drop the reconstructed datagram
258  netBufferSetLength((NetBuffer *) &frag->buffer, 0);
259  //Exit immediately
260  return;
261  }
262 
263  //Fix the length of the first chunk
264  frag->buffer.chunk[0].length = (uint16_t) frag->headerLength;
265  //Always take the IP header from the first fragment
266  netBufferWrite((NetBuffer *) &frag->buffer, 0, packet, frag->headerLength);
267  }
268 
269  //It may be necessary to increase the size of the buffer...
270  if(dataLast > frag->dataLen)
271  {
272  //Enforce the size of the reconstructed datagram
273  if((frag->headerLength + dataLast) > IPV4_MAX_FRAG_DATAGRAM_SIZE)
274  {
275  //Number of failures detected by the IP reassembly algorithm
276  MIB2_INC_COUNTER32(ipGroup.ipReasmFails, 1);
277  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmFails, 1);
278  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmFails, 1);
279 
280  //Drop the reconstructed datagram
281  netBufferSetLength((NetBuffer *) &frag->buffer, 0);
282  //Exit immediately
283  return;
284  }
285 
286  //Adjust the size of the reconstructed datagram
287  error = netBufferSetLength((NetBuffer *) &frag->buffer,
288  frag->headerLength + dataLast + sizeof(Ipv4HoleDesc));
289 
290  //Any error to report?
291  if(error)
292  {
293  //Number of failures detected by the IP reassembly algorithm
294  MIB2_INC_COUNTER32(ipGroup.ipReasmFails, 1);
295  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmFails, 1);
296  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmFails, 1);
297 
298  //Drop the reconstructed datagram
299  netBufferSetLength((NetBuffer *) &frag->buffer, 0);
300  //Exit immediately
301  return;
302  }
303 
304  //Actual length of the payload
305  frag->dataLen = dataLast;
306  }
307 
308  //Select the first hole descriptor from the list
309  hole = ipv4FindHole(frag, frag->firstHole);
310  //Keep track of the previous hole in the list
311  prevHole = NULL;
312 
313  //Iterate through the hole descriptors
314  while(hole != NULL)
315  {
316  //Save lower and upper boundaries for later use
317  uint16_t holeFirst = hole->first;
318  uint16_t holeLast = hole->last;
319 
320  //Check whether the newly arrived fragment interacts with this hole
321  //in some way
322  if(dataFirst < holeLast && dataLast > holeFirst)
323  {
324  //The current descriptor is no longer valid. We will destroy it,
325  //and in the next two steps, we will determine whether or not it
326  //is necessary to create any new hole descriptors
327  if(prevHole != NULL)
328  prevHole->next = hole->next;
329  else
330  frag->firstHole = hole->next;
331 
332  //Is there still a hole at the beginning of the segment?
333  if(dataFirst > holeFirst)
334  {
335  //Create a new entry that describes this hole
336  hole = ipv4FindHole(frag, holeFirst);
337  hole->first = holeFirst;
338  hole->last = dataFirst;
339 
340  //Insert the newly created entry into the hole descriptor list
341  if(prevHole != NULL)
342  {
343  hole->next = prevHole->next;
344  prevHole->next = hole->first;
345  }
346  else
347  {
348  hole->next = frag->firstHole;
349  frag->firstHole = hole->first;
350  }
351 
352  //Always keep track of the previous hole
353  prevHole = hole;
354  }
355 
356  //Is there still a hole at the end of the segment?
357  if(dataLast < holeLast && (offset & IPV4_FLAG_MF))
358  {
359  //Create a new entry that describes this hole
360  hole = ipv4FindHole(frag, dataLast);
361  hole->first = dataLast;
362  hole->last = holeLast;
363 
364  //Insert the newly created entry into the hole descriptor list
365  if(prevHole != NULL)
366  {
367  hole->next = prevHole->next;
368  prevHole->next = hole->first;
369  }
370  else
371  {
372  hole->next = frag->firstHole;
373  frag->firstHole = hole->first;
374  }
375 
376  //Always keep track of the previous hole
377  prevHole = hole;
378  }
379  }
380  else
381  {
382  //The newly arrived fragment does not interact with the current hole
383  prevHole = hole;
384  }
385 
386  //Select the next hole descriptor from the list
387  hole = ipv4FindHole(frag, prevHole ? prevHole->next : frag->firstHole);
388  }
389 
390  //Copy data from the fragment to the reassembly buffer
391  netBufferWrite((NetBuffer *) &frag->buffer,
392  frag->headerLength + dataFirst, IPV4_DATA(packet), length);
393 
394  //Dump hole descriptor list
395  ipv4DumpHoleList(frag);
396 
397  //If the hole descriptor list is empty, the reassembly process is now complete
398  if(!ipv4FindHole(frag, frag->firstHole))
399  {
400  //Discard the extra hole descriptor that follows the reconstructed datagram
401  error = netBufferSetLength((NetBuffer *) &frag->buffer,
402  frag->headerLength + frag->dataLen);
403 
404  //Check status code
405  if(error)
406  {
407  //Number of failures detected by the IP reassembly algorithm
408  MIB2_INC_COUNTER32(ipGroup.ipReasmFails, 1);
409  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmFails, 1);
410  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmFails, 1);
411  }
412  else
413  {
414  //Point to the IP header
415  Ipv4Header *datagram = netBufferAt((NetBuffer *) &frag->buffer, 0);
416 
417  //Fix IP header
418  datagram->totalLength = htons(frag->headerLength + frag->dataLen);
419  datagram->fragmentOffset = 0;
420  datagram->headerChecksum = 0;
421 
422  //Number of IP datagrams successfully reassembled
423  MIB2_INC_COUNTER32(ipGroup.ipReasmOKs, 1);
424  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmOKs, 1);
425  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmOKs, 1);
426 
427  //Pass the original IPv4 datagram to the higher protocol layer
428  ipv4ProcessDatagram(interface, (NetBuffer *) &frag->buffer);
429  }
430 
431  //Release previously allocated memory
432  netBufferSetLength((NetBuffer *) &frag->buffer, 0);
433  }
434 }
435 
436 
437 /**
438  * @brief Fragment reassembly timeout handler
439  *
440  * This routine must be periodically called by the TCP/IP stack to
441  * handle IPv4 fragment reassembly timeout
442  *
443  * @param[in] interface Underlying network interface
444  **/
445 
446 void ipv4FragTick(NetInterface *interface)
447 {
448  error_t error;
449  uint_t i;
450  systime_t time;
451  Ipv4HoleDesc *hole;
452 
453  //Get current time
454  time = osGetSystemTime();
455 
456  //Loop through the reassembly queue
457  for(i = 0; i < IPV4_MAX_FRAG_DATAGRAMS; i++)
458  {
459  //Point to the current entry in the reassembly queue
460  Ipv4FragDesc *frag = &interface->ipv4Context.fragQueue[i];
461 
462  //Make sure the entry is currently in use
463  if(frag->buffer.chunkCount > 0)
464  {
465  //If the timer runs out, the partially-reassembled datagram must be
466  //discarded and ICMP Time Exceeded message sent to the source host
467  if((time - frag->timestamp) >= IPV4_FRAG_TIME_TO_LIVE)
468  {
469  //Debug message
470  TRACE_INFO("IPv4 fragment reassembly timeout...\r\n");
471  //Dump IP header contents for debugging purpose
473 
474  //Number of failures detected by the IP reassembly algorithm
475  MIB2_INC_COUNTER32(ipGroup.ipReasmFails, 1);
476  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmFails, 1);
477  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmFails, 1);
478 
479  //Point to the first hole descriptor
480  hole = ipv4FindHole(frag, frag->firstHole);
481 
482  //Make sure the fragment zero has been received
483  //before sending an ICMP message
484  if(hole != NULL && hole->first > 0)
485  {
486  //Fix the size of the reconstructed datagram
487  error = netBufferSetLength((NetBuffer *) &frag->buffer,
488  frag->headerLength + hole->first);
489 
490  //Check status code
491  if(!error)
492  {
493  //Send an ICMP Time Exceeded message
496  }
497  }
498 
499  //Drop the partially reconstructed datagram
500  netBufferSetLength((NetBuffer *) &frag->buffer, 0);
501  }
502  }
503  }
504 }
505 
506 
507 /**
508  * @brief Search for a matching datagram in the reassembly queue
509  * @param[in] interface Underlying network interface
510  * @param[in] packet Incoming IPv4 packet
511  * @return Matching fragment descriptor
512  **/
513 
515 {
516  error_t error;
517  uint_t i;
518  Ipv4Header *datagram;
519  Ipv4FragDesc *frag;
520  Ipv4HoleDesc *hole;
521 
522  //Search for a matching IP datagram being reassembled
523  for(i = 0; i < IPV4_MAX_FRAG_DATAGRAMS; i++)
524  {
525  //Point to the current entry in the reassembly queue
526  frag = &interface->ipv4Context.fragQueue[i];
527 
528  //Check whether the current entry is used?
529  if(frag->buffer.chunkCount > 0)
530  {
531  //Point to the corresponding datagram
532  datagram = netBufferAt((NetBuffer *) &frag->buffer, 0);
533 
534  //Check source and destination addresses
535  if(datagram->srcAddr != packet->srcAddr)
536  continue;
537  if(datagram->destAddr != packet->destAddr)
538  continue;
539  //Compare identification and protocol fields
540  if(datagram->identification != packet->identification)
541  continue;
542  if(datagram->protocol != packet->protocol)
543  continue;
544 
545  //A matching entry has been found in the reassembly queue
546  return frag;
547  }
548  }
549 
550  //If the current packet does not match an existing entry
551  //in the reassembly queue, then create a new entry
552  for(i = 0; i < IPV4_MAX_FRAG_DATAGRAMS; i++)
553  {
554  //Point to the current entry in the reassembly queue
555  frag = &interface->ipv4Context.fragQueue[i];
556 
557  //The current entry is free?
558  if(!frag->buffer.chunkCount)
559  {
560  //Number of chunks that comprise the reassembly buffer
561  frag->buffer.maxChunkCount = arraysize(frag->buffer.chunk);
562 
563  //Allocate sufficient memory to hold the IPv4 header and
564  //the first hole descriptor
565  error = netBufferSetLength((NetBuffer *) &frag->buffer,
567 
568  //Failed to allocate memory?
569  if(error)
570  {
571  //Clean up side effects
572  netBufferSetLength((NetBuffer *) &frag->buffer, 0);
573  //Exit immediately
574  return NULL;
575  }
576 
577  //Initial length of the reconstructed datagram
578  frag->headerLength = packet->headerLength * 4;
579  frag->dataLen = 0;
580 
581  //Fix the length of the first chunk
582  frag->buffer.chunk[0].length = (uint16_t) frag->headerLength;
583  //Copy IPv4 header from the incoming fragment
584  netBufferWrite((NetBuffer *) &frag->buffer, 0, packet, frag->headerLength);
585 
586  //Save current time
587  frag->timestamp = osGetSystemTime();
588  //Create a new entry in the hole descriptor list
589  frag->firstHole = 0;
590 
591  //Point to first hole descriptor
592  hole = ipv4FindHole(frag, frag->firstHole);
593  //The entry describes the datagram as being completely missing
594  hole->first = 0;
595  hole->last = IPV4_INFINITY;
596  hole->next = IPV4_INFINITY;
597 
598  //Dump hole descriptor list
599  ipv4DumpHoleList(frag);
600 
601  //Return the matching fragment descriptor
602  return frag;
603  }
604  }
605 
606  //The reassembly queue is full
607  return NULL;
608 }
609 
610 
611 /**
612  * @brief Flush IPv4 reassembly queue
613  * @param[in] interface Underlying network interface
614  **/
615 
617 {
618  uint_t i;
619 
620  //Loop through the reassembly queue
621  for(i = 0; i < IPV4_MAX_FRAG_DATAGRAMS; i++)
622  {
623  //Drop any partially reconstructed datagram
624  netBufferSetLength((NetBuffer *) &interface->ipv4Context.fragQueue[i].buffer, 0);
625  }
626 }
627 
628 
629 /**
630  * @brief Retrieve hole descriptor
631  * @param[in] frag IPv4 fragment descriptor
632  * @param[in] offset Offset of the hole
633  * @return A pointer to the hole descriptor is returned if the
634  * specified offset is valid. Otherwise NULL is returned
635  **/
636 
637 Ipv4HoleDesc *ipv4FindHole(Ipv4FragDesc *frag, uint16_t offset)
638 {
639  //Return a pointer to the hole descriptor
640  return netBufferAt((NetBuffer *) &frag->buffer, frag->headerLength + offset);
641 }
642 
643 
644 /**
645  * @brief Dump hole descriptor list
646  * @param[in] frag IPv4 fragment descriptor
647  **/
648 
650 {
651 //Check debugging level
652 #if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
653  Ipv4HoleDesc *hole;
654 
655  //Debug message
656  TRACE_DEBUG("Hole descriptor list:\r\n");
657  //Select the first hole descriptor from the list
658  hole = ipv4FindHole(frag, frag->firstHole);
659 
660  //Loop through the hole descriptor list
661  while(hole != NULL)
662  {
663  //Display current hole
664  TRACE_DEBUG(" %" PRIu16 " - %" PRIu16 "\r\n", hole->first, hole->last);
665  //Select the next hole descriptor from the list
666  hole = ipv4FindHole(frag, hole->next);
667  }
668 #endif
669 }
670 
671 #endif
uint8_t payloadLen
Definition: ipv6.h:341
uint32_t systime_t
Definition: compiler_port.h:44
#define NET_MEM_POOL_BUFFER_SIZE
Definition: net_mem.h:53
error_t ipv4SendPacket(NetInterface *interface, Ipv4PseudoHeader *pseudoHeader, uint16_t fragId, size_t fragOffset, NetBuffer *buffer, size_t offset, uint8_t ttl)
Send an IPv4 packet.
Definition: ipv4.c:842
void ipv4DumpHeader(const Ipv4Header *ipHeader)
Dump IPv4 header for debugging purpose.
Definition: ipv4.c:1809
size_t headerLength
Length of the header.
Definition: ipv4_frag.h:124
systime_t osGetSystemTime(void)
Retrieve system time.
uint32_t time
TCP/IP stack core.
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:280
void ipv4DumpHoleList(Ipv4FragDesc *frag)
Dump hole descriptor list.
Definition: ipv4_frag.c:649
Debugging facilities.
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:295
#define IPV4_FRAG_TIME_TO_LIVE
Definition: ipv4_frag.h:67
void ipv4ProcessDatagram(NetInterface *interface, const NetBuffer *buffer)
Incoming IPv4 datagram processing.
Definition: ipv4.c:627
error_t netBufferSetLength(NetBuffer *buffer, size_t length)
Adjust the length of a multi-part buffer.
Definition: net_mem.c:318
MIB-II module.
#define IPV4_DATA(packet)
Definition: ipv4.h:85
IPv4 and IPv6 common routines.
systime_t ipv4FragTickCounter
Definition: ipv4_frag.c:55
#define htons(value)
Definition: cpu_endian.h:390
#define MIB2_INC_COUNTER32(name, value)
Definition: mib2_module.h:154
#define Ipv4PseudoHeader
Definition: ipv4.h:37
void * address
Definition: net_mem.h:76
#define IPV4_MAX_FRAG_DATAGRAM_SIZE
Definition: ipv4_frag.h:60
void ipv4FlushFragQueue(NetInterface *interface)
Flush IPv4 reassembly queue.
Definition: ipv4_frag.c:616
error_t icmpSendErrorMessage(NetInterface *interface, uint8_t type, uint8_t code, uint8_t parameter, const NetBuffer *ipPacket, size_t ipPacketOffset)
Send an ICMP Error message.
Definition: icmp.c:230
#define arraysize(a)
Definition: os_port.h:68
error_t netBufferConcat(NetBuffer *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Concatenate two multi-part buffers.
Definition: net_mem.c:440
#define IPV4_INFINITY
Definition: ipv4_frag.h:73
Fragmented packet descriptor.
Definition: ipv4_frag.h:121
#define ntohs(value)
Definition: cpu_endian.h:396
systime_t timestamp
Time at which the first fragment was received.
Definition: ipv4_frag.h:123
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:411
NetBuffer * ipAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an IP packet.
Definition: ip.c:596
IPv4 (Internet Protocol Version 4)
Ipv4ReassemblyBuffer buffer
Buffer containing the reassembled datagram.
Definition: ipv4_frag.h:127
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:86
IP MIB module.
IPv4 fragmentation and reassembly.
error_t ipv4FragmentDatagram(NetInterface *interface, Ipv4PseudoHeader *pseudoHeader, uint16_t id, const NetBuffer *payload, size_t payloadOffset, uint8_t timeToLive)
Fragment an IPv4 datagram into smaller packets.
Definition: ipv4_frag.c:69
#define TRACE_INFO(...)
Definition: debug.h:86
Ipv4HoleDesc * ipv4FindHole(Ipv4FragDesc *frag, uint16_t offset)
Retrieve hole descriptor.
Definition: ipv4_frag.c:637
Success.
Definition: error.h:42
uint16_t length
Definition: net_mem.h:77
error_t
Error codes.
Definition: error.h:40
#define IP_MIB_INC_COUNTER32(name, value)
Definition: ip_mib_module.h:44
void ipv4ReassembleDatagram(NetInterface *interface, const Ipv4Header *packet, size_t length)
IPv4 datagram reassembly algorithm.
Definition: ipv4_frag.c:176
unsigned int uint_t
Definition: compiler_port.h:43
#define NetInterface
Definition: net.h:34
#define Ipv4Header
Definition: ipv4.h:34
ICMP (Internet Control Message Protocol)
size_t netBufferWrite(NetBuffer *dest, size_t destOffset, const void *src, size_t length)
Write data to a multi-part buffer.
Definition: net_mem.c:617
__start_packed struct @175 Ipv4HoleDesc
Hole descriptor.
void ipv4FragTick(NetInterface *interface)
Fragment reassembly timeout handler.
Definition: ipv4_frag.c:446
uint8_t length
Definition: dtls_misc.h:140
uint16_t firstHole
Index of the first hole.
Definition: ipv4_frag.h:126
size_t dataLen
Length of the payload.
Definition: ipv4_frag.h:125
Ipv4FragDesc * ipv4SearchFragQueue(NetInterface *interface, const Ipv4Header *packet)
Search for a matching datagram in the reassembly queue.
Definition: ipv4_frag.c:514
ChunkDesc chunk[N(IPV4_MAX_FRAG_DATAGRAM_SIZE)+1]
Definition: ipv4_frag.h:113
#define TRACE_DEBUG(...)
Definition: debug.h:98
#define IPV4_MAX_FRAG_DATAGRAMS
Definition: ipv4_frag.h:53