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.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_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 #endif
49 
50 //Special IP addresses
51 const IpAddr IP_ADDR_ANY = {0};
53 
54 
55 /**
56  * @brief Send an IP datagram
57  * @param[in] interface Underlying network interface
58  * @param[in] pseudoHeader IP pseudo header
59  * @param[in] buffer Multi-part buffer containing the payload
60  * @param[in] offset Offset to the first payload byte
61  * @param[in] ancillary Additional options passed to the stack along with
62  * the packet
63  * @return Error code
64  **/
65 
67  const IpPseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset,
68  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  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 = TRUE;
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 Determine whether an IP address is a broadcast address
282  * @param[in] ipAddr IP address
283  * @return TRUE if the IP address is a broadcast address, else FALSE
284  **/
285 
287 {
288  bool_t result;
289 
290 #if (IPV4_SUPPORT == ENABLED)
291  //Broadcast address?
292  if(ipAddr->length == sizeof(Ipv4Addr) &&
293  ipAddr->ipv4Addr == IPV4_BROADCAST_ADDR)
294  {
295  result = TRUE;
296  }
297  else
298 #endif
299  {
300  result = FALSE;
301  }
302 
303  //Return TRUE if the IP address is a broadcast address, else FALSE
304  return result;
305 }
306 
307 
308 /**
309  * @brief Compare IP addresses
310  * @param[in] ipAddr1 First IP address
311  * @param[in] ipAddr2 Second IP address
312  * @return Comparison result
313  **/
314 
315 bool_t ipCompAddr(const IpAddr *ipAddr1, const IpAddr *ipAddr2)
316 {
317  bool_t result;
318 
319 #if (IPV4_SUPPORT == ENABLED)
320  //IPv4 addresses?
321  if(ipAddr1->length == sizeof(Ipv4Addr) && ipAddr2->length == sizeof(Ipv4Addr))
322  {
323  //Compare IPv4 addresses
324  if(ipAddr1->ipv4Addr == ipAddr2->ipv4Addr)
325  {
326  result = TRUE;
327  }
328  else
329  {
330  result = FALSE;
331  }
332  }
333  else
334 #endif
335 #if (IPV6_SUPPORT == ENABLED)
336  //IPv6 addresses?
337  if(ipAddr1->length == sizeof(Ipv6Addr) && ipAddr2->length == sizeof(Ipv6Addr))
338  {
339  //Compare IPv6 addresses
340  result = ipv6CompAddr(&ipAddr1->ipv6Addr, &ipAddr2->ipv6Addr);
341  }
342  else
343 #endif
344  //Unspecified IP addresses?
345  if(ipAddr1->length == 0 && ipAddr2->length == 0)
346  {
347  result = TRUE;
348  }
349  //Inconsistent IP addresses?
350  else
351  {
352  result = FALSE;
353  }
354 
355  //Return TRUE if the IP addresses match, else FALSE
356  return result;
357 }
358 
359 
360 /**
361  * @brief Compare IP address prefixes
362  * @param[in] ipAddr1 First IP address
363  * @param[in] ipAddr2 Second IP address
364  * @param[in] length Prefix length
365  * @return TRUE if the prefixes match each other, else FALSE
366  **/
367 
368 bool_t ipCompPrefix(const IpAddr *ipAddr1, const IpAddr *ipAddr2,
369  size_t length)
370 {
371  bool_t result;
372 
373 #if (IPV4_SUPPORT == ENABLED)
374  //IPv4 addresses?
375  if(ipAddr1->length == sizeof(Ipv4Addr) && ipAddr2->length == sizeof(Ipv4Addr))
376  {
377  //Compare IPv4 address prefixes
378  result = ipv4CompPrefix(ipAddr1->ipv4Addr, ipAddr2->ipv4Addr, length);
379  }
380  else
381 #endif
382 #if (IPV6_SUPPORT == ENABLED)
383  //IPv6 addresses?
384  if(ipAddr1->length == sizeof(Ipv6Addr) && ipAddr2->length == sizeof(Ipv6Addr))
385  {
386  //Compare IPv6 address prefixes
387  result = ipv6CompPrefix(&ipAddr1->ipv6Addr, &ipAddr2->ipv6Addr, length);
388  }
389  else
390 #endif
391  //Inconsistent IP addresses?
392  {
393  result = FALSE;
394  }
395 
396  //Return TRUE if the prefixes match each other, else FALSE
397  return result;
398 }
399 
400 
401 /**
402  * @brief Join the specified host group
403  * @param[in] interface Underlying network interface (optional parameter)
404  * @param[in] groupAddr IP address identifying the host group to join
405  * @return Error code
406  **/
407 
409 {
410  error_t error;
411 
412  //Use default network interface?
413  if(interface == NULL)
414  {
415  interface = netGetDefaultInterface();
416  }
417 
418 #if (IPV4_SUPPORT == ENABLED)
419  //IPv4 multicast address?
420  if(groupAddr->length == sizeof(Ipv4Addr))
421  {
422  //Join the specified host group
423  error = ipv4JoinMulticastGroup(interface, groupAddr->ipv4Addr);
424  }
425  else
426 #endif
427 #if (IPV6_SUPPORT == ENABLED)
428  //IPv6 multicast address?
429  if(groupAddr->length == sizeof(Ipv6Addr))
430  {
431  //Join the specified host group
432  error = ipv6JoinMulticastGroup(interface, &groupAddr->ipv6Addr);
433  }
434  else
435 #endif
436  //Invalid IP address?
437  {
438  //Report an error
439  error = ERROR_INVALID_ADDRESS;
440  }
441 
442  //Return status code
443  return error;
444 }
445 
446 
447 /**
448  * @brief Leave the specified host group
449  * @param[in] interface Underlying network interface (optional parameter)
450  * @param[in] groupAddr IP address identifying the host group to leave
451  * @return Error code
452  **/
453 
455 {
456  error_t error;
457 
458  //Use default network interface?
459  if(interface == NULL)
460  {
461  interface = netGetDefaultInterface();
462  }
463 
464 #if (IPV4_SUPPORT == ENABLED)
465  //IPv4 multicast address?
466  if(groupAddr->length == sizeof(Ipv4Addr))
467  {
468  //Drop membership
469  error = ipv4LeaveMulticastGroup(interface, groupAddr->ipv4Addr);
470  }
471  else
472 #endif
473 #if (IPV6_SUPPORT == ENABLED)
474  //IPv6 multicast address?
475  if(groupAddr->length == sizeof(Ipv6Addr))
476  {
477  //Drop membership
478  error = ipv6LeaveMulticastGroup(interface, &groupAddr->ipv6Addr);
479  }
480  else
481 #endif
482  //Invalid IP address?
483  {
484  error = ERROR_INVALID_ADDRESS;
485  }
486 
487  //Return status code
488  return error;
489 }
490 
491 
492 /**
493  * @brief IP checksum calculation
494  * @param[in] data Pointer to the data over which to calculate the IP checksum
495  * @param[in] length Number of bytes to process
496  * @return Checksum value
497  **/
498 
499 uint16_t ipCalcChecksum(const void *data, size_t length)
500 {
501  uint32_t temp;
502  uint32_t checksum;
503  const uint8_t *p;
504 
505  //Checksum preset value
506  checksum = 0x0000;
507 
508  //Point to the data over which to calculate the IP checksum
509  p = (const uint8_t *) data;
510 
511  //Pointer not aligned on a 16-bit boundary?
512  if(((uintptr_t) p & 1) != 0)
513  {
514  if(length >= 1)
515  {
516 #ifdef _CPU_BIG_ENDIAN
517  //Update checksum value
518  checksum += (uint32_t) *p;
519 #else
520  //Update checksum value
521  checksum += (uint32_t) *p << 8;
522 #endif
523  //Restore the alignment on 16-bit boundaries
524  p++;
525  //Number of bytes left to process
526  length--;
527  }
528  }
529 
530  //Pointer not aligned on a 32-bit boundary?
531  if(((uintptr_t) p & 2) != 0)
532  {
533  if(length >= 2)
534  {
535  //Update checksum value
536  checksum += (uint32_t) *((uint16_t *) p);
537 
538  //Restore the alignment on 32-bit boundaries
539  p += 2;
540  //Number of bytes left to process
541  length -= 2;
542  }
543  }
544 
545  //Process the data 4 bytes at a time
546  while(length >= 4)
547  {
548  //Update checksum value
549  temp = checksum + *((uint32_t *) p);
550 
551  //Add carry bit, if any
552  if(temp < checksum)
553  {
554  checksum = temp + 1;
555  }
556  else
557  {
558  checksum = temp;
559  }
560 
561  //Point to the next 32-bit word
562  p += 4;
563  //Number of bytes left to process
564  length -= 4;
565  }
566 
567  //Fold 32-bit sum to 16 bits
568  checksum = (checksum & 0xFFFF) + (checksum >> 16);
569 
570  //Add left-over 16-bit word, if any
571  if(length >= 2)
572  {
573  //Update checksum value
574  checksum += (uint32_t) *((uint16_t *) p);
575 
576  //Point to the next byte
577  p += 2;
578  //Number of bytes left to process
579  length -= 2;
580  }
581 
582  //Add left-over byte, if any
583  if(length >= 1)
584  {
585 #ifdef _CPU_BIG_ENDIAN
586  //Update checksum value
587  checksum += (uint32_t) *p << 8;
588 #else
589  //Update checksum value
590  checksum += (uint32_t) *p;
591 #endif
592  }
593 
594  //Fold 32-bit sum to 16 bits (first pass)
595  checksum = (checksum & 0xFFFF) + (checksum >> 16);
596  //Fold 32-bit sum to 16 bits (second pass)
597  checksum = (checksum & 0xFFFF) + (checksum >> 16);
598 
599  //Restore checksum endianness
600  if(((uintptr_t) data & 1) != 0)
601  {
602  //Swap checksum value
603  checksum = ((checksum >> 8) | (checksum << 8)) & 0xFFFF;
604  }
605 
606  //Return 1's complement value
607  return checksum ^ 0xFFFF;
608 }
609 
610 
611 /**
612  * @brief Calculate IP checksum over a multi-part buffer
613  * @param[in] buffer Pointer to the multi-part buffer
614  * @param[in] offset Offset from the beginning of the buffer
615  * @param[in] length Number of bytes to process
616  * @return Checksum value
617  **/
618 
619 uint16_t ipCalcChecksumEx(const NetBuffer *buffer, size_t offset, size_t length)
620 {
621  uint_t i;
622  uint_t n;
623  uint_t pos;
624  uint8_t *data;
625  uint32_t checksum;
626 
627  //Checksum preset value
628  checksum = 0x0000;
629 
630  //Current position in the multi-part buffer
631  pos = 0;
632 
633  //Loop through data chunks
634  for(i = 0; i < buffer->chunkCount && pos < length; i++)
635  {
636  //Is there any data to process in the current chunk?
637  if(offset < buffer->chunk[i].length)
638  {
639  //Point to the first data byte
640  data = (uint8_t *) buffer->chunk[i].address + offset;
641 
642  //Number of bytes available in the current chunk
643  n = buffer->chunk[i].length - offset;
644  //Limit the number of byte to process
645  n = MIN(n, length - pos);
646 
647  //Take care of alignment issues
648  if((pos & 1) != 0)
649  {
650  //Swap checksum value
651  checksum = ((checksum >> 8) | (checksum << 8)) & 0xFFFF;
652  }
653 
654  //Process data chunk
655  checksum += ipCalcChecksum(data, n) ^ 0xFFFF;
656  //Fold 32-bit sum to 16 bits
657  checksum = (checksum & 0xFFFF) + (checksum >> 16);
658 
659  //Restore checksum endianness
660  if((pos & 1) != 0)
661  {
662  //Swap checksum value
663  checksum = ((checksum >> 8) | (checksum << 8)) & 0xFFFF;
664  }
665 
666  //Advance current position
667  pos += n;
668  //Process the next block from the start
669  offset = 0;
670  }
671  else
672  {
673  //Skip the current chunk
674  offset -= buffer->chunk[i].length;
675  }
676  }
677 
678  //Return 1's complement value
679  return checksum ^ 0xFFFF;
680 }
681 
682 
683 /**
684  * @brief Calculate IP upper-layer checksum
685  * @param[in] pseudoHeader Pointer to the pseudo header
686  * @param[in] pseudoHeaderLen Pseudo header length
687  * @param[in] data Pointer to the upper-layer data
688  * @param[in] dataLen Upper-layer data length
689  * @return Checksum value
690  **/
691 
692 uint16_t ipCalcUpperLayerChecksum(const void *pseudoHeader,
693  size_t pseudoHeaderLen, const void *data, size_t dataLen)
694 {
695  uint32_t checksum;
696 
697  //Process pseudo header
698  checksum = ipCalcChecksum(pseudoHeader, pseudoHeaderLen) ^ 0xFFFF;
699  //Process upper-layer data
700  checksum += ipCalcChecksum(data, dataLen) ^ 0xFFFF;
701  //Fold 32-bit sum to 16 bits
702  checksum = (checksum & 0xFFFF) + (checksum >> 16);
703 
704  //Return 1's complement value
705  return checksum ^ 0xFFFF;
706 }
707 
708 
709 /**
710  * @brief Calculate IP upper-layer checksum over a multi-part buffer
711  * @param[in] pseudoHeader Pointer to the pseudo header
712  * @param[in] pseudoHeaderLen Pseudo header length
713  * @param[in] buffer Multi-part buffer containing the upper-layer data
714  * @param[in] offset Offset from the first data byte to process
715  * @param[in] length Number of data bytes to process
716  * @return Checksum value
717  **/
718 
719 uint16_t ipCalcUpperLayerChecksumEx(const void *pseudoHeader,
720  size_t pseudoHeaderLen, const NetBuffer *buffer, size_t offset, size_t length)
721 {
722  uint32_t checksum;
723 
724  //Process pseudo header
725  checksum = ipCalcChecksum(pseudoHeader, pseudoHeaderLen) ^ 0xFFFF;
726  //Process upper-layer data
727  checksum += ipCalcChecksumEx(buffer, offset, length) ^ 0xFFFF;
728  //Fold 32-bit sum to 16 bits
729  checksum = (checksum & 0xFFFF) + (checksum >> 16);
730 
731  //Return 1's complement value
732  return checksum ^ 0xFFFF;
733 }
734 
735 
736 /**
737  * @brief Allocate a buffer to hold an IP packet
738  * @param[in] length Desired payload length
739  * @param[out] offset Offset to the first byte of the payload
740  * @return The function returns a pointer to the newly allocated
741  * buffer. If the system is out of resources, NULL is returned
742  **/
743 
744 NetBuffer *ipAllocBuffer(size_t length, size_t *offset)
745 {
746  size_t headerLen;
747  NetBuffer *buffer;
748 
749 #if (IPV6_SUPPORT == ENABLED)
750  //Maximum overhead when using IPv6
751  headerLen = sizeof(Ipv6Header) + sizeof(Ipv6FragmentHeader);
752 #else
753  //Maximum overhead when using IPv4
754  headerLen = sizeof(Ipv4Header) + sizeof(uint32_t);
755 #endif
756 
757 #if (IPV4_IPSEC_SUPPORT == ENABLED && AH_SUPPORT == ENABLED)
758  //Maximum overhead caused by AH security protocol
759  headerLen += AH_MAX_OVERHEAD;
760 #endif
761 
762 #if (ETH_SUPPORT == ENABLED)
763  //Allocate a buffer to hold the Ethernet header and the IP packet
764  buffer = ethAllocBuffer(length + headerLen, offset);
765 #elif (PPP_SUPPORT == ENABLED)
766  //Allocate a buffer to hold the PPP header and the IP packet
767  buffer = pppAllocBuffer(length + headerLen, offset);
768 #else
769  //Allocate a buffer to hold the IP packet
770  buffer = netBufferAlloc(length + headerLen);
771  //Clear offset value
772  *offset = 0;
773 #endif
774 
775  //Successful memory allocation?
776  if(buffer != NULL)
777  {
778  //Offset to the first byte of the payload
779  *offset += headerLen;
780  }
781 
782  //Return a pointer to the freshly allocated buffer
783  return buffer;
784 }
785 
786 
787 /**
788  * @brief Convert a string representation of an IP address to a binary IP address
789  * @param[in] str NULL-terminated string representing the IP address
790  * @param[out] ipAddr Binary representation of the IP address
791  * @return Error code
792  **/
793 
795 {
796  error_t error;
797 
798 #if (IPV6_SUPPORT == ENABLED)
799  //IPv6 address?
800  if(osStrchr(str, ':') != NULL)
801  {
802  //IPv6 addresses are 16-byte long
803  ipAddr->length = sizeof(Ipv6Addr);
804  //Convert the string to IPv6 address
805  error = ipv6StringToAddr(str, &ipAddr->ipv6Addr);
806  }
807  else
808 #endif
809 #if (IPV4_SUPPORT == ENABLED)
810  //IPv4 address?
811  if(osStrchr(str, '.') != NULL)
812  {
813  //IPv4 addresses are 4-byte long
814  ipAddr->length = sizeof(Ipv4Addr);
815  //Convert the string to IPv4 address
816  error = ipv4StringToAddr(str, &ipAddr->ipv4Addr);
817  }
818  else
819 #endif
820  //Invalid IP address?
821  {
822  //Report an error
823  error = ERROR_FAILURE;
824  }
825 
826  //Return status code
827  return error;
828 }
829 
830 
831 /**
832  * @brief Convert a binary IP address to a string representation
833  * @param[in] ipAddr Binary representation of the IP address
834  * @param[out] str NULL-terminated string representing the IP address
835  * @return Pointer to the formatted string
836  **/
837 
839 {
840 #if (IPV4_SUPPORT == ENABLED)
841  //IPv4 address?
842  if(ipAddr->length == sizeof(Ipv4Addr))
843  {
844  //Convert IPv4 address to string representation
845  return ipv4AddrToString(ipAddr->ipv4Addr, str);
846  }
847  else
848 #endif
849 #if (IPV6_SUPPORT == ENABLED)
850  //IPv6 address?
851  if(ipAddr->length == sizeof(Ipv6Addr))
852  {
853  //Convert IPv6 address to string representation
854  return ipv6AddrToString(&ipAddr->ipv6Addr, str);
855  }
856  else
857 #endif
858  //Invalid IP address?
859  {
860  static char_t c;
861 
862  //The last parameter is optional
863  if(str == NULL)
864  {
865  str = &c;
866  }
867 
868  //Properly terminate the string
869  str[0] = '\0';
870 
871  //Return an empty string
872  return str;
873  }
874 }
AH (IP Authentication Header)
#define AH_MAX_OVERHEAD
Definition: ah.h:119
unsigned int uint_t
Definition: compiler_port.h:50
char char_t
Definition: compiler_port.h:48
int bool_t
Definition: compiler_port.h:53
Debugging facilities.
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ ERROR_INVALID_ADDRESS
Definition: error.h:103
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
NetBuffer * ethAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an Ethernet frame.
Definition: ethernet.c:775
Ethernet.
MacAddr srcAddr
Definition: ethernet.h:220
uint8_t data[]
Definition: ethernet.h:222
Ipv4Addr groupAddr
Definition: igmp_common.h:171
const IpAddr IP_ADDR_ANY
Definition: ip.c:51
NetBuffer * ipAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an IP packet.
Definition: ip.c:744
bool_t ipIsBroadcastAddr(const IpAddr *ipAddr)
Determine whether an IP address is a broadcast address.
Definition: ip.c:286
bool_t ipIsLinkLocalAddr(const IpAddr *ipAddr)
Determine whether an IP address is a link-local address.
Definition: ip.c:210
error_t ipSelectSourceAddr(NetInterface **interface, const IpAddr *destAddr, IpAddr *srcAddr)
IP source address selection.
Definition: ip.c:117
error_t ipLeaveMulticastGroup(NetInterface *interface, const IpAddr *groupAddr)
Leave the specified host group.
Definition: ip.c:454
uint16_t ipCalcChecksumEx(const NetBuffer *buffer, size_t offset, size_t length)
Calculate IP checksum over a multi-part buffer.
Definition: ip.c:619
bool_t ipIsMulticastAddr(const IpAddr *ipAddr)
Determine whether an IP address is a multicast address.
Definition: ip.c:248
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:719
error_t ipSendDatagram(NetInterface *interface, const IpPseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IP datagram.
Definition: ip.c:66
bool_t ipIsUnspecifiedAddr(const IpAddr *ipAddr)
Compare an IP address against the unspecified address.
Definition: ip.c:165
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:794
bool_t ipCompPrefix(const IpAddr *ipAddr1, const IpAddr *ipAddr2, size_t length)
Compare IP address prefixes.
Definition: ip.c:368
const IpAddr IP_ADDR_UNSPECIFIED
Definition: ip.c:52
error_t ipJoinMulticastGroup(NetInterface *interface, const IpAddr *groupAddr)
Join the specified host group.
Definition: ip.c:408
uint16_t ipCalcUpperLayerChecksum(const void *pseudoHeader, size_t pseudoHeaderLen, const void *data, size_t dataLen)
Calculate IP upper-layer checksum.
Definition: ip.c:692
bool_t ipCompAddr(const IpAddr *ipAddr1, const IpAddr *ipAddr2)
Compare IP addresses.
Definition: ip.c:315
char_t * ipAddrToString(const IpAddr *ipAddr, char_t *str)
Convert a binary IP address to a string representation.
Definition: ip.c:838
uint16_t ipCalcChecksum(const void *data, size_t length)
IP checksum calculation.
Definition: ip.c:499
IPv4 and IPv6 common routines.
Ipv4Addr ipAddr
Definition: ipcp.h:105
IPsec (IP security)
error_t ipv4SendDatagram(NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IPv4 datagram.
Definition: ipv4.c:1004
char_t * ipv4AddrToString(Ipv4Addr ipAddr, char_t *str)
Convert a binary IPv4 address to dot-decimal notation.
Definition: ipv4.c:1636
error_t ipv4StringToAddr(const char_t *str, Ipv4Addr *ipAddr)
Convert a dot-decimal string to a binary IPv4 address.
Definition: ipv4.c:1547
error_t ipv4LeaveMulticastGroup(NetInterface *interface, Ipv4Addr groupAddr)
Leave the specified host group.
Definition: ipv4.c:1471
error_t ipv4JoinMulticastGroup(NetInterface *interface, Ipv4Addr groupAddr)
Join the specified host group.
Definition: ipv4.c:1362
IPv4 (Internet Protocol Version 4)
#define Ipv4PseudoHeader
Definition: ipv4.h:39
#define IPV4_BROADCAST_ADDR
Definition: ipv4.h:112
#define Ipv4Header
Definition: ipv4.h:36
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:267
#define IPV4_UNSPECIFIED_ADDR
Definition: ipv4.h:110
#define ipv4IsMulticastAddr(ipAddr)
Definition: ipv4.h:168
Ipv4Addr destAddr
Definition: ipv4.h:299
#define ipv4IsLinkLocalAddr(ipAddr)
Definition: ipv4.h:164
bool_t ipv4CompPrefix(Ipv4Addr ipAddr1, Ipv4Addr ipAddr2, size_t length)
Compare IPv4 address prefixes.
Definition: ipv4_misc.c:621
error_t ipv4SelectSourceAddr(NetInterface **interface, Ipv4Addr destAddr, Ipv4Addr *srcAddr)
IPv4 source address selection.
Definition: ipv4_misc.c:202
Helper functions for IPv4.
error_t ipv6LeaveMulticastGroup(NetInterface *interface, const Ipv6Addr *groupAddr)
Leave an IPv6 multicast group.
Definition: ipv6.c:2145
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:2221
char_t * ipv6AddrToString(const Ipv6Addr *ipAddr, char_t *str)
Convert a binary IPv6 address to a string representation.
Definition: ipv6.c:2376
const Ipv6Addr IPV6_UNSPECIFIED_ADDR
Definition: ipv6.c:65
error_t ipv6SendDatagram(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IPv6 datagram.
Definition: ipv6.c:1667
error_t ipv6JoinMulticastGroup(NetInterface *interface, const Ipv6Addr *groupAddr)
Join an IPv6 multicast group.
Definition: ipv6.c:2035
IPv6 (Internet Protocol Version 6)
Ipv6Addr
Definition: ipv6.h:251
#define Ipv6PseudoHeader
Definition: ipv6.h:42
#define ipv6IsMulticastAddr(ipAddr)
Definition: ipv6.h:132
#define ipv6IsLinkLocalUnicastAddr(ipAddr)
Definition: ipv6.h:124
#define Ipv6FragmentHeader
Definition: ipv6.h:39
#define ipv6CompAddr(ipAddr1, ipAddr2)
Definition: ipv6.h:120
#define Ipv6Header
Definition: ipv6.h:36
error_t ipv6SelectSourceAddr(NetInterface **interface, const Ipv6Addr *destAddr, Ipv6Addr *srcAddr)
IPv6 source address selection.
Definition: ipv6_misc.c:895
bool_t ipv6CompPrefix(const Ipv6Addr *ipAddr1, const Ipv6Addr *ipAddr2, size_t length)
Compare IPv6 address prefixes.
Definition: ipv6_misc.c:1221
Helper functions for IPv6.
uint8_t c
Definition: ndp.h:514
uint8_t p
Definition: ndp.h:300
NetInterface * netGetDefaultInterface(void)
Get default network interface.
Definition: net.c:470
TCP/IP stack core.
#define NetInterface
Definition: net.h:36
NetBuffer * netBufferAlloc(size_t length)
Allocate a multi-part buffer.
Definition: net_mem.c:243
#define NetTxAncillary
Definition: net_misc.h:36
#define MIN(a, b)
Definition: os_port.h:63
#define osStrchr(s, c)
Definition: os_port.h:195
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
NetBuffer * pppAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold a PPP frame.
Definition: ppp.c:1305
uint32_t dataLen
Definition: sftp_common.h:229
uint16_t length
Definition: net_mem.h:79
void * address
Definition: net_mem.h:78
IP network address.
Definition: ip.h:79
Ipv6Addr ipv6Addr
Definition: ip.h:87
Ipv4Addr ipv4Addr
Definition: ip.h:84
size_t length
Definition: ip.h:80
IP pseudo header.
Definition: ip.h:99
Ipv4PseudoHeader ipv4Data
Definition: ip.h:104
Ipv6PseudoHeader ipv6Data
Definition: ip.h:107
size_t length
Definition: ip.h:100
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
uint_t chunkCount
Definition: net_mem.h:90
ChunkDesc chunk[]
Definition: net_mem.h:92
uint8_t length
Definition: tcp.h:368
uint16_t checksum
Definition: tcp.h:355