raw.c, udp.c, init.c, opt.h, ip.h, sockets.h: bug #26309: Implement the SO(F)_BROADCAST filter for all API layers. Avoid the unindented reception of broadcast packets even when this option wasn't set. Port maintainers which want to enable this filter have to set IP_SOF_BROADCAST=1 in opt.h. If you want this option also filter broadcast on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1 in opt.h.

This commit is contained in:
fbernon 2009-04-29 12:42:43 +00:00
parent 42c59e1079
commit d4ecb23015
7 changed files with 84 additions and 23 deletions

View File

@ -95,6 +95,14 @@ HISTORY
++ Bugfixes:
2009-04-29 Frédéric Bernon
* raw.c, udp.c, init.c, opt.h, ip.h, sockets.h: bug #26309: Implement the
SO(F)_BROADCAST filter for all API layers. Avoid the unindented reception
of broadcast packets even when this option wasn't set. Port maintainers
which want to enable this filter have to set IP_SOF_BROADCAST=1 in opt.h.
If you want this option also filter broadcast on recv operations, you also
have to set IP_SOF_BROADCAST_RECV=1 in opt.h.
2009-04-28 Simon Goldschmidt, Jakob Stoklund Olesen
* dhcp.c: patch #6721: Some small fixes to DHCP and DHCP/AUTOIP cooperation

View File

@ -61,6 +61,9 @@
#ifndef BYTE_ORDER
#error "BYTE_ORDER is not defined, you have to define it in your cc.h"
#endif
#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV)
#error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h"
#endif
#if (!LWIP_ARP && ARP_QUEUEING)
#error "If you want to use ARP Queueing, you have to define LWIP_ARP=1 in your lwipopts.h"
#endif

View File

