X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=net%2Fipv6%2Froute.c;h=fe8d9837f9f89a2067b5f633d5a9cdd992385bf2;hb=abdba717253382a669af9c719313ec602cc95a2d;hp=ad9b285692ba72f8f44a76174ee9725bc5e08e15;hpb=0bce0b7a3b25b33220be77dcaf3dc4585641100c;p=powerpc.git diff --git a/net/ipv6/route.c b/net/ipv6/route.c index ad9b285692..fe8d9837f9 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -119,6 +119,19 @@ static struct dst_ops ip6_dst_ops = { .entry_size = sizeof(struct rt6_info), }; +static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) +{ +} + +static struct dst_ops ip6_dst_blackhole_ops = { + .family = AF_INET6, + .protocol = __constant_htons(ETH_P_IPV6), + .destroy = ip6_dst_destroy, + .check = ip6_dst_check, + .update_pmtu = ip6_rt_blackhole_update_pmtu, + .entry_size = sizeof(struct rt6_info), +}; + struct rt6_info ip6_null_entry = { .u = { .dst = { @@ -575,6 +588,8 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, return NULL; } +EXPORT_SYMBOL(rt6_lookup); + /* ip6_ins_rt is called with FREE table->tb6_lock. It takes new route entry, the addition fails by any reason the route is freed. In any case, if caller does not hold it, it may @@ -724,7 +739,7 @@ out2: void ip6_route_input(struct sk_buff *skb) { - struct ipv6hdr *iph = skb->nh.ipv6h; + struct ipv6hdr *iph = ipv6_hdr(skb); int flags = RT6_LOOKUP_F_HAS_SADDR; struct flowi fl = { .iif = skb->dev->ifindex, @@ -829,6 +844,55 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) return fib6_rule_lookup(fl, flags, ip6_pol_route_output); } +EXPORT_SYMBOL(ip6_route_output); + +static int ip6_blackhole_output(struct sk_buff *skb) +{ + kfree_skb(skb); + return 0; +} + +int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl) +{ + struct rt6_info *ort = (struct rt6_info *) *dstp; + struct rt6_info *rt = (struct rt6_info *) + dst_alloc(&ip6_dst_blackhole_ops); + struct dst_entry *new = NULL; + + if (rt) { + new = &rt->u.dst; + + atomic_set(&new->__refcnt, 1); + new->__use = 1; + new->input = ip6_blackhole_output; + new->output = ip6_blackhole_output; + + memcpy(new->metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32)); + new->dev = ort->u.dst.dev; + if (new->dev) + dev_hold(new->dev); + rt->rt6i_idev = ort->rt6i_idev; + if (rt->rt6i_idev) + in6_dev_hold(rt->rt6i_idev); + rt->rt6i_expires = 0; + + ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway); + rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; + rt->rt6i_metric = 0; + + memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); +#ifdef CONFIG_IPV6_SUBTREES + memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key)); +#endif + + dst_free(new); + } + + dst_release(*dstp); + *dstp = new; + return (new ? 0 : -ENOMEM); +} +EXPORT_SYMBOL_GPL(ip6_dst_blackhole); /* * Destination cache support functions @@ -1757,7 +1821,7 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg) rtnl_unlock(); return err; - }; + } return -EINVAL; } @@ -1766,13 +1830,22 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg) * Drop the packet on the floor */ -static inline int ip6_pkt_drop(struct sk_buff *skb, int code) +static inline int ip6_pkt_drop(struct sk_buff *skb, int code, + int ipstats_mib_noroutes) { - int type = ipv6_addr_type(&skb->nh.ipv6h->daddr); - if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) - IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INADDRERRORS); - - IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_OUTNOROUTES); + int type; + switch (ipstats_mib_noroutes) { + case IPSTATS_MIB_INNOROUTES: + type = ipv6_addr_type(&ipv6_hdr(skb)->daddr); + if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) { + IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INADDRERRORS); + break; + } + /* FALLTHROUGH */ + case IPSTATS_MIB_OUTNOROUTES: + IP6_INC_STATS(ip6_dst_idev(skb->dst), ipstats_mib_noroutes); + break; + } icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev); kfree_skb(skb); return 0; @@ -1780,26 +1853,26 @@ static inline int ip6_pkt_drop(struct sk_buff *skb, int code) static int ip6_pkt_discard(struct sk_buff *skb) { - return ip6_pkt_drop(skb, ICMPV6_NOROUTE); + return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_INNOROUTES); } static int ip6_pkt_discard_out(struct sk_buff *skb) { skb->dev = skb->dst->dev; - return ip6_pkt_discard(skb); + return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES); } #ifdef CONFIG_IPV6_MULTIPLE_TABLES static int ip6_pkt_prohibit(struct sk_buff *skb) { - return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED); + return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_INNOROUTES); } static int ip6_pkt_prohibit_out(struct sk_buff *skb) { skb->dev = skb->dst->dev; - return ip6_pkt_prohibit(skb); + return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); } static int ip6_pkt_blk_hole(struct sk_buff *skb) @@ -1926,7 +1999,7 @@ void rt6_mtu_change(struct net_device *dev, unsigned mtu) fib6_clean_all(rt6_mtu_change_route, 0, &arg); } -static struct nla_policy rtm_ipv6_policy[RTA_MAX+1] __read_mostly = { +static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = { [RTA_GATEWAY] = { .len = sizeof(struct in6_addr) }, [RTA_OIF] = { .type = NLA_U32 }, [RTA_IIF] = { .type = NLA_U32 }, @@ -2003,7 +2076,7 @@ errout: return err; } -int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) +static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) { struct fib6_config cfg; int err; @@ -2015,7 +2088,7 @@ int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) return ip6_route_del(&cfg); } -int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) +static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) { struct fib6_config cfg; int err; @@ -2152,7 +2225,7 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg) prefix, NLM_F_MULTI); } -int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) +static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) { struct nlattr *tb[RTA_MAX+1]; struct rt6_info *rt; @@ -2206,7 +2279,7 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) /* Reserve room for dummy headers, this skb can pass through good chunk of routing engine. */ - skb->mac.raw = skb->data; + skb_reset_mac_header(skb); skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); rt = (struct rt6_info*) ip6_route_output(NULL, &fl); @@ -2477,11 +2550,14 @@ ctl_table ipv6_route_table[] = { void __init ip6_route_init(void) { +#ifdef CONFIG_PROC_FS struct proc_dir_entry *p; - +#endif ip6_dst_ops.kmem_cachep = kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); + ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep; + fib6_init(); #ifdef CONFIG_PROC_FS p = proc_net_create("ipv6_route", 0, rt6_proc_info); @@ -2496,6 +2572,10 @@ void __init ip6_route_init(void) #ifdef CONFIG_IPV6_MULTIPLE_TABLES fib6_rules_init(); #endif + + __rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL); + __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL); + __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL); } void ip6_route_cleanup(void)