Merge branch 'feature/add_igmp_socket_ipv6' into 'master'

Add IPv6 multicast for socket

See merge request sdk/ESP8266_RTOS_SDK!591
This commit is contained in:
Dong Heng
2018-11-01 11:41:51 +08:00
12 changed files with 390 additions and 2 deletions

View File

@ -41,6 +41,13 @@ endmenu # LWIP ARP
menu "SOCKET"
config LWIP_IPV6_MLD_SOCK
bool "LWIP socket supports IPv6 multicast configuration"
default y
depends on LWIP_IPV6
help
Enable the option can enable LWIP socket IPv6 multicast configuration.
config LWIP_SOCKET_MULTITHREAD
bool "LWIP socket supports multithread"
default y
@ -221,6 +228,24 @@ config LWIP_DHCP_AUTOIP_COOP_TRIES
address very quickly, but you should be prepared to handle a
changing IP address when DHCP overrides AutoIP."
config LWIP_AUTOIP_MAX_CONFLICTS
int "Max IP conflicts before rate limiting"
range 1 100
default 9
depends on LWIP_AUTOIP
help
If the AUTOIP functionality detects this many IP conflicts while
self-assigning an address, it will go into a rate limited mode.
config LWIP_AUTOIP_RATE_LIMIT_INTERVAL
int "Rate limited interval (seconds)"
range 5 120
default 20
depends on LWIP_AUTOIP
help
If rate limiting self-assignment requests, wait this long between
each request.
config LWIP_IGMP
bool "Enable IGMP module"
default y

View File

