2 * xfrm6_state.c: based on xfrm4_state.c
6 * Kazunori MIYAZAWA @USAGI
7 * Kunihiro Ishiguro <kunihiro@ipinfusion.com>
9 * YOSHIFUJI Hideaki @USAGI
10 * Split up af-specific portion
15 #include <linux/pfkeyv2.h>
16 #include <linux/ipsec.h>
19 static struct xfrm_state_afinfo xfrm6_state_afinfo
;
22 __xfrm6_init_tempsel(struct xfrm_state
*x
, struct flowi
*fl
,
23 struct xfrm_tmpl
*tmpl
,
24 xfrm_address_t
*daddr
, xfrm_address_t
*saddr
)
26 /* Initialize temporary selector matching only
27 * to current session. */
28 ipv6_addr_copy((struct in6_addr
*)&x
->sel
.daddr
, &fl
->fl6_dst
);
29 ipv6_addr_copy((struct in6_addr
*)&x
->sel
.saddr
, &fl
->fl6_src
);
30 x
->sel
.dport
= xfrm_flowi_dport(fl
);
31 x
->sel
.dport_mask
= ~0;
32 x
->sel
.sport
= xfrm_flowi_sport(fl
);
33 x
->sel
.sport_mask
= ~0;
34 x
->sel
.prefixlen_d
= 128;
35 x
->sel
.prefixlen_s
= 128;
36 x
->sel
.proto
= fl
->proto
;
37 x
->sel
.ifindex
= fl
->oif
;
39 if (ipv6_addr_any((struct in6_addr
*)&x
->id
.daddr
))
40 memcpy(&x
->id
.daddr
, daddr
, sizeof(x
->sel
.daddr
));
41 memcpy(&x
->props
.saddr
, &tmpl
->saddr
, sizeof(x
->props
.saddr
));
42 if (ipv6_addr_any((struct in6_addr
*)&x
->props
.saddr
))
43 memcpy(&x
->props
.saddr
, saddr
, sizeof(x
->props
.saddr
));
44 x
->props
.mode
= tmpl
->mode
;
45 x
->props
.reqid
= tmpl
->reqid
;
46 x
->props
.family
= AF_INET6
;
49 static struct xfrm_state
*
50 __xfrm6_state_lookup(xfrm_address_t
*daddr
, u32 spi
, u8 proto
)
52 unsigned h
= __xfrm6_spi_hash(daddr
, spi
, proto
);
55 list_for_each_entry(x
, xfrm6_state_afinfo
.state_byspi
+h
, byspi
) {
56 if (x
->props
.family
== AF_INET6
&&
58 ipv6_addr_equal((struct in6_addr
*)daddr
, (struct in6_addr
*)x
->id
.daddr
.a6
) &&
59 proto
== x
->id
.proto
) {
67 static struct xfrm_state
*
68 __xfrm6_find_acq(u8 mode
, u32 reqid
, u8 proto
,
69 xfrm_address_t
*daddr
, xfrm_address_t
*saddr
,
72 struct xfrm_state
*x
, *x0
;
73 unsigned h
= __xfrm6_dst_hash(daddr
);
77 list_for_each_entry(x
, xfrm6_state_afinfo
.state_bydst
+h
, bydst
) {
78 if (x
->props
.family
== AF_INET6
&&
79 ipv6_addr_equal((struct in6_addr
*)daddr
, (struct in6_addr
*)x
->id
.daddr
.a6
) &&
80 mode
== x
->props
.mode
&&
81 proto
== x
->id
.proto
&&
82 ipv6_addr_equal((struct in6_addr
*)saddr
, (struct in6_addr
*)x
->props
.saddr
.a6
) &&
83 reqid
== x
->props
.reqid
&&
84 x
->km
.state
== XFRM_STATE_ACQ
&&
90 if (!x0
&& create
&& (x0
= xfrm_state_alloc()) != NULL
) {
91 ipv6_addr_copy((struct in6_addr
*)x0
->sel
.daddr
.a6
,
92 (struct in6_addr
*)daddr
);
93 ipv6_addr_copy((struct in6_addr
*)x0
->sel
.saddr
.a6
,
94 (struct in6_addr
*)saddr
);
95 x0
->sel
.prefixlen_d
= 128;
96 x0
->sel
.prefixlen_s
= 128;
97 ipv6_addr_copy((struct in6_addr
*)x0
->props
.saddr
.a6
,
98 (struct in6_addr
*)saddr
);
99 x0
->km
.state
= XFRM_STATE_ACQ
;
100 ipv6_addr_copy((struct in6_addr
*)x0
->id
.daddr
.a6
,
101 (struct in6_addr
*)daddr
);
102 x0
->id
.proto
= proto
;
103 x0
->props
.family
= AF_INET6
;
104 x0
->props
.mode
= mode
;
105 x0
->props
.reqid
= reqid
;
106 x0
->lft
.hard_add_expires_seconds
= XFRM_ACQ_EXPIRES
;
108 x0
->timer
.expires
= jiffies
+ XFRM_ACQ_EXPIRES
*HZ
;
109 add_timer(&x0
->timer
);
111 list_add_tail(&x0
->bydst
, xfrm6_state_afinfo
.state_bydst
+h
);
119 static struct xfrm_state_afinfo xfrm6_state_afinfo
= {
121 .lock
= RW_LOCK_UNLOCKED
,
122 .init_tempsel
= __xfrm6_init_tempsel
,
123 .state_lookup
= __xfrm6_state_lookup
,
124 .find_acq
= __xfrm6_find_acq
,
127 void __init
xfrm6_state_init(void)
129 xfrm_state_register_afinfo(&xfrm6_state_afinfo
);
132 void xfrm6_state_fini(void)
134 xfrm_state_unregister_afinfo(&xfrm6_state_afinfo
);