3 * Copyright (C) 1998 and 1999 WIDE Project.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the project nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/socket.h>
35 #include <sys/queue.h>
36 #if TIME_WITH_SYS_TIME
37 # include <sys/time.h>
41 # include <sys/time.h>
46 #include <netinet/in.h>
57 LIST_ENTRY(hash_entry
) list
;
59 char flag
; /* 0x01: DHCP6_LEASE_DECLINED */
62 /* marked as declined (e.g. someone has been using the same address) */
63 #define DHCP6_LEASE_DECLINED 0x01
65 LIST_HEAD(hash_head
, hash_entry
);
67 typedef unsigned int (*pfn_hash_t
)(void *val
) ;
68 typedef int (*pfh_hash_match_t
)(void *val1
, void *val2
);
71 struct hash_head
*table
;
74 pfh_hash_match_t match
;
77 #ifndef DHCP6_LEASE_TABLE_SIZE
78 #define DHCP6_LEASE_TABLE_SIZE 256
81 static struct hash_table dhcp6_lease_table
;
83 static unsigned int in6_addr_hash
__P((void *));
84 static int in6_addr_match
__P((void *, void *));
86 static int hash_table_init
__P((struct hash_table
*, unsigned int,
87 pfn_hash_t
, pfh_hash_match_t
));
88 static void hash_table_cleanup
__P((struct hash_table
*));
89 static int hash_table_add
__P((struct hash_table
*, void *, unsigned int));
90 static int hash_table_remove
__P((struct hash_table
*, void *));
91 static struct hash_entry
* hash_table_find
__P((struct hash_table
*, void *));
96 dprintf(LOG_DEBUG
, FNAME
, "called");
98 if (hash_table_init(&dhcp6_lease_table
, DHCP6_LEASE_TABLE_SIZE
,
99 in6_addr_hash
, in6_addr_match
) != 0) {
109 hash_table_cleanup(&dhcp6_lease_table
);
114 struct in6_addr
*addr
;
119 dprintf(LOG_DEBUG
, FNAME
, "addr=%s", in6addr2str(addr
, 0));
121 if (hash_table_find(&dhcp6_lease_table
, addr
)) {
122 dprintf(LOG_WARNING
, FNAME
, "already leased: %s",
123 in6addr2str(addr
, 0));
127 if (hash_table_add(&dhcp6_lease_table
, addr
, sizeof(*addr
)) != 0) {
135 release_address(addr
)
136 struct in6_addr
*addr
;
141 dprintf(LOG_DEBUG
, FNAME
, "addr=%s", in6addr2str(addr
, 0));
143 if (hash_table_remove(&dhcp6_lease_table
, addr
) != 0) {
144 dprintf(LOG_WARNING
, FNAME
, "not found: %s", in6addr2str(addr
, 0));
149 decline_address(addr
)
150 struct in6_addr
*addr
;
152 struct hash_entry
*entry
;
157 dprintf(LOG_DEBUG
, FNAME
, "addr=%s", in6addr2str(addr
, 0));
159 entry
= hash_table_find(&dhcp6_lease_table
, addr
);
161 dprintf(LOG_WARNING
, FNAME
, "not found: %s",
162 in6addr2str(addr
, 0));
166 entry
->flag
|= DHCP6_LEASE_DECLINED
;
171 struct in6_addr
*addr
;
173 return (hash_table_find(&dhcp6_lease_table
, addr
) != NULL
);
180 u_int8_t
*addr
= ((struct in6_addr
*)val
)->s6_addr
;
181 unsigned int hash
= 0;
184 for (i
= 0; i
< 16; i
++) {
192 in6_addr_match(val1
, val2
)
195 struct in6_addr
* addr1
= val1
;
196 struct in6_addr
* addr2
= val2
;
198 return (memcmp(addr1
->s6_addr
, addr2
->s6_addr
, 16) == 0);
205 hash_table_init(table
, size
, hash
, match
)
206 struct hash_table
*table
;
209 pfh_hash_match_t match
;
213 if (!table
|| !hash
|| !match
) {
217 if ((table
->table
= malloc(sizeof(*table
->table
) * size
)) == NULL
) {
221 for (i
= 0; i
< size
; i
++)
222 LIST_INIT(&table
->table
[i
]);
226 table
->match
= match
;
232 hash_table_cleanup(table
)
233 struct hash_table
*table
;
241 for (i
= 0; i
< table
->size
; i
++) {
242 while (!LIST_EMPTY(&table
->table
[i
])) {
243 struct hash_entry
*entry
= LIST_FIRST(&table
->table
[i
]);
244 LIST_REMOVE(entry
, list
);
251 memset(table
, 0, sizeof(*table
));
255 hash_table_add(table
, val
, size
)
256 struct hash_table
*table
;
260 struct hash_entry
*entry
= NULL
;
263 if (!table
|| !val
) {
267 if ((entry
= malloc(sizeof(*entry
))) == NULL
) {
270 memset(entry
, 0, sizeof(*entry
));
272 if ((entry
->val
= malloc(size
)) == NULL
) {
275 memcpy(entry
->val
, val
, size
);
277 i
= table
->hash(val
) % table
->size
;
278 LIST_INSERT_HEAD(&table
->table
[i
], entry
, list
);
284 hash_table_remove(table
, val
)
285 struct hash_table
*table
;
288 struct hash_entry
*entry
;
290 if (!table
|| !val
) {
294 if ((entry
= hash_table_find(table
, val
)) == NULL
) {
298 LIST_REMOVE(entry
, list
);
306 static struct hash_entry
*
307 hash_table_find(table
, val
)
308 struct hash_table
*table
;
311 struct hash_entry
*entry
;
314 if (!table
|| !val
) {
318 i
= table
->hash(val
) % table
->size
;
319 LIST_FOREACH(entry
, &table
->table
[i
], list
)
321 if (table
->match(val
, entry
->val
)) {