aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r--net/ipv6/route.c47
1 files changed, 38 insertions, 9 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index a1b0f075462e..c953466b7afd 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -141,6 +141,10 @@ struct rt6_info ip6_null_entry = {
141 141
142#ifdef CONFIG_IPV6_MULTIPLE_TABLES 142#ifdef CONFIG_IPV6_MULTIPLE_TABLES
143 143
144static int ip6_pkt_prohibit(struct sk_buff *skb);
145static int ip6_pkt_prohibit_out(struct sk_buff *skb);
146static int ip6_pkt_blk_hole(struct sk_buff *skb);
147
144struct rt6_info ip6_prohibit_entry = { 148struct rt6_info ip6_prohibit_entry = {
145 .u = { 149 .u = {
146 .dst = { 150 .dst = {
@@ -150,8 +154,8 @@ struct rt6_info ip6_prohibit_entry = {
150 .obsolete = -1, 154 .obsolete = -1,
151 .error = -EACCES, 155 .error = -EACCES,
152 .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, 156 .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
153 .input = ip6_pkt_discard, 157 .input = ip6_pkt_prohibit,
154 .output = ip6_pkt_discard_out, 158 .output = ip6_pkt_prohibit_out,
155 .ops = &ip6_dst_ops, 159 .ops = &ip6_dst_ops,
156 .path = (struct dst_entry*)&ip6_prohibit_entry, 160 .path = (struct dst_entry*)&ip6_prohibit_entry,
157 } 161 }
@@ -170,8 +174,8 @@ struct rt6_info ip6_blk_hole_entry = {
170 .obsolete = -1, 174 .obsolete = -1,
171 .error = -EINVAL, 175 .error = -EINVAL,
172 .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, 176 .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
173 .input = ip6_pkt_discard, 177 .input = ip6_pkt_blk_hole,
174 .output = ip6_pkt_discard_out, 178 .output = ip6_pkt_blk_hole,
175 .ops = &ip6_dst_ops, 179 .ops = &ip6_dst_ops,
176 .path = (struct dst_entry*)&ip6_blk_hole_entry, 180 .path = (struct dst_entry*)&ip6_blk_hole_entry,
177 } 181 }
@@ -484,7 +488,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
484do { \ 488do { \
485 if (rt == &ip6_null_entry) { \ 489 if (rt == &ip6_null_entry) { \
486 struct fib6_node *pn; \ 490 struct fib6_node *pn; \
487 while (fn) { \ 491 while (1) { \
488 if (fn->fn_flags & RTN_TL_ROOT) \ 492 if (fn->fn_flags & RTN_TL_ROOT) \
489 goto out; \ 493 goto out; \
490 pn = fn->parent; \ 494 pn = fn->parent; \
@@ -618,8 +622,6 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d
618 ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); 622 ipv6_addr_copy(&rt->rt6i_dst.addr, daddr);
619 rt->rt6i_dst.plen = 128; 623 rt->rt6i_dst.plen = 128;
620 rt->rt6i_flags |= RTF_CACHE; 624 rt->rt6i_flags |= RTF_CACHE;
621 if (rt->rt6i_flags & RTF_REJECT)
622 rt->u.dst.error = ort->u.dst.error;
623 rt->u.dst.flags |= DST_HOST; 625 rt->u.dst.flags |= DST_HOST;
624 rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop); 626 rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop);
625 } 627 }
@@ -1540,6 +1542,7 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
1540 rt->u.dst.output = ort->u.dst.output; 1542 rt->u.dst.output = ort->u.dst.output;
1541 1543
1542 memcpy(rt->u.dst.metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32)); 1544 memcpy(rt->u.dst.metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32));
1545 rt->u.dst.error = ort->u.dst.error;
1543 rt->u.dst.dev = ort->u.dst.dev; 1546 rt->u.dst.dev = ort->u.dst.dev;
1544 if (rt->u.dst.dev) 1547 if (rt->u.dst.dev)
1545 dev_hold(rt->u.dst.dev); 1548 dev_hold(rt->u.dst.dev);
@@ -1743,24 +1746,50 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg)
1743 * Drop the packet on the floor 1746 * Drop the packet on the floor
1744 */ 1747 */
1745 1748
1746static int ip6_pkt_discard(struct sk_buff *skb) 1749static inline int ip6_pkt_drop(struct sk_buff *skb, int code)
1747{ 1750{
1748 int type = ipv6_addr_type(&skb->nh.ipv6h->daddr); 1751 int type = ipv6_addr_type(&skb->nh.ipv6h->daddr);
1749 if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) 1752 if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED)
1750 IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS); 1753 IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS);
1751 1754
1752 IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); 1755 IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
1753 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev); 1756 icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev);
1754 kfree_skb(skb); 1757 kfree_skb(skb);
1755 return 0; 1758 return 0;
1756} 1759}
1757 1760
1761static int ip6_pkt_discard(struct sk_buff *skb)
1762{
1763 return ip6_pkt_drop(skb, ICMPV6_NOROUTE);
1764}
1765
1758static int ip6_pkt_discard_out(struct sk_buff *skb) 1766static int ip6_pkt_discard_out(struct sk_buff *skb)
1759{ 1767{
1760 skb->dev = skb->dst->dev; 1768 skb->dev = skb->dst->dev;
1761 return ip6_pkt_discard(skb); 1769 return ip6_pkt_discard(skb);
1762} 1770}
1763 1771
1772#ifdef CONFIG_IPV6_MULTIPLE_TABLES
1773
1774static int ip6_pkt_prohibit(struct sk_buff *skb)
1775{
1776 return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED);
1777}
1778
1779static int ip6_pkt_prohibit_out(struct sk_buff *skb)
1780{
1781 skb->dev = skb->dst->dev;
1782 return ip6_pkt_prohibit(skb);
1783}
1784
1785static int ip6_pkt_blk_hole(struct sk_buff *skb)
1786{
1787 kfree_skb(skb);
1788 return 0;
1789}
1790
1791#endif
1792
1764/* 1793/*
1765 * Allocate a dst for local (unicast / anycast) address. 1794 * Allocate a dst for local (unicast / anycast) address.
1766 */ 1795 */