mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-10-05 22:29:49 +00:00
Implement dual-stack in RAW API in the same way as in UDP and TCP
This commit is contained in:
parent
2d80af1dcb
commit
7396d8818b
109
src/core/raw.c
109
src/core/raw.c
@ -57,6 +57,47 @@
|
|||||||
/** The list of RAW PCBs */
|
/** The list of RAW PCBs */
|
||||||
static struct raw_pcb *raw_pcbs;
|
static struct raw_pcb *raw_pcbs;
|
||||||
|
|
||||||
|
static u8_t
|
||||||
|
raw_input_match(struct raw_pcb *pcb, u8_t broadcast)
|
||||||
|
{
|
||||||
|
LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */
|
||||||
|
|
||||||
|
/* Dual-stack: PCBs listening to any IP type also listen to any IP address */
|
||||||
|
if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) {
|
||||||
|
#if LWIP_IPV4 && IP_SOF_BROADCAST_RECV
|
||||||
|
if((broadcast != 0) && !ip_get_option(pcb, SOF_BROADCAST)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV4 && IP_SOF_BROADCAST_RECV */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only need to check PCB if incoming IP version matches PCB IP version */
|
||||||
|
if(IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ip_current_dest_addr())) {
|
||||||
|
#if LWIP_IPV4
|
||||||
|
/* Special case: IPv4 broadcast: receive all broadcasts
|
||||||
|
* Note: broadcast variable can only be 1 if it is an IPv4 broadcast */
|
||||||
|
if(broadcast != 0) {
|
||||||
|
#if IP_SOF_BROADCAST_RECV
|
||||||
|
if(ip_get_option(pcb, SOF_BROADCAST))
|
||||||
|
#endif /* IP_SOF_BROADCAST_RECV */
|
||||||
|
{
|
||||||
|
if(ip4_addr_isany(ip_2_ip4(&pcb->local_ip))) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif /* LWIP_IPV4 */
|
||||||
|
/* Handle IPv4 and IPv6: catch all or exact match */
|
||||||
|
if(ip_addr_isany(&pcb->local_ip) ||
|
||||||
|
ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if in incoming IP packet is covered by a RAW PCB
|
* Determine if in incoming IP packet is covered by a RAW PCB
|
||||||
* and if so, pass it to a user-provided receive callback function.
|
* and if so, pass it to a user-provided receive callback function.
|
||||||
@ -80,6 +121,7 @@ raw_input(struct pbuf *p, struct netif *inp)
|
|||||||
struct raw_pcb *pcb, *prev;
|
struct raw_pcb *pcb, *prev;
|
||||||
s16_t proto;
|
s16_t proto;
|
||||||
u8_t eaten = 0;
|
u8_t eaten = 0;
|
||||||
|
u8_t broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif());
|
||||||
|
|
||||||
LWIP_UNUSED_ARG(inp);
|
LWIP_UNUSED_ARG(inp);
|
||||||
|
|
||||||
@ -106,44 +148,34 @@ raw_input(struct pbuf *p, struct netif *inp)
|
|||||||
/* loop through all raw pcbs until the packet is eaten by one */
|
/* loop through all raw pcbs until the packet is eaten by one */
|
||||||
/* this allows multiple pcbs to match against the packet by design */
|
/* this allows multiple pcbs to match against the packet by design */
|
||||||
while ((eaten == 0) && (pcb != NULL)) {
|
while ((eaten == 0) && (pcb != NULL)) {
|
||||||
if ((pcb->protocol == proto) && IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ip_current_dest_addr()) &&
|
if ((pcb->protocol == proto) && raw_input_match(pcb, broadcast)) {
|
||||||
(ip_addr_isany(&pcb->local_ip) ||
|
/* receive callback function available? */
|
||||||
ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr()))) {
|
if (pcb->recv != NULL) {
|
||||||
#if IP_SOF_BROADCAST_RECV
|
|
||||||
/* broadcast filter? */
|
|
||||||
if ((ip_get_option(pcb, SOF_BROADCAST) || !ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()))
|
|
||||||
|| IP_IS_V6_VAL(pcb->local_ip)
|
|
||||||
)
|
|
||||||
#endif /* IP_SOF_BROADCAST_RECV */
|
|
||||||
{
|
|
||||||
/* receive callback function available? */
|
|
||||||
if (pcb->recv != NULL) {
|
|
||||||
#ifndef LWIP_NOASSERT
|
#ifndef LWIP_NOASSERT
|
||||||
void* old_payload = p->payload;
|
void* old_payload = p->payload;
|
||||||
#endif
|
#endif
|
||||||
/* the receive callback function did not eat the packet? */
|
/* the receive callback function did not eat the packet? */
|
||||||
eaten = pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr());
|
eaten = pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr());
|
||||||
if (eaten != 0) {
|
if (eaten != 0) {
|
||||||
/* receive function ate the packet */
|
/* receive function ate the packet */
|
||||||
p = NULL;
|
p = NULL;
|
||||||
eaten = 1;
|
eaten = 1;
|
||||||
if (prev != NULL) {
|
if (prev != NULL) {
|
||||||
/* move the pcb to the front of raw_pcbs so that is
|
/* move the pcb to the front of raw_pcbs so that is
|
||||||
found faster next time */
|
found faster next time */
|
||||||
prev->next = pcb->next;
|
prev->next = pcb->next;
|
||||||
pcb->next = raw_pcbs;
|
pcb->next = raw_pcbs;
|
||||||
raw_pcbs = pcb;
|
raw_pcbs = pcb;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* sanity-check that the receive callback did not alter the pbuf */
|
|
||||||
LWIP_ASSERT("raw pcb recv callback altered pbuf payload pointer without eating packet",
|
|
||||||
p->payload == old_payload);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* sanity-check that the receive callback did not alter the pbuf */
|
||||||
|
LWIP_ASSERT("raw pcb recv callback altered pbuf payload pointer without eating packet",
|
||||||
|
p->payload == old_payload);
|
||||||
}
|
}
|
||||||
/* no receive callback function was set for this raw PCB */
|
|
||||||
}
|
}
|
||||||
/* drop the packet */
|
/* no receive callback function was set for this raw PCB */
|
||||||
}
|
}
|
||||||
|
/* drop the packet */
|
||||||
prev = pcb;
|
prev = pcb;
|
||||||
pcb = pcb->next;
|
pcb = pcb->next;
|
||||||
}
|
}
|
||||||
@ -416,31 +448,30 @@ raw_new(u8_t proto)
|
|||||||
return pcb;
|
return pcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LWIP_IPV6
|
|
||||||
/**
|
/**
|
||||||
* Create a RAW PCB for IPv6.
|
* Create a RAW PCB for IPv6.
|
||||||
*
|
*
|
||||||
* @return The RAW PCB which was created. NULL if the PCB data structure
|
* @return The RAW PCB which was created. NULL if the PCB data structure
|
||||||
* could not be allocated.
|
* could not be allocated.
|
||||||
*
|
*
|
||||||
|
* @param type IP address type, see IPADDR_TYPE_XX definitions.
|
||||||
* @param proto the protocol number (next header) of the IPv6 packet payload
|
* @param proto the protocol number (next header) of the IPv6 packet payload
|
||||||
* (e.g. IP6_NEXTH_ICMP6)
|
* (e.g. IP6_NEXTH_ICMP6)
|
||||||
*
|
*
|
||||||
* @see raw_remove()
|
* @see raw_remove()
|
||||||
*/
|
*/
|
||||||
struct raw_pcb *
|
struct raw_pcb *
|
||||||
raw_new_ip6(u8_t proto)
|
raw_new_ip_type(u8_t type, u8_t proto)
|
||||||
{
|
{
|
||||||
struct raw_pcb *pcb;
|
struct raw_pcb *pcb;
|
||||||
pcb = raw_new(proto);
|
pcb = raw_new(proto);
|
||||||
#if LWIP_IPV4
|
#if LWIP_IPV4 && LWIP_IPV6
|
||||||
if(pcb != NULL) {
|
if(pcb != NULL) {
|
||||||
IP_SET_TYPE_VAL(pcb->local_ip, IPADDR_TYPE_V6);
|
IP_SET_TYPE_VAL(pcb->local_ip, type);
|
||||||
IP_SET_TYPE_VAL(pcb->remote_ip, IPADDR_TYPE_V6);
|
IP_SET_TYPE_VAL(pcb->remote_ip, type);
|
||||||
}
|
}
|
||||||
#endif /* LWIP_IPV4 */
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||||
return pcb;
|
return pcb;
|
||||||
}
|
}
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
|
|
||||||
#endif /* LWIP_RAW */
|
#endif /* LWIP_RAW */
|
||||||
|
@ -83,6 +83,7 @@ struct raw_pcb {
|
|||||||
/* The following functions is the application layer interface to the
|
/* The following functions is the application layer interface to the
|
||||||
RAW code. */
|
RAW code. */
|
||||||
struct raw_pcb * raw_new (u8_t proto);
|
struct raw_pcb * raw_new (u8_t proto);
|
||||||
|
struct raw_pcb * raw_new_ip_type(u8_t type, u8_t proto);
|
||||||
void raw_remove (struct raw_pcb *pcb);
|
void raw_remove (struct raw_pcb *pcb);
|
||||||
err_t raw_bind (struct raw_pcb *pcb, const ip_addr_t *ipaddr);
|
err_t raw_bind (struct raw_pcb *pcb, const ip_addr_t *ipaddr);
|
||||||
err_t raw_connect (struct raw_pcb *pcb, const ip_addr_t *ipaddr);
|
err_t raw_connect (struct raw_pcb *pcb, const ip_addr_t *ipaddr);
|
||||||
@ -92,14 +93,13 @@ err_t raw_send (struct raw_pcb *pcb, struct pbuf *p);
|
|||||||
|
|
||||||
void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg);
|
void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg);
|
||||||
|
|
||||||
#if LWIP_IPV6
|
|
||||||
struct raw_pcb * raw_new_ip6 (u8_t proto);
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
|
|
||||||
/* The following functions are the lower layer interface to RAW. */
|
/* The following functions are the lower layer interface to RAW. */
|
||||||
u8_t raw_input (struct pbuf *p, struct netif *inp);
|
u8_t raw_input (struct pbuf *p, struct netif *inp);
|
||||||
#define raw_init() /* Compatibility define, no init needed. */
|
#define raw_init() /* Compatibility define, no init needed. */
|
||||||
|
|
||||||
|
/* for compatibility with older implementation */
|
||||||
|
#define raw_new_ip6(proto) raw_new_ip_type(IPADDR_TYPE_V6, proto)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user