2 * Copyright (C) 2008 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #include "kernel_interface.h"
23 #include <utils/linked_list.h>
24 #include <utils/mutex.h>
26 typedef struct private_kernel_interface_t private_kernel_interface_t
;
29 * Private data of a kernel_interface_t object.
31 struct private_kernel_interface_t
{
34 * Public part of kernel_interface_t object.
36 kernel_interface_t
public;
39 * list of registered ipsec kernel interfaces
41 linked_list_t
*ipsec_interfaces
;
44 * list of registered network kernel interfaces
46 linked_list_t
*net_interfaces
;
51 kernel_ipsec_t
*ipsec
;
65 * Implementation of kernel_interface_t.get_spi
67 static status_t
get_spi(private_kernel_interface_t
*this, host_t
*src
, host_t
*dst
,
68 protocol_id_t protocol
, u_int32_t reqid
, u_int32_t
*spi
)
70 return this->ipsec
->get_spi(this->ipsec
, src
, dst
, protocol
, reqid
, spi
);
74 * Implementation of kernel_interface_t.get_cpi
76 static status_t
get_cpi(private_kernel_interface_t
*this, host_t
*src
, host_t
*dst
,
77 u_int32_t reqid
, u_int16_t
*cpi
)
79 return this->ipsec
->get_cpi(this->ipsec
, src
, dst
, reqid
, cpi
);
83 * Implementation of kernel_interface_t.add_sa
85 static status_t
add_sa(private_kernel_interface_t
*this, host_t
*src
, host_t
*dst
,
86 u_int32_t spi
, protocol_id_t protocol
, u_int32_t reqid
,
87 u_int64_t expire_soft
, u_int64_t expire_hard
,
88 u_int16_t enc_alg
, chunk_t enc_key
,
89 u_int16_t int_alg
, chunk_t int_key
,
90 ipsec_mode_t mode
, u_int16_t ipcomp
, bool encap
, bool update
)
92 return this->ipsec
->add_sa(this->ipsec
, src
, dst
, spi
, protocol
, reqid
,
93 expire_soft
, expire_hard
, enc_alg
, enc_key
, int_alg
, int_key
,
94 mode
, ipcomp
, encap
, update
);
98 * Implementation of kernel_interface_t.update_sa
100 static status_t
update_sa(private_kernel_interface_t
*this, u_int32_t spi
,
101 protocol_id_t protocol
, host_t
*src
, host_t
*dst
,
102 host_t
*new_src
, host_t
*new_dst
, bool encap
)
104 return this->ipsec
->update_sa(this->ipsec
, spi
, protocol
, src
, dst
, new_src
,
109 * Implementation of kernel_interface_t.del_sa
111 static status_t
del_sa(private_kernel_interface_t
*this, host_t
*dst
, u_int32_t spi
,
112 protocol_id_t protocol
)
114 return this->ipsec
->del_sa(this->ipsec
, dst
, spi
, protocol
);
118 * Implementation of kernel_interface_t.add_policy
120 static status_t
add_policy(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
, protocol_id_t protocol
,
123 u_int32_t reqid
, bool high_prio
, ipsec_mode_t mode
,
126 return this->ipsec
->add_policy(this->ipsec
, src
, dst
, src_ts
, dst_ts
,
127 direction
, protocol
, reqid
, high_prio
, mode
, ipcomp
);
131 * Implementation of kernel_interface_t.query_policy
133 static status_t
query_policy(private_kernel_interface_t
*this,
134 traffic_selector_t
*src_ts
, traffic_selector_t
*dst_ts
,
135 policy_dir_t direction
, u_int32_t
*use_time
)
137 return this->ipsec
->query_policy(this->ipsec
, src_ts
, dst_ts
, direction
, use_time
);
141 * Implementation of kernel_interface_t.del_policy
143 static status_t
del_policy(private_kernel_interface_t
*this,
144 traffic_selector_t
*src_ts
, traffic_selector_t
*dst_ts
,
145 policy_dir_t direction
)
147 return this->ipsec
->del_policy(this->ipsec
, src_ts
, dst_ts
, direction
);
151 * Implementation of kernel_interface_t.get_source_addr
153 static host_t
*get_source_addr(private_kernel_interface_t
*this,
154 host_t
*dest
, host_t
*src
)
156 return this->net
->get_source_addr(this->net
, dest
, src
);
160 * Implementation of kernel_interface_t.get_nexthop
162 static host_t
*get_nexthop(private_kernel_interface_t
*this, host_t
*dest
)
164 return this->net
->get_nexthop(this->net
, dest
);
168 * Implementation of kernel_interface_t.get_interface
170 static char* get_interface(private_kernel_interface_t
*this, host_t
*host
)
172 return this->net
->get_interface(this->net
, host
);
176 * Implementation of kernel_interface_t.create_address_enumerator
178 static enumerator_t
*create_address_enumerator(private_kernel_interface_t
*this,
179 bool include_down_ifaces
, bool include_virtual_ips
)
181 return this->net
->create_address_enumerator(this->net
, include_down_ifaces
,
182 include_virtual_ips
);
186 * Implementation of kernel_interface_t.add_ip
188 static status_t
add_ip(private_kernel_interface_t
*this, host_t
*virtual_ip
,
191 return this->net
->add_ip(this->net
, virtual_ip
, iface_ip
);
195 * Implementation of kernel_interface_t.del_ip
197 static status_t
del_ip(private_kernel_interface_t
*this, host_t
*virtual_ip
)
199 return this->net
->del_ip(this->net
, virtual_ip
);
203 * Implementation of kernel_interface_t.add_route
205 static status_t
add_route(private_kernel_interface_t
*this, chunk_t dst_net
,
206 u_int8_t prefixlen
, host_t
*gateway
, host_t
*src_ip
, char *if_name
)
208 return this->net
->add_route(this->net
, dst_net
, prefixlen
, gateway
, src_ip
,
213 * Implementation of kernel_interface_t.del_route
215 static status_t
del_route(private_kernel_interface_t
*this, chunk_t dst_net
,
216 u_int8_t prefixlen
, host_t
*gateway
, host_t
*src_ip
, char *if_name
)
218 return this->net
->del_route(this->net
, dst_net
, prefixlen
, gateway
, src_ip
,
224 * Implementation of kernel_interface_t.get_address_by_ts
226 static status_t
get_address_by_ts(private_kernel_interface_t
*this,
227 traffic_selector_t
*ts
, host_t
**ip
)
234 DBG2(DBG_KNL
, "getting a local address in traffic selector %R", ts
);
236 /* if we have a family which includes localhost, we do not
237 * search for an IP, we use the default */
238 family
= ts
->get_type(ts
) == TS_IPV4_ADDR_RANGE ? AF_INET
: AF_INET6
;
240 if (family
== AF_INET
)
242 host
= host_create_from_string("127.0.0.1", 0);
246 host
= host_create_from_string("::1", 0);
249 if (ts
->includes(ts
, host
))
251 *ip
= host_create_any(family
);
253 DBG2(DBG_KNL
, "using host %H", *ip
);
258 addrs
= this->public.create_address_enumerator(&this->public, TRUE
, TRUE
);
259 while (addrs
->enumerate(addrs
, (void**)&host
))
261 if (ts
->includes(ts
, host
))
264 *ip
= host
->clone(host
);
268 addrs
->destroy(addrs
);
272 DBG1(DBG_KNL
, "no local address found in traffic selector %R", ts
);
276 DBG2(DBG_KNL
, "using host %H", *ip
);
282 * Implementation of kernel_interface_t.add_ipsec_interface.
284 static void add_ipsec_interface(private_kernel_interface_t
*this,
285 kernel_ipsec_constructor_t
*create
)
287 this->mutex
->lock(this->mutex
);
288 this->ipsec_interfaces
->insert_last(this->ipsec_interfaces
, create
);
289 this->mutex
->unlock(this->mutex
);
293 * Implementation of kernel_interface_t.remove_ipsec_interface.
295 static void remove_ipsec_interface(private_kernel_interface_t
*this,
296 kernel_ipsec_constructor_t
*create
)
298 this->mutex
->lock(this->mutex
);
299 this->ipsec_interfaces
->remove(this->ipsec_interfaces
, create
, NULL
);
300 this->mutex
->unlock(this->mutex
);
304 * Implementation of kernel_interface_t.add_net_interface.
306 static void add_net_interface(private_kernel_interface_t
*this,
307 kernel_net_constructor_t
*create
)
309 this->mutex
->lock(this->mutex
);
310 this->net_interfaces
->insert_last(this->net_interfaces
, create
);
311 this->mutex
->unlock(this->mutex
);
315 * Implementation of kernel_interface_t.remove_net_interface.
317 static void remove_net_interface(private_kernel_interface_t
*this,
318 kernel_net_constructor_t
*create
)
320 this->mutex
->lock(this->mutex
);
321 this->net_interfaces
->remove(this->net_interfaces
, create
, NULL
);
322 this->mutex
->unlock(this->mutex
);
326 * Implementation of kernel_interface_t.create_interfaces.
328 static void create_interfaces(private_kernel_interface_t
*this)
330 kernel_ipsec_constructor_t create_ipsec
;
331 kernel_net_constructor_t create_net
;
333 this->mutex
->lock(this->mutex
);
334 if (this->ipsec_interfaces
->get_first(this->ipsec_interfaces
, (void**)&create_ipsec
) != SUCCESS
)
336 this->mutex
->unlock(this->mutex
);
337 charon
->kill(charon
, "no ipsec kernel interface loaded");
340 if (this->net_interfaces
->get_first(this->net_interfaces
, (void**)&create_net
) != SUCCESS
)
342 this->mutex
->unlock(this->mutex
);
343 charon
->kill(charon
, "no network kernel interface loaded");
345 this->mutex
->unlock(this->mutex
);
347 this->ipsec
= create_ipsec();
348 this->net
= create_net();
352 * Implementation of kernel_interface_t.destroy.
354 static void destroy(private_kernel_interface_t
*this)
356 DESTROY_IF(this->ipsec
);
357 DESTROY_IF(this->net
);
358 this->ipsec_interfaces
->destroy(this->ipsec_interfaces
);
359 this->net_interfaces
->destroy(this->net_interfaces
);
360 this->mutex
->destroy(this->mutex
);
365 * Described in header-file
367 kernel_interface_t
*kernel_interface_create()
369 private_kernel_interface_t
*this = malloc_thing(private_kernel_interface_t
);
371 this->public.get_spi
= (status_t(*)(kernel_interface_t
*,host_t
*,host_t
*,protocol_id_t
,u_int32_t
,u_int32_t
*))get_spi
;
372 this->public.get_cpi
= (status_t(*)(kernel_interface_t
*,host_t
*,host_t
*,u_int32_t
,u_int16_t
*))get_cpi
;
373 this->public.add_sa
= (status_t(*)(kernel_interface_t
*,host_t
*,host_t
*,u_int32_t
,protocol_id_t
,u_int32_t
,u_int64_t
,u_int64_t
,u_int16_t
,chunk_t
,u_int16_t
,chunk_t
,ipsec_mode_t
,u_int16_t
,bool,bool))add_sa
;
374 this->public.update_sa
= (status_t(*)(kernel_interface_t
*,u_int32_t
,protocol_id_t
,host_t
*,host_t
*,host_t
*,host_t
*,bool))update_sa
;
375 this->public.del_sa
= (status_t(*)(kernel_interface_t
*,host_t
*,u_int32_t
,protocol_id_t
))del_sa
;
376 this->public.add_policy
= (status_t(*)(kernel_interface_t
*,host_t
*,host_t
*,traffic_selector_t
*,traffic_selector_t
*,policy_dir_t
,protocol_id_t
,u_int32_t
,bool,ipsec_mode_t
,u_int16_t
))add_policy
;
377 this->public.query_policy
= (status_t(*)(kernel_interface_t
*,traffic_selector_t
*,traffic_selector_t
*,policy_dir_t
,u_int32_t
*))query_policy
;
378 this->public.del_policy
= (status_t(*)(kernel_interface_t
*,traffic_selector_t
*,traffic_selector_t
*,policy_dir_t
))del_policy
;
380 this->public.get_source_addr
= (host_t
*(*)(kernel_interface_t
*, host_t
*dest
, host_t
*src
))get_source_addr
;
381 this->public.get_nexthop
= (host_t
*(*)(kernel_interface_t
*, host_t
*dest
))get_nexthop
;
382 this->public.get_interface
= (char*(*)(kernel_interface_t
*,host_t
*))get_interface
;
383 this->public.create_address_enumerator
= (enumerator_t
*(*)(kernel_interface_t
*,bool,bool))create_address_enumerator
;
384 this->public.add_ip
= (status_t(*)(kernel_interface_t
*,host_t
*,host_t
*)) add_ip
;
385 this->public.del_ip
= (status_t(*)(kernel_interface_t
*,host_t
*)) del_ip
;
386 this->public.add_route
= (status_t(*)(kernel_interface_t
*,chunk_t
,u_int8_t
,host_t
*,host_t
*,char*)) add_route
;
387 this->public.del_route
= (status_t(*)(kernel_interface_t
*,chunk_t
,u_int8_t
,host_t
*,host_t
*,char*)) del_route
;
389 this->public.get_address_by_ts
= (status_t(*)(kernel_interface_t
*,traffic_selector_t
*,host_t
**))get_address_by_ts
;
391 this->public.add_ipsec_interface
= (void(*)(kernel_interface_t
*, kernel_ipsec_constructor_t
))add_ipsec_interface
;
392 this->public.remove_ipsec_interface
= (void(*)(kernel_interface_t
*, kernel_ipsec_constructor_t
))remove_ipsec_interface
;
393 this->public.add_net_interface
= (void(*)(kernel_interface_t
*, kernel_net_constructor_t
))add_net_interface
;
394 this->public.remove_net_interface
= (void(*)(kernel_interface_t
*, kernel_net_constructor_t
))remove_net_interface
;
396 this->public.create_interfaces
= (void (*)(kernel_interface_t
*))create_interfaces
;
397 this->public.destroy
= (void (*)(kernel_interface_t
*))destroy
;
399 this->ipsec_interfaces
= linked_list_create();
400 this->net_interfaces
= linked_list_create();
401 this->mutex
= mutex_create(MUTEX_RECURSIVE
);
405 return &this->public;