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 * Hashtable hash function
52 static u_int
hash(void *key
)
54 return (uintptr_t)key
;
58 * Hashtable equals function
60 static bool equals(void *a
, void *b
)
66 * Hash ID and host to a key
68 static uintptr_t hash_id_host(identification_t
*id
, host_t
*host
)
70 return chunk_hash_inc(id
->get_encoding(id
),
71 chunk_hash(host
->get_address(host
)));
75 * Hash a DHCP transaction to a key, using address and id
77 static uintptr_t hash_transaction(dhcp_transaction_t
*transaction
)
79 return hash_id_host(transaction
->get_identity(transaction
),
80 transaction
->get_address(transaction
));
83 METHOD(attribute_provider_t
, acquire_address
, host_t
*,
84 private_dhcp_provider_t
*this, linked_list_t
*pools
,
85 identification_t
*id
, host_t
*requested
)
87 dhcp_transaction_t
*transaction
, *old
;
88 enumerator_t
*enumerator
;
92 if (requested
->get_family(requested
) != AF_INET
)
96 enumerator
= pools
->create_enumerator(pools
);
97 while (enumerator
->enumerate(enumerator
, &pool
))
99 if (!streq(pool
, "dhcp"))
103 transaction
= this->socket
->enroll(this->socket
, id
);
108 vip
= transaction
->get_address(transaction
);
109 vip
= vip
->clone(vip
);
110 this->mutex
->lock(this->mutex
);
111 old
= this->transactions
->put(this->transactions
,
112 (void*)hash_transaction(transaction
), transaction
);
113 this->mutex
->unlock(this->mutex
);
117 enumerator
->destroy(enumerator
);
121 METHOD(attribute_provider_t
, release_address
, bool,
122 private_dhcp_provider_t
*this, linked_list_t
*pools
,
123 host_t
*address
, identification_t
*id
)
125 dhcp_transaction_t
*transaction
;
126 enumerator_t
*enumerator
;
130 if (address
->get_family(address
) != AF_INET
)
134 enumerator
= pools
->create_enumerator(pools
);
135 while (enumerator
->enumerate(enumerator
, &pool
))
137 if (!streq(pool
, "dhcp"))
141 this->mutex
->lock(this->mutex
);
142 transaction
= this->transactions
->remove(this->transactions
,
143 (void*)hash_id_host(id
, address
));
144 this->mutex
->unlock(this->mutex
);
147 this->socket
->release(this->socket
, transaction
);
148 transaction
->destroy(transaction
);
153 enumerator
->destroy(enumerator
);
157 METHOD(attribute_provider_t
, create_attribute_enumerator
, enumerator_t
*,
158 private_dhcp_provider_t
*this, linked_list_t
*pools
, identification_t
*id
,
161 dhcp_transaction_t
*transaction
= NULL
;
162 enumerator_t
*enumerator
;
165 this->mutex
->lock(this->mutex
);
166 enumerator
= vips
->create_enumerator(vips
);
167 while (enumerator
->enumerate(enumerator
, &vip
))
169 transaction
= this->transactions
->get(this->transactions
,
170 (void*)hash_id_host(id
, vip
));
176 enumerator
->destroy(enumerator
);
179 this->mutex
->unlock(this->mutex
);
182 return enumerator_create_cleaner(
183 transaction
->create_attribute_enumerator(transaction
),
184 (void*)this->mutex
->unlock
, this->mutex
);
187 METHOD(dhcp_provider_t
, destroy
, void,
188 private_dhcp_provider_t
*this)
190 enumerator_t
*enumerator
;
191 dhcp_transaction_t
*value
;
194 enumerator
= this->transactions
->create_enumerator(this->transactions
);
195 while (enumerator
->enumerate(enumerator
, &key
, &value
))
197 value
->destroy(value
);
199 enumerator
->destroy(enumerator
);
200 this->transactions
->destroy(this->transactions
);
201 this->mutex
->destroy(this->mutex
);
208 dhcp_provider_t
*dhcp_provider_create(dhcp_socket_t
*socket
)
210 private_dhcp_provider_t
*this;
215 .acquire_address
= _acquire_address
,
216 .release_address
= _release_address
,
217 .create_attribute_enumerator
= _create_attribute_enumerator
,
222 .mutex
= mutex_create(MUTEX_TYPE_DEFAULT
),
223 .transactions
= hashtable_create(hash
, equals
, 8),
226 return &this->public;