mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-10-05 22:29:49 +00:00
Implement UDP dual-stack PCB support
Create special IP address type "IPADDR_TYPE_ANY" for it. SNMP uses new feature in non-netconn mode. TODO: Same for TCP & RAW, adapt NETCONN to use this feature
This commit is contained in:
parent
1dde3d6e56
commit
953b7bdd59
@ -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 */
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user