[GFS2] Add nanosecond timestamp feature
[safe/jmp/linux-2.6] / net / xfrm / xfrm_state.c
index 743f07e..dfacb9c 100644 (file)
 #include <linux/cache.h>
 #include <asm/uaccess.h>
 #include <linux/audit.h>
+#include <linux/cache.h>
 
 #include "xfrm_hash.h"
 
 struct sock *xfrm_nl;
 EXPORT_SYMBOL(xfrm_nl);
 
-u32 sysctl_xfrm_aevent_etime = XFRM_AE_ETIME;
+u32 sysctl_xfrm_aevent_etime __read_mostly = XFRM_AE_ETIME;
 EXPORT_SYMBOL(sysctl_xfrm_aevent_etime);
 
-u32 sysctl_xfrm_aevent_rseqth = XFRM_AE_SEQT_SIZE;
+u32 sysctl_xfrm_aevent_rseqth __read_mostly = XFRM_AE_SEQT_SIZE;
 EXPORT_SYMBOL(sysctl_xfrm_aevent_rseqth);
 
+u32 sysctl_xfrm_acq_expires __read_mostly = 30;
+
 /* Each xfrm_state may be linked to two tables:
 
    1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl)
@@ -388,12 +391,48 @@ int xfrm_state_delete(struct xfrm_state *x)
 }
 EXPORT_SYMBOL(xfrm_state_delete);
 
-void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info)
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static inline int
+xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info)
 {
-       int i;
-       int err = 0;
+       int i, err = 0;
+
+       for (i = 0; i <= xfrm_state_hmask; i++) {
+               struct hlist_node *entry;
+               struct xfrm_state *x;
+
+               hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
+                       if (xfrm_id_proto_match(x->id.proto, proto) &&
+                          (err = security_xfrm_state_delete(x)) != 0) {
+                               xfrm_audit_log(audit_info->loginuid,
+                                              audit_info->secid,
+                                              AUDIT_MAC_IPSEC_DELSA,
+                                               0, NULL, x);
+
+                               return err;
+                       }
+               }
+       }
+
+       return err;
+}
+#else
+static inline int
+xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info)
+{
+       return 0;
+}
+#endif
+
+int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info)
+{
+       int i, err = 0;
 
        spin_lock_bh(&xfrm_state_lock);
+       err = xfrm_state_flush_secctx_check(proto, audit_info);
+       if (err)
+               goto out;
+
        for (i = 0; i <= xfrm_state_hmask; i++) {
                struct hlist_node *entry;
                struct xfrm_state *x;
@@ -416,11 +455,25 @@ restart:
                        }
                }
        }
+       err = 0;
+
+out:
        spin_unlock_bh(&xfrm_state_lock);
        wake_up(&km_waitq);
+       return err;
 }
 EXPORT_SYMBOL(xfrm_state_flush);
 
+void xfrm_sad_getinfo(struct xfrmk_sadinfo *si)
+{
+       spin_lock_bh(&xfrm_state_lock);
+       si->sadcnt = xfrm_state_num;
+       si->sadhcnt = xfrm_state_hmask;
+       si->sadhmcnt = xfrm_state_hashmax;
+       spin_unlock_bh(&xfrm_state_lock);
+}
+EXPORT_SYMBOL(xfrm_sad_getinfo);
+
 static int
 xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl,
                  struct xfrm_tmpl *tmpl,
@@ -612,8 +665,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
                                h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family);
                                hlist_add_head(&x->byspi, xfrm_state_byspi+h);
                        }
-                       x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
-                       x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
+                       x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires;
+                       x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ;
                        add_timer(&x->timer);
                        xfrm_state_num++;
                        xfrm_hash_grow_check(x->bydst.next != NULL);
@@ -762,9 +815,9 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re
                x->props.family = family;
                x->props.mode = mode;
                x->props.reqid = reqid;
-               x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
+               x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires;
                xfrm_state_hold(x);
-               x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
+               x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ;
                add_timer(&x->timer);
                hlist_add_head(&x->bydst, xfrm_state_bydst+h);
                h = xfrm_src_hash(daddr, saddr, family);
@@ -1676,7 +1729,7 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu)
            x->type && x->type->get_mtu)
                res = x->type->get_mtu(x, mtu);
        else
-               res = mtu;
+               res = mtu - x->props.header_len;
        spin_unlock_bh(&x->lock);
        return res;
 }