diff options
Diffstat (limited to 'net/ipv4/xfrm4_tunnel.c')
-rw-r--r-- | net/ipv4/xfrm4_tunnel.c | 79 |
1 files changed, 13 insertions, 66 deletions
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c index b08d56b117f8..2d670935c2b5 100644 --- a/net/ipv4/xfrm4_tunnel.c +++ b/net/ipv4/xfrm4_tunnel.c | |||
@@ -26,64 +26,6 @@ static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, s | |||
26 | return 0; | 26 | return 0; |
27 | } | 27 | } |
28 | 28 | ||
29 | static struct xfrm_tunnel *ipip_handler; | ||
30 | static DEFINE_MUTEX(xfrm4_tunnel_mutex); | ||
31 | |||
32 | int xfrm4_tunnel_register(struct xfrm_tunnel *handler) | ||
33 | { | ||
34 | int ret; | ||
35 | |||
36 | mutex_lock(&xfrm4_tunnel_mutex); | ||
37 | ret = 0; | ||
38 | if (ipip_handler != NULL) | ||
39 | ret = -EINVAL; | ||
40 | if (!ret) | ||
41 | ipip_handler = handler; | ||
42 | mutex_unlock(&xfrm4_tunnel_mutex); | ||
43 | |||
44 | return ret; | ||
45 | } | ||
46 | |||
47 | EXPORT_SYMBOL(xfrm4_tunnel_register); | ||
48 | |||
49 | int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler) | ||
50 | { | ||
51 | int ret; | ||
52 | |||
53 | mutex_lock(&xfrm4_tunnel_mutex); | ||
54 | ret = 0; | ||
55 | if (ipip_handler != handler) | ||
56 | ret = -EINVAL; | ||
57 | if (!ret) | ||
58 | ipip_handler = NULL; | ||
59 | mutex_unlock(&xfrm4_tunnel_mutex); | ||
60 | |||
61 | synchronize_net(); | ||
62 | |||
63 | return ret; | ||
64 | } | ||
65 | |||
66 | EXPORT_SYMBOL(xfrm4_tunnel_deregister); | ||
67 | |||
68 | static int ipip_rcv(struct sk_buff *skb) | ||
69 | { | ||
70 | struct xfrm_tunnel *handler = ipip_handler; | ||
71 | |||
72 | /* Tunnel devices take precedence. */ | ||
73 | if (handler && handler->handler(skb) == 0) | ||
74 | return 0; | ||
75 | |||
76 | return xfrm4_rcv(skb); | ||
77 | } | ||
78 | |||
79 | static void ipip_err(struct sk_buff *skb, u32 info) | ||
80 | { | ||
81 | struct xfrm_tunnel *handler = ipip_handler; | ||
82 | |||
83 | if (handler) | ||
84 | handler->err_handler(skb, info); | ||
85 | } | ||
86 | |||
87 | static int ipip_init_state(struct xfrm_state *x) | 29 | static int ipip_init_state(struct xfrm_state *x) |
88 | { | 30 | { |
89 | if (!x->props.mode) | 31 | if (!x->props.mode) |
@@ -111,10 +53,15 @@ static struct xfrm_type ipip_type = { | |||
111 | .output = ipip_output | 53 | .output = ipip_output |
112 | }; | 54 | }; |
113 | 55 | ||
114 | static struct net_protocol ipip_protocol = { | 56 | static int xfrm_tunnel_err(struct sk_buff *skb, u32 info) |
115 | .handler = ipip_rcv, | 57 | { |
116 | .err_handler = ipip_err, | 58 | return -ENOENT; |
117 | .no_policy = 1, | 59 | } |
60 | |||
61 | static struct xfrm_tunnel xfrm_tunnel_handler = { | ||
62 | .handler = xfrm4_rcv, | ||
63 | .err_handler = xfrm_tunnel_err, | ||
64 | .priority = 2, | ||
118 | }; | 65 | }; |
119 | 66 | ||
120 | static int __init ipip_init(void) | 67 | static int __init ipip_init(void) |
@@ -123,8 +70,8 @@ static int __init ipip_init(void) | |||
123 | printk(KERN_INFO "ipip init: can't add xfrm type\n"); | 70 | printk(KERN_INFO "ipip init: can't add xfrm type\n"); |
124 | return -EAGAIN; | 71 | return -EAGAIN; |
125 | } | 72 | } |
126 | if (inet_add_protocol(&ipip_protocol, IPPROTO_IPIP) < 0) { | 73 | if (xfrm4_tunnel_register(&xfrm_tunnel_handler)) { |
127 | printk(KERN_INFO "ipip init: can't add protocol\n"); | 74 | printk(KERN_INFO "ipip init: can't add xfrm handler\n"); |
128 | xfrm_unregister_type(&ipip_type, AF_INET); | 75 | xfrm_unregister_type(&ipip_type, AF_INET); |
129 | return -EAGAIN; | 76 | return -EAGAIN; |
130 | } | 77 | } |
@@ -133,8 +80,8 @@ static int __init ipip_init(void) | |||
133 | 80 | ||
134 | static void __exit ipip_fini(void) | 81 | static void __exit ipip_fini(void) |
135 | { | 82 | { |
136 | if (inet_del_protocol(&ipip_protocol, IPPROTO_IPIP) < 0) | 83 | if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler)) |
137 | printk(KERN_INFO "ipip close: can't remove protocol\n"); | 84 | printk(KERN_INFO "ipip close: can't remove xfrm handler\n"); |
138 | if (xfrm_unregister_type(&ipip_type, AF_INET) < 0) | 85 | if (xfrm_unregister_type(&ipip_type, AF_INET) < 0) |
139 | printk(KERN_INFO "ipip close: can't remove xfrm type\n"); | 86 | printk(KERN_INFO "ipip close: can't remove xfrm type\n"); |
140 | } | 87 | } |