walnux/include/nuttx/net/ip.h
wangchen 204f4a18a0 Support to ARP Address Conflict Detection
Support to ARP Address Conflict Detection

Signed-off-by: wangchen <wangchen41@xiaomi.com>
2024-01-25 11:25:03 -03:00

781 lines
26 KiB
C

/****************************************************************************
* 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 <gnutt@nuttx.org>
*
* This logic was leveraged from uIP which also has a BSD-style license:
*
* Author Adam Dunkels <adam@dunkels.com>
* 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 <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <nuttx/net/netconfig.h>
#include <nuttx/wqueue.h>
/****************************************************************************
* 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 */