diff --git a/components/net/Kconfig b/components/net/Kconfig index 68737176ed..3db8201d8a 100644 --- a/components/net/Kconfig +++ b/components/net/Kconfig @@ -76,6 +76,25 @@ config RT_USING_NETDEV config NETDEV_USING_AUTO_DEFAULT bool "Enable default netdev automatic change features" default y + + config NETDEV_USING_IPV6 + bool "Enable IPV6 protocol support" + default n + + config NETDEV_IPV4 + int + default 1 + + config NETDEV_IPV6 + int + default 1 if NETDEV_USING_IPV6 + default 0 if !NETDEV_USING_IPV6 + + config NETDEV_IPV6_SCOPES + bool + help + Defined to synchronize the ip6_addr structure state + default n endif endmenu @@ -104,11 +123,11 @@ config RT_USING_LWIP endchoice if (RT_USING_LWIP210 || RT_USING_LWIP202) - if (!RT_USING_NETDEV || (RT_USING_NETDEV && NETDEV_IPV6)) - config RT_USING_LWIP_IPV6 - bool "IPV6 protocol" - default n - endif + config RT_USING_LWIP_IPV6 + bool "IPV6 protocol" + default n + select NETDEV_USING_IPV6 + select NETDEV_IPV6_SCOPES if RT_USING_LWIP210 endif config RT_LWIP_IGMP diff --git a/components/net/at/at_socket/at_socket.c b/components/net/at/at_socket/at_socket.c index 993ec33506..804443fe32 100644 --- a/components/net/at/at_socket/at_socket.c +++ b/components/net/at/at_socket/at_socket.c @@ -540,11 +540,12 @@ static int socketaddr_to_ipaddr_port(const struct sockaddr *sockaddr, ip_addr_t const struct sockaddr_in* sin = (const struct sockaddr_in*) (const void *) sockaddr; #if NETDEV_IPV4 && NETDEV_IPV6 - (*addr).u_addr.ip4.addr = sin->sin_addr.s_addr; + addr->u_addr.ip4.addr = sin->sin_addr.s_addr; + addr->type = IPADDR_TYPE_V4; #elif NETDEV_IPV4 - (*addr).addr = sin->sin_addr.s_addr; + addr->addr = sin->sin_addr.s_addr; #elif NETDEV_IPV6 - LOG_E("not support IPV6."); +#error "not support IPV6." #endif /* NETDEV_IPV4 && NETDEV_IPV6 */ *port = (uint16_t) HTONS_PORT(sin->sin_port); @@ -1126,10 +1127,11 @@ struct hostent *at_gethostbyname(const char *name) #if NETDEV_IPV4 && NETDEV_IPV6 addr.u_addr.ip4.addr = ipstr_to_u32(ipstr); + addr.type = IPADDR_TYPE_V4; #elif NETDEV_IPV4 addr.addr = ipstr_to_u32(ipstr); #elif NETDEV_IPV6 - LOG_E("not support IPV6."); +#error "not support IPV6." #endif /* NETDEV_IPV4 && NETDEV_IPV6 */ /* fill hostent structure */ @@ -1202,7 +1204,7 @@ int at_getaddrinfo(const char *nodename, const char *servname, if ((hints != RT_NULL) && (hints->ai_flags & AI_NUMERICHOST)) { /* no DNS lookup, just parse for an address string */ - if (!inet_aton(nodename, (ip4_addr_t * )&addr)) + if (!inet_aton(nodename, &addr)) { return EAI_NONAME; } @@ -1240,7 +1242,7 @@ int at_getaddrinfo(const char *nodename, const char *servname, #elif NETDEV_IPV4 addr.addr = ipstr_to_u32(ip_str); #elif NETDEV_IPV6 - LOG_E("not support IPV6."); + #error "not support IPV6." #endif /* NETDEV_IPV4 && NETDEV_IPV6 */ } } @@ -1275,10 +1277,11 @@ int at_getaddrinfo(const char *nodename, const char *servname, /* set up sockaddr */ #if NETDEV_IPV4 && NETDEV_IPV6 sa4->sin_addr.s_addr = addr.u_addr.ip4.addr; + sa4->type = IPADDR_TYPE_V4; #elif NETDEV_IPV4 sa4->sin_addr.s_addr = addr.addr; #elif NETDEV_IPV6 - LOG_E("not support IPV6."); +#error "not support IPV6." #endif /* NETDEV_IPV4 && NETDEV_IPV6 */ sa4->sin_family = AF_INET; sa4->sin_len = sizeof(struct sockaddr_in); diff --git a/components/net/lwip-2.0.2/src/core/netif.c b/components/net/lwip-2.0.2/src/core/netif.c index 01e83676da..ee57bb9a9d 100644 --- a/components/net/lwip-2.0.2/src/core/netif.c +++ b/components/net/lwip-2.0.2/src/core/netif.c @@ -544,7 +544,7 @@ netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr) #ifdef RT_USING_NETDEV /* rt-thread sal network interface device set IP address operations */ - netdev_low_level_set_ipaddr(netdev_get_by_name(netif->name), (ip_addr_t *)ipaddr); + netdev_low_level_set_ipaddr(netdev_get_by_name(netif->name), &netif->ip_addr); #endif /* RT_USING_NETDEV */ } @@ -579,7 +579,7 @@ netif_set_gw(struct netif *netif, const ip4_addr_t *gw) #ifdef RT_USING_NETDEV /* rt_thread network interface device set gateway address */ - netdev_low_level_set_gw(netdev_get_by_name(netif->name), (ip_addr_t *)gw); + netdev_low_level_set_gw(netdev_get_by_name(netif->name), &netif->gw); #endif /* RT_USING_NETDEV */ } @@ -610,7 +610,7 @@ netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask) #ifdef RT_USING_NETDEV /* rt-thread network interface device set netmask address */ - netdev_low_level_set_netmask(netdev_get_by_name(netif->name), (ip_addr_t *)netmask); + netdev_low_level_set_netmask(netdev_get_by_name(netif->name), &netif->netmask); #endif /* RT_USING_NETDEV */ } #endif /* LWIP_IPV4 */ @@ -1241,6 +1241,11 @@ netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit) } } +#ifdef RT_USING_NETDEV + /* rt-thread network interface device set ipv6 address */ + ip_addr_copy(netdev_get_by_name(netif->name)->ip6_addr[0], netif->ip6_addr[0]); +#endif /* RT_USING_NETDEV */ + /* Set address state. */ #if LWIP_IPV6_DUP_DETECT_ATTEMPTS /* Will perform duplicate address detection (DAD). */ @@ -1279,6 +1284,10 @@ netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chos for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) { ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr); +#ifdef RT_USING_NETDEV + /* rt-thread network interface device set ipv6 address */ + ip_addr_copy(netdev_get_by_name(netif->name)->ip6_addr[i], netif->ip6_addr[i]); +#endif /* RT_USING_NETDEV */ netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE); if (chosen_idx != NULL) { *chosen_idx = i; diff --git a/components/net/lwip-2.0.2/src/netif/ethernetif.c b/components/net/lwip-2.0.2/src/netif/ethernetif.c index a5a1f94c0b..51e1ba511d 100644 --- a/components/net/lwip-2.0.2/src/netif/ethernetif.c +++ b/components/net/lwip-2.0.2/src/netif/ethernetif.c @@ -128,23 +128,23 @@ static int lwip_netdev_set_addr_info(struct netdev *netif, ip_addr_t *ip_addr, i { if (ip_addr && netmask && gw) { - netif_set_addr((struct netif *)netif->user_data, ip_addr, netmask, gw); + netif_set_addr((struct netif *)netif->user_data, ip_2_ip4(ip_addr), ip_2_ip4(netmask), ip_2_ip4(gw)); } else { if (ip_addr) { - netif_set_ipaddr((struct netif *)netif->user_data, ip_addr); + netif_set_ipaddr((struct netif *)netif->user_data, ip_2_ip4(ip_addr)); } if (netmask) { - netif_set_netmask((struct netif *)netif->user_data, netmask); + netif_set_netmask((struct netif *)netif->user_data, ip_2_ip4(netmask)); } if (gw) { - netif_set_gw((struct netif *)netif->user_data, gw); + netif_set_gw((struct netif *)netif->user_data, ip_2_ip4(gw)); } } diff --git a/components/net/lwip-2.1.0/src/core/netif.c b/components/net/lwip-2.1.0/src/core/netif.c index 5b31c627e9..b2b4adf85b 100644 --- a/components/net/lwip-2.1.0/src/core/netif.c +++ b/components/net/lwip-2.1.0/src/core/netif.c @@ -491,7 +491,7 @@ netif_do_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr, ip_addr_t *ol #ifdef RT_USING_NETDEV /* rt-thread sal network interface device set IP address operations */ - netdev_low_level_set_ipaddr(netdev_get_by_name(netif->name), (ip_addr_t *)ipaddr); + netdev_low_level_set_ipaddr(netdev_get_by_name(netif->name), &netif->ip_addr); #endif /* RT_USING_NETDEV */ return 1; /* address changed */ @@ -557,7 +557,7 @@ netif_do_set_netmask(struct netif *netif, const ip4_addr_t *netmask, ip_addr_t * #ifdef RT_USING_NETDEV /* rt-thread network interface device set netmask address */ - netdev_low_level_set_netmask(netdev_get_by_name(netif->name), (ip_addr_t *)netmask); + netdev_low_level_set_netmask(netdev_get_by_name(netif->name), &netif->netmask); #endif /* RT_USING_NETDEV */ return 1; /* netmask changed */ @@ -625,7 +625,7 @@ netif_do_set_gw(struct netif *netif, const ip4_addr_t *gw, ip_addr_t *old_gw) #ifdef RT_USING_NETDEV /* rt_thread network interface device set gateway address */ - netdev_low_level_set_gw(netdev_get_by_name(netif->name), (ip_addr_t *)gw); + netdev_low_level_set_gw(netdev_get_by_name(netif->name), &netif->gw); #endif /* RT_USING_NETDEV */ return 1; /* gateway changed */ @@ -1586,6 +1586,11 @@ netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit) * zone field, so this should not create any compatibility problems. */ ip6_addr_assign_zone(ip_2_ip6(&netif->ip6_addr[0]), IP6_UNICAST, netif); +#ifdef RT_USING_NETDEV + /* rt-thread network interface device set ipv6 address */ + ip_addr_copy(netdev_get_by_name(netif->name)->ip6_addr[0], netif->ip6_addr[0]); +#endif /* RT_USING_NETDEV */ + /* Set address state. */ #if LWIP_IPV6_DUP_DETECT_ATTEMPTS /* Will perform duplicate address detection (DAD). */ @@ -1629,6 +1634,10 @@ netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chos for (i = ip6_addr_islinklocal(ip6addr) ? 0 : 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) { ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr); +#ifdef RT_USING_NETDEV + /* rt-thread network interface device set ipv6 address */ + ip_addr_copy(netdev_get_by_name(netif->name)->ip6_addr[i], netif->ip6_addr[i]); +#endif /* RT_USING_NETDEV */ ip6_addr_assign_zone(ip_2_ip6(&netif->ip6_addr[i]), IP6_UNICAST, netif); netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE); if (chosen_idx != NULL) { diff --git a/components/net/lwip-2.1.0/src/netif/ethernetif.c b/components/net/lwip-2.1.0/src/netif/ethernetif.c index 5ea03a9ae8..0c9e5dec5f 100755 --- a/components/net/lwip-2.1.0/src/netif/ethernetif.c +++ b/components/net/lwip-2.1.0/src/netif/ethernetif.c @@ -129,23 +129,23 @@ static int lwip_netdev_set_addr_info(struct netdev *netif, ip_addr_t *ip_addr, i { if (ip_addr && netmask && gw) { - netif_set_addr((struct netif *)netif->user_data, ip_addr, netmask, gw); + netif_set_addr((struct netif *)netif->user_data, ip_2_ip4(ip_addr), ip_2_ip4(netmask), ip_2_ip4(gw)); } else { if (ip_addr) { - netif_set_ipaddr((struct netif *)netif->user_data, ip_addr); + netif_set_ipaddr((struct netif *)netif->user_data, ip_2_ip4(ip_addr)); } if (netmask) { - netif_set_netmask((struct netif *)netif->user_data, netmask); + netif_set_netmask((struct netif *)netif->user_data, ip_2_ip4(netmask)); } if (gw) { - netif_set_gw((struct netif *)netif->user_data, gw); + netif_set_gw((struct netif *)netif->user_data, ip_2_ip4(gw)); } } diff --git a/components/net/lwip-2.1.0/src/netif/lowpan6.c b/components/net/lwip-2.1.0/src/netif/lowpan6.c index 5769522d5e..6397b0cb5d 100644 --- a/components/net/lwip-2.1.0/src/netif/lowpan6.c +++ b/components/net/lwip-2.1.0/src/netif/lowpan6.c @@ -50,7 +50,7 @@ #include "netif/lowpan6.h" -#if LWIP_IPV6 +#if LWIP_IPV6 && LWIP_6LOWPAN #include "lwip/ip.h" #include "lwip/pbuf.h" diff --git a/components/net/netdev/include/netdev.h b/components/net/netdev/include/netdev.h index 0be2a2bda3..71a61be3c0 100644 --- a/components/net/netdev/include/netdev.h +++ b/components/net/netdev/include/netdev.h @@ -27,6 +27,13 @@ extern "C" { #define NETDEV_DNS_SERVERS_NUM 2U #endif +#if NETDEV_IPV6 +/* the maximum of dns server number supported */ +#ifndef NETDEV_IPV6_NUM_ADDRESSES +#define NETDEV_IPV6_NUM_ADDRESSES 3U +#endif +#endif /* NETDEV_IPV6 */ + /* whether the network interface device is 'up' (set by the network interface driver or application) */ #define NETDEV_FLAG_UP 0x01U /* if set, the network interface device has broadcast capability, only supported in the 'lwIP' stack */ @@ -78,6 +85,9 @@ struct netdev ip_addr_t ip_addr; /* IP address */ ip_addr_t netmask; /* subnet mask */ ip_addr_t gw; /* gateway */ +#if NETDEV_IPV6 + ip_addr_t ip6_addr[NETDEV_IPV6_NUM_ADDRESSES]; /* array of IPv6 addresses */ +#endif /* NETDEV_IPV6 */ ip_addr_t dns_servers[NETDEV_DNS_SERVERS_NUM]; /* DNS server */ uint8_t hwaddr_len; /* hardware address length */ uint8_t hwaddr[NETDEV_HWADDR_MAX_LEN]; /* hardware address */ @@ -163,6 +173,7 @@ int netdev_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_ /* Set network interface device callback, it can be called when the status or address changed */ void netdev_set_status_callback(struct netdev *netdev, netdev_callback_fn status_callback); +void netdev_set_addr_callback(struct netdev *netdev, netdev_callback_fn addr_callback); /* Set network interface device status and address, this function can only be called in the network interface device driver */ void netdev_low_level_set_ipaddr(struct netdev *netdev, const ip_addr_t *ipaddr); diff --git a/components/net/netdev/include/netdev_ipaddr.h b/components/net/netdev/include/netdev_ipaddr.h index c2e13cd118..65970ec5b7 100644 --- a/components/net/netdev/include/netdev_ipaddr.h +++ b/components/net/netdev/include/netdev_ipaddr.h @@ -12,21 +12,53 @@ #define __NETDEV_IPADDR_H__ #include +#include #ifdef __cplusplus extern "C" { #endif -/* Only supports the IPV4 protocol */ -#ifndef NETDEV_IPV4 -#define NETDEV_IPV4 1 -#endif +/* + * Definitions of bits in internet address integers. + * On subnets, the decomposition of addresses to host and net parts + * is done according to subnet mask, not the masks here. + */ +#define IN_CLASSA(i) (((long)(i) & 0x80000000) == 0) +#define IN_CLASSA_NET 0xff000000 +#define IN_CLASSA_NSHIFT 24 +#define IN_CLASSA_HOST 0x00ffffff +#define IN_CLASSA_MAX 128 -#ifndef NETDEV_IPV6 -#define NETDEV_IPV6 0 -#endif +#define IN_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000) +#define IN_CLASSB_NET 0xffff0000 +#define IN_CLASSB_NSHIFT 16 +#define IN_CLASSB_HOST 0x0000ffff +#define IN_CLASSB_MAX 65536 -#ifdef NETDEV_IPV4 +#define IN_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000) +#define IN_CLASSC_NET 0xffffff00 +#define IN_CLASSC_NSHIFT 8 +#define IN_CLASSC_HOST 0x000000ff + +#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000) +#define IN_MULTICAST(i) IN_CLASSD(i) + +#define IN_EXPERIMENTAL(i) (((long)(i) & 0xe0000000) == 0xe0000000) +#define IN_BADCLASS(i) (((long)(i) & 0xf0000000) == 0xf0000000) + +#define IN_LOOPBACKNET 127 /* official! */ + +/* IP address types for use in ip_addr_t.type member */ +enum netdev_ip_addr_type { + /** IPv4 */ + IPADDR_TYPE_V4 = 0U, + /** IPv6 */ + IPADDR_TYPE_V6 = 6U, + /** IPv4+IPv6 ("dual-stack") */ + IPADDR_TYPE_ANY = 46U +}; + +#if NETDEV_IPV4 /** IPv4 only: set the IP address given as an u32_t */ #define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) /** IPv4 only: get the IP address as an u32_t */ @@ -68,53 +100,6 @@ typedef struct ip4_addr uint32_t addr; } ip4_addr_t; -typedef ip4_addr_t ip_addr_t; -#endif /* NETIF_IPV4 */ - -#if NETDEV_IPV6 -struct in6_addr -{ - union - { - uint32_t u32_addr[4]; - uint8_t u8_addr[16]; - } un; -#define s6_addr un.u8_addr -}; - -typedef struct ip6_addr -{ - uint32_t addr[4]; -} ip6_addr_t; - -typedef ip6_addr ip_addr_t -#endif /* NETIF_IPV6 */ - -#if NETDEV_IPV4 && NETDEV_IPV6 -/* IP address types for use in ip_addr_t.type member */ -enum netdev_ip_addr_type -{ - /** IPv4 */ - IPADDR_TYPE_V4 = 0U, - /** IPv6 */ - IPADDR_TYPE_V6 = 6U, - /** IPv4+IPv6 ("dual-stack") */ - IPADDR_TYPE_ANY = 46U -}; - -/* A union struct for both IP version's addresses */ -typedef struct _ip_addr -{ - union - { - ip6_addr_t ip6; - ip4_addr_t ip4; - } u_addr; - /** @ref netdev_ip_addr_type */ - uint8_t type; -} ip_addr_t; -#endif /* NETIF_IPV4 && NETIF_IPV6 */ - /** 255.255.255.255 */ #define IPADDR_NONE ((uint32_t)0xffffffffUL) /** 127.0.0.1 */ @@ -135,32 +120,194 @@ typedef struct _ip_addr #define IPADDR_BROADCAST_STRING "255.255.255.255" -#ifdef NETDEV_IPV4 - /** Copy IP address - faster than ip4_addr_set: no NULL check */ #define ip4_addr_copy(dest, src) ((dest).addr = (src).addr) #define ip4_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) +/** Safely copy one IP address to another (src may be NULL) */ +#define ip4_addr_set(dest, src) ((dest)->addr = ((src) == NULL ? 0 : (src)->addr)) /** Set complete address to zero */ #define ip4_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) +/** Set address to IPADDR_ANY (no need for htonl()) */ +#define ip4_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) #define ip4_addr_isany_val(ipaddr) ((ipaddr).addr == IPADDR_ANY) #define ip4_addr_isany(ipaddr) ((ipaddr) == NULL || ip4_addr_isany_val(*(ipaddr))) -#define ip_addr_copy(dest, src) ip4_addr_copy(dest, src) -#define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2) -#define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr) -#define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr) - in_addr_t netdev_ipaddr_addr(const char *cp); int netdev_ip4addr_aton(const char *cp, ip4_addr_t *addr); char *netdev_ip4addr_ntoa(const ip4_addr_t *addr); char *netdev_ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen); +#endif /* NETIF_IPV4 */ +#if NETDEV_IPV6 +struct in6_addr +{ + union + { + uint32_t u32_addr[4]; + uint8_t u8_addr[16]; + } un; +#define s6_addr un.u8_addr +}; + +typedef struct ip6_addr +{ + uint32_t addr[4]; +#ifdef NETDEV_IPV6_SCOPES + uint8_t zone; +#endif /* NETDEV_IPV6_SCOPES */ +} ip6_addr_t; + +/** This macro can be used to initialize a variable of type struct in6_addr + to the IPv6 wildcard address. */ +#define IN6ADDR_ANY_INIT {{{0,0,0,0}}} +/** This macro can be used to initialize a variable of type struct in6_addr + to the IPv6 loopback address. */ +#define IN6ADDR_LOOPBACK_INIT {{{0,0,0,PP_HTONL(1)}}} + +/** This variable is initialized by the system to contain the wildcard IPv6 address. + */ +extern const struct in6_addr in6addr_any; + +#define ip6_addr_cmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ + ((addr1)->addr[1] == (addr2)->addr[1]) && \ + ((addr1)->addr[2] == (addr2)->addr[2]) && \ + ((addr1)->addr[3] == (addr2)->addr[3])) +/** Copy IPv6 address - faster than ip6_addr_set: no NULL check */ +#define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \ + (dest).addr[1] = (src).addr[1]; \ + (dest).addr[2] = (src).addr[2]; \ + (dest).addr[3] = (src).addr[3];}while(0) +/** Safely copy one IPv6 address to another (src may be NULL) */ +#define ip6_addr_set(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : (src)->addr[0]; \ + (dest)->addr[1] = (src) == NULL ? 0 : (src)->addr[1]; \ + (dest)->addr[2] = (src) == NULL ? 0 : (src)->addr[2]; \ + (dest)->addr[3] = (src) == NULL ? 0 : (src)->addr[3];}while(0) +/** Set complete address to zero */ +#define ip6_addr_set_zero(ip6addr) do{(ip6addr)->addr[0] = 0; \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = 0;}while(0) +/** Set address to ipv6 'any' (no need for lwip_htonl()) */ +#define ip6_addr_set_any(ip6addr) ip6_addr_set_zero(ip6addr) +#define ip6_addr_isany_val(ip6addr) (((ip6addr).addr[0] == 0) && \ + ((ip6addr).addr[1] == 0) && \ + ((ip6addr).addr[2] == 0) && \ + ((ip6addr).addr[3] == 0)) +#define ip6_addr_isany(ip6addr) (((ip6addr) == NULL) || ip6_addr_isany_val(*(ip6addr))) + +int netdev_ip6addr_aton(const char *cp, ip6_addr_t *addr); +char *netdev_ip6addr_ntoa(const ip6_addr_t *addr); +char *netdev_ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen); +#endif /* NETIF_IPV6 */ + +#if NETDEV_IPV4 && NETDEV_IPV6 +/* A union struct for both IP version's addresses */ +typedef struct _ip_addr +{ + union + { + ip6_addr_t ip6; + ip4_addr_t ip4; + } u_addr; + /** @ref netdev_ip_addr_type */ + uint8_t type; +} ip_addr_t; + +#define IP_SET_TYPE_VAL(ipaddr, iptype) do { (ipaddr).type = (iptype); }while(0) +#define IP_SET_TYPE(ipaddr, iptype) do { if((ipaddr) != NULL) { IP_SET_TYPE_VAL(*(ipaddr), iptype); }}while(0) +#define IP_GET_TYPE(ipaddr) ((ipaddr)->type) + +#define IP_IS_V4_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V4) +#define IP_IS_V6_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V6) +#define IP_IS_V4(ipaddr) (((ipaddr) == NULL) || IP_IS_V4_VAL(*(ipaddr))) +#define IP_IS_V6(ipaddr) (((ipaddr) != NULL) && IP_IS_V6_VAL(*(ipaddr))) + +/** Convert generic ip address to specific protocol version */ +#define ip_2_ip6(ipaddr) (&((ipaddr)->u_addr.ip6)) +/** Convert generic ip address to specific protocol version */ +#define ip_2_ip4(ipaddr) (&((ipaddr)->u_addr.ip4)) + +#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \ + ip6_addr_copy(*ip_2_ip6(&(dest)), *ip_2_ip6(&(src))); }else{ \ + ip4_addr_copy(*ip_2_ip4(&(dest)), *ip_2_ip4(&(src))); }}while(0) +#define ip_addr_cmp(addr1, addr2) ((IP_GET_TYPE(addr1) != IP_GET_TYPE(addr2)) ? 0 : (IP_IS_V6_VAL(*(addr1)) ? \ + ip6_addr_cmp(ip_2_ip6(addr1), ip_2_ip6(addr2)) : \ + ip4_addr_cmp(ip_2_ip4(addr1), ip_2_ip4(addr2)))) +#define ip_addr_set(dest, src) do{ IP_SET_TYPE(dest, IP_GET_TYPE(src)); if(IP_IS_V6(src)){ \ + ip6_addr_set(ip_2_ip6(dest), ip_2_ip6(src)); }else{ \ + ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); }}while(0) +#define ip_addr_set_zero(ipaddr) do{ ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); }while(0) +#define ip_addr_set_any(is_ipv6, ipaddr) do{ if(is_ipv6){ \ + ip6_addr_set_any(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \ + ip4_addr_set_any(ip_2_ip4(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) + +#define ip_addr_isany_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ + ip6_addr_isany_val(*ip_2_ip6(&(ipaddr))) : \ + ip4_addr_isany_val(*ip_2_ip4(&(ipaddr)))) +#define ip_addr_isany(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_isany(ip_2_ip6(ipaddr)) : \ + ip4_addr_isany(ip_2_ip4(ipaddr))) + +/* directly map this to the lwip internal functions */ +#define inet_addr(cp) netdev_ipaddr_addr(cp) +#define inet_aton(cp, addr) ((IP_IS_V6_VAL(*addr)) ? \ + netdev_ip6addr_aton(cp, ip_2_ip6(addr)) : \ + netdev_ip4addr_aton(cp, ip_2_ip4(addr))) +#define inet_ntoa(addr) ((IP_IS_V6_VAL(addr)) ? \ + netdev_ip6addr_ntoa(ip_2_ip6(&addr)) : \ + netdev_ip4addr_ntoa(ip_2_ip4(&addr))) +#define inet_ntoa_r(addr, buf, buflen) ((IP_IS_V6_VAL(addr)) ? \ + netdev_ip6addr_ntoa_r(ip_2_ip6(&addr), buf, buflen) : \ + netdev_ip4addr_ntoa_r(ip_2_ip4(&addr), buf, buflen)) +#elif NETDEV_IPV4 /* NETDEV_IPV4 */ + +typedef ip4_addr_t ip_addr_t; + +#define IP_SET_TYPE_VAL(ipaddr, iptype) +#define IP_SET_TYPE(ipaddr, iptype) +#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V4 + +#define ip_addr_copy(dest, src) ip4_addr_copy(dest, src) +#define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2) +#define ip_addr_set(dest, src) ip4_addr_set(dest, src) +#define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr) +#define ip_addr_set_any(is_ipv6, ipaddr) ip4_addr_set_any(ipaddr) +#define ip_addr_isany_val(ipaddr) ip4_addr_isany_val(ipaddr) +#define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr) + +/* directly map this to the lwip internal functions */ #define inet_addr(cp) netdev_ipaddr_addr(cp) #define inet_aton(cp, addr) netdev_ip4addr_aton(cp,(ip4_addr_t*)addr) #define inet_ntoa(addr) netdev_ip4addr_ntoa((const ip4_addr_t*)&(addr)) #define inet_ntoa_r(addr, buf, buflen) netdev_ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) +#else /* NETDEV_IPV6 */ -#endif /* NETDEV_IPV4 */ +typedef ip6_addr_t ip_addr_t; + +#define IP_SET_TYPE_VAL(ipaddr, iptype) +#define IP_SET_TYPE(ipaddr, iptype) +#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V6 + +#define ip_addr_copy(dest, src) ip6_addr_copy(dest, src) +#define ip_addr_cmp(addr1, addr2) ip6_addr_cmp(addr1, addr2) +#define ip_addr_set(dest, src) ip6_addr_set(dest, src) +#define ip_addr_set_zero(ipaddr) ip6_addr_set_zero(ipaddr) +#define ip_addr_set_any(is_ipv6, ipaddr) ip6_addr_set_any(ipaddr) +#define ip_addr_isany_val(ipaddr) ip6_addr_isany_val(ipaddr) +#define ip_addr_isany(ipaddr) ip6_addr_isany(ipaddr) + +/* directly map this to the lwip internal functions */ +#define inet_aton(cp, addr) netdev_ip6addr_aton(cp, (ip6_addr_t*)addr) +#define inet_ntoa(addr) netdev_ip6addr_ntoa((const ip6_addr_t*)&(addr)) +#define inet_ntoa_r(addr, buf, buflen) netdev_ip6addr_ntoa_r((const ip6_addr_t*)&(addr), buf, buflen) +#endif /* NTDEV_IPV4 && NTDEV_IPV6 */ + + +const char *netdev_inet_ntop(int af, const void *src, char *dst, int32_t size); +int netdev_inet_pton(int af, const char *src, void *dst); + +#define inet_ntop(af, src, dst, size) netdev_inet_ntop(af, src, dst, size) +#define inet_pton(af, src, dst) netdev_inet_pton(af, src, dst) #ifdef __cplusplus } diff --git a/components/net/netdev/src/netdev.c b/components/net/netdev/src/netdev.c index 5f49a46f17..eb2835364a 100644 --- a/components/net/netdev/src/netdev.c +++ b/components/net/netdev/src/netdev.c @@ -58,9 +58,21 @@ int netdev_register(struct netdev *netdev, const char *name, void *user_data) ip_addr_set_zero(&(netdev->ip_addr)); ip_addr_set_zero(&(netdev->netmask)); ip_addr_set_zero(&(netdev->gw)); + + IP_SET_TYPE_VAL(netdev->ip_addr, IPADDR_TYPE_V4); + IP_SET_TYPE_VAL(netdev->netmask, IPADDR_TYPE_V4); + IP_SET_TYPE_VAL(netdev->gw, IPADDR_TYPE_V4); +#if NETDEV_IPV6 + for (index = 0; index < NETDEV_IPV6_NUM_ADDRESSES; index++) + { + ip_addr_set_zero(&(netdev->ip6_addr[index])); + IP_SET_TYPE_VAL(netdev->ip_addr, IPADDR_TYPE_V6); + } +#endif /* NETDEV_IPV6 */ for (index = 0; index < NETDEV_DNS_SERVERS_NUM; index++) { ip_addr_set_zero(&(netdev->dns_servers[index])); + IP_SET_TYPE_VAL(netdev->ip_addr, IPADDR_TYPE_V4); } netdev->status_callback = RT_NULL; netdev->addr_callback = RT_NULL; @@ -839,7 +851,7 @@ static void netdev_list_if(void) rt_kprintf("network interface device: %s%s\n", netdev->name, - (netdev == netdev_default)?" (Default)":""); + (netdev == netdev_default) ? " (Default)" : ""); rt_kprintf("MTU: %d\n", netdev->mtu); /* 6 - MAC address, 8 - IEMI */ @@ -881,6 +893,28 @@ static void netdev_list_if(void) rt_kprintf("gw address: %s\n", inet_ntoa(netdev->gw)); rt_kprintf("net mask : %s\n", inet_ntoa(netdev->netmask)); +#if NETDEV_IPV6 + { + ip_addr_t *addr; + int i; + + addr = &netdev->ip6_addr[0]; + + if (!ip_addr_isany(addr)) + { + rt_kprintf("ipv6 link-local: %s %s\n", inet_ntoa(*addr), + !ip_addr_isany(addr) ? "VALID" : "INVALID"); + + for (i = 1; i < NETDEV_IPV6_NUM_ADDRESSES; i++) + { + addr = &netdev->ip6_addr[i]; + rt_kprintf("ipv6[%d] address: %s %s\n", i, inet_ntoa(*addr), + !ip_addr_isany(addr) ? "VALID" : "INVALID"); + } + } + } +#endif /* NETDEV_IPV6 */ + for (index = 0; index < NETDEV_DNS_SERVERS_NUM; index++) { rt_kprintf("dns server #%d: %s\n", index, inet_ntoa(netdev->dns_servers[index])); diff --git a/components/net/netdev/src/netdev_ipaddr.c b/components/net/netdev/src/netdev_ipaddr.c index 988bd50eb7..8d83937da9 100644 --- a/components/net/netdev/src/netdev_ipaddr.c +++ b/components/net/netdev/src/netdev_ipaddr.c @@ -19,8 +19,10 @@ #define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) #define islower(c) in_range(c, 'a', 'z') #define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') +#define xchar(i) ((i) < 10 ? '0' + (i) : 'A' + (i) - 10) #endif +#if NETDEV_IPV4 /** * Check whether "cp" is a valid ascii representation @@ -255,3 +257,358 @@ in_addr_t netdev_ipaddr_addr(const char *cp) } return (IPADDR_NONE); } + +#endif /* NETDEV_IPV4 */ + + +#if NETDEV_IPV6 + +RT_WEAK const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; + +/** + * Check whether "cp" is a valid ascii representation + * of an IPv6 address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * + * @param cp IPv6 address in ascii representation (e.g. "FF01::1") + * @param addr pointer to which to save the ip address in network order + * @return 1 if cp could be converted to addr, 0 on failure + */ +int +netdev_ip6addr_aton(const char *cp, ip6_addr_t *addr) +{ + uint32_t addr_index, zero_blocks, current_block_index, current_block_value; + const char *s; + + /* Count the number of colons, to count the number of blocks in a "::" sequence + zero_blocks may be 1 even if there are no :: sequences */ + zero_blocks = 8; + for (s = cp; *s != 0; s++) + { + if (*s == ':') + { + zero_blocks--; + } + else if (!isxdigit(*s)) + { + break; + } + } + + /* parse each block */ + addr_index = 0; + current_block_index = 0; + current_block_value = 0; + for (s = cp; *s != 0; s++) + { + if (*s == ':') + { + if (addr) + { + if (current_block_index & 0x1) + { + addr->addr[addr_index++] |= current_block_value; + } + else + { + addr->addr[addr_index] = current_block_value << 16; + } + } + current_block_index++; + current_block_value = 0; + if (current_block_index > 7) + { + /* address too long! */ + return 0; + } + if (s[1] == ':') + { + if (s[2] == ':') + { + /* invalid format: three successive colons */ + return 0; + } + s++; + /* "::" found, set zeros */ + while (zero_blocks > 0) + { + zero_blocks--; + if (current_block_index & 0x1) + { + addr_index++; + } + else + { + if (addr) + { + addr->addr[addr_index] = 0; + } + } + current_block_index++; + if (current_block_index > 7) + { + /* address too long! */ + return 0; + } + } + } + } + else if (isxdigit(*s)) + { + /* add current digit */ + current_block_value = (current_block_value << 4) + + (isdigit(*s) ? (uint32_t)(*s - '0') : (uint32_t)(10 + (islower(*s) ? *s - 'a' : *s - 'A'))); + } + else + { + /* unexpected digit, space? CRLF? */ + break; + } + } + + if (addr) + { + if (current_block_index & 0x1) + { + addr->addr[addr_index++] |= current_block_value; + } + else + { + addr->addr[addr_index] = current_block_value << 16; + } + } + + /* convert to network byte order. */ + if (addr) + { + for (addr_index = 0; addr_index < 4; addr_index++) + { + addr->addr[addr_index] = htonl(addr->addr[addr_index]); + } + } + + if (current_block_index != 7) + { + return 0; + } + + return 1; +} + +/** + * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. + * + * @param addr ip6 address in network order to convert + * @param buf target buffer where the string is stored + * @param buflen length of buf + * @return either pointer to buf which now holds the ASCII + * representation of addr or NULL if buf was too small + */ +char * +netdev_ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen) +{ + uint32_t current_block_index, current_block_value, next_block_value; + int32_t i; + uint8_t zero_flag, empty_block_flag; + + i = 0; + empty_block_flag = 0; /* used to indicate a zero chain for "::' */ + + for (current_block_index = 0; current_block_index < 8; current_block_index++) + { + /* get the current 16-bit block */ + current_block_value = htonl(addr->addr[current_block_index >> 1]); + if ((current_block_index & 0x1) == 0) + { + current_block_value = current_block_value >> 16; + } + current_block_value &= 0xffff; + + /* Check for empty block. */ + if (current_block_value == 0) + { + if (current_block_index == 7 && empty_block_flag == 1) + { + /* special case, we must render a ':' for the last block. */ + buf[i++] = ':'; + if (i >= buflen) + { + return NULL; + } + break; + } + if (empty_block_flag == 0) + { + /* generate empty block "::", but only if more than one contiguous zero block, + * according to current formatting suggestions RFC 5952. */ + next_block_value = htonl(addr->addr[(current_block_index + 1) >> 1]); + if ((current_block_index & 0x1) == 0x01) + { + next_block_value = next_block_value >> 16; + } + next_block_value &= 0xffff; + if (next_block_value == 0) + { + empty_block_flag = 1; + buf[i++] = ':'; + if (i >= buflen) + { + return NULL; + } + continue; /* move on to next block. */ + } + } + else if (empty_block_flag == 1) + { + /* move on to next block. */ + continue; + } + } + else if (empty_block_flag == 1) + { + /* Set this flag value so we don't produce multiple empty blocks. */ + empty_block_flag = 2; + } + + if (current_block_index > 0) + { + buf[i++] = ':'; + if (i >= buflen) + { + return NULL; + } + } + + if ((current_block_value & 0xf000) == 0) + { + zero_flag = 1; + } + else + { + buf[i++] = xchar(((current_block_value & 0xf000) >> 12)); + zero_flag = 0; + if (i >= buflen) + { + return NULL; + } + } + + if (((current_block_value & 0xf00) == 0) && (zero_flag)) + { + /* do nothing */ + } + else + { + buf[i++] = xchar(((current_block_value & 0xf00) >> 8)); + zero_flag = 0; + if (i >= buflen) + { + return NULL; + } + } + + if (((current_block_value & 0xf0) == 0) && (zero_flag)) + { + /* do nothing */ + } + else + { + buf[i++] = xchar(((current_block_value & 0xf0) >> 4)); + zero_flag = 0; + if (i >= buflen) + { + return NULL; + } + } + + buf[i++] = xchar((current_block_value & 0xf)); + if (i >= buflen) + { + return NULL; + } + } + + buf[i] = 0; + + return buf; +} + +/** + * Convert numeric IPv6 address into ASCII representation. + * returns ptr to static buffer; not reentrant! + * + * @param addr ip6 address in network order to convert + * @return pointer to a global static (!) buffer that holds the ASCII + * representation of addr + */ +char * +netdev_ip6addr_ntoa(const ip6_addr_t *addr) +{ + static char str[40]; + return netdev_ip6addr_ntoa_r(addr, str, 40); +} + +#endif /* NETDEV_IPV6 */ + +const char * +netdev_inet_ntop(int af, const void *src, char *dst, int32_t size) +{ +#define AF_INET 2 +#define AF_INET6 10 + + const char *ret = NULL; + int size_int = (int)size; + if (size_int < 0) + { + return NULL; + } + switch (af) + { +#if NTEDEV_IPV4 + case AF_INET: + return netdev_ip4addr_ntoa_r((const ip4_addr_t *)src, dst, size_int); +#endif +#if NETDEV_IPV6 + case AF_INET6: + return netdev_ip6addr_ntoa_r((const ip6_addr_t *)src, dst, size_int); +#endif + default: + break; + } + return ret; +} + +int +netdev_inet_pton(int af, const char *src, void *dst) +{ +#define AF_INET 2 +#define AF_INET6 10 + + int err; + switch (af) + { +#if NETDEV_IPV4 + case AF_INET: + err = netdev_ip4addr_aton(src, (ip4_addr_t *)dst); + break; +#endif +#if NETDEV_IPV6 + case AF_INET6: + { + /* convert into temporary variable since ip6_addr_t might be larger + than in6_addr when scopes are enabled */ + ip6_addr_t addr; + err = netdev_ip6addr_aton(src, &addr); + if (err) + { + rt_memcpy(dst, &addr.addr, sizeof(addr.addr)); + } + break; + } +#endif + default: + err = -1; + break; + } + return err; +} diff --git a/components/net/sal_socket/impl/af_inet_lwip.c b/components/net/sal_socket/impl/af_inet_lwip.c index 95e7633635..e53aa845cc 100644 --- a/components/net/sal_socket/impl/af_inet_lwip.c +++ b/components/net/sal_socket/impl/af_inet_lwip.c @@ -25,6 +25,12 @@ #include +#if (LWIP_VERSION < 0x2000000) && NETDEV_IPV6 +#error "The lwIP version is not support IPV6, please disable netdev IPV6 configuration " +#elif (LWIP_VERSION > 0x2000000) && (NETDEV_IPV6 != LWIP_IPV6) +#error "IPV6 configuration error, Please check and synchronize netdev and lwip IPV6 configuration." +#endif + #if LWIP_VERSION < 0x2000000 #define SELWAIT_T int #else @@ -308,7 +314,11 @@ static const struct sal_netdb_ops lwip_netdb_ops = static const struct sal_proto_family lwip_inet_family = { AF_INET, +#if LWIP_VERSION > 0x2000000 + AF_INET6, +#else AF_INET, +#endif &lwip_socket_ops, &lwip_netdb_ops, }; diff --git a/components/net/sal_socket/include/sal_socket.h b/components/net/sal_socket/include/sal_socket.h index d72f1e4c3c..b620bbe23c 100644 --- a/components/net/sal_socket/include/sal_socket.h +++ b/components/net/sal_socket/include/sal_socket.h @@ -157,6 +157,7 @@ struct sockaddr char sa_data[14]; }; +#if NETDEV_IPV4 /* members are in network byte order */ struct sockaddr_in { @@ -167,6 +168,19 @@ struct sockaddr_in #define SIN_ZERO_LEN 8 char sin_zero[SIN_ZERO_LEN]; }; +#endif /* NETDEV_IPV4 */ + +#if NETDEV_IPV6 +struct sockaddr_in6 +{ + uint8_t sin6_len; /* length of this structure */ + sa_family_t sin6_family; /* AF_INET6 */ + in_port_t sin6_port; /* Transport layer port # */ + uint32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ + uint32_t sin6_scope_id; /* Set of interfaces for scope */ +}; +#endif /* NETDEV_IPV6 */ struct sockaddr_storage { @@ -174,9 +188,9 @@ struct sockaddr_storage sa_family_t ss_family; char s2_data1[2]; uint32_t s2_data2[3]; -#if SAL_IPV6 - u32_t s2_data3[3]; -#endif /* SAL_IPV6 */ +#if NETDEV_IPV6 + uint32_t s2_data3[3]; +#endif /* NETDEV_IPV6 */ }; int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen); diff --git a/components/net/sal_socket/src/sal_socket.c b/components/net/sal_socket/src/sal_socket.c index e09b2b7119..be7c1984a1 100644 --- a/components/net/sal_socket/src/sal_socket.c +++ b/components/net/sal_socket/src/sal_socket.c @@ -549,12 +549,13 @@ static void sal_sockaddr_to_ipaddr(const struct sockaddr *name, ip_addr_t *local const struct sockaddr_in *svr_addr = (const struct sockaddr_in *) name; #if NETDEV_IPV4 && NETDEV_IPV6 - (*local_ipaddr).u_addr.ip4.addr = svr_addr->sin_addr.s_addr; + local_ipaddr->u_addr.ip4.addr = svr_addr->sin_addr.s_addr; + local_ipaddr->type = IPADDR_TYPE_V4; #elif NETDEV_IPV4 - (*local_ipaddr).addr = svr_addr->sin_addr.s_addr; + local_ipaddr->addr = svr_addr->sin_addr.s_addr; #elif NETDEV_IPV6 - LOG_E("not support IPV6"); -#endif /* SAL_IPV4 && SAL_IPV6*/ +#error "not only support IPV6" +#endif /* NETDEV_IPV4 && NETDEV_IPV6*/ } int sal_bind(int socket, const struct sockaddr *name, socklen_t namelen) @@ -572,7 +573,7 @@ int sal_bind(int socket, const struct sockaddr *name, socklen_t namelen) sal_sockaddr_to_ipaddr(name, &input_ipaddr); /* check input ipaddr is default netdev ipaddr */ - if (input_ipaddr.addr != INADDR_ANY) + if (!ip_addr_isany_val(input_ipaddr)) { struct sal_proto_family *input_pf = RT_NULL, *local_pf = RT_NULL; struct netdev *new_netdev = RT_NULL;