mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-11-04 23:29:25 +00:00
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:
parent
860072aaaf
commit
78ac382fdf
@ -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.
|
||||
|
@ -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 */
|
||||
|
@ -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 ----------
|
||||
|
@ -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 */
|
||||
|
@ -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(ðhdr->dest, ðbroadcast)) {
|
||||
/* mark the pbuf as link-layer broadcast */
|
||||
p->flags |= PBUF_FLAG_LLBCAST;
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
#if LWIP_ARP
|
||||
/* IP packet? */
|
||||
|
Loading…
Reference in New Issue
Block a user