1 /*	$NetBSD: mdb6_unittest.c,v 1.1.1.2 2014/07/12 11:58:16 spz Exp $	*/
2 /*
3  * Copyright (C) 2007-2012 by Internet Systems Consortium, Inc. ("ISC")
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include "config.h"
19 
20 #include <sys/types.h>
21 #include <time.h>
22 #include <netinet/in.h>
23 
24 #include <stdarg.h>
25 #include "dhcpd.h"
26 #include "omapip/omapip.h"
27 #include "omapip/hash.h"
28 #include <isc/md5.h>
29 
30 #include <atf-c.h>
31 
32 #include <stdlib.h>
33 
34 void build_prefix6(struct in6_addr *pref, const struct in6_addr *net_start_pref,
35                    int pool_bits, int pref_bits,
36                    const struct data_string *input);
37 
38 /*
39  * Basic iaaddr manipulation.
40  * Verify construction and referencing of an iaaddr.
41  */
42 
43 ATF_TC(iaaddr_basic);
44 ATF_TC_HEAD(iaaddr_basic, tc)
45 {
46     atf_tc_set_md_var(tc, "descr", "This test case checks that basic "
47                       "IAADDR manipulation is possible.");
48 }
49 ATF_TC_BODY(iaaddr_basic, tc)
50 {
51     struct iasubopt *iaaddr;
52     struct iasubopt *iaaddr_copy;
53 
54     /* set up dhcp globals */
55     dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB,
56 			NULL, NULL);
57 
58     /* and other common arguments */
59     iaaddr = NULL;
60     iaaddr_copy = NULL;
61 
62     /* tests */
63     if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) {
64         atf_tc_fail("ERROR: iasubopt_allocate() %s:%d", MDL);
65     }
66     if (iaaddr->state != FTS_FREE) {
67         atf_tc_fail("ERROR: bad state %s:%d", MDL);
68     }
69     if (iaaddr->heap_index != -1) {
70         atf_tc_fail("ERROR: bad heap_index %s:%d", MDL);
71     }
72     if (iasubopt_reference(&iaaddr_copy, iaaddr, MDL) != ISC_R_SUCCESS) {
73         atf_tc_fail("ERROR: iasubopt_reference() %s:%d", MDL);
74     }
75     if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
76         atf_tc_fail("ERROR: iasubopt_reference() %s:%d", MDL);
77     }
78     if (iasubopt_dereference(&iaaddr_copy, MDL) != ISC_R_SUCCESS) {
79         atf_tc_fail("ERROR: iasubopt_reference() %s:%d", MDL);
80     }
81 }
82 
83 /*
84  * Basic iaaddr sanity checks.
85  * Verify that the iaaddr code does some sanity checking.
86  */
87 
88 ATF_TC(iaaddr_negative);
89 ATF_TC_HEAD(iaaddr_negative, tc)
90 {
91     atf_tc_set_md_var(tc, "descr", "This test case checks that IAADDR "
92                       "option code can handle various negative scenarios.");
93 }
94 ATF_TC_BODY(iaaddr_negative, tc)
95 {
96     struct iasubopt *iaaddr;
97     struct iasubopt *iaaddr_copy;
98 
99     /* set up dhcp globals */
100     dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB,
101 			NULL, NULL);
102 
103     /* tests */
104     /* bogus allocate arguments */
105     if (iasubopt_allocate(NULL, MDL) != DHCP_R_INVALIDARG) {
106         atf_tc_fail("ERROR: iasubopt_allocate() %s:%d", MDL);
107     }
108     iaaddr = (struct iasubopt *)1;
109     if (iasubopt_allocate(&iaaddr, MDL) != DHCP_R_INVALIDARG) {
110         atf_tc_fail("ERROR: iasubopt_allocate() %s:%d", MDL);
111     }
112 
113     /* bogus reference arguments */
114     iaaddr = NULL;
115     if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) {
116         atf_tc_fail("ERROR: iasubopt_allocate() %s:%d", MDL);
117     }
118     if (iasubopt_reference(NULL, iaaddr, MDL) != DHCP_R_INVALIDARG) {
119         atf_tc_fail("ERROR: iasubopt_reference() %s:%d", MDL);
120     }
121     iaaddr_copy = (struct iasubopt *)1;
122     if (iasubopt_reference(&iaaddr_copy, iaaddr,
123                            MDL) != DHCP_R_INVALIDARG) {
124         atf_tc_fail("ERROR: iasubopt_reference() %s:%d", MDL);
125     }
126     iaaddr_copy = NULL;
127     if (iasubopt_reference(&iaaddr_copy, NULL, MDL) != DHCP_R_INVALIDARG) {
128         atf_tc_fail("ERROR: iasubopt_reference() %s:%d", MDL);
129     }
130     if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
131         atf_tc_fail("ERROR: iasubopt_reference() %s:%d", MDL);
132     }
133 
134     /* bogus dereference arguments */
135     if (iasubopt_dereference(NULL, MDL) != DHCP_R_INVALIDARG) {
136         atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
137     }
138     iaaddr = NULL;
139     if (iasubopt_dereference(&iaaddr, MDL) != DHCP_R_INVALIDARG) {
140         atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
141     }
142 }
143 
144 /*
145  * Basic ia_na manipulation.
146  */
147 
148 ATF_TC(ia_na_basic);
149 ATF_TC_HEAD(ia_na_basic, tc)
150 {
151     atf_tc_set_md_var(tc, "descr", "This test case checks that IA_NA code can "
152                       "handle various basic scenarios.");
153 }
154 ATF_TC_BODY(ia_na_basic, tc)
155 {
156     uint32_t iaid;
157     struct ia_xx *ia_na;
158     struct ia_xx *ia_na_copy;
159     struct iasubopt *iaaddr;
160 
161     /* set up dhcp globals */
162     dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB,
163 			NULL, NULL);
164 
165     /* and other common arguments */
166     iaid = 666;
167     ia_na = NULL;
168     ia_na_copy = NULL;
169     iaaddr = NULL;
170 
171     /* tests */
172     if (ia_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) {
173         atf_tc_fail("ERROR: ia_allocate() %s:%d", MDL);
174     }
175     if (memcmp(ia_na->iaid_duid.data, &iaid, sizeof(iaid)) != 0) {
176         atf_tc_fail("ERROR: bad IAID_DUID %s:%d", MDL);
177     }
178     if (memcmp(ia_na->iaid_duid.data+sizeof(iaid), "TestDUID", 8) != 0) {
179         atf_tc_fail("ERROR: bad IAID_DUID %s:%d", MDL);
180     }
181     if (ia_na->num_iasubopt != 0) {
182         atf_tc_fail("ERROR: bad num_iasubopt %s:%d", MDL);
183     }
184     if (ia_reference(&ia_na_copy, ia_na, MDL) != ISC_R_SUCCESS) {
185         atf_tc_fail("ERROR: ia_reference() %s:%d", MDL);
186     }
187     if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) {
188         atf_tc_fail("ERROR: iasubopt_allocate() %s:%d", MDL);
189     }
190     if (ia_add_iasubopt(ia_na, iaaddr, MDL) != ISC_R_SUCCESS) {
191         atf_tc_fail("ERROR: ia_add_iasubopt() %s:%d", MDL);
192     }
193     ia_remove_iasubopt(ia_na, iaaddr, MDL);
194     if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
195         atf_tc_fail("ERROR: iasubopt_reference() %s:%d", MDL);
196     }
197     if (ia_dereference(&ia_na, MDL) != ISC_R_SUCCESS) {
198         atf_tc_fail("ERROR: ia_dereference() %s:%d", MDL);
199     }
200     if (ia_dereference(&ia_na_copy, MDL) != ISC_R_SUCCESS) {
201         atf_tc_fail("ERROR: ia_dereference() %s:%d", MDL);
202     }
203 }
204 
205 /*
206  * Lots of iaaddr in our ia_na.
207  * Create many iaaddrs and attach them to an ia_na
208  * then clean up by removing them one at a time and
209  * all at once by dereferencing the ia_na.
210  */
211 
212 ATF_TC(ia_na_manyaddrs);
213 ATF_TC_HEAD(ia_na_manyaddrs, tc)
214 {
215     atf_tc_set_md_var(tc, "descr", "This test case checks that IA_NA can "
216                       "handle lots of addresses.");
217 }
218 ATF_TC_BODY(ia_na_manyaddrs, tc)
219 {
220     uint32_t iaid;
221     struct ia_xx *ia_na;
222     struct iasubopt *iaaddr;
223     int i;
224 
225     /* set up dhcp globals */
226     dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB,
227 			NULL, NULL);
228 
229     /* tests */
230     /* lots of iaaddr that we delete */
231     iaid = 666;
232     ia_na = NULL;
233     if (ia_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) {
234         atf_tc_fail("ERROR: ia_allocate() %s:%d", MDL);
235     }
236     for (i=0; i<100; i++) {
237         iaaddr = NULL;
238         if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) {
239             atf_tc_fail("ERROR: iasubopt_allocate() %s:%d", MDL);
240         }
241         if (ia_add_iasubopt(ia_na, iaaddr, MDL) != ISC_R_SUCCESS) {
242             atf_tc_fail("ERROR: ia_add_iasubopt() %s:%d", MDL);
243         }
244         if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
245             atf_tc_fail("ERROR: iasubopt_reference() %s:%d", MDL);
246         }
247     }
248 
249 #if 0
250     for (i=0; i<100; i++) {
251         iaaddr = ia_na->iasubopt[random() % ia_na->num_iasubopt];
252         ia_remove_iasubopt(ia_na, iaaddr, MDL);
253         /* TODO: valgrind reports problem here: Invalid read of size 8
254          * Address 0x51e6258 is 56 bytes inside a block of size 88 free'd */
255     }
256 #endif
257     if (ia_dereference(&ia_na, MDL) != ISC_R_SUCCESS) {
258         atf_tc_fail("ERROR: ia_dereference() %s:%d", MDL);
259     }
260 
261     /* lots of iaaddr, let dereference cleanup */
262     iaid = 666;
263     ia_na = NULL;
264     if (ia_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) {
265         atf_tc_fail("ERROR: ia_allocate() %s:%d", MDL);
266     }
267     for (i=0; i<100; i++) {
268         iaaddr = NULL;
269         if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) {
270             atf_tc_fail("ERROR: iasubopt_allocate() %s:%d", MDL);
271         }
272         if (ia_add_iasubopt(ia_na, iaaddr, MDL) != ISC_R_SUCCESS) {
273             atf_tc_fail("ERROR: ia_add_iasubopt() %s:%d", MDL);
274         }
275         if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
276             atf_tc_fail("ERROR: iasubopt_reference() %s:%d", MDL);
277         }
278     }
279     if (ia_dereference(&ia_na, MDL) != ISC_R_SUCCESS) {
280         atf_tc_fail("ERROR: ia_dereference() %s:%d", MDL);
281     }
282 }
283 
284 /*
285  * Basic ia_na sanity checks.
286  * Verify that the ia_na code does some sanity checking.
287  */
288 
289 ATF_TC(ia_na_negative);
290 ATF_TC_HEAD(ia_na_negative, tc)
291 {
292     atf_tc_set_md_var(tc, "descr", "This test case checks that IA_NA option "
293                       "code can handle various negative scenarios.");
294 }
295 ATF_TC_BODY(ia_na_negative, tc)
296 {
297     uint32_t iaid;
298     struct ia_xx *ia_na;
299     struct ia_xx *ia_na_copy;
300 
301     /* set up dhcp globals */
302     dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB,
303 			NULL, NULL);
304 
305     /* tests */
306     /* bogus allocate arguments */
307     if (ia_allocate(NULL, 123, "", 0, MDL) != DHCP_R_INVALIDARG) {
308         atf_tc_fail("ERROR: ia_allocate() %s:%d", MDL);
309     }
310     ia_na = (struct ia_xx *)1;
311     if (ia_allocate(&ia_na, 456, "", 0, MDL) != DHCP_R_INVALIDARG) {
312         atf_tc_fail("ERROR: ia_allocate() %s:%d", MDL);
313     }
314 
315     /* bogus reference arguments */
316     iaid = 666;
317     ia_na = NULL;
318     if (ia_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) {
319         atf_tc_fail("ERROR: ia_allocate() %s:%d", MDL);
320     }
321     if (ia_reference(NULL, ia_na, MDL) != DHCP_R_INVALIDARG) {
322         atf_tc_fail("ERROR: ia_reference() %s:%d", MDL);
323     }
324     ia_na_copy = (struct ia_xx *)1;
325     if (ia_reference(&ia_na_copy, ia_na, MDL) != DHCP_R_INVALIDARG) {
326         atf_tc_fail("ERROR: ia_reference() %s:%d", MDL);
327     }
328     ia_na_copy = NULL;
329     if (ia_reference(&ia_na_copy, NULL, MDL) != DHCP_R_INVALIDARG) {
330         atf_tc_fail("ERROR: ia_reference() %s:%d", MDL);
331     }
332     if (ia_dereference(&ia_na, MDL) != ISC_R_SUCCESS) {
333         atf_tc_fail("ERROR: ia_dereference() %s:%d", MDL);
334     }
335 
336     /* bogus dereference arguments */
337     if (ia_dereference(NULL, MDL) != DHCP_R_INVALIDARG) {
338         atf_tc_fail("ERROR: ia_dereference() %s:%d", MDL);
339     }
340 
341     /* bogus remove */
342     iaid = 666;
343     ia_na = NULL;
344     if (ia_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) {
345         atf_tc_fail("ERROR: ia_allocate() %s:%d", MDL);
346     }
347     ia_remove_iasubopt(ia_na, NULL, MDL);
348     if (ia_dereference(&ia_na, MDL) != ISC_R_SUCCESS) {
349         atf_tc_fail("ERROR: ia_dereference() %s:%d", MDL);
350     }
351 }
352 
353 /*
354  * Basic ipv6_pool manipulation.
355  * Verify that basic pool operations work properly.
356  * The operations include creating a pool and creating,
357  * renewing, expiring, releasing and declining addresses.
358  */
359 
360 ATF_TC(ipv6_pool_basic);
361 ATF_TC_HEAD(ipv6_pool_basic, tc)
362 {
363     atf_tc_set_md_var(tc, "descr", "This test case checks that IPv6 pool "
364                       "manipulation is possible.");
365 }
366 ATF_TC_BODY(ipv6_pool_basic, tc)
367 {
368     struct iasubopt *iaaddr;
369     struct in6_addr addr;
370     struct ipv6_pool *pool;
371     struct ipv6_pool *pool_copy;
372     char addr_buf[INET6_ADDRSTRLEN];
373     char *uid;
374     struct data_string ds;
375     struct iasubopt *expired_iaaddr;
376     unsigned int attempts;
377 
378     /* set up dhcp globals */
379     dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB,
380 			NULL, NULL);
381 
382     /* and other common arguments */
383     inet_pton(AF_INET6, "1:2:3:4::", &addr);
384 
385     uid = "client0";
386     memset(&ds, 0, sizeof(ds));
387     ds.len = strlen(uid);
388     if (!buffer_allocate(&ds.buffer, ds.len, MDL)) {
389         atf_tc_fail("Out of memory");
390     }
391     ds.data = ds.buffer->data;
392     memcpy((char *)ds.data, uid, ds.len);
393 
394     /* tests */
395     /* allocate, reference */
396     pool = NULL;
397     if (ipv6_pool_allocate(&pool, D6O_IA_NA, &addr,
398                            64, 128, MDL) != ISC_R_SUCCESS) {
399         atf_tc_fail("ERROR: ipv6_pool_allocate() %s:%d", MDL);
400     }
401     if (pool->num_active != 0) {
402         atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
403     }
404     if (pool->bits != 64) {
405         atf_tc_fail("ERROR: bad bits %s:%d", MDL);
406     }
407     inet_ntop(AF_INET6, &pool->start_addr, addr_buf, sizeof(addr_buf));
408     if (strcmp(inet_ntop(AF_INET6, &pool->start_addr, addr_buf,
409                          sizeof(addr_buf)), "1:2:3:4::") != 0) {
410         atf_tc_fail("ERROR: bad start_addr %s:%d", MDL);
411     }
412     pool_copy = NULL;
413     if (ipv6_pool_reference(&pool_copy, pool, MDL) != ISC_R_SUCCESS) {
414         atf_tc_fail("ERROR: ipv6_pool_reference() %s:%d", MDL);
415     }
416 
417     /* create_lease6, renew_lease6, expire_lease6 */
418     iaaddr = NULL;
419     if (create_lease6(pool, &iaaddr,
420                       &attempts, &ds, 1) != ISC_R_SUCCESS) {
421         atf_tc_fail("ERROR: create_lease6() %s:%d", MDL);
422     }
423     if (pool->num_inactive != 1) {
424         atf_tc_fail("ERROR: bad num_inactive %s:%d", MDL);
425     }
426     if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
427         atf_tc_fail("ERROR: renew_lease6() %s:%d", MDL);
428     }
429     if (pool->num_active != 1) {
430         atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
431     }
432     expired_iaaddr = NULL;
433     if (expire_lease6(&expired_iaaddr, pool, 0) != ISC_R_SUCCESS) {
434         atf_tc_fail("ERROR: expire_lease6() %s:%d", MDL);
435     }
436     if (expired_iaaddr != NULL) {
437         atf_tc_fail("ERROR: should not have expired a lease %s:%d", MDL);
438     }
439     if (pool->num_active != 1) {
440         atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
441     }
442     if (expire_lease6(&expired_iaaddr, pool, 1000) != ISC_R_SUCCESS) {
443         atf_tc_fail("ERROR: expire_lease6() %s:%d", MDL);
444     }
445     if (expired_iaaddr == NULL) {
446         atf_tc_fail("ERROR: should have expired a lease %s:%d", MDL);
447     }
448     if (iasubopt_dereference(&expired_iaaddr, MDL) != ISC_R_SUCCESS) {
449         atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
450     }
451     if (pool->num_active != 0) {
452         atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
453     }
454     if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
455         atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
456     }
457 
458     /* release_lease6, decline_lease6 */
459     if (create_lease6(pool, &iaaddr, &attempts,
460               &ds, 1) != ISC_R_SUCCESS) {
461         atf_tc_fail("ERROR: create_lease6() %s:%d", MDL);
462     }
463     if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
464         atf_tc_fail("ERROR: renew_lease6() %s:%d", MDL);
465     }
466     if (pool->num_active != 1) {
467         atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
468     }
469     if (release_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
470         atf_tc_fail("ERROR: decline_lease6() %s:%d", MDL);
471     }
472     if (pool->num_active != 0) {
473         atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
474     }
475     if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
476         atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
477     }
478     if (create_lease6(pool, &iaaddr, &attempts,
479               &ds, 1) != ISC_R_SUCCESS) {
480         atf_tc_fail("ERROR: create_lease6() %s:%d", MDL);
481     }
482     if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
483         atf_tc_fail("ERROR: renew_lease6() %s:%d", MDL);
484     }
485     if (pool->num_active != 1) {
486         atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
487     }
488     if (decline_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
489         atf_tc_fail("ERROR: decline_lease6() %s:%d", MDL);
490     }
491     if (pool->num_active != 1) {
492         atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
493     }
494     if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
495         atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
496     }
497 
498     /* dereference */
499     if (ipv6_pool_dereference(&pool, MDL) != ISC_R_SUCCESS) {
500         atf_tc_fail("ERROR: ipv6_pool_reference() %s:%d", MDL);
501     }
502     if (ipv6_pool_dereference(&pool_copy, MDL) != ISC_R_SUCCESS) {
503         atf_tc_fail("ERROR: ipv6_pool_reference() %s:%d", MDL);
504     }
505 }
506 
507 /*
508  * Basic ipv6_pool sanity checks.
509  * Verify that the ipv6_pool code does some sanity checking.
510  */
511 
512 ATF_TC(ipv6_pool_negative);
513 ATF_TC_HEAD(ipv6_pool_negative, tc)
514 {
515     atf_tc_set_md_var(tc, "descr", "This test case checks that IPv6 pool "
516                       "can handle negative cases.");
517 }
518 ATF_TC_BODY(ipv6_pool_negative, tc)
519 {
520     struct in6_addr addr;
521     struct ipv6_pool *pool;
522     struct ipv6_pool *pool_copy;
523 
524     /* set up dhcp globals */
525     dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB,
526 			NULL, NULL);
527 
528     /* and other common arguments */
529     inet_pton(AF_INET6, "1:2:3:4::", &addr);
530 
531     /* tests */
532     if (ipv6_pool_allocate(NULL, D6O_IA_NA, &addr,
533                            64, 128, MDL) != DHCP_R_INVALIDARG) {
534         atf_tc_fail("ERROR: ipv6_pool_allocate() %s:%d", MDL);
535     }
536     pool = (struct ipv6_pool *)1;
537     if (ipv6_pool_allocate(&pool, D6O_IA_NA, &addr,
538                            64, 128, MDL) != DHCP_R_INVALIDARG) {
539         atf_tc_fail("ERROR: ipv6_pool_allocate() %s:%d", MDL);
540     }
541     if (ipv6_pool_reference(NULL, pool, MDL) != DHCP_R_INVALIDARG) {
542         atf_tc_fail("ERROR: ipv6_pool_reference() %s:%d", MDL);
543     }
544     pool_copy = (struct ipv6_pool *)1;
545     if (ipv6_pool_reference(&pool_copy, pool, MDL) != DHCP_R_INVALIDARG) {
546         atf_tc_fail("ERROR: ipv6_pool_reference() %s:%d", MDL);
547     }
548     pool_copy = NULL;
549     if (ipv6_pool_reference(&pool_copy, NULL, MDL) != DHCP_R_INVALIDARG) {
550         atf_tc_fail("ERROR: ipv6_pool_reference() %s:%d", MDL);
551     }
552     if (ipv6_pool_dereference(NULL, MDL) != DHCP_R_INVALIDARG) {
553         atf_tc_fail("ERROR: ipv6_pool_dereference() %s:%d", MDL);
554     }
555     if (ipv6_pool_dereference(&pool_copy, MDL) != DHCP_R_INVALIDARG) {
556         atf_tc_fail("ERROR: ipv6_pool_dereference() %s:%d", MDL);
557     }
558 }
559 
560 
561 /*
562  * Order of expiration.
563  * Add several addresses to a pool and check that
564  * they expire in the proper order.
565  */
566 
567 ATF_TC(expire_order);
568 ATF_TC_HEAD(expire_order, tc)
569 {
570     atf_tc_set_md_var(tc, "descr", "This test case checks that order "
571                       "of lease expiration is handled properly.");
572 }
573 ATF_TC_BODY(expire_order, tc)
574 {
575     struct iasubopt *iaaddr;
576     struct ipv6_pool *pool;
577     struct in6_addr addr;
578         int i;
579     char *uid;
580     struct data_string ds;
581     struct iasubopt *expired_iaaddr;
582     unsigned int attempts;
583 
584     /* set up dhcp globals */
585     dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB,
586 			NULL, NULL);
587 
588     /* and other common arguments */
589     inet_pton(AF_INET6, "1:2:3:4::", &addr);
590 
591     uid = "client0";
592     memset(&ds, 0, sizeof(ds));
593     ds.len = strlen(uid);
594     if (!buffer_allocate(&ds.buffer, ds.len, MDL)) {
595         atf_tc_fail("Out of memory");
596     }
597     ds.data = ds.buffer->data;
598     memcpy((char *)ds.data, uid, ds.len);
599 
600     iaaddr = NULL;
601     expired_iaaddr = NULL;
602 
603     /* tests */
604     pool = NULL;
605     if (ipv6_pool_allocate(&pool, D6O_IA_NA, &addr,
606                            64, 128, MDL) != ISC_R_SUCCESS) {
607         atf_tc_fail("ERROR: ipv6_pool_allocate() %s:%d", MDL);
608     }
609 
610     for (i=10; i<100; i+=10) {
611         if (create_lease6(pool, &iaaddr, &attempts,
612                   &ds, i) != ISC_R_SUCCESS) {
613             atf_tc_fail("ERROR: create_lease6() %s:%d", MDL);
614                 }
615         if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
616             atf_tc_fail("ERROR: renew_lease6() %s:%d", MDL);
617                 }
618         if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
619             atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
620                 }
621         if (pool->num_active != (i / 10)) {
622             atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
623                 }
624     }
625     if (pool->num_active != 9) {
626         atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
627     }
628 
629     for (i=10; i<100; i+=10) {
630         if (expire_lease6(&expired_iaaddr,
631                   pool, 1000) != ISC_R_SUCCESS) {
632             atf_tc_fail("ERROR: expire_lease6() %s:%d", MDL);
633                 }
634         if (expired_iaaddr == NULL) {
635             atf_tc_fail("ERROR: should have expired a lease %s:%d",
636                    MDL);
637                 }
638         if (pool->num_active != (9 - (i / 10))) {
639             atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
640                 }
641         if (expired_iaaddr->hard_lifetime_end_time != i) {
642             atf_tc_fail("ERROR: bad hard_lifetime_end_time %s:%d",
643                    MDL);
644                 }
645         if (iasubopt_dereference(&expired_iaaddr, MDL) !=
646                 ISC_R_SUCCESS) {
647             atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
648                 }
649     }
650     if (pool->num_active != 0) {
651         atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
652     }
653     expired_iaaddr = NULL;
654     if (expire_lease6(&expired_iaaddr, pool, 1000) != ISC_R_SUCCESS) {
655         atf_tc_fail("ERROR: expire_lease6() %s:%d", MDL);
656     }
657     if (ipv6_pool_dereference(&pool, MDL) != ISC_R_SUCCESS) {
658         atf_tc_fail("ERROR: ipv6_pool_dereference() %s:%d", MDL);
659     }
660 }
661 
662 /*
663  * Reduce the expiration period of a lease.
664  * This test reduces the expiration period of
665  * a lease to verify we process reductions
666  * properly.
667  */
668 ATF_TC(expire_order_reduce);
669 ATF_TC_HEAD(expire_order_reduce, tc)
670 {
671     atf_tc_set_md_var(tc, "descr", "This test case checks that reducing "
672                       "the expiration time of a lease works properly.");
673 }
674 ATF_TC_BODY(expire_order_reduce, tc)
675 {
676     struct iasubopt *iaaddr1, *iaaddr2;
677     struct ipv6_pool *pool;
678     struct in6_addr addr;
679     char *uid;
680     struct data_string ds;
681     struct iasubopt *expired_iaaddr;
682     unsigned int attempts;
683 
684     /* set up dhcp globals */
685     dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB,
686 			NULL, NULL);
687 
688     /* and other common arguments */
689     inet_pton(AF_INET6, "1:2:3:4::", &addr);
690 
691     uid = "client0";
692     memset(&ds, 0, sizeof(ds));
693     ds.len = strlen(uid);
694     if (!buffer_allocate(&ds.buffer, ds.len, MDL)) {
695         atf_tc_fail("Out of memory");
696     }
697     ds.data = ds.buffer->data;
698     memcpy((char *)ds.data, uid, ds.len);
699 
700     pool = NULL;
701     iaaddr1 = NULL;
702     iaaddr2 = NULL;
703     expired_iaaddr = NULL;
704 
705     /*
706      * Add two leases iaaddr1 with expire time of 200
707      * and iaaddr2 with expire time of 300.  Then update
708      * iaaddr2 to expire in 100 instead.  This should cause
709      * iaaddr2 to move with the hash list.
710      */
711     /* create pool and add iaaddr1 and iaaddr2 */
712     if (ipv6_pool_allocate(&pool, D6O_IA_NA, &addr,
713                            64, 128, MDL) != ISC_R_SUCCESS) {
714         atf_tc_fail("ERROR: ipv6_pool_allocate() %s:%d", MDL);
715     }
716     if (create_lease6(pool, &iaaddr1, &attempts, &ds, 200) != ISC_R_SUCCESS) {
717         atf_tc_fail("ERROR: create_lease6() %s:%d", MDL);
718     }
719     if (renew_lease6(pool, iaaddr1) != ISC_R_SUCCESS) {
720             atf_tc_fail("ERROR: renew_lease6() %s:%d", MDL);
721     }
722     if (create_lease6(pool, &iaaddr2, &attempts, &ds, 300) != ISC_R_SUCCESS) {
723         atf_tc_fail("ERROR: create_lease6() %s:%d", MDL);
724     }
725     if (renew_lease6(pool, iaaddr2) != ISC_R_SUCCESS) {
726             atf_tc_fail("ERROR: renew_lease6() %s:%d", MDL);
727     }
728 
729     /* verify pool */
730     if (pool->num_active != 2) {
731         atf_tc_fail("ERROR: bad num_active %s:%d", MDL);
732     }
733 
734     /* reduce lease for iaaddr2 */
735     iaaddr2->soft_lifetime_end_time = 100;
736     if (renew_lease6(pool, iaaddr2) != ISC_R_SUCCESS) {
737             atf_tc_fail("ERROR: renew_lease6() %s:%d", MDL);
738     }
739 
740     /* expire a lease, it should be iaaddr2 with an expire time of 100 */
741     if (expire_lease6(&expired_iaaddr, pool, 1000) != ISC_R_SUCCESS) {
742         atf_tc_fail("ERROR: expire_lease6() %s:%d", MDL);
743     }
744     if (expired_iaaddr == NULL) {
745         atf_tc_fail("ERROR: should have expired a lease %s:%d", MDL);
746     }
747     if (expired_iaaddr != iaaddr2) {
748         atf_tc_fail("Error: incorrect lease expired %s:%d", MDL);
749     }
750     if (expired_iaaddr->hard_lifetime_end_time != 100) {
751         atf_tc_fail("ERROR: bad hard_lifetime_end_time %s:%d", MDL);
752     }
753     if (iasubopt_dereference(&expired_iaaddr, MDL) != ISC_R_SUCCESS) {
754         atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
755     }
756 
757     /* expire a lease, it should be iaaddr1 with an expire time of 200 */
758     if (expire_lease6(&expired_iaaddr, pool, 1000) != ISC_R_SUCCESS) {
759         atf_tc_fail("ERROR: expire_lease6() %s:%d", MDL);
760     }
761     if (expired_iaaddr == NULL) {
762         atf_tc_fail("ERROR: should have expired a lease %s:%d", MDL);
763     }
764     if (expired_iaaddr != iaaddr1) {
765         atf_tc_fail("Error: incorrect lease expired %s:%d", MDL);
766     }
767     if (expired_iaaddr->hard_lifetime_end_time != 200) {
768         atf_tc_fail("ERROR: bad hard_lifetime_end_time %s:%d", MDL);
769     }
770     if (iasubopt_dereference(&expired_iaaddr, MDL) != ISC_R_SUCCESS) {
771         atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
772     }
773 
774     /* cleanup */
775     if (iasubopt_dereference(&iaaddr1, MDL) != ISC_R_SUCCESS) {
776         atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
777     }
778     if (iasubopt_dereference(&iaaddr2, MDL) != ISC_R_SUCCESS) {
779         atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
780     }
781     if (ipv6_pool_dereference(&pool, MDL) != ISC_R_SUCCESS) {
782         atf_tc_fail("ERROR: ipv6_pool_dereference() %s:%d", MDL);
783     }
784 }
785 
786 /*
787  * Small pool.
788  * check that a small pool behaves properly.
789  */
790 
791 ATF_TC(small_pool);
792 ATF_TC_HEAD(small_pool, tc)
793 {
794     atf_tc_set_md_var(tc, "descr", "This test case checks that small pool "
795                       "is handled properly.");
796 }
797 ATF_TC_BODY(small_pool, tc)
798 {
799     struct in6_addr addr;
800     struct ipv6_pool *pool;
801     struct iasubopt *iaaddr;
802     char *uid;
803     struct data_string ds;
804     unsigned int attempts;
805 
806     /* set up dhcp globals */
807     dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB,
808 			NULL, NULL);
809 
810     /* and other common arguments */
811     inet_pton(AF_INET6, "1:2:3:4::", &addr);
812     addr.s6_addr[14] = 0x81;
813 
814     uid = "client0";
815     memset(&ds, 0, sizeof(ds));
816     ds.len = strlen(uid);
817     if (!buffer_allocate(&ds.buffer, ds.len, MDL)) {
818         atf_tc_fail("Out of memory");
819     }
820     ds.data = ds.buffer->data;
821     memcpy((char *)ds.data, uid, ds.len);
822 
823     pool = NULL;
824     iaaddr = NULL;
825 
826     /* tests */
827     if (ipv6_pool_allocate(&pool, D6O_IA_NA, &addr,
828                            127, 128, MDL) != ISC_R_SUCCESS) {
829         atf_tc_fail("ERROR: ipv6_pool_allocate() %s:%d", MDL);
830     }
831 
832     if (create_lease6(pool, &iaaddr, &attempts,
833               &ds, 42) != ISC_R_SUCCESS) {
834         atf_tc_fail("ERROR: create_lease6() %s:%d", MDL);
835     }
836     if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
837         atf_tc_fail("ERROR: renew_lease6() %s:%d", MDL);
838     }
839     if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
840         atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
841     }
842     if (create_lease6(pool, &iaaddr, &attempts,
843               &ds, 11) != ISC_R_SUCCESS) {
844         atf_tc_fail("ERROR: create_lease6() %s:%d", MDL);
845     }
846     if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
847         atf_tc_fail("ERROR: renew_lease6() %s:%d", MDL);
848     }
849     if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
850         atf_tc_fail("ERROR: iasubopt_dereference() %s:%d", MDL);
851     }
852     if (create_lease6(pool, &iaaddr, &attempts,
853               &ds, 11) != ISC_R_NORESOURCES) {
854         atf_tc_fail("ERROR: create_lease6() %s:%d", MDL);
855     }
856     if (ipv6_pool_dereference(&pool, MDL) != ISC_R_SUCCESS) {
857         atf_tc_fail("ERROR: ipv6_pool_dereference() %s:%d", MDL);
858     }
859 }
860 
861 /*
862  * Address to pool mapping.
863  * Verify that we find the proper pool for an address
864  * or don't find a pool if we don't have one for the given
865  * address.
866  */
867 ATF_TC(many_pools);
868 ATF_TC_HEAD(many_pools, tc)
869 {
870     atf_tc_set_md_var(tc, "descr", "This test case checks that functions "
871                       "across all pools are working correctly.");
872 }
873 ATF_TC_BODY(many_pools, tc)
874 {
875     struct in6_addr addr;
876     struct ipv6_pool *pool;
877 
878     /* set up dhcp globals */
879     dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB,
880 			NULL, NULL);
881 
882     /* and other common arguments */
883     inet_pton(AF_INET6, "1:2:3:4::", &addr);
884 
885     /* tests */
886 
887     pool = NULL;
888     if (ipv6_pool_allocate(&pool, D6O_IA_NA, &addr,
889                            64, 128, MDL) != ISC_R_SUCCESS) {
890         atf_tc_fail("ERROR: ipv6_pool_allocate() %s:%d", MDL);
891     }
892     if (add_ipv6_pool(pool) != ISC_R_SUCCESS) {
893         atf_tc_fail("ERROR: add_ipv6_pool() %s:%d", MDL);
894     }
895     if (ipv6_pool_dereference(&pool, MDL) != ISC_R_SUCCESS) {
896         atf_tc_fail("ERROR: ipv6_pool_dereference() %s:%d", MDL);
897     }
898     pool = NULL;
899     if (find_ipv6_pool(&pool, D6O_IA_NA, &addr) != ISC_R_SUCCESS) {
900         atf_tc_fail("ERROR: find_ipv6_pool() %s:%d", MDL);
901     }
902     if (ipv6_pool_dereference(&pool, MDL) != ISC_R_SUCCESS) {
903         atf_tc_fail("ERROR: ipv6_pool_dereference() %s:%d", MDL);
904     }
905     inet_pton(AF_INET6, "1:2:3:4:ffff:ffff:ffff:ffff", &addr);
906     pool = NULL;
907     if (find_ipv6_pool(&pool, D6O_IA_NA, &addr) != ISC_R_SUCCESS) {
908         atf_tc_fail("ERROR: find_ipv6_pool() %s:%d", MDL);
909     }
910     if (ipv6_pool_dereference(&pool, MDL) != ISC_R_SUCCESS) {
911         atf_tc_fail("ERROR: ipv6_pool_dereference() %s:%d", MDL);
912     }
913     inet_pton(AF_INET6, "1:2:3:5::", &addr);
914     pool = NULL;
915     if (find_ipv6_pool(&pool, D6O_IA_NA, &addr) != ISC_R_NOTFOUND) {
916         atf_tc_fail("ERROR: find_ipv6_pool() %s:%d", MDL);
917     }
918     inet_pton(AF_INET6, "1:2:3:3:ffff:ffff:ffff:ffff", &addr);
919     pool = NULL;
920     if (find_ipv6_pool(&pool, D6O_IA_NA, &addr) != ISC_R_NOTFOUND) {
921         atf_tc_fail("ERROR: find_ipv6_pool() %s:%d", MDL);
922     }
923 
924 /*  iaid = 666;
925     ia_na = NULL;
926     if (ia_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) {
927         atf_tc_fail("ERROR: ia_allocate() %s:%d", MDL);
928     }*/
929 
930     {
931         struct in6_addr r;
932         struct data_string ds;
933         u_char data[16];
934         char buf[64];
935         int i, j;
936 
937         memset(&ds, 0, sizeof(ds));
938         memset(data, 0xaa, sizeof(data));
939         ds.len = 16;
940         ds.data = data;
941 
942         inet_pton(AF_INET6, "3ffe:501:ffff:100::", &addr);
943         for (i = 32; i < 42; i++)
944             for (j = i + 1; j < 49; j++) {
945                 memset(&r, 0, sizeof(r));
946                 memset(buf, 0, 64);
947                 build_prefix6(&r, &addr, i, j, &ds);
948                 inet_ntop(AF_INET6, &r, buf, 64);
949                 printf("%d,%d-> %s/%d\n", i, j, buf, j);
950             }
951     }
952 }
953 
954 ATF_TP_ADD_TCS(tp)
955 {
956     ATF_TP_ADD_TC(tp, iaaddr_basic);
957     ATF_TP_ADD_TC(tp, iaaddr_negative);
958     ATF_TP_ADD_TC(tp, ia_na_basic);
959     ATF_TP_ADD_TC(tp, ia_na_manyaddrs);
960     ATF_TP_ADD_TC(tp, ia_na_negative);
961     ATF_TP_ADD_TC(tp, ipv6_pool_basic);
962     ATF_TP_ADD_TC(tp, ipv6_pool_negative);
963     ATF_TP_ADD_TC(tp, expire_order);
964     ATF_TP_ADD_TC(tp, expire_order_reduce);
965     ATF_TP_ADD_TC(tp, small_pool);
966     ATF_TP_ADD_TC(tp, many_pools);
967 
968     return (atf_no_error());
969 }
970