/**************************************************************************** * include/nuttx/net/ip.h * * This header file contains IP-related definitions for a number of C * macros that are used by applications as well as internally by the * OS networking logic. * * Copyright (C) 2007-2012, 2014 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * This logic was leveraged from uIP which also has a BSD-style license: * * Author Adam Dunkels * Copyright (c) 2001-2003, Adam Dunkels. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************/ #ifndef __INCLUDE_NUTTX_NET_IP_H #define __INCLUDE_NUTTX_NET_IP_H /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include #include /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ /* IP Version Mask (bits 0-3 of first byte) */ #define IP_VERSION_MASK 0x70 #define IPv4_VERSION 0x40 #define IPv6_VERSION 0x60 /* Values for the IP protocol field */ #define IP_PROTO_ICMP 1 #define IP_PROTO_IGMP 2 #define IP_PROTO_TCP 6 #define IP_PROTO_UDP 17 #define IP_PROTO_ICMP6 58 /* Values for the TOS field */ #define IPTOS_TOS_MASK 0x1e #define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) #define IPTOS_LOWDELAY 0x10 #define IPTOS_THROUGHPUT 0x08 #define IPTOS_RELIABILITY 0x04 #define IPTOS_MINCOST 0x02 #define IPTOS_PREC_MASK 0xe0 #define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) #define IPTOS_PREC_NETCONTROL 0xe0 #define IPTOS_PREC_INTERNETCONTROL 0xc0 #define IPTOS_PREC_CRITIC_ECP 0xa0 #define IPTOS_PREC_FLASHOVERRIDE 0x80 #define IPTOS_PREC_FLASH 0x60 #define IPTOS_PREC_IMMEDIATE 0x40 #define IPTOS_PREC_PRIORITY 0x20 #define IPTOS_PREC_ROUTINE 0x00 /* Flag bits in 16-bit flags + fragment offset IPv4 header field */ #define IP_FLAG_RESERVED 0x8000 #define IP_FLAG_DONTFRAG 0x4000 #define IP_FLAG_MOREFRAGS 0x2000 /* IP Header sizes */ #ifdef CONFIG_NET_IPv4 # define IPv4_HDRLEN 20 /* Size of IPv4 header (without options) */ # define IPv4_HLMASK 0x0f /* Isolates headler length in VHL field */ # define IPV4_OPTMAX 40 /* The limit of ip option length */ #endif #ifdef CONFIG_NET_IPv6 # define IPv6_HDRLEN 40 /* Size of IPv6 header */ #endif /**************************************************************************** * Public Type Definitions ****************************************************************************/ /* Representation of an IP address in the IPv6 domains */ typedef uint16_t net_ipv6addr_t[8]; #if defined(CONFIG_NET_IPv4) || defined(CONFIG_NET_IPv6) /* Describes and address in either the IPv4 or IPv6 domain */ union ip_addr_u { #ifdef CONFIG_NET_IPv4 /* IPv4 address */ in_addr_t ipv4; #endif #ifdef CONFIG_NET_IPv6 /* IPv6 address */ net_ipv6addr_t ipv6; #endif }; #endif #if defined(CONFIG_NET_IPv4) || defined(CONFIG_NET_IPv6) /* Describes address binding for a PF_INET or PF_INET6 socket */ union ip_binding_u { #ifdef CONFIG_NET_IPv4 /* IPv4 addresses (for PF_INET socket) */ struct { in_addr_t laddr; /* The bound local IPv4 address */ in_addr_t raddr; /* The IPv4 address of the remote host */ } ipv4; #endif /* CONFIG_NET_IPv4 */ #ifdef CONFIG_NET_IPv6 /* IPv6 addresses (for PF_INET6 socket) */ struct { net_ipv6addr_t laddr; /* The bound local IPv6 address */ net_ipv6addr_t raddr; /* The IPv6 address of the remote host */ } ipv6; #endif /* CONFIG_NET_IPv6 */ }; #endif #ifdef CONFIG_NET_IPv4 /* The IPv4 header */ struct ipv4_hdr_s { uint8_t vhl; /* 8-bit Version (4) and header length (5 or 6) */ uint8_t tos; /* 8-bit Type of service (e.g., 6=TCP) */ uint8_t len[2]; /* 16-bit Total length */ uint8_t ipid[2]; /* 16-bit Identification */ uint8_t ipoffset[2]; /* 16-bit IP flags + fragment offset */ uint8_t ttl; /* 8-bit Time to Live */ uint8_t proto; /* 8-bit Protocol */ uint16_t ipchksum; /* 16-bit Header checksum */ uint16_t srcipaddr[2]; /* 32-bit Source IP address */ uint16_t destipaddr[2]; /* 32-bit Destination IP address */ }; /* The IPv4 options */ struct ipv4_opt_s { uint8_t len; uint8_t data[IPV4_OPTMAX]; }; #endif /* CONFIG_NET_IPv4 */ #ifdef CONFIG_NET_IPv6 /* The IPv6 header */ struct ipv6_hdr_s { uint8_t vtc; /* Bits 0-3: version, bits 4-7: traffic class (MS) */ uint8_t tcf; /* Bits 0-3: traffic class (LS), 4-bits: flow label (MS) */ uint16_t flow; /* 16-bit flow label (LS) */ uint8_t len[2]; /* 16-bit Payload length */ uint8_t proto; /* 8-bit Next header (same as IPv4 protocol field) */ uint8_t ttl; /* 8-bit Hop limit (like IPv4 TTL field) */ net_ipv6addr_t srcipaddr; /* 128-bit Source address */ net_ipv6addr_t destipaddr; /* 128-bit Destination address */ }; #endif /* CONFIG_NET_IPv6 */ #ifdef CONFIG_NET_STATISTICS #ifdef CONFIG_NET_IPv4 struct ipv4_stats_s { net_stats_t drop; /* Number of dropped packets at the IP layer */ net_stats_t recv; /* Number of received packets at the IP layer */ net_stats_t sent; /* Number of sent packets at the IP layer */ net_stats_t vhlerr; /* Number of packets dropped due to wrong * IP version or header length */ net_stats_t fragerr; /* Number of packets dropped since they * were IP fragments */ net_stats_t chkerr; /* Number of packets dropped due to IP * checksum errors */ net_stats_t protoerr; /* Number of packets dropped since they * were neither ICMP, UDP nor TCP */ }; #endif /* CONFIG_NET_IPv6 */ #ifdef CONFIG_NET_IPv6 struct ipv6_stats_s { net_stats_t drop; /* Number of dropped packets at the IP layer */ net_stats_t recv; /* Number of received packets at the IP layer */ net_stats_t sent; /* Number of sent packets at the IP layer */ net_stats_t vhlerr; /* Number of packets dropped due to wrong * IP version or header length */ net_stats_t fragerr; /* Number of packets dropped since they * were IP fragments */ net_stats_t protoerr; /* Number of packets dropped since they * were neither ICMP, UDP nor TCP */ }; #endif /* CONFIG_NET_IPv6 */ #endif /* CONFIG_NET_STATISTICS */ #ifdef CONFIG_NET_ARP_ACD #define ARP_ACD_TMR_INTERVAL 100 /* milliseconds */ #define ARP_ACD_TICKS_PER_SECOND (1000 / ARP_ACD_TMR_INTERVAL) /* RFC 5227 Constants */ #define ANNOUNCE_NUM 2 /* (number of announcement packets) */ #define ANNOUNCE_INTERVAL 2 /* seconds (time between announcement packets) */ #define ANNOUNCE_WAIT 2 /* seconds (delay before announcing) */ #define DEFEND_INTERVAL 10 /* seconds (min. wait between defensive ARPs) */ /* arp acd entry states */ enum arp_acd_state_e { ARP_ACD_STATE_INIT = 0, ARP_ACD_STATE_ANNOUNCING = 1, ARP_ACD_STATE_FINISH = 2 }; #define ARP_ACD_ADDRESS_NO_CONFLICT 0 #define ARP_ACD_ADDRESS_CONFLICT 1 struct arp_acd_s { enum arp_acd_state_e state; /* current arp_acd_s status */ int sendnum; /* sent number of probes or announces, dependent on state */ bool conflict_flag; /* arp address conflict flag */ bool need_announce; /* need to send arp announce packet */ uint32_t ttw; /* ticks to wait */ clock_t lastconflict; /* last conflict timestamp */ struct work_s work; /* For deferred timeout operations */ }; #endif /* CONFIG_NET_ARP_ACD */ /**************************************************************************** * Public Data ****************************************************************************/ #ifdef __cplusplus #define EXTERN extern "C" extern "C" { #else #define EXTERN extern #endif /**************************************************************************** * Public Function Prototypes ****************************************************************************/ /**************************************************************************** * Macro: net_ipaddr * * Description: * Construct an IPv4 address from four bytes. * * This function constructs an IPv4 address in network byte order. * * Input Parameters: * addr A pointer to a in_addr_t variable that will be * filled in with the IPv4 address. * addr0 The first octet of the IPv4 address. * addr1 The second octet of the IPv4 address. * addr2 The third octet of the IPv4 address. * addr3 The forth octet of the IPv4 address. * ****************************************************************************/ #define net_ipaddr(addr, addr0, addr1, addr2, addr3) \ do \ { \ addr = HTONL((uint32_t)(addr0) << 24 | (uint32_t)(addr1) << 16 | \ (uint32_t)(addr2) << 8 | (uint32_t)(addr3)); \ } \ while (0) /**************************************************************************** * Macro: net_ip4addr_conv32 * * Description: * Convert an IPv4 address of the form uint16_t[2] to an in_addr_t * ****************************************************************************/ #ifdef CONFIG_ENDIAN_BIG # define net_ip4addr_conv32(addr) \ (((in_addr_t)((FAR uint16_t *)addr)[0] << 16) | \ (in_addr_t)((FAR uint16_t *)addr)[1]) #else # define net_ip4addr_conv32(addr) \ (((in_addr_t)((FAR uint16_t *)addr)[1] << 16) | \ (in_addr_t)((FAR uint16_t *)addr)[0]) #endif /**************************************************************************** * Macro: ip4_addr1, ip4_addr2, ip4_addr3, and ip4_addr4 * * Description: * Extract individual bytes from a 32-bit IPv4 IP address that is in * network byte order. * ****************************************************************************/ #ifdef CONFIG_ENDIAN_BIG /* Big-endian byte order: 11223344 */ # define ip4_addr1(ipaddr) ((uint8_t)(((ipaddr) >> 24) & 0xff)) # define ip4_addr2(ipaddr) ((uint8_t)(((ipaddr) >> 16) & 0xff)) # define ip4_addr3(ipaddr) ((uint8_t)(((ipaddr) >> 8) & 0xff)) # define ip4_addr4(ipaddr) ((uint8_t)((ipaddr) & 0xff)) #else /* Little endian byte order: 44223311 */ # define ip4_addr1(ipaddr) ((uint8_t)((ipaddr) & 0xff)) # define ip4_addr2(ipaddr) ((uint8_t)(((ipaddr) >> 8) & 0xff)) # define ip4_addr3(ipaddr) ((uint8_t)(((ipaddr) >> 16) & 0xff)) # define ip4_addr4(ipaddr) ((uint8_t)(((ipaddr) >> 24) & 0xff)) #endif /**************************************************************************** * Macro: ip6_addr * * Description: * Construct an IPv6 address from eight 16-bit words. * ****************************************************************************/ #define ip6_addr(addr,addr0,addr1,addr2,addr3,addr4,addr5,addr6,addr7) \ do \ { \ ((FAR uint16_t *)(addr))[0] = HTONS((addr0)); \ ((FAR uint16_t *)(addr))[1] = HTONS((addr1)); \ ((FAR uint16_t *)(addr))[2] = HTONS((addr2)); \ ((FAR uint16_t *)(addr))[3] = HTONS((addr3)); \ ((FAR uint16_t *)(addr))[4] = HTONS((addr4)); \ ((FAR uint16_t *)(addr))[5] = HTONS((addr5)); \ ((FAR uint16_t *)(addr))[6] = HTONS((addr6)); \ ((FAR uint16_t *)(addr))[7] = HTONS((addr7)); \ } \ while (0) /**************************************************************************** * Macro: ip6_map_ipv4addr * * Description: * Hybrid dual-stack IPv6/IPv4 implementations recognize a special class * of addresses, the IPv4-mapped IPv6 addresses. These addresses consist * of: * * 1. An 80-bit prefix of zeros, * 2. The next 16 bits are one, and * 3. The remaining, least-significant 32 bits contain the IPv4 address. * * This macro encodes an IPv4 address in an IPv6 address in this fashion. * * Input Parameters: * ipv4addr - The IPv4 address to be mapped (scalar) * ipv6addr - The IPv6 address in which to map the IPv4 address (array) * * Returned Value: * None * ****************************************************************************/ #define ip6_map_ipv4addr(ipv4addr, ipv6addr) \ do \ { \ memset(ipv6addr, 0, 5 * sizeof(uint16_t)); \ (ipv6addr)[5] = 0xffff; \ net_ipv4addr_hdrcopy(&(ipv6addr)[6], &(ipv4addr)); \ } \ while (0) /**************************************************************************** * Macro: ip6_get_ipv4addr * * Description: * Decode an IPv4-mapped IPv6 address. * * Input Parameters: * ipv6addr - The IPv6 address (net_ipv6addr_t array) containing the mapped * IPv4 address * * Returned Value: * The decoded IPv4 address (scalar in_addr_t) * ****************************************************************************/ #define ip6_get_ipv4addr(ipv6addr) net_ip4addr_conv32(&(ipv6addr)[6]) /**************************************************************************** * Macro: ip6_is_ipv4addr * * Description: * Test if an IPv6 is an IPv4-mapped IPv6 address. * * Input Parameters: * ipv6addr - The IPv6 address to be tested * * Returned Value: * True is returned if ipv6addr holds a mapped IPv4 address. * ****************************************************************************/ #define ip6_is_ipv4addr(ipv6addr) \ ((ipv6addr)->s6_addr32[0] == 0 && \ (ipv6addr)->s6_addr32[1] == 0 && \ (ipv6addr)->s6_addr16[4] == 0 && \ (ipv6addr)->s6_addr16[5] == 0xffff) /**************************************************************************** * Macro: net_ip_domain_select * * Description: * Select different value by the domain (PF_INET/PF_INET6). * This domain only needs to exist when both IPv4 and IPv6 are enabled. * * Input Parameters: * value4 - The value returned when domain is PF_INET. * value6 - The value returned when domain is PF_INET6. * domain - The domain field which may only exists when both IPv4 and IPv6 * are enabled. * ****************************************************************************/ #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6) # define net_ip_domain_select(domain, value4, value6) \ (((domain) == PF_INET) ? (value4) : (value6)) #elif defined(CONFIG_NET_IPv4) # define net_ip_domain_select(domain, value4, value6) (value4) #else # define net_ip_domain_select(domain, value4, value6) (value6) #endif /**************************************************************************** * Macro: net_ip_binding_laddr, net_ip_binding_raddr * * Description: * Get the laddr/raddr pointer form an ip_binding_u. * * Input Parameters: * u - The union of address binding. * domain - The domain of address, only needs to exist when both IPv4 and * IPv6 are enabled. * ****************************************************************************/ #define net_ip_binding_laddr(u, domain) \ net_ip_domain_select(domain, (FAR void *)(&(u)->ipv4.laddr), \ (FAR void *)(&(u)->ipv6.laddr)) #define net_ip_binding_raddr(u, domain) \ net_ip_domain_select(domain, (FAR void *)(&(u)->ipv4.raddr), \ (FAR void *)(&(u)->ipv6.raddr)) /**************************************************************************** * Macro: net_ipv4addr_copy, net_ipv4addr_hdrcopy, net_ipv6addr_copy, and * net_ipv6addr_hdrcopy * * Description: * Copy an IP address from one place to another. * * Example: * * in_addr_t ipaddr1, ipaddr2; * * net_ipaddr(&ipaddr1, 192,16,1,2); * net_ipaddr_copy(&ipaddr2, &ipaddr1); * * Input Parameters: * dest - The destination for the copy. * src - The source from where to copy. * ****************************************************************************/ #ifdef CONFIG_NET_IPv4 # define net_ipv4addr_copy(dest, src) \ do \ { \ (dest) = (in_addr_t)(src); \ } \ while (0) # define net_ipv4addr_hdrcopy(dest, src) \ do \ { \ ((FAR uint16_t *)(dest))[0] = ((FAR uint16_t *)(src))[0]; \ ((FAR uint16_t *)(dest))[1] = ((FAR uint16_t *)(src))[1]; \ } \ while (0) #endif #ifdef CONFIG_NET_IPv6 # define net_ipv6addr_copy(dest,src) \ memcpy(dest, src, sizeof(net_ipv6addr_t)) # define net_ipv6addr_hdrcopy(dest,src) \ net_ipv6addr_copy(dest, src) #endif /**************************************************************************** * Macro: net_ipv4addr_cmp, net_ipv4addr_hdrcmp, net_ipv6addr_cmp, and * net_ipv6addr_hdrcmp * * Description: * Compare two IP addresses * * Example: * * in_addr_t ipaddr1, ipaddr2; * * net_ipaddr(&ipaddr1, 192,16,1,2); * if (net_ipv4addr_cmp(ipaddr2, ipaddr1)) * { * printf("They are the same"); * } * * Input Parameters: * addr1 - The first IP address. * addr2 - The second IP address. * ****************************************************************************/ #ifdef CONFIG_NET_IPv4 # define net_ipv4addr_cmp(addr1, addr2) \ (addr1 == addr2) # define net_ipv4addr_hdrcmp(addr1, addr2) \ net_ipv4addr_cmp(net_ip4addr_conv32(addr1), net_ip4addr_conv32(addr2)) #endif #ifdef CONFIG_NET_IPv6 # define net_ipv6addr_cmp(addr1, addr2) \ (memcmp(addr1, addr2, sizeof(net_ipv6addr_t)) == 0) # define net_ipv6addr_hdrcmp(addr1, addr2) \ net_ipv6addr_cmp(addr1, addr2) #endif /**************************************************************************** * Name: net_ipv4addr_maskcmp and net_ipv6addr_maskcmp * * Description: * Compare two IP addresses under a netmask. The mask is used to mask * out the bits that are to be compared: Buts within the mask much * match exactly; bits outside if the mask are ignored. * * IPv4 Example: * * net_ipv6addr_t ipaddr1; * net_ipv6addr_t ipaddr2; * net_ipv6addr_t mask; * * net_ipv6addr(&mask, 255,255,255,0); * net_ipv6addr(&ipaddr1, 192,16,1,2); * net_iv6paddr(&ipaddr2, 192,16,1,3); * if (net_ipv6addr_maskcmp(ipaddr1, ipaddr2, &mask)) * { * printf("They are the same"); * } * * Input Parameters: * addr1 - The first IP address. * addr2 - The second IP address. * mask - The netmask. * * Returned Value: * True if the address under the mask are equal * ****************************************************************************/ #ifdef CONFIG_NET_IPv4 # define net_ipv4addr_maskcmp(addr1, addr2, mask) \ (((in_addr_t)(addr1) & (in_addr_t)(mask)) == \ ((in_addr_t)(addr2) & (in_addr_t)(mask))) #endif #ifdef CONFIG_NET_IPv6 bool net_ipv6addr_maskcmp(const net_ipv6addr_t addr1, const net_ipv6addr_t addr2, const net_ipv6addr_t mask); #endif /**************************************************************************** * Name: net_ipv4addr_broadcast * * Description: * Mask out the network part of an IP address, given the address and * the netmask. * * Example: * * in_addr_t ipaddr; * in_addr_t netmask; * bool isbroadcast; * * net_ipaddr(&netmask, 255,255,255,0); * net_ipaddr(&ipaddr, 192,16,1,255); * isbroadcast = net_ipv4addr_broadcast(ipaddr, netmask); * * Will return isboadcast == true. * * net_ipaddr(&ipaddr, 192,16,1,2); * isbroadcast = net_ipv4addr_broadcast(ipaddr, netmask); * * Will return isboadcast == false. * * NOTES: * 1. This function does not check for the broadcast address * 255.255.255.255. That must be performed as a separate check. * 2. You must also separately check if the ipaddress lies on the sub-net * using, perhaps, net_ipv4addr_maskcmp(). * * Input Parameters: * addr - The IPv4 address to check * mask - The network mask * ****************************************************************************/ #define net_ipv4addr_broadcast(addr, mask) \ (((in_addr_t)(addr) & ~(in_addr_t)(mask)) == \ ((in_addr_t)(0xffffffff) & ~(in_addr_t)(mask))) /**************************************************************************** * Name: net_ipv6addr_prefixcmp * * Description: * Compare two IPv6 address prefixes. * ****************************************************************************/ #define net_ipv6addr_prefixcmp(addr1, addr2, length) \ (memcmp(addr1, addr2, length >> 3) == 0) /**************************************************************************** * Name: net_is_addr_loopback * * Description: * Is the IPv6 address a the loopback address? See RFC 4291 (replaces * 3513). * ****************************************************************************/ #define net_is_addr_loopback(a) \ ((a)[0] == 0 && (a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \ (a)[4] == 0 && (a)[5] == 0 && (a)[6] == 0 && (a)[7] == HTONS(0x0001)) /**************************************************************************** * Name: net_is_addr_unspecified * * Description: * Is the IPv6 address the unspecified address? See RFC 4291 (replaces * 3513). * ****************************************************************************/ #define net_is_addr_unspecified(a) \ ((a)[0] == 0 && (a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \ (a)[4] == 0 && (a)[5] == 0 && (a)[6] == 0 && (a)[7] == 0) /**************************************************************************** * Name: net_is_addr_mcast * * Description: * Is address a multicast address? See RFC 4291 (replaces 3513): * * An IPv6 multicast address is an identifier for a group of interfaces * (typically on different nodes). An interface may belong to any number * of multicast groups. Multicast addresses have the following format * (in host order): * * | 8 | 4 | 4 | 112 bits | * +------ -+----+----+---------------------------------------------+ * |11111111|flgs|scop| group ID | * +--------+----+----+---------------------------------------------+ * * Bits 120-127: Prefix == 0b11111111 * Bits 116-119: Flags (3 defined) * Bits 112-115: Scope * ****************************************************************************/ #define net_is_addr_mcast(a) (((a)[0] & HTONS(0xff00)) == HTONS(0xff00)) /**************************************************************************** * Name: net_is_addr_linklocal_allnodes_mcast * * Description: * Is IPv6 address a the link local all-nodes multicast address? See RFC * 2375 * ****************************************************************************/ #define net_is_addr_linklocal_allnodes_mcast(a) \ ((a)[0] == HTONS(0xff02) && (a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \ (a)[4] == 0 && (a)[5] == 0 && (a)[6] == 0 && (a)[7] == HTONS(0x0001)) /**************************************************************************** * Name: net_is_addr_linklocal_allrouters_mcast * * Description: * Is IPv6 address a the link local all-routers multicast address? See RFC * 2375 * ****************************************************************************/ #define net_is_addr_linklocal_allrouters_mcast(a) \ ((a)[0] == HTONS(0xff02) && (a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \ (a)[4] == 0 && (a)[5] == 0 && (a)[6] == 0 && (a)[7] == HTOS(0x0002)) /**************************************************************************** * Name: net_is_addr_linklocal * * Description: * Checks whether the address 'a' is a link local unicast address. See * RFC 4291 (replaces 3513). * ****************************************************************************/ #define net_is_addr_linklocal(a) ((a)[0] == HTONS(0xfe80)) /**************************************************************************** * Name: net_is_addr_sitelocal * * Description: * Checks whether the address 'a' is a site local unicast address. See * RFC 4291 (replaces 3513). * ****************************************************************************/ #define net_is_addr_sitelocal(a) ((a)[0] == HTONS(0xfec0)) #undef EXTERN #ifdef __cplusplus } #endif #endif /* __INCLUDE_NUTTX_NET_IP_H */