From aea7062223108374586af7f6cec339e4f81ea1c9 Mon Sep 17 00:00:00 2001 From: David van Moolenbroek Date: Wed, 4 Jan 2017 22:23:29 +0000 Subject: [PATCH] raw: extend support for connected sockets The support for connecting raw sockets is extended to match the support for UDP sockets, while keeping the current API unchanged: - for connected sockets, filter incoming packets on source address; - use a flag to indicate whether a socket is connected, at no extra memory cost; the application may check this flag if needed; - added raw_disconnect(), which so far existed in documentation only. --- src/core/raw.c | 30 ++++++++++++++++++++++++++++-- src/include/lwip/raw.h | 6 ++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/core/raw.c b/src/core/raw.c index 93c65473..6d5746da 100644 --- a/src/core/raw.c +++ b/src/core/raw.c @@ -65,7 +65,7 @@ static struct raw_pcb *raw_pcbs; static u8_t -raw_input_match(struct raw_pcb *pcb, u8_t broadcast) +raw_input_local_match(struct raw_pcb *pcb, u8_t broadcast) { LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */ @@ -157,7 +157,9 @@ 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) && raw_input_match(pcb, broadcast)) { + if ((pcb->protocol == proto) && raw_input_local_match(pcb, broadcast) && + (((pcb->flags & RAW_FLAGS_CONNECTED) == 0) || + ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()))) { /* receive callback function available? */ if (pcb->recv != NULL) { #ifndef LWIP_NOASSERT @@ -237,9 +239,33 @@ raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr) return ERR_VAL; } ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr); + pcb->flags |= RAW_FLAGS_CONNECTED; return ERR_OK; } +/** + * @ingroup raw_raw + * Disconnect a RAW PCB. + * + * @param pcb the raw pcb to disconnect. + */ +void +raw_disconnect(struct raw_pcb *pcb) +{ + /* reset remote address association */ +#if LWIP_IPV4 && LWIP_IPV6 + if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { + ip_addr_copy(pcb->remote_ip, *IP_ANY_TYPE); + } else { +#endif + ip_addr_set_any(IP_IS_V6_VAL(pcb->remote_ip), &pcb->remote_ip); +#if LWIP_IPV4 && LWIP_IPV6 + } +#endif + /* mark PCB as unconnected */ + pcb->flags &= ~RAW_FLAGS_CONNECTED; +} + /** * @ingroup raw_raw * Set the callback function for received packets that match the diff --git a/src/include/lwip/raw.h b/src/include/lwip/raw.h index 30aa1471..00027a86 100644 --- a/src/include/lwip/raw.h +++ b/src/include/lwip/raw.h @@ -52,6 +52,8 @@ extern "C" { #endif +#define RAW_FLAGS_CONNECTED 0x01U + struct raw_pcb; /** Function prototype for raw pcb receive callback functions. @@ -75,6 +77,7 @@ struct raw_pcb { struct raw_pcb *next; u8_t protocol; + u8_t flags; /** receive callback function */ raw_recv_fn recv; @@ -94,12 +97,15 @@ 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); +void raw_disconnect (struct raw_pcb *pcb); err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr); 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); +#define raw_flags(pcb) ((pcb)->flags) + /* 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. */