Statistics
| Branch: | Tag: | Revision:

root / src / libstrongswan / attributes / attribute_manager.c @ b5a2055fb1b88ea4abb97334d89e311c9ceaa7d4

History | View | Annotate | Download (8.9 KB)

1
/*
2
 * Copyright (C) 2008 Martin Willi
3
 * Hochschule fuer Technik Rapperswil
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 "attribute_manager.h"
17
18
#include <debug.h>
19
#include <utils/linked_list.h>
20
#include <utils/mutex.h>
21
22
typedef struct private_attribute_manager_t private_attribute_manager_t;
23
24
/**
25
 * private data of attribute_manager
26
 */
27
struct private_attribute_manager_t {
28
29
    /**
30
     * public functions
31
     */
32
    attribute_manager_t public;
33
34
    /**
35
     * list of registered providers
36
     */
37
    linked_list_t *providers;
38
39
    /**
40
     * list of registered handlers
41
     */
42
    linked_list_t *handlers;
43
44
    /**
45
     * rwlock provider list
46
     */
47
    rwlock_t *lock;
48
};
49
50
/**
51
 * Data to pass to enumerator filters
52
 */
53
typedef struct {
54
    /** server/peer identity */
55
    identification_t *id;
56
    /** requesting/assigned virtual IP */
57
    host_t *vip;
58
} enum_data_t;
59
60
/**
61
 * Implementation of attribute_manager_t.acquire_address.
62
 */
63
static host_t* acquire_address(private_attribute_manager_t *this,
64
                               char *pool, identification_t *id,
65
                               host_t *requested)
66
{
67
    enumerator_t *enumerator;
68
    attribute_provider_t *current;
69
    host_t *host = NULL;
70
71
    this->lock->read_lock(this->lock);
72
    enumerator = this->providers->create_enumerator(this->providers);
73
    while (enumerator->enumerate(enumerator, &current))
74
    {
75
        host = current->acquire_address(current, pool, id, requested);
76
        if (host)
77
        {
78
            break;
79
        }
80
    }
81
    enumerator->destroy(enumerator);
82
    this->lock->unlock(this->lock);
83
84
    if (!host)
85
    {
86
        DBG1("acquiring address from pool '%s' failed", pool);
87
    }
88
    return host;
89
}
90
91
/**
92
 * Implementation of attribute_manager_t.release_address.
93
 */
94
static void release_address(private_attribute_manager_t *this,
95
                            char *pool, host_t *address, identification_t *id)
96
{
97
    enumerator_t *enumerator;
98
    attribute_provider_t *current;
99
    bool found = FALSE;
100
101
    this->lock->read_lock(this->lock);
102
    enumerator = this->providers->create_enumerator(this->providers);
103
    while (enumerator->enumerate(enumerator, &current))
104
    {
105
        if (current->release_address(current, pool, address, id))
106
        {
107
            found = TRUE;
108
            break;
109
        }
110
    }
111
    enumerator->destroy(enumerator);
112
    this->lock->unlock(this->lock);
113
114
    if (!found)
115
    {
116
        DBG1("releasing address to pool '%s' failed", pool);
117
    }
118
}
119
120
/**
121
 * inner enumerator constructor for responder attributes
122
 */
123
static enumerator_t *responder_enum_create(attribute_provider_t *provider,
124
                                           enum_data_t *data)
125
{
126
    return provider->create_attribute_enumerator(provider, data->id, data->vip);
127
}
128
129
/**
130
 * Implementation of attribute_manager_t.create_responder_enumerator
131
 */
132
static enumerator_t* create_responder_enumerator(
133
            private_attribute_manager_t *this, identification_t *id, host_t *vip)
134
{
135
    enum_data_t *data = malloc_thing(enum_data_t);
136
137
    data->id = id;
138
    data->vip = vip;
139
    this->lock->read_lock(this->lock);
140
    return enumerator_create_cleaner(
141
                enumerator_create_nested(
142
                    this->providers->create_enumerator(this->providers),
143
                    (void*)responder_enum_create, data, free),
144
                (void*)this->lock->unlock, this->lock);
145
}
146
147
/**
148
 * Implementation of attribute_manager_t.add_provider.
149
 */
150
static void add_provider(private_attribute_manager_t *this,
151
                         attribute_provider_t *provider)
152
{
153
    this->lock->write_lock(this->lock);
154
    this->providers->insert_last(this->providers, provider);
155
    this->lock->unlock(this->lock);
156
}
157
158
/**
159
 * Implementation of attribute_manager_t.remove_provider.
160
 */
161
static void remove_provider(private_attribute_manager_t *this,
162
                            attribute_provider_t *provider)
163
{
164
    this->lock->write_lock(this->lock);
165
    this->providers->remove(this->providers, provider, NULL);
166
    this->lock->unlock(this->lock);
167
}
168
169
/**
170
 * Implementation of attribute_manager_t.handle
171
 */
172
static attribute_handler_t* handle(private_attribute_manager_t *this,
173
                        identification_t *server, attribute_handler_t *handler,
174
                        configuration_attribute_type_t type, chunk_t data)
