diff options
-rw-r--r-- | include/net/xfrm.h | 6 | ||||
-rw-r--r-- | net/ipv4/xfrm4_policy.c | 13 | ||||
-rw-r--r-- | net/ipv4/xfrm4_state.c | 1 | ||||
-rw-r--r-- | net/ipv6/xfrm6_policy.c | 14 | ||||
-rw-r--r-- | net/ipv6/xfrm6_state.c | 1 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 26 |
6 files changed, 24 insertions, 37 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 2143f2911a21..f0f3318f6550 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -253,7 +253,8 @@ extern void km_state_expired(struct xfrm_state *x, int hard, u32 pid); | |||
253 | extern int __xfrm_state_delete(struct xfrm_state *x); | 253 | extern int __xfrm_state_delete(struct xfrm_state *x); |
254 | 254 | ||
255 | struct xfrm_state_afinfo { | 255 | struct xfrm_state_afinfo { |
256 | unsigned short family; | 256 | unsigned int family; |
257 | struct module *owner; | ||
257 | struct xfrm_type *type_map[IPPROTO_MAX]; | 258 | struct xfrm_type *type_map[IPPROTO_MAX]; |
258 | struct xfrm_mode *mode_map[XFRM_MODE_MAX]; | 259 | struct xfrm_mode *mode_map[XFRM_MODE_MAX]; |
259 | int (*init_flags)(struct xfrm_state *x); | 260 | int (*init_flags)(struct xfrm_state *x); |
@@ -267,8 +268,6 @@ struct xfrm_state_afinfo { | |||
267 | 268 | ||
268 | extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo); | 269 | extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo); |
269 | extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo); | 270 | extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo); |
270 | extern struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family); | ||
271 | extern void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); | ||
272 | 271 | ||
273 | extern void xfrm_state_delete_tunnel(struct xfrm_state *x); | 272 | extern void xfrm_state_delete_tunnel(struct xfrm_state *x); |
274 | 273 | ||
@@ -312,6 +311,7 @@ struct xfrm_mode { | |||
312 | */ | 311 | */ |
313 | int (*output)(struct xfrm_state *x,struct sk_buff *skb); | 312 | int (*output)(struct xfrm_state *x,struct sk_buff *skb); |
314 | 313 | ||
314 | struct xfrm_state_afinfo *afinfo; | ||
315 | struct module *owner; | 315 | struct module *owner; |
316 | unsigned int encap; | 316 | unsigned int encap; |
317 | int flags; | 317 | int flags; |
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 2373d673df60..c65b8e03c049 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -151,7 +151,6 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int | |||
151 | i = 0; | 151 | i = 0; |
152 | for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) { | 152 | for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) { |
153 | struct xfrm_dst *x = (struct xfrm_dst*)dst_prev; | 153 | struct xfrm_dst *x = (struct xfrm_dst*)dst_prev; |
154 | struct xfrm_state_afinfo *afinfo; | ||
155 | x->u.rt.fl = *fl; | 154 | x->u.rt.fl = *fl; |
156 | 155 | ||
157 | dst_prev->xfrm = xfrm[i++]; | 156 | dst_prev->xfrm = xfrm[i++]; |
@@ -169,17 +168,7 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int | |||
169 | /* Copy neighbout for reachability confirmation */ | 168 | /* Copy neighbout for reachability confirmation */ |
170 | dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour); | 169 | dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour); |
171 | dst_prev->input = rt->u.dst.input; | 170 | dst_prev->input = rt->u.dst.input; |
172 | /* XXX: When IPv6 module can be unloaded, we should manage reference | 171 | dst_prev->output = dst_prev->xfrm->mode->afinfo->output; |
173 | * to xfrm6_output in afinfo->output. Miyazawa | ||
174 | * */ | ||
175 | afinfo = xfrm_state_get_afinfo(dst_prev->xfrm->props.family); | ||
176 | if (!afinfo) { | ||
177 | dst = *dst_p; | ||
178 | err = -EAFNOSUPPORT; | ||
179 | goto error; | ||
180 | } | ||
181 | dst_prev->output = afinfo->output; | ||
182 | xfrm_state_put_afinfo(afinfo); | ||
183 | if (dst_prev->xfrm->props.family == AF_INET && rt->peer) | 172 | if (dst_prev->xfrm->props.family == AF_INET && rt->peer) |
184 | atomic_inc(&rt->peer->refcnt); | 173 | atomic_inc(&rt->peer->refcnt); |
185 | x->u.rt.peer = rt->peer; | 174 | x->u.rt.peer = rt->peer; |
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index 93e2c061cdda..13d54a1c3337 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c | |||
@@ -49,6 +49,7 @@ __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl, | |||
49 | 49 | ||
50 | static struct xfrm_state_afinfo xfrm4_state_afinfo = { | 50 | static struct xfrm_state_afinfo xfrm4_state_afinfo = { |
51 | .family = AF_INET, | 51 | .family = AF_INET, |
52 | .owner = THIS_MODULE, | ||
52 | .init_flags = xfrm4_init_flags, | 53 | .init_flags = xfrm4_init_flags, |
53 | .init_tempsel = __xfrm4_init_tempsel, | 54 | .init_tempsel = __xfrm4_init_tempsel, |
54 | .output = xfrm4_output, | 55 | .output = xfrm4_output, |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index dc4bdcb55cbe..324268329f69 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -214,7 +214,6 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int | |||
214 | i = 0; | 214 | i = 0; |
215 | for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) { | 215 | for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) { |
216 | struct xfrm_dst *x = (struct xfrm_dst*)dst_prev; | 216 | struct xfrm_dst *x = (struct xfrm_dst*)dst_prev; |
217 | struct xfrm_state_afinfo *afinfo; | ||
218 | 217 | ||
219 | dst_prev->xfrm = xfrm[i++]; | 218 | dst_prev->xfrm = xfrm[i++]; |
220 | dst_prev->dev = rt->u.dst.dev; | 219 | dst_prev->dev = rt->u.dst.dev; |
@@ -231,18 +230,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int | |||
231 | /* Copy neighbour for reachability confirmation */ | 230 | /* Copy neighbour for reachability confirmation */ |
232 | dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour); | 231 | dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour); |
233 | dst_prev->input = rt->u.dst.input; | 232 | dst_prev->input = rt->u.dst.input; |
234 | /* XXX: When IPv4 is implemented as module and can be unloaded, | 233 | dst_prev->output = dst_prev->xfrm->mode->afinfo->output; |
235 | * we should manage reference to xfrm4_output in afinfo->output. | ||
236 | * Miyazawa | ||
237 | */ | ||
238 | afinfo = xfrm_state_get_afinfo(dst_prev->xfrm->props.family); | ||
239 | if (!afinfo) { | ||
240 | dst = *dst_p; | ||
241 | goto error; | ||
242 | } | ||
243 | |||
244 | dst_prev->output = afinfo->output; | ||
245 | xfrm_state_put_afinfo(afinfo); | ||
246 | /* Sheit... I remember I did this right. Apparently, | 234 | /* Sheit... I remember I did this right. Apparently, |
247 | * it was magically lost, so this code needs audit */ | 235 | * it was magically lost, so this code needs audit */ |
248 | x->u.rt6.rt6i_flags = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL); | 236 | x->u.rt6.rt6i_flags = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL); |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index e644c80515fc..b392bee396f1 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -170,6 +170,7 @@ __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n) | |||
170 | 170 | ||
171 | static struct xfrm_state_afinfo xfrm6_state_afinfo = { | 171 | static struct xfrm_state_afinfo xfrm6_state_afinfo = { |
172 | .family = AF_INET6, | 172 | .family = AF_INET6, |
173 | .owner = THIS_MODULE, | ||
173 | .init_tempsel = __xfrm6_init_tempsel, | 174 | .init_tempsel = __xfrm6_init_tempsel, |
174 | .tmpl_sort = __xfrm6_tmpl_sort, | 175 | .tmpl_sort = __xfrm6_tmpl_sort, |
175 | .state_sort = __xfrm6_state_sort, | 176 | .state_sort = __xfrm6_state_sort, |
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 | { |