Webserver+3d print

Dependents:   Nucleo

Committer:
Sergunb
Date:
Sat Feb 04 18:15:49 2017 +0000
Revision:
0:8918a71cdbe9
nothing else

Who changed what in which revision?

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