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 */
|
||||
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
|
||||
* 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;
|
||||
s16_t proto;
|
||||
u8_t eaten = 0;
|
||||
u8_t broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif());
|
||||
|
||||
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 */
|
||||
/* this allows multiple pcbs to match against the packet by design */
|
||||
while ((eaten == 0) && (pcb != NULL)) {
|
||||
if ((pcb->protocol == proto) && IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ip_current_dest_addr()) &&
|
||||
(ip_addr_isany(&pcb->local_ip) ||
|
||||
ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr()))) {
|
||||
#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) {
|
||||
if ((pcb->protocol == proto) && raw_input_match(pcb, broadcast)) {
|
||||
/* receive callback function available? */
|
||||
if (pcb->recv != NULL) {
|
||||
#ifndef LWIP_NOASSERT
|
||||
void* old_payload = p->payload;
|
||||
void* old_payload = p->payload;
|
||||
#endif
|
||||
/* the receive callback function did not eat the packet? */
|
||||
eaten = pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr());
|
||||
if (eaten != 0) {
|
||||
/* receive function ate the packet */
|
||||
p = NULL;
|
||||
eaten = 1;
|
||||
if (prev != NULL) {
|
||||
/* move the pcb to the front of raw_pcbs so that is
|
||||
found faster next time */
|
||||
prev->next = pcb->next;
|
||||
pcb->next = raw_pcbs;
|
||||
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);
|
||||
/* the receive callback function did not eat the packet? */
|
||||
eaten = pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr());
|
||||
if (eaten != 0) {
|
||||
/* receive function ate the packet */
|
||||
p = NULL;
|
||||
eaten = 1;
|
||||
if (prev != NULL) {
|
||||
/* move the pcb to the front of raw_pcbs so that is
|
||||
found faster next time */
|
||||
prev->next = pcb->next;
|
||||
pcb->next = raw_pcbs;
|
||||
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);
|
||||
}
|
||||
/* 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;
|
||||
pcb = pcb->next;
|
||||
}
|
||||
@ -416,31 +448,30 @@ raw_new(u8_t proto)
|
||||
return pcb;
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
/**
|
||||
* Create a RAW PCB for IPv6.
|
||||
*
|
||||
* @return The RAW PCB which was created. NULL if the PCB data structure
|
||||
* 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
|
||||
* (e.g. IP6_NEXTH_ICMP6)
|
||||
*
|
||||
* @see raw_remove()
|
||||
*/
|
||||
struct raw_pcb *
|
||||
raw_new_ip6(u8_t proto)
|
||||
raw_new_ip_type(u8_t type, u8_t proto)
|
||||
{
|
||||
struct raw_pcb *pcb;
|
||||
pcb = raw_new(proto);
|
||||
#if LWIP_IPV4
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
if(pcb != NULL) {
|
||||
IP_SET_TYPE_VAL(pcb->local_ip, IPADDR_TYPE_V6);
|
||||
IP_SET_TYPE_VAL(pcb->remote_ip, IPADDR_TYPE_V6);
|
||||
IP_SET_TYPE_VAL(pcb->local_ip, type);
|
||||
IP_SET_TYPE_VAL(pcb->remote_ip, type);
|
||||
}
|
||||
#endif /* LWIP_IPV4 */
|
||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||
return pcb;
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#endif /* LWIP_RAW */
|
||||
|
@ -83,6 +83,7 @@ struct raw_pcb {
|
||||
/* The following functions is the application layer interface to the
|
||||
RAW code. */
|
||||
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);
|
||||
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);
|
||||
@ -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);
|
||||
|
||||
#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. */
|
||||
u8_t raw_input (struct pbuf *p, struct netif *inp);
|
||||
#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
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user