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 ip.c
Sergunb 0:8918a71cdbe9 3 * @brief IPv4 and IPv6 common routines
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 IP_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/ethernet.h"
Sergunb 0:8918a71cdbe9 35 #include "core/ip.h"
Sergunb 0:8918a71cdbe9 36 #include "ipv4/ipv4.h"
Sergunb 0:8918a71cdbe9 37 #include "ipv6/ipv6.h"
Sergunb 0:8918a71cdbe9 38 #include "ipv6/ipv6_misc.h"
Sergunb 0:8918a71cdbe9 39 #include "debug.h"
Sergunb 0:8918a71cdbe9 40
Sergunb 0:8918a71cdbe9 41 //Special IP address
Sergunb 0:8918a71cdbe9 42 const IpAddr IP_ADDR_ANY = {0};
Sergunb 0:8918a71cdbe9 43 const IpAddr IP_ADDR_UNSPECIFIED = {0};
Sergunb 0:8918a71cdbe9 44
Sergunb 0:8918a71cdbe9 45
Sergunb 0:8918a71cdbe9 46 /**
Sergunb 0:8918a71cdbe9 47 * @brief Send an IP datagram
Sergunb 0:8918a71cdbe9 48 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 49 * @param[in] pseudoHeader IP pseudo header
Sergunb 0:8918a71cdbe9 50 * @param[in] buffer Multi-part buffer containing the payload
Sergunb 0:8918a71cdbe9 51 * @param[in] offset Offset to the first payload byte
Sergunb 0:8918a71cdbe9 52 * @param[in] ttl TTL value. Default Time-To-Live is used when this parameter is zero
Sergunb 0:8918a71cdbe9 53 * @return Error code
Sergunb 0:8918a71cdbe9 54 **/
Sergunb 0:8918a71cdbe9 55
Sergunb 0:8918a71cdbe9 56 error_t ipSendDatagram(NetInterface *interface, IpPseudoHeader *pseudoHeader,
Sergunb 0:8918a71cdbe9 57 NetBuffer *buffer, size_t offset, uint8_t ttl)
Sergunb 0:8918a71cdbe9 58 {
Sergunb 0:8918a71cdbe9 59 error_t error;
Sergunb 0:8918a71cdbe9 60
Sergunb 0:8918a71cdbe9 61 #if (IPV4_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 62 //Destination address is an IPv4 address?
Sergunb 0:8918a71cdbe9 63 if(pseudoHeader->length == sizeof(Ipv4PseudoHeader))
Sergunb 0:8918a71cdbe9 64 {
Sergunb 0:8918a71cdbe9 65 //Form an IPv4 packet and send it
Sergunb 0:8918a71cdbe9 66 error = ipv4SendDatagram(interface, &pseudoHeader->ipv4Data,
Sergunb 0:8918a71cdbe9 67 buffer, offset, ttl);
Sergunb 0:8918a71cdbe9 68 }
Sergunb 0:8918a71cdbe9 69 else
Sergunb 0:8918a71cdbe9 70 #endif
Sergunb 0:8918a71cdbe9 71 #if (IPV6_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 72 //Destination address is an IPv6 address?
Sergunb 0:8918a71cdbe9 73 if(pseudoHeader->length == sizeof(Ipv6PseudoHeader))
Sergunb 0:8918a71cdbe9 74 {
Sergunb 0:8918a71cdbe9 75 //Form an IPv6 packet and send it
Sergunb 0:8918a71cdbe9 76 error = ipv6SendDatagram(interface, &pseudoHeader->ipv6Data,
Sergunb 0:8918a71cdbe9 77 buffer, offset, ttl);
Sergunb 0:8918a71cdbe9 78 }
Sergunb 0:8918a71cdbe9 79 else
Sergunb 0:8918a71cdbe9 80 #endif
Sergunb 0:8918a71cdbe9 81 //Destination address is invalid
Sergunb 0:8918a71cdbe9 82 {
Sergunb 0:8918a71cdbe9 83 //Report an error
Sergunb 0:8918a71cdbe9 84 error = ERROR_INVALID_ADDRESS;
Sergunb 0:8918a71cdbe9 85 }
Sergunb 0:8918a71cdbe9 86
Sergunb 0:8918a71cdbe9 87 //Return status code
Sergunb 0:8918a71cdbe9 88 return error;
Sergunb 0:8918a71cdbe9 89 }
Sergunb 0:8918a71cdbe9 90
Sergunb 0:8918a71cdbe9 91
Sergunb 0:8918a71cdbe9 92 /**
Sergunb 0:8918a71cdbe9 93 * @brief IP source address selection
Sergunb 0:8918a71cdbe9 94 *
Sergunb 0:8918a71cdbe9 95 * This function selects the source address and the relevant network interface
Sergunb 0:8918a71cdbe9 96 * to be used in order to join the specified destination address
Sergunb 0:8918a71cdbe9 97 *
Sergunb 0:8918a71cdbe9 98 * @param[in,out] interface A pointer to a valid network interface may be provided as
Sergunb 0:8918a71cdbe9 99 * a hint. The function returns a pointer identifying the interface to be used
Sergunb 0:8918a71cdbe9 100 * @param[in] destAddr Destination IP address
Sergunb 0:8918a71cdbe9 101 * @param[out] srcAddr Local IP address to be used
Sergunb 0:8918a71cdbe9 102 * @return Error code
Sergunb 0:8918a71cdbe9 103 **/
Sergunb 0:8918a71cdbe9 104
Sergunb 0:8918a71cdbe9 105 error_t ipSelectSourceAddr(NetInterface **interface,
Sergunb 0:8918a71cdbe9 106 const IpAddr *destAddr, IpAddr *srcAddr)
Sergunb 0:8918a71cdbe9 107 {
Sergunb 0:8918a71cdbe9 108 #if (IPV4_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 109 //The destination address is an IPv4 address?
Sergunb 0:8918a71cdbe9 110 if(destAddr->length == sizeof(Ipv4Addr))
Sergunb 0:8918a71cdbe9 111 {
Sergunb 0:8918a71cdbe9 112 //An IPv4 address is expected
Sergunb 0:8918a71cdbe9 113 srcAddr->length = sizeof(Ipv4Addr);
Sergunb 0:8918a71cdbe9 114 //Get the most appropriate source address to use
Sergunb 0:8918a71cdbe9 115 return ipv4SelectSourceAddr(interface, destAddr->ipv4Addr, &srcAddr->ipv4Addr);
Sergunb 0:8918a71cdbe9 116 }
Sergunb 0:8918a71cdbe9 117 else
Sergunb 0:8918a71cdbe9 118 #endif
Sergunb 0:8918a71cdbe9 119 #if (IPV6_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 120 //The destination address is an IPv6 address?
Sergunb 0:8918a71cdbe9 121 if(destAddr->length == sizeof(Ipv6Addr))
Sergunb 0:8918a71cdbe9 122 {
Sergunb 0:8918a71cdbe9 123 //An IPv6 address is expected
Sergunb 0:8918a71cdbe9 124 srcAddr->length = sizeof(Ipv6Addr);
Sergunb 0:8918a71cdbe9 125 //Get the most appropriate source address to use
Sergunb 0:8918a71cdbe9 126 return ipv6SelectSourceAddr(interface, &destAddr->ipv6Addr, &srcAddr->ipv6Addr);
Sergunb 0:8918a71cdbe9 127 }
Sergunb 0:8918a71cdbe9 128 else
Sergunb 0:8918a71cdbe9 129 #endif
Sergunb 0:8918a71cdbe9 130 //The destination address is not valid?
Sergunb 0:8918a71cdbe9 131 {
Sergunb 0:8918a71cdbe9 132 //Report an error
Sergunb 0:8918a71cdbe9 133 return ERROR_INVALID_ADDRESS;
Sergunb 0:8918a71cdbe9 134 }
Sergunb 0:8918a71cdbe9 135 }
Sergunb 0:8918a71cdbe9 136
Sergunb 0:8918a71cdbe9 137
Sergunb 0:8918a71cdbe9 138 /**
Sergunb 0:8918a71cdbe9 139 * @brief IP checksum calculation
Sergunb 0:8918a71cdbe9 140 * @param[in] data Pointer to the data over which to calculate the IP checksum
Sergunb 0:8918a71cdbe9 141 * @param[in] length Number of bytes to process
Sergunb 0:8918a71cdbe9 142 * @return Checksum value
Sergunb 0:8918a71cdbe9 143 **/
Sergunb 0:8918a71cdbe9 144
Sergunb 0:8918a71cdbe9 145 uint16_t ipCalcChecksum(const void *data, size_t length)
Sergunb 0:8918a71cdbe9 146 {
Sergunb 0:8918a71cdbe9 147 //Checksum preset value
Sergunb 0:8918a71cdbe9 148 uint32_t checksum = 0x0000;
Sergunb 0:8918a71cdbe9 149
Sergunb 0:8918a71cdbe9 150 //Process all the data
Sergunb 0:8918a71cdbe9 151 while(length > 1)
Sergunb 0:8918a71cdbe9 152 {
Sergunb 0:8918a71cdbe9 153 //Update checksum value
Sergunb 0:8918a71cdbe9 154 checksum += *((uint16_t *) data);
Sergunb 0:8918a71cdbe9 155 //Point to the next 16-bit word
Sergunb 0:8918a71cdbe9 156 data = (uint16_t *) data + 1;
Sergunb 0:8918a71cdbe9 157 //Adjust the number of remaining words to process
Sergunb 0:8918a71cdbe9 158 length -= 2;
Sergunb 0:8918a71cdbe9 159 }
Sergunb 0:8918a71cdbe9 160
Sergunb 0:8918a71cdbe9 161 //Add left-over byte, if any
Sergunb 0:8918a71cdbe9 162 if(length > 0)
Sergunb 0:8918a71cdbe9 163 checksum += *((uint8_t *) data);
Sergunb 0:8918a71cdbe9 164
Sergunb 0:8918a71cdbe9 165 //Fold 32-bit sum to 16 bits
Sergunb 0:8918a71cdbe9 166 while(checksum >> 16)
Sergunb 0:8918a71cdbe9 167 checksum = (checksum & 0xFFFF) + (checksum >> 16);
Sergunb 0:8918a71cdbe9 168
Sergunb 0:8918a71cdbe9 169 //Return 1's complement value
Sergunb 0:8918a71cdbe9 170 return checksum ^ 0xFFFF;
Sergunb 0:8918a71cdbe9 171 }
Sergunb 0:8918a71cdbe9 172
Sergunb 0:8918a71cdbe9 173
Sergunb 0:8918a71cdbe9 174 /**
Sergunb 0:8918a71cdbe9 175 * @brief Calculate IP checksum over a multi-part buffer
Sergunb 0:8918a71cdbe9 176 * @param[in] buffer Pointer to the multi-part buffer
Sergunb 0:8918a71cdbe9 177 * @param[in] offset Offset from the beginning of the buffer
Sergunb 0:8918a71cdbe9 178 * @param[in] length Number of bytes to process
Sergunb 0:8918a71cdbe9 179 * @return Checksum value
Sergunb 0:8918a71cdbe9 180 **/
Sergunb 0:8918a71cdbe9 181
Sergunb 0:8918a71cdbe9 182 uint16_t ipCalcChecksumEx(const NetBuffer *buffer, size_t offset, size_t length)
Sergunb 0:8918a71cdbe9 183 {
Sergunb 0:8918a71cdbe9 184 uint_t i;
Sergunb 0:8918a71cdbe9 185 uint_t m;
Sergunb 0:8918a71cdbe9 186 uint_t n;
Sergunb 0:8918a71cdbe9 187 bool_t odd;
Sergunb 0:8918a71cdbe9 188 uint8_t *data;
Sergunb 0:8918a71cdbe9 189 uint32_t checksum;
Sergunb 0:8918a71cdbe9 190
Sergunb 0:8918a71cdbe9 191 //Checksum preset value
Sergunb 0:8918a71cdbe9 192 checksum = 0x0000;
Sergunb 0:8918a71cdbe9 193 //Total number of bytes processed
Sergunb 0:8918a71cdbe9 194 n = 0;
Sergunb 0:8918a71cdbe9 195
Sergunb 0:8918a71cdbe9 196 //Loop through data chunks
Sergunb 0:8918a71cdbe9 197 for(i = 0; i < buffer->chunkCount && n < length; i++)
Sergunb 0:8918a71cdbe9 198 {
Sergunb 0:8918a71cdbe9 199 //Is there any data to process in the current chunk?
Sergunb 0:8918a71cdbe9 200 if(offset < buffer->chunk[i].length)
Sergunb 0:8918a71cdbe9 201 {
Sergunb 0:8918a71cdbe9 202 //Check whether the total number of bytes already processed is odd
Sergunb 0:8918a71cdbe9 203 odd = (n & 1) ? TRUE : FALSE;
Sergunb 0:8918a71cdbe9 204
Sergunb 0:8918a71cdbe9 205 //Point to the first data byte
Sergunb 0:8918a71cdbe9 206 data = (uint8_t *) buffer->chunk[i].address + offset;
Sergunb 0:8918a71cdbe9 207
Sergunb 0:8918a71cdbe9 208 //Number of bytes available in the current chunk
Sergunb 0:8918a71cdbe9 209 m = buffer->chunk[i].length - offset;
Sergunb 0:8918a71cdbe9 210 //Limit the number of byte to process
Sergunb 0:8918a71cdbe9 211 m = MIN(m, length - n);
Sergunb 0:8918a71cdbe9 212
Sergunb 0:8918a71cdbe9 213 //Now adjust the total length
Sergunb 0:8918a71cdbe9 214 n += m;
Sergunb 0:8918a71cdbe9 215
Sergunb 0:8918a71cdbe9 216 //Data buffer is not aligned on 16-bit boundaries?
Sergunb 0:8918a71cdbe9 217 if((uint_t) data & 1)
Sergunb 0:8918a71cdbe9 218 {
Sergunb 0:8918a71cdbe9 219 //The total number of bytes is even?
Sergunb 0:8918a71cdbe9 220 if(!odd)
Sergunb 0:8918a71cdbe9 221 {
Sergunb 0:8918a71cdbe9 222 //Fold 32-bit sum to 16 bits
Sergunb 0:8918a71cdbe9 223 while(checksum >> 16)
Sergunb 0:8918a71cdbe9 224 checksum = (checksum & 0xFFFF) + (checksum >> 16);
Sergunb 0:8918a71cdbe9 225 //Swap checksum value
Sergunb 0:8918a71cdbe9 226 checksum = ((checksum >> 8) | (checksum << 8)) & 0xFFFF;
Sergunb 0:8918a71cdbe9 227 }
Sergunb 0:8918a71cdbe9 228
Sergunb 0:8918a71cdbe9 229 //Restore the alignment on 16-bit boundaries
Sergunb 0:8918a71cdbe9 230 if(m > 0)
Sergunb 0:8918a71cdbe9 231 {
Sergunb 0:8918a71cdbe9 232 #ifdef _CPU_BIG_ENDIAN
Sergunb 0:8918a71cdbe9 233 //Update checksum value
Sergunb 0:8918a71cdbe9 234 checksum += *data;
Sergunb 0:8918a71cdbe9 235 #else
Sergunb 0:8918a71cdbe9 236 //Update checksum value
Sergunb 0:8918a71cdbe9 237 checksum += *data << 8;
Sergunb 0:8918a71cdbe9 238 #endif
Sergunb 0:8918a71cdbe9 239 //Point to the next byte
Sergunb 0:8918a71cdbe9 240 data += 1;
Sergunb 0:8918a71cdbe9 241 m -= 1;
Sergunb 0:8918a71cdbe9 242 }
Sergunb 0:8918a71cdbe9 243
Sergunb 0:8918a71cdbe9 244 //Process the data 2 bytes at a time
Sergunb 0:8918a71cdbe9 245 while(m > 1)
Sergunb 0:8918a71cdbe9 246 {
Sergunb 0:8918a71cdbe9 247 //Update checksum value
Sergunb 0:8918a71cdbe9 248 checksum += *((uint16_t *) data);
Sergunb 0:8918a71cdbe9 249 //Point to the next 16-bit word
Sergunb 0:8918a71cdbe9 250 data += 2;
Sergunb 0:8918a71cdbe9 251 m -= 2;
Sergunb 0:8918a71cdbe9 252 }
Sergunb 0:8918a71cdbe9 253
Sergunb 0:8918a71cdbe9 254 //Add left-over byte, if any
Sergunb 0:8918a71cdbe9 255 if(m > 0)
Sergunb 0:8918a71cdbe9 256 {
Sergunb 0:8918a71cdbe9 257 #ifdef _CPU_BIG_ENDIAN
Sergunb 0:8918a71cdbe9 258 //Update checksum value
Sergunb 0:8918a71cdbe9 259 checksum += *data << 8;
Sergunb 0:8918a71cdbe9 260 #else
Sergunb 0:8918a71cdbe9 261 //Update checksum value
Sergunb 0:8918a71cdbe9 262 checksum += *data;
Sergunb 0:8918a71cdbe9 263 #endif
Sergunb 0:8918a71cdbe9 264 }
Sergunb 0:8918a71cdbe9 265
Sergunb 0:8918a71cdbe9 266 //Restore checksum endianness
Sergunb 0:8918a71cdbe9 267 if(!odd)
Sergunb 0:8918a71cdbe9 268 {
Sergunb 0:8918a71cdbe9 269 //Fold 32-bit sum to 16 bits
Sergunb 0:8918a71cdbe9 270 while(checksum >> 16)
Sergunb 0:8918a71cdbe9 271 checksum = (checksum & 0xFFFF) + (checksum >> 16);
Sergunb 0:8918a71cdbe9 272 //Swap checksum value
Sergunb 0:8918a71cdbe9 273 checksum = ((checksum >> 8) | (checksum << 8)) & 0xFFFF;
Sergunb 0:8918a71cdbe9 274 }
Sergunb 0:8918a71cdbe9 275 }
Sergunb 0:8918a71cdbe9 276 //Data buffer is aligned on 16-bit boundaries?
Sergunb 0:8918a71cdbe9 277 else
Sergunb 0:8918a71cdbe9 278 {
Sergunb 0:8918a71cdbe9 279 //The total number of bytes is odd?
Sergunb 0:8918a71cdbe9 280 if(odd)
Sergunb 0:8918a71cdbe9 281 {
Sergunb 0:8918a71cdbe9 282 //Fold 32-bit sum to 16 bits
Sergunb 0:8918a71cdbe9 283 while(checksum >> 16)
Sergunb 0:8918a71cdbe9 284 checksum = (checksum & 0xFFFF) + (checksum >> 16);
Sergunb 0:8918a71cdbe9 285 //Swap checksum value
Sergunb 0:8918a71cdbe9 286 checksum = ((checksum >> 8) | (checksum << 8)) & 0xFFFF;
Sergunb 0:8918a71cdbe9 287 }
Sergunb 0:8918a71cdbe9 288
Sergunb 0:8918a71cdbe9 289 //Process the data 2 bytes at a time
Sergunb 0:8918a71cdbe9 290 while(m > 1)
Sergunb 0:8918a71cdbe9 291 {
Sergunb 0:8918a71cdbe9 292 //Update checksum value
Sergunb 0:8918a71cdbe9 293 checksum += *((uint16_t *) data);
Sergunb 0:8918a71cdbe9 294 //Point to the next 16-bit word
Sergunb 0:8918a71cdbe9 295 data += 2;
Sergunb 0:8918a71cdbe9 296 m -= 2;
Sergunb 0:8918a71cdbe9 297 }
Sergunb 0:8918a71cdbe9 298
Sergunb 0:8918a71cdbe9 299 //Add left-over byte, if any
Sergunb 0:8918a71cdbe9 300 if(m > 0)
Sergunb 0:8918a71cdbe9 301 {
Sergunb 0:8918a71cdbe9 302 #ifdef _CPU_BIG_ENDIAN
Sergunb 0:8918a71cdbe9 303 //Update checksum value
Sergunb 0:8918a71cdbe9 304 checksum += *data << 8;
Sergunb 0:8918a71cdbe9 305 #else
Sergunb 0:8918a71cdbe9 306 //Update checksum value
Sergunb 0:8918a71cdbe9 307 checksum += *data;
Sergunb 0:8918a71cdbe9 308 #endif
Sergunb 0:8918a71cdbe9 309 }
Sergunb 0:8918a71cdbe9 310
Sergunb 0:8918a71cdbe9 311 //Restore checksum endianness
Sergunb 0:8918a71cdbe9 312 if(odd)
Sergunb 0:8918a71cdbe9 313 {
Sergunb 0:8918a71cdbe9 314 //Fold 32-bit sum to 16 bits
Sergunb 0:8918a71cdbe9 315 while(checksum >> 16)
Sergunb 0:8918a71cdbe9 316 checksum = (checksum & 0xFFFF) + (checksum >> 16);
Sergunb 0:8918a71cdbe9 317 //Swap checksum value
Sergunb 0:8918a71cdbe9 318 checksum = ((checksum >> 8) | (checksum << 8)) & 0xFFFF;
Sergunb 0:8918a71cdbe9 319 }
Sergunb 0:8918a71cdbe9 320 }
Sergunb 0:8918a71cdbe9 321
Sergunb 0:8918a71cdbe9 322 //Process the next block from the start
Sergunb 0:8918a71cdbe9 323 offset = 0;
Sergunb 0:8918a71cdbe9 324 }
Sergunb 0:8918a71cdbe9 325 else
Sergunb 0:8918a71cdbe9 326 {
Sergunb 0:8918a71cdbe9 327 //Skip the current chunk
Sergunb 0:8918a71cdbe9 328 offset -= buffer->chunk[i].length;
Sergunb 0:8918a71cdbe9 329 }
Sergunb 0:8918a71cdbe9 330 }
Sergunb 0:8918a71cdbe9 331
Sergunb 0:8918a71cdbe9 332 //Fold 32-bit sum to 16 bits
Sergunb 0:8918a71cdbe9 333 while(checksum >> 16)
Sergunb 0:8918a71cdbe9 334 checksum = (checksum & 0xFFFF) + (checksum >> 16);
Sergunb 0:8918a71cdbe9 335
Sergunb 0:8918a71cdbe9 336 //Return 1's complement value
Sergunb 0:8918a71cdbe9 337 return checksum ^ 0xFFFF;
Sergunb 0:8918a71cdbe9 338 }
Sergunb 0:8918a71cdbe9 339
Sergunb 0:8918a71cdbe9 340
Sergunb 0:8918a71cdbe9 341 /**
Sergunb 0:8918a71cdbe9 342 * @brief Calculate IP upper-layer checksum
Sergunb 0:8918a71cdbe9 343 * @param[in] pseudoHeader Pointer to the pseudo header
Sergunb 0:8918a71cdbe9 344 * @param[in] pseudoHeaderLength Pseudo header length
Sergunb 0:8918a71cdbe9 345 * @param[in] data Pointer to the upper-layer data
Sergunb 0:8918a71cdbe9 346 * @param[in] dataLength Upper-layer data length
Sergunb 0:8918a71cdbe9 347 * @return Checksum value
Sergunb 0:8918a71cdbe9 348 **/
Sergunb 0:8918a71cdbe9 349
Sergunb 0:8918a71cdbe9 350 uint16_t ipCalcUpperLayerChecksum(const void *pseudoHeader,
Sergunb 0:8918a71cdbe9 351 size_t pseudoHeaderLength, const void *data, size_t dataLength)
Sergunb 0:8918a71cdbe9 352 {
Sergunb 0:8918a71cdbe9 353 //Checksum preset value
Sergunb 0:8918a71cdbe9 354 uint32_t checksum = 0x0000;
Sergunb 0:8918a71cdbe9 355
Sergunb 0:8918a71cdbe9 356 //Process pseudo header
Sergunb 0:8918a71cdbe9 357 while(pseudoHeaderLength > 1)
Sergunb 0:8918a71cdbe9 358 {
Sergunb 0:8918a71cdbe9 359 //Update checksum value
Sergunb 0:8918a71cdbe9 360 checksum += *((uint16_t *) pseudoHeader);
Sergunb 0:8918a71cdbe9 361 //Point to the next 16-bit word
Sergunb 0:8918a71cdbe9 362 pseudoHeader = (uint16_t *) pseudoHeader + 1;
Sergunb 0:8918a71cdbe9 363 //Adjust the number of remaining words to process
Sergunb 0:8918a71cdbe9 364 pseudoHeaderLength -= 2;
Sergunb 0:8918a71cdbe9 365 }
Sergunb 0:8918a71cdbe9 366
Sergunb 0:8918a71cdbe9 367 //Process upper-layer data
Sergunb 0:8918a71cdbe9 368 while(dataLength > 1)
Sergunb 0:8918a71cdbe9 369 {
Sergunb 0:8918a71cdbe9 370 //Update checksum value
Sergunb 0:8918a71cdbe9 371 checksum += *((uint16_t *) data);
Sergunb 0:8918a71cdbe9 372 //Point to the next 16-bit word
Sergunb 0:8918a71cdbe9 373 data = (uint16_t *) data + 1;
Sergunb 0:8918a71cdbe9 374 //Adjust the number of remaining words to process
Sergunb 0:8918a71cdbe9 375 dataLength -= 2;
Sergunb 0:8918a71cdbe9 376 }
Sergunb 0:8918a71cdbe9 377
Sergunb 0:8918a71cdbe9 378 //Add left-over byte, if any
Sergunb 0:8918a71cdbe9 379 if(dataLength > 0)
Sergunb 0:8918a71cdbe9 380 {
Sergunb 0:8918a71cdbe9 381 #ifdef _CPU_BIG_ENDIAN
Sergunb 0:8918a71cdbe9 382 //Update checksum value
Sergunb 0:8918a71cdbe9 383 checksum += *((uint8_t *) data) << 8;
Sergunb 0:8918a71cdbe9 384 #else
Sergunb 0:8918a71cdbe9 385 //Update checksum value
Sergunb 0:8918a71cdbe9 386 checksum += *((uint8_t *) data);
Sergunb 0:8918a71cdbe9 387 #endif
Sergunb 0:8918a71cdbe9 388 }
Sergunb 0:8918a71cdbe9 389
Sergunb 0:8918a71cdbe9 390 //Fold 32-bit sum to 16 bits
Sergunb 0:8918a71cdbe9 391 while(checksum >> 16)
Sergunb 0:8918a71cdbe9 392 checksum = (checksum & 0xFFFF) + (checksum >> 16);
Sergunb 0:8918a71cdbe9 393
Sergunb 0:8918a71cdbe9 394 //Return 1's complement value
Sergunb 0:8918a71cdbe9 395 return checksum ^ 0xFFFF;
Sergunb 0:8918a71cdbe9 396 }
Sergunb 0:8918a71cdbe9 397
Sergunb 0:8918a71cdbe9 398
Sergunb 0:8918a71cdbe9 399 /**
Sergunb 0:8918a71cdbe9 400 * @brief Calculate IP upper-layer checksum over a multi-part buffer
Sergunb 0:8918a71cdbe9 401 * @param[in] pseudoHeader Pointer to the pseudo header
Sergunb 0:8918a71cdbe9 402 * @param[in] pseudoHeaderLength Pseudo header length
Sergunb 0:8918a71cdbe9 403 * @param[in] buffer Multi-part buffer containing the upper-layer data
Sergunb 0:8918a71cdbe9 404 * @param[in] offset Offset from the first data byte to process
Sergunb 0:8918a71cdbe9 405 * @param[in] length Number of data bytes to process
Sergunb 0:8918a71cdbe9 406 * @return Checksum value
Sergunb 0:8918a71cdbe9 407 **/
Sergunb 0:8918a71cdbe9 408
Sergunb 0:8918a71cdbe9 409 uint16_t ipCalcUpperLayerChecksumEx(const void *pseudoHeader,
Sergunb 0:8918a71cdbe9 410 size_t pseudoHeaderLength, const NetBuffer *buffer, size_t offset, size_t length)
Sergunb 0:8918a71cdbe9 411 {
Sergunb 0:8918a71cdbe9 412 uint32_t checksum;
Sergunb 0:8918a71cdbe9 413
Sergunb 0:8918a71cdbe9 414 //Process upper-layer data
Sergunb 0:8918a71cdbe9 415 checksum = ipCalcChecksumEx(buffer, offset, length);
Sergunb 0:8918a71cdbe9 416 //Calculate 1's complement value
Sergunb 0:8918a71cdbe9 417 checksum = checksum ^ 0xFFFF;
Sergunb 0:8918a71cdbe9 418
Sergunb 0:8918a71cdbe9 419 //Process pseudo header
Sergunb 0:8918a71cdbe9 420 while(pseudoHeaderLength > 1)
Sergunb 0:8918a71cdbe9 421 {
Sergunb 0:8918a71cdbe9 422 //Update checksum value
Sergunb 0:8918a71cdbe9 423 checksum += *((uint16_t *) pseudoHeader);
Sergunb 0:8918a71cdbe9 424 //Point to the next 16-bit word
Sergunb 0:8918a71cdbe9 425 pseudoHeader = (uint16_t *) pseudoHeader + 1;
Sergunb 0:8918a71cdbe9 426 //Adjust the number of remaining words to process
Sergunb 0:8918a71cdbe9 427 pseudoHeaderLength -= 2;
Sergunb 0:8918a71cdbe9 428 }
Sergunb 0:8918a71cdbe9 429
Sergunb 0:8918a71cdbe9 430 //Fold 32-bit sum to 16 bits
Sergunb 0:8918a71cdbe9 431 while(checksum >> 16)
Sergunb 0:8918a71cdbe9 432 checksum = (checksum & 0xFFFF) + (checksum >> 16);
Sergunb 0:8918a71cdbe9 433
Sergunb 0:8918a71cdbe9 434 //Return 1's complement value
Sergunb 0:8918a71cdbe9 435 return checksum ^ 0xFFFF;
Sergunb 0:8918a71cdbe9 436 }
Sergunb 0:8918a71cdbe9 437
Sergunb 0:8918a71cdbe9 438
Sergunb 0:8918a71cdbe9 439 /**
Sergunb 0:8918a71cdbe9 440 * @brief Allocate a buffer to hold an IP packet
Sergunb 0:8918a71cdbe9 441 * @param[in] length Desired payload length
Sergunb 0:8918a71cdbe9 442 * @param[out] offset Offset to the first byte of the payload
Sergunb 0:8918a71cdbe9 443 * @return The function returns a pointer to the newly allocated
Sergunb 0:8918a71cdbe9 444 * buffer. If the system is out of resources, NULL is returned
Sergunb 0:8918a71cdbe9 445 **/
Sergunb 0:8918a71cdbe9 446
Sergunb 0:8918a71cdbe9 447 NetBuffer *ipAllocBuffer(size_t length, size_t *offset)
Sergunb 0:8918a71cdbe9 448 {
Sergunb 0:8918a71cdbe9 449 size_t headerLength;
Sergunb 0:8918a71cdbe9 450 NetBuffer *buffer;
Sergunb 0:8918a71cdbe9 451
Sergunb 0:8918a71cdbe9 452 #if (IPV6_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 453 //Maximum overhead when using IPv6
Sergunb 0:8918a71cdbe9 454 headerLength = sizeof(Ipv6Header) + sizeof(Ipv6FragmentHeader);
Sergunb 0:8918a71cdbe9 455 #else
Sergunb 0:8918a71cdbe9 456 //Maximum overhead when using IPv4
Sergunb 0:8918a71cdbe9 457 headerLength = sizeof(Ipv4Header);
Sergunb 0:8918a71cdbe9 458 #endif
Sergunb 0:8918a71cdbe9 459
Sergunb 0:8918a71cdbe9 460 #if (ETH_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 461 //Allocate a buffer to hold the Ethernet header and the IP packet
Sergunb 0:8918a71cdbe9 462 buffer = ethAllocBuffer(length + headerLength, offset);
Sergunb 0:8918a71cdbe9 463 #elif (PPP_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 464 //Allocate a buffer to hold the PPP header and the IP packet
Sergunb 0:8918a71cdbe9 465 buffer = pppAllocBuffer(length + headerLength, offset);
Sergunb 0:8918a71cdbe9 466 #else
Sergunb 0:8918a71cdbe9 467 //Allocate a buffer to hold the IP packet
Sergunb 0:8918a71cdbe9 468 buffer = netBufferAlloc(length + headerLength);
Sergunb 0:8918a71cdbe9 469 //Clear offset value
Sergunb 0:8918a71cdbe9 470 *offset = 0;
Sergunb 0:8918a71cdbe9 471 #endif
Sergunb 0:8918a71cdbe9 472
Sergunb 0:8918a71cdbe9 473 //Successful memory allocation?
Sergunb 0:8918a71cdbe9 474 if(buffer != NULL)
Sergunb 0:8918a71cdbe9 475 {
Sergunb 0:8918a71cdbe9 476 //Offset to the first byte of the payload
Sergunb 0:8918a71cdbe9 477 *offset += headerLength;
Sergunb 0:8918a71cdbe9 478 }
Sergunb 0:8918a71cdbe9 479
Sergunb 0:8918a71cdbe9 480 //Return a pointer to the freshly allocated buffer
Sergunb 0:8918a71cdbe9 481 return buffer;
Sergunb 0:8918a71cdbe9 482 }
Sergunb 0:8918a71cdbe9 483
Sergunb 0:8918a71cdbe9 484
Sergunb 0:8918a71cdbe9 485 /**
Sergunb 0:8918a71cdbe9 486 * @brief Join the specified host group
Sergunb 0:8918a71cdbe9 487 * @param[in] interface Underlying network interface (optional parameter)
Sergunb 0:8918a71cdbe9 488 * @param[in] groupAddr IP address identifying the host group to join
Sergunb 0:8918a71cdbe9 489 * @return Error code
Sergunb 0:8918a71cdbe9 490 **/
Sergunb 0:8918a71cdbe9 491
Sergunb 0:8918a71cdbe9 492 error_t ipJoinMulticastGroup(NetInterface *interface, const IpAddr *groupAddr)
Sergunb 0:8918a71cdbe9 493 {
Sergunb 0:8918a71cdbe9 494 error_t error;
Sergunb 0:8918a71cdbe9 495
Sergunb 0:8918a71cdbe9 496 //Use default network interface?
Sergunb 0:8918a71cdbe9 497 if(interface == NULL)
Sergunb 0:8918a71cdbe9 498 interface = netGetDefaultInterface();
Sergunb 0:8918a71cdbe9 499
Sergunb 0:8918a71cdbe9 500 //Get exclusive access
Sergunb 0:8918a71cdbe9 501 osAcquireMutex(&netMutex);
Sergunb 0:8918a71cdbe9 502
Sergunb 0:8918a71cdbe9 503 #if (IPV4_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 504 //IPv4 multicast address?
Sergunb 0:8918a71cdbe9 505 if(groupAddr->length == sizeof(Ipv4Addr))
Sergunb 0:8918a71cdbe9 506 {
Sergunb 0:8918a71cdbe9 507 //Join the specified host group
Sergunb 0:8918a71cdbe9 508 error = ipv4JoinMulticastGroup(interface, groupAddr->ipv4Addr);
Sergunb 0:8918a71cdbe9 509 }
Sergunb 0:8918a71cdbe9 510 else
Sergunb 0:8918a71cdbe9 511 #endif
Sergunb 0:8918a71cdbe9 512 #if (IPV6_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 513 //IPv6 multicast address?
Sergunb 0:8918a71cdbe9 514 if(groupAddr->length == sizeof(Ipv6Addr))
Sergunb 0:8918a71cdbe9 515 {
Sergunb 0:8918a71cdbe9 516 //Join the specified host group
Sergunb 0:8918a71cdbe9 517 error = ipv6JoinMulticastGroup(interface, &groupAddr->ipv6Addr);
Sergunb 0:8918a71cdbe9 518 }
Sergunb 0:8918a71cdbe9 519 else
Sergunb 0:8918a71cdbe9 520 #endif
Sergunb 0:8918a71cdbe9 521 //Invalid IP address?
Sergunb 0:8918a71cdbe9 522 {
Sergunb 0:8918a71cdbe9 523 //Report an error
Sergunb 0:8918a71cdbe9 524 error = ERROR_INVALID_ADDRESS;
Sergunb 0:8918a71cdbe9 525 }
Sergunb 0:8918a71cdbe9 526
Sergunb 0:8918a71cdbe9 527 //Release exclusive access
Sergunb 0:8918a71cdbe9 528 osReleaseMutex(&netMutex);
Sergunb 0:8918a71cdbe9 529
Sergunb 0:8918a71cdbe9 530 //Return status code
Sergunb 0:8918a71cdbe9 531 return error;
Sergunb 0:8918a71cdbe9 532 }
Sergunb 0:8918a71cdbe9 533
Sergunb 0:8918a71cdbe9 534
Sergunb 0:8918a71cdbe9 535 /**
Sergunb 0:8918a71cdbe9 536 * @brief Leave the specified host group
Sergunb 0:8918a71cdbe9 537 * @param[in] interface Underlying network interface (optional parameter)
Sergunb 0:8918a71cdbe9 538 * @param[in] groupAddr IP address identifying the host group to leave
Sergunb 0:8918a71cdbe9 539 * @return Error code
Sergunb 0:8918a71cdbe9 540 **/
Sergunb 0:8918a71cdbe9 541
Sergunb 0:8918a71cdbe9 542 error_t ipLeaveMulticastGroup(NetInterface *interface, const IpAddr *groupAddr)
Sergunb 0:8918a71cdbe9 543 {
Sergunb 0:8918a71cdbe9 544 //Use default network interface?
Sergunb 0:8918a71cdbe9 545 if(interface == NULL)
Sergunb 0:8918a71cdbe9 546 interface = netGetDefaultInterface();
Sergunb 0:8918a71cdbe9 547
Sergunb 0:8918a71cdbe9 548 #if (IPV4_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 549 //IPv4 multicast address?
Sergunb 0:8918a71cdbe9 550 if(groupAddr->length == sizeof(Ipv4Addr))
Sergunb 0:8918a71cdbe9 551 {
Sergunb 0:8918a71cdbe9 552 //Drop membership
Sergunb 0:8918a71cdbe9 553 return ipv4LeaveMulticastGroup(interface, groupAddr->ipv4Addr);
Sergunb 0:8918a71cdbe9 554 }
Sergunb 0:8918a71cdbe9 555 else
Sergunb 0:8918a71cdbe9 556 #endif
Sergunb 0:8918a71cdbe9 557 #if (IPV6_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 558 //IPv6 multicast address?
Sergunb 0:8918a71cdbe9 559 if(groupAddr->length == sizeof(Ipv6Addr))
Sergunb 0:8918a71cdbe9 560 {
Sergunb 0:8918a71cdbe9 561 //Drop membership
Sergunb 0:8918a71cdbe9 562 return ipv6LeaveMulticastGroup(interface, &groupAddr->ipv6Addr);
Sergunb 0:8918a71cdbe9 563 }
Sergunb 0:8918a71cdbe9 564 else
Sergunb 0:8918a71cdbe9 565 #endif
Sergunb 0:8918a71cdbe9 566 //Invalid IP address?
Sergunb 0:8918a71cdbe9 567 {
Sergunb 0:8918a71cdbe9 568 return ERROR_INVALID_ADDRESS;
Sergunb 0:8918a71cdbe9 569 }
Sergunb 0:8918a71cdbe9 570 }
Sergunb 0:8918a71cdbe9 571
Sergunb 0:8918a71cdbe9 572
Sergunb 0:8918a71cdbe9 573 /**
Sergunb 0:8918a71cdbe9 574 * @brief Compare an IP address against the unspecified address
Sergunb 0:8918a71cdbe9 575 * @param[in] ipAddr IP address
Sergunb 0:8918a71cdbe9 576 * @return TRUE if the IP address is unspecified, else FALSE
Sergunb 0:8918a71cdbe9 577 **/
Sergunb 0:8918a71cdbe9 578
Sergunb 0:8918a71cdbe9 579 bool_t ipIsUnspecifiedAddr(const IpAddr *ipAddr)
Sergunb 0:8918a71cdbe9 580 {
Sergunb 0:8918a71cdbe9 581 #if (IPV4_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 582 //IPv4 address?
Sergunb 0:8918a71cdbe9 583 if(ipAddr->length == sizeof(Ipv4Addr))
Sergunb 0:8918a71cdbe9 584 {
Sergunb 0:8918a71cdbe9 585 //Compare IPv4 address
Sergunb 0:8918a71cdbe9 586 return (ipAddr->ipv4Addr == IPV4_UNSPECIFIED_ADDR) ? TRUE : FALSE;
Sergunb 0:8918a71cdbe9 587 }
Sergunb 0:8918a71cdbe9 588 else
Sergunb 0:8918a71cdbe9 589 #endif
Sergunb 0:8918a71cdbe9 590 #if (IPV6_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 591 //IPv6 address?
Sergunb 0:8918a71cdbe9 592 if(ipAddr->length == sizeof(Ipv6Addr))
Sergunb 0:8918a71cdbe9 593 {
Sergunb 0:8918a71cdbe9 594 //Compare IPv6 address
Sergunb 0:8918a71cdbe9 595 return ipv6CompAddr(&ipAddr->ipv6Addr, &IPV6_UNSPECIFIED_ADDR);
Sergunb 0:8918a71cdbe9 596 }
Sergunb 0:8918a71cdbe9 597 else
Sergunb 0:8918a71cdbe9 598 #endif
Sergunb 0:8918a71cdbe9 599 //Invalid IP address?
Sergunb 0:8918a71cdbe9 600 {
Sergunb 0:8918a71cdbe9 601 return FALSE;
Sergunb 0:8918a71cdbe9 602 }
Sergunb 0:8918a71cdbe9 603 }
Sergunb 0:8918a71cdbe9 604
Sergunb 0:8918a71cdbe9 605
Sergunb 0:8918a71cdbe9 606 /**
Sergunb 0:8918a71cdbe9 607 * @brief Convert a string representation of an IP address to a binary IP address
Sergunb 0:8918a71cdbe9 608 * @param[in] str NULL-terminated string representing the IP address
Sergunb 0:8918a71cdbe9 609 * @param[out] ipAddr Binary representation of the IP address
Sergunb 0:8918a71cdbe9 610 * @return Error code
Sergunb 0:8918a71cdbe9 611 **/
Sergunb 0:8918a71cdbe9 612
Sergunb 0:8918a71cdbe9 613 error_t ipStringToAddr(const char_t *str, IpAddr *ipAddr)
Sergunb 0:8918a71cdbe9 614 {
Sergunb 0:8918a71cdbe9 615 #if (IPV6_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 616 //IPv6 address?
Sergunb 0:8918a71cdbe9 617 if(strchr(str, ':'))
Sergunb 0:8918a71cdbe9 618 {
Sergunb 0:8918a71cdbe9 619 //IPv6 addresses are 16-byte long
Sergunb 0:8918a71cdbe9 620 ipAddr->length = sizeof(Ipv6Addr);
Sergunb 0:8918a71cdbe9 621 //Convert the string to IPv6 address
Sergunb 0:8918a71cdbe9 622 return ipv6StringToAddr(str, &ipAddr->ipv6Addr);
Sergunb 0:8918a71cdbe9 623 }
Sergunb 0:8918a71cdbe9 624 else
Sergunb 0:8918a71cdbe9 625 #endif
Sergunb 0:8918a71cdbe9 626 #if (IPV4_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 627 //IPv4 address?
Sergunb 0:8918a71cdbe9 628 if(strchr(str, '.'))
Sergunb 0:8918a71cdbe9 629 {
Sergunb 0:8918a71cdbe9 630 //IPv4 addresses are 4-byte long
Sergunb 0:8918a71cdbe9 631 ipAddr->length = sizeof(Ipv4Addr);
Sergunb 0:8918a71cdbe9 632 //Convert the string to IPv4 address
Sergunb 0:8918a71cdbe9 633 return ipv4StringToAddr(str, &ipAddr->ipv4Addr);
Sergunb 0:8918a71cdbe9 634 }
Sergunb 0:8918a71cdbe9 635 else
Sergunb 0:8918a71cdbe9 636 #endif
Sergunb 0:8918a71cdbe9 637 //Invalid IP address?
Sergunb 0:8918a71cdbe9 638 {
Sergunb 0:8918a71cdbe9 639 //Report an error
Sergunb 0:8918a71cdbe9 640 return ERROR_FAILURE;
Sergunb 0:8918a71cdbe9 641 }
Sergunb 0:8918a71cdbe9 642 }
Sergunb 0:8918a71cdbe9 643
Sergunb 0:8918a71cdbe9 644
Sergunb 0:8918a71cdbe9 645 /**
Sergunb 0:8918a71cdbe9 646 * @brief Convert a binary IP address to a string representation
Sergunb 0:8918a71cdbe9 647 * @param[in] ipAddr Binary representation of the IP address
Sergunb 0:8918a71cdbe9 648 * @param[out] str NULL-terminated string representing the IP address
Sergunb 0:8918a71cdbe9 649 * @return Pointer to the formatted string
Sergunb 0:8918a71cdbe9 650 **/
Sergunb 0:8918a71cdbe9 651
Sergunb 0:8918a71cdbe9 652 char_t *ipAddrToString(const IpAddr *ipAddr, char_t *str)
Sergunb 0:8918a71cdbe9 653 {
Sergunb 0:8918a71cdbe9 654 #if (IPV4_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 655 //IPv4 address?
Sergunb 0:8918a71cdbe9 656 if(ipAddr->length == sizeof(Ipv4Addr))
Sergunb 0:8918a71cdbe9 657 {
Sergunb 0:8918a71cdbe9 658 //Convert IPv4 address to string representation
Sergunb 0:8918a71cdbe9 659 return ipv4AddrToString(ipAddr->ipv4Addr, str);
Sergunb 0:8918a71cdbe9 660 }
Sergunb 0:8918a71cdbe9 661 else
Sergunb 0:8918a71cdbe9 662 #endif
Sergunb 0:8918a71cdbe9 663 #if (IPV6_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 664 //IPv6 address?
Sergunb 0:8918a71cdbe9 665 if(ipAddr->length == sizeof(Ipv6Addr))
Sergunb 0:8918a71cdbe9 666 {
Sergunb 0:8918a71cdbe9 667 //Convert IPv6 address to string representation
Sergunb 0:8918a71cdbe9 668 return ipv6AddrToString(&ipAddr->ipv6Addr, str);
Sergunb 0:8918a71cdbe9 669 }
Sergunb 0:8918a71cdbe9 670 else
Sergunb 0:8918a71cdbe9 671 #endif
Sergunb 0:8918a71cdbe9 672 //Invalid IP address?
Sergunb 0:8918a71cdbe9 673 {
Sergunb 0:8918a71cdbe9 674 static char_t c;
Sergunb 0:8918a71cdbe9 675 //The str parameter is optional
Sergunb 0:8918a71cdbe9 676 if(!str) str = &c;
Sergunb 0:8918a71cdbe9 677 //Properly terminate the string
Sergunb 0:8918a71cdbe9 678 str[0] = '\0';
Sergunb 0:8918a71cdbe9 679 //Return an empty string
Sergunb 0:8918a71cdbe9 680 return str;
Sergunb 0:8918a71cdbe9 681 }
Sergunb 0:8918a71cdbe9 682 }
Sergunb 0:8918a71cdbe9 683