2 * Copyright (C) 2012 Reto Buerki
3 * Copyright (C) 2012 Adrian-Ken Rueegsegger
4 * Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #include <netinet/udp.h>
19 #include <linux/xfrm.h>
20 #include <utils/debug.h>
21 #include <utils/chunk.h>
22 #include <tkm/constants.h>
23 #include <tkm/client.h>
25 #include "tkm_types.h"
26 #include "tkm_keymat.h"
27 #include "tkm_kernel_ipsec.h"
29 typedef struct private_tkm_kernel_ipsec_t private_tkm_kernel_ipsec_t
;
32 * Private variables and functions of TKM kernel ipsec instance.
34 struct private_tkm_kernel_ipsec_t
{
37 * Public tkm_kernel_ipsec interface.
39 tkm_kernel_ipsec_t
public;
42 * RNG used for SPI generation.
53 METHOD(kernel_ipsec_t
, get_spi
, status_t
,
54 private_tkm_kernel_ipsec_t
*this, host_t
*src
, host_t
*dst
,
55 u_int8_t protocol
, u_int32_t reqid
, u_int32_t
*spi
)
57 DBG1(DBG_KNL
, "getting SPI for reqid {%u}", reqid
);
58 const bool result
= this->rng
->get_bytes(this->rng
, sizeof(u_int32_t
),
60 return result ? SUCCESS
: FAILED
;
63 METHOD(kernel_ipsec_t
, get_cpi
, status_t
,
64 private_tkm_kernel_ipsec_t
*this, host_t
*src
, host_t
*dst
,
65 u_int32_t reqid
, u_int16_t
*cpi
)
70 METHOD(kernel_ipsec_t
, add_sa
, status_t
,
71 private_tkm_kernel_ipsec_t
*this, host_t
*src
, host_t
*dst
,
72 u_int32_t spi
, u_int8_t protocol
, u_int32_t reqid
, mark_t mark
,
73 u_int32_t tfc
, lifetime_cfg_t
*lifetime
, u_int16_t enc_alg
, chunk_t enc_key
,
74 u_int16_t int_alg
, chunk_t int_key
, ipsec_mode_t mode
, u_int16_t ipcomp
,
75 u_int16_t cpi
, bool encap
, bool esn
, bool inbound
,
76 traffic_selector_t
* src_ts
, traffic_selector_t
* dst_ts
)
78 if (inbound
&& this->esp_spi_loc
== 0)
80 DBG1(DBG_KNL
, "store local child SA SPI for installation", ntohl(spi
));
81 this->esp_spi_loc
= spi
;
84 const esa_info_t esa
= *(esa_info_t
*)(enc_key
.ptr
);
85 DBG1(DBG_KNL
, "adding child SA (isa: %llu, esp_spi_loc: %x, esp_spi_rem:"
86 " %x)", esa
.isa_id
, ntohl(this->esp_spi_loc
), ntohl(spi
));
87 if (ike_esa_create_first (1, esa
.isa_id
, 1, 1, ntohl(this->esp_spi_loc
),
88 ntohl(spi
)) != TKM_OK
)
90 DBG1(DBG_KNL
, "child SA creation failed");
93 this->esp_spi_loc
= 0;
97 METHOD(kernel_ipsec_t
, query_sa
, status_t
,
98 private_tkm_kernel_ipsec_t
*this, host_t
*src
, host_t
*dst
,
99 u_int32_t spi
, u_int8_t protocol
, mark_t mark
, u_int64_t
*bytes
,
102 return NOT_SUPPORTED
;
105 METHOD(kernel_ipsec_t
, del_sa
, status_t
,
106 private_tkm_kernel_ipsec_t
*this, host_t
*src
, host_t
*dst
,
107 u_int32_t spi
, u_int8_t protocol
, u_int16_t cpi
, mark_t mark
)
109 DBG1(DBG_KNL
, "deleting child SA with SPI %.8x", ntohl(spi
));
113 METHOD(kernel_ipsec_t
, update_sa
, status_t
,
114 private_tkm_kernel_ipsec_t
*this, u_int32_t spi
, u_int8_t protocol
,
115 u_int16_t cpi
, host_t
*src
, host_t
*dst
, host_t
*new_src
, host_t
*new_dst
,
116 bool old_encap
, bool new_encap
, mark_t mark
)
118 return NOT_SUPPORTED
;
121 METHOD(kernel_ipsec_t
, flush_sas
, status_t
,
122 private_tkm_kernel_ipsec_t
*this)
124 DBG1(DBG_KNL
, "flushing child SA entries");
128 METHOD(kernel_ipsec_t
, add_policy
, status_t
,
129 private_tkm_kernel_ipsec_t
*this, host_t
*src
, host_t
*dst
,
130 traffic_selector_t
*src_ts
, traffic_selector_t
*dst_ts
,
131 policy_dir_t direction
, policy_type_t type
, ipsec_sa_cfg_t
*sa
,
132 mark_t mark
, policy_priority_t priority
)
137 METHOD(kernel_ipsec_t
, query_policy
, status_t
,
138 private_tkm_kernel_ipsec_t
*this, traffic_selector_t
*src_ts
,
139 traffic_selector_t
*dst_ts
, policy_dir_t direction
, mark_t mark
,
142 return NOT_SUPPORTED
;
145 METHOD(kernel_ipsec_t
, del_policy
, status_t
,
146 private_tkm_kernel_ipsec_t
*this, traffic_selector_t
*src_ts
,
147 traffic_selector_t
*dst_ts
, policy_dir_t direction
, u_int32_t reqid
,
148 mark_t mark
, policy_priority_t prio
)
153 METHOD(kernel_ipsec_t
, flush_policies
, status_t
,
154 private_tkm_kernel_ipsec_t
*this)
160 METHOD(kernel_ipsec_t
, bypass_socket
, bool,
161 private_tkm_kernel_ipsec_t
*this, int fd
, int family
)
163 struct xfrm_userpolicy_info policy
;
164 u_int sol
, ipsec_policy
;
170 ipsec_policy
= IP_XFRM_POLICY
;
174 ipsec_policy
= IPV6_XFRM_POLICY
;
180 memset(&policy
, 0, sizeof(policy
));
181 policy
.action
= XFRM_POLICY_ALLOW
;
182 policy
.sel
.family
= family
;
184 policy
.dir
= XFRM_POLICY_OUT
;
185 if (setsockopt(fd
, sol
, ipsec_policy
, &policy
, sizeof(policy
)) < 0)
187 DBG1(DBG_KNL
, "unable to set IPSEC_POLICY on socket: %s",
191 policy
.dir
= XFRM_POLICY_IN
;
192 if (setsockopt(fd
, sol
, ipsec_policy
, &policy
, sizeof(policy
)) < 0)
194 DBG1(DBG_KNL
, "unable to set IPSEC_POLICY on socket: %s",
201 METHOD(kernel_ipsec_t
, enable_udp_decap
, bool,
202 private_tkm_kernel_ipsec_t
*this, int fd
, int family
, u_int16_t port
)
204 int type
= UDP_ENCAP_ESPINUDP
;
206 if (setsockopt(fd
, SOL_UDP
, UDP_ENCAP
, &type
, sizeof(type
)) < 0)
208 DBG1(DBG_KNL
, "unable to set UDP_ENCAP: %s", strerror(errno
));
214 METHOD(kernel_ipsec_t
, destroy
, void,
215 private_tkm_kernel_ipsec_t
*this)
217 DESTROY_IF(this->rng
);
222 * Described in header.
224 tkm_kernel_ipsec_t
*tkm_kernel_ipsec_create()
226 private_tkm_kernel_ipsec_t
*this;
234 .update_sa
= _update_sa
,
235 .query_sa
= _query_sa
,
237 .flush_sas
= _flush_sas
,
238 .add_policy
= _add_policy
,
239 .query_policy
= _query_policy
,
240 .del_policy
= _del_policy
,
241 .flush_policies
= _flush_policies
,
242 .bypass_socket
= _bypass_socket
,
243 .enable_udp_decap
= _enable_udp_decap
,
247 .rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
),
253 DBG1(DBG_KNL
, "unable to create RNG");
258 return &this->public;