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