Moving charon to libcharon.
[strongswan.git] / src / libcharon / kernel / kernel_interface.c
1 /*
2 * Copyright (C) 2008-2009 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 * Copyright (C) 2010 Martin Willi
5 * Copyright (C) 2010 revosec AG
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include "kernel_interface.h"
19
20 #include <daemon.h>
21
22 typedef struct private_kernel_interface_t private_kernel_interface_t;
23
24 /**
25 * Private data of a kernel_interface_t object.
26 */
27 struct private_kernel_interface_t {
28
29 /**
30 * Public part of kernel_interface_t object.
31 */
32 kernel_interface_t public;
33
34 /**
35 * ipsec interface
36 */
37 kernel_ipsec_t *ipsec;
38
39 /**
40 * network interface
41 */
42 kernel_net_t *net;
43 };
44
45 METHOD(kernel_interface_t, get_spi, status_t,
46 private_kernel_interface_t *this, host_t *src, host_t *dst,
47 protocol_id_t protocol, u_int32_t reqid, u_int32_t *spi)
48 {
49 if (!this->ipsec)
50 {
51 return NOT_SUPPORTED;
52 }
53 return this->ipsec->get_spi(this->ipsec, src, dst, protocol, reqid, spi);
54 }
55
56 METHOD(kernel_interface_t, get_cpi, status_t,
57 private_kernel_interface_t *this, host_t *src, host_t *dst,
58 u_int32_t reqid, u_int16_t *cpi)
59 {
60 if (!this->ipsec)
61 {
62 return NOT_SUPPORTED;
63 }
64 return this->ipsec->get_cpi(this->ipsec, src, dst, reqid, cpi);
65 }
66
67 METHOD(kernel_interface_t, add_sa, status_t,
68 private_kernel_interface_t *this, host_t *src, host_t *dst,
69 u_int32_t spi, protocol_id_t protocol, u_int32_t reqid,
70 lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
71 u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
72 u_int16_t cpi, bool encap, bool inbound, traffic_selector_t *src_ts,
73 traffic_selector_t *dst_ts)
74 {
75 if (!this->ipsec)
76 {
77 return NOT_SUPPORTED;
78 }
79 return this->ipsec->add_sa(this->ipsec, src, dst, spi, protocol, reqid,
80 lifetime, enc_alg, enc_key, int_alg, int_key, mode, ipcomp, cpi,
81 encap, inbound, src_ts, dst_ts);
82 }
83
84 METHOD(kernel_interface_t, update_sa, status_t,
85 private_kernel_interface_t *this, u_int32_t spi, protocol_id_t protocol,
86 u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
87 bool encap, bool new_encap)
88 {
89 if (!this->ipsec)
90 {
91 return NOT_SUPPORTED;
92 }
93 return this->ipsec->update_sa(this->ipsec, spi, protocol, cpi, src, dst,
94 new_src, new_dst, encap, new_encap);
95 }
96
97 METHOD(kernel_interface_t, query_sa, status_t,
98 private_kernel_interface_t *this, host_t *src, host_t *dst,
99 u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes)
100 {
101 if (!this->ipsec)
102 {
103 return NOT_SUPPORTED;
104 }
105 return this->ipsec->query_sa(this->ipsec, src, dst, spi, protocol, bytes);
106 }
107
108 METHOD(kernel_interface_t, del_sa, status_t,
109 private_kernel_interface_t *this, host_t *src, host_t *dst, u_int32_t spi,
110 protocol_id_t protocol, u_int16_t cpi)
111 {
112 if (!this->ipsec)
113 {
114 return NOT_SUPPORTED;
115 }
116 return this->ipsec->del_sa(this->ipsec, src, dst, spi, protocol, cpi);
117 }
118
119 METHOD(kernel_interface_t, add_policy, status_t,
120 private_kernel_interface_t *this, host_t *src, host_t *dst,
121 traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
122 policy_dir_t direction, u_int32_t spi, protocol_id_t protocol,
123 u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
124 bool routed)
125 {
126 if (!this->ipsec)
127 {
128 return NOT_SUPPORTED;
129 }
130 return this->ipsec->add_policy(this->ipsec, src, dst, src_ts, dst_ts,
131 direction, spi, protocol, reqid, mode, ipcomp, cpi, routed);
132 }
133
134 METHOD(kernel_interface_t, query_policy, status_t,
135 private_kernel_interface_t *this, traffic_selector_t *src_ts,
136 traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time)
137 {
138 if (!this->ipsec)
139 {
140 return NOT_SUPPORTED;
141 }
142 return this->ipsec->query_policy(this->ipsec, src_ts, dst_ts,
143 direction, use_time);
144 }
145
146 METHOD(kernel_interface_t, del_policy, status_t,
147 private_kernel_interface_t *this, traffic_selector_t *src_ts,
148 traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted)
149 {
150 if (!this->ipsec)
151 {
152 return NOT_SUPPORTED;
153 }
154 return this->ipsec->del_policy(this->ipsec, src_ts, dst_ts,
155 direction, unrouted);
156 }
157
158 METHOD(kernel_interface_t, get_source_addr, host_t*,
159 private_kernel_interface_t *this, host_t *dest, host_t *src)
160 {
161 if (!this->net)
162 {
163 return NULL;
164 }
165 return this->net->get_source_addr(this->net, dest, src);
166 }
167
168 METHOD(kernel_interface_t, get_nexthop, host_t*,
169 private_kernel_interface_t *this, host_t *dest)
170 {
171 if (!this->net)
172 {
173 return NULL;
174 }
175 return this->net->get_nexthop(this->net, dest);
176 }
177
178 METHOD(kernel_interface_t, get_interface, char*,
179 private_kernel_interface_t *this, host_t *host)
180 {
181 if (!this->net)
182 {
183 return NULL;
184 }
185 return this->net->get_interface(this->net, host);
186 }
187
188 METHOD(kernel_interface_t, create_address_enumerator, enumerator_t*,
189 private_kernel_interface_t *this, bool include_down_ifaces,
190 bool include_virtual_ips)
191 {
192 if (!this->net)
193 {
194 return enumerator_create_empty();
195 }
196 return this->net->create_address_enumerator(this->net, include_down_ifaces,
197 include_virtual_ips);
198 }
199
200 METHOD(kernel_interface_t, add_ip, status_t,
201 private_kernel_interface_t *this, host_t *virtual_ip, host_t *iface_ip)
202 {
203 if (!this->net)
204 {
205 return NOT_SUPPORTED;
206 }
207 return this->net->add_ip(this->net, virtual_ip, iface_ip);
208 }
209
210 METHOD(kernel_interface_t, del_ip, status_t,
211 private_kernel_interface_t *this, host_t *virtual_ip)
212 {
213 if (!this->net)
214 {
215 return NOT_SUPPORTED;
216 }
217 return this->net->del_ip(this->net, virtual_ip);
218 }
219
220 METHOD(kernel_interface_t, add_route, status_t,
221 private_kernel_interface_t *this, chunk_t dst_net,
222 u_int8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name)
223 {
224 if (!this->net)
225 {
226 return NOT_SUPPORTED;
227 }
228 return this->net->add_route(this->net, dst_net, prefixlen, gateway,
229 src_ip, if_name);
230 }
231
232 METHOD(kernel_interface_t, del_route, status_t,
233 private_kernel_interface_t *this, chunk_t dst_net,
234 u_int8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name)
235 {
236 if (!this->net)
237 {
238 return NOT_SUPPORTED;
239 }
240 return this->net->del_route(this->net, dst_net, prefixlen, gateway,
241 src_ip, if_name);
242 }
243
244 METHOD(kernel_interface_t, bypass_socket, bool,
245 private_kernel_interface_t *this, int fd, int family)
246 {
247 if (!this->ipsec)
248 {
249 return FALSE;
250 }
251 return this->ipsec->bypass_socket(this->ipsec, fd, family);
252 }
253
254 METHOD(kernel_interface_t, get_address_by_ts, status_t,
255 private_kernel_interface_t *this, traffic_selector_t *ts, host_t **ip)
256 {
257 enumerator_t *addrs;
258 host_t *host;
259 int family;
260 bool found = FALSE;
261
262 DBG2(DBG_KNL, "getting a local address in traffic selector %R", ts);
263
264 /* if we have a family which includes localhost, we do not
265 * search for an IP, we use the default */
266 family = ts->get_type(ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6;
267
268 if (family == AF_INET)
269 {
270 host = host_create_from_string("127.0.0.1", 0);
271 }
272 else
273 {
274 host = host_create_from_string("::1", 0);
275 }
276
277 if (ts->includes(ts, host))
278 {
279 *ip = host_create_any(family);
280 host->destroy(host);
281 DBG2(DBG_KNL, "using host %H", *ip);
282 return SUCCESS;
283 }
284 host->destroy(host);
285
286 addrs = create_address_enumerator(this, TRUE, TRUE);
287 while (addrs->enumerate(addrs, (void**)&host))
288 {
289 if (ts->includes(ts, host))
290 {
291 found = TRUE;
292 *ip = host->clone(host);
293 break;
294 }
295 }
296 addrs->destroy(addrs);
297
298 if (!found)
299 {
300 DBG1(DBG_KNL, "no local address found in traffic selector %R", ts);
301 return FAILED;
302 }
303
304 DBG2(DBG_KNL, "using host %H", *ip);
305 return SUCCESS;
306 }
307
308
309 METHOD(kernel_interface_t, add_ipsec_interface, void,
310 private_kernel_interface_t *this, kernel_ipsec_constructor_t constructor)
311 {
312 if (!this->ipsec)
313 {
314 this->ipsec = constructor();
315 }
316 }
317
318 METHOD(kernel_interface_t, remove_ipsec_interface, void,
319 private_kernel_interface_t *this, kernel_ipsec_constructor_t constructor)
320 {
321 /* TODO: replace if interface currently in use */
322 }
323
324 METHOD(kernel_interface_t, add_net_interface, void,
325 private_kernel_interface_t *this, kernel_net_constructor_t constructor)
326 {
327 if (!this->net)
328 {
329 this->net = constructor();
330 }
331 }
332
333 METHOD(kernel_interface_t, remove_net_interface, void,
334 private_kernel_interface_t *this, kernel_net_constructor_t constructor)
335 {
336 /* TODO: replace if interface currently in use */
337 }
338
339 METHOD(kernel_interface_t, destroy, void,
340 private_kernel_interface_t *this)
341 {
342 DESTROY_IF(this->ipsec);
343 DESTROY_IF(this->net);
344 free(this);
345 }
346
347 /*
348 * Described in header-file
349 */
350 kernel_interface_t *kernel_interface_create()
351 {
352 private_kernel_interface_t *this;
353
354 INIT(this,
355 .public = {
356 .get_spi = _get_spi,
357 .get_cpi = _get_cpi,
358 .add_sa = _add_sa,
359 .update_sa = _update_sa,
360 .query_sa = _query_sa,
361 .del_sa = _del_sa,
362 .add_policy = _add_policy,
363 .query_policy = _query_policy,
364 .del_policy = _del_policy,
365 .get_source_addr = _get_source_addr,
366 .get_nexthop = _get_nexthop,
367 .get_interface = _get_interface,
368 .create_address_enumerator = _create_address_enumerator,
369 .add_ip = _add_ip,
370 .del_ip = _del_ip,
371 .add_route = _add_route,
372 .del_route = _del_route,
373 .bypass_socket = _bypass_socket,
374
375 .get_address_by_ts = _get_address_by_ts,
376 .add_ipsec_interface = _add_ipsec_interface,
377 .remove_ipsec_interface = _remove_ipsec_interface,
378 .add_net_interface = _add_net_interface,
379 .remove_net_interface = _remove_net_interface,
380 .destroy = _destroy,
381 },
382 );
383
384 return &this->public;
385 }
386