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-2024 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.4.4
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  * @return Error code
408  **/
409 
411 {
412  uint_t i;
413 
414  //Loop through network interfaces
415  for(i = 0; i < NET_INTERFACE_COUNT; i++)
416  {
417  //Matching interface?
418  if(interface == NULL || interface == &netInterface[i])
419  {
420 #if (IPV4_SUPPORT == ENABLED)
421  //IPv4 group address?
422  if(groupAddr == NULL)
423  {
424  //Update IPv4 multicast filter table
426  }
427  else if(groupAddr->length == sizeof(Ipv4Addr))
428  {
429  //Update IPv4 multicast filter table (for the specified group only)
431  }
432  else
433  {
434  //Just for sanity
435  }
436 #endif
437 #if (IPV6_SUPPORT == ENABLED)
438  //IPv6 group address?
439  if(groupAddr == NULL)
440  {
441  //Update IPv6 multicast filter table
443  }
444  else if(groupAddr->length == sizeof(Ipv6Addr))
445  {
446  //Update IPv6 multicast filter table (for the specified group only)
448  }
449  else
450  {
451  //Just for sanity
452  }
453 #endif
454  }
455  }
456 }
457 
458 
459 /**
460  * @brief IP checksum calculation
461  * @param[in] data Pointer to the data over which to calculate the IP checksum
462  * @param[in] length Number of bytes to process
463  * @return Checksum value
464  **/
465 
466 uint16_t ipCalcChecksum(const void *data, size_t length)
467 {
468  uint32_t temp;
469  uint32_t checksum;
470  const uint8_t *p;
471 
472  //Checksum preset value
473  checksum = 0x0000;
474 
475  //Point to the data over which to calculate the IP checksum
476  p = (const uint8_t *) data;
477 
478  //Pointer not aligned on a 16-bit boundary?
479  if(((uintptr_t) p & 1) != 0)
480  {
481  if(length >= 1)
482  {
483 #ifdef _CPU_BIG_ENDIAN
484  //Update checksum value
485  checksum += (uint32_t) *p;
486 #else
487  //Update checksum value
488  checksum += (uint32_t) *p << 8;
489 #endif
490  //Restore the alignment on 16-bit boundaries
491  p++;
492  //Number of bytes left to process
493  length--;
494  }
495  }
496 
497  //Pointer not aligned on a 32-bit boundary?
498  if(((uintptr_t) p & 2) != 0)
499  {
500  if(length >= 2)
501  {
502  //Update checksum value
503  checksum += (uint32_t) *((uint16_t *) p);
504 
505  //Restore the alignment on 32-bit boundaries
506  p += 2;
507  //Number of bytes left to process
508  length -= 2;
509  }
510  }
511 
512  //Process the data 4 bytes at a time
513  while(length >= 4)
514  {
515  //Update checksum value
516  temp = checksum + *((uint32_t *) p);
517 
518  //Add carry bit, if any
519  if(temp < checksum)
520  {
521  checksum = temp + 1;
522  }
523  else
524  {
525  checksum = temp;
526  }
527 
528  //Point to the next 32-bit word
529  p += 4;
530  //Number of bytes left to process
531  length -= 4;
532  }
533 
534  //Fold 32-bit sum to 16 bits
535  checksum = (checksum & 0xFFFF) + (checksum >> 16);
536 
537  //Add left-over 16-bit word, if any
538  if(length >= 2)
539  {
540  //Update checksum value
541  checksum += (uint32_t) *((uint16_t *) p);
542 
543  //Point to the next byte
544  p += 2;
545  //Number of bytes left to process
546  length -= 2;
547  }
548 
549  //Add left-over byte, if any
550  if(length >= 1)
551  {
552 #ifdef _CPU_BIG_ENDIAN
553  //Update checksum value
554  checksum += (uint32_t) *p << 8;
555 #else
556  //Update checksum value
557  checksum += (uint32_t) *p;
558 #endif
559  }
560 
561  //Fold 32-bit sum to 16 bits (first pass)
562  checksum = (checksum & 0xFFFF) + (checksum >> 16);
563  //Fold 32-bit sum to 16 bits (second pass)
564  checksum = (checksum & 0xFFFF) + (checksum >> 16);
565 
566  //Restore checksum endianness
567  if(((uintptr_t) data & 1) != 0)
568  {
569  //Swap checksum value
570  checksum = ((checksum >> 8) | (checksum << 8)) & 0xFFFF;
571  }
572 
573  //Return 1's complement value
574  return checksum ^ 0xFFFF;
575 }
576 
577 
578 /**
579  * @brief Calculate IP checksum over a multi-part buffer
580  * @param[in] buffer Pointer to the multi-part buffer
581  * @param[in] offset Offset from the beginning of the buffer
582  * @param[in] length Number of bytes to process
583  * @return Checksum value
584  **/
585 
586 uint16_t ipCalcChecksumEx(const NetBuffer *buffer, size_t offset, size_t length)
587 {
588  uint_t i;
589  uint_t n;
590  uint_t pos;
591  uint8_t *data;
592  uint32_t checksum;
593 
594  //Checksum preset value
595  checksum = 0x0000;
596 
597  //Current position in the multi-part buffer
598  pos = 0;
599 
600  //Loop through data chunks
601  for(i = 0; i < buffer->chunkCount && pos < length; i++)
602  {
603  //Is there any data to process in the current chunk?
604  if(offset < buffer->chunk[i].length)
605  {
606  //Point to the first data byte
607  data = (uint8_t *) buffer->chunk[i].address + offset;
608 
609  //Number of bytes available in the current chunk
610  n = buffer->chunk[i].length - offset;
611  //Limit the number of byte to process
612  n = MIN(n, length - pos);
613 
614  //Take care of alignment issues
615  if((pos & 1) != 0)
616  {
617  //Swap checksum value
618  checksum = ((checksum >> 8) | (checksum << 8)) & 0xFFFF;
619  }
620 
621  //Process data chunk
622  checksum += ipCalcChecksum(data, n) ^ 0xFFFF;
623  //Fold 32-bit sum to 16 bits
624  checksum = (checksum & 0xFFFF) + (checksum >> 16);
625 
626  //Restore checksum endianness
627  if((pos & 1) != 0)
628  {
629  //Swap checksum value
630  checksum = ((checksum >> 8) | (checksum << 8)) & 0xFFFF;
631  }
632 
633  //Advance current position
634  pos += n;
635  //Process the next block from the start
636  offset = 0;
637  }
638  else
639  {
640  //Skip the current chunk
641  offset -= buffer->chunk[i].length;
642  }
643  }
644 
645  //Return 1's complement value
646  return checksum ^ 0xFFFF;
647 }
648 
649 
650 /**
651  * @brief Calculate IP upper-layer checksum
652  * @param[in] pseudoHeader Pointer to the pseudo header
653  * @param[in] pseudoHeaderLen Pseudo header length
654  * @param[in] data Pointer to the upper-layer data
655  * @param[in] dataLen Upper-layer data length
656  * @return Checksum value
657  **/
658 
659 uint16_t ipCalcUpperLayerChecksum(const void *pseudoHeader,
660  size_t pseudoHeaderLen, const void *data, size_t dataLen)
661 {
662  uint32_t checksum;
663 
664  //Process pseudo header
665  checksum = ipCalcChecksum(pseudoHeader, pseudoHeaderLen) ^ 0xFFFF;
666  //Process upper-layer data
667  checksum += ipCalcChecksum(data, dataLen) ^ 0xFFFF;
668  //Fold 32-bit sum to 16 bits
669  checksum = (checksum & 0xFFFF) + (checksum >> 16);
670 
671  //Return 1's complement value
672  return checksum ^ 0xFFFF;
673 }
674 
675 
676 /**
677  * @brief Calculate IP upper-layer checksum over a multi-part buffer
678  * @param[in] pseudoHeader Pointer to the pseudo header
679  * @param[in] pseudoHeaderLen Pseudo header length
680  * @param[in] buffer Multi-part buffer containing the upper-layer data
681  * @param[in] offset Offset from the first data byte to process
682  * @param[in] length Number of data bytes to process
683  * @return Checksum value
684  **/
685 
686 uint16_t ipCalcUpperLayerChecksumEx(const void *pseudoHeader,
687  size_t pseudoHeaderLen, const NetBuffer *buffer, size_t offset, size_t length)
688 {
689  uint32_t checksum;
690 
691  //Process pseudo header
692  checksum = ipCalcChecksum(pseudoHeader, pseudoHeaderLen) ^ 0xFFFF;
693  //Process upper-layer data
694  checksum += ipCalcChecksumEx(buffer, offset, length) ^ 0xFFFF;
695  //Fold 32-bit sum to 16 bits
696  checksum = (checksum & 0xFFFF) + (checksum >> 16);
697 
698  //Return 1's complement value
699  return checksum ^ 0xFFFF;
700 }
701 
702 
703 /**
704  * @brief Allocate a buffer to hold an IP packet
705  * @param[in] length Desired payload length
706  * @param[out] offset Offset to the first byte of the payload
707  * @return The function returns a pointer to the newly allocated
708  * buffer. If the system is out of resources, NULL is returned
709  **/
710 
711 NetBuffer *ipAllocBuffer(size_t length, size_t *offset)
712 {
713  size_t headerLen;
714  NetBuffer *buffer;
715 
716 #if (IPV6_SUPPORT == ENABLED)
717  //Maximum overhead when using IPv6
718  headerLen = sizeof(Ipv6Header) + sizeof(Ipv6FragmentHeader);
719 #else
720  //Maximum overhead when using IPv4
721  headerLen = sizeof(Ipv4Header) + sizeof(Ipv4RouterAlertOption);
722 #endif
723 
724 #if (IPV4_IPSEC_SUPPORT == ENABLED && AH_SUPPORT == ENABLED)
725  //Maximum overhead caused by AH security protocol
726  headerLen += AH_MAX_OVERHEAD;
727 #endif
728 
729 #if (ETH_SUPPORT == ENABLED)
730  //Allocate a buffer to hold the Ethernet header and the IP packet
731  buffer = ethAllocBuffer(length + headerLen, offset);
732 #elif (PPP_SUPPORT == ENABLED)
733  //Allocate a buffer to hold the PPP header and the IP packet
734  buffer = pppAllocBuffer(length + headerLen, offset);
735 #else
736  //Allocate a buffer to hold the IP packet
737  buffer = netBufferAlloc(length + headerLen);
738  //Clear offset value
739  *offset = 0;
740 #endif
741 
742  //Successful memory allocation?
743  if(buffer != NULL)
744  {
745  //Offset to the first byte of the payload
746  *offset += headerLen;
747  }
748 
749  //Return a pointer to the freshly allocated buffer
750  return buffer;
751 }
752 
753 
754 /**
755  * @brief Convert a string representation of an IP address to a binary IP address
756  * @param[in] str NULL-terminated string representing the IP address
757  * @param[out] ipAddr Binary representation of the IP address
758  * @return Error code
759  **/
760 
762 {
763  error_t error;
764 
765 #if (IPV6_SUPPORT == ENABLED)
766  //IPv6 address?
767  if(osStrchr(str, ':') != NULL)
768  {
769  //IPv6 addresses are 16-byte long
770  ipAddr->length = sizeof(Ipv6Addr);
771  //Convert the string to IPv6 address
772  error = ipv6StringToAddr(str, &ipAddr->ipv6Addr);
773  }
774  else
775 #endif
776 #if (IPV4_SUPPORT == ENABLED)
777  //IPv4 address?
778  if(osStrchr(str, '.') != NULL)
779  {
780  //IPv4 addresses are 4-byte long
781  ipAddr->length = sizeof(Ipv4Addr);
782  //Convert the string to IPv4 address
783  error = ipv4StringToAddr(str, &ipAddr->ipv4Addr);
784  }
785  else
786 #endif
787  //Invalid IP address?
788  {
789  //Report an error
790  error = ERROR_FAILURE;
791  }
792 
793  //Return status code
794  return error;
795 }
796 
797 
798 /**
799  * @brief Convert a binary IP address to a string representation
800  * @param[in] ipAddr Binary representation of the IP address
801  * @param[out] str NULL-terminated string representing the IP address
802  * @return Pointer to the formatted string
803  **/
804 
806 {
807 #if (IPV4_SUPPORT == ENABLED)
808  //IPv4 address?
809  if(ipAddr->length == sizeof(Ipv4Addr))
810  {
811  //Convert IPv4 address to string representation
812  return ipv4AddrToString(ipAddr->ipv4Addr, str);
813  }
814  else
815 #endif
816 #if (IPV6_SUPPORT == ENABLED)
817  //IPv6 address?
818  if(ipAddr->length == sizeof(Ipv6Addr))
819  {
820  //Convert IPv6 address to string representation
821  return ipv6AddrToString(&ipAddr->ipv6Addr, str);
822  }
823  else
824 #endif
825  //Invalid IP address?
826  {
827  static char_t c;
828 
829  //The last parameter is optional
830  if(str == NULL)
831  {
832  str = &c;
833  }
834 
835  //Properly terminate the string
836  str[0] = '\0';
837 
838  //Return an empty string
839  return str;
840  }
841 }
#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:2329
IPv6 (Internet Protocol Version 6)
#define osStrchr(s, c)
Definition: os_port.h:195
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:711
Ipv6PseudoHeader ipv6Data
Definition: ip.h:118
int bool_t
Definition: compiler_port.h:53
#define Ipv4Header
Definition: ipv4.h:36
Ipv4Addr destAddr
Definition: ipv4.h:329
uint16_t ipCalcChecksumEx(const NetBuffer *buffer, size_t offset, size_t length)
Calculate IP checksum over a multi-part buffer.
Definition: ip.c:586
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:355
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:119
char_t * ipAddrToString(const IpAddr *ipAddr, char_t *str)
Convert a binary IP address to a string representation.
Definition: ip.c:805
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:114
#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:369
size_t length
Definition: ip.h:111
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:297
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:761
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:410
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:368
#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:659
char char_t
Definition: compiler_port.h:48
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:686
error_t ipv4SendDatagram(NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IPv4 datagram.
Definition: ipv4.c:1010
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:1703
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:1368
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:2174
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:50
TCP/IP stack core.
char_t * ipv4AddrToString(Ipv4Addr ipAddr, char_t *str)
Convert a binary IPv4 address to dot-decimal notation.
Definition: ipv4.c:1457
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:466