]> err.no Git - linux-2.6/blobdiff - net/ipv4/xfrm4_state.c
[XFRM] STATE: Search by address using source address list.
[linux-2.6] / net / ipv4 / xfrm4_state.c
index d23e07fc81facafe1c7a34e10c9a0d5fc75a4168..616be131b4e36657ec9d8b6037a562b2dec9176c 100644 (file)
@@ -42,6 +42,21 @@ __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
        x->props.saddr = tmpl->saddr;
        if (x->props.saddr.a4 == 0)
                x->props.saddr.a4 = saddr->a4;
+       if (tmpl->mode == XFRM_MODE_TUNNEL && x->props.saddr.a4 == 0) {
+               struct rtable *rt;
+               struct flowi fl_tunnel = {
+                       .nl_u = {
+                               .ip4_u = {
+                                       .daddr = x->id.daddr.a4,
+                               }
+                       }
+               };
+               if (!xfrm_dst_lookup((struct xfrm_dst **)&rt,
+                                    &fl_tunnel, AF_INET)) {
+                       x->props.saddr.a4 = rt->rt_src;
+                       dst_release(&rt->u.dst);
+               }
+       }
        x->props.mode = tmpl->mode;
        x->props.reqid = tmpl->reqid;
        x->props.family = AF_INET;
@@ -65,6 +80,14 @@ __xfrm4_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto)
        return NULL;
 }
 
+/* placeholder until ipv4's code is written */
+static struct xfrm_state *
+__xfrm4_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr,
+                           u8 proto)
+{
+       return NULL;
+}
+
 static struct xfrm_state *
 __xfrm4_find_acq(u8 mode, u32 reqid, u8 proto, 
                 xfrm_address_t *daddr, xfrm_address_t *saddr, 
@@ -107,6 +130,9 @@ __xfrm4_find_acq(u8 mode, u32 reqid, u8 proto,
                add_timer(&x0->timer);
                xfrm_state_hold(x0);
                list_add_tail(&x0->bydst, xfrm4_state_afinfo.state_bydst+h);
+               h = __xfrm4_src_hash(saddr);
+               xfrm_state_hold(x0);
+               list_add_tail(&x0->bysrc, xfrm4_state_afinfo.state_bysrc+h);
                wake_up(&km_waitq);
        }
        if (x0)
@@ -116,10 +142,10 @@ __xfrm4_find_acq(u8 mode, u32 reqid, u8 proto,
 
 static struct xfrm_state_afinfo xfrm4_state_afinfo = {
        .family                 = AF_INET,
-       .lock                   = RW_LOCK_UNLOCKED,
        .init_flags             = xfrm4_init_flags,
        .init_tempsel           = __xfrm4_init_tempsel,
        .state_lookup           = __xfrm4_state_lookup,
+       .state_lookup_byaddr    = __xfrm4_state_lookup_byaddr,
        .find_acq               = __xfrm4_find_acq,
 };