bug #33634 ip_forward() have a faulty behaviour: Added pbuf flags to mark incoming packets as link-layer broadcast/multicast. Also added code to allow ip_forward() to forward non-broadcast packets to the input netif (set IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1).

This commit is contained in:
Simon Goldschmidt 2011-07-21 21:47:25 +02:00
parent 860072aaaf
commit 78ac382fdf
5 changed files with 127 additions and 4 deletions

View File

@ -6,6 +6,12 @@ HISTORY
++ New features: ++ New features:
2011-07-21: Simon Goldschmidt (patch by hanhui)
* ip4.c, etharp.c, pbuf.h: bug #33634 ip_forward() have a faulty behaviour:
Added pbuf flags to mark incoming packets as link-layer broadcast/multicast.
Also added code to allow ip_forward() to forward non-broadcast packets to
the input netif (set IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1).
2011-07-21: Simon Goldschmidt 2011-07-21: Simon Goldschmidt
* sockets.c, opt.h: (bug #30185): added LWIP_FIONREAD_LINUXMODE that makes * sockets.c, opt.h: (bug #30185): added LWIP_FIONREAD_LINUXMODE that makes
ioctl/FIONREAD return the size of the next pending datagram. ioctl/FIONREAD return the size of the next pending datagram.

View File

@ -113,8 +113,15 @@ ip_route(ip_addr_t *dest)
{ {
struct netif *netif; struct netif *netif;
#ifdef LWIP_HOOK_IP4_ROUTE
netif = LWIP_HOOK_IP4_ROUTE(dest);
if (netif != NULL) {
return netif;
}
#endif
/* iterate through netifs */ /* iterate through netifs */
for(netif = netif_list; netif != NULL; netif = netif->next) { for (netif = netif_list; netif != NULL; netif = netif->next) {
/* network mask matches? */ /* network mask matches? */
if (netif_is_up(netif)) { if (netif_is_up(netif)) {
if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) { if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
@ -135,6 +142,41 @@ ip_route(ip_addr_t *dest)
} }
#if IP_FORWARD #if IP_FORWARD
/**
* Determine whether an IP address is in a reserved set of addresses
* that may not be forwarded, or whether datagrams to that destination
* may be forwarded.
* @param p the packet to forward
* @param dest the destination IP address
* @return 1: can forward 0: discard
*/
static int
ip_canforward(struct pbuf *p)
{
u32_t addr = ip4_addr_get_u32(ip_current_dest_addr());
if (p->flags & PBUF_FLAG_LLBCAST) {
/* don't route link-layer broadcasts */
return 0;
}
if ((p->flags & PBUF_FLAG_LLMCAST) && !IP_MULTICAST(addr)) {
/* don't route link-layer multicasts unless the destination address is an IP
multicast address */
return 0;
}
if (IP_EXPERIMENTAL(addr)) {
return 0;
}
if (IP_CLASSA(addr)) {
u32_t net = addr & IP_CLASSA_NET;
if ((net == 0) || (net == (IP_LOOPBACKNET << IP_CLASSA_NSHIFT))) {
/* don't route loopback packets */
return 0;
}
}
return 1;
}
/** /**
* Forwards an IP packet. It finds an appropriate route for the * Forwards an IP packet. It finds an appropriate route for the
* packet, decrements the TTL value of the packet, adjusts the * packet, decrements the TTL value of the packet, adjusts the
@ -151,6 +193,10 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
PERF_START; PERF_START;
if (!ip_canforward(p)) {
goto return_noroute;
}
/* RFC3927 2.7: do not forward link-local addresses */ /* RFC3927 2.7: do not forward link-local addresses */
if (ip_addr_islinklocal(ip_current_dest_addr())) { if (ip_addr_islinklocal(ip_current_dest_addr())) {
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
@ -167,12 +213,14 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
ip4_addr3_16(ip_current_dest_addr()), ip4_addr4_16(ip_current_dest_addr()))); ip4_addr3_16(ip_current_dest_addr()), ip4_addr4_16(ip_current_dest_addr())));
goto return_noroute; goto return_noroute;
} }
#if !IP_FORWARD_ALLOW_TX_ON_RX_NETIF
/* Do not forward packets onto the same network interface on which /* Do not forward packets onto the same network interface on which
* they arrived. */ * they arrived. */
if (netif == inp) { if (netif == inp) {
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n")); LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
goto return_noroute; goto return_noroute;
} }
#endif /* IP_FORWARD_ALLOW_TX_ON_RX_NETIF */
/* decrement TTL */ /* decrement TTL */
IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1); IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1);
@ -252,6 +300,13 @@ ip_input(struct pbuf *p, struct netif *inp)
return ERR_OK; return ERR_OK;
} }
#ifdef LWIP_HOOK_IP4_INPUT
if (LWIP_HOOK_IP4_INPUT(p, inp)) {
/* the packet has been eaten */
return ERR_OK;
}
#endif
/* obtain IP header length in number of 32-bit words */ /* obtain IP header length in number of 32-bit words */
iphdr_hlen = IPH_HL(iphdr); iphdr_hlen = IPH_HL(iphdr);
/* calculate IP header length in bytes */ /* calculate IP header length in bytes */

View File

