Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9ce8ade0 authored by Thomas Graf's avatar Thomas Graf Committed by David S. Miller
Browse files

[IPv6] route: Fix prohibit and blackhole routing decision



Lookups resolving to ip6_blk_hole_entry must result in silently
discarding the packets whereas an ip6_pkt_prohibit_entry is
supposed to cause an ICMPV6_ADM_PROHIBITED message to be sent.

Thanks to Kim Nordlund <kim.nordlund@nokia.com> for noticing
this bug.

Signed-off-by: default avatarThomas Graf <tgraf@suug.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3a31b9d2
Loading
Loading
Loading
Loading
+31 −6
Original line number Diff line number Diff line
@@ -94,6 +94,9 @@ static int ip6_dst_gc(void);

static int		ip6_pkt_discard(struct sk_buff *skb);
static int		ip6_pkt_discard_out(struct sk_buff *skb);
static int		ip6_pkt_prohibit(struct sk_buff *skb);
static int		ip6_pkt_prohibit_out(struct sk_buff *skb);
static int		ip6_pkt_blk_hole(struct sk_buff *skb);
static void		ip6_link_failure(struct sk_buff *skb);
static void		ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu);

@@ -150,8 +153,8 @@ struct rt6_info ip6_prohibit_entry = {
			.obsolete	= -1,
			.error		= -EACCES,
			.metrics	= { [RTAX_HOPLIMIT - 1] = 255, },
			.input		= ip6_pkt_discard,
			.output		= ip6_pkt_discard_out,
			.input		= ip6_pkt_prohibit,
			.output		= ip6_pkt_prohibit_out,
			.ops		= &ip6_dst_ops,
			.path		= (struct dst_entry*)&ip6_prohibit_entry,
		}
@@ -170,8 +173,8 @@ struct rt6_info ip6_blk_hole_entry = {
			.obsolete	= -1,
			.error		= -EINVAL,
			.metrics	= { [RTAX_HOPLIMIT - 1] = 255, },
			.input		= ip6_pkt_discard,
			.output		= ip6_pkt_discard_out,
			.input		= ip6_pkt_blk_hole,
			.output		= ip6_pkt_blk_hole,
			.ops		= &ip6_dst_ops,
			.path		= (struct dst_entry*)&ip6_blk_hole_entry,
		}
@@ -1742,24 +1745,46 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg)
 *	Drop the packet on the floor
 */

static int ip6_pkt_discard(struct sk_buff *skb)
static inline int ip6_pkt_drop(struct sk_buff *skb, int code)
{
	int type = ipv6_addr_type(&skb->nh.ipv6h->daddr);
	if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED)
		IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS);

	IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
	icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev);
	icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev);
	kfree_skb(skb);
	return 0;
}

static int ip6_pkt_discard(struct sk_buff *skb)
{
	return ip6_pkt_drop(skb, ICMPV6_NOROUTE);
}

static int ip6_pkt_discard_out(struct sk_buff *skb)
{
	skb->dev = skb->dst->dev;
	return ip6_pkt_discard(skb);
}

static int ip6_pkt_prohibit(struct sk_buff *skb)
{
	return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED);
}

static int ip6_pkt_prohibit_out(struct sk_buff *skb)
{
	skb->dev = skb->dst->dev;
	return ip6_pkt_prohibit(skb);
}

static int ip6_pkt_blk_hole(struct sk_buff *skb)
{
	kfree_skb(skb);
	return 0;
}

/*
 *	Allocate a dst for local (unicast / anycast) address.
 */