]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - net/xfrm/xfrm_state.c
[XFRM]: Do not define km_migrate() if !CONFIG_XFRM_MIGRATE
[mv-sheeva.git] / net / xfrm / xfrm_state.c
index dc438f2b944226a26ec45033d5ff73cffe8dc433..f26aaaca1fae78dd92efe9d4e456e2dc1e60d822 100644 (file)
@@ -57,6 +57,9 @@ static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
 static unsigned int xfrm_state_num;
 static unsigned int xfrm_state_genid;
 
+static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
+static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
+
 static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr,
                                         xfrm_address_t *saddr,
                                         u32 reqid,
@@ -289,11 +292,18 @@ int xfrm_register_mode(struct xfrm_mode *mode, int family)
 
        err = -EEXIST;
        modemap = afinfo->mode_map;
-       if (likely(modemap[mode->encap] == NULL)) {
-               modemap[mode->encap] = mode;
-               err = 0;
-       }
+       if (modemap[mode->encap])
+               goto out;
+
+       err = -ENOENT;
+       if (!try_module_get(afinfo->owner))
+               goto out;
+
+       mode->afinfo = afinfo;
+       modemap[mode->encap] = mode;
+       err = 0;
 
+out:
        xfrm_state_unlock_afinfo(afinfo);
        return err;
 }
@@ -316,6 +326,7 @@ int xfrm_unregister_mode(struct xfrm_mode *mode, int family)
        modemap = afinfo->mode_map;
        if (likely(modemap[mode->encap] == mode)) {
                modemap[mode->encap] = NULL;
+               module_put(mode->afinfo->owner);
                err = 0;
        }
 
@@ -366,8 +377,10 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
        kfree(x->calg);
        kfree(x->encap);
        kfree(x->coaddr);
-       if (x->mode)
-               xfrm_put_mode(x->mode);
+       if (x->inner_mode)
+               xfrm_put_mode(x->inner_mode);
+       if (x->outer_mode)
+               xfrm_put_mode(x->outer_mode);
        if (x->type) {
                x->type->destructor(x);
                xfrm_put_type(x->type);
@@ -539,7 +552,7 @@ int __xfrm_state_delete(struct xfrm_state *x)
                 * The xfrm_state_alloc call gives a reference, and that
                 * is what we are dropping here.
                 */
-               __xfrm_state_put(x);
+               xfrm_state_put(x);
                err = 0;
        }
 
@@ -1736,6 +1749,7 @@ void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid)
 }
 EXPORT_SYMBOL(km_policy_expired);
 
+#ifdef CONFIG_XFRM_MIGRATE
 int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
               struct xfrm_migrate *m, int num_migrate)
 {
@@ -1755,6 +1769,7 @@ int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
        return err;
 }
 EXPORT_SYMBOL(km_migrate);
+#endif
 
 int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr)
 {
@@ -1869,7 +1884,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
 }
 EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
 
-struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family)
+static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family)
 {
        struct xfrm_state_afinfo *afinfo;
        if (unlikely(family >= NPROTO))
@@ -1881,14 +1896,11 @@ struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family)
        return afinfo;
 }
 
-void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
+static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
 {
        read_unlock(&xfrm_state_afinfo_lock);
 }
 
-EXPORT_SYMBOL(xfrm_state_get_afinfo);
-EXPORT_SYMBOL(xfrm_state_put_afinfo);
-
 /* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */
 void xfrm_state_delete_tunnel(struct xfrm_state *x)
 {
@@ -1939,6 +1951,14 @@ int xfrm_init_state(struct xfrm_state *x)
                goto error;
 
        err = -EPROTONOSUPPORT;
+       x->inner_mode = xfrm_get_mode(x->props.mode, x->sel.family);
+       if (x->inner_mode == NULL)
+               goto error;
+
+       if (!(x->inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
+           family != x->sel.family)
+               goto error;
+
        x->type = xfrm_get_type(x->id.proto, family);
        if (x->type == NULL)
                goto error;
@@ -1947,8 +1967,8 @@ int xfrm_init_state(struct xfrm_state *x)
        if (err)
                goto error;
 
-       x->mode = xfrm_get_mode(x->props.mode, family);
-       if (x->mode == NULL)
+       x->outer_mode = xfrm_get_mode(x->props.mode, family);
+       if (x->outer_mode == NULL)
                goto error;
 
        x->km.state = XFRM_STATE_VALID;
@@ -2010,17 +2030,18 @@ void
 xfrm_audit_state_add(struct xfrm_state *x, int result, u32 auid, u32 sid)
 {
        struct audit_buffer *audit_buf;
+       u32 spi;
        extern int audit_enabled;
 
        if (audit_enabled == 0)
                return;
-       audit_buf = xfrm_audit_start(sid, auid);
+       audit_buf = xfrm_audit_start(auid, sid);
        if (audit_buf == NULL)
                return;
        audit_log_format(audit_buf, " op=SAD-add res=%u",result);
        xfrm_audit_common_stateinfo(x, audit_buf);
-       audit_log_format(audit_buf, " spi=%lu(0x%lx)",
-                        (unsigned long)x->id.spi, (unsigned long)x->id.spi);
+       spi = ntohl(x->id.spi);
+       audit_log_format(audit_buf, " spi=%u(0x%x)", spi, spi);
        audit_log_end(audit_buf);
 }
 EXPORT_SYMBOL_GPL(xfrm_audit_state_add);
@@ -2029,17 +2050,18 @@ void
 xfrm_audit_state_delete(struct xfrm_state *x, int result, u32 auid, u32 sid)
 {
        struct audit_buffer *audit_buf;
+       u32 spi;
        extern int audit_enabled;
 
        if (audit_enabled == 0)
                return;
-       audit_buf = xfrm_audit_start(sid, auid);
+       audit_buf = xfrm_audit_start(auid, sid);
        if (audit_buf == NULL)
                return;
        audit_log_format(audit_buf, " op=SAD-delete res=%u",result);
        xfrm_audit_common_stateinfo(x, audit_buf);
-       audit_log_format(audit_buf, " spi=%lu(0x%lx)",
-                        (unsigned long)x->id.spi, (unsigned long)x->id.spi);
+       spi = ntohl(x->id.spi);
+       audit_log_format(audit_buf, " spi=%u(0x%x)", spi, spi);
        audit_log_end(audit_buf);
 }
 EXPORT_SYMBOL_GPL(xfrm_audit_state_delete);