8eed497785707f0bf2770a7121fa9caf0d4420a1
[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 <utils/hashtable.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 * Hashtable with active virtual IPs
35 */
36 hashtable_t *ips;
37
38 /**
39 * RWlock for IP list
40 */
41 rwlock_t *lock;
42 };
43
44 /**
45 * Hashtable hash function
46 */
47 static u_int hash(host_t *key)
48 {
49 return chunk_hash(key->get_address(key));
50 }
51
52 /**
53 * Hashtable equals function
54 */
55 static bool equals(host_t *a, host_t *b)
56 {
57 return a->ip_equals(a, b);
58 }
59
60 METHOD(listener_t, ike_updown, bool,
61 private_farp_listener_t *this, ike_sa_t *ike_sa, bool up)
62 {
63 if (!up)
64 {
65 host_t *ip;
66
67 ip = ike_sa->get_virtual_ip(ike_sa, FALSE);
68 if (ip)
69 {
70 this->lock->write_lock(this->lock);
71 ip = this->ips->remove(this->ips, ip);
72 this->lock->unlock(this->lock);
73 DESTROY_IF(ip);
74 }
75 }
76 return TRUE;
77 }
78
79 METHOD(listener_t, message_hook, bool,
80 private_farp_listener_t *this, ike_sa_t *ike_sa,
81 message_t *message, bool incoming)
82 {
83 if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
84 message->get_exchange_type(message) == IKE_AUTH &&
85 !message->get_request(message))
86 {
87 host_t *ip;
88
89 ip = ike_sa->get_virtual_ip(ike_sa, FALSE);
90 if (ip)
91 {
92 ip = ip->clone(ip);
93 this->lock->write_lock(this->lock);
94 ip = this->ips->put(this->ips, ip, ip);
95 this->lock->unlock(this->lock);
96 DESTROY_IF(ip);
97 }
98 }
99 return TRUE;
100 }
101
102 METHOD(farp_listener_t, is_active, bool,
103 private_farp_listener_t *this, host_t *ip)
104 {
105 bool active;
106
107 this->lock->read_lock(this->lock);
108 active = this->ips->get(this->ips, ip) != NULL;
109 this->lock->unlock(this->lock);
110 return active;
111 }
112
113 METHOD(farp_listener_t, destroy, void,
114 private_farp_listener_t *this)
115 {
116 enumerator_t *enumerator;
117 host_t *key, *value;
118
119 enumerator = this->ips->create_enumerator(this->ips);
120 while (enumerator->enumerate(enumerator, &key, &value))
121 {
122 value->destroy(value);
123 }
124 enumerator->destroy(enumerator);
125 this->ips->destroy(this->ips);
126
127 this->lock->destroy(this->lock);
128 free(this);
129 }
130
131 /**
132 * See header
133 */
134 farp_listener_t *farp_listener_create()
135 {
136 private_farp_listener_t *this;
137
138 INIT(this,
139 .public = {
140 .listener = {
141 .ike_updown = _ike_updown,
142 .message = _message_hook,
143 },
144 .is_active = _is_active,
145 .destroy = _destroy,
146 },
147 .ips = hashtable_create((hashtable_hash_t)hash,
148 (hashtable_equals_t)equals, 8),
149 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
150 );
151
152 return &this->public;
153 }
154