aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/xfrm.h6
-rw-r--r--net/ipv4/xfrm4_policy.c13
-rw-r--r--net/ipv4/xfrm4_state.c1
-rw-r--r--net/ipv6/xfrm6_policy.c14
-rw-r--r--net/ipv6/xfrm6_state.c1
-rw-r--r--net/xfrm/xfrm_state.c26
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);
253extern int __xfrm_state_delete(struct xfrm_state *x); 253extern int __xfrm_state_delete(struct xfrm_state *x);
254 254
255struct xfrm_state_afinfo { 255struct 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
268extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo); 269extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
269extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo); 270extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
270extern struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
271extern void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
272 271
273extern void xfrm_state_delete_tunnel(struct xfrm_state *x); 272extern 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
50static struct xfrm_state_afinfo xfrm4_state_afinfo = { 50static 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
171static struct xfrm_state_afinfo xfrm6_state_afinfo = { 171static 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;
57static unsigned int xfrm_state_num; 57static unsigned int xfrm_state_num;
58static unsigned int xfrm_state_genid; 58static unsigned int xfrm_state_genid;
59 59
60static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
61static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
62
60static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, 63static 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
306out:
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}
1870EXPORT_SYMBOL(xfrm_state_unregister_afinfo); 1881EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
1871 1882
1872struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family) 1883static 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
1884void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo) 1895static 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
1889EXPORT_SYMBOL(xfrm_state_get_afinfo);
1890EXPORT_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 */
1893void xfrm_state_delete_tunnel(struct xfrm_state *x) 1901void xfrm_state_delete_tunnel(struct xfrm_state *x)
1894{ 1902{