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:
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
* sockets.c, opt.h: (bug #30185): added LWIP_FIONREAD_LINUXMODE that makes
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;
#ifdef LWIP_HOOK_IP4_ROUTE
netif = LWIP_HOOK_IP4_ROUTE(dest);
if (netif != NULL) {
return netif;
}
#endif
/* iterate through netifs */
for(netif = netif_list; netif != NULL; netif = netif->next) {
for (netif = netif_list; netif != NULL; netif = netif->next) {
/* network mask matches? */
if (netif_is_up(netif)) {
if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
@ -135,6 +142,41 @@ ip_route(ip_addr_t *dest)
}
#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
* 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;
if (!ip_canforward(p)) {
goto return_noroute;
}
/* RFC3927 2.7: do not forward link-local addresses */
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",
@ -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())));
goto return_noroute;
}
#if !IP_FORWARD_ALLOW_TX_ON_RX_NETIF
/* Do not forward packets onto the same network interface on which
* they arrived. */
if (netif == inp) {
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
goto return_noroute;
}
#endif /* IP_FORWARD_ALLOW_TX_ON_RX_NETIF */
/* decrement TTL */
IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1);
@ -252,6 +300,13 @@ ip_input(struct pbuf *p, struct netif *inp)
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 */
iphdr_hlen = IPH_HL(iphdr);
/* calculate IP header length in bytes */

View File

@ -593,6 +593,17 @@
#define IP_SOF_BROADCAST_RECV 0
#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 ----------
@ -2056,6 +2067,34 @@
#define LWIP_IPV6_DHCP6 0
#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 ----------

View File

@ -76,6 +76,10 @@ typedef enum {
#define PBUF_FLAG_IS_CUSTOM 0x02U
/** indicates this pbuf is UDP multicast to be looped back */
#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 {
/** 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 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 */
/** 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? */
} else if (ip_addr_ismulticast(ipaddr)) {
/* Hash IP multicast address to MAC address.*/
mcastaddr.addr[0] = 0x01;
mcastaddr.addr[1] = 0x00;
mcastaddr.addr[2] = 0x5e;
mcastaddr.addr[0] = LL_MULTICAST_ADDR_0;
mcastaddr.addr[1] = LL_MULTICAST_ADDR_1;
mcastaddr.addr[2] = LL_MULTICAST_ADDR_2;
mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
mcastaddr.addr[4] = ip4_addr3(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));
#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) {
#if LWIP_ARP
/* IP packet? */