@ -196,6 +196,18 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
return;
}
#if LWIP_IPV6
#if ESP_LWIP_IPV6_MLD
/* This should be eventually moved to a flag on the UDP PCB, and this drop can happen
more correctly in udp_input(). This will also allow icmp_dest_unreach() to be called. */
if (conn->flags & NETCONN_FLAG_IPV6_V6ONLY && !ip_current_is_v6()) {
LWIP_DEBUGF(API_MSG_DEBUG, ("recv_udp: Dropping IPv4 UDP packet (IPv6-only socket)"));
pbuf_free(p);
return;
}
#endif /* ESP_LWIP_IPV6_MLD */
#endif /* LWIP_IPV6 */
buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
if (buf == NULL) {
pbuf_free(p);
@ -611,6 +623,17 @@ pcb_new(struct api_msg *msg)
if (msg->conn->pcb.ip == NULL) {
msg->err = ERR_MEM;
}
#if LWIP_IPV4 && LWIP_IPV6
#if ESP_LWIP_IPV6_MLD
else {
if (NETCONNTYPE_ISIPV6(msg->conn->type)) {
/* Convert IPv4 PCB manually to an IPv6 PCB */
IP_SET_TYPE_VAL(msg->conn->pcb.ip->local_ip, IPADDR_TYPE_V6);
IP_SET_TYPE_VAL(msg->conn->pcb.ip->remote_ip, IPADDR_TYPE_V6);
}
}
#endif /* ESP_LWIP_IPV6_MLD*/
#endif /* LWIP_IPV4 && LWIP_IPV6 */
}
/**
@ -1132,6 +1155,24 @@ lwip_netconn_do_bind(void *m)
msg->err = msg->conn->last_err;
} else {
msg->err = ERR_VAL;
#if LWIP_IPV4 && LWIP_IPV6
#if ESP_LWIP_IPV6_MLD
/* "Socket API like" dual-stack support: If IP to bind to is IP6_ADDR_ANY,
* and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to bind
*/
if (ip_addr_cmp(API_EXPR_REF(msg->msg.bc.ipaddr), IP6_ADDR_ANY) &&
(netconn_get_ipv6only(msg->conn) == 0)) {
/* change PCB type to IPADDR_TYPE_ANY */
IP_SET_TYPE_VAL(msg->conn->pcb.ip->local_ip, IPADDR_TYPE_ANY);
IP_SET_TYPE_VAL(msg->conn->pcb.ip->remote_ip, IPADDR_TYPE_ANY);
/* bind to IPADDR_TYPE_ANY */
API_EXPR_REF(msg->msg.bc.ipaddr) = IP_ANY_TYPE;
}
#endif /* ESP_LWIP_IPV6_MLD */
#endif /* LWIP_IPV4 && LWIP_IPV6 */
if (msg->conn->pcb.tcp != NULL) {
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
#if LWIP_RAW
@ -1400,6 +1441,14 @@ lwip_netconn_do_send(void *m)
if (ERR_IS_FATAL(msg->conn->last_err)) {
msg->err = msg->conn->last_err;
#if ESP_LWIP_IPV6_MLD
#if LWIP_IPV4 && LWIP_IPV6
} else if ((msg->conn->flags & NETCONN_FLAG_IPV6_V6ONLY) &&
IP_IS_V4MAPPEDV6(&msg->msg.b->addr)) {
LWIP_DEBUGF(API_MSG_DEBUG, ("lwip_netconn_do_send: Dropping IPv4 packet on IPv6-only socket"));
msg->err = ERR_VAL;
#endif /* LWIP_IPV4 && LWIP_IPV6 */
#endif /* ESP_LWIP_IPV6_MLD */
} else {
msg->err = ERR_CONN;
if (msg->conn->pcb.tcp != NULL) {

View File

@ -332,6 +332,11 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
type = NETCONN_DNS_IPV4;
} else if (ai_family == AF_INET6) {
type = NETCONN_DNS_IPV6;
#if ESP_LWIP_IPV6_MLD
if (hints->ai_flags & AI_V4MAPPED) {
type = NETCONN_DNS_IPV6_IPV4;
}
#endif /* ESP_LWIP_IPV6_MLD */
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
err = netconn_gethostbyname_addrtype(nodename, &addr, type);
@ -348,6 +353,16 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
}
}
#if LWIP_IPV4 && LWIP_IPV6
#if ESP_LWIP_IPV6_MLD
if (ai_family == AF_INET6 && (hints->ai_flags & AI_V4MAPPED)
&& IP_GET_TYPE(&addr) == IPADDR_TYPE_V4) {
/* Convert native V4 address to a V4-mapped IPV6 address */
ip4_2_ipv4_mapped_ipv6(ip_2_ip6(&addr), ip_2_ip4(&addr));
}
#endif /* ESP_LWIP_IPV6_MLD */
#endif /* LWIP_IPV4 && LWIP_IPV6 */
total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage);
if (nodename != NULL) {
namelen = strlen(nodename);

View File

@ -77,6 +77,10 @@
#define LWIP_NETCONN 0
#endif
#ifdef ESP_LWIP_IPV6_MLD
#include "lwip/mld6.h"
#endif
#if LWIP_IPV4
#define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \
(sin)->sin_len = sizeof(struct sockaddr_in); \
@ -263,6 +267,23 @@ union sockaddr_aligned {
#define LWIP_SOCKET_MAX_MEMBERSHIPS NUM_SOCKETS
#endif
/* This is to keep track of IP_ADD_MEMBERSHIP calls to drop the membership when
a socket is closed */
#if ESP_LWIP_IPV6_MLD
struct lwip_socket_multicast_pair {
/** the socket (+1 to not require initialization) */
int sa;
/** the interface address */
ip_addr_t if_addr;
/** the group address */
ip_addr_t multi_addr;
};
struct lwip_socket_multicast_pair socket_multicast_memberships[LWIP_SOCKET_MAX_MEMBERSHIPS];
static int lwip_socket_register_membership(int s, const ip_addr_t *if_addr, const ip_addr_t *multi_addr);
static void lwip_socket_unregister_membership(int s, const ip_addr_t *if_addr, const ip_addr_t *multi_addr);
#else
/* This is to keep track of IP_ADD_MEMBERSHIP calls to drop the membership when
a socket is closed */
struct lwip_socket_multicast_pair {
@ -278,6 +299,8 @@ struct lwip_socket_multicast_pair socket_ipv4_multicast_memberships[LWIP_SOCKET_
static int lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr);
static void lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr);
#endif /* ESP_LWIP_IPV6_MLD */
static void lwip_socket_drop_registered_memberships(int s);
#endif /* LWIP_IGMP */
@ -624,10 +647,17 @@ lwip_close(int s)
LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL);
}
#if ESP_LWIP_IPV6_MLD
#if (LWIP_IGMP) || (LWIP_IPV6_MLD && LWIP_MULTICAST_TX_OPTIONS)
/* drop all possibly joined IGMP memberships */
lwip_socket_drop_registered_memberships(s);
#endif
#else
#if LWIP_IGMP
/* drop all possibly joined IGMP memberships */
lwip_socket_drop_registered_memberships(s);
#endif /* LWIP_IGMP */
#endif /* ESP_LWIP_IPV6_MLD */
#ifndef SOCKETS_MT
#if ESP_UDP
@ -2135,6 +2165,42 @@ lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *opt
break;
} /* switch (optname) */
break;
#if LWIP_IPV6_MLD && LWIP_MULTICAST_TX_OPTIONS /* Multicast options, similar to LWIP_IGMP options for IPV4 */
#if ESP_LWIP_IPV6_MLD
case IPV6_MULTICAST_IF: /* NB: like IP_MULTICAST_IF, this returns an IP not an index */
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, struct in6_addr);
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
return ENOPROTOOPT;
}
inet6_addr_from_ip6addr((struct in6_addr*)optval,
udp_get_multicast_netif_ip6addr(sock->conn->pcb.udp));
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_MULTICAST_IF) = 0x%"X32_F"\n",
s, *(u32_t *)optval));
break;
case IPV6_MULTICAST_HOPS:
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t);
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
return ENOPROTOOPT;
}
*(u8_t*)optval = sock->conn->pcb.udp->mcast_ttl;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IP_MULTICAST_LOOP) = %d\n",
s, *(int *)optval));
break;
case IPV6_MULTICAST_LOOP:
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t);
if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) {
*(u8_t*)optval = 1;
} else {
*(u8_t*)optval = 0;
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IP_MULTICAST_LOOP) = %d\n",
s, *(int *)optval));
break;
#endif /* ESP_LWIP_IPV6_MLD */
#endif /* LWIP_IPV6_MLD && LWIP_MULTICAST_TX_OPTIONS */
#endif /* LWIP_IPV6 */
#if LWIP_UDP && LWIP_UDPLITE
@ -2433,21 +2499,39 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
/* @todo: assign membership to this socket so that it is dropped when closing the socket */
err_t igmp_err;
const struct ip_mreq *imr = (const struct ip_mreq *)optval;
#if ESP_LWIP_IPV6_MLD
ip_addr_t if_addr;
ip_addr_t multi_addr;
#else
ip4_addr_t if_addr;
ip4_addr_t multi_addr;
#endif /* ESP_LWIP_IPV6_MLD */
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct ip_mreq, NETCONN_UDP);
#if ESP_LWIP_IPV6_MLD
inet_addr_to_ip4addr(ip_2_ip4(&if_addr), &imr->imr_interface);
inet_addr_to_ip4addr(ip_2_ip4(&multi_addr), &imr->imr_multiaddr);
#else
inet_addr_to_ip4addr(&if_addr, &imr->imr_interface);
inet_addr_to_ip4addr(&multi_addr, &imr->imr_multiaddr);
#endif /* ESP_LWIP_IPV6_MLD */
if (optname == IP_ADD_MEMBERSHIP) {
if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) {
/* cannot track membership (out of memory) */
err = ENOMEM;
igmp_err = ERR_OK;
} else {
#if ESP_LWIP_IPV6_MLD
igmp_err = igmp_joingroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr));
#else
igmp_err = igmp_joingroup(&if_addr, &multi_addr);
#endif /* ESP_LWIP_IPV6_MLD */
}
} else {
#if ESP_LWIP_IPV6_MLD
igmp_err = igmp_leavegroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr));
#else
igmp_err = igmp_leavegroup(&if_addr, &multi_addr);
#endif /* ESP_LWIP_IPV6_MLD */
lwip_socket_unregister_membership(s, &if_addr, &multi_addr);
}
if (igmp_err != ERR_OK) {
@ -2519,7 +2603,11 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
case IPPROTO_IPV6:
switch (optname) {
case IPV6_V6ONLY:
#if ESP_LWIP_IPV6_MLD
LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, int);
#else
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP);
#endif /* ESP_LWIP_IPV6_MLD */
if (*(const int*)optval) {
netconn_set_ipv6only(sock->conn, 1);
} else {
@ -2528,6 +2616,59 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY, ..) -> %d\n",
s, (netconn_get_ipv6only(sock->conn) ? 1 : 0)));
break;
#if LWIP_IPV6_MLD && LWIP_MULTICAST_TX_OPTIONS /* Multicast options, similar to LWIP_IGMP options for IPV4 */
#if ESP_LWIP_IPV6_MLD
case IPV6_MULTICAST_IF: /* NB: like IP_MULTICAST_IF, this takes an IP not an index */
{
ip6_addr_t if_addr;
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct in6_addr, NETCONN_UDP);
inet6_addr_to_ip6addr(&if_addr, (const struct in6_addr*)optval);
udp_set_multicast_netif_ip6addr(sock->conn->pcb.udp, &if_addr);
}
break;
case IPV6_MULTICAST_HOPS:
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP);
sock->conn->pcb.udp->mcast_ttl = (u8_t)(*(const u8_t*)optval);
break;
case IPV6_MULTICAST_LOOP:
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP);
if (*(const u8_t*)optval) {
udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP);
} else {
udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP);
}
break;
case IPV6_ADD_MEMBERSHIP:
case IPV6_DROP_MEMBERSHIP:
{
err_t mld_err;
const struct ip6_mreq *imr = (const struct ip6_mreq *)optval;
ip_addr_t if_addr;
ip_addr_t multi_addr;
LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct ip6_mreq, NETCONN_UDP);
inet6_addr_to_ip6addr(ip_2_ip6(&if_addr), &imr->ipv6mr_interface);
inet6_addr_to_ip6addr(ip_2_ip6(&multi_addr), &imr->ipv6mr_multiaddr);
if (optname == IPV6_ADD_MEMBERSHIP) {
if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) {
/* cannot track membership (out of memory) */
err = ENOMEM;
mld_err = ERR_OK;
} else {
mld_err = mld6_joingroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr));
}
} else {
mld_err = mld6_leavegroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr));
lwip_socket_unregister_membership(s, &if_addr, &multi_addr);
}
if (mld_err != ERR_OK) {
err = EADDRNOTAVAIL;
}
}
break;
#endif /* ESP_LWIP_IPV6_MLD */
#endif /* LWIP_IPV6_MLD && LWIP_MULTICAST_TX_OPTIONS */
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n",
s, optname));
@ -2748,6 +2889,7 @@ lwip_fcntl(int s, int cmd, int val)
}
#if LWIP_IGMP
#if LWIP_IPV6_MLD && LWIP_MULTICAST_TX_OPTIONS && ESP_LWIP_IPV6_MLD
/** Register a new IGMP membership. On socket close, the membership is dropped automatically.
*
* ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK).
@ -2755,6 +2897,77 @@ lwip_fcntl(int s, int cmd, int val)
* @return 1 on success, 0 on failure
*/
static int
lwip_socket_register_membership(int s, const ip_addr_t *if_addr, const ip_addr_t *multi_addr)
{
/* s+1 is stored in the array to prevent having to initialize the array
(default initialization is to 0) */
int sa = s + 1;
int i;
for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
if (socket_multicast_memberships[i].sa == 0) {
socket_multicast_memberships[i].sa = sa;
ip_addr_copy(socket_multicast_memberships[i].if_addr, *if_addr);
ip_addr_copy(socket_multicast_memberships[i].multi_addr, *multi_addr);
return 1;
}
}
return 0;
}
/** Unregister a previously registered membership. This prevents dropping the membership
* on socket close.
*
* ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK).
*/
static void
lwip_socket_unregister_membership(int s, const ip_addr_t *if_addr, const ip_addr_t *multi_addr)
{
/* s+1 is stored in the array to prevent having to initialize the array
(default initialization is to 0) */
int sa = s + 1;
int i;
for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
if ((socket_multicast_memberships[i].sa == sa) &&
ip_addr_cmp(&socket_multicast_memberships[i].if_addr, if_addr) &&
ip_addr_cmp(&socket_multicast_memberships[i].multi_addr, multi_addr)) {
socket_multicast_memberships[i].sa = 0;
ip_addr_set_zero(&socket_multicast_memberships[i].if_addr);
ip_addr_set_zero(&socket_multicast_memberships[i].multi_addr);
return;
}
}
}
/** Drop all memberships of a socket that were not dropped explicitly via setsockopt.
*
* ATTENTION: this function is NOT called from tcpip_thread (or under CORE_LOCK).
*/
static void lwip_socket_drop_registered_memberships(int s)
{
/* s+1 is stored in the array to prevent having to initialize the array
(default initialization is to 0) */
int sa = s + 1;
int i;
struct lwip_sock *sock = get_socket(s);
LWIP_ASSERT("socket has no netconn", sock->conn != NULL);
for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
if (socket_multicast_memberships[i].sa == sa) {
socket_multicast_memberships[i].sa = 0;
netconn_join_leave_group(sock->conn,
&socket_multicast_memberships[i].multi_addr,
&socket_multicast_memberships[i].if_addr,
NETCONN_LEAVE);
ip_addr_set_zero(&socket_multicast_memberships[i].if_addr);
ip_addr_set_zero(&socket_multicast_memberships[i].multi_addr);
}
}
}
#else /* LWIP_IPV6_MLD && LWIP_MULTICAST_TX_OPTIONS && ESP_LWIP_IPV6_MLD*/
static int
lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr)
{
struct lwip_sock *sock = get_socket(s);
@ -2829,5 +3042,6 @@ lwip_socket_drop_registered_memberships(int s)
}
}
}
#endif /* LWIP_IPV6_MLD && LWIP_MULTICAST_TX_OPTIONS && ESP_LWIP_IPV6_MLD */
#endif /* LWIP_IGMP */
#endif /* LWIP_SOCKET */

