diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 1a58a6f..9253b34 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -376,6 +376,7 @@ drop: int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { struct iphdr *iph; + struct in_device *in_dev; u32 len; /* When the interface is in promisc. mode, drop all the crap @@ -415,6 +416,28 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, iph = ip_hdr(skb); + /* + * RFC792 Page 6 + * If the gateway processing a datagram finds the time to live field + * is zero it must discard the datagram. The gateway may also notify + * the source host via the time exceeded message. + */ + if ((in_dev = in_dev_get(dev)) != NULL) { + if (iph->ttl == 0 && IPV4_DEVCONF(in_dev->cnf, FORWARDING)) { + if (likely(skb->dst == NULL)) { + int err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, + skb->dev); + if (unlikely(err)) + goto inhdr_error; + } + icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0); + goto inhdr_error; + } + } else { + IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS); + goto drop; + } + if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) goto inhdr_error; diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index f171e8d..fee40f9 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -103,6 +103,19 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt goto err; /* + * RFC4443 3.3 + * If a router receives a packet with a Hop Limit of zero, or if a + * router decrements a packet's Hop Limit to zero, it MUST discard the + * packet and originate an ICMPv6 Time Exceeded message with Code 0 to + * the source of the packet. + */ + if (hdr->hop_limit == 0 && idev->cnf.forwarding) { + icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, + 0, skb->dev); + goto err; + } + + /* * RFC4291 2.5.3 * A packet received on an interface with a destination address * of loopback must be dropped.