diff --git a/src/apps/snmp/snmp_raw.c b/src/apps/snmp/snmp_raw.c index 2fb7765c..c3422dac 100644 --- a/src/apps/snmp/snmp_raw.c +++ b/src/apps/snmp/snmp_raw.c @@ -84,13 +84,16 @@ snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result) void snmp_init(void) { - struct udp_pcb *snmp_pcb = udp_new(); + err_t err; + + struct udp_pcb *snmp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); LWIP_ERROR("snmp_raw: no PCB", (snmp_pcb != NULL), return;); snmp_traps_handle = snmp_pcb; udp_recv(snmp_pcb, snmp_recv, (void *)SNMP_IN_PORT); - udp_bind(snmp_pcb, IP_ADDR_ANY, SNMP_IN_PORT); + err = udp_bind(snmp_pcb, IP_ANY_TYPE, SNMP_IN_PORT); + LWIP_ERROR("snmp_raw: Unable to bind PCB", (err == ERR_OK), return;); } #endif /* LWIP_SNMP && SNMP_USE_RAW */ diff --git a/src/core/init.c b/src/core/init.c index 99419df7..349d071d 100644 --- a/src/core/init.c +++ b/src/core/init.c @@ -61,6 +61,10 @@ #include "lwip/api.h" #include "netif/ppp/ppp_impl.h" +#if LWIP_IPV4 && LWIP_IPV6 +const ip_addr_t ip_addr_any_type = IPADDR_ANY_TYPE_INIT; +#endif + /* Compile-time sanity checks for configuration errors. * These can be done independently of LWIP_DEBUG, without penalty. */ diff --git a/src/core/raw.c b/src/core/raw.c index 651ae73a..3da0d969 100644 --- a/src/core/raw.c +++ b/src/core/raw.c @@ -167,7 +167,7 @@ raw_input(struct pbuf *p, struct netif *inp) err_t raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr) { - if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { + if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) { return ERR_VAL; } ip_addr_set_ipaddr(&pcb->local_ip, ipaddr); @@ -190,7 +190,7 @@ raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr) err_t raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr) { - if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { + if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) { return ERR_VAL; } ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr); diff --git a/src/core/tcp.c b/src/core/tcp.c index 783db33c..58315d74 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c @@ -450,7 +450,7 @@ tcp_bind(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) #endif /* LWIP_IPV4 */ /* still need to check for ipaddr == NULL in IPv6 only case */ - if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { + if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) { return ERR_VAL; } @@ -756,7 +756,7 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port, u32_t iss; u16_t old_local_port; - if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { + if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) { return ERR_VAL; } diff --git a/src/core/udp.c b/src/core/udp.c index 911c4856..4371583a 100644 --- a/src/core/udp.c +++ b/src/core/udp.c @@ -147,11 +147,20 @@ again: * @return 1 on match, 0 otherwise */ static u8_t -udp_input_local_match(struct udp_pcb *pcb, struct netif *inp, u8_t broadcast) +udp_input_local_match(struct udp_pcb *pcb, struct netif *netif, u8_t broadcast) { + LWIP_UNUSED_ARG(netif); /* in IPv6 only case */ LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */ - /* @todo: Add special dualstack case here */ + /* Dual-stack: PCBs listening to any IP type also listen to any IP address */ + if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { +#if IP_SOF_BROADCAST_RECV + if(broadcast && !ip_get_option(pcb, SOF_BROADCAST)) { + return 0; + } +#endif /* IP_SOF_BROADCAST_RECV */ + return 1; + } /* Only need to check PCB if incoming IP version matches PCB IP version */ if(ip_current_is_v6() == IP_IS_V6_VAL(pcb->local_ip)) { @@ -167,7 +176,7 @@ udp_input_local_match(struct udp_pcb *pcb, struct netif *inp, u8_t broadcast) { if(ip4_addr_isany(ip_2_ip4(&pcb->local_ip)) || ((ip4_current_dest_addr()->addr == IPADDR_BROADCAST)) || - ip4_addr_netcmp(ip_2_ip4(&pcb->local_ip), ip4_current_dest_addr(), netif_ip4_netmask(inp))) { + ip4_addr_netcmp(ip_2_ip4(&pcb->local_ip), ip4_current_dest_addr(), netif_ip4_netmask(netif))) { return 1; } } @@ -907,7 +916,7 @@ udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) #endif /* LWIP_IPV4 */ /* still need to check for ipaddr == NULL in IPv6 only case */ - if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { + if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) { return ERR_VAL; } @@ -998,7 +1007,7 @@ udp_connect(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) { struct udp_pcb *ipcb; - if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { + if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) { return ERR_VAL; } @@ -1123,9 +1132,8 @@ udp_new(void) return pcb; } -#if LWIP_IPV6 /** - * Create a UDP PCB for IPv6. + * Create a UDP PCB for specific IP type. See IPADDR_TYPE_XX definitions. * * @return The UDP PCB which was created. NULL if the PCB data structure * could not be allocated. @@ -1133,17 +1141,18 @@ udp_new(void) * @see udp_remove() */ struct udp_pcb * -udp_new_ip6(void) +udp_new_ip_type(u8_t type) { struct udp_pcb *pcb; pcb = udp_new(); -#if LWIP_IPV4 - IP_SET_TYPE_VAL(pcb->local_ip, IPADDR_TYPE_V6); - IP_SET_TYPE_VAL(pcb->remote_ip, IPADDR_TYPE_V6); -#endif /* LWIP_IPV4 */ +#if LWIP_IPV4 && LWIP_IPV6 + IP_SET_TYPE_VAL(pcb->local_ip, type); + IP_SET_TYPE_VAL(pcb->remote_ip, type); +#else + LWIP_UNUSED_ARG(type); +#endif /* LWIP_IPV4 && LWIP_IPV6 */ return pcb; } -#endif /* LWIP_IPV6 */ #if LWIP_IPV4 /** This function is called from netif.c when address is changed diff --git a/src/include/lwip/ip_addr.h b/src/include/lwip/ip_addr.h index 99a7c170..8f7d35ef 100644 --- a/src/include/lwip/ip_addr.h +++ b/src/include/lwip/ip_addr.h @@ -42,6 +42,11 @@ extern "C" { #endif +/** These are the values for ip_addr_t.type */ +#define IPADDR_TYPE_V4 0U +#define IPADDR_TYPE_V6 6U +#define IPADDR_TYPE_ANY 46U + #if LWIP_IPV4 && LWIP_IPV6 /** A union struct for both IP version's addresses. * ATTENTION: watch out for its size when adding IPv6 address scope! @@ -54,19 +59,21 @@ typedef struct _ip_addr { u8_t type; } ip_addr_t; -/** These are the values for ip_addr_t.type */ -#define IPADDR_TYPE_V4 0U -#define IPADDR_TYPE_V6 6U +extern const ip_addr_t ip_addr_any_type; #define IPADDR4_INIT(u32val) { { { { u32val, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_V4 } #define IPADDR6_INIT(a, b, c, d) { { { { a, b, c, d } } }, IPADDR_TYPE_V6 } +#define IP_IS_ANY_TYPE_VAL(ipaddr) ((ipaddr).type == IPADDR_TYPE_ANY) +#define IPADDR_ANY_TYPE_INIT { { { { 0ul, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_ANY } + #define IP_IS_V6_VAL(ipaddr) ((ipaddr).type == IPADDR_TYPE_V6) #define IP_IS_V6(ipaddr) (((ipaddr) != NULL) && IP_IS_V6_VAL(*(ipaddr))) #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_ADDR_PCB_VERSION_MATCH(pcb, ipaddr) (IP_IS_V6_VAL(pcb->local_ip) == IP_IS_V6(ipaddr)) +#define IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr) (pcb->local_ip.type == ipaddr->type) +#define IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr) (IP_IS_ANY_TYPE_VAL(pcb->local_ip) || IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) /* Convert generic ip address to specific protocol version */ #define ip_2_ip6(ipaddr) (&((ipaddr)->u_addr.ip6)) @@ -88,12 +95,10 @@ typedef struct _ip_addr { IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) #define ip_addr_get_ip4_u32(ipaddr) (((ipaddr) && !IP_IS_V6(ipaddr)) ? \ ip4_addr_get_u32(ip_2_ip4(ipaddr)) : 0) -#define ip_addr_set(dest, src) do{if(IP_IS_V6(src)){ \ - ip6_addr_set(ip_2_ip6(dest), ip_2_ip6(src)); IP_SET_TYPE(dest, IPADDR_TYPE_V6); }else{ \ - ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); IP_SET_TYPE(dest, IPADDR_TYPE_V4); }}while(0) -#define ip_addr_set_ipaddr(dest, src) do{if(IP_IS_V6(src)){ \ - ip6_addr_set(ip_2_ip6(dest), ip_2_ip6(src)); IP_SET_TYPE(dest, IPADDR_TYPE_V6); }else{ \ - ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); IP_SET_TYPE(dest, IPADDR_TYPE_V4); }}while(0) +#define ip_addr_set(dest, src) do{ IP_SET_TYPE(dest, src->type); 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_ipaddr(dest, src) ip_addr_set(dest, src) #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_zero_ip4(ipaddr) do{ \ @@ -150,7 +155,8 @@ int ipaddr_aton(const char *cp, ip_addr_t *addr); #else /* LWIP_IPV4 && LWIP_IPV6 */ -#define IP_ADDR_PCB_VERSION_MATCH(addr, pcb) 1 +#define IP_ADDR_PCB_VERSION_MATCH(addr, pcb) 1 +#define IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr) 1 #if LWIP_IPV4 @@ -158,6 +164,7 @@ typedef ip4_addr_t ip_addr_t; #define IPADDR4_INIT(u32val) { u32val } #define IP_IS_V6_VAL(ipaddr) 0 #define IP_IS_V6(ipaddr) 0 +#define IP_IS_ANY_TYPE_VAL(ipaddr) 0 #define IP_SET_TYPE_VAL(ipaddr, iptype) #define IP_SET_TYPE(ipaddr, iptype) #define ip_2_ip4(ipaddr) (ipaddr) @@ -195,6 +202,7 @@ typedef ip6_addr_t ip_addr_t; #define IPADDR6_INIT(a, b, c, d) { { a, b, c, d } } #define IP_IS_V6_VAL(ipaddr) 1 #define IP_IS_V6(ipaddr) 1 +#define IP_IS_ANY_TYPE_VAL(ipaddr) 0 #define IP_SET_TYPE_VAL(ipaddr, iptype) #define IP_SET_TYPE(ipaddr, iptype) #define ip_2_ip6(ipaddr) (ipaddr) @@ -265,6 +273,12 @@ extern const ip_addr_t ip6_addr_any; #endif +#if LWIP_IPV4 && LWIP_IPV6 +#define IP_ANY_TYPE (&ip_addr_any_type) +#else +#define IP_ANY_TYPE IP_ADDR_ANY +#endif + #ifdef __cplusplus } #endif diff --git a/src/include/lwip/udp.h b/src/include/lwip/udp.h index 783f1ff8..03e98e48 100644 --- a/src/include/lwip/udp.h +++ b/src/include/lwip/udp.h @@ -123,6 +123,7 @@ extern struct udp_pcb *udp_pcbs; /* The following functions is the application layer interface to the UDP code. */ struct udp_pcb * udp_new (void); +struct udp_pcb * udp_new_ip_type(u8_t type); void udp_remove (struct udp_pcb *pcb); err_t udp_bind (struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port); @@ -164,10 +165,6 @@ void udp_input (struct pbuf *p, struct netif *inp); void udp_init (void); -#if LWIP_IPV6 -struct udp_pcb * udp_new_ip6(void); -#endif /* LWIP_IPV6 */ - #if LWIP_MULTICAST_TX_OPTIONS #define udp_set_multicast_netif_addr(pcb, ip4addr) ip_addr_copy_from_ip4((pcb)->multicast_ip, *(ip4addr)) #define udp_get_multicast_netif_addr(pcb) ip_2_ip4(&(pcb)->multicast_ip) diff --git a/src/netif/ppp/pppol2tp.c b/src/netif/ppp/pppol2tp.c index c500b832..752fde73 100644 --- a/src/netif/ppp/pppol2tp.c +++ b/src/netif/ppp/pppol2tp.c @@ -131,7 +131,7 @@ ppp_pcb *pppol2tp_create(struct netif *pppif, #if LWIP_IPV6 if (IP_IS_V6_VAL(*ipaddr)) { - udp = udp_new_ip6(); + udp = udp_new_ip_type(IPADDR_TYPE_V6); } else #endif /* LWIP_IPV6 */ udp = udp_new();