diff options
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r-- | net/xfrm/xfrm_state.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index dc438f2b9442..48b4a06b3d1a 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, |
@@ -289,11 +292,18 @@ int xfrm_register_mode(struct xfrm_mode *mode, int family) | |||
289 | 292 | ||
290 | err = -EEXIST; | 293 | err = -EEXIST; |
291 | modemap = afinfo->mode_map; | 294 | modemap = afinfo->mode_map; |
292 | if (likely(modemap[mode->encap] == NULL)) { | 295 | if (modemap[mode->encap]) |
293 | modemap[mode->encap] = mode; | 296 | goto out; |
294 | err = 0; | ||
295 | } | ||
296 | 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: | ||
297 | xfrm_state_unlock_afinfo(afinfo); | 307 | xfrm_state_unlock_afinfo(afinfo); |
298 | return err; | 308 | return err; |
299 | } | 309 | } |
@@ -316,6 +326,7 @@ int xfrm_unregister_mode(struct xfrm_mode *mode, int family) | |||
316 | modemap = afinfo->mode_map; | 326 | modemap = afinfo->mode_map; |
317 | if (likely(modemap[mode->encap] == mode)) { | 327 | if (likely(modemap[mode->encap] == mode)) { |
318 | modemap[mode->encap] = NULL; | 328 | modemap[mode->encap] = NULL; |
329 | module_put(mode->afinfo->owner); | ||
319 | err = 0; | 330 | err = 0; |
320 | } | 331 | } |
321 | 332 | ||
@@ -1869,7 +1880,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo) | |||
1869 | } | 1880 | } |
1870 | EXPORT_SYMBOL(xfrm_state_unregister_afinfo); | 1881 | EXPORT_SYMBOL(xfrm_state_unregister_afinfo); |
1871 | 1882 | ||
1872 | struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family) | 1883 | static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family) |
1873 | { | 1884 | { |
1874 | struct xfrm_state_afinfo *afinfo; | 1885 | struct xfrm_state_afinfo *afinfo; |
1875 | if (unlikely(family >= NPROTO)) | 1886 | if (unlikely(family >= NPROTO)) |
@@ -1881,14 +1892,11 @@ struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family) | |||
1881 | return afinfo; | 1892 | return afinfo; |
1882 | } | 1893 | } |
1883 | 1894 | ||
1884 | void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo) | 1895 | static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo) |
1885 | { | 1896 | { |
1886 | read_unlock(&xfrm_state_afinfo_lock); | 1897 | read_unlock(&xfrm_state_afinfo_lock); |
1887 | } | 1898 | } |
1888 | 1899 | ||
1889 | EXPORT_SYMBOL(xfrm_state_get_afinfo); | ||
1890 | EXPORT_SYMBOL(xfrm_state_put_afinfo); | ||
1891 | |||
1892 | /* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */ | 1900 | /* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */ |
1893 | void xfrm_state_delete_tunnel(struct xfrm_state *x) | 1901 | void xfrm_state_delete_tunnel(struct xfrm_state *x) |
1894 | { | 1902 | { |