2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
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 "dhcp_provider.h"
18 #include <collections/hashtable.h>
19 #include <threading/mutex.h>
21 typedef struct private_dhcp_provider_t private_dhcp_provider_t
;
24 * Private data of an dhcp_provider_t object.
26 struct private_dhcp_provider_t
{
29 * Public dhcp_provider_t interface.
31 dhcp_provider_t
public;
34 * Completed DHCP transactions
36 hashtable_t
*transactions
;
39 * Lock for transactions
44 * DHCP communication socket
46 dhcp_socket_t
*socket
;
50 * Hash ID and host to a key
52 static uintptr_t hash_id_host(identification_t
*id
, host_t
*host
)
54 return chunk_hash_inc(id
->get_encoding(id
),
55 chunk_hash(host
->get_address(host
)));
59 * Hash a DHCP transaction to a key, using address and id
61 static uintptr_t hash_transaction(dhcp_transaction_t
*transaction
)
63 return hash_id_host(transaction
->get_identity(transaction
),
64 transaction
->get_address(transaction
));
67 METHOD(attribute_provider_t
, acquire_address
, host_t
*,
68 private_dhcp_provider_t
*this, linked_list_t
*pools
,
69 ike_sa_t
*ike_sa
, host_t
*requested
)
71 dhcp_transaction_t
*transaction
, *old
;
72 enumerator_t
*enumerator
;
77 if (requested
->get_family(requested
) != AF_INET
)
81 id
= ike_sa
->get_other_eap_id(ike_sa
);
82 enumerator
= pools
->create_enumerator(pools
);
83 while (enumerator
->enumerate(enumerator
, &pool
))
85 if (!streq(pool
, "dhcp"))
89 transaction
= this->socket
->enroll(this->socket
, id
);
94 vip
= transaction
->get_address(transaction
);
95 vip
= vip
->clone(vip
);
96 this->mutex
->lock(this->mutex
);
97 old
= this->transactions
->put(this->transactions
,
98 (void*)hash_transaction(transaction
), transaction
);
99 this->mutex
->unlock(this->mutex
);
103 enumerator
->destroy(enumerator
);
107 METHOD(attribute_provider_t
, release_address
, bool,
108 private_dhcp_provider_t
*this, linked_list_t
*pools
,
109 host_t
*address
, ike_sa_t
*ike_sa
)
111 dhcp_transaction_t
*transaction
;
112 enumerator_t
*enumerator
;
113 identification_t
*id
;
117 if (address
->get_family(address
) != AF_INET
)
121 id
= ike_sa
->get_other_eap_id(ike_sa
);
122 enumerator
= pools
->create_enumerator(pools
);
123 while (enumerator
->enumerate(enumerator
, &pool
))
125 if (!streq(pool
, "dhcp"))
129 this->mutex
->lock(this->mutex
);
130 transaction
= this->transactions
->remove(this->transactions
,
131 (void*)hash_id_host(id
, address
));
132 this->mutex
->unlock(this->mutex
);
135 this->socket
->release(this->socket
, transaction
);
136 transaction
->destroy(transaction
);
141 enumerator
->destroy(enumerator
);
145 METHOD(attribute_provider_t
, create_attribute_enumerator
, enumerator_t
*,
146 private_dhcp_provider_t
*this, linked_list_t
*pools
, ike_sa_t
*ike_sa
,
149 dhcp_transaction_t
*transaction
= NULL
;
150 enumerator_t
*enumerator
;
151 identification_t
*id
;
154 if (!pools
->find_first(pools
, linked_list_match_str
, NULL
, "dhcp"))
159 id
= ike_sa
->get_other_eap_id(ike_sa
);
160 this->mutex
->lock(this->mutex
);
161 enumerator
= vips
->create_enumerator(vips
);
162 while (enumerator
->enumerate(enumerator
, &vip
))
164 transaction
= this->transactions
->get(this->transactions
,
165 (void*)hash_id_host(id
, vip
));
171 enumerator
->destroy(enumerator
);
174 this->mutex
->unlock(this->mutex
);
177 return enumerator_create_cleaner(
178 transaction
->create_attribute_enumerator(transaction
),
179 (void*)this->mutex
->unlock
, this->mutex
);
182 METHOD(dhcp_provider_t
, destroy
, void,
183 private_dhcp_provider_t
*this)
185 enumerator_t
*enumerator
;
186 dhcp_transaction_t
*value
;
189 enumerator
= this->transactions
->create_enumerator(this->transactions
);
190 while (enumerator
->enumerate(enumerator
, &key
, &value
))
192 value
->destroy(value
);
194 enumerator
->destroy(enumerator
);
195 this->transactions
->destroy(this->transactions
);
196 this->mutex
->destroy(this->mutex
);
203 dhcp_provider_t
*dhcp_provider_create(dhcp_socket_t
*socket
)
205 private_dhcp_provider_t
*this;
210 .acquire_address
= _acquire_address
,
211 .release_address
= _release_address
,
212 .create_attribute_enumerator
= _create_attribute_enumerator
,
217 .mutex
= mutex_create(MUTEX_TYPE_DEFAULT
),
218 .transactions
= hashtable_create(hashtable_hash_ptr
,
219 hashtable_equals_ptr
, 8),
222 return &this->public;