e19fc59721db5173bd6f65accf6050d7ffda1f1e
[strongswan.git] / src / libcharon / plugins / farp / farp_listener.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 *
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>.
9 *
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
13 * for more details.
14 */
15
16 #include "farp_listener.h"
17
18 #include <collections/linked_list.h>
19 #include <threading/rwlock.h>
20
21 typedef struct private_farp_listener_t private_farp_listener_t;
22
23 /**
24 * Private data of an farp_listener_t object.
25 */
26 struct private_farp_listener_t {
27
28 /**
29 * Public farp_listener_t interface.
30 */
31 farp_listener_t public;
32
33 /**
34 * List with entry_t
35 */
36 linked_list_t *entries;
37
38 /**
39 * RWlock for IP list
40 */
41 rwlock_t *lock;
42 };
43
44 /**
45 * Traffic selector cache entry
46 */
47 typedef struct {
48 /** list of local selectors */
49 linked_list_t *local;
50 /** list of remote selectors */
51 linked_list_t *remote;
52 /** reqid of CHILD_SA */
53 uint32_t reqid;
54 } entry_t;
55
56 METHOD(listener_t, child_updown, bool,
57 private_farp_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
58 bool up)
59 {
60 enumerator_t *enumerator;
61 traffic_selector_t *ts;
62 entry_t *entry;
63
64 if (up)
65 {
66 INIT(entry,
67 .local = linked_list_create(),
68 .remote = linked_list_create(),
69 .reqid = child_sa->get_reqid(child_sa),
70 );
71
72 enumerator = child_sa->create_ts_enumerator(child_sa, TRUE);
73 while (enumerator->enumerate(enumerator, &ts))
74 {
75 entry->local->insert_last(entry->local, ts->clone(ts));
76 }
77 enumerator->destroy(enumerator);
78
79 enumerator = child_sa->create_ts_enumerator(child_sa, FALSE);
80 while (enumerator->enumerate(enumerator, &ts))
81 {
82 entry->remote->insert_last(entry->remote, ts->clone(ts));
83 }
84 enumerator->destroy(enumerator);
85
86 this->lock->write_lock(this->lock);
87 this->entries->insert_last(this->entries, entry);
88 this->lock->unlock(this->lock);
89 }
90 else
91 {
92 this->lock->write_lock(this->lock);
93 enumerator = this->entries->create_enumerator(this->entries);
94 while (enumerator->enumerate(enumerator, &entry))
95 {
96 if (entry->reqid == child_sa->get_reqid(child_sa))
97 {
98 this->entries->remove_at(this->entries, enumerator);
99 entry->local->destroy_offset(entry->local,
100 offsetof(traffic_selector_t, destroy));
101 entry->remote->destroy_offset(entry->remote,
102 offsetof(traffic_selector_t, destroy));
103 free(entry);
104 }
105 }
106 enumerator->destroy(enumerator);
107 this->lock->unlock(this->lock);
108 }
109 return TRUE;
110 }
111
112 METHOD(farp_listener_t, has_tunnel, bool,
113 private_farp_listener_t *this, host_t *local, host_t *remote)
114 {
115 enumerator_t *entries, *locals, *remotes;
116 traffic_selector_t *ts;
117 bool found = FALSE;
118 entry_t *entry;
119
120 this->lock->read_lock(this->lock);
121 entries = this->entries->create_enumerator(this->entries);
122 while (!found && entries->enumerate(entries, &entry))
123 {
124 remotes = entry->remote->create_enumerator(entry->remote);
125 while (!found && remotes->enumerate(remotes, &ts))
126 {
127 if (ts->includes(ts, remote))
128 {
129 locals = entry->local->create_enumerator(entry->local);
130 while (!found && locals->enumerate(locals, &ts))
131 {
132 found = ts->includes(ts, local);
133 }
134 locals->destroy(locals);
135 }
136 }
137 remotes->destroy(remotes);
138 }
139 entries->destroy(entries);
140 this->lock->unlock(this->lock);
141
142 return found;
143 }
144
145 METHOD(farp_listener_t, destroy, void,
146 private_farp_listener_t *this)
147 {
148 this->entries->destroy(this->entries);
149 this->lock->destroy(this->lock);
150 free(this);
151 }
152
153 /**
154 * See header
155 */
156 farp_listener_t *farp_listener_create()
157 {
158 private_farp_listener_t *this;
159
160 INIT(this,
161 .public = {
162 .listener = {
163 .child_updown = _child_updown,
164 },
165 .has_tunnel = _has_tunnel,
166 .destroy = _destroy,
167 },
168 .entries = linked_list_create(),
169 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
170 );
171
172 return &this->public;
173 }