diff options
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 47 |
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 | ||
144 | static int ip6_pkt_prohibit(struct sk_buff *skb); | ||
145 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); | ||
146 | static int ip6_pkt_blk_hole(struct sk_buff *skb); | ||
147 | |||
144 | struct rt6_info ip6_prohibit_entry = { | 148 | struct 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, | |||
484 | do { \ | 488 | do { \ |
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 | ||
1746 | static int ip6_pkt_discard(struct sk_buff *skb) | 1749 | static 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 | ||
1761 | static int ip6_pkt_discard(struct sk_buff *skb) | ||
1762 | { | ||
1763 | return ip6_pkt_drop(skb, ICMPV6_NOROUTE); | ||
1764 | } | ||
1765 | |||
1758 | static int ip6_pkt_discard_out(struct sk_buff *skb) | 1766 | static 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 | |||
1774 | static int ip6_pkt_prohibit(struct sk_buff *skb) | ||
1775 | { | ||
1776 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED); | ||
1777 | } | ||
1778 | |||
1779 | static int ip6_pkt_prohibit_out(struct sk_buff *skb) | ||
1780 | { | ||
1781 | skb->dev = skb->dst->dev; | ||
1782 | return ip6_pkt_prohibit(skb); | ||
1783 | } | ||
1784 | |||
1785 | static 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 | */ |