View File

@ -904,6 +904,15 @@ ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
}
}
}
#if LWIP_IPV6_MLD
#if ESP_LWIP_IPV6_MLD
if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) {
netif_loop_output(netif, p);
}
#endif /* ESP_LWIP_IPV6_MLD */
#endif /* LWIP_IPV6_MLD */
#endif /* ENABLE_LOOPBACK */
#if LWIP_IPV6_FRAG
/* don't fragment if interface has mtu set to 0 [loopif] */

View File

@ -551,6 +551,21 @@ udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip,
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n"));
#if LWIP_IPV4 && LWIP_IPV6
#if ESP_LWIP_IPV6
/* Unwrap IPV4-mapped IPV6 addresses and convert to native IPV4 here */
if (IP_IS_V4MAPPEDV6(dst_ip)) {
ip_addr_t dest_ipv4;
unmap_ipv4_mapped_ipv6(ip_2_ip4(&dest_ipv4), ip_2_ip6(dst_ip));
#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UP
return udp_sendto_chksum(pcb, p, &dest_ipv4, dst_port, have_chksum, chksum);
#else
return udp_sendto(pcb, p, &dest_ipv4, dst_port);
#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UP */
}
#endif /* ESP_LWIP_IPV6 */
#endif /* LWIP_IPV4 && LWIP_IPV6 */
#if LWIP_IPV6 || (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS)
if (ip_addr_ismulticast(dst_ip_route)) {
#if LWIP_IPV6

View File

@ -100,6 +100,11 @@ extern const ip_addr_t ip_addr_any_type;
/** @ingroup ip6addr */
#define IP_IS_V6(ipaddr) (((ipaddr) != NULL) && IP_IS_V6_VAL(*(ipaddr)))
#if ESP_LWIP_IPV6_MLD
#define IP_V6_EQ_PART(ipaddr, WORD, VAL) (ip_2_ip6(ipaddr)->addr[WORD] == htonl(VAL))
#define IP_IS_V4MAPPEDV6(ipaddr) (IP_IS_V6(ipaddr) && IP_V6_EQ_PART(ipaddr, 0, 0) && IP_V6_EQ_PART(ipaddr, 1, 0) && IP_V6_EQ_PART(ipaddr, 2, 0x0000FFFF))
#endif /* ESP_LWIP_IPV6_MLD */
#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)

View File

@ -935,6 +935,23 @@
#if !defined LWIP_DHCP_AUTOIP_COOP_TRIES || defined __DOXYGEN__
#define LWIP_DHCP_AUTOIP_COOP_TRIES 9
#endif
/**
* LWIP_AUTOIP_MAX_CONFLICTS:
* Maximum number of AutoIP IP conflicts before rate limiting is enabled.
*/
#ifndef LWIP_AUTOIP_MAX_CONFLICTS
#define LWIP_AUTOIP_MAX_CONFLICTS 10
#endif
/**
* LWIP_AUTOIP_RATE_LIMIT_INTERVAL:
* Rate limited request interval, in seconds.
*/
#ifndef LWIP_AUTOIP_RATE_LIMIT_INTERVAL
#define LWIP_AUTOIP_RATE_LIMIT_INTERVAL 60
#endif
/**
* @}
*/

View File

@ -59,8 +59,10 @@ extern "C" {
#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 MAX_CONFLICTS 10 /* (max conflicts before rate limiting) */
#define RATE_LIMIT_INTERVAL 60 /* seconds (delay between successive attempts) */
#define MAX_CONFLICTS LWIP_AUTOIP_MAX_CONFLICTS /* (max conflicts before rate limiting) */
#define RATE_LIMIT_INTERVAL LWIP_AUTOIP_RATE_LIMIT_INTERVAL /* seconds (delay between successive attempts) */
#define DEFEND_INTERVAL 10 /* seconds (min. wait between defensive ARPs) */
/* AutoIP client states */

View File

@ -262,6 +262,29 @@ struct linger {
*/
#define IPV6_CHECKSUM 7 /* RFC3542: calculate and insert the ICMPv6 checksum for raw sockets. */
#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */
#if LWIP_IPV6_MLD
#if ESP_LWIP_IPV6_MLD
/* Socket options for IPV6 multicast, uses the MLD interface to manage group memberships. RFC2133. */
#define IPV6_MULTICAST_IF 0x300
#define IPV6_MULTICAST_HOPS 0x301
#define IPV6_MULTICAST_LOOP 0x302
#define IPV6_ADD_MEMBERSHIP 0x303
#define IPV6_DROP_MEMBERSHIP 0x304
/* Structure used for IPV6_ADD/DROP_MEMBERSHIP */
typedef struct ip6_mreq {
struct in6_addr ipv6mr_multiaddr; /* IPv6 multicast addr */
struct in6_addr ipv6mr_interface; /* local IP address of interface */
} ip6_mreq;
/* Commonly used synonyms for these options */
#define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
#define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
#endif /* ESP_LWIP_IPV6_MLD */
#endif /* LWIP_IPV6_MLD */
#endif /* LWIP_IPV6 */
#if LWIP_UDP && LWIP_UDPLITE

View File

@ -174,6 +174,14 @@ void udp_init (void);
#define udp_get_multicast_netif_addr(pcb) ip_2_ip4(&(pcb)->multicast_ip)
#define udp_set_multicast_ttl(pcb, value) do { (pcb)->mcast_ttl = value; } while(0)
#define udp_get_multicast_ttl(pcb) ((pcb)->mcast_ttl)
#if LWIP_IPV6_MLD
#if ESP_LWIP_IPV6_MLD
#define udp_set_multicast_netif_ip6addr(pcb, ip6addr) ip_addr_copy_from_ip6((pcb)->multicast_ip, *(ip6addr))
#define udp_get_multicast_netif_ip6addr(pcb) ip_2_ip6(&(pcb)->multicast_ip)
#endif /* ESP_LWIP_IPV6_MLD */
#endif /* LWIP_IPV6_MLD */
#endif /* LWIP_MULTICAST_TX_OPTIONS */
#if UDP_DEBUG

View File

@ -52,6 +52,12 @@
#define ESP_LWIP 1
#ifdef CONFIG_LWIP_IPV6_MLD_SOCK
#define ESP_LWIP_IPV6_MLD 1
#else
#define ESP_LWIP_IPV6_MLD 0
#endif
#ifdef CONFIG_ESP_UDP_SYNC_SEND
#define ESP_UDP 1
#endif