@ -593,6 +593,17 @@
#define IP_SOF_BROADCAST_RECV 0 #define IP_SOF_BROADCAST_RECV 0
#endif #endif
/**
* IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1: allow ip_forward() to send packets back
* out on the netif where it was received. This should only be used for
* wireless networks.
* ATTENTION: When this is 1, make sure your netif driver correctly marks incoming
* link-layer-broadcast/multicast packets as such using the corresponding pbuf flags!
*/
#ifndef IP_FORWARD_ALLOW_TX_ON_RX_NETIF
#define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0
#endif
/* /*
---------------------------------- ----------------------------------
---------- ICMP options ---------- ---------- ICMP options ----------
@ -2056,6 +2067,34 @@
#define LWIP_IPV6_DHCP6 0 #define LWIP_IPV6_DHCP6 0
#endif #endif
/*
---------------------------------------
---------- Hook options ---------------
---------------------------------------
*/
/* Hooks are undefined by default, define them to a function if you need them. */
/**
* LWIP_HOOK_IP4_INPUT(pbuf, input_netif):
* - called from ip_input() (IPv4)
* - pbuf: received struct pbuf passed to ip_input()
* - input_netif: struct netif on which the packet has been received
* Return values:
* - 0: Hook has not consumed the packet, packet is processed as normal
* - != 0: Hook has consumed the packet.
* If the hook consumed the packet, 'pbuf' is in the responsibility of the hook
* (i.e. free it when done).
*/
/**
* LWIP_HOOK_IP4_ROUTE(dest):
* - called from ip_route() (IPv4)
* - dest: destination IPv4 address
* Returns the destination netif or NULL if no destination netif is found. In
* that case, ip_route() continues as normal.
*/
/* /*
--------------------------------------- ---------------------------------------
---------- Debugging options ---------- ---------- Debugging options ----------

View File

@ -76,6 +76,10 @@ typedef enum {
#define PBUF_FLAG_IS_CUSTOM 0x02U #define PBUF_FLAG_IS_CUSTOM 0x02U
/** indicates this pbuf is UDP multicast to be looped back */ /** indicates this pbuf is UDP multicast to be looped back */
#define PBUF_FLAG_MCASTLOOP 0x04U #define PBUF_FLAG_MCASTLOOP 0x04U
/** indicates this pbuf was received as link-level broadcast */
#define PBUF_FLAG_LLBCAST 0x08U
/** indicates this pbuf was received as link-level multicast */
#define PBUF_FLAG_LLMCAST 0x10U
struct pbuf { struct pbuf {
/** next pbuf in singly linked pbuf chain */ /** next pbuf in singly linked pbuf chain */

View File

@ -66,6 +66,11 @@
const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
const struct eth_addr ethzero = {{0,0,0,0,0,0}}; const struct eth_addr ethzero = {{0,0,0,0,0,0}};
/** The 24-bit IANA multicast OUI is 01-00-5e: */
#define LL_MULTICAST_ADDR_0 0x01
#define LL_MULTICAST_ADDR_1 0x00
#define LL_MULTICAST_ADDR_2 0x5e
#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */ #if LWIP_ARP /* don't build if not configured for use in lwipopts.h */
/** the time an ARP entry stays valid after its last update, /** the time an ARP entry stays valid after its last update,
@ -932,9 +937,9 @@ etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr)
/* multicast destination IP address? */ /* multicast destination IP address? */
} else if (ip_addr_ismulticast(ipaddr)) { } else if (ip_addr_ismulticast(ipaddr)) {
/* Hash IP multicast address to MAC address.*/ /* Hash IP multicast address to MAC address.*/
mcastaddr.addr[0] = 0x01; mcastaddr.addr[0] = LL_MULTICAST_ADDR_0;
mcastaddr.addr[1] = 0x00; mcastaddr.addr[1] = LL_MULTICAST_ADDR_1;
mcastaddr.addr[2] = 0x5e; mcastaddr.addr[2] = LL_MULTICAST_ADDR_2;
mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f; mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
mcastaddr.addr[4] = ip4_addr3(ipaddr); mcastaddr.addr[4] = ip4_addr3(ipaddr);
mcastaddr.addr[5] = ip4_addr4(ipaddr); mcastaddr.addr[5] = ip4_addr4(ipaddr);
@ -1308,6 +1313,20 @@ ethernet_input(struct pbuf *p, struct netif *netif)
netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, htons(type)); netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, htons(type));
#endif /* LWIP_ARP_FILTER_NETIF*/ #endif /* LWIP_ARP_FILTER_NETIF*/
if (ethhdr->dest.addr[0] & 1) {
/* this might be a multicast or broadcast packet */
if (ethhdr->dest.addr[0] == LL_MULTICAST_ADDR_0) {
if ((ethhdr->dest.addr[1] == LL_MULTICAST_ADDR_1) &&
(ethhdr->dest.addr[2] == LL_MULTICAST_ADDR_2)) {
/* mark the pbuf as link-layer multicast */
p->flags |= PBUF_FLAG_LLMCAST;
}
} else if (eth_addr_cmp(&ethhdr->dest, &ethbroadcast)) {
/* mark the pbuf as link-layer broadcast */
p->flags |= PBUF_FLAG_LLBCAST;
}
}
switch (type) { switch (type) {
#if LWIP_ARP #if LWIP_ARP
/* IP packet? */ /* IP packet? */