175
{
176
    enumerator_t *enumerator;
177
    attribute_handler_t *current, *handled = NULL;
178
179
    this->lock->read_lock(this->lock);
180
181
    /* try to find the passed handler */
182
    enumerator = this->handlers->create_enumerator(this->handlers);
183
    while (enumerator->enumerate(enumerator, &current))
184
    {
185
        if (current == handler && current->handle(current, server, type, data))
186
        {
187
            handled = current;
188
            break;
189
        }
190
    }
191
    enumerator->destroy(enumerator);
192
    if (!handled)
193
    {    /* handler requesting this attribute not found, try any other */
194
        enumerator = this->handlers->create_enumerator(this->handlers);
195
        while (enumerator->enumerate(enumerator, &current))
196
        {
197
            if (current->handle(current, server, type, data))
198
            {
199
                handled = current;
200
                break;
201
            }
202
        }
203
        enumerator->destroy(enumerator);
204
    }
205
    this->lock->unlock(this->lock);
206
207
    if (!handled)
208
    {
209
        DBG1("handling %N attribute failed",
210
             configuration_attribute_type_names, type);
211
    }
212
    return handled;
213
}
214
215
/**
216
 * Implementation of attribute_manager_t.release
217
 */
218
static void release(private_attribute_manager_t *this,
219
                    attribute_handler_t *handler,
220
                    identification_t *server,
221
                    configuration_attribute_type_t type, chunk_t data)
222
{
223
    enumerator_t *enumerator;
224
    attribute_handler_t *current;
225
226
    this->lock->read_lock(this->lock);
227
    enumerator = this->handlers->create_enumerator(this->handlers);
228
    while (enumerator->enumerate(enumerator, &current))
229
    {
230
        if (current == handler)
231
        {
232
            current->release(current, server, type, data);
233
            break;
234
        }
235
    }
236
    enumerator->destroy(enumerator);
237
    this->lock->unlock(this->lock);
238
}
239
240
/**
241
 * inner enumerator constructor for initiator attributes
242
 */
243
static enumerator_t *initiator_enum_create(attribute_handler_t *handler,
244
                                           enum_data_t *data)
245
{
246
    return handler->create_attribute_enumerator(handler, data->id, data->vip);
247
}
248
249
/**
250
 * Implementation of attribute_manager_t.create_initiator_enumerator
251
 */
252
static enumerator_t* create_initiator_enumerator(
253
        private_attribute_manager_t *this, identification_t *id, host_t *vip)
254
{
255
    enum_data_t *data = malloc_thing(enum_data_t);
256
257
    data->id = id;
258
    data->vip = vip;
259
    this->lock->read_lock(this->lock);
260
    return enumerator_create_cleaner(
261
                enumerator_create_nested(
262
                    this->handlers->create_enumerator(this->handlers),
263
                    (void*)initiator_enum_create, data, free),
264
                (void*)this->lock->unlock, this->lock);
265
}
266
267
/**
268
 * Implementation of attribute_manager_t.add_handler
269
 */
270
static void add_handler(private_attribute_manager_t *this,
271
                        attribute_handler_t *handler)
272
{
273
    this->lock->write_lock(this->lock);
274
    this->handlers->insert_last(this->handlers, handler);
275
    this->lock->unlock(this->lock);
276
}
277
278
/**
279
 * Implementation of attribute_manager_t.remove_handler
280
 */
281
static void remove_handler(private_attribute_manager_t *this,
282
                        attribute_handler_t *handler)
283
{
284
    this->lock->write_lock(this->lock);
285
    this->handlers->remove(this->handlers, handler, NULL);
286
    this->lock->unlock(this->lock);
287
}
288
289
/**
290
 * Implementation of attribute_manager_t.destroy
291
 */
292
static void destroy(private_attribute_manager_t *this)
293
{
294
    this->providers->destroy(this->providers);
295
    this->handlers->destroy(this->handlers);
296
    this->lock->destroy(this->lock);
297
    free(this);
298
}
299
300
/*
301
 * see header file
302
 */
303
attribute_manager_t *attribute_manager_create()
304
{
305
    private_attribute_manager_t *this = malloc_thing(private_attribute_manager_t);
306
307
    this->public.acquire_address = (host_t*(*)(attribute_manager_t*, char*, identification_t*,host_t*))acquire_address;
308
    this->public.release_address = (void(*)(attribute_manager_t*, char *, host_t*, identification_t*))release_address;
309
    this->public.create_responder_enumerator = (enumerator_t*(*)(attribute_manager_t*, identification_t*, host_t*))create_responder_enumerator;
310
    this->public.add_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))add_provider;
311
    this->public.remove_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))remove_provider;
312
    this->public.handle = (attribute_handler_t*(*)(attribute_manager_t*,identification_t*, attribute_handler_t*, configuration_attribute_type_t, chunk_t))handle;
313
    this->public.release = (void(*)(attribute_manager_t*, attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))release;
314
    this->public.create_initiator_enumerator = (enumerator_t*(*)(attribute_manager_t*, identification_t*, host_t*))create_initiator_enumerator;
315
    this->public.add_handler = (void(*)(attribute_manager_t*, attribute_handler_t*))add_handler;
316
    this->public.remove_handler = (void(*)(attribute_manager_t*, attribute_handler_t*))remove_handler;
317
    this->public.destroy = (void(*)(attribute_manager_t*))destroy;
318
319
    this->providers = linked_list_create();
320
    this->handlers = linked_list_create();
321
    this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
322
323
    return &this->public;
324
}
325