]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
Merged IA_XXrelated structures
authorFrancis Dupont <fdupont@isc.org>
Mon, 17 Mar 2008 15:35:37 +0000 (15:35 +0000)
committerFrancis Dupont <fdupont@isc.org>
Mon, 17 Mar 2008 15:35:37 +0000 (15:35 +0000)
RELNOTES
includes/dhcpd.h
server/confpars.c
server/db.c
server/ddns.c
server/dhcpd.c
server/dhcpv6.c
server/mdb6.c

index 2d08edcee25cf43996f9155050622d2b64b92aa3..f5a7a352e8f8ce935869c00e84624b5cd980bf53 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -71,6 +71,8 @@ work on other platforms. Please report any problems and suggested fixes to
 
 - Prefix pools are attached to shared network scopes.
 
+- Merged IA_XX related structures.
+
                        Changes since 4.0.0 (new features)
 
 - Added DHCPv6 rapid commit support.
index eddeb08141ddcb70aee39930008968f89ca98b16..75f6ffe6017743ffaaf184ee8295a03788fd2d61 100644 (file)
@@ -813,7 +813,6 @@ struct shared_network {
        struct ipv6_pool **ipv6_pools;          /* NULL-terminated array */
        int last_ipv6_pool;                     /* offset of last IPv6 pool
                                                   used to issue a lease */
-       struct ipv6_ppool **ipv6_ppools;        /* NULL-terminated array */
        struct group *group;
 #if defined (FAILOVER_PROTOCOL)
        dhcp_failover_state_t *failover_peer;
@@ -1334,19 +1333,22 @@ typedef unsigned char option_mask [16];
 #define MIN_TIME 0
 
                                                /* these are referenced */
-typedef struct hash_table ia_na_hash_t;
+typedef struct hash_table ia_hash_t;
 typedef struct hash_table iaaddr_hash_t;
 
+                                               /* should be lease6 */
+                                               /* shared with iaprefix */
+
 struct iaaddr {
        int refcnt;                             /* reference count */
-       struct in6_addr addr;                   /* IPv6 address */
-       u_int8_t plen;                          /* unused/placeholder */
+       struct in6_addr addr;                   /* IPv6 address/prefix */
+       u_int8_t plen;                          /* iaprefix prefix length */
        binding_state_t state;                  /* state */
        struct binding_scope *scope;            /* "set var = value;" */
        time_t hard_lifetime_end_time;          /* time address expires */
        time_t soft_lifetime_end_time;          /* time ephemeral expires */
-       struct ia_na *ia_na;                    /* IA for this address */
-       struct ipv6_pool *ipv6_pool;            /* pool for this address */
+       struct ia_xx *ia;                       /* IA for this lease */
+       struct ipv6_pool *ipv6_pool;            /* pool for this lease */
 /*
  * For now, just pick an arbitrary time to keep old hard leases
  * around (value in seconds).
@@ -1357,23 +1359,25 @@ struct iaaddr {
                                                   (internal use only) */
 };
 
-struct ia_na {
+struct ia_xx {
        int refcnt;                     /* reference count */
        struct data_string iaid_duid;   /* from the client */
-       u_int16_t ia_type;              /* IA_NA or IA_TA */
-       int num_iaaddr;                 /* number of IAADDR for this IA_NA */
+       u_int16_t ia_type;              /* IA_XX */
+       int num_iaaddr;                 /* number of IAADDR for this IA */
        int max_iaaddr;                 /* space available for IAADDR */
        struct iaaddr **iaaddr;         /* pointers to the various IAADDRs */
 };
 
-extern ia_na_hash_t *ia_na_active;
-extern ia_na_hash_t *ia_ta_active;
+extern ia_hash_t *ia_na_active;
+extern ia_hash_t *ia_ta_active;
+extern ia_hash_t *ia_pd_active;
 
 struct ipv6_pool {
        int refcnt;                             /* reference count */
+       u_int16_t pool_type;                    /* IA_xx */
        struct in6_addr start_addr;             /* first IPv6 address */
-#define POOL_IS_FOR_TEMP       0x8000
        int bits;                               /* number of bits, CIDR style */
+       int units;                              /* allocation unit in bits */
        iaaddr_hash_t *addrs;                   /* non-free IAADDR */
        int num_active;                         /* count of active IAADDR */
        isc_heap_t *active_timeouts;            /* timeouts for active leases */
@@ -1387,54 +1391,6 @@ struct ipv6_pool {
 extern struct ipv6_pool **pools;
 extern int num_pools;
 
-/* Sames thing for IA_PDs */
-
-typedef struct hash_table ia_pd_hash_t;
-typedef struct hash_table iaprefix_hash_t;
-
-struct iaprefix {
-       /* Must keep the same layout than iaaddr */
-       int refcnt;                             /* reference count */
-       struct in6_addr pref;                   /* IPv6 prefix */
-       u_int8_t plen;                          /* prefix length */
-       binding_state_t state;                  /* state */
-       struct binding_scope *scope;            /* "set var = value;" */
-       time_t hard_lifetime_end_time;          /* time prefix expires */
-       time_t soft_lifetime_end_time;          /* time ephemeral expires */
-       struct ia_pd *ia_pd;                    /* IA for this prefix */
-       struct ipv6_ppool *ipv6_ppool;          /* pool for this prefix */
-       int heap_index;                         /* index into heap, or -1 
-                                                  (internal use only) */
-};
-
-struct ia_pd {
-       int refcnt;                     /* reference count */
-       struct data_string iaid_duid;   /* from the client */
-       int num_iaprefix;               /* number of IAPREFIX for this IA_PD */
-       int max_iaprefix;               /* space available for IAPREFIX */
-       struct iaprefix **iaprefix;     /* pointers to the various IAPREFIXs */
-};
-
-extern ia_pd_hash_t *ia_pd_active;
-
-struct ipv6_ppool {
-       int refcnt;                             /* reference count */
-       struct in6_addr start_pref;             /* first IPv6 prefix */
-       u_int8_t pool_plen;                     /* pool prefix length */
-       u_int8_t alloc_plen;                    /* allocation prefix length */
-       iaprefix_hash_t *prefs;                 /* non-free IAPREFIX */
-       int num_active;                         /* count of active IAPREFIX */
-       isc_heap_t *active_timeouts;            /* timeouts for active leases */
-       int num_inactive;                       /* count of inactive IAADDR */
-       isc_heap_t *inactive_timeouts;          /* timeouts for expired or 
-                                                  released leases */
-       struct shared_network *shared_network;  /* shared_network for 
-                                                  this pool */
-};
-
-extern struct ipv6_ppool **ppools;
-extern int num_ppools;
-
 /* External definitions... */
 
 HASH_FUNCTIONS_DECL (group, const char *, struct group_object, group_hash_t)
@@ -2590,8 +2546,7 @@ int commit_leases PROTO ((void));
 void db_startup PROTO ((int));
 int new_lease_file PROTO ((void));
 int group_writer (struct group_object *);
-int write_ia(const struct ia_na *);
-int write_ia_pd(const struct ia_pd *);
+int write_ia(const struct ia_xx *);
 
 /* packet.c */
 u_int32_t checksum PROTO ((unsigned char *, unsigned, u_int32_t));
@@ -3240,7 +3195,7 @@ isc_result_t dhcp_failover_process_update_request_all (dhcp_failover_state_t *,
                                                       failover_message_t *);
 isc_result_t dhcp_failover_process_update_done (dhcp_failover_state_t *,
                                                failover_message_t *);
-void ia_na_remove_all_iaaddr(struct ia_na *ia_na, const char *file, int line);
+void ia_remove_all_iaaddr(struct ia_xx *ia, const char *file, int line);
 void dhcp_failover_recover_done (void *);
 void failover_print PROTO ((char *, unsigned *, unsigned, const char *));
 void update_partner PROTO ((struct lease *));
@@ -3268,11 +3223,8 @@ const char *binding_state_print (enum failover_state);
 
 
 /* mdb6.c */
-HASH_FUNCTIONS_DECL(ia_na, unsigned char *, struct ia_na, ia_na_hash_t);
-HASH_FUNCTIONS_DECL(ia_pd, unsigned char *, struct ia_pd, ia_pd_hash_t);
+HASH_FUNCTIONS_DECL(ia, unsigned char *, struct ia_xx, ia_hash_t);
 HASH_FUNCTIONS_DECL(iaaddr, struct in6_addr *, struct iaaddr, iaaddr_hash_t);
-HASH_FUNCTIONS_DECL(iaprefix, struct in6_addr *,
-                   struct iaprefix, iaaddr_hash_t);
 
 isc_result_t iaaddr_allocate(struct iaaddr **iaaddr,
                             const char *file, int line);
@@ -3281,60 +3233,31 @@ isc_result_t iaaddr_reference(struct iaaddr **iaaddr, struct iaaddr *src,
 isc_result_t iaaddr_dereference(struct iaaddr **iaaddr,
                                const char *file, int line);
 
-isc_result_t iaprefix_allocate(struct iaprefix **iaprefix,
-                              const char *file, int line);
-isc_result_t iaprefix_reference(struct iaprefix **iaprefix,
-                               struct iaprefix *src,
-                               const char *file, int line);
-isc_result_t iaprefix_dereference(struct iaprefix **iaprefix,
-                                 const char *file, int line);
-
 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);
-isc_result_t ia_na_allocate(struct ia_na **ia_na, u_int32_t iaid,
-                           const char *duid, unsigned int duid_len,
-                           const char *file, int line);
-isc_result_t ia_na_reference(struct ia_na **ia_na, struct ia_na *src,
-                            const char *file, int line);
-isc_result_t ia_na_dereference(struct ia_na **ia_na,
-                              const char *file, int line);
-isc_result_t ia_na_add_iaaddr(struct ia_na *ia_na, struct iaaddr *iaaddr,
-                             const char *file, int line);
-void ia_na_remove_iaaddr(struct ia_na *ia_na, struct iaaddr *iaaddr,
+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);
-isc_boolean_t ia_na_equal(const struct ia_na *a, const struct ia_na *b);
-
-isc_result_t ia_pd_allocate(struct ia_pd **ia_pd, u_int32_t iaid,
-                           const char *duid, unsigned int duid_len,
+isc_result_t ia_reference(struct ia_xx **ia, struct ia_xx *src,
+                         const char *file, int line);
+isc_result_t ia_dereference(struct ia_xx **ia,
                            const char *file, int line);
-isc_result_t ia_pd_reference(struct ia_pd **ia_pd, struct ia_pd *src,
-                            const char *file, int line);
-isc_result_t ia_pd_dereference(struct ia_pd **ia_pd,
-                              const char *file, int line);
-isc_result_t ia_pd_add_iaprefix(struct ia_pd *ia_pd, struct iaprefix *iaprefix,
-                               const char *file, int line);
-void ia_pd_remove_iaprefix(struct ia_pd *ia_pd, struct iaprefix *iaprefix,
+isc_result_t ia_add_iaaddr(struct ia_xx *ia, struct iaaddr *iaaddr,
                           const char *file, int line);
-isc_boolean_t ia_pd_equal(const struct ia_pd *a, const struct ia_pd *b);
+void ia_remove_iaaddr(struct ia_xx *ia, struct iaaddr *iaaddr,
+                     const char *file, int line);
+isc_boolean_t ia_equal(const struct ia_xx *a, const struct ia_xx *b);
 
-isc_result_t ipv6_pool_allocate(struct ipv6_pool **pool,
-                               const struct in6_addr *start_addr, int bits, 
+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);
 isc_result_t ipv6_pool_reference(struct ipv6_pool **pool,
                                 struct ipv6_pool *src,
                                 const char *file, int line);
 isc_result_t ipv6_pool_dereference(struct ipv6_pool **pool,
                                   const char *file, int line);
-isc_result_t ipv6_ppool_allocate(struct ipv6_ppool **ppool,
-                                const struct in6_addr *start_pref,
-                                u_int8_t pool_plen, u_int8_t alloc_plen,
-                                const char *file, int line);
-isc_result_t ipv6_ppool_reference(struct ipv6_ppool **ppool,
-                                 struct ipv6_ppool *src,
-                                 const char *file, int line);
-isc_result_t ipv6_ppool_dereference(struct ipv6_ppool **ppool,
-                                   const char *file, int line);
 isc_result_t create_lease6(struct ipv6_pool *pool,
                           struct iaaddr **addr,
                           unsigned int *attempts,
@@ -3350,46 +3273,29 @@ isc_result_t release_lease6(struct ipv6_pool *pool, struct iaaddr *addr);
 isc_result_t decline_lease6(struct ipv6_pool *pool, struct iaaddr *addr);
 isc_boolean_t lease6_exists(const struct ipv6_pool *pool, 
                            const struct in6_addr *addr);
-isc_result_t mark_address_unavailble(struct ipv6_pool *pool,
-                                    const struct in6_addr *addr);
+isc_result_t mark_lease_unavailble(struct ipv6_pool *pool,
+                                  const struct in6_addr *addr);
 
-isc_result_t create_prefix6(struct ipv6_ppool *ppool,
-                           struct iaprefix **pref,
+isc_result_t create_prefix6(struct ipv6_pool *pool,
+                           struct iaaddr **pref,
                            unsigned int *attempts,
                            const struct data_string *uid,
                            time_t soft_lifetime_end_time);
-isc_result_t add_prefix6(struct ipv6_ppool *ppool,
-                        struct iaprefix *pref,
-                        time_t valid_lifetime_end_time);
-isc_result_t renew_prefix6(struct ipv6_ppool *ppool, struct iaprefix *pref);
-isc_result_t expire_prefix6(struct iaprefix **pref, 
-                           struct ipv6_ppool *ppool, time_t now);
-isc_result_t release_prefix6(struct ipv6_ppool *ppool, struct iaprefix *pref);
-isc_boolean_t prefix6_exists(const struct ipv6_ppool *ppool, 
+isc_boolean_t prefix6_exists(const struct ipv6_pool *pool, 
                             const struct in6_addr *pref, u_int8_t plen);
 
 isc_result_t add_ipv6_pool(struct ipv6_pool *pool);
-isc_result_t find_ipv6_pool(struct ipv6_pool **pool, int temp,
+isc_result_t find_ipv6_pool(struct ipv6_pool **pool, u_int16_t type,
                            const struct in6_addr *addr);
-isc_boolean_t ipv6_addr_in_pool(const struct in6_addr *addr, 
-                               const struct ipv6_pool *pool);
-isc_result_t add_ipv6_ppool(struct ipv6_ppool *ppool);
-isc_result_t find_ipv6_ppool(struct ipv6_ppool **pool,
-                            const struct in6_addr *pref);
-isc_boolean_t ipv6_prefix_in_ppool(const struct in6_addr *pref,
-                                  const struct ipv6_ppool *ppool);
-
-isc_result_t renew_leases(struct ia_na *ia_na);
-isc_result_t release_leases(struct ia_na *ia_na);
-isc_result_t decline_leases(struct ia_na *ia_na);
+isc_boolean_t ipv6_in_pool(const struct in6_addr *addr, 
+                          const struct ipv6_pool *pool);
+
+isc_result_t renew_leases(struct ia_xx *ia);
+isc_result_t release_leases(struct ia_xx *ia);
+isc_result_t decline_leases(struct ia_xx *ia);
 void schedule_lease_timeout(struct ipv6_pool *pool);
 void schedule_all_ipv6_lease_timeouts();
 
-isc_result_t renew_prefixes(struct ia_pd *ia_pd);
-isc_result_t release_prefixes(struct ia_pd *ia_pd);
-void schedule_prefix_timeout(struct ipv6_ppool *ppool);
-void schedule_all_ipv6_prefix_timeouts();
-
 void mark_hosts_unavailable(void);
 void mark_phosts_unavailable(void);
 void mark_interfaces_unavailable(void);
index b01638844920404f92e449feda9078af23c4da15..3a54da05c63f86578312ababbbdb134017e3e314 100644 (file)
@@ -590,13 +590,13 @@ int parse_statement (cfile, group, type, host_decl, declaration)
 
              case POOL:
                next_token (&val, (unsigned *)0, cfile);
-               if (type != SUBNET_DECL && type != SHARED_NET_DECL) {
-                       parse_warn (cfile, "pool declared outside of network");
-                       skip_to_semi(cfile);
-               } else if (type == POOL_DECL) {
+               if (type == POOL_DECL) {
                        parse_warn (cfile, "pool declared within pool.");
                        skip_to_semi(cfile);
-               } else
+               } else if (type != SUBNET_DECL && type != SHARED_NET_DECL) {
+                       parse_warn (cfile, "pool declared outside of network");
+                       skip_to_semi(cfile);
+               } else 
                        parse_pool_statement (cfile, group, type);
 
                return declaration;
@@ -629,7 +629,7 @@ int parse_statement (cfile, group, type, host_decl, declaration)
                next_token(NULL, NULL, cfile);
                if ((type != SUBNET_DECL) || (group->subnet == NULL)) {
                        parse_warn (cfile,
-                                   "prefix6 definitions may not be scoped.");
+                                   "prefix6 declaration not allowed here.");
                        skip_to_semi(cfile);
                        return declaration;
                }
@@ -3636,9 +3636,11 @@ void parse_address_range (cfile, group, type, inpool, lpchain)
 
 #ifdef DHCPv6
 static void
-add_ipv6_pool_to_shared_network(struct shared_network *share, 
+add_ipv6_pool_to_shared_network(struct shared_network *share,
+                               u_int16_t type,
                                struct iaddr *lo_addr,
-                               int bits) {
+                               int bits,
+                               int units) {
        struct ipv6_pool *pool;
        struct in6_addr tmp_in6_addr;
        int num_pools;
@@ -3653,8 +3655,8 @@ add_ipv6_pool_to_shared_network(struct shared_network *share,
        }
        memcpy(&tmp_in6_addr, lo_addr->iabuf, sizeof(tmp_in6_addr));
        pool = NULL;
-       if (ipv6_pool_allocate(&pool, &tmp_in6_addr, 
-                              bits, MDL) != ISC_R_SUCCESS) {
+       if (ipv6_pool_allocate(&pool, type, &tmp_in6_addr,
+                              bits, units, MDL) != ISC_R_SUCCESS) {
                log_fatal("Out of memory");
        }
 
@@ -3765,7 +3767,8 @@ parse_address_range6(struct parse *cfile, struct group *group) {
                        return;
                }
 
-               add_ipv6_pool_to_shared_network(share, &lo, bits);
+               add_ipv6_pool_to_shared_network(share, D6O_IA_NA, &lo,
+                                               bits, 128);
 
        } else if (token == TEMPORARY) {
                /*
@@ -3778,9 +3781,9 @@ parse_address_range6(struct parse *cfile, struct group *group) {
                        skip_to_semi(cfile);
                        return;
                }
-               bits |= POOL_IS_FOR_TEMP;
 
-               add_ipv6_pool_to_shared_network(share, &lo, bits);
+               add_ipv6_pool_to_shared_network(share, D6O_IA_TA, &lo,
+                                               bits, 128);
        } else {
                /*
                 * No '/', so we are looking for the end address of 
@@ -3799,9 +3802,9 @@ parse_address_range6(struct parse *cfile, struct group *group) {
                }
 
                for (p=nets; p != NULL; p=p->next) {
-                       add_ipv6_pool_to_shared_network(share, 
+                       add_ipv6_pool_to_shared_network(share, D6O_IA_NA,
                                                        &p->cidrnet.lo_addr, 
-                                                       p->cidrnet.bits);
+                                                       p->cidrnet.bits, 128);
                }
 
                free_iaddrcidrnetlist(&nets);
@@ -3816,75 +3819,6 @@ parse_address_range6(struct parse *cfile, struct group *group) {
        }
 }
 
-static void
-add_ipv6_ppool_to_shared_network(struct shared_network *share, 
-                                struct iaddr *start_addr,
-                                int pool_bits,
-                                int alloc_bits) {
-       struct ipv6_ppool *ppool;
-       struct in6_addr tmp_in6_addr;
-       int num_ppools;
-       struct ipv6_ppool **tmp;
-
-       /*
-        * Create our prefix pool.
-        */
-       if (start_addr->len != sizeof(tmp_in6_addr)) {
-               log_fatal("Internal error: Attempt to add non-IPv6 prefix.");
-       }
-       memcpy(&tmp_in6_addr, start_addr->iabuf, sizeof(tmp_in6_addr));
-       ppool = NULL;
-       if (ipv6_ppool_allocate(&ppool, &tmp_in6_addr,
-                               (u_int8_t) pool_bits, (u_int8_t) alloc_bits,
-                               MDL) != ISC_R_SUCCESS) {
-               log_fatal("Out of memory");
-       }
-
-       /*
-        * Add to our IPv6 prefix pool set.
-        */
-       if (add_ipv6_ppool(ppool) != ISC_R_SUCCESS) {
-               log_fatal ("Out of memory");
-       }
-
-       /*
-        * Link our prefix pool to our shared_network.
-        */
-       ppool->shared_network = NULL;
-       shared_network_reference(&ppool->shared_network, share, MDL);
-
-       /* 
-        * Increase our array size for ipv6_ppools in the shared_network.
-        */
-       if (share->ipv6_ppools == NULL) {
-               num_ppools = 0;
-       } else {
-               num_ppools = 0;
-               while (share->ipv6_ppools[num_ppools] != NULL) {
-                       num_ppools++;
-               }
-       }
-       tmp = dmalloc(sizeof(struct ipv6_ppool *) * (num_ppools + 2), MDL);
-       if (tmp == NULL) {
-               log_fatal("Out of memory");
-       }
-       if (num_ppools > 0) {
-               memcpy(tmp, share->ipv6_ppools,
-                      sizeof(struct ipv6_ppool *) * num_ppools);
-       }
-       if (share->ipv6_ppools != NULL) {
-               dfree(share->ipv6_ppools, MDL);
-       }
-       share->ipv6_ppools = tmp;
-
-       /* 
-        * Record this prefix pool in our array of prefix pools
-        * for this shared network.
-        */
-       ipv6_ppool_reference(&share->ipv6_ppools[num_ppools], ppool, MDL);
-       share->ipv6_ppools[num_ppools+1] = NULL;
-}
-
 /* prefix6-declaration :== ip-address6 ip-address6 SLASH number SEMI */
 
 void 
@@ -3973,9 +3907,9 @@ parse_prefix6(struct parse *cfile, struct group *group) {
                        parse_warn(cfile, "impossible mask length");
                        continue;
                }
-               add_ipv6_ppool_to_shared_network(share,
-                                                &p->cidrnet.lo_addr,
-                                                p->cidrnet.bits, bits);
+               add_ipv6_pool_to_shared_network(share, D6O_IA_PD,
+                                               &p->cidrnet.lo_addr,
+                                               p->cidrnet.bits, bits);
        }
 
        free_iaddrcidrnetlist(&nets);
@@ -4141,9 +4075,9 @@ parse_ia_na_declaration(struct parse *cfile) {
        skip_to_semi(cfile);
 #else /* defined(DHCPv6) */
        enum dhcp_token token;
-       struct ia_na *ia;
+       struct ia_xx *ia;
        const char *val;
-       struct ia_na *old_ia;
+       struct ia_xx *old_ia;
        unsigned int len;
        u_int32_t iaid;
        struct iaddr iaddr;
@@ -4179,7 +4113,7 @@ parse_ia_na_declaration(struct parse *cfile) {
 
        memcpy(&iaid, val, 4);
        ia = NULL;
-       if (ia_na_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) {
+       if (ia_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) {
                log_fatal("Out of memory.");
        }
        ia->ia_type = D6O_IA_NA;
@@ -4379,6 +4313,7 @@ parse_ia_na_declaration(struct parse *cfile) {
                        log_fatal("Out of memory.");
                }
                memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr));
+               iaaddr->plen = 0;
                iaaddr->state = state;
                if (iaaddr->state == FTS_RELEASED)
                        iaaddr->hard_lifetime_end_time = end_time;
@@ -4389,11 +4324,12 @@ parse_ia_na_declaration(struct parse *cfile) {
                }
 
                /* add to our various structures */
-               ia_na_add_iaaddr(ia, iaaddr, MDL);
-               ia_na_reference(&iaaddr->ia_na, ia, MDL);
+               ia_add_iaaddr(ia, iaaddr, MDL);
+               ia_reference(&iaaddr->ia, ia, MDL);
                pool = NULL;
-               if (find_ipv6_pool(&pool, 0, &iaaddr->addr) != ISC_R_SUCCESS) {
-                       inet_ntop(AF_INET6, &iaaddr->addr, 
+               if (find_ipv6_pool(&pool, D6O_IA_NA,
+                                  &iaaddr->addr) != ISC_R_SUCCESS) {
+                       inet_ntop(AF_INET6, &iaaddr->addr,
                                  addr_buf, sizeof(addr_buf));
                        parse_warn(cfile, "no pool found for address %s", 
                                   addr_buf);
@@ -4408,24 +4344,24 @@ parse_ia_na_declaration(struct parse *cfile) {
         * If we have an existing record for this IA_NA, remove it.
         */
        old_ia = NULL;
-       if (ia_na_hash_lookup(&old_ia, ia_na_active,
-                             (unsigned char *)ia->iaid_duid.data,
-                             ia->iaid_duid.len, MDL)) {
-               ia_na_hash_delete(ia_na_active, 
-                                 (unsigned char *)ia->iaid_duid.data,
-                                 ia->iaid_duid.len, MDL);
-               ia_na_dereference(&old_ia, MDL);
+       if (ia_hash_lookup(&old_ia, ia_na_active,
+                          (unsigned char *)ia->iaid_duid.data,
+                          ia->iaid_duid.len, MDL)) {
+               ia_hash_delete(ia_na_active, 
+                              (unsigned char *)ia->iaid_duid.data,
+                              ia->iaid_duid.len, MDL);
+               ia_dereference(&old_ia, MDL);
        }
 
        /*
         * If we have addresses, add this, otherwise don't bother.
         */
        if (ia->num_iaaddr > 0) {
-               ia_na_hash_add(ia_na_active, 
-                              (unsigned char *)ia->iaid_duid.data,
-                              ia->iaid_duid.len, ia, MDL);
+               ia_hash_add(ia_na_active, 
+                           (unsigned char *)ia->iaid_duid.data,
+                           ia->iaid_duid.len, ia, MDL);
        }
-       ia_na_dereference(&ia, MDL);
+       ia_dereference(&ia, MDL);
 #endif /* defined(DHCPv6) */
 }
 
@@ -4436,9 +4372,9 @@ parse_ia_ta_declaration(struct parse *cfile) {
        skip_to_semi(cfile);
 #else /* defined(DHCPv6) */
        enum dhcp_token token;
-       struct ia_na *ia;
+       struct ia_xx *ia;
        const char *val;
-       struct ia_na *old_ia;
+       struct ia_xx *old_ia;
        unsigned int len;
        u_int32_t iaid;
        struct iaddr iaddr;
@@ -4474,7 +4410,7 @@ parse_ia_ta_declaration(struct parse *cfile) {
 
        memcpy(&iaid, val, 4);
        ia = NULL;
-       if (ia_na_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) {
+       if (ia_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) {
                log_fatal("Out of memory.");
        }
        ia->ia_type = D6O_IA_TA;
@@ -4674,6 +4610,7 @@ parse_ia_ta_declaration(struct parse *cfile) {
                        log_fatal("Out of memory.");
                }
                memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr));
+               iaaddr->plen = 0;
                iaaddr->state = state;
                if (iaaddr->state == FTS_RELEASED)
                        iaaddr->hard_lifetime_end_time = end_time;
@@ -4684,11 +4621,12 @@ parse_ia_ta_declaration(struct parse *cfile) {
                }
 
                /* add to our various structures */
-               ia_na_add_iaaddr(ia, iaaddr, MDL);
-               ia_na_reference(&iaaddr->ia_na, ia, MDL);
+               ia_add_iaaddr(ia, iaaddr, MDL);
+               ia_reference(&iaaddr->ia, ia, MDL);
                pool = NULL;
-               if (find_ipv6_pool(&pool, 1, &iaaddr->addr) != ISC_R_SUCCESS) {
-                       inet_ntop(AF_INET6, &iaaddr->addr, 
+               if (find_ipv6_pool(&pool, D6O_IA_TA,
+                                  &iaaddr->addr) != ISC_R_SUCCESS) {
+                       inet_ntop(AF_INET6, &iaaddr->addr,
                                  addr_buf, sizeof(addr_buf));
                        parse_warn(cfile, "no pool found for address %s", 
                                   addr_buf);
@@ -4703,24 +4641,24 @@ parse_ia_ta_declaration(struct parse *cfile) {
         * If we have an existing record for this IA_TA, remove it.
         */
        old_ia = NULL;
-       if (ia_na_hash_lookup(&old_ia, ia_ta_active,
-                             (unsigned char *)ia->iaid_duid.data,
-                             ia->iaid_duid.len, MDL)) {
-               ia_na_hash_delete(ia_ta_active, 
-                                 (unsigned char *)ia->iaid_duid.data,
-                                 ia->iaid_duid.len, MDL);
-               ia_na_dereference(&old_ia, MDL);
+       if (ia_hash_lookup(&old_ia, ia_ta_active,
+                          (unsigned char *)ia->iaid_duid.data,
+                          ia->iaid_duid.len, MDL)) {
+               ia_hash_delete(ia_ta_active, 
+                              (unsigned char *)ia->iaid_duid.data,
+                              ia->iaid_duid.len, MDL);
+               ia_dereference(&old_ia, MDL);
        }
 
        /*
         * If we have addresses, add this, otherwise don't bother.
         */
        if (ia->num_iaaddr > 0) {
-               ia_na_hash_add(ia_ta_active, 
-                              (unsigned char *)ia->iaid_duid.data,
-                              ia->iaid_duid.len, ia, MDL);
+               ia_hash_add(ia_ta_active, 
+                           (unsigned char *)ia->iaid_duid.data,
+                           ia->iaid_duid.len, ia, MDL);
        }
-       ia_na_dereference(&ia, MDL);
+       ia_dereference(&ia, MDL);
 #endif /* defined(DHCPv6) */
 }
 
@@ -4731,17 +4669,17 @@ parse_ia_pd_declaration(struct parse *cfile) {
        skip_to_semi(cfile);
 #else /* defined(DHCPv6) */
        enum dhcp_token token;
-       struct ia_pd *ia_pd;
+       struct ia_xx *ia;
        const char *val;
-       struct ia_pd *old_ia_pd;
+       struct ia_xx *old_ia;
        unsigned int len;
        u_int32_t iaid;
        struct iaddr iaddr;
        u_int8_t plen;
        binding_state_t state;
        TIME end_time;
-       struct iaprefix *iapref;
-       struct ipv6_ppool *ppool;
+       struct iaaddr *iapref;
+       struct ipv6_pool *pool;
        char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
        isc_boolean_t newbinding;
        struct binding_scope *scope=NULL;
@@ -4769,10 +4707,11 @@ parse_ia_pd_declaration(struct parse *cfile) {
        }
 
        memcpy(&iaid, val, 4);
-       ia_pd = NULL;
-       if (ia_pd_allocate(&ia_pd, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) {
+       ia = NULL;
+       if (ia_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) {
                log_fatal("Out of memory.");
        }
+       ia->ia_type = D6O_IA_PD;
 
        token = next_token(&val, NULL, cfile);
        if (token != LBRACE) {
@@ -4965,10 +4904,10 @@ parse_ia_pd_declaration(struct parse *cfile) {
                }
 
                iapref = NULL;
-               if (iaprefix_allocate(&iapref, MDL) != ISC_R_SUCCESS) {
+               if (iaaddr_allocate(&iapref, MDL) != ISC_R_SUCCESS) {
                        log_fatal("Out of memory.");
                }
-               memcpy(&iapref->pref, iaddr.iabuf, sizeof(iapref->pref));
+               memcpy(&iapref->addr, iaddr.iabuf, sizeof(iapref->addr));
                iapref->plen = plen;
                iapref->state = state;
                if (iapref->state == FTS_RELEASED)
@@ -4980,43 +4919,44 @@ parse_ia_pd_declaration(struct parse *cfile) {
                }
 
                /* add to our various structures */
-               ia_pd_add_iaprefix(ia_pd, iapref, MDL);
-               ia_pd_reference(&iapref->ia_pd, ia_pd, MDL);
-               ppool = NULL;
-               if (find_ipv6_ppool(&ppool, &iapref->pref) != ISC_R_SUCCESS) {
-                       inet_ntop(AF_INET6, &iapref->pref, 
+               ia_add_iaaddr(ia, iapref, MDL);
+               ia_reference(&iapref->ia, ia, MDL);
+               pool = NULL;
+               if (find_ipv6_pool(&pool, D6O_IA_PD,
+                                  &iapref->addr) != ISC_R_SUCCESS) {
+                       inet_ntop(AF_INET6, &iapref->addr,
                                  addr_buf, sizeof(addr_buf));
-                       parse_warn(cfile, "no ppool found for address %s", 
+                       parse_warn(cfile, "no pool found for address %s", 
                                   addr_buf);
                        return;
                }
-               add_prefix6(ppool, iapref, end_time);
-               ipv6_ppool_dereference(&ppool, MDL);
-               iaprefix_dereference(&iapref, MDL);
+               add_lease6(pool, iapref, end_time);
+               ipv6_pool_dereference(&pool, MDL);
+               iaaddr_dereference(&iapref, MDL);
        }
 
        /*
         * If we have an existing record for this IA_PD, remove it.
         */
-       old_ia_pd = NULL;
-       if (ia_pd_hash_lookup(&old_ia_pd, ia_pd_active,
-                             (unsigned char *)ia_pd->iaid_duid.data,
-                             ia_pd->iaid_duid.len, MDL)) {
-               ia_pd_hash_delete(ia_pd_active,
-                                 (unsigned char *)ia_pd->iaid_duid.data,
-                                 ia_pd->iaid_duid.len, MDL);
-               ia_pd_dereference(&old_ia_pd, MDL);
+       old_ia = NULL;
+       if (ia_hash_lookup(&old_ia, ia_pd_active,
+                          (unsigned char *)ia->iaid_duid.data,
+                          ia->iaid_duid.len, MDL)) {
+               ia_hash_delete(ia_pd_active,
+                              (unsigned char *)ia->iaid_duid.data,
+                              ia->iaid_duid.len, MDL);
+               ia_dereference(&old_ia, MDL);
        }
 
        /*
         * If we have prefixes, add this, otherwise don't bother.
         */
-       if (ia_pd->num_iaprefix > 0) {
-               ia_pd_hash_add(ia_pd_active, 
-                              (unsigned char *)ia_pd->iaid_duid.data,
-                              ia_pd->iaid_duid.len, ia_pd, MDL);
+       if (ia->num_iaaddr > 0) {
+               ia_hash_add(ia_pd_active, 
+                           (unsigned char *)ia->iaid_duid.data,
+                           ia->iaid_duid.len, ia, MDL);
        }
-       ia_pd_dereference(&ia_pd, MDL);
+       ia_dereference(&ia, MDL);
 #endif /* defined(DHCPv6) */
 }
 
index 563a261c99e4cc074588e1e1f214949b9b0b8cdc..29b140d35adffbc40421f2c6b7518c95cc346792 100644 (file)
@@ -500,7 +500,7 @@ int write_group (group)
  * Write an IA and the options it has.
  */
 int
-write_ia(const struct ia_na *ia) {
+write_ia(const struct ia_xx *ia) {
        struct iaaddr *iaaddr;
        struct binding *bnd;
        int i;
@@ -529,14 +529,20 @@ write_ia(const struct ia_na *ia) {
        if (s == NULL) {
                goto error_exit;
        }
-       if (ia->ia_type == D6O_IA_NA) {
+       switch (ia->ia_type) {
+       case D6O_IA_NA:
                fprintf_ret = fprintf(db_file, "ia-na \"%s\" {\n", s);
-       } else if (ia->ia_type == D6O_IA_TA) {
+               break;
+       case D6O_IA_TA:
                fprintf_ret = fprintf(db_file, "ia-ta \"%s\" {\n", s);
-       } else {
-               log_error("Unknown ia type %u at %s:%d",
-                         (unsigned)ia->ia_type, MDL);
-               goto error_exit;
+               break;
+       case D6O_IA_PD:
+               fprintf_ret = fprintf(db_file, "ia-pd \"%s\" {\n", s);
+               break;
+       default:
+               log_error("Unknown ia type %u for \"%s\" at %s:%d",
+                         (unsigned)ia->ia_type, s, MDL);
+               fprintf_ret = -1;
        }
        dfree(s, MDL);
        if (fprintf_ret < 0) {
@@ -546,7 +552,13 @@ write_ia(const struct ia_na *ia) {
                iaaddr = ia->iaaddr[i];
 
                inet_ntop(AF_INET6, &iaaddr->addr, addr_buf, sizeof(addr_buf));
-               if (fprintf(db_file, "  iaaddr %s {\n", addr_buf) < 0) {
+               if ((ia->ia_type != D6O_IA_PD) &&
+                   (fprintf(db_file, "  iaaddr %s {\n", addr_buf) < 0)) {
+                       goto error_exit;
+               }
+               if ((ia->ia_type == D6O_IA_PD) &&
+                   (fprintf(db_file, "  iaprefix %s/%d {\n",
+                            addr_buf, (int)iaaddr->plen) < 0)) {
                        goto error_exit;
                }
                if ((iaaddr->state <= 0) || (iaaddr->state > FTS_LAST)) {
@@ -607,115 +619,7 @@ write_ia(const struct ia_na *ia) {
        return 1;
 
 error_exit:
-       log_info("write_ia: unable to write ia-na");
-       lease_file_is_corrupt = 1;
-       return 0;
-}
-
-/*
- * Write an IA_PD and the options it has.
- */
-int
-write_ia_pd(const struct ia_pd *ia_pd) {
-       struct iaprefix *iapref;
-       struct binding *bnd;
-       int i;
-       char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff.255.255.255.255")];
-       const char *binding_state;
-       const char *tval;
-       char *s;
-       int fprintf_ret;
-
-       /* 
-        * If the lease file is corrupt, don't try to write any more 
-        * leases until we've written a good lease file. 
-        */
-       if (lease_file_is_corrupt) {
-               if (!new_lease_file()) {
-                       return 0;
-               }
-       }
-
-       if (counting) {
-               ++count;
-       }
-
-       
-       s = quotify_buf(ia_pd->iaid_duid.data, ia_pd->iaid_duid.len, MDL);
-       if (s == NULL) {
-               goto error_exit;
-       }
-       fprintf_ret = fprintf(db_file, "ia-pd \"%s\" {\n", s);
-       dfree(s, MDL);
-       if (fprintf_ret < 0) {
-               goto error_exit;
-       }
-       for (i=0; i<ia_pd->num_iaprefix; i++) {
-               iapref = ia_pd->iaprefix[i];
-
-               inet_ntop(AF_INET6, &iapref->pref, addr_buf, sizeof(addr_buf));
-               if (fprintf(db_file, "  iaprefix %s/%d {\n",
-                           addr_buf, (int)iapref->plen) < 0) {
-                       goto error_exit;
-               }
-               if ((iapref->state <= 0) || (iapref->state > FTS_LAST)) {
-                       log_fatal("Unknown iaprefix state %d at %s:%d", 
-                                 iapref->state, MDL);
-               }
-               binding_state = binding_state_names[iapref->state-1];
-               if (fprintf(db_file, "    binding state %s;\n", 
-                           binding_state) < 0) {
-                       goto error_exit;
-               }
-
-               /* Note that from here on out, the \n is prepended to the
-                * next write, rather than appended to the current write.
-                */
-               if ((iapref->state == FTS_ACTIVE) ||
-                   (iapref->state == FTS_ABANDONED)) {
-                       tval = print_time(iapref->hard_lifetime_end_time);
-               } else {
-                       tval = print_time(iapref->soft_lifetime_end_time);
-               }
-               if (tval == NULL) {
-                       goto error_exit;
-               }
-               if (fprintf(db_file, "    ends %s", tval) < 0) {
-                       goto error_exit;
-               }
-
-               /* Write out any binding scopes: note that 'ends' above does
-                * not have \n on the end!  We want that.
-                */
-               if (iapref->scope != NULL)
-                       bnd = iapref->scope->bindings;
-               else
-                       bnd = NULL;
-
-               for (; bnd != NULL ; bnd = bnd->next) {
-                       if (bnd->value == NULL)
-                               continue;
-
-                       /* We don't do a regular error_exit because the
-                        * lease db is not corrupt in this case.
-                        */
-                       if (write_binding_scope(db_file, bnd,
-                                               "\n    ") != ISC_R_SUCCESS)
-                               goto error_exit;
-                               
-               }
-
-               if (fprintf(db_file, "\n  }\n") < 0)
-                        goto error_exit;
-       }
-       if (fprintf(db_file, "}\n\n") < 0)
-                goto error_exit;
-
-       fflush(db_file);
-       return 1;
-
-error_exit:
-       log_info("write_ia_pd: unable to write ia-pd");
+       log_info("write_ia: unable to write ia");
        lease_file_is_corrupt = 1;
        return 0;
 }
index fe8276a31403323b32dd291357fb29652331788e..b87924bd2230252dfd4125c75e4c8eb5d6e3eadb 100644 (file)
@@ -565,8 +565,8 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
                memset (&ddns_dhcid, 0, sizeof ddns_dhcid);
                if (lease6 != NULL)
                        result = get_dhcid(&ddns_dhcid, 2,
-                                          lease6->ia_na->iaid_duid.data,
-                                          lease6->ia_na->iaid_duid.len);
+                                          lease6->ia->iaid_duid.data,
+                                          lease6->ia->iaid_duid.len);
                else if ((lease != NULL) && (lease->uid != NULL) &&
                         (lease->uid_len != 0))
                        result = get_dhcid (&ddns_dhcid,
index 1d60827cf1838140cfe1ccb6d00a5c1d4cdd4365..61b8f7427e3948380ec65ff8c963622e9d3e2206 100644 (file)
@@ -655,13 +655,13 @@ main(int argc, char **argv) {
 
 #ifdef DHCPv6
        /* set up DHCPv6 hashes */
-       if (!ia_na_new_hash(&ia_na_active, DEFAULT_HASH_SIZE, MDL)) {
+       if (!ia_new_hash(&ia_na_active, DEFAULT_HASH_SIZE, MDL)) {
                log_fatal("Out of memory creating hash for active IA_NA.");
        }
-       if (!ia_na_new_hash(&ia_ta_active, DEFAULT_HASH_SIZE, MDL)) {
+       if (!ia_new_hash(&ia_ta_active, DEFAULT_HASH_SIZE, MDL)) {
                log_fatal("Out of memory creating hash for active IA_TA.");
        }
-       if (!ia_pd_new_hash(&ia_pd_active, DEFAULT_HASH_SIZE, MDL)) {
+       if (!ia_new_hash(&ia_pd_active, DEFAULT_HASH_SIZE, MDL)) {
                log_fatal("Out of memory creating hash for active IA_PD.");
        }
 #endif /* DHCPv6 */
index a0ecec03b9ae7202a051e8398a5ef9f7264b49b5..2dad33ed202f837eddfb2a9e97125affc0a39103 100644 (file)
@@ -49,26 +49,18 @@ struct reply_state {
 
        /* IA level persistent state */
        unsigned ia_count;
-       unsigned ia_pd_count;
+       unsigned pd_count;
        unsigned client_resources;
-       isc_boolean_t ia_resources_included;
+       isc_boolean_t resources_included;
        isc_boolean_t static_lease;
        unsigned static_prefixes;
-       struct ia_na *ia_na;
-       struct ia_na *ia_ta;
-       union {
-               struct ia_na *old__ia;
-               struct ia_pd *old__pd;
-       } old;
-#define old_ia         old.old__ia
-#define old_ia_pd      old.old__pd
-       struct ia_pd *ia_pd;
+       struct ia_xx *ia;
+       struct ia_xx *old_ia;
        struct option_state *reply_ia;
        struct data_string fixed;
 
-       /* IAADDR/IAPREFIX level persistent state */
+       /* IAADDR/PREFIX level persistent state */
        struct iaaddr *lease;
-       struct iaprefix *prefix;
 
        /*
         * "t1", "t2", preferred, and valid lifetimes records for calculating
@@ -122,7 +114,6 @@ static isc_result_t reply_process_try_addr(struct reply_state *reply,
                                           struct iaddr *addr);
 static isc_result_t find_client_address(struct reply_state *reply);
 static isc_result_t reply_process_is_addressed(struct reply_state *reply,
-                                              struct ia_na *ia,
                                               struct binding_scope **scope,
                                               struct group *group);
 static isc_result_t reply_process_send_addr(struct reply_state *reply,
@@ -138,14 +129,13 @@ static isc_result_t find_client_prefix(struct reply_state *reply);
 static isc_result_t reply_process_try_prefix(struct reply_state *reply,
                                             struct iaddrcidrnet *pref);
 static isc_result_t reply_process_is_prefixed(struct reply_state *reply,
-                                             struct ia_pd *ia_pd,
                                              struct binding_scope **scope,
                                              struct group *group);
 static isc_result_t reply_process_send_prefix(struct reply_state *reply,
                                              struct iaddrcidrnet *pref);
-static struct iaprefix *prefix_compare(struct reply_state *reply,
-                                      struct iaprefix *alpha,
-                                      struct iaprefix *beta);
+static struct iaaddr *prefix_compare(struct reply_state *reply,
+                                    struct iaaddr *alpha,
+                                    struct iaaddr *beta);
 
 /*
  * This function returns the time since DUID time start for the
@@ -965,7 +955,7 @@ try_client_v6_address(struct iaaddr **addr,
                return ISC_R_FAILURE;
        }
 
-       if (!ipv6_addr_in_pool(&tmp_addr, pool)) {
+       if (!ipv6_in_pool(&tmp_addr, pool)) {
                return ISC_R_FAILURE;
        }
 
@@ -978,6 +968,7 @@ try_client_v6_address(struct iaaddr **addr,
                return result;
        }
        (*addr)->addr = tmp_addr;
+       (*addr)->plen = 0;
 
        /* Default is soft binding for 2 minutes. */
        result = add_lease6(pool, *addr, cur_time + 120);
@@ -1006,7 +997,7 @@ pick_v6_address(struct iaaddr **addr, struct shared_network *shared_network,
        char tmp_buf[INET6_ADDRSTRLEN];
 
        /*
-        * No pools or all temporary, we're done.
+        * No address pools, we're done.
         */
        if (shared_network->ipv6_pools == NULL) {
                log_debug("Unable to pick client address: "
@@ -1017,11 +1008,11 @@ pick_v6_address(struct iaaddr **addr, struct shared_network *shared_network,
                p = shared_network->ipv6_pools[i];
                if (p == NULL) {
                        log_debug("Unable to pick client address: "
-                                 "only temporary IPv6 pools "
+                                 "no IPv6 address pools "
                                  "on this shared network");
                        return ISC_R_NORESOURCES;
                }
-               if ((p->bits & POOL_IS_FOR_TEMP) == 0) {
+               if (p->pool_type == D6O_IA_NA) {
                        break;
                }
        }
@@ -1038,7 +1029,7 @@ pick_v6_address(struct iaaddr **addr, struct shared_network *shared_network,
        do {
 
                p = shared_network->ipv6_pools[i];
-               if (((p->bits & POOL_IS_FOR_TEMP) == 0) &&
+               if ((p->pool_type == D6O_IA_NA) &&
                    (create_lease6(p, addr, &attempts, client_id,
                                   cur_time + 120) == ISC_R_SUCCESS)) {
                        /*
@@ -1078,12 +1069,12 @@ pick_v6_address(struct iaaddr **addr, struct shared_network *shared_network,
  * prefix pool.
  *
  * pref is the result (should be a pointer to NULL on entry)
- * ppool is the prefix pool to search in
+ * pool is the prefix pool to search in
  * requested_pref is the address the client wants
  */
 static isc_result_t
-try_client_v6_prefix(struct iaprefix **pref,
-                    struct ipv6_ppool *ppool,
+try_client_v6_prefix(struct iaaddr **pref,
+                    struct ipv6_pool *pool,
                     const struct data_string *requested_pref)
 {
        u_int8_t tmp_plen;
@@ -1108,26 +1099,26 @@ try_client_v6_prefix(struct iaprefix **pref,
                return ISC_R_FAILURE;
        }
 
-       if ((tmp_plen != ppool->alloc_plen) ||
-           !ipv6_prefix_in_ppool(&tmp_pref, ppool)) {
+       if (((int)tmp_plen != pool->units) ||
+           !ipv6_in_pool(&tmp_pref, pool)) {
                return ISC_R_FAILURE;
        }
 
-       if (prefix6_exists(ppool, &tmp_pref, tmp_plen)) {
+       if (prefix6_exists(pool, &tmp_pref, tmp_plen)) {
                return ISC_R_ADDRINUSE;
        }
 
-       result = iaprefix_allocate(pref, MDL);
+       result = iaaddr_allocate(pref, MDL);
        if (result != ISC_R_SUCCESS) {
                return result;
        }
-       (*pref)->pref = tmp_pref;
+       (*pref)->addr = tmp_pref;
        (*pref)->plen = tmp_plen;
 
        /* Default is soft binding for 2 minutes. */
-       result = add_prefix6(ppool, *pref, cur_time + 120);
+       result = add_lease6(pool, *pref, cur_time + 120);
        if (result != ISC_R_SUCCESS) {
-               iaprefix_dereference(pref, MDL);
+               iaaddr_dereference(pref, MDL);
        }
        return result;
 }
@@ -1142,11 +1133,11 @@ try_client_v6_prefix(struct iaprefix **pref,
  * client_id is the DUID for the client
  */
 static isc_result_t 
-pick_v6_prefix(struct iaprefix **pref, int plen,
+pick_v6_prefix(struct iaaddr **pref, int plen,
               struct shared_network *shared_network,
               const struct data_string *client_id)
 {
-       struct ipv6_ppool *p;
+       struct ipv6_pool *p;
        int i;
        unsigned int attempts;
        char tmp_buf[INET6_ADDRSTRLEN];
@@ -1154,32 +1145,47 @@ pick_v6_prefix(struct iaprefix **pref, int plen,
        /*
         * No prefix pools, we're done.
         */
-       if (shared_network->ipv6_ppools == NULL) {
+       if (shared_network->ipv6_pools == NULL) {
                log_debug("Unable to pick client prefix: "
-                         "no IPv6 prefix pools on this shared network");
+                         "no IPv6 pools on this shared network");
                return ISC_R_NORESOURCES;
        }
+       for (i = 0;; i++) {
+               p = shared_network->ipv6_pools[i];
+               if (p == NULL) {
+                       log_debug("Unable to pick client prefix: "
+                                 "no IPv6 prefix pools "
+                                 "on this shared network");
+                       return ISC_R_NORESOURCES;
+               }
+               if (p->pool_type == D6O_IA_PD) {
+                       break;
+               }
+       }
 
        /*
         * Otherwise try to get a prefix.
         */
        for (i = 0;; i++) {
-               p = shared_network->ipv6_ppools[i];
+               p = shared_network->ipv6_pools[i];
                if (p == NULL) {
                        break;
                }
+               if (p->pool_type != D6O_IA_PD) {
+                       continue;
+               }
 
                /*
                 * Try only pools with the requested prefix length if any.
                 */
-               if ((plen >= 0) && ((int) p->alloc_plen != plen)) {
+               if ((plen >= 0) && (p->units != plen)) {
                        continue;
                }
 
                if (create_prefix6(p, pref, &attempts, client_id,
                                   cur_time + 120) == ISC_R_SUCCESS) {
                        log_debug("Picking pool prefix %s/%u",
-                                 inet_ntop(AF_INET6, &((*pref)->pref),
+                                 inet_ntop(AF_INET6, &((*pref)->addr),
                                            tmp_buf, sizeof(tmp_buf)),
                                  (unsigned) (*pref)->plen);
                        return ISC_R_SUCCESS;
@@ -1285,7 +1291,7 @@ lease_to_client(struct data_string *reply_ret,
 
                /* Start counting resources (addresses) offered. */
                reply.client_resources = 0;
-               reply.ia_resources_included = ISC_FALSE;
+               reply.resources_included = ISC_FALSE;
 
                status = reply_process_ia_na(&reply, oc);
 
@@ -1310,7 +1316,7 @@ lease_to_client(struct data_string *reply_ret,
 
                /* Start counting resources (addresses) offered. */
                reply.client_resources = 0;
-               reply.ia_resources_included = ISC_FALSE;
+               reply.resources_included = ISC_FALSE;
 
                status = reply_process_ia_ta(&reply, oc);
 
@@ -1331,14 +1337,14 @@ lease_to_client(struct data_string *reply_ret,
        }
 
        /* Same for IA_PD's. */
-       reply.ia_pd_count = 0;
+       reply.pd_count = 0;
        oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
        for (; oc != NULL ; oc = oc->next) {
                isc_result_t status;
 
                /* Start counting resources (prefixes) offered. */
                reply.client_resources = 0;
-               reply.ia_resources_included = ISC_FALSE;
+               reply.resources_included = ISC_FALSE;
 
                status = reply_process_ia_pd(&reply, oc);
 
@@ -1362,7 +1368,7 @@ lease_to_client(struct data_string *reply_ret,
         * Make no reply if we gave no resources and is not
         * for Information-Request.
         */
-       if ((reply.ia_count == 0) && (reply.ia_pd_count == 0) &&
+       if ((reply.ia_count == 0) && (reply.pd_count == 0) &&
            (reply.packet->dhcpv6_msg_type != DHCPV6_INFORMATION_REQUEST))
                goto exit;
 
@@ -1519,7 +1525,7 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
        /* Fetch the IA_NA contents. */
        if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
                                       ia, IA_NA_OFFSET)) {
-               log_error("reply_process_ia_na: error evaluating ia_na");
+               log_error("reply_process_ia_na: error evaluating ia");
                status = ISC_R_FAILURE;
                goto cleanup;
        }
@@ -1530,18 +1536,18 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
        reply->rebind = getULong(ia_data.data + 8);
 
        /* Create an IA_NA structure. */
-       if (ia_na_allocate(&reply->ia_na, iaid, (char *)reply->client_id.data, 
-                          reply->client_id.len, MDL) != ISC_R_SUCCESS) {
-               log_error("reply_process_ia_na: no memory for ia_na.");
+       if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data, 
+                       reply->client_id.len, MDL) != ISC_R_SUCCESS) {
+               log_error("reply_process_ia_na: no memory for ia.");
                status = ISC_R_NOMEMORY;
                goto cleanup;
        }
-       reply->ia_na->ia_type = D6O_IA_NA;
+       reply->ia->ia_type = D6O_IA_NA;
 
        /* Cache pre-existing IA, if any. */
-       ia_na_hash_lookup(&reply->old_ia, ia_na_active,
-                         (unsigned char *)reply->ia_na->iaid_duid.data,
-                         reply->ia_na->iaid_duid.len, MDL);
+       ia_hash_lookup(&reply->old_ia, ia_na_active,
+                      (unsigned char *)reply->ia->iaid_duid.data,
+                      reply->ia->iaid_duid.len, MDL);
 
        /*
         * Create an option cache to carry the IA_NA option contents, and
@@ -1699,7 +1705,7 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
                                 * provide zero addresses including zeroed
                                 * lifetimes.
                                 */
-                               if (reply->ia_resources_included)
+                               if (reply->resources_included)
                                        status = ISC_R_SUCCESS;
                                else
                                        goto cleanup;
@@ -1775,17 +1781,17 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
         */
        if ((status != ISC_R_CANCELED) && !reply->static_lease &&
            (reply->buf.reply.msg_type == DHCPV6_REPLY) &&
-           (reply->ia_na->num_iaaddr != 0)) {
+           (reply->ia->num_iaaddr != 0)) {
                struct iaaddr *tmp;
                struct data_string *ia_id;
                int i;
 
-               for (i = 0 ; i < reply->ia_na->num_iaaddr ; i++) {
-                       tmp = reply->ia_na->iaaddr[i];
+               for (i = 0 ; i < reply->ia->num_iaaddr ; i++) {
+                       tmp = reply->ia->iaaddr[i];
 
-                       if (tmp->ia_na != NULL)
-                               ia_na_dereference(&tmp->ia_na, MDL);
-                       ia_na_reference(&tmp->ia_na, reply->ia_na, MDL);
+                       if (tmp->ia != NULL)
+                               ia_dereference(&tmp->ia, MDL);
+                       ia_reference(&tmp->ia, reply->ia, MDL);
 
                        /* Commit 'hard' bindings. */
                        tmp->hard_lifetime_end_time =
@@ -1811,21 +1817,21 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
                        }
                }
 
-               /* Remove any old ia_na from the hash. */
+               /* Remove any old ia from the hash. */
                if (reply->old_ia != NULL) {
                        ia_id = &reply->old_ia->iaid_duid;
-                       ia_na_hash_delete(ia_na_active,
-                                         (unsigned char *)ia_id->data,
-                                         ia_id->len, MDL);
-                       ia_na_dereference(&reply->old_ia, MDL);
+                       ia_hash_delete(ia_na_active,
+                                      (unsigned char *)ia_id->data,
+                                      ia_id->len, MDL);
+                       ia_dereference(&reply->old_ia, MDL);
                }
 
-               /* Put new ia_na into the hash. */
-               ia_id = &reply->ia_na->iaid_duid;
-               ia_na_hash_add(ia_na_active, (unsigned char *)ia_id->data,
-                              ia_id->len, reply->ia_na, MDL);
+               /* Put new ia into the hash. */
+               ia_id = &reply->ia->iaid_duid;
+               ia_hash_add(ia_na_active, (unsigned char *)ia_id->data,
+                           ia_id->len, reply->ia, MDL);
 
-               write_ia(reply->ia_na);
+               write_ia(reply->ia);
        }
 
       cleanup:
@@ -1837,10 +1843,10 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
                data_string_forget(&ia_data, MDL);
        if (data.data != NULL)
                data_string_forget(&data, MDL);
-       if (reply->ia_na != NULL)
-               ia_na_dereference(&reply->ia_na, MDL);
+       if (reply->ia != NULL)
+               ia_dereference(&reply->ia, MDL);
        if (reply->old_ia != NULL)
-               ia_na_dereference(&reply->old_ia, MDL);
+               ia_dereference(&reply->old_ia, MDL);
        if (reply->lease != NULL)
                iaaddr_dereference(&reply->lease, MDL);
        if (reply->fixed.data != NULL)
@@ -1855,7 +1861,7 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
 }
 
 /*
- * Process an IAADDR within a given IA_NA, storing any IAADDR reply contents
+ * Process an IAADDR within a given IA_xA, storing any IAADDR reply contents
  * into the reply's current ia-scoped option cache.  Returns ISC_R_CANCELED
  * in the event we are replying with a status code and do not wish to process
  * more IAADDRs within this IA.
@@ -1934,9 +1940,15 @@ reply_process_addr(struct reply_state *reply, struct option_cache *addr) {
        /* Address not found on shared network. */
        if (subnet == NULL) {
                /* Ignore this address on 'soft' bindings. */
-               if (reply->packet->dhcpv6_msg_type == DHCPV6_SOLICIT)
+               if (reply->packet->dhcpv6_msg_type == DHCPV6_SOLICIT) {
+                       /* disable rapid commit */
+                       reply->buf.reply.msg_type = DHCPV6_ADVERTISE;
+                       delete_option(&dhcpv6_universe,
+                                     reply->opt_state,
+                                     D6O_RAPID_COMMIT);
                        /* status remains success */
                        goto cleanup;
+               }
 
                /*
                 * RFC3315 section 18.2.1:
@@ -2120,7 +2132,7 @@ reply_process_addr(struct reply_state *reply, struct option_cache *addr) {
                        goto cleanup;
        }
 
-       status = reply_process_is_addressed(reply, reply->ia_na, scope, group);
+       status = reply_process_is_addressed(reply, scope, group);
        if (status != ISC_R_SUCCESS)
                goto cleanup;
 
@@ -2208,7 +2220,7 @@ reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) {
        /* Fetch the IA_TA contents. */
        if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
                                       ia, IA_TA_OFFSET)) {
-               log_error("reply_process_ia_ta: error evaluating ia_ta");
+               log_error("reply_process_ia_ta: error evaluating ia");
                status = ISC_R_FAILURE;
                goto cleanup;
        }
@@ -2217,18 +2229,18 @@ reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) {
        iaid = getULong(ia_data.data);
 
        /* Create an IA_TA structure. */
-       if (ia_na_allocate(&reply->ia_ta, iaid, (char *)reply->client_id.data, 
-                          reply->client_id.len, MDL) != ISC_R_SUCCESS) {
-               log_error("reply_process_ia_ta: no memory for ia_ta.");
+       if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data, 
+                       reply->client_id.len, MDL) != ISC_R_SUCCESS) {
+               log_error("reply_process_ia_ta: no memory for ia.");
                status = ISC_R_NOMEMORY;
                goto cleanup;
        }
-       reply->ia_ta->ia_type = D6O_IA_TA;
+       reply->ia->ia_type = D6O_IA_TA;
 
        /* Cache pre-existing IA, if any. */
-       ia_na_hash_lookup(&reply->old_ia, ia_ta_active,
-                         (unsigned char *)reply->ia_ta->iaid_duid.data,
-                         reply->ia_ta->iaid_duid.len, MDL);
+       ia_hash_lookup(&reply->old_ia, ia_ta_active,
+                      (unsigned char *)reply->ia->iaid_duid.data,
+                      reply->ia->iaid_duid.len, MDL);
 
        /*
         * Create an option cache to carry the IA_TA option contents, and
@@ -2383,17 +2395,17 @@ reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) {
         */
        if ((status != ISC_R_CANCELED) &&
            (reply->buf.reply.msg_type == DHCPV6_REPLY) &&
-           (reply->ia_ta->num_iaaddr != 0)) {
+           (reply->ia->num_iaaddr != 0)) {
                struct iaaddr *tmp;
                struct data_string *ia_id;
                int i;
 
-               for (i = 0 ; i < reply->ia_ta->num_iaaddr ; i++) {
-                       tmp = reply->ia_ta->iaaddr[i];
+               for (i = 0 ; i < reply->ia->num_iaaddr ; i++) {
+                       tmp = reply->ia->iaaddr[i];
 
-                       if (tmp->ia_na != NULL)
-                               ia_na_dereference(&tmp->ia_na, MDL);
-                       ia_na_reference(&tmp->ia_na, reply->ia_ta, MDL);
+                       if (tmp->ia != NULL)
+                               ia_dereference(&tmp->ia, MDL);
+                       ia_reference(&tmp->ia, reply->ia, MDL);
 
                        /* Commit 'hard' bindings. */
                        tmp->hard_lifetime_end_time =
@@ -2419,21 +2431,21 @@ reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) {
                        }
                }
 
-               /* Remove any old ia_ta from the hash. */
+               /* Remove any old ia from the hash. */
                if (reply->old_ia != NULL) {
                        ia_id = &reply->old_ia->iaid_duid;
-                       ia_na_hash_delete(ia_ta_active,
-                                         (unsigned char *)ia_id->data,
-                                         ia_id->len, MDL);
-                       ia_na_dereference(&reply->old_ia, MDL);
+                       ia_hash_delete(ia_ta_active,
+                                      (unsigned char *)ia_id->data,
+                                      ia_id->len, MDL);
+                       ia_dereference(&reply->old_ia, MDL);
                }
 
-               /* Put new ia_ta into the hash. */
-               ia_id = &reply->ia_ta->iaid_duid;
-               ia_na_hash_add(ia_ta_active, (unsigned char *)ia_id->data,
-                              ia_id->len, reply->ia_ta, MDL);
+               /* Put new ia into the hash. */
+               ia_id = &reply->ia->iaid_duid;
+               ia_hash_add(ia_ta_active, (unsigned char *)ia_id->data,
+                           ia_id->len, reply->ia, MDL);
 
-               write_ia(reply->ia_ta);
+               write_ia(reply->ia);
        }
 
       cleanup:
@@ -2447,10 +2459,10 @@ reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) {
                data_string_forget(&ia_data, MDL);
        if (data.data != NULL)
                data_string_forget(&data, MDL);
-       if (reply->ia_ta != NULL)
-               ia_na_dereference(&reply->ia_ta, MDL);
+       if (reply->ia != NULL)
+               ia_dereference(&reply->ia, MDL);
        if (reply->old_ia != NULL)
-               ia_na_dereference(&reply->old_ia, MDL);
+               ia_dereference(&reply->old_ia, MDL);
        if (reply->lease != NULL)
                iaaddr_dereference(&reply->lease, MDL);
 
@@ -2490,7 +2502,7 @@ find_client_temporaries(struct reply_state *reply) {
                if (p == NULL) {
                        break;
                }
-               if ((p->bits & POOL_IS_FOR_TEMP) == 0) {
+               if (p->pool_type != D6O_IA_TA) {
                        continue;
                }
 
@@ -2505,7 +2517,6 @@ find_client_temporaries(struct reply_state *reply) {
                }
 
                status = reply_process_is_addressed(reply,
-                                                   reply->ia_ta,
                                                    &reply->lease->scope,
                                                    reply->shared->group);
                if (status != ISC_R_SUCCESS) {
@@ -2535,7 +2546,7 @@ find_client_temporaries(struct reply_state *reply) {
  */
 static isc_result_t
 reply_process_try_addr(struct reply_state *reply, struct iaddr *addr) {
-       isc_result_t status = ISC_R_FAILURE;
+       isc_result_t status = ISC_R_NORESOURCES;
        struct ipv6_pool *pool;
        int i;
        struct data_string data_addr;
@@ -2550,6 +2561,8 @@ reply_process_try_addr(struct reply_state *reply, struct iaddr *addr) {
        data_addr.data = addr->iabuf;
 
        for (i = 0 ; (pool = reply->shared->ipv6_pools[i]) != NULL ; i++) {
+               if (pool->pool_type != D6O_IA_NA)
+                       continue;
                status = try_client_v6_address(&reply->lease, pool,
                                               &data_addr);
                if (status == ISC_R_SUCCESS)
@@ -2617,7 +2630,7 @@ find_client_address(struct reply_state *reply) {
                log_error("Reclaiming abandoned addresses is not yet "
                          "supported.  Treating this as an out of space "
                          "condition.");
-               /* lease_reference(&reply->lease, best_lease, MDL); */
+               /* iaaddr_reference(&reply->lease, best_lease, MDL); */
        }
 
        /* Give up now if we didn't find a lease. */
@@ -2634,7 +2647,7 @@ find_client_address(struct reply_state *reply) {
        memcpy(send_addr.iabuf, &reply->lease->addr, 16);
 
       send_addr:
-       status = reply_process_is_addressed(reply, reply->ia_na, scope, group);
+       status = reply_process_is_addressed(reply, scope, group);
        if (status != ISC_R_SUCCESS)
                return status;
 
@@ -2647,7 +2660,7 @@ find_client_address(struct reply_state *reply) {
  * into the option state.
  */
 static isc_result_t
-reply_process_is_addressed(struct reply_state *reply, struct ia_na *ia,
+reply_process_is_addressed(struct reply_state *reply,
                           struct binding_scope **scope, struct group *group)
 {
        isc_result_t status = ISC_R_SUCCESS;
@@ -2744,7 +2757,7 @@ reply_process_is_addressed(struct reply_state *reply, struct ia_na *ia,
                        /* Wait before renew! */
                }
 
-               status = ia_na_add_iaaddr(ia, reply->lease, MDL);
+               status = ia_add_iaaddr(reply->ia, reply->lease, MDL);
                if (status != ISC_R_SUCCESS) {
                        log_fatal("reply_process_is_addressed: Unable to "
                                  "attach lease to new IA: %s",
@@ -2754,8 +2767,8 @@ reply_process_is_addressed(struct reply_state *reply, struct ia_na *ia,
                /*
                 * If this is a new lease, make sure it is attached somewhere.
                 */
-               if (reply->lease->ia_na == NULL) {
-                       ia_na_reference(&reply->lease->ia_na, ia, MDL);
+               if (reply->lease->ia == NULL) {
+                       ia_reference(&reply->lease->ia, reply->ia, MDL);
                }
        }
 
@@ -2805,7 +2818,7 @@ reply_process_send_addr(struct reply_state *reply, struct iaddr *addr) {
                goto cleanup;
        }
 
-       reply->ia_resources_included = ISC_TRUE;
+       reply->resources_included = ISC_TRUE;
 
       cleanup:
        if (data.data != NULL)
@@ -2899,20 +2912,20 @@ lease_compare(struct iaaddr *alpha, struct iaaddr *beta) {
  * the reply packet being built in the reply_state structure.
  */
 static isc_result_t
-reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia_pd) {
+reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia) {
        isc_result_t status = ISC_R_SUCCESS;
        u_int32_t iaid;
        unsigned ia_cursor;
        struct option_state *packet_ia;
        struct option_cache *oc;
-       struct data_string ia_pd_data, data;
+       struct data_string ia_data, data;
 
        /* Initialize values that will get cleaned up on return. */
        packet_ia = NULL;
-       memset(&ia_pd_data, 0, sizeof(ia_pd_data));
+       memset(&ia_data, 0, sizeof(ia_data));
        memset(&data, 0, sizeof(data));
        /* 
-        * Note that find_client_prefix() may set reply->prefix. 
+        * Note that find_client_prefix() may set reply->lease.
         */
 
        /* Make sure there is at least room for the header. */
@@ -2923,30 +2936,31 @@ reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia_pd) {
 
 
        /* Fetch the IA_PD contents. */
-       if (!get_encapsulated_IA_state(&packet_ia, &ia_pd_data, reply->packet,
-                                      ia_pd, IA_PD_OFFSET)) {
-               log_error("reply_process_ia_pd: error evaluating ia_pd");
+       if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
+                                      ia, IA_PD_OFFSET)) {
+               log_error("reply_process_ia_pd: error evaluating ia");
                status = ISC_R_FAILURE;
                goto cleanup;
        }
 
        /* Extract IA_PD header contents. */
-       iaid = getULong(ia_pd_data.data);
-       reply->renew = getULong(ia_pd_data.data + 4);
-       reply->rebind = getULong(ia_pd_data.data + 8);
+       iaid = getULong(ia_data.data);
+       reply->renew = getULong(ia_data.data + 4);
+       reply->rebind = getULong(ia_data.data + 8);
 
        /* Create an IA_PD structure. */
-       if (ia_pd_allocate(&reply->ia_pd, iaid, (char *)reply->client_id.data, 
-                          reply->client_id.len, MDL) != ISC_R_SUCCESS) {
-               log_error("reply_process_ia_pd: no memory for ia_pd.");
+       if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data, 
+                       reply->client_id.len, MDL) != ISC_R_SUCCESS) {
+               log_error("reply_process_ia_pd: no memory for ia.");
                status = ISC_R_NOMEMORY;
                goto cleanup;
        }
+       reply->ia->ia_type = D6O_IA_PD;
 
        /* Cache pre-existing IA_PD, if any. */
-       ia_pd_hash_lookup(&reply->old_ia_pd, ia_pd_active,
-                         (unsigned char *)reply->ia_pd->iaid_duid.data,
-                         reply->ia_pd->iaid_duid.len, MDL);
+       ia_hash_lookup(&reply->old_ia, ia_pd_active,
+                      (unsigned char *)reply->ia->iaid_duid.data,
+                      reply->ia->iaid_duid.len, MDL);
 
        /*
         * Create an option cache to carry the IA_PD option contents, and
@@ -3019,7 +3033,7 @@ reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia_pd) {
                        goto cleanup;
        }
 
-       reply->ia_pd_count++;
+       reply->pd_count++;
 
        /*
         * If we fell through the above and never gave the client
@@ -3066,7 +3080,7 @@ reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia_pd) {
                                break;
 
                              default:
-                               if (reply->ia_resources_included)
+                               if (reply->resources_included)
                                        status = ISC_R_SUCCESS;
                                else
                                        goto cleanup;
@@ -3142,41 +3156,41 @@ reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia_pd) {
         */
        if ((status != ISC_R_CANCELED) && (reply->static_prefixes == 0) &&
            (reply->buf.reply.msg_type == DHCPV6_REPLY) &&
-           (reply->ia_pd->num_iaprefix != 0)) {
-               struct iaprefix *tmp;
+           (reply->ia->num_iaaddr != 0)) {
+               struct iaaddr *tmp;
                struct data_string *ia_id;
                int i;
 
-               for (i = 0 ; i < reply->ia_pd->num_iaprefix ; i++) {
-                       tmp = reply->ia_pd->iaprefix[i];
+               for (i = 0 ; i < reply->ia->num_iaaddr ; i++) {
+                       tmp = reply->ia->iaaddr[i];
 
-                       if (tmp->ia_pd != NULL)
-                               ia_pd_dereference(&tmp->ia_pd, MDL);
-                       ia_pd_reference(&tmp->ia_pd, reply->ia_pd, MDL);
+                       if (tmp->ia != NULL)
+                               ia_dereference(&tmp->ia, MDL);
+                       ia_reference(&tmp->ia, reply->ia, MDL);
 
                        /* Commit 'hard' bindings. */
                        tmp->hard_lifetime_end_time =
                                tmp->soft_lifetime_end_time;
                        tmp->soft_lifetime_end_time = 0;
-                       renew_prefix6(tmp->ipv6_ppool, tmp);
-                       schedule_prefix_timeout(tmp->ipv6_ppool);
+                       renew_lease6(tmp->ipv6_pool, tmp);
+                       schedule_lease_timeout(tmp->ipv6_pool);
                }
 
-               /* Remove any old ia_pd from the hash. */
-               if (reply->old_ia_pd != NULL) {
-                       ia_id = &reply->old_ia_pd->iaid_duid;
-                       ia_pd_hash_delete(ia_pd_active,
-                                         (unsigned char *)ia_id->data,
-                                         ia_id->len, MDL);
-                       ia_pd_dereference(&reply->old_ia_pd, MDL);
+               /* Remove any old ia from the hash. */
+               if (reply->old_ia != NULL) {
+                       ia_id = &reply->old_ia->iaid_duid;
+                       ia_hash_delete(ia_pd_active,
+                                      (unsigned char *)ia_id->data,
+                                      ia_id->len, MDL);
+                       ia_dereference(&reply->old_ia, MDL);
                }
 
-               /* Put new ia_pd into the hash. */
-               ia_id = &reply->ia_pd->iaid_duid;
-               ia_pd_hash_add(ia_pd_active, (unsigned char *)ia_id->data,
-                              ia_id->len, reply->ia_pd, MDL);
+               /* Put new ia into the hash. */
+               ia_id = &reply->ia->iaid_duid;
+               ia_hash_add(ia_pd_active, (unsigned char *)ia_id->data,
+                           ia_id->len, reply->ia, MDL);
 
-               write_ia_pd(reply->ia_pd);
+               write_ia(reply->ia);
        }
 
       cleanup:
@@ -3184,16 +3198,16 @@ reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia_pd) {
                option_state_dereference(&packet_ia, MDL);
        if (reply->reply_ia != NULL)
                option_state_dereference(&reply->reply_ia, MDL);
-       if (ia_pd_data.data != NULL)
-               data_string_forget(&ia_pd_data, MDL);
+       if (ia_data.data != NULL)
+               data_string_forget(&ia_data, MDL);
        if (data.data != NULL)
                data_string_forget(&data, MDL);
-       if (reply->ia_pd != NULL)
-               ia_pd_dereference(&reply->ia_pd, MDL);
-       if (reply->old_ia_pd != NULL)
-               ia_pd_dereference(&reply->old_ia_pd, MDL);
-       if (reply->prefix != NULL)
-               iaprefix_dereference(&reply->prefix, MDL);
+       if (reply->ia != NULL)
+               ia_dereference(&reply->ia, MDL);
+       if (reply->old_ia != NULL)
+               ia_dereference(&reply->old_ia, MDL);
+       if (reply->lease != NULL)
+               iaaddr_dereference(&reply->lease, MDL);
 
        /*
         * ISC_R_CANCELED is a status code used by the prefix processing to
@@ -3222,7 +3236,7 @@ reply_process_prefix(struct reply_state *reply, struct option_cache *pref) {
        /* Initializes values that will be cleaned up. */
        memset(&iapref, 0, sizeof(iapref));
        memset(&data, 0, sizeof(data));
-       /* Note that reply->prefix may be set by prefix_is_owned() */
+       /* Note that reply->lease may be set by prefix_is_owned() */
 
        /*
         * There is no point trying to process an incoming prefix if there
@@ -3298,7 +3312,7 @@ reply_process_prefix(struct reply_state *reply, struct option_cache *pref) {
                            (status != ISC_R_ADDRINUSE)) 
                                goto cleanup;
 
-                       if (reply->prefix == NULL) {
+                       if (reply->lease == NULL) {
                                if (reply->packet->dhcpv6_msg_type ==
                                                        DHCPV6_REBIND) {
                                        reply->send_prefer = 0;
@@ -3360,10 +3374,10 @@ reply_process_prefix(struct reply_state *reply, struct option_cache *pref) {
                scope = &global_scope;
                group = reply->host->group;
        } else {
-               if (reply->prefix == NULL)
+               if (reply->lease == NULL)
                        log_fatal("Impossible condition at %s:%d.", MDL);
 
-               scope = &reply->prefix->scope;
+               scope = &reply->lease->scope;
                group = reply->shared->group;
        }
 
@@ -3408,7 +3422,7 @@ reply_process_prefix(struct reply_state *reply, struct option_cache *pref) {
                        goto cleanup;
        }
 
-       status = reply_process_is_prefixed(reply, reply->ia_pd, scope, group);
+       status = reply_process_is_prefixed(reply, scope, group);
        if (status != ISC_R_SUCCESS)
                goto cleanup;
 
@@ -3420,8 +3434,8 @@ reply_process_prefix(struct reply_state *reply, struct option_cache *pref) {
                data_string_forget(&iapref, MDL);
        if (data.data != NULL)
                data_string_forget(&data, MDL);
-       if (reply->prefix != NULL)
-               iaprefix_dereference(&reply->prefix, MDL);
+       if (reply->lease != NULL)
+               iaaddr_dereference(&reply->lease, MDL);
 
        return status;
 }
@@ -3450,18 +3464,18 @@ prefix_is_owned(struct reply_state *reply, struct iaddrcidrnet *pref) {
                return ISC_FALSE;
        }
 
-       if ((reply->old_ia_pd == NULL) ||
-           (reply->old_ia_pd->num_iaprefix == 0))
+       if ((reply->old_ia == NULL) ||
+           (reply->old_ia->num_iaaddr == 0))
                return ISC_FALSE;
 
-       for (i = 0 ; i < reply->old_ia_pd->num_iaprefix ; i++) {
-               struct iaprefix *tmp;
+       for (i = 0 ; i < reply->old_ia->num_iaaddr ; i++) {
+               struct iaaddr *tmp;
 
-               tmp = reply->old_ia_pd->iaprefix[i];
+               tmp = reply->old_ia->iaaddr[i];
 
                if ((pref->bits == (int) tmp->plen) &&
-                   memcmp(pref->lo_addr.iabuf, &tmp->pref, 16) == 0) {
-                       iaprefix_reference(&reply->prefix, tmp, MDL);
+                   memcmp(pref->lo_addr.iabuf, &tmp->addr, 16) == 0) {
+                       iaaddr_reference(&reply->lease, tmp, MDL);
                        return ISC_TRUE;
                }
        }
@@ -3476,14 +3490,14 @@ prefix_is_owned(struct reply_state *reply, struct iaddrcidrnet *pref) {
 static isc_result_t
 reply_process_try_prefix(struct reply_state *reply,
                         struct iaddrcidrnet *pref) {
-       isc_result_t status = ISC_R_FAILURE;
-       struct ipv6_ppool *ppool;
+       isc_result_t status = ISC_R_NORESOURCES;
+       struct ipv6_pool *pool;
        int i;
        struct data_string data_pref;
 
        if ((reply == NULL) || (reply->shared == NULL) ||
-           (reply->shared->ipv6_ppools == NULL) || (pref == NULL) ||
-           (reply->prefix != NULL))
+           (reply->shared->ipv6_pools == NULL) || (pref == NULL) ||
+           (reply->lease != NULL))
                return ISC_R_INVALIDARG;
 
        memset(&data_pref, 0, sizeof(data_pref));
@@ -3496,11 +3510,10 @@ reply_process_try_prefix(struct reply_state *reply,
        data_pref.buffer->data[0] = (u_int8_t) pref->bits;
        memcpy(data_pref.buffer->data + 1, pref->lo_addr.iabuf, 16);
 
-       for (i = 0 ;; i++) {
-               ppool = reply->shared->ipv6_ppools[i];
-               if (ppool == NULL)
-                       break;
-               status = try_client_v6_prefix(&reply->prefix, ppool,
+       for (i = 0 ; (pool = reply->shared->ipv6_pools[i]) != NULL ; i++) {
+               if (pool->pool_type != D6O_IA_PD)
+                       continue;
+               status = try_client_v6_prefix(&reply->lease, pool,
                                              &data_pref);
                if (status == ISC_R_SUCCESS)
                        break;
@@ -3519,7 +3532,7 @@ static isc_result_t
 find_client_prefix(struct reply_state *reply) {
        struct iaddrcidrnet send_pref;
        isc_result_t status = ISC_R_NORESOURCES;
-       struct iaprefix *prefix, *best_prefix = NULL;
+       struct iaaddr *prefix, *best_prefix = NULL;
        struct binding_scope **scope;
        struct group *group;
        int i;
@@ -3553,9 +3566,9 @@ find_client_prefix(struct reply_state *reply) {
                goto send_pref;
        }
 
-       if (reply->old_ia_pd != NULL)  {
-               for (i = 0 ; i < reply->old_ia_pd->num_iaprefix ; i++) {
-                       prefix = reply->old_ia_pd->iaprefix[i];
+       if (reply->old_ia != NULL)  {
+               for (i = 0 ; i < reply->old_ia->num_iaaddr ; i++) {
+                       prefix = reply->old_ia->iaaddr[i];
 
                        best_prefix = prefix_compare(reply, prefix,
                                                     best_prefix);
@@ -3566,10 +3579,10 @@ find_client_prefix(struct reply_state *reply) {
         * abandoned prefix.
         */
        if ((best_prefix == NULL) || (best_prefix->state == FTS_ABANDONED)) {
-               status = pick_v6_prefix(&reply->prefix, reply->preflen,
+               status = pick_v6_prefix(&reply->lease, reply->preflen,
                                        reply->shared, &reply->client_id);
        } else if (best_prefix != NULL) {
-               iaprefix_reference(&reply->prefix, best_prefix, MDL);
+               iaaddr_reference(&reply->lease, best_prefix, MDL);
                status = ISC_R_SUCCESS;
        }
 
@@ -3579,25 +3592,25 @@ find_client_prefix(struct reply_state *reply) {
                log_error("Reclaiming abandoned prefixes is not yet "
                          "supported.  Treating this as an out of space "
                          "condition.");
-               /* prefix_reference(&reply->prefix, best_prefix, MDL); */
+               /* iaaddr_reference(&reply->lease, best_prefix, MDL); */
        }
 
        /* Give up now if we didn't find a prefix. */
        if (status != ISC_R_SUCCESS)
                return status;
 
-       if (reply->prefix == NULL)
+       if (reply->lease == NULL)
                log_fatal("Impossible condition at %s:%d.", MDL);
 
-       scope = &reply->prefix->scope;
+       scope = &reply->lease->scope;
        group = reply->shared->group;
 
        send_pref.lo_addr.len = 16;
-       memcpy(send_pref.lo_addr.iabuf, &reply->prefix->pref, 16);
-       send_pref.bits = (int) reply->prefix->plen;
+       memcpy(send_pref.lo_addr.iabuf, &reply->lease->addr, 16);
+       send_pref.bits = (int) reply->lease->plen;
 
       send_pref:
-       status = reply_process_is_prefixed(reply, reply->ia_pd, scope, group);
+       status = reply_process_is_prefixed(reply, scope, group);
        if (status != ISC_R_SUCCESS)
                return status;
 
@@ -3610,7 +3623,7 @@ find_client_prefix(struct reply_state *reply) {
  * into the option state.
  */
 static isc_result_t
-reply_process_is_prefixed(struct reply_state *reply, struct ia_pd *ia_pd,
+reply_process_is_prefixed(struct reply_state *reply,
                          struct binding_scope **scope, struct group *group)
 {
        isc_result_t status = ISC_R_SUCCESS;
@@ -3684,15 +3697,15 @@ reply_process_is_prefixed(struct reply_state *reply, struct ia_pd *ia_pd,
                reply->valid = reply->send_valid;
 
        /* Perform dynamic prefix related update work. */
-       if (reply->prefix != NULL) {
+       if (reply->lease != NULL) {
                /* Advance (or rewind) the valid lifetime. */
                if (reply->buf.reply.msg_type == DHCPV6_REPLY) {
-                       reply->prefix->soft_lifetime_end_time =
+                       reply->lease->soft_lifetime_end_time =
                                cur_time + reply->send_valid;
                        /* Wait before renew! */
                }
 
-               status = ia_pd_add_iaprefix(ia_pd, reply->prefix, MDL);
+               status = ia_add_iaaddr(reply->ia, reply->lease, MDL);
                if (status != ISC_R_SUCCESS) {
                        log_fatal("reply_process_is_prefixed: Unable to "
                                  "attach prefix to new IA_PD: %s",
@@ -3702,8 +3715,8 @@ reply_process_is_prefixed(struct reply_state *reply, struct ia_pd *ia_pd,
                /*
                 * If this is a new prefix, make sure it is attached somewhere.
                 */
-               if (reply->prefix->ia_pd == NULL) {
-                       ia_pd_reference(&reply->prefix->ia_pd, ia_pd, MDL);
+               if (reply->lease->ia == NULL) {
+                       ia_reference(&reply->lease->ia, reply->ia, MDL);
                }
        }
 
@@ -3755,7 +3768,7 @@ reply_process_send_prefix(struct reply_state *reply,
                goto cleanup;
        }
 
-       reply->ia_resources_included = ISC_TRUE;
+       reply->resources_included = ISC_TRUE;
 
       cleanup:
        if (data.data != NULL)
@@ -3765,9 +3778,9 @@ reply_process_send_prefix(struct reply_state *reply,
 }
 
 /* Choose the better of two prefixes. */
-static struct iaprefix *
+static struct iaaddr *
 prefix_compare(struct reply_state *reply,
-              struct iaprefix *alpha, struct iaprefix *beta) {
+              struct iaaddr *alpha, struct iaaddr *beta) {
        if (alpha == NULL)
                return beta;
        if (beta == NULL)
@@ -4263,7 +4276,7 @@ ia_na_match_decline(const struct data_string *client_id,
                            tmp_addr, sizeof(tmp_addr)));
        if (lease != NULL) {
                decline_lease6(lease->ipv6_pool, lease);
-               write_ia(lease->ia_na);
+               write_ia(lease->ia);
        }
 }
 
@@ -4366,7 +4379,7 @@ iterate_over_ia_na(struct data_string *reply_ret,
        int reply_ofs = (int)((char *)reply->options - (char *)reply);
        char status_msg[32];
        struct iaaddr *lease;
-       struct ia_na *existing_ia_na;
+       struct ia_xx *existing_ia_na;
        int i;
        struct data_string key;
        u_int32_t iaid;
@@ -4548,9 +4561,9 @@ iterate_over_ia_na(struct data_string *reply_ret,
                        }
 
                        existing_ia_na = NULL;
-                       if (ia_na_hash_lookup(&existing_ia_na, ia_na_active, 
-                                             (unsigned char *)key.data, 
-                                             key.len, MDL)) {
+                       if (ia_hash_lookup(&existing_ia_na, ia_na_active, 
+                                          (unsigned char *)key.data, 
+                                          key.len, MDL)) {
                                /* 
                                 * Make sure this address is in the IA_NA.
                                 */
@@ -4679,7 +4692,7 @@ ia_na_match_release(const struct data_string *client_id,
                 inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
        if (lease != NULL) {
                release_lease6(lease->ipv6_pool, lease);
-               write_ia(lease->ia_na);
+               write_ia(lease->ia);
        }
 }
 
@@ -4760,7 +4773,7 @@ exit:
 static void
 ia_pd_match_release(const struct data_string *client_id,
                    const struct data_string *iapref,
-                   struct iaprefix *prefix)
+                   struct iaaddr *prefix)
 {
        char tmp_addr[INET6_ADDRSTRLEN];
 
@@ -4770,8 +4783,8 @@ ia_pd_match_release(const struct data_string *client_id,
                           tmp_addr, sizeof(tmp_addr)),
                 (unsigned) getUChar(iapref->data + 8));
        if (prefix != NULL) {
-               release_prefix6(prefix->ipv6_ppool, prefix);
-               write_ia_pd(prefix->ia_pd);
+               release_lease6(prefix->ipv6_pool, prefix);
+               write_ia(prefix->ia);
        }
 }
 
@@ -4875,8 +4888,8 @@ iterate_over_ia_pd(struct data_string *reply_ret,
        int iaprefix_is_found;
        char reply_data[65536];
        int reply_ofs;
-       struct iaprefix *prefix;
-       struct ia_pd *existing_ia_pd;
+       struct iaaddr *prefix;
+       struct ia_xx *existing_ia_pd;
        int i;
        struct data_string key;
        u_int32_t iaid;
@@ -5013,26 +5026,26 @@ iterate_over_ia_pd(struct data_string *reply_ret,
                        }
 
                        existing_ia_pd = NULL;
-                       if (ia_pd_hash_lookup(&existing_ia_pd, ia_pd_active, 
-                                             (unsigned char *)key.data, 
-                                             key.len, MDL)) {
+                       if (ia_hash_lookup(&existing_ia_pd, ia_pd_active, 
+                                          (unsigned char *)key.data, 
+                                          key.len, MDL)) {
                                /* 
                                 * Make sure this prefix is in the IA_PD.
                                 */
                                for (i = 0;
-                                    i < existing_ia_pd->num_iaprefix;
+                                    i < existing_ia_pd->num_iaaddr;
                                     i++) {
-                                       struct iaprefix *tmp;
+                                       struct iaaddr *tmp;
                                        u_int8_t plen;
 
                                        plen = getUChar(iaprefix.data + 8);
-                                       tmp = existing_ia_pd->iaprefix[i];
+                                       tmp = existing_ia_pd->iaaddr[i];
                                        if ((tmp->plen == plen) &&
-                                           (memcmp(&tmp->pref,
+                                           (memcmp(&tmp->addr,
                                                    iaprefix.data + 9,
                                                    16) == 0)) {
-                                               iaprefix_reference(&prefix,
-                                                                  tmp, MDL);
+                                               iaaddr_reference(&prefix,
+                                                                tmp, MDL);
                                                break;
                                        }
                                }
@@ -5051,7 +5064,7 @@ iterate_over_ia_pd(struct data_string *reply_ret,
                }
 
                if (prefix != NULL) {
-                       iaprefix_dereference(&prefix, MDL);
+                       iaaddr_dereference(&prefix, MDL);
                }
 
                data_string_forget(&iaprefix, MDL);
@@ -5080,7 +5093,7 @@ iterate_over_ia_pd(struct data_string *reply_ret,
 
 exit:
        if (prefix != NULL) {
-               iaprefix_dereference(&prefix, MDL);
+               iaaddr_dereference(&prefix, MDL);
        }
        if (host_opt_state != NULL) {
                option_state_dereference(&host_opt_state, MDL);
@@ -5100,7 +5113,7 @@ exit:
 }
 
 /*
- * Release means a client is done with the addresses.
+ * Release means a client is done with the leases.
  */
 
 /* TODO: reject unicast messages, unless we set unicast option */
index 0c0a18990ec50c5b12d4c99c9abf77b769f27e44..021fdc37f7aaac66f75868a823726ef36bffdc77 100644 (file)
 #include "omapip/hash.h"
 #include "dst/md5.h"
 
-HASH_FUNCTIONS(ia_na, unsigned char *, struct ia_na, ia_na_hash_t,
-              ia_na_reference, ia_na_dereference, do_string_hash);
+HASH_FUNCTIONS(ia, unsigned char *, struct ia_xx, ia_hash_t,
+              ia_reference, ia_dereference, do_string_hash);
 
-ia_na_hash_t *ia_na_active;
-ia_na_hash_t *ia_ta_active;
-
-HASH_FUNCTIONS(ia_pd, unsigned char *, struct ia_pd, ia_pd_hash_t,
-              ia_pd_reference, ia_pd_dereference, do_string_hash);
-
-ia_pd_hash_t *ia_pd_active;
+ia_hash_t *ia_na_active;
+ia_hash_t *ia_ta_active;
+ia_hash_t *ia_pd_active;
 
 HASH_FUNCTIONS(iaaddr, struct in6_addr *, struct iaaddr, iaaddr_hash_t,
               iaaddr_reference, iaaddr_dereference, do_string_hash);
 
-HASH_FUNCTIONS(iaprefix, struct in6_addr *, struct iaprefix, iaprefix_hash_t,
-              iaprefix_reference, iaprefix_dereference, do_string_hash);
-
 struct ipv6_pool **pools;
 int num_pools;
 
-struct ipv6_ppool **ppools;
-int num_ppools;
-
 /*
- * Create a new IAADDR structure.
+ * Create a new IAADDR/PREFIX structure.
  *
  * - iaaddr must be a pointer to a (struct iaaddr *) pointer previously
  *   initialized to NULL
@@ -79,13 +69,14 @@ iaaddr_allocate(struct iaaddr **iaaddr, const char *file, int line) {
        tmp->refcnt = 1;
        tmp->state = FTS_FREE;
        tmp->heap_index = -1;
+       tmp->plen = 255;
 
        *iaaddr = tmp;
        return ISC_R_SUCCESS;
 }
 
 /*
- * Reference an IAADDR structure.
+ * Reference an IAADDR/PREFIX structure.
  *
  * - iaaddr must be a pointer to a (struct iaaddr *) pointer previously
  *   initialized to NULL
@@ -112,7 +103,7 @@ iaaddr_reference(struct iaaddr **iaaddr, struct iaaddr *src,
 
 
 /*
- * Dereference an IAADDR structure.
+ * Dereference an IAADDR/PREFIX structure.
  *
  * If it is the last reference, then the memory for the 
  * structure is freed.
@@ -135,8 +126,8 @@ iaaddr_dereference(struct iaaddr **iaaddr, const char *file, int line) {
                tmp->refcnt = 0;
        }
        if (tmp->refcnt == 0) {
-               if (tmp->ia_na != NULL) {
-                       ia_na_dereference(&(tmp->ia_na), file, line);
+               if (tmp->ia != NULL) {
+                       ia_dereference(&(tmp->ia), file, line);
                }
                if (tmp->ipv6_pool != NULL) {
                        ipv6_pool_dereference(&(tmp->ipv6_pool), file, line);
@@ -150,104 +141,6 @@ iaaddr_dereference(struct iaaddr **iaaddr, const char *file, int line) {
        return ISC_R_SUCCESS;
 }
 
-/*
- * Create a new IAPREFIX structure.
- *
- * - iapref must be a pointer to a (struct iaprefix *) pointer previously
- *   initialized to NULL
- */
-isc_result_t
-iaprefix_allocate(struct iaprefix **iapref, const char *file, int line) {
-       struct iaprefix *tmp;
-
-       if (iapref == NULL) {
-               log_error("%s(%d): NULL pointer reference", file, line);
-               return ISC_R_INVALIDARG;
-       }
-       if (*iapref != NULL) {
-               log_error("%s(%d): non-NULL pointer", file, line);
-               return ISC_R_INVALIDARG;
-       }
-
-       tmp = dmalloc(sizeof(*tmp), file, line);
-       if (tmp == NULL) {
-               return ISC_R_NOMEMORY;
-       }
-
-       tmp->refcnt = 1;
-       tmp->state = FTS_FREE;
-       tmp->heap_index = -1;
-
-       *iapref = tmp;
-       return ISC_R_SUCCESS;
-}
-
-/*
- * Reference an IAPREFIX structure.
- *
- * - iapref must be a pointer to a (struct iaprefix *) pointer previously
- *   initialized to NULL
- */
-isc_result_t
-iaprefix_reference(struct iaprefix **iapref, struct iaprefix *src,
-                const char *file, int line) {
-       if (iapref == NULL) {
-               log_error("%s(%d): NULL pointer reference", file, line);
-               return ISC_R_INVALIDARG;
-       }
-       if (*iapref != NULL) {
-               log_error("%s(%d): non-NULL pointer", file, line);
-               return ISC_R_INVALIDARG;
-       }
-       if (src == NULL) {
-               log_error("%s(%d): NULL pointer reference", file, line);
-               return ISC_R_INVALIDARG;
-       }
-       *iapref = src;
-       src->refcnt++;
-       return ISC_R_SUCCESS;
-}
-
-
-/*
- * Dereference an IAPREFIX structure.
- *
- * If it is the last reference, then the memory for the 
- * structure is freed.
- */
-isc_result_t
-iaprefix_dereference(struct iaprefix **iapref, const char *file, int line) {
-       struct iaprefix *tmp;
-
-       if ((iapref == NULL) || (*iapref == NULL)) {
-               log_error("%s(%d): NULL pointer", file, line);
-               return ISC_R_INVALIDARG;
-       }
-
-       tmp = *iapref;
-       *iapref = NULL;
-
-       tmp->refcnt--;
-       if (tmp->refcnt < 0) {
-               log_error("%s(%d): negative refcnt", file, line);
-               tmp->refcnt = 0;
-       }
-       if (tmp->refcnt == 0) {
-               if (tmp->ia_pd != NULL) {
-                       ia_pd_dereference(&(tmp->ia_pd), file, line);
-               }
-               if (tmp->ipv6_ppool != NULL) {
-                       ipv6_ppool_dereference(&(tmp->ipv6_ppool), file, line);
-               }
-               if (tmp->scope != NULL) {
-                       binding_scope_dereference(&tmp->scope, file, line);
-               }
-               dfree(tmp, file, line);
-       }
-
-       return ISC_R_SUCCESS;
-}
-
 /* 
  * Make the key that we use for IA.
  */
@@ -271,7 +164,7 @@ ia_make_key(struct data_string *key, u_int32_t iaid,
 /*
  * Create a new IA structure.
  *
- * - ia must be a pointer to a (struct ia_na *) pointer previously
+ * - ia must be a pointer to a (struct ia_xx *) pointer previously
  *   initialized to NULL
  * - iaid and duid are values from the client
  *
@@ -280,10 +173,10 @@ ia_make_key(struct data_string *key, u_int32_t iaid,
  *        between machines of different byte order
  */
 isc_result_t
-ia_na_allocate(struct ia_na **ia, u_int32_t iaid, 
-              const char *duid, unsigned int duid_len,
-              const char *file, int line) {
-       struct ia_na *tmp;
+ia_allocate(struct ia_xx **ia, u_int32_t iaid, 
+           const char *duid, unsigned int duid_len,
+           const char *file, int line) {
+       struct ia_xx *tmp;
 
        if (ia == NULL) {
                log_error("%s(%d): NULL pointer reference", file, line);
@@ -314,12 +207,12 @@ ia_na_allocate(struct ia_na **ia, u_int32_t iaid,
 /*
  * Reference an IA structure.
  *
- * - ia must be a pointer to a (struct ia_na *) pointer previously
+ * - ia must be a pointer to a (struct ia_xx *) pointer previously
  *   initialized to NULL
  */
 isc_result_t
-ia_na_reference(struct ia_na **ia, struct ia_na *src,
-               const char *file, int line) {
+ia_reference(struct ia_xx **ia, struct ia_xx *src,
+            const char *file, int line) {
        if (ia == NULL) {
                log_error("%s(%d): NULL pointer reference", file, line);
                return ISC_R_INVALIDARG;
@@ -344,8 +237,8 @@ ia_na_reference(struct ia_na **ia, struct ia_na *src,
  * structure is freed.
  */
 isc_result_t
-ia_na_dereference(struct ia_na **ia, const char *file, int line) {
-       struct ia_na *tmp;
+ia_dereference(struct ia_xx **ia, const char *file, int line) {
+       struct ia_xx *tmp;
        int i;
 
        if ((ia == NULL) || (*ia == NULL)) {
@@ -377,11 +270,11 @@ ia_na_dereference(struct ia_na **ia, const char *file, int line) {
 
 
 /*
- * Add an IAADDR entry to an IA structure.
+ * Add an IAADDR/PREFIX entry to an IA structure.
  */
 isc_result_t
-ia_na_add_iaaddr(struct ia_na *ia, struct iaaddr *iaaddr, 
-                const char *file, int line) {
+ia_add_iaaddr(struct ia_xx *ia, struct iaaddr *iaaddr, 
+             const char *file, int line) {
        int max;
        struct iaaddr **new;
 
@@ -389,8 +282,8 @@ ia_na_add_iaaddr(struct ia_na *ia, struct iaaddr *iaaddr,
         * Grow our array if we need to.
         * 
         * Note: we pick 4 as the increment, as that seems a reasonable
-        *       guess as to how many addresses we might expect on an 
-        *       interface.
+        *       guess as to how many addresses/prefixes we might expect
+        *       on an interface.
         */
        if (ia->max_iaaddr <= ia->num_iaaddr) {
                max = ia->max_iaaddr + 4;
@@ -412,13 +305,13 @@ ia_na_add_iaaddr(struct ia_na *ia, struct iaaddr *iaaddr,
 }
 
 /*
- * Remove an IAADDR entry to an IA structure.
+ * Remove an IAADDR/PREFIX entry to an IA structure.
  *
  * Note: if an IAADDR appears more than once, then only ONE will be removed.
  */
 void
-ia_na_remove_iaaddr(struct ia_na *ia, struct iaaddr *iaaddr,
-                   const char *file, int line) {
+ia_remove_iaaddr(struct ia_xx *ia, struct iaaddr *iaaddr,
+                const char *file, int line) {
        int i, j;
 
        for (i=0; i<ia->num_iaaddr; i++) {
@@ -431,23 +324,23 @@ ia_na_remove_iaaddr(struct ia_na *ia, struct iaaddr *iaaddr,
                        }
                        /* decrease our total count */
                        /* remove the back-reference in the IAADDR itself */
-                       ia_na_dereference(&iaaddr->ia_na, file, line);
+                       ia_dereference(&iaaddr->ia, file, line);
                        ia->num_iaaddr--;
                        return;
                }
        }
-       log_error("%s(%d): IAADDR not in IA", file, line);
+       log_error("%s(%d): IAADDR/PREFIX not in IA", file, line);
 }
 
 /*
- * Remove all addresses from an IA.
+ * Remove all addresses/prefixes from an IA.
  */
 void
-ia_na_remove_all_iaaddr(struct ia_na *ia, const char *file, int line) {
+ia_remove_all_iaaddr(struct ia_xx *ia, const char *file, int line) {
        int i;
 
        for (i=0; i<ia->num_iaaddr; i++) {
-               ia_na_dereference(&(ia->iaaddr[i]->ia_na), file, line);
+               ia_dereference(&(ia->iaaddr[i]->ia), file, line);
                iaaddr_dereference(&(ia->iaaddr[i]), file, line);
        }
        ia->num_iaaddr = 0;
@@ -457,7 +350,7 @@ ia_na_remove_all_iaaddr(struct ia_na *ia, const char *file, int line) {
  * Compare two IA.
  */
 isc_boolean_t
-ia_na_equal(const struct ia_na *a, const struct ia_na *b) 
+ia_equal(const struct ia_xx *a, const struct ia_xx *b) 
 {
        isc_boolean_t found;
        int i, j;
@@ -492,18 +385,20 @@ ia_na_equal(const struct ia_na *a, const struct ia_na *b)
        }
 
        /*
-        * Make sure we have the same number of addresses in each.
+        * Make sure we have the same number of addresses/prefixes in each.
         */
        if (a->num_iaaddr != b->num_iaaddr) {
                return ISC_FALSE;
        }
 
        /*
-        * Check that each address is present in both.
+        * Check that each address/prefix is present in both.
         */
        for (i=0; i<a->num_iaaddr; i++) {
                found = ISC_FALSE;
                for (j=0; j<a->num_iaaddr; j++) {
+                       if (a->iaaddr[i]->plen != b->iaaddr[i]->plen)
+                               continue;
                        if (memcmp(&(a->iaaddr[i]->addr),
                                   &(b->iaaddr[j]->addr), 
                                   sizeof(struct in6_addr)) == 0) {
@@ -522,260 +417,9 @@ ia_na_equal(const struct ia_na *a, const struct ia_na *b)
        return ISC_TRUE;
 }
 
-/*
- * Create a new IA_PD structure.
- *
- * - ia_pd must be a pointer to a (struct ia_pd *) pointer previously
- *   initialized to NULL
- * - iaid and duid are values from the client
- *
- * XXXsk: we don't concern ourself with the byte order of the IAID, 
- *        which might be a problem if we transfer this structure 
- *        between machines of different byte order
- */
-isc_result_t
-ia_pd_allocate(struct ia_pd **ia_pd, u_int32_t iaid, 
-              const char *duid, unsigned int duid_len,
-              const char *file, int line) {
-       struct ia_pd *tmp;
-
-       if (ia_pd == NULL) {
-               log_error("%s(%d): NULL pointer reference", file, line);
-               return ISC_R_INVALIDARG;
-       }
-       if (*ia_pd != NULL) {
-               log_error("%s(%d): non-NULL pointer", file, line);
-               return ISC_R_INVALIDARG;
-       }
-
-       tmp = dmalloc(sizeof(*tmp), file, line);
-       if (tmp == NULL) {
-               return ISC_R_NOMEMORY;
-       }
-
-       if (ia_make_key(&tmp->iaid_duid, iaid, 
-                       duid, duid_len, file, line) != ISC_R_SUCCESS) {
-               dfree(tmp, file, line);
-               return ISC_R_NOMEMORY;
-       }
-
-       tmp->refcnt = 1;
-
-       *ia_pd = tmp;
-       return ISC_R_SUCCESS;
-}
-
-/*
- * Reference an IA_PD structure.
- *
- * - ia_pd must be a pointer to a (struct ia_pd *) pointer previously
- *   initialized to NULL
- */
-isc_result_t
-ia_pd_reference(struct ia_pd **ia_pd, struct ia_pd *src,
-               const char *file, int line) {
-       if (ia_pd == NULL) {
-               log_error("%s(%d): NULL pointer reference", file, line);
-               return ISC_R_INVALIDARG;
-       }
-       if (*ia_pd != NULL) {
-               log_error("%s(%d): non-NULL pointer", file, line);
-               return ISC_R_INVALIDARG;
-       }
-       if (src == NULL) {
-               log_error("%s(%d): NULL pointer reference", file, line);
-               return ISC_R_INVALIDARG;
-       }
-       *ia_pd = src;
-       src->refcnt++;
-       return ISC_R_SUCCESS;
-}
-
-/*
- * Dereference an IA_PD structure.
- *
- * If it is the last reference, then the memory for the 
- * structure is freed.
- */
-isc_result_t
-ia_pd_dereference(struct ia_pd **ia_pd, const char *file, int line) {
-       struct ia_pd *tmp;
-       int i;
-
-       if ((ia_pd == NULL) || (*ia_pd == NULL)) {
-               log_error("%s(%d): NULL pointer", file, line);
-               return ISC_R_INVALIDARG;
-       }
-
-       tmp = *ia_pd;
-       *ia_pd = NULL;
-
-       tmp->refcnt--;
-       if (tmp->refcnt < 0) {
-               log_error("%s(%d): negative refcnt", file, line);
-               tmp->refcnt = 0;
-       }
-       if (tmp->refcnt == 0) {
-               if (tmp->iaprefix != NULL) {
-                       for (i=0; i<tmp->num_iaprefix; i++) {
-                               iaprefix_dereference(&(tmp->iaprefix[i]), 
-                                                    file, line);
-                       }
-                       dfree(tmp->iaprefix, file, line);
-               }
-               data_string_forget(&(tmp->iaid_duid), file, line);
-               dfree(tmp, file, line);
-       }
-       return ISC_R_SUCCESS;
-}
-
-
-/*
- * Add an IAPREFIX entry to an IA_PD structure.
- */
-isc_result_t
-ia_pd_add_iaprefix(struct ia_pd *ia_pd, struct iaprefix *iapref, 
-                  const char *file, int line) {
-       int max;
-       struct iaprefix **new;
-
-       /* 
-        * Grow our array if we need to.
-        * 
-        * Note: we pick 4 as the increment, as that seems a reasonable
-        *       guess as to how many prefixes we might expect on an 
-        *       interface.
-        */
-       if (ia_pd->max_iaprefix <= ia_pd->num_iaprefix) {
-               max = ia_pd->max_iaprefix + 4;
-               new = dmalloc(max * sizeof(struct iaprefix *), file, line);
-               if (new == NULL) {
-                       return ISC_R_NOMEMORY;
-               }
-               memcpy(new, ia_pd->iaprefix, 
-                      ia_pd->num_iaprefix * sizeof(struct iaprefix *));
-               ia_pd->iaprefix = new;
-               ia_pd->max_iaprefix = max;
-       }
-
-       iaprefix_reference(&(ia_pd->iaprefix[ia_pd->num_iaprefix]), iapref, 
-                          file, line);
-       ia_pd->num_iaprefix++;
-
-       return ISC_R_SUCCESS;
-}
-
-/*
- * Remove an IAPREFIX entry to an IA_PD structure.
- *
- * Note: if an IAPREFIX appears more than once, then only ONE will be removed.
- */
-void
-ia_pd_remove_iaprefix(struct ia_pd *ia_pd, struct iaprefix *iapref,
-                     const char *file, int line) {
-       int i, j;
-
-       for (i=0; i<ia_pd->num_iaprefix; i++) {
-               if (ia_pd->iaprefix[i] == iapref) {
-                       /* remove this IAPREFIX */
-                       iaprefix_dereference(&(ia_pd->iaprefix[i]),
-                                            file, line);
-                       /* move remaining IAPREFIX pointers down one */
-                       for (j=i+1; j < ia_pd->num_iaprefix; j++) {
-                               ia_pd->iaprefix[j-1] = ia_pd->iaprefix[j];
-                       }
-                       /* decrease our total count */
-                       /* remove the back-reference in the IAPREFIX itself */
-                       ia_pd_dereference(&iapref->ia_pd, file, line);
-                       ia_pd->num_iaprefix--;
-                       return;
-               }
-       }
-       log_error("%s(%d): IAPREFIX not in IA_PD", file, line);
-}
-
-/*
- * Remove all prefixes from an IA_PD.
- */
-void
-ia_pd_remove_all_iaprefix(struct ia_pd *ia_pd, const char *file, int line) {
-       int i;
-
-       for (i=0; i<ia_pd->num_iaprefix; i++) {
-               ia_pd_dereference(&(ia_pd->iaprefix[i]->ia_pd), file, line);
-               iaprefix_dereference(&(ia_pd->iaprefix[i]), file, line);
-       }
-       ia_pd->num_iaprefix = 0;
-}
-
-/*
- * Compare two IA_PD.
- */
-isc_boolean_t
-ia_pd_equal(const struct ia_pd *a, const struct ia_pd *b) 
-{
-       isc_boolean_t found;
-       int i, j;
-
-       /*
-        * Handle cases where one or both of the inputs is NULL.
-        */
-       if (a == NULL) {
-               if (b == NULL) {
-                       return ISC_TRUE;
-               } else {
-                       return ISC_FALSE;
-               }
-       }       
-
-       /*
-        * Check the DUID is the same.
-        */
-       if (a->iaid_duid.len != b->iaid_duid.len) {
-               return ISC_FALSE;
-       }
-       if (memcmp(a->iaid_duid.data, 
-                  b->iaid_duid.data, a->iaid_duid.len) != 0) {
-               return ISC_FALSE;
-       }
-
-       /*
-        * Make sure we have the same number of prefixes in each.
-        */
-       if (a->num_iaprefix != b->num_iaprefix) {
-               return ISC_FALSE;
-       }
-
-       /*
-        * Check that each prefix is present in both.
-        */
-       for (i=0; i<a->num_iaprefix; i++) {
-               found = ISC_FALSE;
-               for (j=0; j<a->num_iaprefix; j++) {
-                       if (a->iaprefix[i]->plen != b->iaprefix[i]->plen)
-                               continue;
-                       if (memcmp(&(a->iaprefix[i]->pref),
-                                  &(b->iaprefix[j]->pref), 
-                                  sizeof(struct in6_addr)) == 0) {
-                               found = ISC_TRUE;
-                               break;
-                       }
-               }
-               if (!found) {
-                       return ISC_FALSE;
-               }
-       }
-
-       /*
-        * These are the same in every way we care about.
-        */
-       return ISC_TRUE;
-}
-
 /*
  * Helper function for lease heaps.
  * Makes the top of the heap the oldest lease.
- * Note: this relies on the unique layout for leases!
  */
 static isc_boolean_t 
 lease_older(void *a, void *b) {
@@ -792,34 +436,25 @@ lease_older(void *a, void *b) {
 }
 
 /*
- * Helper function for lease address heaps.
+ * Helper function for lease address/prefix heaps.
  * Callback when an address's position in the heap changes.
  */
 static void
-lease_address_index_changed(void *iaaddr, unsigned int new_heap_index) {
+lease_index_changed(void *iaaddr, unsigned int new_heap_index) {
        ((struct iaaddr *)iaaddr)-> heap_index = new_heap_index;
 }
 
-/*
- * Helper function for lease prefix heaps.
- * Callback when a prefix's position in the heap changes.
- */
-static void
-lease_prefix_index_changed(void *iapref, unsigned int new_heap_index) {
-       ((struct iaprefix *)iapref)-> heap_index = new_heap_index;
-}
-
 
 /*
- * Create a new IPv6 lease (address) pool structure.
+ * Create a new IPv6 lease pool structure.
  *
  * - pool must be a pointer to a (struct ipv6_pool *) pointer previously
  *   initialized to NULL
  */
 isc_result_t
-ipv6_pool_allocate(struct ipv6_pool **pool,
+ipv6_pool_allocate(struct ipv6_pool **pool, u_int16_t type,
                   const struct in6_addr *start_addr, int bits, 
-                  const char *file, int line) {
+                  int units, const char *file, int line) {
        struct ipv6_pool *tmp;
 
        if (pool == NULL) {
@@ -837,19 +472,21 @@ ipv6_pool_allocate(struct ipv6_pool **pool,
        }
 
        tmp->refcnt = 1;
+       tmp->pool_type = type;
        tmp->start_addr = *start_addr;
        tmp->bits = bits;
+       tmp->units = units;
        if (!iaaddr_new_hash(&tmp->addrs, DEFAULT_HASH_SIZE, file, line)) {
                dfree(tmp, file, line);
                return ISC_R_NOMEMORY;
        }
-       if (isc_heap_create(lease_older, lease_address_index_changed,
+       if (isc_heap_create(lease_older, lease_index_changed,
                            0, &(tmp->active_timeouts)) != ISC_R_SUCCESS) {
                iaaddr_free_hash_table(&(tmp->addrs), file, line);
                dfree(tmp, file, line);
                return ISC_R_NOMEMORY;
        }
-       if (isc_heap_create(lease_older, lease_address_index_changed,
+       if (isc_heap_create(lease_older, lease_index_changed,
                            0, &(tmp->inactive_timeouts)) != ISC_R_SUCCESS) {
                isc_heap_destroy(&(tmp->active_timeouts));
                iaaddr_free_hash_table(&(tmp->addrs), file, line);
@@ -888,7 +525,7 @@ ipv6_pool_reference(struct ipv6_pool **pool, struct ipv6_pool *src,
 }
 
 /* 
- * Note: Each IAADDR in a pool is referenced by the pool. This is needed
+ * Note: Each IAADDR/PREFIX in a pool is referenced by the pool. This is needed
  * to prevent the IAADDR from being garbage collected out from under the
  * pool.
  *
@@ -958,156 +595,6 @@ ipv6_pool_dereference(struct ipv6_pool **pool, const char *file, int line) {
        return ISC_R_SUCCESS;
 }
 
-/*
- * Create a new IPv6 lease (prefix) pool structure.
- *
- * - ppool must be a pointer to a (struct ipv6_ppool *) pointer previously
- *   initialized to NULL
- */
-isc_result_t
-ipv6_ppool_allocate(struct ipv6_ppool **ppool,
-                   const struct in6_addr *start_pref,
-                   u_int8_t pool_plen, u_int8_t alloc_plen,
-                   const char *file, int line) {
-       struct ipv6_ppool *tmp;
-
-       if (ppool == NULL) {
-               log_error("%s(%d): NULL pointer reference", file, line);
-               return ISC_R_INVALIDARG;
-       }
-       if (*ppool != NULL) {
-               log_error("%s(%d): non-NULL pointer", file, line);
-               return ISC_R_INVALIDARG;
-       }
-
-       tmp = dmalloc(sizeof(*tmp), file, line);
-       if (tmp == NULL) {
-               return ISC_R_NOMEMORY;
-       }
-
-       tmp->refcnt = 1;
-       tmp->start_pref = *start_pref;
-       tmp->pool_plen = pool_plen;
-       tmp->alloc_plen = alloc_plen;
-       if (!iaprefix_new_hash(&tmp->prefs, DEFAULT_HASH_SIZE, file, line)) {
-               dfree(tmp, file, line);
-               return ISC_R_NOMEMORY;
-       }
-       if (isc_heap_create(lease_older, lease_prefix_index_changed,
-                           0, &(tmp->active_timeouts)) != ISC_R_SUCCESS) {
-               iaprefix_free_hash_table(&(tmp->prefs), file, line);
-               dfree(tmp, file, line);
-               return ISC_R_NOMEMORY;
-       }
-       if (isc_heap_create(lease_older, lease_prefix_index_changed,
-                           0, &(tmp->inactive_timeouts)) != ISC_R_SUCCESS) {
-               isc_heap_destroy(&(tmp->active_timeouts));
-               iaprefix_free_hash_table(&(tmp->prefs), file, line);
-               dfree(tmp, file, line);
-               return ISC_R_NOMEMORY;
-       }
-
-       *ppool = tmp;
-       return ISC_R_SUCCESS;
-}
-
-/*
- * Reference an IPv6 prefix pool structure.
- *
- * - ppool must be a pointer to a (struct ppool *) pointer previously
- *   initialized to NULL
- */
-isc_result_t
-ipv6_ppool_reference(struct ipv6_ppool **ppool, struct ipv6_ppool *src,
-                    const char *file, int line) {
-       if (ppool == NULL) {
-               log_error("%s(%d): NULL pointer reference", file, line);
-               return ISC_R_INVALIDARG;
-       }
-       if (*ppool != NULL) {
-               log_error("%s(%d): non-NULL pointer", file, line);
-               return ISC_R_INVALIDARG;
-       }
-       if (src == NULL) {
-               log_error("%s(%d): NULL pointer reference", file, line);
-               return ISC_R_INVALIDARG;
-       }
-       *ppool = src;
-       src->refcnt++;
-       return ISC_R_SUCCESS;
-}
-
-/* 
- * Note: Each IAPREFIX in a pool is referenced by the pool. This is needed
- * to prevent the IAPREFIX from being garbage collected out from under the
- * pool.
- *
- * The references are made from the hash and from the heap. The following
- * helper functions dereference these when a pool is destroyed.
- */
-
-/*
- * Helper function for prefix pool cleanup.
- * Dereference each of the hash entries in a pool.
- */
-static isc_result_t 
-dereference_phash_entry(const void *name, unsigned len, void *value) {
-       struct iaprefix *iapref = (struct iaprefix *)value;
-
-       iaprefix_dereference(&iapref, MDL);
-       return ISC_R_SUCCESS;
-}
-
-/*
- * Helper function for prefix pool cleanup.
- * Dereference each of the heap entries in a pool.
- */
-static void
-dereference_pheap_entry(void *value, void *dummy) {
-       struct iaprefix *iapref = (struct iaprefix *)value;
-
-       iaprefix_dereference(&iapref, MDL);
-}
-
-
-/*
- * Dereference an IPv6 prefix pool structure.
- *
- * If it is the last reference, then the memory for the 
- * structure is freed.
- */
-isc_result_t
-ipv6_ppool_dereference(struct ipv6_ppool **ppool, const char *file, int line) {
-       struct ipv6_ppool *tmp;
-
-       if ((ppool == NULL) || (*ppool == NULL)) {
-               log_error("%s(%d): NULL pointer", file, line);
-               return ISC_R_INVALIDARG;
-       }
-
-       tmp = *ppool;
-       *ppool = NULL;
-
-       tmp->refcnt--;
-       if (tmp->refcnt < 0) {
-               log_error("%s(%d): negative refcnt", file, line);
-               tmp->refcnt = 0;
-       }
-       if (tmp->refcnt == 0) {
-               iaprefix_hash_foreach(tmp->prefs, dereference_phash_entry);
-               iaprefix_free_hash_table(&(tmp->prefs), file, line);
-               isc_heap_foreach(tmp->active_timeouts, 
-                                dereference_pheap_entry, NULL);
-               isc_heap_destroy(&(tmp->active_timeouts));
-               isc_heap_foreach(tmp->inactive_timeouts, 
-                                dereference_pheap_entry, NULL);
-               isc_heap_destroy(&(tmp->inactive_timeouts));
-               dfree(tmp, file, line);
-       }
-
-       return ISC_R_SUCCESS;
-}
-
 /* 
  * Create an address by hashing the input, and using that for
  * the non-network part.
@@ -1265,13 +752,25 @@ create_lease6(struct ipv6_pool *pool, struct iaaddr **addr,
                }
 
                /* 
-                * Build an address or a temporary address.
+                * Build a resource.
                 */
-               if ((pool->bits & POOL_IS_FOR_TEMP) == 0) {
+               switch (pool->pool_type) {
+               case D6O_IA_NA:
+                       /* address */
                        build_address6(&tmp, &pool->start_addr,
                                       pool->bits, &ds);
-               } else {
+                       break;
+               case D6O_IA_TA:
+                       /* temporary address */
                        build_temporary6(&tmp, &pool->start_addr, &ds);
+                       break;
+               case D6O_IA_PD:
+                       /* prefix */
+                       log_error("create_lease6: prefix pool.");
+                       return ISC_R_INVALIDARG;
+               default:
+                       log_error("create_lease6: untyped pool.");
+                       return ISC_R_INVALIDARG;
                }
 
                /*
@@ -1328,6 +827,7 @@ create_lease6(struct ipv6_pool *pool, struct iaaddr **addr,
        if (result != ISC_R_SUCCESS) {
                return result;
        }
+       iaaddr->plen = 0;
        memcpy(&iaaddr->addr, &tmp, sizeof(iaaddr->addr));
 
        /*
@@ -1359,7 +859,7 @@ add_lease6(struct ipv6_pool *pool, struct iaaddr *iaaddr,
        ipv6_pool_reference(&iaaddr->ipv6_pool, pool, MDL);
 
        /*
-        * If this IAADDR is already in our structures, remove the 
+        * If this IAADDR/PREFIX is already in our structures, remove the 
         * old one.
         */
        test_iaaddr = NULL;
@@ -1399,7 +899,7 @@ add_lease6(struct ipv6_pool *pool, struct iaaddr *iaaddr,
        }
 
        /* 
-        * Add IAADDR to our structures.
+        * Add IAADDR/PREFIX to our structures.
         */
        tmp_iaaddr = NULL;
        iaaddr_reference(&tmp_iaaddr, iaaddr, MDL);
@@ -1475,8 +975,8 @@ move_lease_to_active(struct ipv6_pool *pool, struct iaaddr *addr) {
 /*
  * Renew an lease in the pool.
  *
- * To do this, first set the new hard_lifetime_end_time for the address, 
- * and then invoke renew_lease() on the address.
+ * To do this, first set the new hard_lifetime_end_time for the resource,
+ * and then invoke renew_lease() on it.
  *
  * WARNING: lease times must only be extended, never reduced!!!
  */
@@ -1510,7 +1010,9 @@ move_lease_to_inactive(struct ipv6_pool *pool, struct iaaddr *addr,
        insert_result = isc_heap_insert(pool->inactive_timeouts, addr);
        if (insert_result == ISC_R_SUCCESS) {
                /* Process events upon expiration. */
-               ddns_removals(NULL, addr);
+               if (pool->pool_type != D6O_IA_PD) {
+                       ddns_removals(NULL, addr);
+               }
 
                /* Binding scopes are no longer valid after expiry or
                 * release.
@@ -1666,7 +1168,7 @@ build_prefix6(struct in6_addr *pref,
 /*
  * Create a lease for the given prefix and client duid.
  *
- * - ppool must be a pointer to a (struct ppool *) pointer previously
+ * - pool must be a pointer to a (struct pool *) pointer previously
  *   initialized to NULL
  *
  * Right now we simply hash the DUID, and if we get a collision, we hash 
@@ -1685,15 +1187,15 @@ build_prefix6(struct in6_addr *pref,
  * the long term.
  */
 isc_result_t
-create_prefix6(struct ipv6_ppool *ppool, struct iaprefix **pref, 
+create_prefix6(struct ipv6_pool *pool, struct iaaddr **pref, 
               unsigned int *attempts,
               const struct data_string *uid,
               time_t soft_lifetime_end_time) {
        struct data_string ds;
        struct in6_addr tmp;
-       struct iaprefix *test_iapref;
+       struct iaaddr *test_iapref;
        struct data_string new_ds;
-       struct iaprefix *iapref;
+       struct iaaddr *iapref;
        isc_result_t result;
 
        /* 
@@ -1715,313 +1217,89 @@ create_prefix6(struct ipv6_ppool *ppool, struct iaprefix **pref,
                /* 
                 * Build a prefix
                 */
-               build_prefix6(&tmp, &ppool->start_pref,
-                             (int)ppool->pool_plen, (int)ppool->alloc_plen,
-                             &ds);
+               build_prefix6(&tmp, &pool->start_addr,
+                             pool->bits, pool->units, &ds);
 
                /*
                 * If this prefix is not in use, we're happy with it
                 */
                test_iapref = NULL;
-               if (iaprefix_hash_lookup(&test_iapref, ppool->prefs,
-                                        &tmp, sizeof(tmp), MDL) == 0) {
+               if (iaaddr_hash_lookup(&test_iapref, pool->addrs,
+                                      &tmp, sizeof(tmp), MDL) == 0) {
                        break;
                }
-               iaprefix_dereference(&test_iapref, MDL);
+               iaaddr_dereference(&test_iapref, MDL);
 
                /* 
                 * Otherwise, we create a new input, adding the prefix
                 */
                memset(&new_ds, 0, sizeof(new_ds));
-               new_ds.len = ds.len + sizeof(tmp);
-               if (!buffer_allocate(&new_ds.buffer, new_ds.len, MDL)) {
-                       data_string_forget(&ds, MDL);
-                       return ISC_R_NOMEMORY;
-               }
-               new_ds.data = new_ds.buffer->data;
-               memcpy(new_ds.buffer->data, ds.data, ds.len);
-               memcpy(new_ds.buffer->data + ds.len, &tmp, sizeof(tmp));
-               data_string_forget(&ds, MDL);
-               data_string_copy(&ds, &new_ds, MDL);
-               data_string_forget(&new_ds, MDL);
-       }
-
-       data_string_forget(&ds, MDL);
-
-       /* 
-        * We're happy with the prefix, create an IAPREFIX
-        * to hold it.
-        */
-       iapref = NULL;
-       result = iaprefix_allocate(&iapref, MDL);
-       if (result != ISC_R_SUCCESS) {
-               return result;
-       }
-       iapref->plen = ppool->alloc_plen;
-       memcpy(&iapref->pref, &tmp, sizeof(iapref->pref));
-
-       /*
-        * Add the prefix to the pool (note state is free, not active?!).
-        */
-       result = add_prefix6(ppool, iapref, soft_lifetime_end_time);
-       if (result == ISC_R_SUCCESS) {
-               iaprefix_reference(pref, iapref, MDL);
-       }
-       iaprefix_dereference(&iapref, MDL);
-       return result;
-}
-
-/*
- * Put a prefix in the pool directly. This is intended to be used when
- * loading leases from the file.
- */
-isc_result_t
-add_prefix6(struct ipv6_ppool *ppool, struct iaprefix *iapref,
-           time_t valid_lifetime_end_time) {
-       isc_result_t insert_result;
-       struct iaprefix *test_iapref;
-       struct iaprefix *tmp_iapref;
-
-       /* If a state was not assigned by the caller, assume active. */
-       if (iapref->state == 0)
-               iapref->state = FTS_ACTIVE;
-
-       ipv6_ppool_reference(&iapref->ipv6_ppool, ppool, MDL);
-
-       /*
-        * If this IAPREFIX is already in our structures, remove the 
-        * old one.
-        */
-       test_iapref = NULL;
-       if (iaprefix_hash_lookup(&test_iapref, ppool->prefs,
-                                &iapref->pref, sizeof(iapref->pref), MDL)) {
-               /* XXX: we should probably ask the iaprefix what heap it is on
-                * (as a consistency check).
-                * XXX: we should probably have one function to "put this
-                * prefix on its heap" rather than doing these if's
-                * everywhere.  If you add more states to this list, don't.
-                */
-               if ((test_iapref->state == FTS_ACTIVE) ||
-                   (test_iapref->state == FTS_ABANDONED)) {
-                       isc_heap_delete(ppool->active_timeouts,
-                                       test_iapref->heap_index);
-                       ppool->num_active--;
-               } else {
-                       isc_heap_delete(ppool->inactive_timeouts,
-                                       test_iapref->heap_index);
-                       ppool->num_inactive--;
-               }
-
-               iaprefix_hash_delete(ppool->prefs, &test_iapref->pref, 
-                                    sizeof(test_iapref->pref), MDL);
-
-               /*
-                * We're going to do a bit of evil trickery here.
-                *
-                * We need to dereference the entry once to remove our
-                * current reference (in test_iapref), and then one
-                * more time to remove the reference left when the
-                * prefix was added to the pool before.
-                */
-               tmp_iapref = test_iapref;
-               iaprefix_dereference(&test_iapref, MDL);
-               iaprefix_dereference(&tmp_iapref, MDL);
-       }
-
-       /* 
-        * Add IAPREFIX to our structures.
-        */
-       tmp_iapref = NULL;
-       iaprefix_reference(&tmp_iapref, iapref, MDL);
-       if ((tmp_iapref->state == FTS_ACTIVE) ||
-           (tmp_iapref->state == FTS_ABANDONED)) {
-               tmp_iapref->hard_lifetime_end_time = valid_lifetime_end_time;
-               iaprefix_hash_add(ppool->prefs, &tmp_iapref->pref, 
-                                 sizeof(tmp_iapref->pref), iapref, MDL);
-               insert_result = isc_heap_insert(ppool->active_timeouts,
-                                               tmp_iapref);
-               if (insert_result == ISC_R_SUCCESS)
-                       ppool->num_active++;
-       } else {
-               tmp_iapref->soft_lifetime_end_time = valid_lifetime_end_time;
-               insert_result = isc_heap_insert(ppool->inactive_timeouts,
-                                               tmp_iapref);
-               if (insert_result == ISC_R_SUCCESS)
-                       ppool->num_inactive++;
-       }
-       if (insert_result != ISC_R_SUCCESS) {
-               iaprefix_hash_delete(ppool->prefs, &iapref->pref, 
-                                    sizeof(iapref->pref), MDL);
-               iaprefix_dereference(&tmp_iapref, MDL);
-               return insert_result;
-       }
-
-       /* 
-        * Note: we intentionally leave tmp_iapref referenced; there
-        * is a reference in the heap/hash, after all.
-        */
-
-       return ISC_R_SUCCESS;
-}
-
-/*
- * Determine if a prefix is present in a pool or not.
- */
-isc_boolean_t
-prefix6_exists(const struct ipv6_ppool *ppool,
-              const struct in6_addr *pref, u_int8_t plen) {
-       struct iaprefix *test_iapref;
-
-       if (plen != ppool->alloc_plen)
-               return ISC_FALSE;
-
-       test_iapref = NULL;
-       if (iaprefix_hash_lookup(&test_iapref, ppool->prefs, 
-                                (void *)pref, sizeof(*pref), MDL)) {
-               iaprefix_dereference(&test_iapref, MDL);
-               return ISC_TRUE;
-       } else {
-               return ISC_FALSE;
-       }
-}
-
-/*
- * Put the prefix on our active pool.
- */
-static isc_result_t
-move_prefix_to_active(struct ipv6_ppool *ppool, struct iaprefix *pref) {
-       isc_result_t insert_result;
-       int old_heap_index;
-
-       old_heap_index = pref->heap_index;
-       insert_result = isc_heap_insert(ppool->active_timeouts, pref);
-       if (insert_result == ISC_R_SUCCESS) {
-                       iaprefix_hash_add(ppool->prefs, &pref->pref, 
-                                 sizeof(pref->pref), pref, MDL);
-               isc_heap_delete(ppool->inactive_timeouts, old_heap_index);
-               ppool->num_active++;
-               ppool->num_inactive--;
-               pref->state = FTS_ACTIVE;
-       }
-       return insert_result;
-}
-
-/*
- * Renew a prefix in the pool.
- *
- * To do this, first set the new hard_lifetime_end_time for the prefix, 
- * and then invoke renew_prefix() on the prefix.
- *
- * WARNING: lease times must only be extended, never reduced!!!
- */
-isc_result_t
-renew_prefix6(struct ipv6_ppool *ppool, struct iaprefix *pref) {
-       /*
-        * If we're already active, then we can just move our expiration
-        * time down the heap. 
-        *
-        * Otherwise, we have to move from the inactive heap to the 
-        * active heap.
-        */
-       if (pref->state == FTS_ACTIVE) {
-               isc_heap_decreased(ppool->active_timeouts, pref->heap_index);
-               return ISC_R_SUCCESS;
-       } else {
-               return move_prefix_to_active(ppool, pref);
-       }
-}
-
-/*
- * Put the prefix on our inactive pool, with the specified state.
- */
-static isc_result_t
-move_prefix_to_inactive(struct ipv6_ppool *ppool, struct iaprefix *pref, 
-                       binding_state_t state) {
-       isc_result_t insert_result;
-       int old_heap_index;
-
-       old_heap_index = pref->heap_index;
-       insert_result = isc_heap_insert(ppool->inactive_timeouts, pref);
-       if (insert_result == ISC_R_SUCCESS) {
-               /* Process events upon expiration. */
-               /* No DDNS for prefixes. */
-
-               /* Binding scopes are no longer valid after expiry or
-                * release.
-                */
-               if (pref->scope != NULL) {
-                       binding_scope_dereference(&pref->scope, MDL);
+               new_ds.len = ds.len + sizeof(tmp);
+               if (!buffer_allocate(&new_ds.buffer, new_ds.len, MDL)) {
+                       data_string_forget(&ds, MDL);
+                       return ISC_R_NOMEMORY;
                }
-
-               iaprefix_hash_delete(ppool->prefs, 
-                                    &pref->pref, sizeof(pref->pref), MDL);
-               isc_heap_delete(ppool->active_timeouts, old_heap_index);
-               pref->state = state;
-               ppool->num_active--;
-               ppool->num_inactive++;
+               new_ds.data = new_ds.buffer->data;
+               memcpy(new_ds.buffer->data, ds.data, ds.len);
+               memcpy(new_ds.buffer->data + ds.len, &tmp, sizeof(tmp));
+               data_string_forget(&ds, MDL);
+               data_string_copy(&ds, &new_ds, MDL);
+               data_string_forget(&new_ds, MDL);
        }
-       return insert_result;
-}
 
-/*
- * Expire the oldest prefix if it's lifetime_end_time is 
- * older than the given time.
- *
- * - iapref must be a pointer to a (struct iaprefix *) pointer previously
- *   initialized to NULL
- *
- * On return iapref has a reference to the removed entry. It is left
- * pointing to NULL if the oldest prefix has not expired.
- */
-isc_result_t
-expire_prefix6(struct iaprefix **pref, struct ipv6_ppool *ppool, time_t now) {
-       struct iaprefix *tmp;
-       isc_result_t result;
+       data_string_forget(&ds, MDL);
 
-       if (pref == NULL) {
-               log_error("%s(%d): NULL pointer reference", MDL);
-               return ISC_R_INVALIDARG;
-       }
-       if (*pref != NULL) {
-               log_error("%s(%d): non-NULL pointer", MDL);
-               return ISC_R_INVALIDARG;
+       /* 
+        * We're happy with the prefix, create an IAPREFIX
+        * to hold it.
+        */
+       iapref = NULL;
+       result = iaaddr_allocate(&iapref, MDL);
+       if (result != ISC_R_SUCCESS) {
+               return result;
        }
+       iapref->plen = (u_int8_t)pool->units;
+       memcpy(&iapref->addr, &tmp, sizeof(iapref->addr));
 
-       if (ppool->num_active > 0) {
-               tmp = (struct iaprefix *)
-                       isc_heap_element(ppool->active_timeouts, 1);
-               if (now > tmp->hard_lifetime_end_time) {
-                       result = move_prefix_to_inactive(ppool, tmp,
-                                                        FTS_EXPIRED);
-                       if (result == ISC_R_SUCCESS) {
-                               iaprefix_reference(pref, tmp, MDL);
-                       }
-                       return result;
-               }
+       /*
+        * Add the prefix to the pool (note state is free, not active?!).
+        */
+       result = add_lease6(pool, iapref, soft_lifetime_end_time);
+       if (result == ISC_R_SUCCESS) {
+               iaaddr_reference(pref, iapref, MDL);
        }
-       return ISC_R_SUCCESS;
+       iaaddr_dereference(&iapref, MDL);
+       return result;
 }
 
-
 /*
- * Put the returned prefix on our inactive pool.
+ * Determine if a prefix is present in a pool or not.
  */
-isc_result_t
-release_prefix6(struct ipv6_ppool *ppool, struct iaprefix *pref) {
-       if (pref->state == FTS_ACTIVE) {
-               return move_prefix_to_inactive(ppool, pref, FTS_RELEASED);
+isc_boolean_t
+prefix6_exists(const struct ipv6_pool *pool,
+              const struct in6_addr *pref, u_int8_t plen) {
+       struct iaaddr *test_iapref;
+
+       if ((int)plen != pool->units)
+               return ISC_FALSE;
+
+       test_iapref = NULL;
+       if (iaaddr_hash_lookup(&test_iapref, pool->addrs, 
+                              (void *)pref, sizeof(*pref), MDL)) {
+               iaaddr_dereference(&test_iapref, MDL);
+               return ISC_TRUE;
        } else {
-               return ISC_R_SUCCESS;
+               return ISC_FALSE;
        }
 }
 
 /*
- * Mark an IPv6 address as unavailable from a pool.
+ * Mark an IPv6 address/prefix as unavailable from a pool.
  *
  * This is used for host entries and the addresses of the server itself.
  */
 isc_result_t
-mark_address_unavailable(struct ipv6_pool *pool, const struct in6_addr *addr) {
+mark_lease_unavailable(struct ipv6_pool *pool, const struct in6_addr *addr) {
        struct iaaddr *dummy_iaaddr;
        isc_result_t result;
 
@@ -2035,27 +1313,6 @@ mark_address_unavailable(struct ipv6_pool *pool, const struct in6_addr *addr) {
        return result;
 }
 
-/*
- * Mark an IPv6 prefix as unavailable from a prefix pool.
- *
- * This is used for host entries.
- */
-isc_result_t
-mark_prefix_unavailable(struct ipv6_ppool *ppool,
-                       const struct in6_addr *pref) {
-       struct iaprefix *dummy_iapref;
-       isc_result_t result;
-
-       dummy_iapref = NULL;
-       result = iaprefix_allocate(&dummy_iapref, MDL);
-       if (result == ISC_R_SUCCESS) {
-               dummy_iapref->pref = *pref;
-               iaprefix_hash_add(ppool->prefs, &dummy_iapref->pref,
-                                 sizeof(*pref), dummy_iapref, MDL);
-       }
-       return result;
-}
-
 /* 
  * Add a pool.
  */
@@ -2081,38 +1338,11 @@ add_ipv6_pool(struct ipv6_pool *pool) {
        return ISC_R_SUCCESS;
 }
 
-/* 
- * Add a prefix pool.
- */
-isc_result_t
-add_ipv6_ppool(struct ipv6_ppool *ppool) {
-       struct ipv6_ppool **new_ppools;
-
-       new_ppools = dmalloc(sizeof(struct ipv6_ppool *) * (num_ppools + 1),
-                            MDL);
-       if (new_ppools == NULL) {
-               return ISC_R_NOMEMORY;
-       }
-
-       if (num_ppools > 0) {
-               memcpy(new_ppools, ppools, 
-                      sizeof(struct ipv6_ppool *) * num_ppools);
-               dfree(ppools, MDL);
-       }
-       ppools = new_ppools;
-
-       ppools[num_ppools] = NULL;
-       ipv6_ppool_reference(&ppools[num_ppools], ppool, MDL);
-       num_ppools++;
-       return ISC_R_SUCCESS;
-}
-
-
 static void
 cleanup_old_expired(struct ipv6_pool *pool) {
        struct iaaddr *tmp;
-       struct ia_na *ia;
-       struct ia_na *ia_active;
+       struct ia_xx *ia;
+       struct ia_xx *ia_active;
        unsigned char *tmpd;
        time_t timeout;
        
@@ -2132,36 +1362,42 @@ cleanup_old_expired(struct ipv6_pool *pool) {
                isc_heap_delete(pool->inactive_timeouts, tmp->heap_index);
                pool->num_inactive--;
 
-               if (tmp->ia_na != NULL) {
+               if (tmp->ia != NULL) {
                        /*
-                        * Check to see if this IA is in the active list,
-                        * but has no remaining addresses. If so, remove it
+                        * Check to see if this IA is in an active list,
+                        * but has no remaining resources. If so, remove it
                         * from the active list.
                         */
                        ia = NULL;
-                       ia_na_reference(&ia, tmp->ia_na, MDL);
-                       ia_na_remove_iaaddr(ia, tmp, MDL);
+                       ia_reference(&ia, tmp->ia, MDL);
+                       ia_remove_iaaddr(ia, tmp, MDL);
                        ia_active = NULL;
                        tmpd = (unsigned char *)ia->iaid_duid.data;
                        if ((ia->ia_type == D6O_IA_NA) &&
                            (ia->num_iaaddr <= 0) &&
-                           (ia_na_hash_lookup(&ia_active, ia_na_active, tmpd,
-                                              ia->iaid_duid.len,
-                                              MDL) == 0) &&
+                           (ia_hash_lookup(&ia_active, ia_na_active, tmpd,
+                                           ia->iaid_duid.len, MDL) == 0) &&
                            (ia_active == ia)) {
-                               ia_na_hash_delete(ia_na_active, tmpd, 
-                                                 ia->iaid_duid.len, MDL);
+                               ia_hash_delete(ia_na_active, tmpd, 
+                                              ia->iaid_duid.len, MDL);
                        }
                        if ((ia->ia_type == D6O_IA_TA) &&
                            (ia->num_iaaddr <= 0) &&
-                           (ia_na_hash_lookup(&ia_active, ia_ta_active, tmpd,
-                                              ia->iaid_duid.len,
-                                              MDL) == 0) &&
+                           (ia_hash_lookup(&ia_active, ia_ta_active, tmpd,
+                                           ia->iaid_duid.len, MDL) == 0) &&
+                           (ia_active == ia)) {
+                               ia_hash_delete(ia_ta_active, tmpd, 
+                                              ia->iaid_duid.len, MDL);
+                       }
+                       if ((ia->ia_type == D6O_IA_PD) &&
+                           (ia->num_iaaddr <= 0) &&
+                           (ia_hash_lookup(&ia_active, ia_pd_active, tmpd,
+                                           ia->iaid_duid.len, MDL) == 0) &&
                            (ia_active == ia)) {
-                               ia_na_hash_delete(ia_ta_active, tmpd, 
-                                                 ia->iaid_duid.len, MDL);
+                               ia_hash_delete(ia_pd_active, tmpd, 
+                                              ia->iaid_duid.len, MDL);
                        }
-                       ia_na_dereference(&ia, MDL);
+                       ia_dereference(&ia, MDL);
                }
                iaaddr_dereference(&tmp, MDL);
        }
@@ -2195,9 +1431,11 @@ lease_timeout_support(void *vpool) {
                 * DH: Do we want to do this on a special 'depref'
                 * timer rather than expiration timer?
                 */
-               ddns_removals(NULL, addr);
+               if (pool->pool_type != D6O_IA_PD) {
+                       ddns_removals(NULL, addr);
+               }
 
-               write_ia(addr->ia_na);
+               write_ia(addr->ia);
 
                iaaddr_dereference(&addr, MDL);
        }
@@ -2269,151 +1507,6 @@ schedule_all_ipv6_lease_timeouts(void) {
        }
 }
 
-static void
-cleanup_old_pexpired(struct ipv6_ppool *ppool) {
-       struct iaprefix *tmp;
-       struct ia_pd *ia_pd;
-       struct ia_pd *ia_active;
-       unsigned char *tmpd;
-       time_t timeout;
-       
-       while (ppool->num_inactive > 0) {
-               tmp = (struct iaprefix *)
-                       isc_heap_element(ppool->inactive_timeouts, 1);
-               if (tmp->hard_lifetime_end_time != 0) {
-                       timeout = tmp->hard_lifetime_end_time;
-                       timeout += EXPIRED_IPV6_CLEANUP_TIME;
-               } else {
-                       timeout = tmp->soft_lifetime_end_time;
-               }
-               if (cur_time < timeout) {
-                       break;
-               }
-
-               isc_heap_delete(ppool->inactive_timeouts, tmp->heap_index);
-               ppool->num_inactive--;
-
-               if (tmp->ia_pd != NULL) {
-                       /*
-                        * Check to see if this IA_PD is in the active list,
-                        * but has no remaining prefixes. If so, remove it
-                        * from the active list.
-                        */
-                       ia_pd = NULL;
-                       ia_pd_reference(&ia_pd, tmp->ia_pd, MDL);
-                       ia_pd_remove_iaprefix(ia_pd, tmp, MDL);
-                       ia_active = NULL;
-                       tmpd = (unsigned char *)ia_pd->iaid_duid.data;
-                       if ((ia_pd->num_iaprefix <= 0) &&
-                           (ia_pd_hash_lookup(&ia_active, ia_pd_active,
-                                              tmpd, ia_pd->iaid_duid.len,
-                                              MDL) == 0) &&
-                           (ia_active == ia_pd)) {
-                               ia_pd_hash_delete(ia_pd_active, tmpd, 
-                                                 ia_pd->iaid_duid.len, MDL);
-                       }
-                       ia_pd_dereference(&ia_pd, MDL);
-               }
-               iaprefix_dereference(&tmp, MDL);
-       }
-}
-
-static void
-prefix_timeout_support(void *vppool) {
-       struct ipv6_ppool *ppool;
-       struct iaprefix *pref;
-       
-       ppool = (struct ipv6_ppool *)vppool;
-       for (;;) {
-               /*
-                * Get the next prefix scheduled to expire.
-                *
-                * Note that if there are no prefixes in the pool, 
-                * expire_prefix6() will return ISC_R_SUCCESS with 
-                * a NULL prefix.
-                */
-               pref = NULL;
-               if (expire_prefix6(&pref, ppool, cur_time) != ISC_R_SUCCESS) {
-                       break;
-               }
-               if (pref == NULL) {
-                       break;
-               }
-
-               /* No DDNS for prefixes. */
-
-               write_ia_pd(pref->ia_pd);
-
-               iaprefix_dereference(&pref, MDL);
-       }
-
-       /*
-        * Do some cleanup of our expired prefixes.
-        */
-       cleanup_old_pexpired(ppool);
-
-       /*
-        * Schedule next round of expirations.
-        */
-       schedule_prefix_timeout(ppool);
-}
-
-/*
- * For a given prefix pool, add a timer that will remove the next
- * prefix to expire.
- */
-void 
-schedule_prefix_timeout(struct ipv6_ppool *ppool) {
-       struct iaprefix *tmp;
-       time_t timeout;
-       time_t next_timeout;
-       struct timeval tv;
-
-       next_timeout = MAX_TIME;
-
-       if (ppool->num_active > 0) {
-               tmp = (struct iaprefix *)
-                       isc_heap_element(ppool->active_timeouts, 1);
-               if (tmp->hard_lifetime_end_time < next_timeout) {
-                       next_timeout = tmp->hard_lifetime_end_time + 1;
-               }
-       }
-
-       if (ppool->num_inactive > 0) {
-               tmp = (struct iaprefix *)
-                       isc_heap_element(ppool->inactive_timeouts, 1);
-               if (tmp->hard_lifetime_end_time != 0) {
-                       timeout = tmp->hard_lifetime_end_time;
-                       timeout += EXPIRED_IPV6_CLEANUP_TIME;
-               } else {
-                       timeout = tmp->soft_lifetime_end_time + 1;
-               }
-               if (timeout < next_timeout) {
-                       next_timeout = timeout;
-               }
-       }
-
-       if (next_timeout < MAX_TIME) {
-               tv.tv_sec = next_timeout;
-               tv.tv_usec = 0;
-               add_timeout(&tv, prefix_timeout_support, ppool,
-                           (tvref_t)ipv6_ppool_reference, 
-                           (tvunref_t)ipv6_ppool_dereference);
-       }
-}
-
-/*
- * Schedule timeouts across all pools.
- */
-void
-schedule_all_ipv6_prefix_timeouts(void) {
-       int i;
-
-       for (i=0; i<num_ppools; i++) {
-               schedule_prefix_timeout(ppools[i]);
-       }
-}
-
 /* 
  * Given an address and the length of the network mask, return
  * only the network portion.
@@ -2468,13 +1561,13 @@ ipv6_network_portion(struct in6_addr *result,
 }
 
 /*
- * Determine if the given address is in the pool.
+ * Determine if the given address/prefix is in the pool.
  */
 isc_boolean_t
-ipv6_addr_in_pool(const struct in6_addr *addr, const struct ipv6_pool *pool) {
+ipv6_in_pool(const struct in6_addr *addr, const struct ipv6_pool *pool) {
        struct in6_addr tmp;
-       
-       ipv6_network_portion(&tmp, addr, pool->bits & ~POOL_IS_FOR_TEMP);
+
+       ipv6_network_portion(&tmp, addr, pool->bits);
        if (memcmp(&tmp, &pool->start_addr, sizeof(tmp)) == 0) {
                return ISC_TRUE;
        } else {
@@ -2489,7 +1582,7 @@ ipv6_addr_in_pool(const struct in6_addr *addr, const struct ipv6_pool *pool) {
  *   initialized to NULL
  */
 isc_result_t
-find_ipv6_pool(struct ipv6_pool **pool, int temp,
+find_ipv6_pool(struct ipv6_pool **pool, u_int16_t type,
               const struct in6_addr *addr) {
        int i;
 
@@ -2503,13 +1596,9 @@ find_ipv6_pool(struct ipv6_pool **pool, int temp,
        }
 
        for (i=0; i<num_pools; i++) {
-               if (temp && ((pools[i]->bits & POOL_IS_FOR_TEMP) == 0)) {
-                       continue;
-               }
-               if (!temp && ((pools[i]->bits & POOL_IS_FOR_TEMP) != 0)) {
+               if (pools[i]->pool_type != type)
                        continue;
-               }
-               if (ipv6_addr_in_pool(addr, pools[i])) { 
+               if (ipv6_in_pool(addr, pools[i])) { 
                        ipv6_pool_reference(pool, pools[i], MDL);
                        return ISC_R_SUCCESS;
                }
@@ -2522,28 +1611,21 @@ find_ipv6_pool(struct ipv6_pool **pool, int temp,
  * pools.
  */
 static isc_result_t 
-change_leases(struct ia_na *ia, 
+change_leases(struct ia_xx *ia, 
              isc_result_t (*change_func)(struct ipv6_pool *, struct iaaddr*)) {
        isc_result_t retval;
        isc_result_t renew_retval;
        struct ipv6_pool *pool;
        struct in6_addr *addr;
-       int temp, i;
+       int i;
 
        retval = ISC_R_SUCCESS;
-       if (ia->ia_type == D6O_IA_NA) {
-               temp = 0;
-       } else if (ia->ia_type == D6O_IA_TA) {
-               temp = 1;
-       } else {
-               log_error("IA without type.");
-               return ISC_R_INVALIDARG;
-       }
        for (i=0; i<ia->num_iaaddr; i++) {
                pool = NULL;
                addr = &ia->iaaddr[i]->addr;
-               if (find_ipv6_pool(&pool, temp, addr) == ISC_R_SUCCESS) {
-                       renew_retval =  change_func(pool, ia->iaaddr[i]);
+               if (find_ipv6_pool(&pool, ia->ia_type,
+                                  addr) == ISC_R_SUCCESS) {
+                       renew_retval = change_func(pool, ia->iaaddr[i]);
                        if (renew_retval != ISC_R_SUCCESS) {
                                retval = renew_retval;
                        }
@@ -2556,12 +1638,12 @@ change_leases(struct ia_na *ia,
 /*
  * Renew all leases in an IA from all pools.
  *
- * The new hard_lifetime_end_time should be updated for the addresses.
+ * The new hard_lifetime_end_time should be updated for the addresses/prefixes.
  *
  * WARNING: lease times must only be extended, never reduced!!!
  */
 isc_result_t 
-renew_leases(struct ia_na *ia) {
+renew_leases(struct ia_xx *ia) {
        return change_leases(ia, renew_lease6);
 }
 
@@ -2569,7 +1651,7 @@ renew_leases(struct ia_na *ia) {
  * Release all leases in an IA from all pools.
  */
 isc_result_t 
-release_leases(struct ia_na *ia) {
+release_leases(struct ia_xx *ia) {
        return change_leases(ia, release_lease6);
 }
 
@@ -2577,103 +1659,10 @@ release_leases(struct ia_na *ia) {
  * Decline all leases in an IA from all pools.
  */
 isc_result_t 
-decline_leases(struct ia_na *ia) {
+decline_leases(struct ia_xx *ia) {
        return change_leases(ia, decline_lease6);
 }
 
-/*
- * Determine if the given prefix is in the pool.
- */
-isc_boolean_t
-ipv6_prefix_in_ppool(const struct in6_addr *pref,
-                    const struct ipv6_ppool *ppool) {
-       struct in6_addr tmp;
-       
-       ipv6_network_portion(&tmp, pref, (int)ppool->pool_plen);
-       if (memcmp(&tmp, &ppool->start_pref, sizeof(tmp)) == 0) {
-               return ISC_TRUE;
-       } else {
-               return ISC_FALSE;
-       }
-}
-
-/*
- * Find the pool that contains the given prefix.
- *
- * - pool must be a pointer to a (struct ipv6_ppool *) pointer previously
- *   initialized to NULL
- */
-isc_result_t
-find_ipv6_ppool(struct ipv6_ppool **ppool, const struct in6_addr *pref) {
-       int i;
-
-       if (ppool == NULL) {
-               log_error("%s(%d): NULL pointer reference", MDL);
-               return ISC_R_INVALIDARG;
-       }
-       if (*ppool != NULL) {
-               log_error("%s(%d): non-NULL pointer", MDL);
-               return ISC_R_INVALIDARG;
-       }
-
-       for (i=0; i<num_ppools; i++) {
-               if (ipv6_prefix_in_ppool(pref, ppools[i])) { 
-                       ipv6_ppool_reference(ppool, ppools[i], MDL);
-                       return ISC_R_SUCCESS;
-               }
-       }
-       return ISC_R_NOTFOUND;
-}
-
-/*
- * Helper function for the various functions that act across all
- * prefix pools.
- */
-static isc_result_t 
-change_prefixes(struct ia_pd *ia_pd, 
-               isc_result_t (*change_func)(struct ipv6_ppool *,
-                                           struct iaprefix*)) {
-       isc_result_t retval;
-       isc_result_t renew_retval;
-       struct ipv6_ppool *ppool;
-       struct in6_addr *pref;
-       int i;
-
-       retval = ISC_R_SUCCESS;
-       for (i=0; i<ia_pd->num_iaprefix; i++) {
-               ppool = NULL;
-               pref = &ia_pd->iaprefix[i]->pref;
-               if (find_ipv6_ppool(&ppool, pref) == ISC_R_SUCCESS) {
-                       renew_retval = change_func(ppool, ia_pd->iaprefix[i]);
-                       if (renew_retval != ISC_R_SUCCESS) {
-                               retval = renew_retval;
-                       }
-               }
-               /* XXXsk: should we warn if we don't find a pool? */
-       }
-       return retval;
-}
-
-/*
- * Renew all prefixes in an IA_PD from all pools.
- *
- * The new hard_lifetime_end_time should be updated for the addresses.
- *
- * WARNING: lease times must only be extended, never reduced!!!
- */
-isc_result_t 
-renew_prefixes(struct ia_pd *ia_pd) {
-       return change_prefixes(ia_pd, renew_prefix6);
-}
-
-/*
- * Release all prefixes in an IA_PD from all pools.
- */
-isc_result_t 
-release_prefixes(struct ia_pd *ia_pd) {
-       return change_prefixes(ia_pd, release_prefix6);
-}
-
 #ifdef DHCPv6
 /*
  * Helper function to output leases.
@@ -2682,7 +1671,7 @@ static int write_error;
 
 static isc_result_t 
 write_ia_leases(const void *name, unsigned len, void *value) {
-       struct ia_na *ia = (struct ia_na *)value;
+       struct ia_xx *ia = (struct ia_xx *)value;
        
        if (!write_error) { 
                if (!write_ia(ia)) {
@@ -2692,21 +1681,6 @@ write_ia_leases(const void *name, unsigned len, void *value) {
        return ISC_R_SUCCESS;
 }
 
-/*
- * Helper function to output prefixes.
- */
-static isc_result_t 
-write_ia_pd_prefixes(const void *name, unsigned len, void *value) {
-       struct ia_pd *ia_pd = (struct ia_pd *)value;
-       
-       if (!write_error) { 
-               if (!write_ia_pd(ia_pd)) {
-                       write_error = 1;
-               }
-       }
-       return ISC_R_SUCCESS;
-}
-
 /*
  * Write all DHCPv6 information.
  */
@@ -2714,15 +1688,15 @@ int
 write_leases6(void) {
        write_error = 0;
        write_server_duid();
-       ia_na_hash_foreach(ia_na_active, write_ia_leases);
+       ia_hash_foreach(ia_na_active, write_ia_leases);
        if (write_error) {
                return 0;
        }
-       ia_na_hash_foreach(ia_ta_active, write_ia_leases);
+       ia_hash_foreach(ia_ta_active, write_ia_leases);
        if (write_error) {
                return 0;
        }
-       ia_pd_hash_foreach(ia_pd_active, write_ia_pd_prefixes);
+       ia_hash_foreach(ia_pd_active, write_ia_leases);
        if (write_error) {
                return 0;
        }
@@ -2770,12 +1744,12 @@ mark_hosts_unavailable_support(const void *name, unsigned len, void *value) {
         * sit in any pool.)
         */
        p = NULL;
-       if (find_ipv6_pool(&p, 0, &addr) == ISC_R_SUCCESS) {
-               mark_address_unavailable(p, &addr);
+       if (find_ipv6_pool(&p, D6O_IA_NA, &addr) == ISC_R_SUCCESS) {
+               mark_lease_unavailable(p, &addr);
                ipv6_pool_dereference(&p, MDL);
        } 
-       if (find_ipv6_pool(&p, 1, &addr) == ISC_R_SUCCESS) {
-               mark_address_unavailable(p, &addr);
+       if (find_ipv6_pool(&p, D6O_IA_TA, &addr) == ISC_R_SUCCESS) {
+               mark_lease_unavailable(p, &addr);
                ipv6_pool_dereference(&p, MDL);
        } 
 
@@ -2792,7 +1766,7 @@ mark_phosts_unavailable_support(const void *name, unsigned len, void *value) {
        struct host_decl *h;
        struct iaddrcidrnetlist *l;
        struct in6_addr pref;
-       struct ipv6_ppool *p;
+       struct ipv6_pool *p;
 
        h = (struct host_decl *)value;
 
@@ -2818,15 +1792,15 @@ mark_phosts_unavailable_support(const void *name, unsigned len, void *value) {
                 * sit in any pool.)
                 */
                p = NULL;
-               if (find_ipv6_ppool(&p, &pref) != ISC_R_SUCCESS) {
+               if (find_ipv6_pool(&p, D6O_IA_PD, &pref) != ISC_R_SUCCESS) {
                        continue;
                }
-               if (l->cidrnet.bits != (int) p->alloc_plen) {
-                       ipv6_ppool_dereference(&p, MDL);
+               if (l->cidrnet.bits != p->units) {
+                       ipv6_pool_dereference(&p, MDL);
                        continue;
                }
-               mark_prefix_unavailable(p, &pref);
-               ipv6_ppool_dereference(&p, MDL);
+               mark_lease_unavailable(p, &pref);
+               ipv6_pool_dereference(&p, MDL);
        } 
 
        return ISC_R_SUCCESS;
@@ -2847,16 +1821,16 @@ mark_interfaces_unavailable(void) {
        while (ip != NULL) {
                for (i=0; i<ip->v6address_count; i++) {
                        p = NULL;
-                       if (find_ipv6_pool(&p, 0, &ip->v6addresses[i]) 
+                       if (find_ipv6_pool(&p, D6O_IA_NA, &ip->v6addresses[i]) 
                                                        == ISC_R_SUCCESS) {
-                               mark_address_unavailable(p, 
-                                                        &ip->v6addresses[i]);
+                               mark_lease_unavailable(p, 
+                                                      &ip->v6addresses[i]);
                                ipv6_pool_dereference(&p, MDL);
                        } 
-                       if (find_ipv6_pool(&p, 1, &ip->v6addresses[i]) 
+                       if (find_ipv6_pool(&p, D6O_IA_TA, &ip->v6addresses[i]) 
                                                        == ISC_R_SUCCESS) {
-                               mark_address_unavailable(p, 
-                                                        &ip->v6addresses[i]);
+                               mark_lease_unavailable(p, 
+                                                      &ip->v6addresses[i]);
                                ipv6_pool_dereference(&p, MDL);
                        } 
                }
@@ -2873,8 +1847,8 @@ main(int argc, char *argv[]) {
        struct iaaddr *iaaddr;
        struct iaaddr *iaaddr_copy;
        u_int32_t iaid;
-       struct ia_na *ia_na;
-       struct ia_na *ia_na_copy;
+       struct ia_xx *ia_na;
+       struct ia_xx *ia_na_copy;
        int i;
        struct in6_addr addr;
        struct ipv6_pool *pool;
@@ -2970,8 +1944,8 @@ main(int argc, char *argv[]) {
         */
        iaid = 666;
        ia_na = NULL;
-       if (ia_na_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) {
-               printf("ERROR: ia_na_allocate() %s:%d\n", MDL);
+       if (ia_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) {
+               printf("ERROR: ia_allocate() %s:%d\n", MDL);
                return 1;
        }
        if (memcmp(ia_na->iaid_duid.data, &iaid, sizeof(iaid)) != 0) {
@@ -2987,8 +1961,8 @@ main(int argc, char *argv[]) {
                return 1;
        }
        ia_na_copy = NULL;
-       if (ia_na_reference(&ia_na_copy, ia_na, MDL) != ISC_R_SUCCESS) {
-               printf("ERROR: ia_na_reference() %s:%d\n", MDL);
+       if (ia_reference(&ia_na_copy, ia_na, MDL) != ISC_R_SUCCESS) {
+               printf("ERROR: ia_reference() %s:%d\n", MDL);
                return 1;
        }
        iaaddr = NULL;
@@ -2996,21 +1970,21 @@ main(int argc, char *argv[]) {
                printf("ERROR: iaaddr_allocate() %s:%d\n", MDL);
                return 1;
        }
-       if (ia_na_add_iaaddr(ia_na, iaaddr, MDL) != ISC_R_SUCCESS) {
-               printf("ERROR: ia_na_add_iaaddr() %s:%d\n", MDL);
+       if (ia_add_iaaddr(ia_na, iaaddr, MDL) != ISC_R_SUCCESS) {
+               printf("ERROR: ia_add_iaaddr() %s:%d\n", MDL);
                return 1;
        }
-       ia_na_remove_iaaddr(ia_na, iaaddr, MDL);
+       ia_remove_iaaddr(ia_na, iaaddr, MDL);
        if (iaaddr_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
                printf("ERROR: iaaddr_reference() %s:%d\n", MDL);
                return 1;
        }
-       if (ia_na_dereference(&ia_na, MDL) != ISC_R_SUCCESS) {
-               printf("ERROR: ia_na_dereference() %s:%d\n", MDL);
+       if (ia_dereference(&ia_na, MDL) != ISC_R_SUCCESS) {
+               printf("ERROR: ia_dereference() %s:%d\n", MDL);
                return 1;
        }
-       if (ia_na_dereference(&ia_na_copy, MDL) != ISC_R_SUCCESS) {
-               printf("ERROR: ia_na_dereference() %s:%d\n", MDL);
+       if (ia_dereference(&ia_na_copy, MDL) != ISC_R_SUCCESS) {
+               printf("ERROR: ia_dereference() %s:%d\n", MDL);
                return 1;
        }
 
@@ -3021,8 +1995,8 @@ main(int argc, char *argv[]) {
        /* lots of iaaddr that we delete */
        iaid = 666;
        ia_na = NULL;
-       if (ia_na_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) {
-               printf("ERROR: ia_na_allocate() %s:%d\n", MDL);
+       if (ia_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) {
+               printf("ERROR: ia_allocate() %s:%d\n", MDL);
                return 1;
        }
        for (i=0; i<100; i++) {
@@ -3031,8 +2005,8 @@ main(int argc, char *argv[]) {
                        printf("ERROR: iaaddr_allocate() %s:%d\n", MDL);
                        return 1;
                }
-               if (ia_na_add_iaaddr(ia_na, iaaddr, MDL) != ISC_R_SUCCESS) {
-                       printf("ERROR: ia_na_add_iaaddr() %s:%d\n", MDL);
+               if (ia_add_iaaddr(ia_na, iaaddr, MDL) != ISC_R_SUCCESS) {
+                       printf("ERROR: ia_add_iaaddr() %s:%d\n", MDL);
                        return 1;
                }
                if (iaaddr_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
@@ -3042,18 +2016,18 @@ main(int argc, char *argv[]) {
        }
        for (i=0; i<100; i++) {
                iaaddr = ia_na->iaaddr[random() % ia_na->num_iaaddr];
-               ia_na_remove_iaaddr(ia_na, iaaddr, MDL);
+               ia_remove_iaaddr(ia_na, iaaddr, MDL);
        }
-       if (ia_na_dereference(&ia_na, MDL) != ISC_R_SUCCESS) {
-               printf("ERROR: ia_na_dereference() %s:%d\n", MDL);
+       if (ia_dereference(&ia_na, MDL) != ISC_R_SUCCESS) {
+               printf("ERROR: ia_dereference() %s:%d\n", MDL);
                return 1;
        }
 
        /* lots of iaaddr, let dereference cleanup */
        iaid = 666;
        ia_na = NULL;
-       if (ia_na_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) {
-               printf("ERROR: ia_na_allocate() %s:%d\n", MDL);
+       if (ia_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) {
+               printf("ERROR: ia_allocate() %s:%d\n", MDL);
                return 1;
        }
        for (i=0; i<100; i++) {
@@ -3062,8 +2036,8 @@ main(int argc, char *argv[]) {
                        printf("ERROR: iaaddr_allocate() %s:%d\n", MDL);
                        return 1;
                }
-               if (ia_na_add_iaaddr(ia_na, iaaddr, MDL) != ISC_R_SUCCESS) {
-                       printf("ERROR: ia_na_add_iaaddr() %s:%d\n", MDL);
+               if (ia_add_iaaddr(ia_na, iaaddr, MDL) != ISC_R_SUCCESS) {
+                       printf("ERROR: ia_add_iaaddr() %s:%d\n", MDL);
                        return 1;
                }
                if (iaaddr_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
@@ -3071,8 +2045,8 @@ main(int argc, char *argv[]) {
                        return 1;
                }
        }
-       if (ia_na_dereference(&ia_na, MDL) != ISC_R_SUCCESS) {
-               printf("ERROR: ia_na_dereference() %s:%d\n", MDL);
+       if (ia_dereference(&ia_na, MDL) != ISC_R_SUCCESS) {
+               printf("ERROR: ia_dereference() %s:%d\n", MDL);
                return 1;
        }
 
@@ -3080,58 +2054,58 @@ main(int argc, char *argv[]) {
         * Test 4: Errors in ia_na.
         */
        /* bogus allocate arguments */
-       if (ia_na_allocate(NULL, 123, "", 0, MDL) != ISC_R_INVALIDARG) {
-               printf("ERROR: ia_na_allocate() %s:%d\n", MDL);
+       if (ia_allocate(NULL, 123, "", 0, MDL) != ISC_R_INVALIDARG) {
+               printf("ERROR: ia_allocate() %s:%d\n", MDL);
                return 1;
        }
        ia_na = (struct ia_na *)1;
-       if (ia_na_allocate(&ia_na, 456, "", 0, MDL) != ISC_R_INVALIDARG) {
-               printf("ERROR: ia_na_allocate() %s:%d\n", MDL);
+       if (ia_allocate(&ia_na, 456, "", 0, MDL) != ISC_R_INVALIDARG) {
+               printf("ERROR: ia_allocate() %s:%d\n", MDL);
                return 1;
        }
 
        /* bogus reference arguments */
        iaid = 666;
        ia_na = NULL;
-       if (ia_na_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) {
-               printf("ERROR: ia_na_allocate() %s:%d\n", MDL);
+       if (ia_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) {
+               printf("ERROR: ia_allocate() %s:%d\n", MDL);
                return 1;
        }
-       if (ia_na_reference(NULL, ia_na, MDL) != ISC_R_INVALIDARG) {
-               printf("ERROR: ia_na_reference() %s:%d\n", MDL);
+       if (ia_reference(NULL, ia_na, MDL) != ISC_R_INVALIDARG) {
+               printf("ERROR: ia_reference() %s:%d\n", MDL);
                return 1;
        }
        ia_na_copy = (struct ia_na *)1;
-       if (ia_na_reference(&ia_na_copy, ia_na, MDL) != ISC_R_INVALIDARG) {
-               printf("ERROR: ia_na_reference() %s:%d\n", MDL);
+       if (ia_reference(&ia_na_copy, ia_na, MDL) != ISC_R_INVALIDARG) {
+               printf("ERROR: ia_reference() %s:%d\n", MDL);
                return 1;
        }
        ia_na_copy = NULL;
-       if (ia_na_reference(&ia_na_copy, NULL, MDL) != ISC_R_INVALIDARG) {
-               printf("ERROR: ia_na_reference() %s:%d\n", MDL);
+       if (ia_reference(&ia_na_copy, NULL, MDL) != ISC_R_INVALIDARG) {
+               printf("ERROR: ia_reference() %s:%d\n", MDL);
                return 1;
        }
-       if (ia_na_dereference(&ia_na, MDL) != ISC_R_SUCCESS) {
-               printf("ERROR: ia_na_dereference() %s:%d\n", MDL);
+       if (ia_dereference(&ia_na, MDL) != ISC_R_SUCCESS) {
+               printf("ERROR: ia_dereference() %s:%d\n", MDL);
                return 1;
        }
 
        /* bogus dereference arguments */
-       if (ia_na_dereference(NULL, MDL) != ISC_R_INVALIDARG) {
-               printf("ERROR: ia_na_dereference() %s:%d\n", MDL);
+       if (ia_dereference(NULL, MDL) != ISC_R_INVALIDARG) {
+               printf("ERROR: ia_dereference() %s:%d\n", MDL);
                return 1;
        }
 
        /* bogus remove */
        iaid = 666;
        ia_na = NULL;
-       if (ia_na_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) {
-               printf("ERROR: ia_na_allocate() %s:%d\n", MDL);
+       if (ia_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) {
+               printf("ERROR: ia_allocate() %s:%d\n", MDL);
                return 1;
        }
-       ia_na_remove_iaaddr(ia_na, NULL, MDL);
-       if (ia_na_dereference(&ia_na, MDL) != ISC_R_SUCCESS) {
-               printf("ERROR: ia_na_dereference() %s:%d\n", MDL);
+       ia_remove_iaaddr(ia_na, NULL, MDL);
+       if (ia_dereference(&ia_na, MDL) != ISC_R_SUCCESS) {
+               printf("ERROR: ia_dereference() %s:%d\n", MDL);
                return 1;
        }
 
@@ -3142,7 +2116,7 @@ main(int argc, char *argv[]) {
        /* allocate, reference */
        inet_pton(AF_INET6, "1:2:3:4::", &addr);
        pool = NULL;
-       if (ipv6_pool_allocate(&pool, &addr, 64, MDL) != ISC_R_SUCCESS) {
+       if (ipv6_pool_allocate(&pool, 0, &addr, 64, 128, MDL) != ISC_R_SUCCESS) {
                printf("ERROR: ipv6_pool_allocate() %s:%d\n", MDL);
                return 1;
        }
@@ -3292,12 +2266,12 @@ main(int argc, char *argv[]) {
        /*
         * Test 6: Error ipv6_pool manipulation
         */
-       if (ipv6_pool_allocate(NULL, &addr, 64, MDL) != ISC_R_INVALIDARG) {
+       if (ipv6_pool_allocate(NULL, 0, &addr, 64, 128, MDL) != ISC_R_INVALIDARG) {
                printf("ERROR: ipv6_pool_allocate() %s:%d\n", MDL);
                return 1;
        }
        pool = (struct ipv6_pool *)1;
-       if (ipv6_pool_allocate(&pool, &addr, 64, MDL) != ISC_R_INVALIDARG) {
+       if (ipv6_pool_allocate(&pool, 0, &addr, 64, 128, MDL) != ISC_R_INVALIDARG) {
                printf("ERROR: ipv6_pool_allocate() %s:%d\n", MDL);
                return 1;
        }
@@ -3328,7 +2302,7 @@ main(int argc, char *argv[]) {
         * Test 7: order of expiration
         */
        pool = NULL;
-       if (ipv6_pool_allocate(&pool, &addr, 64, MDL) != ISC_R_SUCCESS) {
+       if (ipv6_pool_allocate(&pool, 0, &addr, 64, 128, MDL) != ISC_R_SUCCESS) {
                printf("ERROR: ipv6_pool_allocate() %s:%d\n", MDL);
                return 1;
        }
@@ -3399,7 +2373,7 @@ main(int argc, char *argv[]) {
         */
        pool = NULL;
        addr.s6_addr[14] = 0x81;
-       if (ipv6_pool_allocate(&pool, &addr, 127, MDL) != ISC_R_SUCCESS) {
+       if (ipv6_pool_allocate(&pool, 0, &addr, 127, 128, MDL) != ISC_R_SUCCESS) {
                printf("ERROR: ipv6_pool_allocate() %s:%d\n", MDL);
                return 1;
        }
@@ -3444,7 +2418,7 @@ main(int argc, char *argv[]) {
         * Test 9: functions across all pools
         */
        pool = NULL;
-       if (ipv6_pool_allocate(&pool, &addr, 64, MDL) != ISC_R_SUCCESS) {
+       if (ipv6_pool_allocate(&pool, 0, &addr, 64, 128, MDL) != ISC_R_SUCCESS) {
                printf("ERROR: ipv6_pool_allocate() %s:%d\n", MDL);
                return 1;
        }
@@ -3490,8 +2464,8 @@ main(int argc, char *argv[]) {
 
 /*     iaid = 666;
        ia_na = NULL;
-       if (ia_na_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) {
-               printf("ERROR: ia_na_allocate() %s:%d\n", MDL);
+       if (ia_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) {
+               printf("ERROR: ia_allocate() %s:%d\n", MDL);
                return 1;
        }*/
 
@@ -3512,7 +2486,7 @@ main(int argc, char *argv[]) {
                        for (j = i + 1; j < 49; j++) {
                                memset(&r, 0, sizeof(r));
                                memset(buf, 0, 64);
-                               create_prefix(&r, &addr, i, j, &ds);
+                               build_prefix6(&r, &addr, i, j, &ds);
                                inet_ntop(AF_INET6, &r, buf, 64);
                                printf("%d,%d-> %s/%d\n", i, j, buf, j);
                        }