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 <utils/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, char *pool
,
123 host_t
*address
, identification_t
*id
)
125 if (streq(pool
, "dhcp") && address
->get_family(address
) == AF_INET
)
127 dhcp_transaction_t
*transaction
;
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
);
143 METHOD(attribute_provider_t
, create_attribute_enumerator
, enumerator_t
*,
144 private_dhcp_provider_t
*this, linked_list_t
*pools
, identification_t
*id
,
147 dhcp_transaction_t
*transaction
= NULL
;
148 enumerator_t
*enumerator
;
151 this->mutex
->lock(this->mutex
);
152 enumerator
= vips
->create_enumerator(vips
);
153 while (enumerator
->enumerate(enumerator
, &vip
))
155 transaction
= this->transactions
->get(this->transactions
,
156 (void*)hash_id_host(id
, vip
));
162 enumerator
->destroy(enumerator
);
165 this->mutex
->unlock(this->mutex
);
168 return enumerator_create_cleaner(
169 transaction
->create_attribute_enumerator(transaction
),
170 (void*)this->mutex
->unlock
, this->mutex
);
173 METHOD(dhcp_provider_t
, destroy
, void,
174 private_dhcp_provider_t
*this)
176 enumerator_t
*enumerator
;
177 dhcp_transaction_t
*value
;
180 enumerator
= this->transactions
->create_enumerator(this->transactions
);
181 while (enumerator
->enumerate(enumerator
, &key
, &value
))
183 value
->destroy(value
);
185 enumerator
->destroy(enumerator
);
186 this->transactions
->destroy(this->transactions
);
187 this->mutex
->destroy(this->mutex
);
194 dhcp_provider_t
*dhcp_provider_create(dhcp_socket_t
*socket
)
196 private_dhcp_provider_t
*this;
201 .acquire_address
= _acquire_address
,
202 .release_address
= _release_address
,
203 .create_attribute_enumerator
= _create_attribute_enumerator
,
208 .mutex
= mutex_create(MUTEX_TYPE_DEFAULT
),
209 .transactions
= hashtable_create(hash
, equals
, 8),
212 return &this->public;