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