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