2 * Copyright (C) 2011 Andreas Steffen
3 * HSR 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
16 #include "shunt_manager.h"
20 #include <threading/rwlock.h>
21 #include <utils/linked_list.h>
24 typedef struct private_shunt_manager_t private_shunt_manager_t
;
27 * Private data of an shunt_manager_t object.
29 struct private_shunt_manager_t
{
32 * Public shunt_manager_t interface.
34 shunt_manager_t
public;
37 * Installed shunts, as child_cfg_t
39 linked_list_t
*shunts
;
43 * Install in and out shunt policies in the kernel
45 static bool install_shunt_policy(child_cfg_t
*child
)
47 enumerator_t
*e_my_ts
, *e_other_ts
;
48 linked_list_t
*my_ts_list
, *other_ts_list
;
49 traffic_selector_t
*my_ts
, *other_ts
;
51 policy_type_t policy_type
;
52 status_t status
= SUCCESS
;
53 ipsec_sa_cfg_t sa
= { .mode
= MODE_TRANSPORT
};
55 policy_type
= (child
->get_mode(child
) == MODE_PASS
) ?
56 POLICY_PASS
: POLICY_DROP
;
57 my_ts_list
= child
->get_traffic_selectors(child
, TRUE
, NULL
, NULL
);
58 other_ts_list
= child
->get_traffic_selectors(child
, FALSE
, NULL
, NULL
);
59 host_any
= host_create_any(AF_INET
);
61 /* enumerate pairs of traffic selectors */
62 e_my_ts
= my_ts_list
->create_enumerator(my_ts_list
);
63 while (e_my_ts
->enumerate(e_my_ts
, &my_ts
))
65 e_other_ts
= other_ts_list
->create_enumerator(other_ts_list
);
66 while (e_other_ts
->enumerate(e_other_ts
, &other_ts
))
68 /* install out policy */
69 status
|= hydra
->kernel_interface
->add_policy(
70 hydra
->kernel_interface
, host_any
, host_any
,
71 my_ts
, other_ts
, POLICY_OUT
, policy_type
,
72 &sa
, child
->get_mark(child
, FALSE
),
73 POLICY_PRIORITY_DEFAULT
);
75 /* install in policy */
76 status
|= hydra
->kernel_interface
->add_policy(
77 hydra
->kernel_interface
, host_any
, host_any
,
78 other_ts
, my_ts
, POLICY_IN
, policy_type
,
79 &sa
, child
->get_mark(child
, TRUE
),
80 POLICY_PRIORITY_DEFAULT
);
82 /* install forward policy */
83 status
|= hydra
->kernel_interface
->add_policy(
84 hydra
->kernel_interface
, host_any
, host_any
,
85 other_ts
, my_ts
, POLICY_FWD
, policy_type
,
86 &sa
, child
->get_mark(child
, TRUE
),
87 POLICY_PRIORITY_DEFAULT
);
89 e_other_ts
->destroy(e_other_ts
);
91 e_my_ts
->destroy(e_my_ts
);
93 my_ts_list
->destroy_offset(my_ts_list
,
94 offsetof(traffic_selector_t
, destroy
));
95 other_ts_list
->destroy_offset(other_ts_list
,
96 offsetof(traffic_selector_t
, destroy
));
97 host_any
->destroy(host_any
);
99 return status
== SUCCESS
;
102 METHOD(shunt_manager_t
, install
, bool,
103 private_shunt_manager_t
*this, child_cfg_t
*child
)
105 enumerator_t
*enumerator
;
106 child_cfg_t
*child_cfg
;
109 /* check if not already installed */
110 enumerator
= this->shunts
->create_enumerator(this->shunts
);
111 while (enumerator
->enumerate(enumerator
, &child_cfg
))
113 if (streq(child_cfg
->get_name(child_cfg
), child
->get_name(child
)))
119 enumerator
->destroy(enumerator
);
123 DBG1(DBG_CFG
, "shunt %N policy '%s' already installed",
124 ipsec_mode_names
, child
->get_mode(child
), child
->get_name(child
));
127 this->shunts
->insert_last(this->shunts
, child
->get_ref(child
));
129 return install_shunt_policy(child
);
133 * Uninstall in and out shunt policies in the kernel
135 static void uninstall_shunt_policy(child_cfg_t
*child
)
137 enumerator_t
*e_my_ts
, *e_other_ts
;
138 linked_list_t
*my_ts_list
, *other_ts_list
;
139 traffic_selector_t
*my_ts
, *other_ts
;
140 status_t status
= SUCCESS
;
142 my_ts_list
= child
->get_traffic_selectors(child
, TRUE
, NULL
, NULL
);
143 other_ts_list
= child
->get_traffic_selectors(child
, FALSE
, NULL
, NULL
);
145 /* enumerate pairs of traffic selectors */
146 e_my_ts
= my_ts_list
->create_enumerator(my_ts_list
);
147 while (e_my_ts
->enumerate(e_my_ts
, &my_ts
))
149 e_other_ts
= other_ts_list
->create_enumerator(other_ts_list
);
150 while (e_other_ts
->enumerate(e_other_ts
, &other_ts
))
152 /* uninstall out policy */
153 status
|= hydra
->kernel_interface
->del_policy(
154 hydra
->kernel_interface
, my_ts
, other_ts
,
155 POLICY_OUT
, 0, child
->get_mark(child
, FALSE
),
156 POLICY_PRIORITY_DEFAULT
);
158 /* uninstall in policy */
159 status
|= hydra
->kernel_interface
->del_policy(
160 hydra
->kernel_interface
, other_ts
, my_ts
,
161 POLICY_IN
, 0, child
->get_mark(child
, TRUE
),
162 POLICY_PRIORITY_DEFAULT
);
164 /* uninstall forward policy */
165 status
|= hydra
->kernel_interface
->del_policy(
166 hydra
->kernel_interface
, other_ts
, my_ts
,
167 POLICY_FWD
, 0, child
->get_mark(child
, TRUE
),
168 POLICY_PRIORITY_DEFAULT
);
170 e_other_ts
->destroy(e_other_ts
);
172 e_my_ts
->destroy(e_my_ts
);
174 my_ts_list
->destroy_offset(my_ts_list
,
175 offsetof(traffic_selector_t
, destroy
));
176 other_ts_list
->destroy_offset(other_ts_list
,
177 offsetof(traffic_selector_t
, destroy
));
179 if (status
!= SUCCESS
)
181 DBG1(DBG_CFG
, "uninstalling shunt %N 'policy %s' failed",
182 ipsec_mode_names
, child
->get_mode(child
), child
->get_name(child
));
186 METHOD(shunt_manager_t
, uninstall
, bool,
187 private_shunt_manager_t
*this, char *name
)
189 enumerator_t
*enumerator
;
190 child_cfg_t
*child
, *found
= NULL
;
192 enumerator
= this->shunts
->create_enumerator(this->shunts
);
193 while (enumerator
->enumerate(enumerator
, &child
))
195 if (streq(name
, child
->get_name(child
)))
197 this->shunts
->remove_at(this->shunts
, enumerator
);
202 enumerator
->destroy(enumerator
);
208 uninstall_shunt_policy(child
);
212 METHOD(shunt_manager_t
, create_enumerator
, enumerator_t
*,
213 private_shunt_manager_t
*this)
215 return this->shunts
->create_enumerator(this->shunts
);
218 METHOD(shunt_manager_t
, destroy
, void,
219 private_shunt_manager_t
*this)
223 while (this->shunts
->remove_last(this->shunts
, (void**)&child
) == SUCCESS
)
225 uninstall_shunt_policy(child
);
226 child
->destroy(child
);
228 this->shunts
->destroy(this->shunts
);
235 shunt_manager_t
*shunt_manager_create()
237 private_shunt_manager_t
*this;
242 .uninstall
= _uninstall
,
243 .create_enumerator
= _create_enumerator
,
246 .shunts
= linked_list_create(),
249 return &this->public;