aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/route.c
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2006-10-18 23:46:54 -0400
committerDavid S. Miller <davem@davemloft.net>2006-10-18 23:46:54 -0400
commit9ce8ade015a3f82dbdf856df7a685878dd1cc0e1 (patch)
treedaa2d5f9b335ef9762d9aaa3b91cd07077006640 /net/ipv6/route.c
parent3a31b9d2f2d98667832e87fa1853754ff062d6ef (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/ipv6/route.c')
-rw-r--r--net/ipv6/route.c37
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
95static int ip6_pkt_discard(struct sk_buff *skb); 95static int ip6_pkt_discard(struct sk_buff *skb);
96static int ip6_pkt_discard_out(struct sk_buff *skb); 96static int ip6_pkt_discard_out(struct sk_buff *skb);
97static int ip6_pkt_prohibit(struct sk_buff *skb);
98static int ip6_pkt_prohibit_out(struct sk_buff *skb);
99static int ip6_pkt_blk_hole(struct sk_buff *skb);
97static void ip6_link_failure(struct sk_buff *skb); 100static void ip6_link_failure(struct sk_buff *skb);
98static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu); 101static 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
1745static int ip6_pkt_discard(struct sk_buff *skb) 1748static 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
1760static int ip6_pkt_discard(struct sk_buff *skb)
1761{
1762 return ip6_pkt_drop(skb, ICMPV6_NOROUTE);
1763}
1764
1757static int ip6_pkt_discard_out(struct sk_buff *skb) 1765static 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
1771static int ip6_pkt_prohibit(struct sk_buff *skb)
1772{
1773 return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED);
1774}
1775
1776static int ip6_pkt_prohibit_out(struct sk_buff *skb)
1777{
1778 skb->dev = skb->dst->dev;
1779 return ip6_pkt_prohibit(skb);
1780}
1781
1782static 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 */