diff options
author | Thomas Graf <tgraf@suug.ch> | 2006-10-18 23:46:54 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-10-18 23:46:54 -0400 |
commit | 9ce8ade015a3f82dbdf856df7a685878dd1cc0e1 (patch) | |
tree | daa2d5f9b335ef9762d9aaa3b91cd07077006640 /net | |
parent | 3a31b9d2f2d98667832e87fa1853754ff062d6ef (diff) |
[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')
-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 aa96be860e96..5c00ca4fa52c 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -94,6 +94,9 @@ static int ip6_dst_gc(void); | |||
94 | 94 | ||
95 | static int ip6_pkt_discard(struct sk_buff *skb); | 95 | static int ip6_pkt_discard(struct sk_buff *skb); |
96 | static int ip6_pkt_discard_out(struct sk_buff *skb); | 96 | static int ip6_pkt_discard_out(struct sk_buff *skb); |
97 | static int ip6_pkt_prohibit(struct sk_buff *skb); | ||
98 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); | ||
99 | static int ip6_pkt_blk_hole(struct sk_buff *skb); | ||
97 | static void ip6_link_failure(struct sk_buff *skb); | 100 | static void ip6_link_failure(struct sk_buff *skb); |
98 | static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu); | 101 | static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu); |
99 | 102 | ||
@@ -150,8 +153,8 @@ struct rt6_info ip6_prohibit_entry = { | |||
150 | .obsolete = -1, | 153 | .obsolete = -1, |
151 | .error = -EACCES, | 154 | .error = -EACCES, |
152 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | 155 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, |
153 | .input = ip6_pkt_discard, | 156 | .input = ip6_pkt_prohibit, |
154 | .output = ip6_pkt_discard_out, | 157 | .output = ip6_pkt_prohibit_out, |
155 | .ops = &ip6_dst_ops, | 158 | .ops = &ip6_dst_ops, |
156 | .path = (struct dst_entry*)&ip6_prohibit_entry, | 159 | .path = (struct dst_entry*)&ip6_prohibit_entry, |
157 | } | 160 | } |
@@ -170,8 +173,8 @@ struct rt6_info ip6_blk_hole_entry = { | |||
170 | .obsolete = -1, | 173 | .obsolete = -1, |
171 | .error = -EINVAL, | 174 | .error = -EINVAL, |
172 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | 175 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, |
173 | .input = ip6_pkt_discard, | 176 | .input = ip6_pkt_blk_hole, |
174 | .output = ip6_pkt_discard_out, | 177 | .output = ip6_pkt_blk_hole, |
175 | .ops = &ip6_dst_ops, | 178 | .ops = &ip6_dst_ops, |
176 | .path = (struct dst_entry*)&ip6_blk_hole_entry, | 179 | .path = (struct dst_entry*)&ip6_blk_hole_entry, |
177 | } | 180 | } |
@@ -1742,24 +1745,46 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg) | |||
1742 | * Drop the packet on the floor | 1745 | * Drop the packet on the floor |
1743 | */ | 1746 | */ |
1744 | 1747 | ||
1745 | static int ip6_pkt_discard(struct sk_buff *skb) | 1748 | static inline int ip6_pkt_drop(struct sk_buff *skb, int code) |
1746 | { | 1749 | { |
1747 | int type = ipv6_addr_type(&skb->nh.ipv6h->daddr); | 1750 | int type = ipv6_addr_type(&skb->nh.ipv6h->daddr); |
1748 | if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) | 1751 | if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) |
1749 | IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS); | 1752 | IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS); |
1750 | 1753 | ||
1751 | IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); | 1754 | IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); |
1752 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev); | 1755 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev); |
1753 | kfree_skb(skb); | 1756 | kfree_skb(skb); |
1754 | return 0; | 1757 | return 0; |
1755 | } | 1758 | } |
1756 | 1759 | ||
1760 | static int ip6_pkt_discard(struct sk_buff *skb) | ||
1761 | { | ||
1762 | return ip6_pkt_drop(skb, ICMPV6_NOROUTE); | ||
1763 | } | ||
1764 | |||
1757 | static int ip6_pkt_discard_out(struct sk_buff *skb) | 1765 | static int ip6_pkt_discard_out(struct sk_buff *skb) |
1758 | { | 1766 | { |
1759 | skb->dev = skb->dst->dev; | 1767 | skb->dev = skb->dst->dev; |
1760 | return ip6_pkt_discard(skb); | 1768 | return ip6_pkt_discard(skb); |
1761 | } | 1769 | } |
1762 | 1770 | ||
1771 | static int ip6_pkt_prohibit(struct sk_buff *skb) | ||
1772 | { | ||
1773 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED); | ||
1774 | } | ||
1775 | |||
1776 | static int ip6_pkt_prohibit_out(struct sk_buff *skb) | ||
1777 | { | ||
1778 | skb->dev = skb->dst->dev; | ||
1779 | return ip6_pkt_prohibit(skb); | ||
1780 | } | ||
1781 | |||
1782 | static int ip6_pkt_blk_hole(struct sk_buff *skb) | ||
1783 | { | ||
1784 | kfree_skb(skb); | ||
1785 | return 0; | ||
1786 | } | ||
1787 | |||
1763 | /* | 1788 | /* |
1764 | * Allocate a dst for local (unicast / anycast) address. | 1789 | * Allocate a dst for local (unicast / anycast) address. |
1765 | */ | 1790 | */ |