ip.c
Go to the documentation of this file.
1 /**
2  * @file ip.c
3  * @brief IPv4 and IPv6 common routines
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.6.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL IP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "core/ethernet.h"
37 #include "core/ip.h"
38 #include "ipv4/ipv4.h"
39 #include "ipv4/ipv4_multicast.h"
40 #include "ipv4/ipv4_misc.h"
41 #include "ipv6/ipv6.h"
42 #include "ipv6/ipv6_multicast.h"
43 #include "ipv6/ipv6_misc.h"
44 #include "debug.h"
45 
46 //IPsec supported?
47 #if (IPV4_IPSEC_SUPPORT == ENABLED)
48  #include "ipsec/ipsec.h"
49  #include "ah/ah.h"
50 #endif
51 
52 //Special IP addresses
53 const IpAddr IP_ADDR_ANY = {0};
55 
56 
57 /**
58  * @brief Send an IP datagram
59  * @param[in] interface Underlying network interface
60  * @param[in] pseudoHeader IP pseudo header
61  * @param[in] buffer Multi-part buffer containing the payload
62  * @param[in] offset Offset to the first payload byte
63  * @param[in] ancillary Additional options passed to the stack along with
64  * the packet
65  * @return Error code
66  **/
67 
69  const IpPseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset,
70  NetTxAncillary *ancillary)
71 {
72  error_t error;
73 
74 #if (IPV4_SUPPORT == ENABLED)
75  //Destination address is an IPv4 address?
76  if(pseudoHeader->length == sizeof(Ipv4PseudoHeader))
77  {
78  //Form an IPv4 packet and send it
79  error = ipv4SendDatagram(interface, &pseudoHeader->ipv4Data, buffer,
80  offset, ancillary);
81  }
82  else
83 #endif
84 #if (IPV6_SUPPORT == ENABLED)
85  //Destination address is an IPv6 address?
86  if(pseudoHeader->length == sizeof(Ipv6PseudoHeader))
87  {
88  //Form an IPv6 packet and send it
89  error = ipv6SendDatagram(interface, &pseudoHeader->ipv6Data, buffer,
90  offset, ancillary);
91  }
92  else
93 #endif
94  //Destination address is invalid
95  {
96  //Report an error
97  error = ERROR_INVALID_ADDRESS;
98  }
99 
100  //Return status code
101  return error;
102 }
103 
104 
105 /**
106  * @brief IP source address selection
107  *
108  * This function selects the source address and the relevant network interface
109  * to be used in order to join the specified destination address
110  *
111  * @param[in] context Pointer to the TCP/IP stack context
112  * @param[in,out] interface A pointer to a valid network interface may be
113  * provided as a hint. The function returns a pointer identifying the
114  * interface to be used
115  * @param[in] destAddr Destination IP address
116  * @param[out] srcAddr Local IP address to be used
117  * @return Error code
118  **/
119 
121  const IpAddr *destAddr, IpAddr *srcAddr)
122 {
123  error_t error;
124 
125 #if (IPV4_SUPPORT == ENABLED)
126  //The destination address is an IPv4 address?
127  if(destAddr->length == sizeof(Ipv4Addr))
128  {
129  //An IPv4 address is expected
130  srcAddr->length = sizeof(Ipv4Addr);
131 
132  //Get the most appropriate source address to use
133  error = ipv4SelectSourceAddr(context, interface, destAddr->ipv4Addr,
134  &srcAddr->ipv4Addr);
135  }
136  else
137 #endif
138 #if (IPV6_SUPPORT == ENABLED)
139  //The destination address is an IPv6 address?
140  if(destAddr->length == sizeof(Ipv6Addr))
141  {
142  //An IPv6 address is expected
143  srcAddr->length = sizeof(Ipv6Addr);
144 
145  //Get the most appropriate source address to use
146  error = ipv6SelectSourceAddr(context, interface, &destAddr->ipv6Addr,
147  &srcAddr->ipv6Addr);
148  }
149  else
150 #endif
151  //The destination address is not valid?
152  {
153  //Report an error
154  error = ERROR_INVALID_ADDRESS;
155  }
156 
157  //Return status code
158  return error;
159 }
160 
161 
162 /**
163  * @brief Compare an IP address against the unspecified address
164  * @param[in] ipAddr IP address
165  * @return TRUE if the IP address is unspecified, else FALSE
166  **/
167 
169 {
170  bool_t result;
171 
172 #if (IPV4_SUPPORT == ENABLED)
173  //IPv4 address?
174  if(ipAddr->length == sizeof(Ipv4Addr))
175  {
176  //Compare IPv4 address
177  if(ipAddr->ipv4Addr == IPV4_UNSPECIFIED_ADDR)
178  {
179  result = TRUE;
180  }
181  else
182  {
183  result = FALSE;
184  }
185  }
186  else
187 #endif
188 #if (IPV6_SUPPORT == ENABLED)
189  //IPv6 address?
190  if(ipAddr->length == sizeof(Ipv6Addr))
191  {
192  //Compare IPv6 address
193  result = ipv6CompAddr(&ipAddr->ipv6Addr, &IPV6_UNSPECIFIED_ADDR);
194  }
195  else
196 #endif
197  //Invalid IP address?
198  {
199  result = TRUE;
200  }
201 
202  //Return TRUE if the IP address is unspecified, else FALSE
203  return result;
204 }
205 
206 
207 /**
208  * @brief Determine whether an IP address is a link-local address
209  * @param[in] ipAddr IP address
210  * @return TRUE if the IP address is a link-local address, else FALSE
211  **/
212 
214 {
215  bool_t result;
216 
217 #if (IPV4_SUPPORT == ENABLED)
218  //IPv4 address?
219  if(ipAddr->length == sizeof(Ipv4Addr))
220  {
221  //Check whether the IPv4 address is a link-local address
222  result = ipv4IsLinkLocalAddr(ipAddr->ipv4Addr);
223  }
224  else
225 #endif
226 #if (IPV6_SUPPORT == ENABLED)
227  //IPv6 address?
228  if(ipAddr->length == sizeof(Ipv6Addr))
229  {
230  //Check whether the IPv6 address is a link-local address
231  result = ipv6IsLinkLocalUnicastAddr(&ipAddr->ipv6Addr);
232  }
233  else
234 #endif
235  //Invalid IP address?
236  {
237  result = FALSE;
238  }
239 
240  //Return TRUE if the IP address is a link-local address, else FALSE
241  return result;
242 }
243 
244 
245 /**
246  * @brief Determine whether an IP address is a multicast address
247  * @param[in] ipAddr IP address
248  * @return TRUE if the IP address is a multicast address, else FALSE
249  **/
250 
252 {
253  bool_t result;
254 
255 #if (IPV4_SUPPORT == ENABLED)
256  //IPv4 address?
257  if(ipAddr->length == sizeof(Ipv4Addr))
258  {
259  //Check whether the IPv4 address is a multicast address
260  result = ipv4IsMulticastAddr(ipAddr->ipv4Addr);
261  }
262  else
263 #endif
264 #if (IPV6_SUPPORT == ENABLED)
265  //IPv6 address?
266  if(ipAddr->length == sizeof(Ipv6Addr))
267  {
268  //Check whether the IPv6 address is a multicast address
269  result = ipv6IsMulticastAddr(&ipAddr->ipv6Addr);
270  }
271  else
272 #endif
273  //Invalid IP address?
274  {
275  result = FALSE;
276  }
277 
278  //Return TRUE if the IP address is a multicast address, else FALSE
279  return result;
280 }
281 
282 
283 /**
284  * @brief Determine whether an IP address is a broadcast address
285  * @param[in] ipAddr IP address
286  * @return TRUE if the IP address is a broadcast address, else FALSE
287  **/
288 
290 {
291  bool_t result;
292 
293 #if (IPV4_SUPPORT == ENABLED)
294  //Broadcast address?
295  if(ipAddr->length == sizeof(Ipv4Addr) &&
296  ipAddr->ipv4Addr == IPV4_BROADCAST_ADDR)
297  {
298  result = TRUE;
299  }
300  else
301 #endif
302  {
303  result = FALSE;
304  }
305 
306  //Return TRUE if the IP address is a broadcast address, else FALSE
307  return result;
308 }
309 
310 
311 /**
312  * @brief Compare IP addresses
313  * @param[in] ipAddr1 First IP address
314  * @param[in] ipAddr2 Second IP address
315  * @return Comparison result
316  **/
317 
318 bool_t ipCompAddr(const IpAddr *ipAddr1, const IpAddr *ipAddr2)
319 {
320  bool_t result;
321 
322 #if (IPV4_SUPPORT == ENABLED)
323  //IPv4 addresses?
324  if(ipAddr1->length == sizeof(Ipv4Addr) && ipAddr2->length == sizeof(Ipv4Addr))
325  {
326  //Compare IPv4 addresses
327  if(ipAddr1->ipv4Addr == ipAddr2->ipv4Addr)
328  {
329  result = TRUE;
330  }
331  else
332  {
333  result = FALSE;
334  }
335  }
336  else
337 #endif
338 #if (IPV6_SUPPORT == ENABLED)
339  //IPv6 addresses?
340  if(ipAddr1->length == sizeof(Ipv6Addr) && ipAddr2->length == sizeof(Ipv6Addr))
341  {
342  //Compare IPv6 addresses
343  result = ipv6CompAddr(&ipAddr1->ipv6Addr, &ipAddr2->ipv6Addr);
344  }
345  else
346 #endif
347  //Unspecified IP addresses?
348  if(ipAddr1->length == 0 && ipAddr2->length == 0)
349  {
350  result = TRUE;
351  }
352  //Inconsistent IP addresses?
353  else
354  {
355  result = FALSE;
356  }
357 
358  //Return TRUE if the IP addresses match, else FALSE
359  return result;
360 }
361 
362 
363 /**
364  * @brief Compare IP address prefixes
365  * @param[in] ipAddr1 First IP address
366  * @param[in] ipAddr2 Second IP address
367  * @param[in] length Prefix length
368  * @return TRUE if the prefixes match each other, else FALSE
369  **/
370 
371 bool_t ipCompPrefix(const IpAddr *ipAddr1, const IpAddr *ipAddr2,
372  size_t length)
373 {
374  bool_t result;
375 
376 #if (IPV4_SUPPORT == ENABLED)
377  //IPv4 addresses?
378  if(ipAddr1->length == sizeof(Ipv4Addr) && ipAddr2->length == sizeof(Ipv4Addr))
379  {
380  //Compare IPv4 address prefixes
381  result = ipv4CompPrefix(ipAddr1->ipv4Addr, ipAddr2->ipv4Addr, length);
382  }
383  else
384 #endif
385 #if (IPV6_SUPPORT == ENABLED)
386  //IPv6 addresses?
387  if(ipAddr1->length == sizeof(Ipv6Addr) && ipAddr2->length == sizeof(Ipv6Addr))
388  {
389  //Compare IPv6 address prefixes
390  result = ipv6CompPrefix(&ipAddr1->ipv6Addr, &ipAddr2->ipv6Addr, length);
391  }
392  else
393 #endif
394  //Inconsistent IP addresses?
395  {
396  result = FALSE;
397  }
398 
399  //Return TRUE if the prefixes match each other, else FALSE
400  return result;
401 }
402 
403 
404 /**
405  * @brief Update IP multicast filter table
406  * @param[in] context Pointer to the TCP/IP stack context
407  * @param[in] interface Underlying network interface
408  * @param[in] groupAddr IP multicast address
409  **/
410 
412  const IpAddr *groupAddr)
413 {
414  uint_t i;
415 
416  //Loop through network interfaces
417  for(i = 0; i < context->numInterfaces; i++)
418  {
419  //Matching interface?
420  if(interface == NULL || interface == &context->interfaces[i])
421  {
422 #if (IPV4_SUPPORT == ENABLED)
423  //IPv4 group address?
424  if(groupAddr == NULL)
425  {
426  //Update IPv4 multicast filter table
427  ipv4UpdateMulticastFilter(&context->interfaces[i],
429  }
430  else if(groupAddr->length == sizeof(Ipv4Addr))
431  {
432  //Update IPv4 multicast filter table (for the specified group only)
433  ipv4UpdateMulticastFilter(&context->interfaces[i],
434  groupAddr->ipv4Addr);
435  }
436  else
437  {
438  //Just for sanity
439  }
440 #endif
441 #if (IPV6_SUPPORT == ENABLED)
442  //IPv6 group address?
443  if(groupAddr == NULL)
444  {
445  //Update IPv6 multicast filter table
446  ipv6UpdateMulticastFilter(&context->interfaces[i], NULL);
447  }
448  else if(groupAddr->length == sizeof(Ipv6Addr))
449  {
450  //Update IPv6 multicast filter table (for the specified group only)
451  ipv6UpdateMulticastFilter(&context->interfaces[i],
452  &groupAddr->ipv6Addr);
453  }
454  else
455  {
456  //Just for sanity
457  }
458 #endif
459  }
460  }
461 }
462 
463 
464 /**
465  * @brief IP checksum calculation
466  * @param[in] data Pointer to the data over which to calculate the IP checksum
467  * @param[in] length Number of bytes to process
468  * @return Checksum value
469  **/
470 
471 uint16_t ipCalcChecksum(const void *data, size_t length)
472 {
473  uint32_t temp;
474  uint32_t checksum;
475  const uint8_t *p;
476 
477  //Checksum preset value
478  checksum = 0x0000;
479 
480  //Point to the data over which to calculate the IP checksum
481  p = (const uint8_t *) data;
482 
483  //Pointer not aligned on a 16-bit boundary?
484  if(((uintptr_t) p & 1) != 0)
485  {
486  if(length >= 1)
487  {
488 #ifdef _CPU_BIG_ENDIAN
489  //Update checksum value
490  checksum += (uint32_t) *p;
491 #else
492  //Update checksum value
493  checksum += (uint32_t) *p << 8;
494 #endif
495  //Restore the alignment on 16-bit boundaries
496  p++;
497  //Number of bytes left to process
498  length--;
499  }
500  }
501 
502  //Pointer not aligned on a 32-bit boundary?
503  if(((uintptr_t) p & 2) != 0)
504  {
505  if(length >= 2)
506  {
507  //Update checksum value
508  checksum += (uint32_t) *((uint16_t *) p);
509 
510  //Restore the alignment on 32-bit boundaries
511  p += 2;
512  //Number of bytes left to process
513  length -= 2;
514  }
515  }
516 
517  //Process the data 4 bytes at a time
518  while(length >= 4)
519  {
520  //Update checksum value
521  temp = checksum + *((uint32_t *) p);
522 
523  //Add carry bit, if any
524  if(temp < checksum)
525  {
526  checksum = temp + 1;
527  }
528  else
529  {
530  checksum = temp;
531  }
532 
533  //Point to the next 32-bit word
534  p += 4;
535  //Number of bytes left to process
536  length -= 4;
537  }
538 
539  //Fold 32-bit sum to 16 bits
540  checksum = (checksum & 0xFFFF) + (checksum >> 16);
541 
542  //Add left-over 16-bit word, if any
543  if(length >= 2)
544  {
545  //Update checksum value
546  checksum += (uint32_t) *((uint16_t *) p);
547 
548  //Point to the next byte
549  p += 2;
550  //Number of bytes left to process
551  length -= 2;
552  }
553 
554  //Add left-over byte, if any
555  if(length >= 1)
556  {
557 #ifdef _CPU_BIG_ENDIAN
558  //Update checksum value
559  checksum += (uint32_t) *p << 8;
560 #else
561  //Update checksum value
562  checksum += (uint32_t) *p;
563 #endif
564  }
565 
566  //Fold 32-bit sum to 16 bits (first pass)
567  checksum = (checksum & 0xFFFF) + (checksum >> 16);
568  //Fold 32-bit sum to 16 bits (second pass)
569  checksum = (checksum & 0xFFFF) + (checksum >> 16);
570 
571  //Restore checksum endianness
572  if(((uintptr_t) data & 1) != 0)
573  {
574  //Swap checksum value
575  checksum = ((checksum >> 8) | (checksum << 8)) & 0xFFFF;
576  }
577 
578  //Return 1's complement value
579  return checksum ^ 0xFFFF;
580 }
581 
582 
583 /**
584  * @brief Calculate IP checksum over a multi-part buffer
585  * @param[in] buffer Pointer to the multi-part buffer
586  * @param[in] offset Offset from the beginning of the buffer
587  * @param[in] length Number of bytes to process
588  * @return Checksum value
589  **/
590 
591 uint16_t ipCalcChecksumEx(const NetBuffer *buffer, size_t offset, size_t length)
592 {
593  uint_t i;
594  uint_t n;
595  uint_t pos;
596  uint8_t *data;
597  uint32_t checksum;
598 
599  //Checksum preset value
600  checksum = 0x0000;
601 
602  //Current position in the multi-part buffer
603  pos = 0;
604 
605  //Loop through data chunks
606  for(i = 0; i < buffer->chunkCount && pos < length; i++)
607  {
608  //Is there any data to process in the current chunk?
609  if(offset < buffer->chunk[i].length)
610  {
611  //Point to the first data byte
612  data = (uint8_t *) buffer->chunk[i].address + offset;
613 
614  //Number of bytes available in the current chunk
615  n = buffer->chunk[i].length - offset;
616  //Limit the number of byte to process
617  n = MIN(n, length - pos);
618 
619  //Take care of alignment issues
620  if((pos & 1) != 0)
621  {
622  //Swap checksum value
623  checksum = ((checksum >> 8) | (checksum << 8)) & 0xFFFF;
624  }
625 
626  //Process data chunk
627  checksum += ipCalcChecksum(data, n) ^ 0xFFFF;
628  //Fold 32-bit sum to 16 bits
629  checksum = (checksum & 0xFFFF) + (checksum >> 16);
630 
631  //Restore checksum endianness
632  if((pos & 1) != 0)
633  {
634  //Swap checksum value
635  checksum = ((checksum >> 8) | (checksum << 8)) & 0xFFFF;
636  }
637 
638  //Advance current position
639  pos += n;
640  //Process the next block from the start
641  offset = 0;
642  }
643  else
644  {
645  //Skip the current chunk
646  offset -= buffer->chunk[i].length;
647  }
648  }
649 
650  //Return 1's complement value
651  return checksum ^ 0xFFFF;
652 }
653 
654 
655 /**
656  * @brief Calculate IP upper-layer checksum
657  * @param[in] pseudoHeader Pointer to the pseudo header
658  * @param[in] pseudoHeaderLen Pseudo header length
659  * @param[in] data Pointer to the upper-layer data
660  * @param[in] dataLen Upper-layer data length
661  * @return Checksum value
662  **/
663 
664 uint16_t ipCalcUpperLayerChecksum(const void *pseudoHeader,
665  size_t pseudoHeaderLen, const void *data, size_t dataLen)
666 {
667  uint32_t checksum;
668 
669  //Process pseudo header
670  checksum = ipCalcChecksum(pseudoHeader, pseudoHeaderLen) ^ 0xFFFF;
671  //Process upper-layer data
672  checksum += ipCalcChecksum(data, dataLen) ^ 0xFFFF;
673  //Fold 32-bit sum to 16 bits
674  checksum = (checksum & 0xFFFF) + (checksum >> 16);
675 
676  //Return 1's complement value
677  return checksum ^ 0xFFFF;
678 }
679 
680 
681 /**
682  * @brief Calculate IP upper-layer checksum over a multi-part buffer
683  * @param[in] pseudoHeader Pointer to the pseudo header
684  * @param[in] pseudoHeaderLen Pseudo header length
685  * @param[in] buffer Multi-part buffer containing the upper-layer data
686  * @param[in] offset Offset from the first data byte to process
687  * @param[in] length Number of data bytes to process
688  * @return Checksum value
689  **/
690 
691 uint16_t ipCalcUpperLayerChecksumEx(const void *pseudoHeader,
692  size_t pseudoHeaderLen, const NetBuffer *buffer, size_t offset, size_t length)
693 {
694  uint32_t checksum;
695 
696  //Process pseudo header
697  checksum = ipCalcChecksum(pseudoHeader, pseudoHeaderLen) ^ 0xFFFF;
698  //Process upper-layer data
699  checksum += ipCalcChecksumEx(buffer, offset, length) ^ 0xFFFF;
700  //Fold 32-bit sum to 16 bits
701  checksum = (checksum & 0xFFFF) + (checksum >> 16);
702 
703  //Return 1's complement value
704  return checksum ^ 0xFFFF;
705 }
706 
707 
708 /**
709  * @brief Allocate a buffer to hold an IP packet
710  * @param[in] length Desired payload length
711  * @param[out] offset Offset to the first byte of the payload
712  * @return The function returns a pointer to the newly allocated
713  * buffer. If the system is out of resources, NULL is returned
714  **/
715 
716 NetBuffer *ipAllocBuffer(size_t length, size_t *offset)
717 {
718  size_t headerLen;
719  NetBuffer *buffer;
720 
721 #if (IPV6_SUPPORT == ENABLED)
722  //Maximum overhead when using IPv6
723  headerLen = sizeof(Ipv6Header) + sizeof(Ipv6FragmentHeader);
724 #else
725  //Maximum overhead when using IPv4
726  headerLen = sizeof(Ipv4Header) + sizeof(Ipv4RouterAlertOption);
727 #endif
728 
729 #if (IPV4_IPSEC_SUPPORT == ENABLED && AH_SUPPORT == ENABLED)
730  //Maximum overhead caused by AH security protocol
731  headerLen += AH_MAX_OVERHEAD;
732 #endif
733 
734 #if (ETH_SUPPORT == ENABLED)
735  //Allocate a buffer to hold the Ethernet header and the IP packet
736  buffer = ethAllocBuffer(length + headerLen, offset);
737 #elif (PPP_SUPPORT == ENABLED)
738  //Allocate a buffer to hold the PPP header and the IP packet
739  buffer = pppAllocBuffer(length + headerLen, offset);
740 #else
741  //Allocate a buffer to hold the IP packet
742  buffer = netBufferAlloc(length + headerLen);
743  //Clear offset value
744  *offset = 0;
745 #endif
746 
747  //Successful memory allocation?
748  if(buffer != NULL)
749  {
750  //Offset to the first byte of the payload
751  *offset += headerLen;
752  }
753 
754  //Return a pointer to the freshly allocated buffer
755  return buffer;
756 }
757 
758 
759 /**
760  * @brief Convert a string representation of an IP address to a binary IP address
761  * @param[in] str NULL-terminated string representing the IP address
762  * @param[out] ipAddr Binary representation of the IP address
763  * @return Error code
764  **/
765 
767 {
768  error_t error;
769 
770 #if (IPV6_SUPPORT == ENABLED)
771  //IPv6 address?
772  if(osStrchr(str, ':') != NULL)
773  {
774  //IPv6 addresses are 16-byte long
775  ipAddr->length = sizeof(Ipv6Addr);
776  //Convert the string to IPv6 address
777  error = ipv6StringToAddr(str, &ipAddr->ipv6Addr);
778  }
779  else
780 #endif
781 #if (IPV4_SUPPORT == ENABLED)
782  //IPv4 address?
783  if(osStrchr(str, '.') != NULL)
784  {
785  //IPv4 addresses are 4-byte long
786  ipAddr->length = sizeof(Ipv4Addr);
787  //Convert the string to IPv4 address
788  error = ipv4StringToAddr(str, &ipAddr->ipv4Addr);
789  }
790  else
791 #endif
792  //Invalid IP address?
793  {
794  //Report an error
795  error = ERROR_FAILURE;
796  }
797 
798  //Return status code
799  return error;
800 }
801 
802 
803 /**
804  * @brief Convert a binary IP address to a string representation
805  * @param[in] ipAddr Binary representation of the IP address
806  * @param[out] str NULL-terminated string representing the IP address
807  * @return Pointer to the formatted string
808  **/
809 
811 {
812 #if (IPV4_SUPPORT == ENABLED)
813  //IPv4 address?
814  if(ipAddr->length == sizeof(Ipv4Addr))
815  {
816  //Convert IPv4 address to string representation
817  return ipv4AddrToString(ipAddr->ipv4Addr, str);
818  }
819  else
820 #endif
821 #if (IPV6_SUPPORT == ENABLED)
822  //IPv6 address?
823  if(ipAddr->length == sizeof(Ipv6Addr))
824  {
825  //Convert IPv6 address to string representation
826  return ipv6AddrToString(&ipAddr->ipv6Addr, str);
827  }
828  else
829 #endif
830  //Invalid IP address?
831  {
832  static char_t c;
833 
834  //The last parameter is optional
835  if(str == NULL)
836  {
837  str = &c;
838  }
839 
840  //Properly terminate the string
841  str[0] = '\0';
842 
843  //Return an empty string
844  return str;
845  }
846 }
#define ipv4IsMulticastAddr(ipAddr)
Definition: ipv4.h:186
char_t * ipv6AddrToString(const Ipv6Addr *ipAddr, char_t *str)
Convert a binary IPv6 address to a string representation.
Definition: ipv6.c:2344
IPv6 (Internet Protocol Version 6)
#define osStrchr(s, c)
Definition: os_port.h:198
#define NetContext
Definition: net.h:36
bool_t ipv4CompPrefix(Ipv4Addr ipAddr1, Ipv4Addr ipAddr2, size_t length)
Compare IPv4 address prefixes.
Definition: ipv4_misc.c:626
NetBuffer * ipAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an IP packet.
Definition: ip.c:716
Ipv6PseudoHeader ipv6Data
Definition: ip.h:118
int bool_t
Definition: compiler_port.h:63
#define Ipv4Header
Definition: ipv4.h:36
Ipv4Addr destAddr
Definition: ipv4.h:354
uint16_t ipCalcChecksumEx(const NetBuffer *buffer, size_t offset, size_t length)
Calculate IP checksum over a multi-part buffer.
Definition: ip.c:591
IP network address.
Definition: ip.h:90
bool_t ipCompPrefix(const IpAddr *ipAddr1, const IpAddr *ipAddr2, size_t length)
Compare IP address prefixes.
Definition: ip.c:371
uint8_t p
Definition: ndp.h:300
uint16_t checksum
Definition: tcp.h:362
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
uint_t chunkCount
Definition: net_mem.h:90
const IpAddr IP_ADDR_UNSPECIFIED
Definition: ip.c:54
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:224
error_t ipSendDatagram(NetInterface *interface, const IpPseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IP datagram.
Definition: ip.c:68
#define Ipv6Header
Definition: ipv6.h:36
#define AH_MAX_OVERHEAD
Definition: ah.h:172
char_t * ipAddrToString(const IpAddr *ipAddr, char_t *str)
Convert a binary IP address to a string representation.
Definition: ip.c:810
Ipv6Addr
Definition: ipv6.h:280
error_t ipSelectSourceAddr(NetContext *context, NetInterface **interface, const IpAddr *destAddr, IpAddr *srcAddr)
IP source address selection.
Definition: ip.c:120
#define ipv6CompAddr(ipAddr1, ipAddr2)
Definition: ipv6.h:134
#define ipv4IsLinkLocalAddr(ipAddr)
Definition: ipv4.h:182
NetBuffer * pppAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold a PPP frame.
Definition: ppp.c:1306
Ipv4RouterAlertOption
Definition: ipv4.h:394
size_t length
Definition: ip.h:111
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:322
Ethernet.
IP pseudo header.
Definition: ip.h:110
error_t ipStringToAddr(const char_t *str, IpAddr *ipAddr)
Convert a string representation of an IP address to a binary IP address.
Definition: ip.c:766
IPv4 multicast filtering.
const IpAddr IP_ADDR_ANY
Definition: ip.c:53
#define ipv6IsMulticastAddr(ipAddr)
Definition: ipv6.h:146
IPv6 multicast filtering.
Helper functions for IPv4.
uint16_t length
Definition: net_mem.h:79
#define FALSE
Definition: os_port.h:46
error_t
Error codes.
Definition: error.h:43
bool_t ipCompAddr(const IpAddr *ipAddr1, const IpAddr *ipAddr2)
Compare IP addresses.
Definition: ip.c:318
void ipUpdateMulticastFilter(NetContext *context, NetInterface *interface, const IpAddr *groupAddr)
Update IP multicast filter table.
Definition: ip.c:411
bool_t ipIsMulticastAddr(const IpAddr *ipAddr)
Determine whether an IP address is a multicast address.
Definition: ip.c:251
#define Ipv6PseudoHeader
Definition: ipv6.h:42
void * address
Definition: net_mem.h:78
@ ERROR_INVALID_ADDRESS
Definition: error.h:103
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
error_t ipv4SelectSourceAddr(NetContext *context, NetInterface **interface, Ipv4Addr destAddr, Ipv4Addr *srcAddr)
IPv4 source address selection.
Definition: ipv4_misc.c:173
#define NetInterface
Definition: net.h:40
Helper functions for IPv6.
bool_t ipIsUnspecifiedAddr(const IpAddr *ipAddr)
Compare an IP address against the unspecified address.
Definition: ip.c:168
#define NetTxAncillary
Definition: net_misc.h:36
const Ipv6Addr IPV6_UNSPECIFIED_ADDR
Definition: ipv6.c:65
#define Ipv4PseudoHeader
Definition: ipv4.h:39
uint8_t length
Definition: tcp.h:375
#define MIN(a, b)
Definition: os_port.h:63
size_t length
Definition: ip.h:91
uint32_t dataLen
Definition: sftp_common.h:229
AH (IP Authentication Header)
#define IPV4_BROADCAST_ADDR
Definition: ipv4.h:130
bool_t ipIsBroadcastAddr(const IpAddr *ipAddr)
Determine whether an IP address is a broadcast address.
Definition: ip.c:289
#define ipv6IsLinkLocalUnicastAddr(ipAddr)
Definition: ipv6.h:138
void ipv4UpdateMulticastFilter(NetInterface *interface, Ipv4Addr groupAddr)
Update IPv4 multicast filter table.
NetBuffer * netBufferAlloc(size_t length)
Allocate a multi-part buffer.
Definition: net_mem.c:243
uint16_t ipCalcUpperLayerChecksum(const void *pseudoHeader, size_t pseudoHeaderLen, const void *data, size_t dataLen)
Calculate IP upper-layer checksum.
Definition: ip.c:664
char char_t
Definition: compiler_port.h:55
Ipv4Addr ipv4Addr
Definition: ip.h:95
void ipv6UpdateMulticastFilter(NetInterface *interface, const Ipv6Addr *groupAddr)
Update IPv6 multicast filter table.
ChunkDesc chunk[]
Definition: net_mem.h:92
uint16_t ipCalcUpperLayerChecksumEx(const void *pseudoHeader, size_t pseudoHeaderLen, const NetBuffer *buffer, size_t offset, size_t length)
Calculate IP upper-layer checksum over a multi-part buffer.
Definition: ip.c:691
error_t ipv4SendDatagram(NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IPv4 datagram.
Definition: ipv4.c:1021
IPsec (IP security)
IPv4 and IPv6 common routines.
uint8_t n
error_t ipv6SendDatagram(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IPv6 datagram.
Definition: ipv6.c:1716
Ipv4Addr groupAddr
Definition: igmp_common.h:214
MacAddr srcAddr
Definition: ethernet.h:222
bool_t ipv6CompPrefix(const Ipv6Addr *ipAddr1, const Ipv6Addr *ipAddr2, size_t length)
Compare IPv6 address prefixes.
Definition: ipv6_misc.c:1218
#define Ipv6FragmentHeader
Definition: ipv6.h:39
bool_t ipIsLinkLocalAddr(const IpAddr *ipAddr)
Determine whether an IP address is a link-local address.
Definition: ip.c:213
error_t ipv4StringToAddr(const char_t *str, Ipv4Addr *ipAddr)
Convert a dot-decimal string to a binary IPv4 address.
Definition: ipv4.c:1379
Ipv4Addr ipAddr
Definition: ipcp.h:105
error_t ipv6StringToAddr(const char_t *str, Ipv6Addr *ipAddr)
Convert a string representation of an IPv6 address to a binary IPv6 address.
Definition: ipv6.c:2189
IPv4 (Internet Protocol Version 4)
Ipv6Addr ipv6Addr
Definition: ip.h:98
NetBuffer * ethAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an Ethernet frame.
Definition: ethernet.c:784
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
char_t * ipv4AddrToString(Ipv4Addr ipAddr, char_t *str)
Convert a binary IPv4 address to dot-decimal notation.
Definition: ipv4.c:1468
Ipv4PseudoHeader ipv4Data
Definition: ip.h:115
error_t ipv6SelectSourceAddr(NetContext *context, NetInterface **interface, const Ipv6Addr *destAddr, Ipv6Addr *srcAddr)
IPv6 source address selection.
Definition: ipv6_misc.c:891
uint8_t c
Definition: ndp.h:514
Debugging facilities.
#define IPV4_UNSPECIFIED_ADDR
Definition: ipv4.h:128
uint16_t ipCalcChecksum(const void *data, size_t length)
IP checksum calculation.
Definition: ip.c:471