diff options
Diffstat (limited to 'net/ipv6')
27 files changed, 254 insertions, 197 deletions
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index e6f83b6a2b76..f8a107ab5592 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig @@ -88,7 +88,7 @@ config INET6_IPCOMP tristate "IPv6: IPComp transformation" depends on IPV6 select XFRM - select INET6_TUNNEL + select INET6_XFRM_TUNNEL select CRYPTO select CRYPTO_DEFLATE ---help--- @@ -97,19 +97,18 @@ config INET6_IPCOMP If unsure, say Y. +config INET6_XFRM_TUNNEL + tristate + select INET6_TUNNEL + default n + config INET6_TUNNEL - tristate "IPv6: tunnel transformation" - depends on IPV6 - select XFRM - ---help--- - Support for generic IPv6-in-IPv6 tunnel transformation, which is - required by the IPv6-in-IPv6 tunneling module as well as tunnel mode - IPComp. - - If unsure, say Y. + tristate + default n config IPV6_TUNNEL tristate "IPv6: IPv6-in-IPv6 tunnel" + select INET6_TUNNEL depends on IPV6 ---help--- Support for IPv6-in-IPv6 tunnels described in RFC 2473. diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 41877abd22e6..a760b0988fbb 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile @@ -18,7 +18,8 @@ ipv6-objs += $(ipv6-y) obj-$(CONFIG_INET6_AH) += ah6.o obj-$(CONFIG_INET6_ESP) += esp6.o obj-$(CONFIG_INET6_IPCOMP) += ipcomp6.o -obj-$(CONFIG_INET6_TUNNEL) += xfrm6_tunnel.o +obj-$(CONFIG_INET6_XFRM_TUNNEL) += xfrm6_tunnel.o +obj-$(CONFIG_INET6_TUNNEL) += tunnel6.o obj-$(CONFIG_NETFILTER) += netfilter/ obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 01c62a0d3742..445006ee4522 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -143,7 +143,7 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, struct prefix_info *pinfo); static int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev); -static struct notifier_block *inet6addr_chain; +static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); struct ipv6_devconf ipv6_devconf = { .forwarding = 0, @@ -593,7 +593,7 @@ out2: read_unlock_bh(&addrconf_lock); if (likely(err == 0)) - notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa); + atomic_notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa); else { kfree(ifa); ifa = ERR_PTR(err); @@ -688,7 +688,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) ipv6_ifa_notify(RTM_DELADDR, ifp); - notifier_call_chain(&inet6addr_chain,NETDEV_DOWN,ifp); + atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifp); addrconf_del_timer(ifp); @@ -3767,12 +3767,12 @@ static void addrconf_sysctl_unregister(struct ipv6_devconf *p) int register_inet6addr_notifier(struct notifier_block *nb) { - return notifier_chain_register(&inet6addr_chain, nb); + return atomic_notifier_chain_register(&inet6addr_chain, nb); } int unregister_inet6addr_notifier(struct notifier_block *nb) { - return notifier_chain_unregister(&inet6addr_chain,nb); + return atomic_notifier_chain_unregister(&inet6addr_chain,nb); } /* diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 48597538db3f..ff9040c92556 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -44,7 +44,6 @@ #include <net/ip.h> #include <net/ipv6.h> -#include <net/protocol.h> #include <net/ip6_route.h> #include <net/addrconf.h> #include <net/ip6_tunnel.h> @@ -391,7 +390,7 @@ parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw) * to the specifications in RFC 2473. **/ -static void +static int ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, int type, int code, int offset, __u32 info) { @@ -402,6 +401,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, int rel_code = ICMPV6_ADDR_UNREACH; __u32 rel_info = 0; __u16 len; + int err = -ENOENT; /* If the packet doesn't contain the original IPv6 header we are in trouble since we might need the source address for further @@ -411,6 +411,8 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if ((t = ip6ip6_tnl_lookup(&ipv6h->daddr, &ipv6h->saddr)) == NULL) goto out; + err = 0; + switch (type) { __u32 teli; struct ipv6_tlv_tnl_enc_lim *tel; @@ -492,6 +494,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, } out: read_unlock(&ip6ip6_lock); + return err; } static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph, @@ -511,9 +514,8 @@ static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph, **/ static int -ip6ip6_rcv(struct sk_buff **pskb) +ip6ip6_rcv(struct sk_buff *skb) { - struct sk_buff *skb = *pskb; struct ipv6hdr *ipv6h; struct ip6_tnl *t; @@ -1112,39 +1114,12 @@ ip6ip6_fb_tnl_dev_init(struct net_device *dev) return 0; } -#ifdef CONFIG_INET6_TUNNEL static struct xfrm6_tunnel ip6ip6_handler = { .handler = ip6ip6_rcv, .err_handler = ip6ip6_err, + .priority = 1, }; -static inline int ip6ip6_register(void) -{ - return xfrm6_tunnel_register(&ip6ip6_handler); -} - -static inline int ip6ip6_unregister(void) -{ - return xfrm6_tunnel_deregister(&ip6ip6_handler); -} -#else -static struct inet6_protocol xfrm6_tunnel_protocol = { - .handler = ip6ip6_rcv, - .err_handler = ip6ip6_err, - .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, -}; - -static inline int ip6ip6_register(void) -{ - return inet6_add_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6); -} - -static inline int ip6ip6_unregister(void) -{ - return inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6); -} -#endif - /** * ip6_tunnel_init - register protocol and reserve needed resources * @@ -1155,7 +1130,7 @@ static int __init ip6_tunnel_init(void) { int err; - if (ip6ip6_register() < 0) { + if (xfrm6_tunnel_register(&ip6ip6_handler)) { printk(KERN_ERR "ip6ip6 init: can't register tunnel\n"); return -EAGAIN; } @@ -1174,7 +1149,7 @@ static int __init ip6_tunnel_init(void) } return 0; fail: - ip6ip6_unregister(); + xfrm6_tunnel_deregister(&ip6ip6_handler); return err; } @@ -1184,7 +1159,7 @@ fail: static void __exit ip6_tunnel_cleanup(void) { - if (ip6ip6_unregister() < 0) + if (xfrm6_tunnel_deregister(&ip6ip6_handler)) printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n"); unregister_netdev(ip6ip6_fb_tnl_dev); diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 028b636687ec..d4cfec3f414e 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -228,6 +228,9 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) t->id.proto = IPPROTO_IPV6; t->id.spi = xfrm6_tunnel_alloc_spi((xfrm_address_t *)&x->props.saddr); + if (!t->id.spi) + goto error; + memcpy(t->id.daddr.a6, x->id.daddr.a6, sizeof(struct in6_addr)); memcpy(&t->sel, &x->sel, sizeof(t->sel)); t->props.family = AF_INET6; @@ -243,7 +246,9 @@ out: return t; error: + t->km.state = XFRM_STATE_DEAD; xfrm_state_put(t); + t = NULL; goto out; } diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 344eab3b5da8..e81c6a9dab81 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -713,13 +713,13 @@ cleanup_netlink_notifier: return status; } -static int __init init(void) +static int __init ip6_queue_init(void) { return init_or_cleanup(1); } -static void __exit fini(void) +static void __exit ip6_queue_fini(void) { init_or_cleanup(0); } @@ -727,5 +727,5 @@ static void __exit fini(void) MODULE_DESCRIPTION("IPv6 packet queue handler"); MODULE_LICENSE("GPL"); -module_init(init); -module_exit(fini); +module_init(ip6_queue_init); +module_exit(ip6_queue_fini); diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index db3c9ae98e95..3ecf2db841f8 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1406,7 +1406,7 @@ static struct ip6t_match icmp6_matchstruct = { .family = AF_INET6, }; -static int __init init(void) +static int __init ip6_tables_init(void) { int ret; @@ -1429,7 +1429,7 @@ static int __init init(void) return 0; } -static void __exit fini(void) +static void __exit ip6_tables_fini(void) { nf_unregister_sockopt(&ip6t_sockopts); xt_unregister_match(&icmp6_matchstruct); @@ -1517,5 +1517,5 @@ EXPORT_SYMBOL(ip6t_do_table); EXPORT_SYMBOL(ip6t_ext_hdr); EXPORT_SYMBOL(ipv6_find_hdr); -module_init(init); -module_exit(fini); +module_init(ip6_tables_init); +module_exit(ip6_tables_fini); diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c index da14c6d86bcc..b8eff8ee69b1 100644 --- a/net/ipv6/netfilter/ip6t_HL.c +++ b/net/ipv6/netfilter/ip6t_HL.c @@ -93,15 +93,15 @@ static struct ip6t_target ip6t_HL = { .me = THIS_MODULE }; -static int __init init(void) +static int __init ip6t_hl_init(void) { return ip6t_register_target(&ip6t_HL); } -static void __exit fini(void) +static void __exit ip6t_hl_fini(void) { ip6t_unregister_target(&ip6t_HL); } -module_init(init); -module_exit(fini); +module_init(ip6t_hl_init); +module_exit(ip6t_hl_fini); diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index 07c6bcbe4c5f..a96c0de14b00 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c @@ -483,7 +483,7 @@ static struct nf_logger ip6t_logger = { .me = THIS_MODULE, }; -static int __init init(void) +static int __init ip6t_log_init(void) { if (ip6t_register_target(&ip6t_log_reg)) return -EINVAL; @@ -497,11 +497,11 @@ static int __init init(void) return 0; } -static void __exit fini(void) +static void __exit ip6t_log_fini(void) { nf_log_unregister_logger(&ip6t_logger); ip6t_unregister_target(&ip6t_log_reg); } -module_init(init); -module_exit(fini); +module_init(ip6t_log_init); +module_exit(ip6t_log_fini); diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index ddfa38575fe2..de1175c27f6d 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c @@ -255,17 +255,17 @@ static struct ip6t_target ip6t_reject_reg = { .me = THIS_MODULE }; -static int __init init(void) +static int __init ip6t_reject_init(void) { if (ip6t_register_target(&ip6t_reject_reg)) return -EINVAL; return 0; } -static void __exit fini(void) +static void __exit ip6t_reject_fini(void) { ip6t_unregister_target(&ip6t_reject_reg); } -module_init(init); -module_exit(fini); +module_init(ip6t_reject_init); +module_exit(ip6t_reject_fini); diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c index 178f6fb1e53d..2f7bb20c758b 100644 --- a/net/ipv6/netfilter/ip6t_ah.c +++ b/net/ipv6/netfilter/ip6t_ah.c @@ -122,15 +122,15 @@ static struct ip6t_match ah_match = { .me = THIS_MODULE, }; -static int __init init(void) +static int __init ip6t_ah_init(void) { return ip6t_register_match(&ah_match); } -static void __exit cleanup(void) +static void __exit ip6t_ah_fini(void) { ip6t_unregister_match(&ah_match); } -module_init(init); -module_exit(cleanup); +module_init(ip6t_ah_init); +module_exit(ip6t_ah_fini); diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c index e97a70226987..9422413d0571 100644 --- a/net/ipv6/netfilter/ip6t_dst.c +++ b/net/ipv6/netfilter/ip6t_dst.c @@ -206,15 +206,15 @@ static struct ip6t_match opts_match = { .me = THIS_MODULE, }; -static int __init init(void) +static int __init ip6t_dst_init(void) { return ip6t_register_match(&opts_match); } -static void __exit cleanup(void) +static void __exit ip6t_dst_fini(void) { ip6t_unregister_match(&opts_match); } -module_init(init); -module_exit(cleanup); +module_init(ip6t_dst_init); +module_exit(ip6t_dst_fini); diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c index 540b8bfd5055..36bedad2c6f7 100644 --- a/net/ipv6/netfilter/ip6t_esp.c +++ b/net/ipv6/netfilter/ip6t_esp.c @@ -101,15 +101,15 @@ static struct ip6t_match esp_match = { .me = THIS_MODULE, }; -static int __init init(void) +static int __init ip6t_esp_init(void) { return ip6t_register_match(&esp_match); } -static void __exit cleanup(void) +static void __exit ip6t_esp_fini(void) { ip6t_unregister_match(&esp_match); } -module_init(init); -module_exit(cleanup); +module_init(ip6t_esp_init); +module_exit(ip6t_esp_fini); diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c index d4b0bad52830..94dbdb8b458d 100644 --- a/net/ipv6/netfilter/ip6t_eui64.c +++ b/net/ipv6/netfilter/ip6t_eui64.c @@ -70,15 +70,15 @@ static struct ip6t_match eui64_match = { .me = THIS_MODULE, }; -static int __init init(void) +static int __init ip6t_eui64_init(void) { return ip6t_register_match(&eui64_match); } -static void __exit fini(void) +static void __exit ip6t_eui64_fini(void) { ip6t_unregister_match(&eui64_match); } -module_init(init); -module_exit(fini); +module_init(ip6t_eui64_init); +module_exit(ip6t_eui64_fini); diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c index 4c41e14823d5..06768c84bd31 100644 --- a/net/ipv6/netfilter/ip6t_frag.c +++ b/net/ipv6/netfilter/ip6t_frag.c @@ -139,15 +139,15 @@ static struct ip6t_match frag_match = { .me = THIS_MODULE, }; -static int __init init(void) +static int __init ip6t_frag_init(void) { return ip6t_register_match(&frag_match); } -static void __exit cleanup(void) +static void __exit ip6t_frag_fini(void) { ip6t_unregister_match(&frag_match); } -module_init(init); -module_exit(cleanup); +module_init(ip6t_frag_init); +module_exit(ip6t_frag_fini); diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index b4a1fdfe6abc..374f1be85c0d 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c @@ -206,15 +206,15 @@ static struct ip6t_match opts_match = { .me = THIS_MODULE, }; -static int __init init(void) +static int __init ip6t_hbh_init(void) { return ip6t_register_match(&opts_match); } -static void __exit cleanup(void) +static void __exit ip6t_hbh_fini(void) { ip6t_unregister_match(&opts_match); } -module_init(init); -module_exit(cleanup); +module_init(ip6t_hbh_init); +module_exit(ip6t_hbh_fini); diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c index 374055733b26..44a729e17c48 100644 --- a/net/ipv6/netfilter/ip6t_hl.c +++ b/net/ipv6/netfilter/ip6t_hl.c @@ -55,16 +55,16 @@ static struct ip6t_match hl_match = { .me = THIS_MODULE, }; -static int __init init(void) +static int __init ip6t_hl_init(void) { return ip6t_register_match(&hl_match); } -static void __exit fini(void) +static void __exit ip6t_hl_fini(void) { ip6t_unregister_match(&hl_match); } -module_init(init); -module_exit(fini); +module_init(ip6t_hl_init); +module_exit(ip6t_hl_fini); diff --git a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c index 752b65d21c72..10c48ba596d6 100644 --- a/net/ipv6/netfilter/ip6t_multiport.c +++ b/net/ipv6/netfilter/ip6t_multiport.c @@ -111,15 +111,15 @@ static struct ip6t_match multiport_match = { .me = THIS_MODULE, }; -static int __init init(void) +static int __init ip6t_multiport_init(void) { return ip6t_register_match(&multiport_match); } -static void __exit fini(void) +static void __exit ip6t_multiport_fini(void) { ip6t_unregister_match(&multiport_match); } -module_init(init); -module_exit(fini); +module_init(ip6t_multiport_init); +module_exit(ip6t_multiport_fini); diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c index e2cee3bcdef9..5d047990cd44 100644 --- a/net/ipv6/netfilter/ip6t_owner.c +++ b/net/ipv6/netfilter/ip6t_owner.c @@ -79,15 +79,15 @@ static struct ip6t_match owner_match = { .me = THIS_MODULE, }; -static int __init init(void) +static int __init ip6t_owner_init(void) { return ip6t_register_match(&owner_match); } -static void __exit fini(void) +static void __exit ip6t_owner_fini(void) { ip6t_unregister_match(&owner_match); } -module_init(init); -module_exit(fini); +module_init(ip6t_owner_init); +module_exit(ip6t_owner_fini); diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index 4c6b55bb225b..fbb0184a41d8 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c @@ -225,15 +225,15 @@ static struct ip6t_match rt_match = { .me = THIS_MODULE, }; -static int __init init(void) +static int __init ip6t_rt_init(void) { return ip6t_register_match(&rt_match); } -static void __exit cleanup(void) +static void __exit ip6t_rt_fini(void) { ip6t_unregister_match(&rt_match); } -module_init(init); -module_exit(cleanup); +module_init(ip6t_rt_init); +module_exit(ip6t_rt_fini); diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index ce4a968e1f70..e5e724d9ee60 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c @@ -159,7 +159,7 @@ static struct nf_hook_ops ip6t_ops[] = { static int forward = NF_ACCEPT; module_param(forward, bool, 0000); -static int __init init(void) +static int __init ip6table_filter_init(void) { int ret; @@ -201,7 +201,7 @@ static int __init init(void) return ret; } -static void __exit fini(void) +static void __exit ip6table_filter_fini(void) { unsigned int i; @@ -211,5 +211,5 @@ static void __exit fini(void) ip6t_unregister_table(&packet_filter); } -module_init(init); -module_exit(fini); +module_init(ip6table_filter_init); +module_exit(ip6table_filter_fini); diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 30a4627e000d..e1f0f6ae9841 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -228,7 +228,7 @@ static struct nf_hook_ops ip6t_ops[] = { }, }; -static int __init init(void) +static int __init ip6table_mangle_init(void) { int ret; @@ -274,7 +274,7 @@ static int __init init(void) return ret; } -static void __exit fini(void) +static void __exit ip6table_mangle_fini(void) { unsigned int i; @@ -284,5 +284,5 @@ static void __exit fini(void) ip6t_unregister_table(&packet_mangler); } -module_init(init); -module_exit(fini); +module_init(ip6table_mangle_init); +module_exit(ip6table_mangle_fini); diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index db28ba3855e2..54d1fffd62ba 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c @@ -142,7 +142,7 @@ static struct nf_hook_ops ip6t_ops[] = { }, }; -static int __init init(void) +static int __init ip6table_raw_init(void) { int ret; @@ -170,7 +170,7 @@ static int __init init(void) return ret; } -static void __exit fini(void) +static void __exit ip6table_raw_fini(void) { unsigned int i; @@ -180,6 +180,6 @@ static void __exit fini(void) ip6t_unregister_table(&packet_raw); } -module_init(init); -module_exit(fini); +module_init(ip6table_raw_init); +module_exit(ip6table_raw_fini); MODULE_LICENSE("GPL"); diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index c16f62934bd9..c8b5a96cbb0f 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -588,16 +588,16 @@ MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6)); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); -static int __init init(void) +static int __init nf_conntrack_l3proto_ipv6_init(void) { need_conntrack(); return init_or_cleanup(1); } -static void __exit fini(void) +static void __exit nf_conntrack_l3proto_ipv6_fini(void) { init_or_cleanup(0); } -module_init(init); -module_exit(fini); +module_init(nf_conntrack_l3proto_ipv6_init); +module_exit(nf_conntrack_l3proto_ipv6_fini); diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c new file mode 100644 index 000000000000..5659b52284bd --- /dev/null +++ b/net/ipv6/tunnel6.c @@ -0,0 +1,131 @@ +/* + * Copyright (C)2003,2004 USAGI/WIDE Project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors Mitsuru KANDA <mk@linux-ipv6.org> + * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/netdevice.h> +#include <linux/skbuff.h> +#include <net/protocol.h> +#include <net/xfrm.h> + +static struct xfrm6_tunnel *tunnel6_handlers; +static DEFINE_MUTEX(tunnel6_mutex); + +int xfrm6_tunnel_register(struct xfrm6_tunnel *handler) +{ + struct xfrm6_tunnel **pprev; + int ret = -EEXIST; + int priority = handler->priority; + + mutex_lock(&tunnel6_mutex); + + for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) { + if ((*pprev)->priority > priority) + break; + if ((*pprev)->priority == priority) + goto err; + } + + handler->next = *pprev; + *pprev = handler; + + ret = 0; + +err: + mutex_unlock(&tunnel6_mutex); + + return ret; +} + +EXPORT_SYMBOL(xfrm6_tunnel_register); + +int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler) +{ + struct xfrm6_tunnel **pprev; + int ret = -ENOENT; + + mutex_lock(&tunnel6_mutex); + + for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) { + if (*pprev == handler) { + *pprev = handler->next; + ret = 0; + break; + } + } + + mutex_unlock(&tunnel6_mutex); + + synchronize_net(); + + return ret; +} + +EXPORT_SYMBOL(xfrm6_tunnel_deregister); + +static int tunnel6_rcv(struct sk_buff **pskb) +{ + struct sk_buff *skb = *pskb; + struct xfrm6_tunnel *handler; + + for (handler = tunnel6_handlers; handler; handler = handler->next) + if (!handler->handler(skb)) + return 0; + + kfree_skb(skb); + return 0; +} + +static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + int type, int code, int offset, __u32 info) +{ + struct xfrm6_tunnel *handler; + + for (handler = tunnel6_handlers; handler; handler = handler->next) + if (!handler->err_handler(skb, opt, type, code, offset, info)) + break; +} + +static struct inet6_protocol tunnel6_protocol = { + .handler = tunnel6_rcv, + .err_handler = tunnel6_err, + .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, +}; + +static int __init tunnel6_init(void) +{ + if (inet6_add_protocol(&tunnel6_protocol, IPPROTO_IPV6)) { + printk(KERN_ERR "tunnel6 init(): can't add protocol\n"); + return -EAGAIN; + } + return 0; +} + +static void __exit tunnel6_fini(void) +{ + if (inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6)) + printk(KERN_ERR "tunnel6 close: can't remove protocol\n"); +} + +module_init(tunnel6_init); +module_exit(tunnel6_fini); +MODULE_LICENSE("GPL"); diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index 1ca2da68ef69..cccf8b76f046 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c @@ -28,9 +28,8 @@ static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) IP6_ECN_set_ce(inner_iph); } -int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi) +int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi) { - struct sk_buff *skb = *pskb; int err; u32 seq; struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH]; @@ -159,5 +158,5 @@ EXPORT_SYMBOL(xfrm6_rcv_spi); int xfrm6_rcv(struct sk_buff **pskb) { - return xfrm6_rcv_spi(pskb, 0); + return xfrm6_rcv_spi(*pskb, 0); } diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 08f9abbdf1d7..a8f6776c518d 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -28,7 +28,6 @@ #include <net/ip.h> #include <net/xfrm.h> #include <net/ipv6.h> -#include <net/protocol.h> #include <linux/ipv6.h> #include <linux/icmpv6.h> #include <linux/mutex.h> @@ -357,71 +356,18 @@ static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *dec return 0; } -static struct xfrm6_tunnel *xfrm6_tunnel_handler; -static DEFINE_MUTEX(xfrm6_tunnel_mutex); - -int xfrm6_tunnel_register(struct xfrm6_tunnel *handler) +static int xfrm6_tunnel_rcv(struct sk_buff *skb) { - int ret; - - mutex_lock(&xfrm6_tunnel_mutex); - ret = 0; - if (xfrm6_tunnel_handler != NULL) - ret = -EINVAL; - if (!ret) - xfrm6_tunnel_handler = handler; - mutex_unlock(&xfrm6_tunnel_mutex); - - return ret; -} - -EXPORT_SYMBOL(xfrm6_tunnel_register); - -int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler) -{ - int ret; - - mutex_lock(&xfrm6_tunnel_mutex); - ret = 0; - if (xfrm6_tunnel_handler != handler) - ret = -EINVAL; - if (!ret) - xfrm6_tunnel_handler = NULL; - mutex_unlock(&xfrm6_tunnel_mutex); - - synchronize_net(); - - return ret; -} - -EXPORT_SYMBOL(xfrm6_tunnel_deregister); - -static int xfrm6_tunnel_rcv(struct sk_buff **pskb) -{ - struct sk_buff *skb = *pskb; - struct xfrm6_tunnel *handler = xfrm6_tunnel_handler; struct ipv6hdr *iph = skb->nh.ipv6h; u32 spi; - /* device-like_ip6ip6_handler() */ - if (handler && handler->handler(pskb) == 0) - return 0; - spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr); - return xfrm6_rcv_spi(pskb, spi); + return xfrm6_rcv_spi(skb, spi); } -static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) +static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + int type, int code, int offset, __u32 info) { - struct xfrm6_tunnel *handler = xfrm6_tunnel_handler; - - /* call here first for device-like ip6ip6 err handling */ - if (handler) { - handler->err_handler(skb, opt, type, code, offset, info); - return; - } - /* xfrm6_tunnel native err handling */ switch (type) { case ICMPV6_DEST_UNREACH: @@ -462,7 +408,8 @@ static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, default: break; } - return; + + return 0; } static int xfrm6_tunnel_init_state(struct xfrm_state *x) @@ -493,10 +440,10 @@ static struct xfrm_type xfrm6_tunnel_type = { .output = xfrm6_tunnel_output, }; -static struct inet6_protocol xfrm6_tunnel_protocol = { +static struct xfrm6_tunnel xfrm6_tunnel_handler = { .handler = xfrm6_tunnel_rcv, - .err_handler = xfrm6_tunnel_err, - .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, + .err_handler = xfrm6_tunnel_err, + .priority = 2, }; static int __init xfrm6_tunnel_init(void) @@ -508,16 +455,16 @@ static int __init xfrm6_tunnel_init(void) "xfrm6_tunnel init: can't add xfrm type\n"); return -EAGAIN; } - if (inet6_add_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0) { + if (xfrm6_tunnel_register(&xfrm6_tunnel_handler)) { X6TPRINTK1(KERN_ERR - "xfrm6_tunnel init(): can't add protocol\n"); + "xfrm6_tunnel init(): can't add handler\n"); xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); return -EAGAIN; } if (xfrm6_tunnel_spi_init() < 0) { X6TPRINTK1(KERN_ERR "xfrm6_tunnel init: failed to initialize spi\n"); - inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6); + xfrm6_tunnel_deregister(&xfrm6_tunnel_handler); xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); return -EAGAIN; } @@ -529,9 +476,9 @@ static void __exit xfrm6_tunnel_fini(void) X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__); xfrm6_tunnel_spi_fini(); - if (inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0) + if (xfrm6_tunnel_deregister(&xfrm6_tunnel_handler)) X6TPRINTK1(KERN_ERR - "xfrm6_tunnel close: can't remove protocol\n"); + "xfrm6_tunnel close: can't remove handler\n"); if (xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6) < 0) X6TPRINTK1(KERN_ERR "xfrm6_tunnel close: can't remove xfrm type\n"); |