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