5 * YOSHIFUJI Hideaki @USAGI
6 * Split up af-specific portion
12 #include <linux/pfkeyv2.h>
13 #include <linux/ipsec.h>
15 static struct xfrm_state_afinfo xfrm4_state_afinfo
;
17 static int xfrm4_init_flags(struct xfrm_state
*x
)
19 if (ipv4_config
.no_pmtu_disc
)
20 x
->props
.flags
|= XFRM_STATE_NOPMTUDISC
;
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
)
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
;
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 if (tmpl
->mode
== XFRM_MODE_TUNNEL
&& x
->props
.saddr
.a4
== 0) {
47 struct flowi fl_tunnel
= {
50 .daddr
= x
->id
.daddr
.a4
,
54 if (!xfrm_dst_lookup((struct xfrm_dst
**)&rt
,
55 &fl_tunnel
, AF_INET
)) {
56 x
->props
.saddr
.a4
= rt
->rt_src
;
57 dst_release(&rt
->u
.dst
);
60 x
->props
.mode
= tmpl
->mode
;
61 x
->props
.reqid
= tmpl
->reqid
;
62 x
->props
.family
= AF_INET
;
65 static struct xfrm_state
*
66 __xfrm4_state_lookup(xfrm_address_t
*daddr
, u32 spi
, u8 proto
)
68 unsigned h
= __xfrm4_spi_hash(daddr
, spi
, proto
);
71 list_for_each_entry(x
, xfrm4_state_afinfo
.state_byspi
+h
, byspi
) {
72 if (x
->props
.family
== AF_INET
&&
74 daddr
->a4
== x
->id
.daddr
.a4
&&
75 proto
== x
->id
.proto
) {
83 /* placeholder until ipv4's code is written */
84 static struct xfrm_state
*
85 __xfrm4_state_lookup_byaddr(xfrm_address_t
*daddr
, xfrm_address_t
*saddr
,
91 static struct xfrm_state
*
92 __xfrm4_find_acq(u8 mode
, u32 reqid
, u8 proto
,
93 xfrm_address_t
*daddr
, xfrm_address_t
*saddr
,
96 struct xfrm_state
*x
, *x0
;
97 unsigned h
= __xfrm4_dst_hash(daddr
);
101 list_for_each_entry(x
, xfrm4_state_afinfo
.state_bydst
+h
, bydst
) {
102 if (x
->props
.family
== AF_INET
&&
103 daddr
->a4
== x
->id
.daddr
.a4
&&
104 mode
== x
->props
.mode
&&
105 proto
== x
->id
.proto
&&
106 saddr
->a4
== x
->props
.saddr
.a4
&&
107 reqid
== x
->props
.reqid
&&
108 x
->km
.state
== XFRM_STATE_ACQ
&&
114 if (!x0
&& create
&& (x0
= xfrm_state_alloc()) != NULL
) {
115 x0
->sel
.daddr
.a4
= daddr
->a4
;
116 x0
->sel
.saddr
.a4
= saddr
->a4
;
117 x0
->sel
.prefixlen_d
= 32;
118 x0
->sel
.prefixlen_s
= 32;
119 x0
->props
.saddr
.a4
= saddr
->a4
;
120 x0
->km
.state
= XFRM_STATE_ACQ
;
121 x0
->id
.daddr
.a4
= daddr
->a4
;
122 x0
->id
.proto
= proto
;
123 x0
->props
.family
= AF_INET
;
124 x0
->props
.mode
= mode
;
125 x0
->props
.reqid
= reqid
;
126 x0
->props
.family
= AF_INET
;
127 x0
->lft
.hard_add_expires_seconds
= XFRM_ACQ_EXPIRES
;
129 x0
->timer
.expires
= jiffies
+ XFRM_ACQ_EXPIRES
*HZ
;
130 add_timer(&x0
->timer
);
132 list_add_tail(&x0
->bydst
, xfrm4_state_afinfo
.state_bydst
+h
);
133 h
= __xfrm4_src_hash(saddr
);
135 list_add_tail(&x0
->bysrc
, xfrm4_state_afinfo
.state_bysrc
+h
);
143 static struct xfrm_state_afinfo xfrm4_state_afinfo
= {
145 .init_flags
= xfrm4_init_flags
,
146 .init_tempsel
= __xfrm4_init_tempsel
,
147 .state_lookup
= __xfrm4_state_lookup
,
148 .state_lookup_byaddr
= __xfrm4_state_lookup_byaddr
,
149 .find_acq
= __xfrm4_find_acq
,
152 void __init
xfrm4_state_init(void)
154 xfrm_state_register_afinfo(&xfrm4_state_afinfo
);
158 void __exit
xfrm4_state_fini(void)
160 xfrm_state_unregister_afinfo(&xfrm4_state_afinfo
);