linux-bk/net/ipv4/xfrm4_state.c
<<
>>
Prefs
   1/*
   2 * xfrm4_state.c
   3 *
   4 * Changes:
   5 *      YOSHIFUJI Hideaki @USAGI
   6 *              Split up af-specific portion
   7 *
   8 */
   9
  10#include <net/xfrm.h>
  11#include <linux/pfkeyv2.h>
  12#include <linux/ipsec.h>
  13
  14extern struct xfrm_state_afinfo xfrm4_state_afinfo;
  15
  16static void
  17__xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
  18                     struct xfrm_tmpl *tmpl,
  19                     xfrm_address_t *daddr, xfrm_address_t *saddr)
  20{
  21        x->sel.daddr.a4 = fl->fl4_dst;
  22        x->sel.saddr.a4 = fl->fl4_src;
  23        x->sel.dport = fl->fl_ip_dport;
  24        x->sel.dport_mask = ~0;
  25        x->sel.sport = fl->fl_ip_sport;
  26        x->sel.sport_mask = ~0;
  27        x->sel.prefixlen_d = 32;
  28        x->sel.prefixlen_s = 32;
  29        x->sel.proto = fl->proto;
  30        x->sel.ifindex = fl->oif;
  31        x->id = tmpl->id;
  32        if (x->id.daddr.a4 == 0)
  33                x->id.daddr.a4 = daddr->a4;
  34        x->props.saddr = tmpl->saddr;
  35        if (x->props.saddr.a4 == 0)
  36                x->props.saddr.a4 = saddr->a4;
  37        x->props.mode = tmpl->mode;
  38        x->props.reqid = tmpl->reqid;
  39        x->props.family = AF_INET;
  40}
  41
  42static struct xfrm_state *
  43__xfrm4_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto)
  44{
  45        unsigned h = __xfrm4_spi_hash(daddr, spi, proto);
  46        struct xfrm_state *x;
  47
  48        list_for_each_entry(x, xfrm4_state_afinfo.state_byspi+h, byspi) {
  49                if (x->props.family == AF_INET &&
  50                    spi == x->id.spi &&
  51                    daddr->a4 == x->id.daddr.a4 &&
  52                    proto == x->id.proto) {
  53                        xfrm_state_hold(x);
  54                        return x;
  55                }
  56        }
  57        return NULL;
  58}
  59
  60static struct xfrm_state *
  61__xfrm4_find_acq(u8 mode, u32 reqid, u8 proto, 
  62                 xfrm_address_t *daddr, xfrm_address_t *saddr, 
  63                 int create)
  64{
  65        struct xfrm_state *x, *x0;
  66        unsigned h = __xfrm4_dst_hash(daddr);
  67
  68        x0 = NULL;
  69
  70        list_for_each_entry(x, xfrm4_state_afinfo.state_bydst+h, bydst) {
  71                if (x->props.family == AF_INET &&
  72                    daddr->a4 == x->id.daddr.a4 &&
  73                    mode == x->props.mode &&
  74                    proto == x->id.proto &&
  75                    saddr->a4 == x->props.saddr.a4 &&
  76                    reqid == x->props.reqid &&
  77                    x->km.state == XFRM_STATE_ACQ) {
  78                            if (!x0)
  79                                    x0 = x;
  80                            if (x->id.spi)
  81                                    continue;
  82                            x0 = x;
  83                            break;
  84                    }
  85        }
  86        if (x0) {
  87                xfrm_state_hold(x0);
  88        } else if (create && (x0 = xfrm_state_alloc()) != NULL) {
  89                x0->sel.daddr.a4 = daddr->a4;
  90                x0->sel.saddr.a4 = saddr->a4;
  91                x0->sel.prefixlen_d = 32;
  92                x0->sel.prefixlen_s = 32;
  93                x0->props.saddr.a4 = saddr->a4;
  94                x0->km.state = XFRM_STATE_ACQ;
  95                x0->id.daddr.a4 = daddr->a4;
  96                x0->id.proto = proto;
  97                x0->props.family = AF_INET;
  98                x0->props.mode = mode;
  99                x0->props.reqid = reqid;
 100                x0->props.family = AF_INET;
 101                x0->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
 102                xfrm_state_hold(x0);
 103                mod_timer(&x0->timer, jiffies + XFRM_ACQ_EXPIRES*HZ);
 104                xfrm_state_hold(x0);
 105                list_add_tail(&x0->bydst, xfrm4_state_afinfo.state_bydst+h);
 106                wake_up(&km_waitq);
 107        }
 108        return x0;
 109}
 110
 111static struct xfrm_state_afinfo xfrm4_state_afinfo = {
 112        .family                 = AF_INET,
 113        .lock                   = RW_LOCK_UNLOCKED,
 114        .init_tempsel           = __xfrm4_init_tempsel,
 115        .state_lookup           = __xfrm4_state_lookup,
 116        .find_acq               = __xfrm4_find_acq,
 117};
 118
 119void __init xfrm4_state_init(void)
 120{
 121        xfrm_state_register_afinfo(&xfrm4_state_afinfo);
 122}
 123
 124void __exit xfrm4_state_fini(void)
 125{
 126        xfrm_state_unregister_afinfo(&xfrm4_state_afinfo);
 127}
 128
 129
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.