diff options
Diffstat (limited to 'net/xfrm')
-rw-r--r-- | net/xfrm/xfrm_input.c | 5 | ||||
-rw-r--r-- | net/xfrm/xfrm_output.c | 4 | ||||
-rw-r--r-- | net/xfrm/xfrm_policy.c | 179 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 206 |
4 files changed, 207 insertions, 187 deletions
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 113f44429982..cb97fda1b6df 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c | |||
@@ -49,13 +49,16 @@ EXPORT_SYMBOL(secpath_dup); | |||
49 | int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq) | 49 | int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq) |
50 | { | 50 | { |
51 | int offset, offset_seq; | 51 | int offset, offset_seq; |
52 | int hlen; | ||
52 | 53 | ||
53 | switch (nexthdr) { | 54 | switch (nexthdr) { |
54 | case IPPROTO_AH: | 55 | case IPPROTO_AH: |
56 | hlen = sizeof(struct ip_auth_hdr); | ||
55 | offset = offsetof(struct ip_auth_hdr, spi); | 57 | offset = offsetof(struct ip_auth_hdr, spi); |
56 | offset_seq = offsetof(struct ip_auth_hdr, seq_no); | 58 | offset_seq = offsetof(struct ip_auth_hdr, seq_no); |
57 | break; | 59 | break; |
58 | case IPPROTO_ESP: | 60 | case IPPROTO_ESP: |
61 | hlen = sizeof(struct ip_esp_hdr); | ||
59 | offset = offsetof(struct ip_esp_hdr, spi); | 62 | offset = offsetof(struct ip_esp_hdr, spi); |
60 | offset_seq = offsetof(struct ip_esp_hdr, seq_no); | 63 | offset_seq = offsetof(struct ip_esp_hdr, seq_no); |
61 | break; | 64 | break; |
@@ -69,7 +72,7 @@ int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq) | |||
69 | return 1; | 72 | return 1; |
70 | } | 73 | } |
71 | 74 | ||
72 | if (!pskb_may_pull(skb, 16)) | 75 | if (!pskb_may_pull(skb, hlen)) |
73 | return -EINVAL; | 76 | return -EINVAL; |
74 | 77 | ||
75 | *spi = *(__be32*)(skb_transport_header(skb) + offset); | 78 | *spi = *(__be32*)(skb_transport_header(skb) + offset); |
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 0eb3377602e9..f4bfd6c45651 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
@@ -63,7 +63,7 @@ int xfrm_output(struct sk_buff *skb) | |||
63 | xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); | 63 | xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); |
64 | } | 64 | } |
65 | 65 | ||
66 | err = x->mode->output(x, skb); | 66 | err = x->outer_mode->output(x, skb); |
67 | if (err) | 67 | if (err) |
68 | goto error; | 68 | goto error; |
69 | 69 | ||
@@ -82,7 +82,7 @@ int xfrm_output(struct sk_buff *skb) | |||
82 | } | 82 | } |
83 | dst = skb->dst; | 83 | dst = skb->dst; |
84 | x = dst->xfrm; | 84 | x = dst->xfrm; |
85 | } while (x && (x->props.mode != XFRM_MODE_TUNNEL)); | 85 | } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); |
86 | 86 | ||
87 | err = 0; | 87 | err = 0; |
88 | 88 | ||
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index af27c193697c..b702bd8a3893 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -49,8 +49,6 @@ static DEFINE_SPINLOCK(xfrm_policy_gc_lock); | |||
49 | 49 | ||
50 | static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family); | 50 | static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family); |
51 | static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo); | 51 | static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo); |
52 | static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family); | ||
53 | static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo); | ||
54 | 52 | ||
55 | static inline int | 53 | static inline int |
56 | __xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl) | 54 | __xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl) |
@@ -86,72 +84,6 @@ int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl, | |||
86 | return 0; | 84 | return 0; |
87 | } | 85 | } |
88 | 86 | ||
89 | int xfrm_register_type(struct xfrm_type *type, unsigned short family) | ||
90 | { | ||
91 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family); | ||
92 | struct xfrm_type **typemap; | ||
93 | int err = 0; | ||
94 | |||
95 | if (unlikely(afinfo == NULL)) | ||
96 | return -EAFNOSUPPORT; | ||
97 | typemap = afinfo->type_map; | ||
98 | |||
99 | if (likely(typemap[type->proto] == NULL)) | ||
100 | typemap[type->proto] = type; | ||
101 | else | ||
102 | err = -EEXIST; | ||
103 | xfrm_policy_unlock_afinfo(afinfo); | ||
104 | return err; | ||
105 | } | ||
106 | EXPORT_SYMBOL(xfrm_register_type); | ||
107 | |||
108 | int xfrm_unregister_type(struct xfrm_type *type, unsigned short family) | ||
109 | { | ||
110 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family); | ||
111 | struct xfrm_type **typemap; | ||
112 | int err = 0; | ||
113 | |||
114 | if (unlikely(afinfo == NULL)) | ||
115 | return -EAFNOSUPPORT; | ||
116 | typemap = afinfo->type_map; | ||
117 | |||
118 | if (unlikely(typemap[type->proto] != type)) | ||
119 | err = -ENOENT; | ||
120 | else | ||
121 | typemap[type->proto] = NULL; | ||
122 | xfrm_policy_unlock_afinfo(afinfo); | ||
123 | return err; | ||
124 | } | ||
125 | EXPORT_SYMBOL(xfrm_unregister_type); | ||
126 | |||
127 | struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family) | ||
128 | { | ||
129 | struct xfrm_policy_afinfo *afinfo; | ||
130 | struct xfrm_type **typemap; | ||
131 | struct xfrm_type *type; | ||
132 | int modload_attempted = 0; | ||
133 | |||
134 | retry: | ||
135 | afinfo = xfrm_policy_get_afinfo(family); | ||
136 | if (unlikely(afinfo == NULL)) | ||
137 | return NULL; | ||
138 | typemap = afinfo->type_map; | ||
139 | |||
140 | type = typemap[proto]; | ||
141 | if (unlikely(type && !try_module_get(type->owner))) | ||
142 | type = NULL; | ||
143 | if (!type && !modload_attempted) { | ||
144 | xfrm_policy_put_afinfo(afinfo); | ||
145 | request_module("xfrm-type-%d-%d", | ||
146 | (int) family, (int) proto); | ||
147 | modload_attempted = 1; | ||
148 | goto retry; | ||
149 | } | ||
150 | |||
151 | xfrm_policy_put_afinfo(afinfo); | ||
152 | return type; | ||
153 | } | ||
154 | |||
155 | int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, | 87 | int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, |
156 | unsigned short family) | 88 | unsigned short family) |
157 | { | 89 | { |
@@ -170,94 +102,6 @@ int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, | |||
170 | } | 102 | } |
171 | EXPORT_SYMBOL(xfrm_dst_lookup); | 103 | EXPORT_SYMBOL(xfrm_dst_lookup); |
172 | 104 | ||
173 | void xfrm_put_type(struct xfrm_type *type) | ||
174 | { | ||
175 | module_put(type->owner); | ||
176 | } | ||
177 | |||
178 | int xfrm_register_mode(struct xfrm_mode *mode, int family) | ||
179 | { | ||
180 | struct xfrm_policy_afinfo *afinfo; | ||
181 | struct xfrm_mode **modemap; | ||
182 | int err; | ||
183 | |||
184 | if (unlikely(mode->encap >= XFRM_MODE_MAX)) | ||
185 | return -EINVAL; | ||
186 | |||
187 | afinfo = xfrm_policy_lock_afinfo(family); | ||
188 | if (unlikely(afinfo == NULL)) | ||
189 | return -EAFNOSUPPORT; | ||
190 | |||
191 | err = -EEXIST; | ||
192 | modemap = afinfo->mode_map; | ||
193 | if (likely(modemap[mode->encap] == NULL)) { | ||
194 | modemap[mode->encap] = mode; | ||
195 | err = 0; | ||
196 | } | ||
197 | |||
198 | xfrm_policy_unlock_afinfo(afinfo); | ||
199 | return err; | ||
200 | } | ||
201 | EXPORT_SYMBOL(xfrm_register_mode); | ||
202 | |||
203 | int xfrm_unregister_mode(struct xfrm_mode *mode, int family) | ||
204 | { | ||
205 | struct xfrm_policy_afinfo *afinfo; | ||
206 | struct xfrm_mode **modemap; | ||
207 | int err; | ||
208 | |||
209 | if (unlikely(mode->encap >= XFRM_MODE_MAX)) | ||
210 | return -EINVAL; | ||
211 | |||
212 | afinfo = xfrm_policy_lock_afinfo(family); | ||
213 | if (unlikely(afinfo == NULL)) | ||
214 | return -EAFNOSUPPORT; | ||
215 | |||
216 | err = -ENOENT; | ||
217 | modemap = afinfo->mode_map; | ||
218 | if (likely(modemap[mode->encap] == mode)) { | ||
219 | modemap[mode->encap] = NULL; | ||
220 | err = 0; | ||
221 | } | ||
222 | |||
223 | xfrm_policy_unlock_afinfo(afinfo); | ||
224 | return err; | ||
225 | } | ||
226 | EXPORT_SYMBOL(xfrm_unregister_mode); | ||
227 | |||
228 | struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family) | ||
229 | { | ||
230 | struct xfrm_policy_afinfo *afinfo; | ||
231 | struct xfrm_mode *mode; | ||
232 | int modload_attempted = 0; | ||
233 | |||
234 | if (unlikely(encap >= XFRM_MODE_MAX)) | ||
235 | return NULL; | ||
236 | |||
237 | retry: | ||
238 | afinfo = xfrm_policy_get_afinfo(family); | ||
239 | if (unlikely(afinfo == NULL)) | ||
240 | return NULL; | ||
241 | |||
242 | mode = afinfo->mode_map[encap]; | ||
243 | if (unlikely(mode && !try_module_get(mode->owner))) | ||
244 | mode = NULL; | ||
245 | if (!mode && !modload_attempted) { | ||
246 | xfrm_policy_put_afinfo(afinfo); | ||
247 | request_module("xfrm-mode-%d-%d", family, encap); | ||
248 | modload_attempted = 1; | ||
249 | goto retry; | ||
250 | } | ||
251 | |||
252 | xfrm_policy_put_afinfo(afinfo); | ||
253 | return mode; | ||
254 | } | ||
255 | |||
256 | void xfrm_put_mode(struct xfrm_mode *mode) | ||
257 | { | ||
258 | module_put(mode->owner); | ||
259 | } | ||
260 | |||
261 | static inline unsigned long make_jiffies(long secs) | 105 | static inline unsigned long make_jiffies(long secs) |
262 | { | 106 | { |
263 | if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ) | 107 | if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ) |
@@ -2096,7 +1940,8 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first, | |||
2096 | if (xdst->genid != dst->xfrm->genid) | 1940 | if (xdst->genid != dst->xfrm->genid) |
2097 | return 0; | 1941 | return 0; |
2098 | 1942 | ||
2099 | if (strict && fl && dst->xfrm->props.mode != XFRM_MODE_TUNNEL && | 1943 | if (strict && fl && |
1944 | !(dst->xfrm->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) && | ||
2100 | !xfrm_state_addr_flow_check(dst->xfrm, fl, family)) | 1945 | !xfrm_state_addr_flow_check(dst->xfrm, fl, family)) |
2101 | return 0; | 1946 | return 0; |
2102 | 1947 | ||
@@ -2213,23 +2058,6 @@ static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo) | |||
2213 | read_unlock(&xfrm_policy_afinfo_lock); | 2058 | read_unlock(&xfrm_policy_afinfo_lock); |
2214 | } | 2059 | } |
2215 | 2060 | ||
2216 | static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family) | ||
2217 | { | ||
2218 | struct xfrm_policy_afinfo *afinfo; | ||
2219 | if (unlikely(family >= NPROTO)) | ||
2220 | return NULL; | ||
2221 | write_lock_bh(&xfrm_policy_afinfo_lock); | ||
2222 | afinfo = xfrm_policy_afinfo[family]; | ||
2223 | if (unlikely(!afinfo)) | ||
2224 | write_unlock_bh(&xfrm_policy_afinfo_lock); | ||
2225 | return afinfo; | ||
2226 | } | ||
2227 | |||
2228 | static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo) | ||
2229 | { | ||
2230 | write_unlock_bh(&xfrm_policy_afinfo_lock); | ||
2231 | } | ||
2232 | |||
2233 | static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) | 2061 | static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) |
2234 | { | 2062 | { |
2235 | struct net_device *dev = ptr; | 2063 | struct net_device *dev = ptr; |
@@ -2464,7 +2292,8 @@ static int xfrm_policy_migrate(struct xfrm_policy *pol, | |||
2464 | if (!migrate_tmpl_match(mp, &pol->xfrm_vec[i])) | 2292 | if (!migrate_tmpl_match(mp, &pol->xfrm_vec[i])) |
2465 | continue; | 2293 | continue; |
2466 | n++; | 2294 | n++; |
2467 | if (pol->xfrm_vec[i].mode != XFRM_MODE_TUNNEL) | 2295 | if (pol->xfrm_vec[i].mode != XFRM_MODE_TUNNEL && |
2296 | pol->xfrm_vec[i].mode != XFRM_MODE_BEET) | ||
2468 | continue; | 2297 | continue; |
2469 | /* update endpoints */ | 2298 | /* update endpoints */ |
2470 | memcpy(&pol->xfrm_vec[i].id.daddr, &mp->new_daddr, | 2299 | memcpy(&pol->xfrm_vec[i].id.daddr, &mp->new_daddr, |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 344f0a6abec5..224b44e31a07 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -57,6 +57,9 @@ static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024; | |||
57 | static unsigned int xfrm_state_num; | 57 | static unsigned int xfrm_state_num; |
58 | static unsigned int xfrm_state_genid; | 58 | static unsigned int xfrm_state_genid; |
59 | 59 | ||
60 | static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family); | ||
61 | static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); | ||
62 | |||
60 | static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, | 63 | static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, |
61 | xfrm_address_t *saddr, | 64 | xfrm_address_t *saddr, |
62 | u32 reqid, | 65 | u32 reqid, |
@@ -187,6 +190,184 @@ int __xfrm_state_delete(struct xfrm_state *x); | |||
187 | int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); | 190 | int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); |
188 | void km_state_expired(struct xfrm_state *x, int hard, u32 pid); | 191 | void km_state_expired(struct xfrm_state *x, int hard, u32 pid); |
189 | 192 | ||
193 | static struct xfrm_state_afinfo *xfrm_state_lock_afinfo(unsigned int family) | ||
194 | { | ||
195 | struct xfrm_state_afinfo *afinfo; | ||
196 | if (unlikely(family >= NPROTO)) | ||
197 | return NULL; | ||
198 | write_lock_bh(&xfrm_state_afinfo_lock); | ||
199 | afinfo = xfrm_state_afinfo[family]; | ||
200 | if (unlikely(!afinfo)) | ||
201 | write_unlock_bh(&xfrm_state_afinfo_lock); | ||
202 | return afinfo; | ||
203 | } | ||
204 | |||
205 | static void xfrm_state_unlock_afinfo(struct xfrm_state_afinfo *afinfo) | ||
206 | { | ||
207 | write_unlock_bh(&xfrm_state_afinfo_lock); | ||
208 | } | ||
209 | |||
210 | int xfrm_register_type(struct xfrm_type *type, unsigned short family) | ||
211 | { | ||
212 | struct xfrm_state_afinfo *afinfo = xfrm_state_lock_afinfo(family); | ||
213 | struct xfrm_type **typemap; | ||
214 | int err = 0; | ||
215 | |||
216 | if (unlikely(afinfo == NULL)) | ||
217 | return -EAFNOSUPPORT; | ||
218 | typemap = afinfo->type_map; | ||
219 | |||
220 | if (likely(typemap[type->proto] == NULL)) | ||
221 | typemap[type->proto] = type; | ||
222 | else | ||
223 | err = -EEXIST; | ||
224 | xfrm_state_unlock_afinfo(afinfo); | ||
225 | return err; | ||
226 | } | ||
227 | EXPORT_SYMBOL(xfrm_register_type); | ||
228 | |||
229 | int xfrm_unregister_type(struct xfrm_type *type, unsigned short family) | ||
230 | { | ||
231 | struct xfrm_state_afinfo *afinfo = xfrm_state_lock_afinfo(family); | ||
232 | struct xfrm_type **typemap; | ||
233 | int err = 0; | ||
234 | |||
235 | if (unlikely(afinfo == NULL)) | ||
236 | return -EAFNOSUPPORT; | ||
237 | typemap = afinfo->type_map; | ||
238 | |||
239 | if (unlikely(typemap[type->proto] != type)) | ||
240 | err = -ENOENT; | ||
241 | else | ||
242 | typemap[type->proto] = NULL; | ||
243 | xfrm_state_unlock_afinfo(afinfo); | ||
244 | return err; | ||
245 | } | ||
246 | EXPORT_SYMBOL(xfrm_unregister_type); | ||
247 | |||
248 | static struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family) | ||
249 | { | ||
250 | struct xfrm_state_afinfo *afinfo; | ||
251 | struct xfrm_type **typemap; | ||
252 | struct xfrm_type *type; | ||
253 | int modload_attempted = 0; | ||
254 | |||
255 | retry: | ||
256 | afinfo = xfrm_state_get_afinfo(family); | ||
257 | if (unlikely(afinfo == NULL)) | ||
258 | return NULL; | ||
259 | typemap = afinfo->type_map; | ||
260 | |||
261 | type = typemap[proto]; | ||
262 | if (unlikely(type && !try_module_get(type->owner))) | ||
263 | type = NULL; | ||
264 | if (!type && !modload_attempted) { | ||
265 | xfrm_state_put_afinfo(afinfo); | ||
266 | request_module("xfrm-type-%d-%d", family, proto); | ||
267 | modload_attempted = 1; | ||
268 | goto retry; | ||
269 | } | ||
270 | |||
271 | xfrm_state_put_afinfo(afinfo); | ||
272 | return type; | ||
273 | } | ||
274 | |||
275 | static void xfrm_put_type(struct xfrm_type *type) | ||
276 | { | ||
277 | module_put(type->owner); | ||
278 | } | ||
279 | |||
280 | int xfrm_register_mode(struct xfrm_mode *mode, int family) | ||
281 | { | ||
282 | struct xfrm_state_afinfo *afinfo; | ||
283 | struct xfrm_mode **modemap; | ||
284 | int err; | ||
285 | |||
286 | if (unlikely(mode->encap >= XFRM_MODE_MAX)) | ||
287 | return -EINVAL; | ||
288 | |||
289 | afinfo = xfrm_state_lock_afinfo(family); | ||
290 | if (unlikely(afinfo == NULL)) | ||
291 | return -EAFNOSUPPORT; | ||
292 | |||
293 | err = -EEXIST; | ||
294 | modemap = afinfo->mode_map; | ||
295 | if (modemap[mode->encap]) | ||
296 | goto out; | ||
297 | |||
298 | err = -ENOENT; | ||
299 | if (!try_module_get(afinfo->owner)) | ||
300 | goto out; | ||
301 | |||
302 | mode->afinfo = afinfo; | ||
303 | modemap[mode->encap] = mode; | ||
304 | err = 0; | ||
305 | |||
306 | out: | ||
307 | xfrm_state_unlock_afinfo(afinfo); | ||
308 | return err; | ||
309 | } | ||
310 | EXPORT_SYMBOL(xfrm_register_mode); | ||
311 | |||
312 | int xfrm_unregister_mode(struct xfrm_mode *mode, int family) | ||
313 | { | ||
314 | struct xfrm_state_afinfo *afinfo; | ||
315 | struct xfrm_mode **modemap; | ||
316 | int err; | ||
317 | |||
318 | if (unlikely(mode->encap >= XFRM_MODE_MAX)) | ||
319 | return -EINVAL; | ||
320 | |||
321 | afinfo = xfrm_state_lock_afinfo(family); | ||
322 | if (unlikely(afinfo == NULL)) | ||
323 | return -EAFNOSUPPORT; | ||
324 | |||
325 | err = -ENOENT; | ||
326 | modemap = afinfo->mode_map; | ||
327 | if (likely(modemap[mode->encap] == mode)) { | ||
328 | modemap[mode->encap] = NULL; | ||
329 | module_put(mode->afinfo->owner); | ||
330 | err = 0; | ||
331 | } | ||
332 | |||
333 | xfrm_state_unlock_afinfo(afinfo); | ||
334 | return err; | ||
335 | } | ||
336 | EXPORT_SYMBOL(xfrm_unregister_mode); | ||
337 | |||
338 | static struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family) | ||
339 | { | ||
340 | struct xfrm_state_afinfo *afinfo; | ||
341 | struct xfrm_mode *mode; | ||
342 | int modload_attempted = 0; | ||
343 | |||
344 | if (unlikely(encap >= XFRM_MODE_MAX)) | ||
345 | return NULL; | ||
346 | |||
347 | retry: | ||
348 | afinfo = xfrm_state_get_afinfo(family); | ||
349 | if (unlikely(afinfo == NULL)) | ||
350 | return NULL; | ||
351 | |||
352 | mode = afinfo->mode_map[encap]; | ||
353 | if (unlikely(mode && !try_module_get(mode->owner))) | ||
354 | mode = NULL; | ||
355 | if (!mode && !modload_attempted) { | ||
356 | xfrm_state_put_afinfo(afinfo); | ||
357 | request_module("xfrm-mode-%d-%d", family, encap); | ||
358 | modload_attempted = 1; | ||
359 | goto retry; | ||
360 | } | ||
361 | |||
362 | xfrm_state_put_afinfo(afinfo); | ||
363 | return mode; | ||
364 | } | ||
365 | |||
366 | static void xfrm_put_mode(struct xfrm_mode *mode) | ||
367 | { | ||
368 | module_put(mode->owner); | ||
369 | } | ||
370 | |||
190 | static void xfrm_state_gc_destroy(struct xfrm_state *x) | 371 | static void xfrm_state_gc_destroy(struct xfrm_state *x) |
191 | { | 372 | { |
192 | del_timer_sync(&x->timer); | 373 | del_timer_sync(&x->timer); |
@@ -196,8 +377,10 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) | |||
196 | kfree(x->calg); | 377 | kfree(x->calg); |
197 | kfree(x->encap); | 378 | kfree(x->encap); |
198 | kfree(x->coaddr); | 379 | kfree(x->coaddr); |
199 | if (x->mode) | 380 | if (x->inner_mode) |
200 | xfrm_put_mode(x->mode); | 381 | xfrm_put_mode(x->inner_mode); |
382 | if (x->outer_mode) | ||
383 | xfrm_put_mode(x->outer_mode); | ||
201 | if (x->type) { | 384 | if (x->type) { |
202 | x->type->destructor(x); | 385 | x->type->destructor(x); |
203 | xfrm_put_type(x->type); | 386 | xfrm_put_type(x->type); |
@@ -1699,7 +1882,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo) | |||
1699 | } | 1882 | } |
1700 | EXPORT_SYMBOL(xfrm_state_unregister_afinfo); | 1883 | EXPORT_SYMBOL(xfrm_state_unregister_afinfo); |
1701 | 1884 | ||
1702 | struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family) | 1885 | static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family) |
1703 | { | 1886 | { |
1704 | struct xfrm_state_afinfo *afinfo; | 1887 | struct xfrm_state_afinfo *afinfo; |
1705 | if (unlikely(family >= NPROTO)) | 1888 | if (unlikely(family >= NPROTO)) |
@@ -1711,14 +1894,11 @@ struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family) | |||
1711 | return afinfo; | 1894 | return afinfo; |
1712 | } | 1895 | } |
1713 | 1896 | ||
1714 | void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo) | 1897 | static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo) |
1715 | { | 1898 | { |
1716 | read_unlock(&xfrm_state_afinfo_lock); | 1899 | read_unlock(&xfrm_state_afinfo_lock); |
1717 | } | 1900 | } |
1718 | 1901 | ||
1719 | EXPORT_SYMBOL(xfrm_state_get_afinfo); | ||
1720 | EXPORT_SYMBOL(xfrm_state_put_afinfo); | ||
1721 | |||
1722 | /* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */ | 1902 | /* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */ |
1723 | void xfrm_state_delete_tunnel(struct xfrm_state *x) | 1903 | void xfrm_state_delete_tunnel(struct xfrm_state *x) |
1724 | { | 1904 | { |
@@ -1769,6 +1949,14 @@ int xfrm_init_state(struct xfrm_state *x) | |||
1769 | goto error; | 1949 | goto error; |
1770 | 1950 | ||
1771 | err = -EPROTONOSUPPORT; | 1951 | err = -EPROTONOSUPPORT; |
1952 | x->inner_mode = xfrm_get_mode(x->props.mode, x->sel.family); | ||
1953 | if (x->inner_mode == NULL) | ||
1954 | goto error; | ||
1955 | |||
1956 | if (!(x->inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) && | ||
1957 | family != x->sel.family) | ||
1958 | goto error; | ||
1959 | |||
1772 | x->type = xfrm_get_type(x->id.proto, family); | 1960 | x->type = xfrm_get_type(x->id.proto, family); |
1773 | if (x->type == NULL) | 1961 | if (x->type == NULL) |
1774 | goto error; | 1962 | goto error; |
@@ -1777,8 +1965,8 @@ int xfrm_init_state(struct xfrm_state *x) | |||
1777 | if (err) | 1965 | if (err) |
1778 | goto error; | 1966 | goto error; |
1779 | 1967 | ||
1780 | x->mode = xfrm_get_mode(x->props.mode, family); | 1968 | x->outer_mode = xfrm_get_mode(x->props.mode, family); |
1781 | if (x->mode == NULL) | 1969 | if (x->outer_mode == NULL) |
1782 | goto error; | 1970 | goto error; |
1783 | 1971 | ||
1784 | x->km.state = XFRM_STATE_VALID; | 1972 | x->km.state = XFRM_STATE_VALID; |