@ -93,24 +93,29 @@ raw_input(struct pbuf *p, struct netif *inp)
/* this allows multiple pcbs to match against the packet by design */
while ((eaten == 0) && (pcb != NULL)) {
if (pcb->protocol == proto) {
/* receive callback function available? */
if (pcb->recv != NULL) {
/* the receive callback function did not eat the packet? */
if (pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)) != 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;
#if IP_SOF_BROADCAST_RECV
/* broadcast filter? */
if ((pcb->so_options & SOF_BROADCAST) || !ip_addr_isbroadcast(&(iphdr->dest), inp))
#endif /* IP_SOF_BROADCAST_RECV */
{
/* receive callback function available? */
if (pcb->recv != NULL) {
/* the receive callback function did not eat the packet? */
if (pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)) != 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;
}
}
}
/* no receive callback function was set for this raw PCB */
}
/* no receive callback function was set for this raw PCB */
/* drop the packet */
}
prev = pcb;
@ -228,7 +233,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
return ERR_MEM;
}
}
if ((netif = ip_route(ipaddr)) == NULL) {
LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_sendto: No route to 0x%"X32_F"\n", ipaddr->addr));
/* free any temporary header pbuf allocated by pbuf_header() */
@ -238,6 +243,18 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
return ERR_RTE;
}
#if IP_SOF_BROADCAST
/* broadcast filter? */
if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(ipaddr, netif) ) {
LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
/* free any temporary header pbuf allocated by pbuf_header() */
if (q != p) {
pbuf_free(q);
}
return ERR_VAL;
}
#endif /* IP_SOF_BROADCAST */
if (ip_addr_isany(&pcb->local_ip)) {
/* use outgoing network interface IP address as source address */
src_ip = &(netif->ip_addr);

View File

@ -90,6 +90,7 @@ udp_input(struct pbuf *p, struct netif *inp)
struct ip_hdr *iphdr;
u16_t src, dest;
u8_t local_match;
u8_t broadcast;
PERF_START;
@ -112,6 +113,9 @@ udp_input(struct pbuf *p, struct netif *inp)
udphdr = (struct udp_hdr *)p->payload;
/* is broadcast packet ? */
broadcast = ip_addr_isbroadcast(&(iphdr->dest), inp);
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len));
/* convert src and dest ports to host byte order */
@ -169,16 +173,20 @@ udp_input(struct pbuf *p, struct netif *inp)
/* compare PCB local addr+port to UDP destination addr+port */
if ((pcb->local_port == dest) &&
(ip_addr_isany(&pcb->local_ip) ||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)) ||
((!broadcast && ip_addr_isany(&pcb->local_ip)) ||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)) ||
#if LWIP_IGMP
ip_addr_ismulticast(&(iphdr->dest)) ||
#endif /* LWIP_IGMP */
ip_addr_isbroadcast(&(iphdr->dest), inp))) {
#if IP_SOF_BROADCAST_RECV
(broadcast && (pcb->so_options & SOF_BROADCAST)))) {
#else /* IP_SOF_BROADCAST_RECV */
(broadcast))) {
#endif /* IP_SOF_BROADCAST_RECV */
local_match = 1;
if ((uncon_pcb == NULL) &&
((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) {
/* the first unconnected matching PCB */
/* the first unconnected matching PCB */
uncon_pcb = pcb;
}
}
@ -286,7 +294,7 @@ udp_input(struct pbuf *p, struct netif *inp)
#if LWIP_ICMP
/* No match was found, send ICMP destination port unreachable unless
destination address was broadcast/multicast. */
if (!ip_addr_isbroadcast(&iphdr->dest, inp) &&
if (!broadcast &&
!ip_addr_ismulticast(&iphdr->dest)) {
/* move payload pointer back to ip header */
pbuf_header(p, (IPH_HL(iphdr) * 4) + UDP_HLEN);
@ -400,6 +408,14 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
err_t err;
struct pbuf *q; /* q will be sent down the stack */
#if IP_SOF_BROADCAST
/* broadcast filter? */
if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(dst_ip, netif) ) {
LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
return ERR_VAL;
}
#endif /* IP_SOF_BROADCAST */
/* if the PCB is not yet bound to a port, bind it here */
if (pcb->local_port == 0) {
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | 2, ("udp_send: not yet bound to a port, binding now\n"));

View File

@ -107,7 +107,7 @@ struct ip_pcb {
#define SOF_REUSEADDR (u16_t)0x0004U /* allow local address reuse */
#define SOF_KEEPALIVE (u16_t)0x0008U /* keep connections alive */
#define SOF_DONTROUTE (u16_t)0x0010U /* just use interface addresses */
#define SOF_BROADCAST (u16_t)0x0020U /* permit sending of broadcast msgs */
#define SOF_BROADCAST (u16_t)0x0020U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
#define SOF_USELOOPBACK (u16_t)0x0040U /* bypass hardware when possible */
#define SOF_LINGER (u16_t)0x0080U /* linger on close if data present */
#define SOF_OOBINLINE (u16_t)0x0100U /* leave received OOB data in line */

View File

@ -450,6 +450,23 @@
#define IP_DEFAULT_TTL 255
#endif
/**
* IP_SOF_BROADCAST=1: Use the SOF_BROADCAST field to enable broadcast
* filter per pcb on udp and raw send operations. To enable broadcast filter
* on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1.
*/
#ifndef IP_SOF_BROADCAST
#define IP_SOF_BROADCAST 0
#endif
/**
* IP_SOF_BROADCAST_RECV (requires IP_SOF_BROADCAST=1) enable the broadcast
* filter on recv operations.
*/
#ifndef IP_SOF_BROADCAST_RECV
#define IP_SOF_BROADCAST_RECV 0
#endif
/*
----------------------------------
---------- ICMP options ----------

View File

@ -77,7 +77,7 @@ struct sockaddr {
#define SO_REUSEADDR 0x0004 /* Unimplemented: allow local address reuse */
#define SO_KEEPALIVE 0x0008 /* keep connections alive */
#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */
#define SO_BROADCAST 0x0020 /* Unimplemented: permit sending of broadcast msgs */
#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */
#define SO_LINGER 0x0080 /* linger on close if data present */
#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */