X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fxfrm%2Fxfrm_policy.c;h=b469c8b54613354a495db0fc4996aa5916e53829;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=3da67ca2c3ce9890b9774e4d2757d3f33928c493;hpb=41689045f6a3cbe0550e1d34e9cc20d2e8c432ba;p=linux-2.6.git diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 3da67ca2c..b469c8b54 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -13,6 +13,7 @@ * */ +#include #include #include #include @@ -45,43 +46,45 @@ static DEFINE_SPINLOCK(xfrm_policy_gc_lock); static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family); static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo); -static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family); -static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo); int xfrm_register_type(struct xfrm_type *type, unsigned short family) { - struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family); - struct xfrm_type **typemap; + struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); + struct xfrm_type_map *typemap; int err = 0; if (unlikely(afinfo == NULL)) return -EAFNOSUPPORT; typemap = afinfo->type_map; - if (likely(typemap[type->proto] == NULL)) - typemap[type->proto] = type; + write_lock_bh(&typemap->lock); + if (likely(typemap->map[type->proto] == NULL)) + typemap->map[type->proto] = type; else err = -EEXIST; - xfrm_policy_unlock_afinfo(afinfo); + write_unlock_bh(&typemap->lock); + xfrm_policy_put_afinfo(afinfo); return err; } EXPORT_SYMBOL(xfrm_register_type); int xfrm_unregister_type(struct xfrm_type *type, unsigned short family) { - struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family); - struct xfrm_type **typemap; + struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); + struct xfrm_type_map *typemap; int err = 0; if (unlikely(afinfo == NULL)) return -EAFNOSUPPORT; typemap = afinfo->type_map; - if (unlikely(typemap[type->proto] != type)) + write_lock_bh(&typemap->lock); + if (unlikely(typemap->map[type->proto] != type)) err = -ENOENT; else - typemap[type->proto] = NULL; - xfrm_policy_unlock_afinfo(afinfo); + typemap->map[type->proto] = NULL; + write_unlock_bh(&typemap->lock); + xfrm_policy_put_afinfo(afinfo); return err; } EXPORT_SYMBOL(xfrm_unregister_type); @@ -89,7 +92,7 @@ EXPORT_SYMBOL(xfrm_unregister_type); struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family) { struct xfrm_policy_afinfo *afinfo; - struct xfrm_type **typemap; + struct xfrm_type_map *typemap; struct xfrm_type *type; int modload_attempted = 0; @@ -99,9 +102,11 @@ retry: return NULL; typemap = afinfo->type_map; - type = typemap[proto]; + read_lock(&typemap->lock); + type = typemap->map[proto]; if (unlikely(type && !try_module_get(type->owner))) type = NULL; + read_unlock(&typemap->lock); if (!type && !modload_attempted) { xfrm_policy_put_afinfo(afinfo); request_module("xfrm-type-%d-%d", @@ -137,89 +142,6 @@ void xfrm_put_type(struct xfrm_type *type) module_put(type->owner); } -int xfrm_register_mode(struct xfrm_mode *mode, int family) -{ - struct xfrm_policy_afinfo *afinfo; - struct xfrm_mode **modemap; - int err; - - if (unlikely(mode->encap >= XFRM_MODE_MAX)) - return -EINVAL; - - afinfo = xfrm_policy_lock_afinfo(family); - if (unlikely(afinfo == NULL)) - return -EAFNOSUPPORT; - - err = -EEXIST; - modemap = afinfo->mode_map; - if (likely(modemap[mode->encap] == NULL)) { - modemap[mode->encap] = mode; - err = 0; - } - - xfrm_policy_unlock_afinfo(afinfo); - return err; -} -EXPORT_SYMBOL(xfrm_register_mode); - -int xfrm_unregister_mode(struct xfrm_mode *mode, int family) -{ - struct xfrm_policy_afinfo *afinfo; - struct xfrm_mode **modemap; - int err; - - if (unlikely(mode->encap >= XFRM_MODE_MAX)) - return -EINVAL; - - afinfo = xfrm_policy_lock_afinfo(family); - if (unlikely(afinfo == NULL)) - return -EAFNOSUPPORT; - - err = -ENOENT; - modemap = afinfo->mode_map; - if (likely(modemap[mode->encap] == mode)) { - modemap[mode->encap] = NULL; - err = 0; - } - - xfrm_policy_unlock_afinfo(afinfo); - return err; -} -EXPORT_SYMBOL(xfrm_unregister_mode); - -struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family) -{ - struct xfrm_policy_afinfo *afinfo; - struct xfrm_mode *mode; - int modload_attempted = 0; - - if (unlikely(encap >= XFRM_MODE_MAX)) - return NULL; - -retry: - afinfo = xfrm_policy_get_afinfo(family); - if (unlikely(afinfo == NULL)) - return NULL; - - mode = afinfo->mode_map[encap]; - if (unlikely(mode && !try_module_get(mode->owner))) - mode = NULL; - if (!mode && !modload_attempted) { - xfrm_policy_put_afinfo(afinfo); - request_module("xfrm-mode-%d-%d", family, encap); - modload_attempted = 1; - goto retry; - } - - xfrm_policy_put_afinfo(afinfo); - return mode; -} - -void xfrm_put_mode(struct xfrm_mode *mode) -{ - module_put(mode->owner); -} - static inline unsigned long make_jiffies(long secs) { if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ) @@ -307,9 +229,10 @@ struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp) { struct xfrm_policy *policy; - policy = kzalloc(sizeof(struct xfrm_policy), gfp); + policy = kmalloc(sizeof(struct xfrm_policy), gfp); if (policy) { + memset(policy, 0, sizeof(struct xfrm_policy)); atomic_set(&policy->refcnt, 1); rwlock_init(&policy->lock); init_timer(&policy->timer); @@ -1134,33 +1057,12 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) } EXPORT_SYMBOL(__xfrm_route_forward); -/* Optimize later using cookies and generation ids. */ - static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) { - /* Code (such as __xfrm4_bundle_create()) sets dst->obsolete - * to "-1" to force all XFRM destinations to get validated by - * dst_ops->check on every use. We do this because when a - * normal route referenced by an XFRM dst is obsoleted we do - * not go looking around for all parent referencing XFRM dsts - * so that we can invalidate them. It is just too much work. - * Instead we make the checks here on every use. For example: - * - * XFRM dst A --> IPv4 dst X - * - * X is the "xdst->route" of A (X is also the "dst->path" of A - * in this example). If X is marked obsolete, "A" will not - * notice. That's what we are validating here via the - * stale_bundle() check. - * - * When a policy's bundle is pruned, we dst_free() the XFRM - * dst which causes it's ->obsolete field to be set to a - * positive non-zero integer. If an XFRM dst has been pruned - * like this, we want to force a new route lookup. + /* If it is marked obsolete, which is how we even get here, + * then we have purged it from the policy bundle list and we + * did that for a good reason. */ - if (dst->obsolete < 0 && !stale_bundle(dst)) - return dst; - return NULL; } @@ -1404,31 +1306,17 @@ static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family) return NULL; read_lock(&xfrm_policy_afinfo_lock); afinfo = xfrm_policy_afinfo[family]; - if (unlikely(!afinfo)) - read_unlock(&xfrm_policy_afinfo_lock); - return afinfo; -} - -static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo) -{ + if (likely(afinfo != NULL)) + read_lock(&afinfo->lock); read_unlock(&xfrm_policy_afinfo_lock); -} - -static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family) -{ - struct xfrm_policy_afinfo *afinfo; - if (unlikely(family >= NPROTO)) - return NULL; - write_lock_bh(&xfrm_policy_afinfo_lock); - afinfo = xfrm_policy_afinfo[family]; - if (unlikely(!afinfo)) - write_unlock_bh(&xfrm_policy_afinfo_lock); return afinfo; } -static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo) +static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo) { - write_unlock_bh(&xfrm_policy_afinfo_lock); + if (unlikely(afinfo == NULL)) + return; + read_unlock(&afinfo->lock); } static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)