X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=net%2Fxfrm%2Fxfrm_state.c;h=72fddafd891a0b3f3be603804e6c5727a56a5b3d;hb=2106b531eaa2edd0c2dfa735a0556c08c7ba3c86;hp=58f1f9347b54515e0bdfe534940adf3263d40755;hpb=858c52d15f186e055dc33a1872f5b45a66d42296;p=linux-2.6-omap-h63xx.git diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 58f1f9347b5..72fddafd891 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -50,6 +50,7 @@ static DEFINE_SPINLOCK(xfrm_state_lock); * Main use is finding SA after policy selected tunnel or transport mode. * Also, it can be used by ah/esp icmp error handler to find offending SA. */ +static LIST_HEAD(xfrm_state_all); static struct hlist_head *xfrm_state_bydst __read_mostly; static struct hlist_head *xfrm_state_bysrc __read_mostly; static struct hlist_head *xfrm_state_byspi __read_mostly; @@ -495,7 +496,8 @@ expired: km_state_expired(x, 1, 0); xfrm_audit_state_delete(x, err ? 0 : 1, - audit_get_loginuid(current), 0); + audit_get_loginuid(current), + audit_get_sessionid(current), 0); out: spin_unlock(&x->lock); @@ -512,6 +514,7 @@ struct xfrm_state *xfrm_state_alloc(void) if (x) { atomic_set(&x->refcnt, 1); atomic_set(&x->tunnel_users, 0); + INIT_LIST_HEAD(&x->all); INIT_HLIST_NODE(&x->bydst); INIT_HLIST_NODE(&x->bysrc); INIT_HLIST_NODE(&x->byspi); @@ -537,6 +540,10 @@ void __xfrm_state_destroy(struct xfrm_state *x) { BUG_TRAP(x->km.state == XFRM_STATE_DEAD); + spin_lock_bh(&xfrm_state_lock); + list_del(&x->all); + spin_unlock_bh(&xfrm_state_lock); + spin_lock_bh(&xfrm_state_gc_lock); hlist_add_head(&x->bydst, &xfrm_state_gc_list); spin_unlock_bh(&xfrm_state_gc_lock); @@ -597,6 +604,7 @@ xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info) (err = security_xfrm_state_delete(x)) != 0) { xfrm_audit_state_delete(x, 0, audit_info->loginuid, + audit_info->sessionid, audit_info->secid); return err; } @@ -635,6 +643,7 @@ restart: err = xfrm_state_delete(x); xfrm_audit_state_delete(x, err ? 0 : 1, audit_info->loginuid, + audit_info->sessionid, audit_info->secid); xfrm_state_put(x); @@ -913,6 +922,8 @@ static void __xfrm_state_insert(struct xfrm_state *x) x->genid = ++xfrm_state_genid; + list_add_tail(&x->all, &xfrm_state_all); + h = xfrm_dst_hash(&x->id.daddr, &x->props.saddr, x->props.reqid, x->props.family); hlist_add_head(&x->bydst, xfrm_state_bydst+h); @@ -1522,36 +1533,47 @@ unlock: } EXPORT_SYMBOL(xfrm_alloc_spi); -int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), +int xfrm_state_walk(struct xfrm_state_walk *walk, + int (*func)(struct xfrm_state *, int, void*), void *data) { - int i; - struct xfrm_state *x, *last = NULL; - struct hlist_node *entry; - int count = 0; + struct xfrm_state *old, *x, *last = NULL; int err = 0; + if (walk->state == NULL && walk->count != 0) + return 0; + + old = x = walk->state; + walk->state = NULL; spin_lock_bh(&xfrm_state_lock); - for (i = 0; i <= xfrm_state_hmask; i++) { - hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) { - if (!xfrm_id_proto_match(x->id.proto, proto)) - continue; - if (last) { - err = func(last, count, data); - if (err) - goto out; + if (x == NULL) + x = list_first_entry(&xfrm_state_all, struct xfrm_state, all); + list_for_each_entry_from(x, &xfrm_state_all, all) { + if (x->km.state == XFRM_STATE_DEAD) + continue; + if (!xfrm_id_proto_match(x->id.proto, walk->proto)) + continue; + if (last) { + err = func(last, walk->count, data); + if (err) { + xfrm_state_hold(last); + walk->state = last; + goto out; } - last = x; - count++; } + last = x; + walk->count++; } - if (count == 0) { + if (walk->count == 0) { err = -ENOENT; goto out; } - err = func(last, 0, data); + if (last) + err = func(last, 0, data); out: spin_unlock_bh(&xfrm_state_lock); + if (old != NULL) + xfrm_state_put(old); return err; } EXPORT_SYMBOL(xfrm_state_walk); @@ -2093,7 +2115,7 @@ static void xfrm_audit_helper_pktinfo(struct sk_buff *skb, u16 family, iph6 = ipv6_hdr(skb); audit_log_format(audit_buf, " src=" NIP6_FMT " dst=" NIP6_FMT - " flowlbl=0x%x%x%x", + " flowlbl=0x%x%02x%02x", NIP6(iph6->saddr), NIP6(iph6->daddr), iph6->flow_lbl[0] & 0x0f, @@ -2104,14 +2126,14 @@ static void xfrm_audit_helper_pktinfo(struct sk_buff *skb, u16 family, } void xfrm_audit_state_add(struct xfrm_state *x, int result, - u32 auid, u32 secid) + uid_t auid, u32 sessionid, u32 secid) { struct audit_buffer *audit_buf; audit_buf = xfrm_audit_start("SAD-add"); if (audit_buf == NULL) return; - xfrm_audit_helper_usrinfo(auid, secid, audit_buf); + xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf); xfrm_audit_helper_sainfo(x, audit_buf); audit_log_format(audit_buf, " res=%u", result); audit_log_end(audit_buf); @@ -2119,14 +2141,14 @@ void xfrm_audit_state_add(struct xfrm_state *x, int result, EXPORT_SYMBOL_GPL(xfrm_audit_state_add); void xfrm_audit_state_delete(struct xfrm_state *x, int result, - u32 auid, u32 secid) + uid_t auid, u32 sessionid, u32 secid) { struct audit_buffer *audit_buf; audit_buf = xfrm_audit_start("SAD-delete"); if (audit_buf == NULL) return; - xfrm_audit_helper_usrinfo(auid, secid, audit_buf); + xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf); xfrm_audit_helper_sainfo(x, audit_buf); audit_log_format(audit_buf, " res=%u", result); audit_log_end(audit_buf);