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