diff options
author | Thomas Graf <tgraf@suug.ch> | 2006-10-18 20:46:54 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-10-18 20:46:54 -0700 |
commit | 9ce8ade015a3f82dbdf856df7a685878dd1cc0e1 (patch) | |
tree | daa2d5f9b335ef9762d9aaa3b91cd07077006640 /net/ipv6/route.c | |
parent | 3a31b9d2f2d98667832e87fa1853754ff062d6ef (diff) | |
download | op-kernel-dev-9ce8ade015a3f82dbdf856df7a685878dd1cc0e1.zip op-kernel-dev-9ce8ade015a3f82dbdf856df7a685878dd1cc0e1.tar.gz |
[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: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index aa96be8..5c00ca4 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -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. */ |