net/ipfwd: Support ICMP error reply when forwarding IPv4
Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
parent
da6ab79d65
commit
f416fd86bb
@ -37,6 +37,7 @@
|
||||
#include "netdev/netdev.h"
|
||||
#include "utils/utils.h"
|
||||
#include "sixlowpan/sixlowpan.h"
|
||||
#include "icmp/icmp.h"
|
||||
#include "ipforward/ipforward.h"
|
||||
#include "nat/nat.h"
|
||||
#include "devif/devif.h"
|
||||
@ -148,12 +149,6 @@ static int ipv4_decr_ttl(FAR struct ipv4_hdr_s *ipv4)
|
||||
ttl = (int)ipv4->ttl - 1;
|
||||
if (ttl <= 0)
|
||||
{
|
||||
#ifdef CONFIG_NET_ICMP
|
||||
/* Return an ICMP error packet back to the sender. */
|
||||
|
||||
# warning Missing logic
|
||||
#endif
|
||||
|
||||
/* Return zero which must cause the packet to be dropped */
|
||||
|
||||
return 0;
|
||||
@ -317,7 +312,8 @@ static int ipv4_dev_forward(FAR struct net_driver_s *dev,
|
||||
/* Try NAT outbound, rule matching will be performed in NAT module. */
|
||||
|
||||
ret = ipv4_nat_outbound(fwd->f_dev,
|
||||
(FAR struct ipv4_hdr_s *)fwd->f_iob->io_data);
|
||||
(FAR struct ipv4_hdr_s *)fwd->f_iob->io_data,
|
||||
NAT_MANIP_SRC);
|
||||
if (ret < 0)
|
||||
{
|
||||
nwarn("WARNING: Performing NAT outbound failed, dropping!\n");
|
||||
@ -444,6 +440,10 @@ int ipv4_forward(FAR struct net_driver_s *dev, FAR struct ipv4_hdr_s *ipv4)
|
||||
in_addr_t srcipaddr;
|
||||
FAR struct net_driver_s *fwddev;
|
||||
int ret;
|
||||
#ifdef CONFIG_NET_ICMP
|
||||
int icmp_reply_type;
|
||||
int icmp_reply_code;
|
||||
#endif /* CONFIG_NET_ICMP */
|
||||
|
||||
/* Search for a device that can forward this packet. */
|
||||
|
||||
@ -454,7 +454,8 @@ int ipv4_forward(FAR struct net_driver_s *dev, FAR struct ipv4_hdr_s *ipv4)
|
||||
if (fwddev == NULL)
|
||||
{
|
||||
nwarn("WARNING: Not routable\n");
|
||||
return (ssize_t)-ENETUNREACH;
|
||||
ret = -ENETUNREACH;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* Check if we are forwarding on the same device that we received the
|
||||
@ -505,8 +506,48 @@ int ipv4_forward(FAR struct net_driver_s *dev, FAR struct ipv4_hdr_s *ipv4)
|
||||
|
||||
drop:
|
||||
ipv4_dropstats(ipv4);
|
||||
|
||||
#ifdef CONFIG_NET_ICMP
|
||||
/* Reply ICMP to the sender for particular errors. */
|
||||
|
||||
switch (ret)
|
||||
{
|
||||
case -ENETUNREACH:
|
||||
icmp_reply_type = ICMP_DEST_UNREACHABLE;
|
||||
icmp_reply_code = ICMP_NET_UNREACH;
|
||||
goto reply;
|
||||
|
||||
case -EFBIG:
|
||||
icmp_reply_type = ICMP_DEST_UNREACHABLE;
|
||||
icmp_reply_code = ICMP_FRAG_NEEDED;
|
||||
goto reply;
|
||||
|
||||
case -EMULTIHOP:
|
||||
icmp_reply_type = ICMP_TIME_EXCEEDED;
|
||||
icmp_reply_code = 0;
|
||||
goto reply;
|
||||
|
||||
default:
|
||||
break; /* We don't know how to reply, just go on (to drop). */
|
||||
}
|
||||
#endif /* CONFIG_NET_ICMP */
|
||||
|
||||
dev->d_len = 0;
|
||||
return ret;
|
||||
|
||||
#ifdef CONFIG_NET_ICMP
|
||||
reply:
|
||||
# ifdef CONFIG_NET_NAT
|
||||
/* Before we reply ICMP, call NAT outbound to try to translate destination
|
||||
* address & port back to original status.
|
||||
*/
|
||||
|
||||
ipv4_nat_outbound(dev, ipv4, NAT_MANIP_DST);
|
||||
# endif /* CONFIG_NET_NAT */
|
||||
|
||||
icmp_reply(dev, icmp_reply_type, icmp_reply_code);
|
||||
return OK;
|
||||
#endif /* CONFIG_NET_ICMP */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -76,20 +76,6 @@
|
||||
# define L4_MAXHDRLEN ICMP_HDRLEN
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* NAT IP/Port manipulate type, to indicate whether to manipulate source or
|
||||
* destination IP/Port in a packet.
|
||||
*/
|
||||
|
||||
enum nat_manip_type_e
|
||||
{
|
||||
NAT_MANIP_SRC,
|
||||
NAT_MANIP_DST
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
@ -790,6 +776,7 @@ int ipv4_nat_inbound(FAR struct net_driver_s *dev,
|
||||
* Input Parameters:
|
||||
* dev - The device on which the packet will be sent.
|
||||
* ipv4 - Points to the IPv4 header to be filled into dev->d_buf later.
|
||||
* manip_type - Whether local IP/Port is in source or destination.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero is returned if NAT is successfully applied, or is not enabled for
|
||||
@ -799,20 +786,22 @@ int ipv4_nat_inbound(FAR struct net_driver_s *dev,
|
||||
****************************************************************************/
|
||||
|
||||
int ipv4_nat_outbound(FAR struct net_driver_s *dev,
|
||||
FAR struct ipv4_hdr_s *ipv4)
|
||||
FAR struct ipv4_hdr_s *ipv4,
|
||||
enum nat_manip_type_e manip_type)
|
||||
{
|
||||
/* We only process packets targeting at NAT device but not targeting at the
|
||||
* address assigned to the device.
|
||||
*/
|
||||
|
||||
if (IFF_IS_NAT(dev->d_flags) &&
|
||||
!net_ipv4addr_hdrcmp(ipv4->srcipaddr, &dev->d_ipaddr) &&
|
||||
!net_ipv4addr_hdrcmp(ipv4->destipaddr, &dev->d_ipaddr))
|
||||
{
|
||||
/* TODO: Skip broadcast? */
|
||||
|
||||
FAR struct ipv4_nat_entry *entry =
|
||||
ipv4_nat_outbound_internal(dev, ipv4, NAT_MANIP_SRC);
|
||||
if (!entry)
|
||||
ipv4_nat_outbound_internal(dev, ipv4, manip_type);
|
||||
if (manip_type == NAT_MANIP_SRC && !entry)
|
||||
{
|
||||
/* Outbound entry creation failed, should have entry. */
|
||||
|
||||
|
@ -71,6 +71,16 @@ struct ipv4_nat_entry
|
||||
uint32_t expire_time; /* The expiration time of this entry. */
|
||||
};
|
||||
|
||||
/* NAT IP/Port manipulate type, to indicate whether to manipulate source or
|
||||
* destination IP/Port in a packet.
|
||||
*/
|
||||
|
||||
enum nat_manip_type_e
|
||||
{
|
||||
NAT_MANIP_SRC,
|
||||
NAT_MANIP_DST
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
@ -147,6 +157,7 @@ int ipv4_nat_inbound(FAR struct net_driver_s *dev,
|
||||
* Input Parameters:
|
||||
* dev - The device on which the packet will be sent.
|
||||
* ipv4 - Points to the IPv4 header to be filled into dev->d_buf later.
|
||||
* manip_type - Whether local IP/Port is in source or destination.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero is returned if NAT is successfully applied, or is not enabled for
|
||||
@ -156,7 +167,8 @@ int ipv4_nat_inbound(FAR struct net_driver_s *dev,
|
||||
****************************************************************************/
|
||||
|
||||
int ipv4_nat_outbound(FAR struct net_driver_s *dev,
|
||||
FAR struct ipv4_hdr_s *ipv4);
|
||||
FAR struct ipv4_hdr_s *ipv4,
|
||||
enum nat_manip_type_e manip_type);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipv4_nat_port_inuse
|
||||
|
Loading…
Reference in New Issue
Block a user