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 /*!
18  * \todo assert()
19  * \todo simplify functions, as pool is now in iaaddr
20  */
21 
22 /*! \file server/mdb6.c
23  *
24  * \page ipv6structures IPv6 Structures Overview
25  *
26  * A brief description of the IPv6 structures as reverse engineered.
27  *
28  * There are four major data structures in the lease configuraion.
29  *
30  * - shared_network - The shared network is the outer enclosing scope for a
31  *                    network region that shares a broadcast domain.  It is
32  *                    composed of one or more subnets all of which are valid
33  *                    in the given region.  The share network may be
34  *                    explicitly defined or implicitly created if there is
35  *                    only a subnet statement.  This structrure is shared
36  *                    with v4.  Each shared network statment or naked subnet
37  *                    will map to one of these structures
38  *
39  * - subnet     - The subnet structure mostly specifies the address range
40  *                that could be valid in a given region.  This structute
41  *                doesn't include the addresses that the server can delegate
42  *                those are in the ipv6_pool.  This structure is also shared
43  *                with v4.  Each subnet statement will map to one of these
44  *                structures.
45  *
46  * - ipv6_pond  - The pond structure is a grouping of the address and prefix
47  *                information via the pointers to the ipv6_pool and the
48  *                allowability of this pool for given clinets via the permit
49  *                lists and the valid TIMEs.  This is equivilent to the v4
50  *                pool structure and would have been named ip6_pool except
51  *                that the name was already in use.  Generally each pool6
52  *                statement will map to one of these structures. In addition
53  *                there may be one or for each group of naked range6 and
54  *                prefix6 statements within a shared network that share
55  *                the same group of statements.
56  *
57  * - ipv6_pool - this contains information about a pool of addresses or prefixes
58  *               that the server is using.  This includes a hash table that
59  *               tracks the active items and a pair of heap tables one for
60  *               active items and one for non-active items.  The heap tables
61  *               are used to determine the next items to be modified due to
62  *               timing events (expire mostly).
63  *
64  * The linkages then look like this:
65  * \verbatim
66  *+--------------+   +-------------+
67  *|Shared Network|   | ipv6_pond   |
68  *|   group      |   |   group     |
69  *|              |   | permit info |
70  *|              |   |    next    ---->
71  *|    ponds    ---->|             |
72  *|              |<----  shared    |
73  *|   Subnets    |   |    pools    |
74  *+-----|--------+   +------|------+
75  *      |  ^                |    ^
76  *      |  |                v    |
77  *      |  |         +-----------|-+
78  *      |  |         | ipv6_pool | |
79  *      |  |         |    type   | |
80  *      |  |         |   ipv6_pond |
81  *      |  |         |             |
82  *      |  |         |    next    ---->
83  *      |  |         |             |
84  *      |  |         |   subnet    |
85  *      |  |         +-----|-------+
86  *      |  |               |
87  *      |  |               v
88  *      |  |         +-------------+
89  *      |  |         |   subnet    |
90  *      |  +----------   shared    |
91  *      +----------->|             |
92  *                   |   group     |
93  *                   +-------------+
94  *
95  * The shared network contains a list of all the subnets that are on a broadcast
96  * doamin.  These can be used to determine if an address makes sense in a given
97  * domain, but the subnets do not contain the addresses the server can delegate.
98  * Those are stored in the ponds and pools.
99  *
100  * In the simple case to find an acceptable address the server would first find
101  * the shared network the client is on based on either the interface used to
102  * receive the request or the relay agent's information.  From the shared
103  * network the server will walk through it's list of ponds.  For each pond it
104  * will evaluate the permit information against the (already done) classification.
105  * If it finds an acceptable pond it will then walk through the pools for that
106  * pond.  The server first checks the type of the pool (NA, TA and PD) agaisnt the
107  * request and if they match it attemps to find an address within that pool.  On
108  * success the address is used, on failure the server steps to the next pool and
109  * if necessary to the next pond.
110  *
111  * When the server is successful in finding an address it will execute any
112  * statements assocaited with the pond, then the subnet, then the shared
113  * network the group field is for in the above picture).
114  *
115  * In configurations that don't include either a shared network or a pool6
116  * statement (or both) the missing pieces are created.
117  *
118  *
119  * There are three major data structuress involved in the lease database:
120  *
121  * - ipv6_pool - see above
122  * - ia_xx   - this contains information about a single IA from a request
123  *             normally it will contain one pointer to a lease for the client
124  *             but it may contain more in some circumstances.  There are 3
125  *             hash tables to aid in accessing these one each for NA, TA and PD.
126  * - iasubopt - the v6 lease structure.  These are created dynamically when
127  *              a client asks for something and will eventually be destroyed
128  *              if the client doesn't re-ask for that item.  A lease has space
129  *              for backpointers to the IA and to the pool to which it belongs.
130  *              The pool backpointer is always filled, the IA pointer may not be.
131  *
132  * In normal use we then have something like this:
133  *
134  * \verbatim
135  * ia hash tables
136  *  ia_na_active                           +----------------+
137  *  ia_ta_active          +------------+   | pool           |
138  *  ia_pd_active          | iasubopt   |<--|  active hash   |
139  * +-----------------+    | aka lease  |<--|  active heap   |
140  * | ia_xx           |    |  pool ptr  |-->|                |
141  * |  iasubopt array |<---|  iaptr     |<--|  inactive heap |
142  * |   lease ptr     |--->|            |   |                |
143  * +-----------------+    +------------+   +----------------+
144  * \endverbatim
145  *
146  * For the pool either the inactive heap will have a pointer
147  * or both the active heap and the active hash will have pointers.
148  *
149  * I think there are several major items to notice.   The first is
150  * that as a lease moves around it will be added to and removed
151  * from the address hash table in the pool and between the active
152  * and inactive hash tables.  The hash table and the active heap
153  * are used when the lease is either active or abandoned.  The
154  * inactive heap is used for all other states.  In particular a
155  * lease that has expired or been released will be cleaned
156  * (DDNS removal etc) and then moved to the inactive heap.  After
157  * some time period (currently 1 hour) it will be freed.
158  *
159  * The second is that when a client requests specific addresses,
160  * either because it previously owned them or if the server supplied
161  * them as part of a solicit, the server will try to lookup the ia_xx
162  * associated with the client and find the addresses there.  If it
163  * does find appropriate leases it moves them from the old IA to
164  * a new IA and eventually replaces the old IA with the new IA
165  * in the IA hash tables.
166  *
167  */
168 #include "config.h"
169 
170 #include <sys/types.h>
171 #include <time.h>
172 #include <netinet/in.h>
173 
174 #include <stdarg.h>
175 #include "dhcpd.h"
176 #include "omapip/omapip.h"
177 #include "omapip/hash.h"
178 #include <isc/md5.h>
179 
180 HASH_FUNCTIONS(ia, unsigned char *, struct ia_xx, ia_hash_t,
181 	       ia_reference, ia_dereference, do_string_hash)
182 
183 ia_hash_t *ia_na_active;
184 ia_hash_t *ia_ta_active;
185 ia_hash_t *ia_pd_active;
186 
187 HASH_FUNCTIONS(iasubopt, struct in6_addr *, struct iasubopt, iasubopt_hash_t,
188 	       iasubopt_reference, iasubopt_dereference, do_string_hash)
189 
190 struct ipv6_pool **pools;
191 int num_pools;
192 
193 /*
194  * Create a new IAADDR/PREFIX structure.
195  *
196  * - iasubopt must be a pointer to a (struct iasubopt *) pointer previously
197  *   initialized to NULL
198  */
199 isc_result_t
iasubopt_allocate(struct iasubopt ** iasubopt,const char * file,int line)200 iasubopt_allocate(struct iasubopt **iasubopt, const char *file, int line) {
201 	struct iasubopt *tmp;
202 
203 	if (iasubopt == NULL) {
204 		log_error("%s(%d): NULL pointer reference", file, line);
205 		return DHCP_R_INVALIDARG;
206 	}
207 	if (*iasubopt != NULL) {
208 		log_error("%s(%d): non-NULL pointer", file, line);
209 		return DHCP_R_INVALIDARG;
210 	}
211 
212 	tmp = dmalloc(sizeof(*tmp), file, line);
213 	if (tmp == NULL) {
214 		return ISC_R_NOMEMORY;
215 	}
216 
217 	tmp->refcnt = 1;
218 	tmp->state = FTS_FREE;
219 	tmp->active_index = 0;
220 	tmp->inactive_index = 0;
221 	tmp->plen = 255;
222 
223 	*iasubopt = tmp;
224 	return ISC_R_SUCCESS;
225 }
226 
227 /*
228  * Reference an IAADDR/PREFIX structure.
229  *
230  * - iasubopt must be a pointer to a (struct iasubopt *) pointer previously
231  *   initialized to NULL
232  */
233 isc_result_t
iasubopt_reference(struct iasubopt ** iasubopt,struct iasubopt * src,const char * file,int line)234 iasubopt_reference(struct iasubopt **iasubopt, struct iasubopt *src,
235 		 const char *file, int line) {
236 	if (iasubopt == NULL) {
237 		log_error("%s(%d): NULL pointer reference", file, line);
238 		return DHCP_R_INVALIDARG;
239 	}
240 	if (*iasubopt != NULL) {
241 		log_error("%s(%d): non-NULL pointer", file, line);
242 		return DHCP_R_INVALIDARG;
243 	}
244 	if (src == NULL) {
245 		log_error("%s(%d): NULL pointer reference", file, line);
246 		return DHCP_R_INVALIDARG;
247 	}
248 	*iasubopt = src;
249 	src->refcnt++;
250 	return ISC_R_SUCCESS;
251 }
252 
253 
254 /*
255  * Dereference an IAADDR/PREFIX structure.
256  *
257  * If it is the last reference, then the memory for the
258  * structure is freed.
259  */
260 isc_result_t
iasubopt_dereference(struct iasubopt ** iasubopt,const char * file,int line)261 iasubopt_dereference(struct iasubopt **iasubopt, const char *file, int line) {
262 	struct iasubopt *tmp;
263 
264 	if ((iasubopt == NULL) || (*iasubopt == NULL)) {
265 		log_error("%s(%d): NULL pointer", file, line);
266 		return DHCP_R_INVALIDARG;
267 	}
268 
269 	tmp = *iasubopt;
270 	*iasubopt = NULL;
271 
272 	tmp->refcnt--;
273 	if (tmp->refcnt < 0) {
274 		log_error("%s(%d): negative refcnt", file, line);
275 		tmp->refcnt = 0;
276 	}
277 	if (tmp->refcnt == 0) {
278 		if (tmp->ia != NULL) {
279 			ia_dereference(&(tmp->ia), file, line);
280 		}
281 		if (tmp->ipv6_pool != NULL) {
282 			ipv6_pool_dereference(&(tmp->ipv6_pool), file, line);
283 		}
284 		if (tmp->scope != NULL) {
285 			binding_scope_dereference(&tmp->scope, file, line);
286 		}
287 
288 		if (tmp->on_star.on_expiry != NULL) {
289 			executable_statement_dereference
290 				(&tmp->on_star.on_expiry, MDL);
291 		}
292 		if (tmp->on_star.on_commit != NULL) {
293 			executable_statement_dereference
294 				(&tmp->on_star.on_commit, MDL);
295 		}
296 		if (tmp->on_star.on_release != NULL) {
297 			executable_statement_dereference
298 				(&tmp->on_star.on_release, MDL);
299 		}
300 
301 		dfree(tmp, file, line);
302 	}
303 
304 	return ISC_R_SUCCESS;
305 }
306 
307 /*
308  * Make the key that we use for IA.
309  */
310 isc_result_t
ia_make_key(struct data_string * key,u_int32_t iaid,const char * duid,unsigned int duid_len,const char * file,int line)311 ia_make_key(struct data_string *key, u_int32_t iaid,
312 	    const char *duid, unsigned int duid_len,
313 	    const char *file, int line) {
314 
315 	memset(key, 0, sizeof(*key));
316 	key->len = duid_len + sizeof(iaid);
317 	if (!buffer_allocate(&(key->buffer), key->len, file, line)) {
318 		return ISC_R_NOMEMORY;
319 	}
320 	key->data = key->buffer->data;
321 	memcpy((char *)key->data, &iaid, sizeof(iaid));
322 	memcpy((char *)key->data + sizeof(iaid), duid, duid_len);
323 
324 	return ISC_R_SUCCESS;
325 }
326 
327 /*
328  * Create a new IA structure.
329  *
330  * - ia must be a pointer to a (struct ia_xx *) pointer previously
331  *   initialized to NULL
332  * - iaid and duid are values from the client
333  *
334  * XXXsk: we don't concern ourself with the byte order of the IAID,
335  *        which might be a problem if we transfer this structure
336  *        between machines of different byte order
337  */
338 isc_result_t
ia_allocate(struct ia_xx ** ia,u_int32_t iaid,const char * duid,unsigned int duid_len,const char * file,int line)339 ia_allocate(struct ia_xx **ia, u_int32_t iaid,
340 	    const char *duid, unsigned int duid_len,
341 	    const char *file, int line) {
342 	struct ia_xx *tmp;
343 
344 	if (ia == NULL) {
345 		log_error("%s(%d): NULL pointer reference", file, line);
346 		return DHCP_R_INVALIDARG;
347 	}
348 	if (*ia != NULL) {
349 		log_error("%s(%d): non-NULL pointer", file, line);
350 		return DHCP_R_INVALIDARG;
351 	}
352 
353 	tmp = dmalloc(sizeof(*tmp), file, line);
354 	if (tmp == NULL) {
355 		return ISC_R_NOMEMORY;
356 	}
357 
358 	if (ia_make_key(&tmp->iaid_duid, iaid,
359 			duid, duid_len, file, line) != ISC_R_SUCCESS) {
360 		dfree(tmp, file, line);
361 		return ISC_R_NOMEMORY;
362 	}
363 
364 	tmp->refcnt = 1;
365 
366 	*ia = tmp;
367 	return ISC_R_SUCCESS;
368 }
369 
370 /*
371  * Reference an IA structure.
372  *
373  * - ia must be a pointer to a (struct ia_xx *) pointer previously
374  *   initialized to NULL
375  */
376 isc_result_t
ia_reference(struct ia_xx ** ia,struct ia_xx * src,const char * file,int line)377 ia_reference(struct ia_xx **ia, struct ia_xx *src,
378 	     const char *file, int line) {
379 	if (ia == NULL) {
380 		log_error("%s(%d): NULL pointer reference", file, line);
381 		return DHCP_R_INVALIDARG;
382 	}
383 	if (*ia != NULL) {
384 		log_error("%s(%d): non-NULL pointer", file, line);
385 		return DHCP_R_INVALIDARG;
386 	}
387 	if (src == NULL) {
388 		log_error("%s(%d): NULL pointer reference", file, line);
389 		return DHCP_R_INVALIDARG;
390 	}
391 	*ia = src;
392 	src->refcnt++;
393 	return ISC_R_SUCCESS;
394 }
395 
396 /*
397  * Dereference an IA structure.
398  *
399  * If it is the last reference, then the memory for the
400  * structure is freed.
401  */
402 isc_result_t
ia_dereference(struct ia_xx ** ia,const char * file,int line)403 ia_dereference(struct ia_xx **ia, const char *file, int line) {
404 	struct ia_xx *tmp;
405 	int i;
406 
407 	if ((ia == NULL) || (*ia == NULL)) {
408 		log_error("%s(%d): NULL pointer", file, line);
409 		return DHCP_R_INVALIDARG;
410 	}
411 
412 	tmp = *ia;
413 	*ia = NULL;
414 
415 	tmp->refcnt--;
416 	if (tmp->refcnt < 0) {
417 		log_error("%s(%d): negative refcnt", file, line);
418 		tmp->refcnt = 0;
419 	}
420 	if (tmp->refcnt == 0) {
421 		if (tmp->iasubopt != NULL) {
422 			for (i=0; i<tmp->num_iasubopt; i++) {
423 				iasubopt_dereference(&(tmp->iasubopt[i]),
424 						     file, line);
425 			}
426 			dfree(tmp->iasubopt, file, line);
427 		}
428 		data_string_forget(&(tmp->iaid_duid), file, line);
429 		dfree(tmp, file, line);
430 	}
431 	return ISC_R_SUCCESS;
432 }
433 
434 
435 /*
436  * Add an IAADDR/PREFIX entry to an IA structure.
437  */
438 isc_result_t
ia_add_iasubopt(struct ia_xx * ia,struct iasubopt * iasubopt,const char * file,int line)439 ia_add_iasubopt(struct ia_xx *ia, struct iasubopt *iasubopt,
440 		const char *file, int line) {
441 	int max;
442 	struct iasubopt **new;
443 
444 	/*
445 	 * Grow our array if we need to.
446 	 *
447 	 * Note: we pick 4 as the increment, as that seems a reasonable
448 	 *       guess as to how many addresses/prefixes we might expect
449 	 *       on an interface.
450 	 */
451 	if (ia->max_iasubopt <= ia->num_iasubopt) {
452 		max = ia->max_iasubopt + 4;
453 		new = dmalloc(max * sizeof(struct iasubopt *), file, line);
454 		if (new == NULL) {
455 			return ISC_R_NOMEMORY;
456 		}
457 		memcpy(new, ia->iasubopt,
458 		       ia->num_iasubopt * sizeof(struct iasubopt *));
459 		ia->iasubopt = new;
460 		ia->max_iasubopt = max;
461 	}
462 
463 	iasubopt_reference(&(ia->iasubopt[ia->num_iasubopt]), iasubopt,
464 			   file, line);
465 	ia->num_iasubopt++;
466 
467 	return ISC_R_SUCCESS;
468 }
469 
470 /*
471  * Remove an IAADDR/PREFIX entry to an IA structure.
472  *
473  * Note: if a suboption appears more than once, then only ONE will be removed.
474  */
475 void
ia_remove_iasubopt(struct ia_xx * ia,struct iasubopt * iasubopt,const char * file,int line)476 ia_remove_iasubopt(struct ia_xx *ia, struct iasubopt *iasubopt,
477 		   const char *file, int line) {
478 	int i, j;
479         if (ia == NULL || iasubopt == NULL)
480             return;
481 
482 	for (i=0; i<ia->num_iasubopt; i++) {
483 		if (ia->iasubopt[i] == iasubopt) {
484 			/* remove this sub option */
485 			iasubopt_dereference(&(ia->iasubopt[i]), file, line);
486 			/* move remaining suboption pointers down one */
487 			for (j=i+1; j < ia->num_iasubopt; j++) {
488 				ia->iasubopt[j-1] = ia->iasubopt[j];
489 			}
490 			/* decrease our total count */
491 			/* remove the back-reference in the suboption itself */
492 			ia_dereference(&iasubopt->ia, file, line);
493 			ia->num_iasubopt--;
494 			return;
495 		}
496 	}
497 	log_error("%s(%d): IAADDR/PREFIX not in IA", file, line);
498 }
499 
500 /*
501  * Remove all addresses/prefixes from an IA.
502  */
503 void
ia_remove_all_lease(struct ia_xx * ia,const char * file,int line)504 ia_remove_all_lease(struct ia_xx *ia, const char *file, int line) {
505 	int i;
506 
507 	for (i=0; i<ia->num_iasubopt; i++) {
508 		ia_dereference(&(ia->iasubopt[i]->ia), file, line);
509 		iasubopt_dereference(&(ia->iasubopt[i]), file, line);
510 	}
511 	ia->num_iasubopt = 0;
512 }
513 
514 /*
515  * Compare two IA.
516  */
517 isc_boolean_t
ia_equal(const struct ia_xx * a,const struct ia_xx * b)518 ia_equal(const struct ia_xx *a, const struct ia_xx *b)
519 {
520 	isc_boolean_t found;
521 	int i, j;
522 
523 	/*
524 	 * Handle cases where one or both of the inputs is NULL.
525 	 */
526 	if (a == NULL) {
527 		if (b == NULL) {
528 			return ISC_TRUE;
529 		} else {
530 			return ISC_FALSE;
531 		}
532 	}
533 
534 	/*
535 	 * Check the type is the same.
536 	 */
537 	if (a->ia_type != b->ia_type) {
538 		return ISC_FALSE;
539 	}
540 
541 	/*
542 	 * Check the DUID is the same.
543 	 */
544 	if (a->iaid_duid.len != b->iaid_duid.len) {
545 		return ISC_FALSE;
546 	}
547 	if (memcmp(a->iaid_duid.data,
548 		   b->iaid_duid.data, a->iaid_duid.len) != 0) {
549 		return ISC_FALSE;
550 	}
551 
552 	/*
553 	 * Make sure we have the same number of addresses/prefixes in each.
554 	 */
555 	if (a->num_iasubopt != b->num_iasubopt) {
556 		return ISC_FALSE;
557 	}
558 
559 	/*
560 	 * Check that each address/prefix is present in both.
561 	 */
562 	for (i=0; i<a->num_iasubopt; i++) {
563 		found = ISC_FALSE;
564 		for (j=0; j<a->num_iasubopt; j++) {
565 			if (a->iasubopt[i]->plen != b->iasubopt[i]->plen)
566 				continue;
567 			if (memcmp(&(a->iasubopt[i]->addr),
568 			           &(b->iasubopt[j]->addr),
569 				   sizeof(struct in6_addr)) == 0) {
570 				found = ISC_TRUE;
571 				break;
572 			}
573 		}
574 		if (!found) {
575 			return ISC_FALSE;
576 		}
577 	}
578 
579 	/*
580 	 * These are the same in every way we care about.
581 	 */
582 	return ISC_TRUE;
583 }
584 
585 /*
586  * Helper function for lease heaps.
587  * Makes the top of the heap the oldest lease.
588  */
589 static isc_boolean_t
lease_older(void * a,void * b)590 lease_older(void *a, void *b) {
591 	struct iasubopt *la = (struct iasubopt *)a;
592 	struct iasubopt *lb = (struct iasubopt *)b;
593 
594 	if (la->hard_lifetime_end_time == lb->hard_lifetime_end_time) {
595 		return difftime(la->soft_lifetime_end_time,
596 				lb->soft_lifetime_end_time) < 0;
597 	} else {
598 		return difftime(la->hard_lifetime_end_time,
599 				lb->hard_lifetime_end_time) < 0;
600 	}
601 }
602 
603 /*
604  * Helper functions for lease address/prefix heaps.
605  * Callback when an address's position in the heap changes.
606  */
607 static void
active_changed(void * iasubopt,unsigned int new_heap_index)608 active_changed(void *iasubopt, unsigned int new_heap_index) {
609 	((struct iasubopt *)iasubopt)->active_index = new_heap_index;
610 }
611 
612 static void
inactive_changed(void * iasubopt,unsigned int new_heap_index)613 inactive_changed(void *iasubopt, unsigned int new_heap_index) {
614 	((struct iasubopt *)iasubopt)->inactive_index = new_heap_index;
615 }
616 
617 /*!
618  *
619  * \brief Create a new IPv6 lease pool structure
620  *
621  * Allocate space for a new ipv6_pool structure and return a reference
622  * to it, includes setting the reference count to 1.
623  *
624  * \param     pool       = space for returning a referenced pointer to the pool.
625  *			   This must point to a space that has been initialzied
626  *			   to NULL by the caller.
627  * \param[in] type       = The type of the pool NA, TA or PD
628  * \param[in] start_addr = The first address in the range for the pool
629  * \param[in] bits       = The contiguous bits of the pool
630 
631  *
632  * \return
633  * ISC_R_SUCCESS     = The pool was successfully created, pool points to it.
634  * DHCP_R_INVALIDARG = One of the arugments was invalid, pool has not been
635  *		       modified
636  * ISC_R_NOMEMORY    = The system wasn't able to allocate memory, pool has
637  *		       not been modified.
638  */
639 isc_result_t
ipv6_pool_allocate(struct ipv6_pool ** pool,u_int16_t type,const struct in6_addr * start_addr,int bits,int units,const char * file,int line)640 ipv6_pool_allocate(struct ipv6_pool **pool, u_int16_t type,
641 		   const struct in6_addr *start_addr, int bits,
642 		   int units, const char *file, int line) {
643 	struct ipv6_pool *tmp;
644 
645 	if (pool == NULL) {
646 		log_error("%s(%d): NULL pointer reference", file, line);
647 		return DHCP_R_INVALIDARG;
648 	}
649 	if (*pool != NULL) {
650 		log_error("%s(%d): non-NULL pointer", file, line);
651 		return DHCP_R_INVALIDARG;
652 	}
653 
654 	tmp = dmalloc(sizeof(*tmp), file, line);
655 	if (tmp == NULL) {
656 		return ISC_R_NOMEMORY;
657 	}
658 
659 	tmp->refcnt = 1;
660 	tmp->pool_type = type;
661 	tmp->start_addr = *start_addr;
662 	tmp->bits = bits;
663 	tmp->units = units;
664 	if (!iasubopt_new_hash(&tmp->leases, DEFAULT_HASH_SIZE, file, line)) {
665 		dfree(tmp, file, line);
666 		return ISC_R_NOMEMORY;
667 	}
668 	if (isc_heap_create(dhcp_gbl_ctx.mctx, lease_older, active_changed,
669 			    0, &(tmp->active_timeouts)) != ISC_R_SUCCESS) {
670 		iasubopt_free_hash_table(&(tmp->leases), file, line);
671 		dfree(tmp, file, line);
672 		return ISC_R_NOMEMORY;
673 	}
674 	if (isc_heap_create(dhcp_gbl_ctx.mctx, lease_older, inactive_changed,
675 			    0, &(tmp->inactive_timeouts)) != ISC_R_SUCCESS) {
676 		isc_heap_destroy(&(tmp->active_timeouts));
677 		iasubopt_free_hash_table(&(tmp->leases), file, line);
678 		dfree(tmp, file, line);
679 		return ISC_R_NOMEMORY;
680 	}
681 
682 	*pool = tmp;
683 	return ISC_R_SUCCESS;
684 }
685 
686 /*!
687  *
688  * \brief reference an IPv6 pool structure.
689  *
690  * This function genreates a reference to an ipv6_pool structure
691  * and increments the reference count on the structure.
692  *
693  * \param[out] pool = space for returning a referenced pointer to the pool.
694  *		      This must point to a space that has been initialzied
695  *		      to NULL by the caller.
696  * \param[in]  src  = A pointer to the pool to reference.  This must not be
697  *		      NULL.
698  *
699  * \return
700  * ISC_R_SUCCESS     = The pool was successfully referenced, pool now points
701  *		       to src.
702  * DHCP_R_INVALIDARG = One of the arugments was invalid, pool has not been
703  *		       modified.
704  */
705 isc_result_t
ipv6_pool_reference(struct ipv6_pool ** pool,struct ipv6_pool * src,const char * file,int line)706 ipv6_pool_reference(struct ipv6_pool **pool, struct ipv6_pool *src,
707 		    const char *file, int line) {
708 	if (pool == NULL) {
709 		log_error("%s(%d): NULL pointer reference", file, line);
710 		return DHCP_R_INVALIDARG;
711 	}
712 	if (*pool != NULL) {
713 		log_error("%s(%d): non-NULL pointer", file, line);
714 		return DHCP_R_INVALIDARG;
715 	}
716 	if (src == NULL) {
717 		log_error("%s(%d): NULL pointer reference", file, line);
718 		return DHCP_R_INVALIDARG;
719 	}
720 	*pool = src;
721 	src->refcnt++;
722 	return ISC_R_SUCCESS;
723 }
724 
725 /*
726  * Note: Each IAADDR/PREFIX in a pool is referenced by the pool. This is needed
727  * to prevent the lease from being garbage collected out from under the
728  * pool.
729  *
730  * The references are made from the hash and from the heap. The following
731  * helper functions dereference these when a pool is destroyed.
732  */
733 
734 /*
735  * Helper function for pool cleanup.
736  * Dereference each of the hash entries in a pool.
737  */
738 static isc_result_t
dereference_hash_entry(const void * name,unsigned len,void * value)739 dereference_hash_entry(const void *name, unsigned len, void *value) {
740 	struct iasubopt *iasubopt = (struct iasubopt *)value;
741 
742 	iasubopt_dereference(&iasubopt, MDL);
743 	return ISC_R_SUCCESS;
744 }
745 
746 /*
747  * Helper function for pool cleanup.
748  * Dereference each of the heap entries in a pool.
749  */
750 static void
dereference_heap_entry(void * value,void * dummy)751 dereference_heap_entry(void *value, void *dummy) {
752 	struct iasubopt *iasubopt = (struct iasubopt *)value;
753 
754 	iasubopt_dereference(&iasubopt, MDL);
755 }
756 
757 /*!
758  *
759  * \brief de-reference an IPv6 pool structure.
760  *
761  * This function decrements the reference count in an ipv6_pool structure.
762  * If this was the last reference then the memory for the structure is
763  * freed.
764  *
765  * \param[in] pool = A pointer to the pointer to the pool that should be
766  *		     de-referenced.  On success the pointer to the pool
767  *		     is cleared.  It must not be NULL and must not point
768  *		     to NULL.
769  *
770  * \return
771  * ISC_R_SUCCESS     = The pool was successfully de-referenced, pool now points
772  *		       to NULL
773  * DHCP_R_INVALIDARG = One of the arugments was invalid, pool has not been
774  *		       modified.
775  */
776 isc_result_t
ipv6_pool_dereference(struct ipv6_pool ** pool,const char * file,int line)777 ipv6_pool_dereference(struct ipv6_pool **pool, const char *file, int line) {
778 	struct ipv6_pool *tmp;
779 
780 	if ((pool == NULL) || (*pool == NULL)) {
781 		log_error("%s(%d): NULL pointer", file, line);
782 		return DHCP_R_INVALIDARG;
783 	}
784 
785 	tmp = *pool;
786 	*pool = NULL;
787 
788 	tmp->refcnt--;
789 	if (tmp->refcnt < 0) {
790 		log_error("%s(%d): negative refcnt", file, line);
791 		tmp->refcnt = 0;
792 	}
793 	if (tmp->refcnt == 0) {
794 		iasubopt_hash_foreach(tmp->leases, dereference_hash_entry);
795 		iasubopt_free_hash_table(&(tmp->leases), file, line);
796 		isc_heap_foreach(tmp->active_timeouts,
797 				 dereference_heap_entry, NULL);
798 		isc_heap_destroy(&(tmp->active_timeouts));
799 		isc_heap_foreach(tmp->inactive_timeouts,
800 				 dereference_heap_entry, NULL);
801 		isc_heap_destroy(&(tmp->inactive_timeouts));
802 		dfree(tmp, file, line);
803 	}
804 
805 	return ISC_R_SUCCESS;
806 }
807 
808 /*
809  * Create an address by hashing the input, and using that for
810  * the non-network part.
811  */
812 static void
build_address6(struct in6_addr * addr,const struct in6_addr * net_start_addr,int net_bits,const struct data_string * input)813 build_address6(struct in6_addr *addr,
814 	       const struct in6_addr *net_start_addr, int net_bits,
815 	       const struct data_string *input) {
816 	isc_md5_t ctx;
817 	int net_bytes;
818 	int i;
819 	char *str;
820 	const char *net_str;
821 
822 	/*
823 	 * Use MD5 to get a nice 128 bit hash of the input.
824 	 * Yes, we know MD5 isn't cryptographically sound.
825 	 * No, we don't care.
826 	 */
827 	isc_md5_init(&ctx);
828 	isc_md5_update(&ctx, input->data, input->len);
829 	isc_md5_final(&ctx, (unsigned char *)addr);
830 
831 	/*
832 	 * Copy the [0..128] network bits over.
833 	 */
834 	str = (char *)addr;
835 	net_str = (const char *)net_start_addr;
836 	net_bytes = net_bits / 8;
837 	for (i = 0; i < net_bytes; i++) {
838 		str[i] = net_str[i];
839 	}
840 	switch (net_bits % 8) {
841 		case 1: str[i] = (str[i] & 0x7F) | (net_str[i] & 0x80); break;
842 		case 2: str[i] = (str[i] & 0x3F) | (net_str[i] & 0xC0); break;
843 		case 3: str[i] = (str[i] & 0x1F) | (net_str[i] & 0xE0); break;
844 		case 4: str[i] = (str[i] & 0x0F) | (net_str[i] & 0xF0); break;
845 		case 5: str[i] = (str[i] & 0x07) | (net_str[i] & 0xF8); break;
846 		case 6: str[i] = (str[i] & 0x03) | (net_str[i] & 0xFC); break;
847 		case 7: str[i] = (str[i] & 0x01) | (net_str[i] & 0xFE); break;
848 	}
849 
850 	/*
851 	 * Set the universal/local bit ("u bit") to zero for /64s.  The
852 	 * individual/group bit ("g bit") is unchanged, because the g-bit
853 	 * has no meaning when the u-bit is cleared.
854 	 */
855 	if (net_bits == 64)
856 		str[8] &= ~0x02;
857 }
858 
859 #ifdef EUI_64
860 int
valid_eui_64_duid(const struct data_string * uid,int offset)861 valid_eui_64_duid(const struct data_string* uid, int offset) {
862 	if (uid->len == (offset + EUI_64_ID_LEN)) {
863 		const unsigned char* duid = uid->data + offset;
864 		return (((duid[0] == 0x00 && duid[1] == 0x03)  &&
865 			(duid[2] == 0x00 && duid[3] == 0x1b)));
866 	}
867 
868     return(0);
869 }
870 
871 
872 /*
873  * Create an EUI-64 address
874  */
875 static isc_result_t
build_address6_eui_64(struct in6_addr * addr,const struct in6_addr * net_start_addr,int net_bits,const struct data_string * iaid_duid,int duid_beg)876 build_address6_eui_64(struct in6_addr *addr,
877 		      const struct in6_addr *net_start_addr, int net_bits,
878 		      const struct data_string *iaid_duid, int duid_beg) {
879 
880 	if (net_bits != 64) {
881 		log_error("build_address_eui_64: network is not 64 bits");
882 		return (ISC_R_FAILURE);
883 	}
884 
885 	if (valid_eui_64_duid(iaid_duid, duid_beg)) {
886 		const unsigned char *duid = iaid_duid->data + duid_beg;
887 
888 		/* copy network prefix to the high 64 bits */
889 		memcpy(addr->s6_addr, net_start_addr->s6_addr, 8);
890 
891 		/* copy Link-layer address to low 64 bits */
892 		memcpy(addr->s6_addr + 8, duid + 4, 8);
893 
894 		/* RFC-3315 Any address assigned by a server that is based
895 		 * on an EUI-64 identifier MUST include an interface identifier
896 		 * with the "u" (universal/local) and "g" (individual/group)
897 		 * bits of the interface identifier set appropriately, as
898 		 * indicated in section 2.5.1 of RFC 2373 [5]. */
899 		addr->s6_addr[8] |= 0x02;
900 		return (ISC_R_SUCCESS);
901 	}
902 
903 	log_error("build_address_eui_64: iaid_duid not a valid EUI-64: %s",
904 		  print_hex_1(iaid_duid->len, iaid_duid->data, 60));
905 	return (ISC_R_FAILURE);
906 }
907 
908 int
valid_for_eui_64_pool(struct ipv6_pool * pool,struct data_string * uid,int duid_beg,struct in6_addr * ia_addr)909 valid_for_eui_64_pool(struct ipv6_pool* pool, struct data_string* uid,
910 		      int duid_beg, struct in6_addr* ia_addr) {
911         struct in6_addr test_addr;
912 	/* If it's not an EUI-64 pool bail */
913         if (!pool->ipv6_pond->use_eui_64) {
914                 return (0);
915         }
916 
917         if (!valid_eui_64_duid(uid, duid_beg)) {
918                 /* Dynamic lease in a now eui_64 pond, toss it*/
919                 return (0);
920         }
921 
922         /*  Call build_address6_eui_64() and compare it's result to
923 	 *  this lease and see if they match. */
924         memset (&test_addr, 0, sizeof(test_addr));
925         build_address6_eui_64(&test_addr, &pool->start_addr, pool->bits,
926                               uid, duid_beg);
927 
928         return (!memcmp(ia_addr, &test_addr, sizeof(test_addr)));
929 }
930 #endif
931 
932 
933 /*
934  * Create a temporary address by a variant of RFC 4941 algo.
935  * Note: this should not be used for prefixes shorter than 64 bits.
936  */
937 static void
build_temporary6(struct in6_addr * addr,const struct in6_addr * net_start_addr,int net_bits,const struct data_string * input)938 build_temporary6(struct in6_addr *addr,
939 		 const struct in6_addr *net_start_addr, int net_bits,
940 		 const struct data_string *input) {
941 	static u_int32_t history[2];
942 	static u_int32_t counter = 0;
943 	isc_md5_t ctx;
944 	unsigned char md[16];
945 
946 	/*
947 	 * First time/time to reseed.
948 	 * Please use a good pseudo-random generator here!
949 	 */
950 	if (counter == 0) {
951 		isc_random_get(&history[0]);
952 		isc_random_get(&history[1]);
953 	}
954 
955 	/*
956 	 * Use MD5 as recommended by RFC 4941.
957 	 */
958 	isc_md5_init(&ctx);
959 	isc_md5_update(&ctx, (unsigned char *)&history[0], 8UL);
960 	isc_md5_update(&ctx, input->data, input->len);
961 	isc_md5_final(&ctx, md);
962 
963 	/*
964 	 * Build the address.
965 	 */
966 	if (net_bits == 64) {
967 		memcpy(&addr->s6_addr[0], &net_start_addr->s6_addr[0], 8);
968 		memcpy(&addr->s6_addr[8], md, 8);
969 		addr->s6_addr[8] &= ~0x02;
970 	} else {
971 		int net_bytes;
972 		int i;
973 		char *str;
974 		const char *net_str;
975 
976 		/*
977 		 * Copy the [0..128] network bits over.
978 		 */
979 		str = (char *)addr;
980 		net_str = (const char *)net_start_addr;
981 		net_bytes = net_bits / 8;
982 		for (i = 0; i < net_bytes; i++) {
983 			str[i] = net_str[i];
984 		}
985 		memcpy(str + net_bytes, md, 16 - net_bytes);
986 		switch (net_bits % 8) {
987 		case 1: str[i] = (str[i] & 0x7F) | (net_str[i] & 0x80); break;
988 		case 2: str[i] = (str[i] & 0x3F) | (net_str[i] & 0xC0); break;
989 		case 3: str[i] = (str[i] & 0x1F) | (net_str[i] & 0xE0); break;
990 		case 4: str[i] = (str[i] & 0x0F) | (net_str[i] & 0xF0); break;
991 		case 5: str[i] = (str[i] & 0x07) | (net_str[i] & 0xF8); break;
992 		case 6: str[i] = (str[i] & 0x03) | (net_str[i] & 0xFC); break;
993 		case 7: str[i] = (str[i] & 0x01) | (net_str[i] & 0xFE); break;
994 		}
995 	}
996 
997 
998 	/*
999 	 * Save history for the next call.
1000 	 */
1001 	memcpy((unsigned char *)&history[0], md + 8, 8);
1002 	counter++;
1003 }
1004 
1005 /* Reserved Subnet Router Anycast ::0:0:0:0. */
1006 static struct in6_addr rtany;
1007 /* Reserved Subnet Anycasts ::fdff:ffff:ffff:ff80-::fdff:ffff:ffff:ffff. */
1008 static struct in6_addr resany;
1009 
1010 /*
1011  * Create a lease for the given address and client duid.
1012  *
1013  * - pool must be a pointer to a (struct ipv6_pool *) pointer previously
1014  *   initialized to NULL
1015  *
1016  * Right now we simply hash the DUID, and if we get a collision, we hash
1017  * again until we find a free address. We try this a fixed number of times,
1018  * to avoid getting stuck in a loop (this is important on small pools
1019  * where we can run out of space).
1020  *
1021  * We return the number of attempts that it took to find an available
1022  * lease. This tells callers when a pool is are filling up, as
1023  * well as an indication of how full the pool is; statistically the
1024  * more full a pool is the more attempts must be made before finding
1025  * a free lease. Realistically this will only happen in very full
1026  * pools.
1027  *
1028  * We probably want different algorithms depending on the network size, in
1029  * the long term.
1030  */
1031 isc_result_t
create_lease6(struct ipv6_pool * pool,struct iasubopt ** addr,unsigned int * attempts,const struct data_string * uid,time_t soft_lifetime_end_time)1032 create_lease6(struct ipv6_pool *pool, struct iasubopt **addr,
1033 	      unsigned int *attempts,
1034 	      const struct data_string *uid, time_t soft_lifetime_end_time) {
1035 	struct data_string ds;
1036 	struct in6_addr tmp;
1037 	struct iasubopt *test_iaaddr;
1038 	struct data_string new_ds;
1039 	struct iasubopt *iaaddr;
1040 	isc_result_t result;
1041 	isc_boolean_t reserved_iid;
1042 	static isc_boolean_t init_resiid = ISC_FALSE;
1043 
1044 	/*
1045 	 * Fill the reserved IIDs.
1046 	 */
1047 	if (!init_resiid) {
1048 		memset(&rtany, 0, 16);
1049 		memset(&resany, 0, 8);
1050 		resany.s6_addr[8] = 0xfd;
1051 		memset(&resany.s6_addr[9], 0xff, 6);
1052 		init_resiid = ISC_TRUE;
1053 	}
1054 
1055 	/*
1056 	 * Use the UID as our initial seed for the hash
1057 	 */
1058 	memset(&ds, 0, sizeof(ds));
1059 	data_string_copy(&ds, (struct data_string *)uid, MDL);
1060 
1061 	*attempts = 0;
1062 	for (;;) {
1063 		/*
1064 		 * Give up at some point.
1065 		 */
1066 		if (++(*attempts) > 100) {
1067 			data_string_forget(&ds, MDL);
1068 			return ISC_R_NORESOURCES;
1069 		}
1070 
1071 		/*
1072 		 * Build a resource.
1073 		 */
1074 		switch (pool->pool_type) {
1075 		case D6O_IA_NA:
1076 			/* address */
1077 			build_address6(&tmp, &pool->start_addr,
1078 				       pool->bits, &ds);
1079 			break;
1080 		case D6O_IA_TA:
1081 			/* temporary address */
1082 			build_temporary6(&tmp, &pool->start_addr,
1083 					 pool->bits, &ds);
1084 			break;
1085 		case D6O_IA_PD:
1086 			/* prefix */
1087 			log_error("create_lease6: prefix pool.");
1088 			data_string_forget(&ds, MDL);
1089 			return DHCP_R_INVALIDARG;
1090 		default:
1091 			log_error("create_lease6: untyped pool.");
1092 			data_string_forget(&ds, MDL);
1093 			return DHCP_R_INVALIDARG;
1094 		}
1095 
1096 		/*
1097 		 * Avoid reserved interface IDs. (cf. RFC 5453)
1098 		 */
1099 		reserved_iid = ISC_FALSE;
1100 		if (memcmp(&tmp.s6_addr[8], &rtany.s6_addr[8], 8) == 0) {
1101 			reserved_iid = ISC_TRUE;
1102 		}
1103 		if (!reserved_iid &&
1104 		    (memcmp(&tmp.s6_addr[8], &resany.s6_addr[8], 7) == 0) &&
1105 		    ((tmp.s6_addr[15] & 0x80) == 0x80)) {
1106 			reserved_iid = ISC_TRUE;
1107 		}
1108 
1109 		/*
1110 		 * If this address is not in use, we're happy with it
1111 		 */
1112 		test_iaaddr = NULL;
1113 		if (!reserved_iid &&
1114 		    (iasubopt_hash_lookup(&test_iaaddr, pool->leases,
1115 					  &tmp, sizeof(tmp), MDL) == 0)) {
1116 			break;
1117 		}
1118 		if (test_iaaddr != NULL)
1119 			iasubopt_dereference(&test_iaaddr, MDL);
1120 
1121 		/*
1122 		 * Otherwise, we create a new input, adding the address
1123 		 */
1124 		memset(&new_ds, 0, sizeof(new_ds));
1125 		new_ds.len = ds.len + sizeof(tmp);
1126 		if (!buffer_allocate(&new_ds.buffer, new_ds.len, MDL)) {
1127 			data_string_forget(&ds, MDL);
1128 			return ISC_R_NOMEMORY;
1129 		}
1130 		new_ds.data = new_ds.buffer->data;
1131 		memcpy(new_ds.buffer->data, ds.data, ds.len);
1132 		memcpy(new_ds.buffer->data + ds.len, &tmp, sizeof(tmp));
1133 		data_string_forget(&ds, MDL);
1134 		data_string_copy(&ds, &new_ds, MDL);
1135 		data_string_forget(&new_ds, MDL);
1136 	}
1137 
1138 	data_string_forget(&ds, MDL);
1139 
1140 	/*
1141 	 * We're happy with the address, create an IAADDR
1142 	 * to hold it.
1143 	 */
1144 	iaaddr = NULL;
1145 	result = iasubopt_allocate(&iaaddr, MDL);
1146 	if (result != ISC_R_SUCCESS) {
1147 		return result;
1148 	}
1149 	iaaddr->plen = 0;
1150 	memcpy(&iaaddr->addr, &tmp, sizeof(iaaddr->addr));
1151 
1152 	/*
1153 	 * Add the lease to the pool (note state is free, not active?!).
1154 	 */
1155 	result = add_lease6(pool, iaaddr, soft_lifetime_end_time);
1156 	if (result == ISC_R_SUCCESS) {
1157 		iasubopt_reference(addr, iaaddr, MDL);
1158 	}
1159 	iasubopt_dereference(&iaaddr, MDL);
1160 	return result;
1161 }
1162 
1163 #ifdef EUI_64
1164 /*!
1165  * \brief Assign an EUI-64 address from a pool for a given iaid-duid
1166  *
1167  *  \param pool - pool from which the address is assigned
1168  *  \param iaddr - pointer to the iasubopt to contain the assigned address is
1169  *  \param uid - data_string containing the iaid-duid tuple
1170  *  \param soft_lifetime_end_time - lifetime of the lease for a solicit?
1171  *
1172  *  \return status indicating success or nature of the failure
1173 */
1174 isc_result_t
create_lease6_eui_64(struct ipv6_pool * pool,struct iasubopt ** addr,const struct data_string * uid,time_t soft_lifetime_end_time)1175 create_lease6_eui_64(struct ipv6_pool *pool, struct iasubopt **addr,
1176 	      const struct data_string *uid,
1177 	      time_t soft_lifetime_end_time) {
1178 	struct in6_addr tmp;
1179 	struct iasubopt *test_iaaddr;
1180 	struct iasubopt *iaaddr;
1181 	isc_result_t result;
1182 	static isc_boolean_t init_resiid = ISC_FALSE;
1183 
1184 	/*  Fill the reserved IIDs.  */
1185 	if (!init_resiid) {
1186 		memset(&rtany, 0, 16);
1187 		memset(&resany, 0, 8);
1188 		resany.s6_addr[8] = 0xfd;
1189 		memset(&resany.s6_addr[9], 0xff, 6);
1190 		init_resiid = ISC_TRUE;
1191 	}
1192 
1193 	/* Pool must be IA_NA */
1194 	if (pool->pool_type != D6O_IA_NA) {
1195 		log_error("create_lease6_eui_64: pool type is not IA_NA.");
1196 		return (DHCP_R_INVALIDARG);
1197 	}
1198 
1199 	/* Attempt to build the address */
1200 	if (build_address6_eui_64 (&tmp, &pool->start_addr, pool->bits,
1201 				   uid, IAID_LEN) != ISC_R_SUCCESS) {
1202 		log_error("create_lease6_eui_64: build_address6_eui_64 failed");
1203 		return (ISC_R_FAILURE);
1204 	}
1205 
1206 	/* Avoid reserved interface IDs. (cf. RFC 5453) */
1207 	if ((memcmp(&tmp.s6_addr[8], &rtany.s6_addr[8], 8) == 0)  ||
1208 	    ((memcmp(&tmp.s6_addr[8], &resany.s6_addr[8], 7) == 0) &&
1209 	    ((tmp.s6_addr[15] & 0x80) == 0x80))) {
1210 		log_error("create_lease6_eui_64: "
1211 			  "address conflicts with reserved IID");
1212 		return (ISC_R_FAILURE);
1213 	}
1214 
1215 	/* If this address is not in use, we're happy with it */
1216 	test_iaaddr = NULL;
1217 	if (iasubopt_hash_lookup(&test_iaaddr, pool->leases,
1218 				  &tmp, sizeof(tmp), MDL) != 0) {
1219 
1220 		/* See if it's ours. Static leases won't have an ia */
1221 		int ours = 0;
1222 		if (!test_iaaddr->ia) {
1223 			log_error("create_lease6_eui_64: "
1224 				  "address  %s is assigned to static lease",
1225 				  pin6_addr(&test_iaaddr->addr));
1226 		} else {
1227 			/* Not sure if this can actually happen */
1228 			struct data_string* found = &test_iaaddr->ia->iaid_duid;
1229 			ours = ((found->len == uid->len) &&
1230 				(!memcmp(found->data, uid->data, uid->len)));
1231 			log_error("create_lease6_eui_64: "
1232 				  "address  %s belongs to %s",
1233 				  pin6_addr(&test_iaaddr->addr),
1234 				  print_hex_1(found->len, found->data, 60));
1235 		}
1236 
1237 		iasubopt_dereference(&test_iaaddr, MDL);
1238 		if (!ours) {
1239 			/* Cant' use it */
1240 			return (ISC_R_FAILURE);
1241 		}
1242 	}
1243 
1244 	/* We're happy with the address, create an IAADDR to hold it. */
1245 	iaaddr = NULL;
1246 	result = iasubopt_allocate(&iaaddr, MDL);
1247 	if (result != ISC_R_SUCCESS) {
1248 		log_error("create_lease6_eui_64: could not allocate iasubop");
1249 		return result;
1250 	}
1251 	iaaddr->plen = 0;
1252 	memcpy(&iaaddr->addr, &tmp, sizeof(iaaddr->addr));
1253 
1254 	/* Add the lease to the pool and the reply */
1255 	result = add_lease6(pool, iaaddr, soft_lifetime_end_time);
1256 	if (result == ISC_R_SUCCESS) {
1257 		iasubopt_reference(addr, iaaddr, MDL);
1258 	}
1259 
1260 	iasubopt_dereference(&iaaddr, MDL);
1261 	return result;
1262 }
1263 #endif
1264 
1265 /*!
1266  *
1267  * \brief Cleans up leases when reading from a lease file
1268  *
1269  * This function is only expected to be run when reading leases in from a file.
1270  * It checks to see if a lease already exists for the new leases's address.
1271  * We don't add expired leases to the structures when reading a lease file
1272  * which limits what can happen.  We have two variables the owners of the leases
1273  * being the same or different and the new lease being active or non-active:
1274  * Owners active
1275  * same   no     remove old lease and its connections
1276  * same   yes    nothing to do, other code will update the structures.
1277  * diff   no     nothing to do
1278  * diff   yes    this combination shouldn't happen, we should only have a
1279  *               single active lease per address at a time and that lease
1280  *               should move to non-active before any other lease can
1281  *               become active for that address.
1282  *               Currently we delete the previous lease and pass an error
1283  *               to the caller who should log an error.
1284  *
1285  * When we remove a lease we remove it from the hash table and active heap
1286  * (remember only active leases are in the structures at this time) for the
1287  * pool, and from the IA's array.  If, after we've removed the pointer from
1288  * IA's array to the lease, the IA has no more pointers we remove it from
1289  * the appropriate hash table as well.
1290  *
1291  * \param[in] ia_table = the hash table for the IA
1292  * \param[in] pool     = the pool to update
1293  * \param[in] lease    = the new lease we want to add
1294  * \param[in] ia       = the new ia we are building
1295  *
1296  * \return
1297  * ISC_R_SUCCESS = the incoming lease and any previous lease were in
1298  *                 an expected state - one of the first 3 options above.
1299  *                 If necessary the old lease was removed.
1300  * ISC_R_FAILURE = there is already an active lease for the address in
1301  *                 the incoming lease.  This shouldn't happen if it does
1302  *                 flag an error for the caller to log.
1303  */
1304 
1305 isc_result_t
cleanup_lease6(ia_hash_t * ia_table,struct ipv6_pool * pool,struct iasubopt * lease,struct ia_xx * ia)1306 cleanup_lease6(ia_hash_t *ia_table,
1307 	       struct ipv6_pool *pool,
1308 	       struct iasubopt *lease,
1309 	       struct ia_xx *ia) {
1310 
1311 	struct iasubopt *test_iasubopt, *tmp_iasubopt;
1312 	struct ia_xx *old_ia;
1313 	isc_result_t status = ISC_R_SUCCESS;
1314 
1315 	test_iasubopt = NULL;
1316 	old_ia = NULL;
1317 
1318 	/*
1319 	 * Look up the address - if we don't find a lease
1320 	 * we don't need to do anything.
1321 	 */
1322 	if (iasubopt_hash_lookup(&test_iasubopt, pool->leases,
1323 				 &lease->addr, sizeof(lease->addr),
1324 				 MDL) == 0) {
1325 		return (ISC_R_SUCCESS);
1326 	}
1327 
1328 	if (test_iasubopt->ia == NULL) {
1329 		/* no old ia, no work to do */
1330 		iasubopt_dereference(&test_iasubopt, MDL);
1331 		return (status);
1332 	}
1333 
1334 	ia_reference(&old_ia, test_iasubopt->ia, MDL);
1335 
1336 	if ((old_ia->iaid_duid.len == ia->iaid_duid.len) &&
1337 	    (memcmp((unsigned char *)ia->iaid_duid.data,
1338 		    (unsigned char *)old_ia->iaid_duid.data,
1339 		    ia->iaid_duid.len) == 0)) {
1340 		/* same IA */
1341 		if ((lease->state == FTS_ACTIVE) ||
1342 		    (lease->state == FTS_ABANDONED)) {
1343 			/* still active, no need to delete */
1344 			goto cleanup;
1345 		}
1346 	} else {
1347 		/* different IA */
1348 		if ((lease->state != FTS_ACTIVE) &&
1349 		    (lease->state != FTS_ABANDONED)) {
1350 			/* new lease isn't active, no work */
1351 			goto cleanup;
1352 		}
1353 
1354 		/*
1355 		 * We appear to have two active leases, this shouldn't happen.
1356 		 * Before a second lease can be set to active the first lease
1357 		 * should be set to inactive (released, expired etc). For now
1358 		 * delete the previous lease and indicate a failure to the
1359 		 * caller so it can generate a warning.
1360 		 * In the future we may try and determine which is the better
1361 		 * lease to keep.
1362 		 */
1363 
1364 		status = ISC_R_FAILURE;
1365 	}
1366 
1367 	/*
1368 	 * Remove the old lease from the active heap and from the hash table
1369 	 * then remove the lease from the IA and clean up the IA if necessary.
1370 	 */
1371 	isc_heap_delete(pool->active_timeouts, test_iasubopt->active_index);
1372 	pool->num_active--;
1373 	if (pool->ipv6_pond)
1374 		pool->ipv6_pond->num_active--;
1375 
1376 	if (lease->state == FTS_ABANDONED) {
1377 		pool->num_abandoned--;
1378 		if (pool->ipv6_pond)
1379 			pool->ipv6_pond->num_abandoned--;
1380 	}
1381 
1382 	iasubopt_hash_delete(pool->leases, &test_iasubopt->addr,
1383 			     sizeof(test_iasubopt->addr), MDL);
1384 	ia_remove_iasubopt(old_ia, test_iasubopt, MDL);
1385 	if (old_ia->num_iasubopt <= 0) {
1386 		ia_hash_delete(ia_table,
1387 			       (unsigned char *)old_ia->iaid_duid.data,
1388 			       old_ia->iaid_duid.len, MDL);
1389 	}
1390 
1391 	/*
1392 	 * We derefenrece the subopt here as we've just removed it from
1393 	 * the hash table in the pool.  We need to make a copy as we
1394 	 * need to derefernece it again later.
1395 	 */
1396 	tmp_iasubopt = test_iasubopt;
1397 	iasubopt_dereference(&tmp_iasubopt, MDL);
1398 
1399       cleanup:
1400 	ia_dereference(&old_ia, MDL);
1401 
1402 	/*
1403 	 * Clean up the reference, this is in addition to the deference
1404 	 * above after removing the entry from the hash table
1405 	 */
1406 	iasubopt_dereference(&test_iasubopt, MDL);
1407 
1408 	return (status);
1409 }
1410 
1411 /*
1412  * Put a lease in the pool directly. This is intended to be used when
1413  * loading leases from the file.
1414  */
1415 isc_result_t
add_lease6(struct ipv6_pool * pool,struct iasubopt * lease,time_t valid_lifetime_end_time)1416 add_lease6(struct ipv6_pool *pool, struct iasubopt *lease,
1417 	   time_t valid_lifetime_end_time) {
1418 	isc_result_t insert_result;
1419 	struct iasubopt *test_iasubopt;
1420 	struct iasubopt *tmp_iasubopt;
1421 
1422 	/* If a state was not assigned by the caller, assume active. */
1423 	if (lease->state == 0)
1424 		lease->state = FTS_ACTIVE;
1425 
1426 	ipv6_pool_reference(&lease->ipv6_pool, pool, MDL);
1427 
1428 	/*
1429 	 * If this IAADDR/PREFIX is already in our structures, remove the
1430 	 * old one.
1431 	 */
1432 	test_iasubopt = NULL;
1433 	if (iasubopt_hash_lookup(&test_iasubopt, pool->leases,
1434 				 &lease->addr, sizeof(lease->addr), MDL)) {
1435 		/* XXX: we should probably ask the lease what heap it is on
1436 		 * (as a consistency check).
1437 		 * XXX: we should probably have one function to "put this lease
1438 		 * on its heap" rather than doing these if's everywhere.  If
1439 		 * you add more states to this list, don't.
1440 		 */
1441 		if ((test_iasubopt->state == FTS_ACTIVE) ||
1442 		    (test_iasubopt->state == FTS_ABANDONED)) {
1443 			isc_heap_delete(pool->active_timeouts,
1444 					test_iasubopt->active_index);
1445 			pool->num_active--;
1446 			if (pool->ipv6_pond)
1447 				pool->ipv6_pond->num_active--;
1448 
1449 			if (test_iasubopt->state == FTS_ABANDONED) {
1450 				pool->num_abandoned--;
1451 				if (pool->ipv6_pond)
1452 					pool->ipv6_pond->num_abandoned--;
1453 			}
1454 		} else {
1455 			isc_heap_delete(pool->inactive_timeouts,
1456 					test_iasubopt->inactive_index);
1457 			pool->num_inactive--;
1458 		}
1459 
1460 		iasubopt_hash_delete(pool->leases, &test_iasubopt->addr,
1461 				     sizeof(test_iasubopt->addr), MDL);
1462 
1463 		/*
1464 		 * We're going to do a bit of evil trickery here.
1465 		 *
1466 		 * We need to dereference the entry once to remove our
1467 		 * current reference (in test_iasubopt), and then one
1468 		 * more time to remove the reference left when the
1469 		 * address was added to the pool before.
1470 		 */
1471 		tmp_iasubopt = test_iasubopt;
1472 		iasubopt_dereference(&test_iasubopt, MDL);
1473 		iasubopt_dereference(&tmp_iasubopt, MDL);
1474 	}
1475 
1476 	/*
1477 	 * Add IAADDR/PREFIX to our structures.
1478 	 */
1479 	tmp_iasubopt = NULL;
1480 	iasubopt_reference(&tmp_iasubopt, lease, MDL);
1481 	if ((tmp_iasubopt->state == FTS_ACTIVE) ||
1482 	    (tmp_iasubopt->state == FTS_ABANDONED)) {
1483 		tmp_iasubopt->hard_lifetime_end_time = valid_lifetime_end_time;
1484 		iasubopt_hash_add(pool->leases, &tmp_iasubopt->addr,
1485 				  sizeof(tmp_iasubopt->addr), lease, MDL);
1486 		insert_result = isc_heap_insert(pool->active_timeouts,
1487 						tmp_iasubopt);
1488 		if (insert_result == ISC_R_SUCCESS) {
1489 			pool->num_active++;
1490 			if (pool->ipv6_pond)
1491 				pool->ipv6_pond->num_active++;
1492 
1493 			if (tmp_iasubopt->state == FTS_ABANDONED) {
1494 				pool->num_abandoned++;
1495 				if (pool->ipv6_pond)
1496 					pool->ipv6_pond->num_abandoned++;
1497 			}
1498 		}
1499 
1500 	} else {
1501 		tmp_iasubopt->soft_lifetime_end_time = valid_lifetime_end_time;
1502 		insert_result = isc_heap_insert(pool->inactive_timeouts,
1503 						tmp_iasubopt);
1504 		if (insert_result == ISC_R_SUCCESS)
1505 			pool->num_inactive++;
1506 	}
1507 	if (insert_result != ISC_R_SUCCESS) {
1508 		iasubopt_hash_delete(pool->leases, &lease->addr,
1509 				     sizeof(lease->addr), MDL);
1510 		iasubopt_dereference(&tmp_iasubopt, MDL);
1511 		return insert_result;
1512 	}
1513 
1514 	/*
1515 	 * Note: we intentionally leave tmp_iasubopt referenced; there
1516 	 * is a reference in the heap/hash, after all.
1517 	 */
1518 
1519 	return ISC_R_SUCCESS;
1520 }
1521 
1522 /*
1523  * Determine if an address is present in a pool or not.
1524  */
1525 isc_boolean_t
lease6_exists(const struct ipv6_pool * pool,const struct in6_addr * addr)1526 lease6_exists(const struct ipv6_pool *pool, const struct in6_addr *addr) {
1527 	struct iasubopt *test_iaaddr;
1528 
1529 	test_iaaddr = NULL;
1530 	if (iasubopt_hash_lookup(&test_iaaddr, pool->leases,
1531 				 (void *)addr, sizeof(*addr), MDL)) {
1532 		iasubopt_dereference(&test_iaaddr, MDL);
1533 		return ISC_TRUE;
1534 	} else {
1535 		return ISC_FALSE;
1536 	}
1537 }
1538 
1539 /*!
1540  *
1541  * \brief Check if address is available to a lease
1542  *
1543  * Determine if the address in the lease is available to that
1544  * lease.  Either the address isn't in use or it is in use
1545  * but by that lease.
1546  *
1547  * \param[in] lease = lease to check
1548  *
1549  * \return
1550  * ISC_TRUE  = The lease is allowed to use that address
1551  * ISC_FALSE = The lease isn't allowed to use that address
1552  */
1553 isc_boolean_t
lease6_usable(struct iasubopt * lease)1554 lease6_usable(struct iasubopt *lease) {
1555 	struct iasubopt *test_iaaddr;
1556 	isc_boolean_t status = ISC_TRUE;
1557 
1558 	test_iaaddr = NULL;
1559 	if (iasubopt_hash_lookup(&test_iaaddr, lease->ipv6_pool->leases,
1560 				 (void *)&lease->addr,
1561 				 sizeof(lease->addr), MDL)) {
1562 		if (test_iaaddr != lease) {
1563 			status = ISC_FALSE;
1564 		}
1565 		iasubopt_dereference(&test_iaaddr, MDL);
1566 	}
1567 
1568 	return (status);
1569 }
1570 
1571 /*
1572  * Put the lease on our active pool.
1573  */
1574 static isc_result_t
move_lease_to_active(struct ipv6_pool * pool,struct iasubopt * lease)1575 move_lease_to_active(struct ipv6_pool *pool, struct iasubopt *lease) {
1576 	isc_result_t insert_result;
1577 
1578 	insert_result = isc_heap_insert(pool->active_timeouts, lease);
1579 	if (insert_result == ISC_R_SUCCESS) {
1580        		iasubopt_hash_add(pool->leases, &lease->addr,
1581 				  sizeof(lease->addr), lease, MDL);
1582 		isc_heap_delete(pool->inactive_timeouts,
1583 				lease->inactive_index);
1584 		pool->num_active++;
1585 		pool->num_inactive--;
1586 		lease->state = FTS_ACTIVE;
1587 		if (pool->ipv6_pond)
1588 			pool->ipv6_pond->num_active++;
1589 
1590 	}
1591 	return insert_result;
1592 }
1593 
1594 /*!
1595  *
1596  * \brief Renew a lease in the pool.
1597  *
1598  * The hard_lifetime_end_time of the lease should be set to
1599  * the current expiration time.
1600  * The soft_lifetime_end_time of the lease should be set to
1601  * the desired expiration time.
1602  *
1603  * This routine will compare the two and call the correct
1604  * heap routine to move the lease.  If the lease is active
1605  * and the new expiration time is greater (the normal case)
1606  * then we call isc_heap_decreased() as a larger time is a
1607  * lower priority.  If the new expiration time is less then
1608  * we call isc_heap_increased().
1609  *
1610  * If the lease is abandoned then it will be on the active list
1611  * and we will always call isc_heap_increased() as the previous
1612  * expiration would have been all 1s (as close as we can get
1613  * to infinite).
1614  *
1615  * If the lease is moving to active we call that routine
1616  * which will move it from the inactive list to the active list.
1617  *
1618  * \param pool  = a pool the lease belongs to
1619  * \param lease = the lease to be renewed
1620  *
1621  * \return result of the renew operation (ISC_R_SUCCESS if successful,
1622            ISC_R_NOMEMORY when run out of memory)
1623  */
1624 isc_result_t
renew_lease6(struct ipv6_pool * pool,struct iasubopt * lease)1625 renew_lease6(struct ipv6_pool *pool, struct iasubopt *lease) {
1626 	time_t old_end_time = lease->hard_lifetime_end_time;
1627 	lease->hard_lifetime_end_time = lease->soft_lifetime_end_time;
1628 	lease->soft_lifetime_end_time = 0;
1629 
1630 	if (lease->state == FTS_ACTIVE) {
1631 		if (old_end_time <= lease->hard_lifetime_end_time) {
1632 			isc_heap_decreased(pool->active_timeouts,
1633 					   lease->active_index);
1634 		} else {
1635 			isc_heap_increased(pool->active_timeouts,
1636 					   lease->active_index);
1637 		}
1638 		return ISC_R_SUCCESS;
1639 	} else if (lease->state == FTS_ABANDONED) {
1640 		char tmp_addr[INET6_ADDRSTRLEN];
1641                 lease->state = FTS_ACTIVE;
1642                 isc_heap_increased(pool->active_timeouts, lease->active_index);
1643 		log_info("Reclaiming previously abandoned address %s",
1644 			 inet_ntop(AF_INET6, &(lease->addr), tmp_addr,
1645 				   sizeof(tmp_addr)));
1646 
1647 		pool->num_abandoned--;
1648 		if (pool->ipv6_pond)
1649 			pool->ipv6_pond->num_abandoned--;
1650 
1651                 return ISC_R_SUCCESS;
1652 	} else {
1653 		return move_lease_to_active(pool, lease);
1654 	}
1655 }
1656 
1657 /*
1658  * Put the lease on our inactive pool, with the specified state.
1659  */
1660 static isc_result_t
move_lease_to_inactive(struct ipv6_pool * pool,struct iasubopt * lease,binding_state_t state)1661 move_lease_to_inactive(struct ipv6_pool *pool, struct iasubopt *lease,
1662 		       binding_state_t state) {
1663 	isc_result_t insert_result;
1664 
1665 	insert_result = isc_heap_insert(pool->inactive_timeouts, lease);
1666 	if (insert_result == ISC_R_SUCCESS) {
1667 		/*
1668 		 * Handle expire and release statements
1669 		 * To get here we must be active and have done a commit so
1670 		 * we should run the proper statements if they exist, though
1671 		 * that will change when we remove the inactive heap.
1672 		 * In addition we get rid of the references for both as we
1673 		 * can only do one (expire or release) on a lease
1674 		 */
1675 		if (lease->on_star.on_expiry != NULL) {
1676 			if (state == FTS_EXPIRED) {
1677 				execute_statements(NULL, NULL, NULL,
1678 						   NULL, NULL, NULL,
1679 						   &lease->scope,
1680 						   lease->on_star.on_expiry,
1681 						   &lease->on_star);
1682 			}
1683 			executable_statement_dereference
1684 				(&lease->on_star.on_expiry, MDL);
1685 		}
1686 
1687 		if (lease->on_star.on_release != NULL) {
1688 			if (state == FTS_RELEASED) {
1689 				execute_statements(NULL, NULL, NULL,
1690 						   NULL, NULL, NULL,
1691 						   &lease->scope,
1692 						   lease->on_star.on_release,
1693 						   &lease->on_star);
1694 			}
1695 			executable_statement_dereference
1696 				(&lease->on_star.on_release, MDL);
1697 		}
1698 
1699 #if defined (NSUPDATE)
1700 		/* Process events upon expiration. */
1701 		if (pool->pool_type != D6O_IA_PD) {
1702 			(void) ddns_removals(NULL, lease, NULL, ISC_FALSE);
1703 		}
1704 #endif
1705 
1706 		/* Binding scopes are no longer valid after expiry or
1707 		 * release.
1708 		 */
1709 		if (lease->scope != NULL) {
1710 			binding_scope_dereference(&lease->scope, MDL);
1711 		}
1712 
1713 		iasubopt_hash_delete(pool->leases,
1714 				     &lease->addr, sizeof(lease->addr), MDL);
1715 		isc_heap_delete(pool->active_timeouts, lease->active_index);
1716 		lease->state = state;
1717 		pool->num_active--;
1718 		pool->num_inactive++;
1719 		if (pool->ipv6_pond)
1720 			pool->ipv6_pond->num_active--;
1721 
1722 		if (lease->state == FTS_ABANDONED) {
1723 			pool->num_abandoned--;
1724 			if (pool->ipv6_pond)
1725 				pool->ipv6_pond->num_abandoned--;
1726 		}
1727 	}
1728 	return insert_result;
1729 }
1730 
1731 /*
1732  * Expire the oldest lease if it's lifetime_end_time is
1733  * older than the given time.
1734  *
1735  * - leasep must be a pointer to a (struct iasubopt *) pointer previously
1736  *   initialized to NULL
1737  *
1738  * On return leasep has a reference to the removed entry. It is left
1739  * pointing to NULL if the oldest lease has not expired.
1740  */
1741 isc_result_t
expire_lease6(struct iasubopt ** leasep,struct ipv6_pool * pool,time_t now)1742 expire_lease6(struct iasubopt **leasep, struct ipv6_pool *pool, time_t now) {
1743 	struct iasubopt *tmp;
1744 	isc_result_t result;
1745 
1746 	if (leasep == NULL) {
1747 		log_error("%s(%d): NULL pointer reference", MDL);
1748 		return DHCP_R_INVALIDARG;
1749 	}
1750 	if (*leasep != NULL) {
1751 		log_error("%s(%d): non-NULL pointer", MDL);
1752 		return DHCP_R_INVALIDARG;
1753 	}
1754 
1755 	if (pool->num_active > 0) {
1756 		tmp = (struct iasubopt *)
1757 				isc_heap_element(pool->active_timeouts, 1);
1758 		if (now > tmp->hard_lifetime_end_time) {
1759 			result = move_lease_to_inactive(pool, tmp,
1760 							FTS_EXPIRED);
1761 			if (result == ISC_R_SUCCESS) {
1762 				iasubopt_reference(leasep, tmp, MDL);
1763 			}
1764 			return result;
1765 		}
1766 	}
1767 	return ISC_R_SUCCESS;
1768 }
1769 
1770 
1771 /*
1772  * For a declined lease, leave it on the "active" pool, but mark
1773  * it as declined. Give it an infinite (well, really long) life.
1774  */
1775 isc_result_t
decline_lease6(struct ipv6_pool * pool,struct iasubopt * lease)1776 decline_lease6(struct ipv6_pool *pool, struct iasubopt *lease) {
1777 	isc_result_t result;
1778 
1779 	if ((lease->state != FTS_ACTIVE) &&
1780 	    (lease->state != FTS_ABANDONED)) {
1781 		result = move_lease_to_active(pool, lease);
1782 		if (result != ISC_R_SUCCESS) {
1783 			return result;
1784 		}
1785 	}
1786 	lease->state = FTS_ABANDONED;
1787 
1788 	pool->num_abandoned++;
1789 	if (pool->ipv6_pond)
1790 		pool->ipv6_pond->num_abandoned++;
1791 
1792 	lease->hard_lifetime_end_time = MAX_TIME;
1793 	isc_heap_decreased(pool->active_timeouts, lease->active_index);
1794 	return ISC_R_SUCCESS;
1795 }
1796 
1797 /*
1798  * Put the returned lease on our inactive pool.
1799  */
1800 isc_result_t
release_lease6(struct ipv6_pool * pool,struct iasubopt * lease)1801 release_lease6(struct ipv6_pool *pool, struct iasubopt *lease) {
1802 	if (lease->state == FTS_ACTIVE) {
1803 		return move_lease_to_inactive(pool, lease, FTS_RELEASED);
1804 	} else {
1805 		return ISC_R_SUCCESS;
1806 	}
1807 }
1808 
1809 /*
1810  * Create a prefix by hashing the input, and using that for
1811  * the part subject to allocation.
1812  */
1813 void
build_prefix6(struct in6_addr * pref,const struct in6_addr * net_start_pref,int pool_bits,int pref_bits,const struct data_string * input)1814 build_prefix6(struct in6_addr *pref,
1815 	      const struct in6_addr *net_start_pref,
1816 	      int pool_bits, int pref_bits,
1817 	      const struct data_string *input) {
1818 	isc_md5_t ctx;
1819 	int net_bytes;
1820 	int i;
1821 	char *str;
1822 	const char *net_str;
1823 
1824 	/*
1825 	 * Use MD5 to get a nice 128 bit hash of the input.
1826 	 * Yes, we know MD5 isn't cryptographically sound.
1827 	 * No, we don't care.
1828 	 */
1829 	isc_md5_init(&ctx);
1830 	isc_md5_update(&ctx, input->data, input->len);
1831 	isc_md5_final(&ctx, (unsigned char *)pref);
1832 
1833 	/*
1834 	 * Copy the network bits over.
1835 	 */
1836 	str = (char *)pref;
1837 	net_str = (const char *)net_start_pref;
1838 	net_bytes = pool_bits / 8;
1839 	for (i = 0; i < net_bytes; i++) {
1840 		str[i] = net_str[i];
1841 	}
1842 	i = net_bytes;
1843 	switch (pool_bits % 8) {
1844 		case 1: str[i] = (str[i] & 0x7F) | (net_str[i] & 0x80); break;
1845 		case 2: str[i] = (str[i] & 0x3F) | (net_str[i] & 0xC0); break;
1846 		case 3: str[i] = (str[i] & 0x1F) | (net_str[i] & 0xE0); break;
1847 		case 4: str[i] = (str[i] & 0x0F) | (net_str[i] & 0xF0); break;
1848 		case 5: str[i] = (str[i] & 0x07) | (net_str[i] & 0xF8); break;
1849 		case 6: str[i] = (str[i] & 0x03) | (net_str[i] & 0xFC); break;
1850 		case 7: str[i] = (str[i] & 0x01) | (net_str[i] & 0xFE); break;
1851 	}
1852 	/*
1853 	 * Zero the remaining bits.
1854 	 */
1855 	net_bytes = pref_bits / 8;
1856 	for (i=net_bytes+1; i<16; i++) {
1857 		str[i] = 0;
1858 	}
1859 	i = net_bytes;
1860 	switch (pref_bits % 8) {
1861 		case 0: str[i] &= 0; break;
1862 		case 1: str[i] &= 0x80; break;
1863 		case 2: str[i] &= 0xC0; break;
1864 		case 3: str[i] &= 0xE0; break;
1865 		case 4: str[i] &= 0xF0; break;
1866 		case 5: str[i] &= 0xF8; break;
1867 		case 6: str[i] &= 0xFC; break;
1868 		case 7: str[i] &= 0xFE; break;
1869 	}
1870 }
1871 
1872 /*
1873  * Create a lease for the given prefix and client duid.
1874  *
1875  * - pool must be a pointer to a (struct ipv6_pool *) pointer previously
1876  *   initialized to NULL
1877  *
1878  * Right now we simply hash the DUID, and if we get a collision, we hash
1879  * again until we find a free prefix. We try this a fixed number of times,
1880  * to avoid getting stuck in a loop (this is important on small pools
1881  * where we can run out of space).
1882  *
1883  * We return the number of attempts that it took to find an available
1884  * prefix. This tells callers when a pool is are filling up, as
1885  * well as an indication of how full the pool is; statistically the
1886  * more full a pool is the more attempts must be made before finding
1887  * a free prefix. Realistically this will only happen in very full
1888  * pools.
1889  *
1890  * We probably want different algorithms depending on the network size, in
1891  * the long term.
1892  */
1893 isc_result_t
create_prefix6(struct ipv6_pool * pool,struct iasubopt ** pref,unsigned int * attempts,const struct data_string * uid,time_t soft_lifetime_end_time)1894 create_prefix6(struct ipv6_pool *pool, struct iasubopt **pref,
1895 	       unsigned int *attempts,
1896 	       const struct data_string *uid,
1897 	       time_t soft_lifetime_end_time) {
1898 	struct data_string ds;
1899 	struct in6_addr tmp;
1900 	struct iasubopt *test_iapref;
1901 	struct data_string new_ds;
1902 	struct iasubopt *iapref;
1903 	isc_result_t result;
1904 
1905 	/*
1906 	 * Use the UID as our initial seed for the hash
1907 	 */
1908 	memset(&ds, 0, sizeof(ds));
1909 	data_string_copy(&ds, (struct data_string *)uid, MDL);
1910 
1911 	*attempts = 0;
1912 	for (;;) {
1913 		/*
1914 		 * Give up at some point.
1915 		 */
1916 		if (++(*attempts) > 10) {
1917 			data_string_forget(&ds, MDL);
1918 			return ISC_R_NORESOURCES;
1919 		}
1920 
1921 		/*
1922 		 * Build a prefix
1923 		 */
1924 		build_prefix6(&tmp, &pool->start_addr,
1925 			      pool->bits, pool->units, &ds);
1926 
1927 		/*
1928 		 * If this prefix is not in use, we're happy with it
1929 		 */
1930 		test_iapref = NULL;
1931 		if (iasubopt_hash_lookup(&test_iapref, pool->leases,
1932 					 &tmp, sizeof(tmp), MDL) == 0) {
1933 			break;
1934 		}
1935 		iasubopt_dereference(&test_iapref, MDL);
1936 
1937 		/*
1938 		 * Otherwise, we create a new input, adding the prefix
1939 		 */
1940 		memset(&new_ds, 0, sizeof(new_ds));
1941 		new_ds.len = ds.len + sizeof(tmp);
1942 		if (!buffer_allocate(&new_ds.buffer, new_ds.len, MDL)) {
1943 			data_string_forget(&ds, MDL);
1944 			return ISC_R_NOMEMORY;
1945 		}
1946 		new_ds.data = new_ds.buffer->data;
1947 		memcpy(new_ds.buffer->data, ds.data, ds.len);
1948 		memcpy(&new_ds.buffer->data[0] + ds.len, &tmp, sizeof(tmp));
1949 		data_string_forget(&ds, MDL);
1950 		data_string_copy(&ds, &new_ds, MDL);
1951 		data_string_forget(&new_ds, MDL);
1952 	}
1953 
1954 	data_string_forget(&ds, MDL);
1955 
1956 	/*
1957 	 * We're happy with the prefix, create an IAPREFIX
1958 	 * to hold it.
1959 	 */
1960 	iapref = NULL;
1961 	result = iasubopt_allocate(&iapref, MDL);
1962 	if (result != ISC_R_SUCCESS) {
1963 		return result;
1964 	}
1965 	iapref->plen = (u_int8_t)pool->units;
1966 	memcpy(&iapref->addr, &tmp, sizeof(iapref->addr));
1967 
1968 	/*
1969 	 * Add the prefix to the pool (note state is free, not active?!).
1970 	 */
1971 	result = add_lease6(pool, iapref, soft_lifetime_end_time);
1972 	if (result == ISC_R_SUCCESS) {
1973 		iasubopt_reference(pref, iapref, MDL);
1974 	}
1975 	iasubopt_dereference(&iapref, MDL);
1976 	return result;
1977 }
1978 
1979 /*
1980  * Determine if a prefix is present in a pool or not.
1981  */
1982 isc_boolean_t
prefix6_exists(const struct ipv6_pool * pool,const struct in6_addr * pref,u_int8_t plen)1983 prefix6_exists(const struct ipv6_pool *pool,
1984 	       const struct in6_addr *pref, u_int8_t plen) {
1985 	struct iasubopt *test_iapref;
1986 
1987 	if ((int)plen != pool->units)
1988 		return ISC_FALSE;
1989 
1990 	test_iapref = NULL;
1991 	if (iasubopt_hash_lookup(&test_iapref, pool->leases,
1992 				 (void *)pref, sizeof(*pref), MDL)) {
1993 		iasubopt_dereference(&test_iapref, MDL);
1994 		return ISC_TRUE;
1995 	} else {
1996 		return ISC_FALSE;
1997 	}
1998 }
1999 
2000 /*
2001  * Mark an IPv6 address/prefix as unavailable from a pool.
2002  *
2003  * This is used for host entries and the addresses of the server itself.
2004  */
2005 isc_result_t
mark_lease_unavailable(struct ipv6_pool * pool,const struct in6_addr * addr)2006 mark_lease_unavailable(struct ipv6_pool *pool, const struct in6_addr *addr) {
2007 	struct iasubopt *dummy_iasubopt;
2008 	isc_result_t result;
2009 
2010 	dummy_iasubopt = NULL;
2011 	result = iasubopt_allocate(&dummy_iasubopt, MDL);
2012 	if (result == ISC_R_SUCCESS) {
2013 		dummy_iasubopt->addr = *addr;
2014 		iasubopt_hash_add(pool->leases, &dummy_iasubopt->addr,
2015 				  sizeof(*addr), dummy_iasubopt, MDL);
2016 	}
2017 	return result;
2018 }
2019 
2020 /*
2021  * Add a pool.
2022  */
2023 isc_result_t
add_ipv6_pool(struct ipv6_pool * pool)2024 add_ipv6_pool(struct ipv6_pool *pool) {
2025 	struct ipv6_pool **new_pools;
2026 
2027 	new_pools = dmalloc(sizeof(struct ipv6_pool *) * (num_pools+1), MDL);
2028 	if (new_pools == NULL) {
2029 		return ISC_R_NOMEMORY;
2030 	}
2031 
2032 	if (num_pools > 0) {
2033 		memcpy(new_pools, pools,
2034 		       sizeof(struct ipv6_pool *) * num_pools);
2035 		dfree(pools, MDL);
2036 	}
2037 	pools = new_pools;
2038 
2039 	pools[num_pools] = NULL;
2040 	ipv6_pool_reference(&pools[num_pools], pool, MDL);
2041 	num_pools++;
2042 	return ISC_R_SUCCESS;
2043 }
2044 
2045 static void
cleanup_old_expired(struct ipv6_pool * pool)2046 cleanup_old_expired(struct ipv6_pool *pool) {
2047 	struct iasubopt *tmp;
2048 	struct ia_xx *ia;
2049 	struct ia_xx *ia_active;
2050 	unsigned char *tmpd;
2051 	time_t timeout;
2052 
2053 	while (pool->num_inactive > 0) {
2054 		tmp = (struct iasubopt *)
2055 				isc_heap_element(pool->inactive_timeouts, 1);
2056 		if (tmp->hard_lifetime_end_time != 0) {
2057 			timeout = tmp->hard_lifetime_end_time;
2058 			timeout += EXPIRED_IPV6_CLEANUP_TIME;
2059 		} else {
2060 			timeout = tmp->soft_lifetime_end_time;
2061 		}
2062 		if (cur_time < timeout) {
2063 			break;
2064 		}
2065 
2066 		isc_heap_delete(pool->inactive_timeouts, tmp->inactive_index);
2067 		pool->num_inactive--;
2068 
2069 		if (tmp->ia != NULL) {
2070 			/*
2071 			 * Check to see if this IA is in an active list,
2072 			 * but has no remaining resources. If so, remove it
2073 			 * from the active list.
2074 			 */
2075 			ia = NULL;
2076 			ia_reference(&ia, tmp->ia, MDL);
2077 			ia_remove_iasubopt(ia, tmp, MDL);
2078 			ia_active = NULL;
2079 			tmpd = (unsigned char *)ia->iaid_duid.data;
2080 			if ((ia->ia_type == D6O_IA_NA) &&
2081 			    (ia->num_iasubopt <= 0) &&
2082 			    (ia_hash_lookup(&ia_active, ia_na_active, tmpd,
2083 					    ia->iaid_duid.len, MDL) == 0) &&
2084 			    (ia_active == ia)) {
2085 				ia_hash_delete(ia_na_active, tmpd,
2086 					       ia->iaid_duid.len, MDL);
2087 			}
2088 			if ((ia->ia_type == D6O_IA_TA) &&
2089 			    (ia->num_iasubopt <= 0) &&
2090 			    (ia_hash_lookup(&ia_active, ia_ta_active, tmpd,
2091 					    ia->iaid_duid.len, MDL) == 0) &&
2092 			    (ia_active == ia)) {
2093 				ia_hash_delete(ia_ta_active, tmpd,
2094 					       ia->iaid_duid.len, MDL);
2095 			}
2096 			if ((ia->ia_type == D6O_IA_PD) &&
2097 			    (ia->num_iasubopt <= 0) &&
2098 			    (ia_hash_lookup(&ia_active, ia_pd_active, tmpd,
2099 					    ia->iaid_duid.len, MDL) == 0) &&
2100 			    (ia_active == ia)) {
2101 				ia_hash_delete(ia_pd_active, tmpd,
2102 					       ia->iaid_duid.len, MDL);
2103 			}
2104 			ia_dereference(&ia, MDL);
2105 		}
2106 		iasubopt_dereference(&tmp, MDL);
2107 	}
2108 }
2109 
2110 static void
lease_timeout_support(void * vpool)2111 lease_timeout_support(void *vpool) {
2112 	struct ipv6_pool *pool;
2113 	struct iasubopt *lease;
2114 
2115 	pool = (struct ipv6_pool *)vpool;
2116 	for (;;) {
2117 		/*
2118 		 * Get the next lease scheduled to expire.
2119 		 *
2120 		 * Note that if there are no leases in the pool,
2121 		 * expire_lease6() will return ISC_R_SUCCESS with
2122 		 * a NULL lease.
2123 		 *
2124 		 * expire_lease6() will call move_lease_to_inactive() which
2125 		 * calls ddns_removals() do we want that on the standard
2126 		 * expiration timer or a special 'depref' timer?  Original
2127 		 * query from DH, moved here by SAR.
2128 		 */
2129 		lease = NULL;
2130 		if (expire_lease6(&lease, pool, cur_time) != ISC_R_SUCCESS) {
2131 			break;
2132 		}
2133 		if (lease == NULL) {
2134 			break;
2135 		}
2136 
2137 		write_ia(lease->ia);
2138 
2139 		iasubopt_dereference(&lease, MDL);
2140 	}
2141 
2142 	/*
2143 	 * If appropriate commit and rotate the lease file
2144 	 * As commit_leases_timed() checks to see if we've done any writes
2145 	 * we don't bother tracking if this function called write _ia
2146 	 */
2147 	(void) commit_leases_timed();
2148 
2149 	/*
2150 	 * Do some cleanup of our expired leases.
2151 	 */
2152 	cleanup_old_expired(pool);
2153 
2154 	/*
2155 	 * Schedule next round of expirations.
2156 	 */
2157 	schedule_lease_timeout(pool);
2158 }
2159 
2160 /*
2161  * For a given pool, add a timer that will remove the next
2162  * lease to expire.
2163  */
2164 void
schedule_lease_timeout(struct ipv6_pool * pool)2165 schedule_lease_timeout(struct ipv6_pool *pool) {
2166 	struct iasubopt *tmp;
2167 	time_t timeout;
2168 	time_t next_timeout;
2169 	struct timeval tv;
2170 
2171 	next_timeout = MAX_TIME;
2172 
2173 	if (pool->num_active > 0) {
2174 		tmp = (struct iasubopt *)
2175 				isc_heap_element(pool->active_timeouts, 1);
2176 		if (tmp->hard_lifetime_end_time < next_timeout) {
2177 			next_timeout = tmp->hard_lifetime_end_time + 1;
2178 		}
2179 	}
2180 
2181 	if (pool->num_inactive > 0) {
2182 		tmp = (struct iasubopt *)
2183 				isc_heap_element(pool->inactive_timeouts, 1);
2184 		if (tmp->hard_lifetime_end_time != 0) {
2185 			timeout = tmp->hard_lifetime_end_time;
2186 			timeout += EXPIRED_IPV6_CLEANUP_TIME;
2187 		} else {
2188 			timeout = tmp->soft_lifetime_end_time + 1;
2189 		}
2190 		if (timeout < next_timeout) {
2191 			next_timeout = timeout;
2192 		}
2193 	}
2194 
2195 	if (next_timeout < MAX_TIME) {
2196 		tv.tv_sec = next_timeout;
2197 		tv.tv_usec = 0;
2198 		add_timeout(&tv, lease_timeout_support, pool,
2199 			    (tvref_t)ipv6_pool_reference,
2200 			    (tvunref_t)ipv6_pool_dereference);
2201 	}
2202 }
2203 
2204 /*
2205  * Schedule timeouts across all pools.
2206  */
2207 void
schedule_all_ipv6_lease_timeouts(void)2208 schedule_all_ipv6_lease_timeouts(void) {
2209 	int i;
2210 
2211 	for (i=0; i<num_pools; i++) {
2212 		schedule_lease_timeout(pools[i]);
2213 	}
2214 }
2215 
2216 /*
2217  * Given an address and the length of the network mask, return
2218  * only the network portion.
2219  *
2220  * Examples:
2221  *
2222  *   "fe80::216:6fff:fe49:7d9b", length 64 = "fe80::"
2223  *   "2001:888:1936:2:216:6fff:fe49:7d9b", length 48 = "2001:888:1936::"
2224  */
2225 static void
ipv6_network_portion(struct in6_addr * result,const struct in6_addr * addr,int bits)2226 ipv6_network_portion(struct in6_addr *result,
2227 		     const struct in6_addr *addr, int bits) {
2228 	unsigned char *addrp;
2229 	int mask_bits;
2230 	int bytes;
2231 	int extra_bits;
2232 	int i;
2233 
2234 	static const unsigned char bitmasks[] = {
2235 		0x00, 0xFE, 0xFC, 0xF8,
2236 		0xF0, 0xE0, 0xC0, 0x80,
2237 	};
2238 
2239 	/*
2240 	 *  Sanity check our bits. ;)
2241 	 */
2242 	if ((bits < 0) || (bits > 128)) {
2243 		log_fatal("ipv6_network_portion: bits %d not between 0 and 128",
2244 			  bits);
2245 	}
2246 
2247 	/*
2248 	 * Copy our address portion.
2249 	 */
2250 	*result = *addr;
2251 	addrp = ((unsigned char *)result) + 15;
2252 
2253 	/*
2254 	 * Zero out masked portion.
2255 	 */
2256 	mask_bits = 128 - bits;
2257 	bytes = mask_bits / 8;
2258 	extra_bits = mask_bits % 8;
2259 
2260 	for (i=0; i<bytes; i++) {
2261 		*addrp = 0;
2262 		addrp--;
2263 	}
2264 	if (extra_bits) {
2265 		*addrp &= bitmasks[extra_bits];
2266 	}
2267 }
2268 
2269 /*
2270  * Determine if the given address/prefix is in the pool.
2271  */
2272 isc_boolean_t
ipv6_in_pool(const struct in6_addr * addr,const struct ipv6_pool * pool)2273 ipv6_in_pool(const struct in6_addr *addr, const struct ipv6_pool *pool) {
2274 	struct in6_addr tmp;
2275 
2276 	ipv6_network_portion(&tmp, addr, pool->bits);
2277 	if (memcmp(&tmp, &pool->start_addr, sizeof(tmp)) == 0) {
2278 		return ISC_TRUE;
2279 	} else {
2280 		return ISC_FALSE;
2281 	}
2282 }
2283 
2284 /*
2285  * Find the pool that contains the given address.
2286  *
2287  * - pool must be a pointer to a (struct ipv6_pool *) pointer previously
2288  *   initialized to NULL
2289  */
2290 isc_result_t
find_ipv6_pool(struct ipv6_pool ** pool,u_int16_t type,const struct in6_addr * addr)2291 find_ipv6_pool(struct ipv6_pool **pool, u_int16_t type,
2292 	       const struct in6_addr *addr) {
2293 	int i;
2294 
2295 	if (pool == NULL) {
2296 		log_error("%s(%d): NULL pointer reference", MDL);
2297 		return DHCP_R_INVALIDARG;
2298 	}
2299 	if (*pool != NULL) {
2300 		log_error("%s(%d): non-NULL pointer", MDL);
2301 		return DHCP_R_INVALIDARG;
2302 	}
2303 
2304 	for (i=0; i<num_pools; i++) {
2305 		if (pools[i]->pool_type != type)
2306 			continue;
2307 		if (ipv6_in_pool(addr, pools[i])) {
2308 			ipv6_pool_reference(pool, pools[i], MDL);
2309 			return ISC_R_SUCCESS;
2310 		}
2311 	}
2312 	return ISC_R_NOTFOUND;
2313 }
2314 
2315 /*
2316  * Helper function for the various functions that act across all
2317  * pools.
2318  */
2319 static isc_result_t
change_leases(struct ia_xx * ia,isc_result_t (* change_func)(struct ipv6_pool *,struct iasubopt *))2320 change_leases(struct ia_xx *ia,
2321 	      isc_result_t (*change_func)(struct ipv6_pool *,
2322 					  struct iasubopt *)) {
2323 	isc_result_t retval;
2324 	isc_result_t renew_retval;
2325 	struct ipv6_pool *pool;
2326 	struct in6_addr *addr;
2327 	int i;
2328 
2329 	retval = ISC_R_SUCCESS;
2330 	for (i=0; i<ia->num_iasubopt; i++) {
2331 		pool = NULL;
2332 		addr = &ia->iasubopt[i]->addr;
2333 		if (find_ipv6_pool(&pool, ia->ia_type,
2334 				   addr) == ISC_R_SUCCESS) {
2335 			renew_retval = change_func(pool, ia->iasubopt[i]);
2336 			if (renew_retval != ISC_R_SUCCESS) {
2337 				retval = renew_retval;
2338 			}
2339 		}
2340 		/* XXXsk: should we warn if we don't find a pool? */
2341 	}
2342 	return retval;
2343 }
2344 
2345 /*
2346  * Renew all leases in an IA from all pools.
2347  *
2348  * The new lifetime should be in the soft_lifetime_end_time
2349  * and will be moved to hard_lifetime_end_time by renew_lease6.
2350  */
2351 isc_result_t
renew_leases(struct ia_xx * ia)2352 renew_leases(struct ia_xx *ia) {
2353 	return change_leases(ia, renew_lease6);
2354 }
2355 
2356 /*
2357  * Release all leases in an IA from all pools.
2358  */
2359 isc_result_t
release_leases(struct ia_xx * ia)2360 release_leases(struct ia_xx *ia) {
2361 	return change_leases(ia, release_lease6);
2362 }
2363 
2364 /*
2365  * Decline all leases in an IA from all pools.
2366  */
2367 isc_result_t
decline_leases(struct ia_xx * ia)2368 decline_leases(struct ia_xx *ia) {
2369 	return change_leases(ia, decline_lease6);
2370 }
2371 
2372 #ifdef DHCPv6
2373 /*
2374  * Helper function to output leases.
2375  */
2376 static int write_error;
2377 
2378 static isc_result_t
write_ia_leases(const void * name,unsigned len,void * value)2379 write_ia_leases(const void *name, unsigned len, void *value) {
2380 	struct ia_xx *ia = (struct ia_xx *)value;
2381 
2382 	if (!write_error) {
2383 		if (!write_ia(ia)) {
2384 			write_error = 1;
2385 		}
2386 	}
2387 	return ISC_R_SUCCESS;
2388 }
2389 
2390 /*
2391  * Write all DHCPv6 information.
2392  */
2393 int
write_leases6(void)2394 write_leases6(void) {
2395 	int nas, tas, pds;
2396 
2397 	write_error = 0;
2398 	write_server_duid();
2399 	nas = ia_hash_foreach(ia_na_active, write_ia_leases);
2400 	if (write_error) {
2401 		return 0;
2402 	}
2403 	tas = ia_hash_foreach(ia_ta_active, write_ia_leases);
2404 	if (write_error) {
2405 		return 0;
2406 	}
2407 	pds = ia_hash_foreach(ia_pd_active, write_ia_leases);
2408 	if (write_error) {
2409 		return 0;
2410 	}
2411 
2412 	log_info("Wrote %d NA, %d TA, %d PD leases to lease file.",
2413 		 nas, tas, pds);
2414 	return 1;
2415 }
2416 #endif /* DHCPv6 */
2417 
2418 static isc_result_t
mark_hosts_unavailable_support(const void * name,unsigned len,void * value)2419 mark_hosts_unavailable_support(const void *name, unsigned len, void *value) {
2420 	struct host_decl *h;
2421 	struct data_string fixed_addr;
2422 	struct in6_addr addr;
2423 	struct ipv6_pool *p;
2424 
2425 	h = (struct host_decl *)value;
2426 
2427 	/*
2428 	 * If the host has no address, we don't need to mark anything.
2429 	 */
2430 	if (h->fixed_addr == NULL) {
2431 		return ISC_R_SUCCESS;
2432 	}
2433 
2434 	/*
2435 	 * Evaluate the fixed address.
2436 	 */
2437 	memset(&fixed_addr, 0, sizeof(fixed_addr));
2438 	if (!evaluate_option_cache(&fixed_addr, NULL, NULL, NULL, NULL, NULL,
2439 				   &global_scope, h->fixed_addr, MDL)) {
2440 		log_error("mark_hosts_unavailable: "
2441 			  "error evaluating host address.");
2442 		return ISC_R_SUCCESS;
2443 	}
2444 	if (fixed_addr.len != 16) {
2445 		log_error("mark_hosts_unavailable: "
2446 			  "host address is not 128 bits.");
2447 		return ISC_R_SUCCESS;
2448 	}
2449 	memcpy(&addr, fixed_addr.data, 16);
2450 	data_string_forget(&fixed_addr, MDL);
2451 
2452 	/*
2453 	 * Find the pool holding this host, and mark the address.
2454 	 * (I suppose it is arguably valid to have a host that does not
2455 	 * sit in any pool.)
2456 	 */
2457 	p = NULL;
2458 	if (find_ipv6_pool(&p, D6O_IA_NA, &addr) == ISC_R_SUCCESS) {
2459 		mark_lease_unavailable(p, &addr);
2460 		ipv6_pool_dereference(&p, MDL);
2461 	}
2462 	if (find_ipv6_pool(&p, D6O_IA_TA, &addr) == ISC_R_SUCCESS) {
2463 		mark_lease_unavailable(p, &addr);
2464 		ipv6_pool_dereference(&p, MDL);
2465 	}
2466 
2467 	return ISC_R_SUCCESS;
2468 }
2469 
2470 void
mark_hosts_unavailable(void)2471 mark_hosts_unavailable(void) {
2472 	hash_foreach(host_name_hash, mark_hosts_unavailable_support);
2473 }
2474 
2475 static isc_result_t
mark_phosts_unavailable_support(const void * name,unsigned len,void * value)2476 mark_phosts_unavailable_support(const void *name, unsigned len, void *value) {
2477 	struct host_decl *h;
2478 	struct iaddrcidrnetlist *l;
2479 	struct in6_addr pref;
2480 	struct ipv6_pool *p;
2481 
2482 	h = (struct host_decl *)value;
2483 
2484 	/*
2485 	 * If the host has no prefix, we don't need to mark anything.
2486 	 */
2487 	if (h->fixed_prefix == NULL) {
2488 		return ISC_R_SUCCESS;
2489 	}
2490 
2491 	/*
2492 	 * Get the fixed prefixes.
2493 	 */
2494 	for (l = h->fixed_prefix; l != NULL; l = l->next) {
2495 		if (l->cidrnet.lo_addr.len != 16) {
2496 			continue;
2497 		}
2498 		memcpy(&pref, l->cidrnet.lo_addr.iabuf, 16);
2499 
2500 		/*
2501 		 * Find the pool holding this host, and mark the prefix.
2502 		 * (I suppose it is arguably valid to have a host that does not
2503 		 * sit in any pool.)
2504 		 */
2505 		p = NULL;
2506 		if (find_ipv6_pool(&p, D6O_IA_PD, &pref) != ISC_R_SUCCESS) {
2507 			continue;
2508 		}
2509 		if (l->cidrnet.bits != p->units) {
2510 			ipv6_pool_dereference(&p, MDL);
2511 			continue;
2512 		}
2513 		mark_lease_unavailable(p, &pref);
2514 		ipv6_pool_dereference(&p, MDL);
2515 	}
2516 
2517 	return ISC_R_SUCCESS;
2518 }
2519 
2520 void
mark_phosts_unavailable(void)2521 mark_phosts_unavailable(void) {
2522 	hash_foreach(host_name_hash, mark_phosts_unavailable_support);
2523 }
2524 
2525 void
mark_interfaces_unavailable(void)2526 mark_interfaces_unavailable(void) {
2527 	struct interface_info *ip;
2528 	int i;
2529 	struct ipv6_pool *p;
2530 
2531 	ip = interfaces;
2532 	while (ip != NULL) {
2533 		for (i=0; i<ip->v6address_count; i++) {
2534 			p = NULL;
2535 			if (find_ipv6_pool(&p, D6O_IA_NA, &ip->v6addresses[i])
2536 							== ISC_R_SUCCESS) {
2537 				mark_lease_unavailable(p,
2538 						       &ip->v6addresses[i]);
2539 				ipv6_pool_dereference(&p, MDL);
2540 			}
2541 			if (find_ipv6_pool(&p, D6O_IA_TA, &ip->v6addresses[i])
2542 							== ISC_R_SUCCESS) {
2543 				mark_lease_unavailable(p,
2544 						       &ip->v6addresses[i]);
2545 				ipv6_pool_dereference(&p, MDL);
2546 			}
2547 		}
2548 		ip = ip->next;
2549 	}
2550 }
2551 
2552 /*!
2553  * \brief Create a new IPv6 pond structure.
2554  *
2555  * Allocate space for a new ipv6_pond structure and return a reference
2556  * to it, includes setting the reference count to 1.
2557  *
2558  * \param pond = space for returning a referenced pointer to the pond.
2559  *		 This must point to a space that has been initialzied
2560  *		 to NULL by the caller.
2561  *
2562  * \return
2563  * ISC_R_SUCCESS     = The pond was successfully created, pond points to it.
2564  * DHCP_R_INVALIDARG = One of the arugments was invalid, pond has not been
2565  *		       modified
2566  * ISC_R_NOMEMORY    = The system wasn't able to allocate memory, pond has
2567  *		       not been modified.
2568  */
2569 isc_result_t
ipv6_pond_allocate(struct ipv6_pond ** pond,const char * file,int line)2570 ipv6_pond_allocate(struct ipv6_pond **pond, const char *file, int line) {
2571 	struct ipv6_pond *tmp;
2572 
2573 	if (pond == NULL) {
2574 		log_error("%s(%d): NULL pointer reference", file, line);
2575 		return DHCP_R_INVALIDARG;
2576 	}
2577 	if (*pond != NULL) {
2578 		log_error("%s(%d): non-NULL pointer", file, line);
2579 		return DHCP_R_INVALIDARG;
2580 	}
2581 
2582 	tmp = dmalloc(sizeof(*tmp), file, line);
2583 	if (tmp == NULL) {
2584 		return ISC_R_NOMEMORY;
2585 	}
2586 
2587 	tmp->refcnt = 1;
2588 
2589 	*pond = tmp;
2590 	return ISC_R_SUCCESS;
2591 }
2592 
2593 /*!
2594  *
2595  * \brief reference an IPv6 pond structure.
2596  *
2597  * This function genreates a reference to an ipv6_pond structure
2598  * and increments the reference count on the structure.
2599  *
2600  * \param[out] pond = space for returning a referenced pointer to the pond.
2601  *		      This must point to a space that has been initialzied
2602  *		      to NULL by the caller.
2603  * \param[in]  src  = A pointer to the pond to reference.  This must not be
2604  *		      NULL.
2605  *
2606  * \return
2607  * ISC_R_SUCCESS     = The pond was successfully referenced, pond now points
2608  *		       to src.
2609  * DHCP_R_INVALIDARG = One of the arugments was invalid, pond has not been
2610  *		       modified.
2611  */
2612 isc_result_t
ipv6_pond_reference(struct ipv6_pond ** pond,struct ipv6_pond * src,const char * file,int line)2613 ipv6_pond_reference(struct ipv6_pond **pond, struct ipv6_pond *src,
2614 		    const char *file, int line) {
2615 	if (pond == NULL) {
2616 		log_error("%s(%d): NULL pointer reference", file, line);
2617 		return DHCP_R_INVALIDARG;
2618 	}
2619 	if (*pond != NULL) {
2620 		log_error("%s(%d): non-NULL pointer", file, line);
2621 		return DHCP_R_INVALIDARG;
2622 	}
2623 	if (src == NULL) {
2624 		log_error("%s(%d): NULL pointer reference", file, line);
2625 		return DHCP_R_INVALIDARG;
2626 	}
2627 	*pond = src;
2628 	src->refcnt++;
2629 	return ISC_R_SUCCESS;
2630 }
2631 
2632 /*!
2633  *
2634  * \brief de-reference an IPv6 pond structure.
2635  *
2636  * This function decrements the reference count in an ipv6_pond structure.
2637  * If this was the last reference then the memory for the structure is
2638  * freed.
2639  *
2640  * \param[in] pond = A pointer to the pointer to the pond that should be
2641  *		     de-referenced.  On success the pointer to the pond
2642  *		     is cleared.  It must not be NULL and must not point
2643  *		     to NULL.
2644  *
2645  * \return
2646  * ISC_R_SUCCESS     = The pond was successfully de-referenced, pond now points
2647  *		       to NULL
2648  * DHCP_R_INVALIDARG = One of the arugments was invalid, pond has not been
2649  *		       modified.
2650  */
2651 
2652 isc_result_t
ipv6_pond_dereference(struct ipv6_pond ** pond,const char * file,int line)2653 ipv6_pond_dereference(struct ipv6_pond **pond, const char *file, int line) {
2654 	struct ipv6_pond *tmp;
2655 
2656 	if ((pond == NULL) || (*pond == NULL)) {
2657 		log_error("%s(%d): NULL pointer", file, line);
2658 		return DHCP_R_INVALIDARG;
2659 	}
2660 
2661 	tmp = *pond;
2662 	*pond = NULL;
2663 
2664 	tmp->refcnt--;
2665 	if (tmp->refcnt < 0) {
2666 		log_error("%s(%d): negative refcnt", file, line);
2667 		tmp->refcnt = 0;
2668 	}
2669 	if (tmp->refcnt == 0) {
2670 		dfree(tmp, file, line);
2671 	}
2672 
2673 	return ISC_R_SUCCESS;
2674 }
2675 
2676 #ifdef EUI_64
2677 /*
2678  * Enables/disables EUI-64 address assignment for a pond
2679  *
2680  * Excecutes statements down to the pond's scope and sets the pond's
2681  * use_eui_64 flag accordingly. In addition it iterates over the
2682  * pond's pools ensuring they are all /64.  Anything else is deemed
2683  * invalid for EUI-64.  It returns the number of invalid pools
2684  * detected.  This is done post-parsing as use-eui-64 can be set
2685  * down to the pool scope and we can't reliably do it until the
2686  * entire configuration has been parsed.
2687  */
2688 int
set_eui_64(struct ipv6_pond * pond)2689 set_eui_64(struct ipv6_pond *pond) {
2690 	int invalid_cnt = 0;
2691 	struct option_state* options = NULL;
2692 	struct option_cache *oc = NULL;
2693 	option_state_allocate(&options, MDL);
2694 	execute_statements_in_scope(NULL, NULL, NULL, NULL, NULL, options,
2695 				    &global_scope, pond->group, NULL, NULL);
2696 
2697 	pond->use_eui_64 =
2698 		((oc = lookup_option(&server_universe, options, SV_USE_EUI_64))
2699 		 &&
2700 		 (evaluate_boolean_option_cache (NULL, NULL, NULL, NULL,
2701 						 options, NULL, &global_scope,
2702 						 oc, MDL)));
2703 	if (pond->use_eui_64) {
2704 		// Check all pools are valid
2705 		int i = 0;
2706 		struct ipv6_pool* p;
2707 		while((p = pond->ipv6_pools[i++]) != NULL) {
2708 			if (p->bits != 64) {
2709 				log_error("Pool %s/%d cannot use EUI-64,"
2710 					  " prefix must 64",
2711 					  pin6_addr(&p->start_addr), p->bits);
2712 				invalid_cnt++;
2713 			} else {
2714 				log_debug("Pool: %s/%d - will use EUI-64",
2715 					  pin6_addr(&p->start_addr), p->bits);
2716 			}
2717 		}
2718 	}
2719 
2720         /* Don't need the options anymore. */
2721         option_state_dereference(&options, MDL);
2722 	return (invalid_cnt);
2723 }
2724 #endif
2725 
2726 /*
2727  * Emits a log for each pond that has been flagged as being a "jumbo range"
2728  * A pond is considered a "jumbo range" when the total number of elements
2729  * exceeds the maximum value of POND_TRACK_MAX (currently maximum value
2730  * that can be stored by ipv6_pond.num_total).  Since we disable threshold
2731  * logging for jumbo ranges, we need to report this to the user.  This
2732  * function allows us to report jumbo ponds after config parsing, so the
2733  * logs can be seen both on the console (-T) and the log facility (i.e syslog).
2734  *
2735  * Note, threshold logging is done at the pond level, so we need emit a list
2736  * of the addresses ranges of the pools in the pond affected.
2737  */
2738 void
report_jumbo_ranges()2739 report_jumbo_ranges() {
2740 	struct shared_network* s;
2741 	char log_buf[1084];
2742 #ifdef EUI_64
2743 	int invalid_cnt = 0;
2744 #endif
2745 
2746 	/* Loop thru all the networks looking for jumbo range ponds */
2747 	for (s = shared_networks; s; s = s -> next) {
2748 		struct ipv6_pond* pond = s->ipv6_pond;
2749 		while (pond) {
2750 #ifdef EUI_64
2751 			/* while we're here, set the pond's use_eui_64 flag */
2752 			invalid_cnt += set_eui_64(pond);
2753 #endif
2754 			/* if its a jumbo and has pools(sanity check) */
2755 			if (pond->jumbo_range == 1 && (pond->ipv6_pools)) {
2756 				struct ipv6_pool* pool;
2757 				char *bufptr = log_buf;
2758 				size_t space_left = sizeof(log_buf) - 1;
2759 				int i = 0;
2760 				int used = 0;
2761 
2762 				/* Build list containing the start-address/CIDR
2763 				 * of each pool */
2764 				*bufptr = '\0';
2765 				while ((pool = pond->ipv6_pools[i++]) &&
2766 				        (space_left > (INET6_ADDRSTRLEN + 6))) {
2767 					/* more than one so add a comma */
2768 					if (i > 1) {
2769 						*bufptr++ = ',';
2770 						*bufptr++ = ' ';
2771 						*bufptr = '\0';
2772 						space_left -= 2;
2773 					}
2774 
2775 					/* add the address */
2776 					inet_ntop(AF_INET6, &pool->start_addr,
2777 						  bufptr, INET6_ADDRSTRLEN);
2778 
2779 					used = strlen(bufptr);
2780 					bufptr += used;
2781 					space_left -= used;
2782 
2783 					/* add the CIDR */
2784 					sprintf (bufptr, "/%d",pool->bits);
2785 					used = strlen(bufptr);
2786 					bufptr += used;
2787 					space_left -= used;
2788 					*bufptr = '\0';
2789 				}
2790 
2791 				log_info("Threshold logging disabled for shared"
2792 					 " subnet of ranges: %s", log_buf);
2793 			}
2794 			pond = pond->next;
2795 		}
2796 
2797 	}
2798 
2799 #ifdef EUI_64
2800 	if (invalid_cnt) {
2801 		log_fatal ("%d pool(s) are invalid for EUI-64 use",
2802 			   invalid_cnt);
2803 	}
2804 #endif
2805 }
2806 
2807 
2808 /*
2809  * \brief Tests that 16-bit hardware type is less than 256
2810  *
2811  * XXX: DHCPv6 gives a 16-bit field for the htype.  DHCPv4 gives an
2812  * 8-bit field.  To change the semantics of the generic 'hardware'
2813  * structure, we would have to adjust many DHCPv4 sources (from
2814  * interface to DHCPv4 lease code), and we would have to update the
2815  * 'hardware' config directive (probably being reverse compatible and
2816  * providing a new upgrade/replacement primitive).  This is a little
2817  * too much to change for now.  Hopefully we will revisit this before
2818  * hardware types exceeding 8 bits are assigned.
2819  *
2820  * Uses a static variable to limit log occurence to once per startup
2821  *
2822  * \param htype hardware type value to test
2823  *
2824  * \return returns 0 if the value is too large
2825  *
2826 */
htype_bounds_check(uint16_t htype)2827 int htype_bounds_check(uint16_t htype) {
2828 	static int log_once = 0;
2829 
2830 	if (htype & 0xFF00) {
2831 		if (!log_once) {
2832 			log_error("Attention: At least one client advertises a "
2833 			  "hardware type of %d, which exceeds the software "
2834 			  "limitation of 255.", htype);
2835 			log_once = 1;
2836 		}
2837 
2838 		return(0);
2839 	}
2840 
2841 	return(1);
2842 }
2843 
2844 /*!
2845  * \brief Look for hosts by MAC address if it's available
2846  *
2847  * Checks the inbound packet against host declarations which specified:
2848  *
2849  *      "hardware ethernet <MAC>;"
2850  *
2851  * For directly connected clients, the function will use the MAC address
2852  * contained in packet:haddr if it's populated.  \TODO - While the logic is in
2853  * place for this search, the socket layer does not yet populate packet:haddr,
2854  * this is to be done under rt41523.
2855  *
2856  * For relayed clients, the function will use the MAC address from the
2857  * client-linklayer-address option if it has been supplied by the relay
2858  * directly connected to the client.
2859  *
2860  * \param hp[out] - pointer to storage for the host delcaration if found
2861  * \param packet - received packet
2862  * \param opt_state - option state to search
2863  * \param file - source file
2864  * \param line - line number
2865  *
2866  * \return non-zero if a matching host was found, zero otherwise
2867 */
find_hosts_by_haddr6(struct host_decl ** hp,struct packet * packet,struct option_state * opt_state,const char * file,int line)2868 int find_hosts_by_haddr6(struct host_decl **hp,
2869 			 struct packet *packet,
2870 			 struct option_state *opt_state,
2871 			 const char *file, int line) {
2872 	int found = 0;
2873 	int htype;
2874 	int hlen;
2875 
2876 	/* For directly connected clients, use packet:haddr if populated */
2877 	if (packet->dhcpv6_container_packet == NULL) {
2878 		if (packet->haddr) {
2879 			htype = packet->haddr->hbuf[0];
2880 			hlen = packet->haddr->hlen - 1,
2881 			log_debug("find_hosts_by_haddr6: using packet->haddr,"
2882 				  " type: %d, len: %d", htype, hlen);
2883 			found = find_hosts_by_haddr (hp, htype,
2884 						     &packet->haddr->hbuf[1],
2885 						     hlen, MDL);
2886 		}
2887 	} else {
2888 		/* The first container packet is the from the relay directly
2889 		 * connected to the client. Per RFC 6939, that is only relay
2890 		 * that may supply the client linklayer address option. */
2891 		struct packet *relay_packet = packet->dhcpv6_container_packet;
2892 		struct option_state *relay_state = relay_packet->options;
2893 		struct data_string rel_addr;
2894 		struct option_cache *oc;
2895 
2896 		/* Look for the option in the first relay packet */
2897 		oc = lookup_option(&dhcpv6_universe, relay_state,
2898 				   D6O_CLIENT_LINKLAYER_ADDR);
2899 		if (!oc) {
2900 			/* Not there, so bail */
2901 			return (0);
2902 		}
2903 
2904 		/* The option is present, fetch the address data */
2905 		memset(&rel_addr, 0, sizeof(rel_addr));
2906 		if (!evaluate_option_cache(&rel_addr, relay_packet, NULL, NULL,
2907 					   relay_state, NULL, &global_scope,
2908 					   oc, MDL)) {
2909 			log_error("find_hosts_by_add6:"
2910 				  "Error evaluating option cache");
2911 			return (0);
2912 		}
2913 
2914 		/* The relay address data should be:
2915 		 *   byte 0 - 1 = hardware type
2916 		 *   bytes 2 - hlen = hardware address
2917                  * where  hlen ( hardware address len) is option data len - 2 */
2918 		hlen = rel_addr.len - 2;
2919 		if (hlen > 0 && hlen <= HARDWARE_ADDR_LEN) {
2920 			htype = getUShort(rel_addr.data);
2921 			if (htype_bounds_check(htype)) {
2922 				/* Looks valid, let's search with it */
2923 				log_debug("find_hosts_by_haddr6:"
2924 					  "using relayed haddr"
2925 					  " type: %d, len: %d", htype, hlen);
2926 				found = find_hosts_by_haddr (hp, htype,
2927 							     &rel_addr.data[2],
2928 							     hlen, MDL);
2929 			}
2930 		}
2931 
2932 		data_string_forget(&rel_addr, MDL);
2933         }
2934 
2935 	return (found);
2936 }
2937 
2938 /*
2939  * find_host_by_duid_chaddr() synthesizes a DHCPv4-like 'hardware'
2940  * parameter from a DHCPv6 supplied DUID (client-identifier option),
2941  * and may seek to use client or relay supplied hardware addresses.
2942  */
2943 int
find_hosts_by_duid_chaddr(struct host_decl ** host,const struct data_string * client_id)2944 find_hosts_by_duid_chaddr(struct host_decl **host,
2945 			  const struct data_string *client_id) {
2946 	int htype, hlen;
2947 	const unsigned char *chaddr;
2948 
2949 	/*
2950 	 * The DUID-LL and DUID-LLT must have a 2-byte DUID type and 2-byte
2951 	 * htype.
2952 	 */
2953 	if (client_id->len < 4)
2954 		return 0;
2955 
2956 	/*
2957 	 * The third and fourth octets of the DUID-LL and DUID-LLT
2958 	 * is the hardware type, but in 16 bits.
2959 	 */
2960 	htype = getUShort(client_id->data + 2);
2961 	hlen = 0;
2962 	chaddr = NULL;
2963 
2964 	/* The first two octets of the DUID identify the type. */
2965 	switch(getUShort(client_id->data)) {
2966 	      case DUID_LLT:
2967 		if (client_id->len > 8) {
2968 			hlen = client_id->len - 8;
2969 			chaddr = client_id->data + 8;
2970 		}
2971 		break;
2972 
2973 	      case DUID_LL:
2974 		/*
2975 		 * Note that client_id->len must be greater than or equal
2976 		 * to four to get to this point in the function.
2977 		 */
2978 		hlen = client_id->len - 4;
2979 		chaddr = client_id->data + 4;
2980 		break;
2981 
2982 	      default:
2983 		break;
2984 	}
2985 
2986 	if ((hlen == 0) || (hlen > HARDWARE_ADDR_LEN) ||
2987 	    !htype_bounds_check(htype)) {
2988 		return (0);
2989 	}
2990 
2991 	return find_hosts_by_haddr(host, htype, chaddr, hlen, MDL);
2992 }
2993 
2994 /*
2995  * \brief Finds a host record that matches the packet, if any
2996  *
2997  * This function centralizes the logic for matching v6 client
2998  * packets to host declarations.  We check in the following order
2999  * for matches with:
3000  *
3001  * 1. client_id if specified
3002  * 2. MAC address when explicitly available
3003  * 3. packet option
3004  * 4. synthesized hardware address - this is done last as some
3005  * synthesis methods are not consided to be reliable
3006  *
3007  * \param[out] host - pointer to storage for the located host
3008  * \param packet - inbound client packet
3009  * \param client_id - client identifier (if one)
3010  * \param file - source file
3011  * \param line - source file line number
3012  * \return non-zero if a host is found, zero otherwise
3013 */
3014 int
find_hosts6(struct host_decl ** host,struct packet * packet,const struct data_string * client_id,char * file,int line)3015 find_hosts6(struct host_decl** host, struct packet* packet,
3016             const struct data_string* client_id, char* file, int line) {
3017         return (find_hosts_by_uid(host, client_id->data, client_id->len, MDL)
3018                 || find_hosts_by_haddr6(host, packet, packet->options, MDL)
3019                 || find_hosts_by_option(host, packet, packet->options, MDL)
3020                 || find_hosts_by_duid_chaddr(host, client_id));
3021 }
3022 
3023 /* unittest moved to server/tests/mdb6_unittest.c */
3024