case PREFIX6:
next_token(NULL, NULL, cfile);
- if (type != ROOT_GROUP) {
+ if ((type != SUBNET_DECL) || (group->subnet == NULL)) {
parse_warn (cfile,
"prefix6 definitions may not be scoped.");
skip_to_semi(cfile);
}
static void
-add_ipv6_ppool_to_global(struct iaddr *start_addr,
- int pool_bits,
- int alloc_bits) {
+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 (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 */
int bits;
enum dhcp_token token;
const char *val;
+ struct shared_network *share;
struct iaddrcidrnetlist *nets;
struct iaddrcidrnetlist *p;
+ if (local_family != AF_INET6) {
+ parse_warn(cfile, "prefix6 statement is only supported "
+ "in DHCPv6 mode.");
+ skip_to_semi(cfile);
+ return;
+ }
+
+ /*
+ * We'll use the shared_network from our group.
+ */
+ share = group->shared_network;
+ if (share == NULL) {
+ share = group->subnet->shared_network;
+ }
+
/*
* Read starting and ending address.
*/
return;
}
-
/*
* Convert our range to a set of CIDR networks.
*/
parse_warn(cfile, "impossible mask length");
continue;
}
- add_ipv6_ppool_to_global(&p->cidrnet.lo_addr,
- p->cidrnet.bits, bits);
+ add_ipv6_ppool_to_shared_network(share,
+ &p->cidrnet.lo_addr,
+ p->cidrnet.bits, bits);
}
free_iaddrcidrnetlist(&nets);
struct option_cache *oc,
int offset);
static void build_dhcpv6_reply(struct data_string *, struct packet *);
-static void shared_network_from_packet6(struct shared_network **shared,
- struct packet *packet);
+static isc_result_t shared_network_from_packet6(struct shared_network **shared,
+ struct packet *packet);
static void seek_shared_host(struct host_decl **hp,
struct shared_network *shared);
static isc_boolean_t fixed_matches_shared(struct host_decl *host,
*/
static isc_result_t
pick_v6_prefix(struct iaprefix **pref, int plen,
+ struct shared_network *shared_network,
const struct data_string *client_id)
{
struct ipv6_ppool *p;
/*
* No prefix pools, we're done.
*/
- if (!num_ppools) {
+ if (shared_network->ipv6_ppools == NULL) {
log_debug("Unable to pick client prefix: "
- "no IPv6 prefix pools");
+ "no IPv6 prefix pools on this shared network");
return ISC_R_NORESOURCES;
}
/*
* Otherwise try to get a prefix.
*/
- for (i = 0; i < num_ppools; i++) {
- p = ppools[i];
+ for (i = 0;; i++) {
+ p = shared_network->ipv6_ppools[i];
if (p == NULL) {
- continue;
+ break;
}
/*
isc_boolean_t no_resources_avail;
/* Locate the client. */
- shared_network_from_packet6(&reply.shared, packet);
+ if (shared_network_from_packet6(&reply.shared,
+ packet) != ISC_R_SUCCESS)
+ goto exit;
/*
* Initialize the reply.
* valid for the shared network the client is on.
*/
if (find_hosts_by_option(&reply.host, packet, packet->options, MDL)) {
- if (reply.shared != NULL) {
- seek_shared_host(&reply.host, reply.shared);
- }
+ seek_shared_host(&reply.host, reply.shared);
}
if ((reply.host == NULL) &&
find_hosts_by_uid(&reply.host, client_id->data, client_id->len,
MDL)) {
- if (reply.shared != NULL) {
- seek_shared_host(&reply.host, reply.shared);
- }
+ seek_shared_host(&reply.host, reply.shared);
}
/* Process the client supplied IA's onto the reply buffer. */
for (; oc != NULL ; oc = oc->next) {
isc_result_t status;
- /* A shared network is required. */
- if (reply.shared == NULL)
- goto exit;
-
/* Start counting resources (addresses) offered. */
reply.client_resources = 0;
reply.ia_resources_included = ISC_FALSE;
for (; oc != NULL ; oc = oc->next) {
isc_result_t status;
- /* A shared network is required. */
- if (reply.shared == NULL)
- goto exit;
-
/* Start counting resources (addresses) offered. */
reply.client_resources = 0;
reply.ia_resources_included = ISC_FALSE;
log_fatal("Impossible condition at %s:%d.", MDL);
scope = &reply->prefix->scope;
- group = root_group;
+ group = reply->shared->group;
}
/*
int i;
struct data_string data_pref;
- if ((reply == NULL) || (pref == NULL) || (reply->prefix != NULL))
+ if ((reply == NULL) || (reply->shared == NULL) ||
+ (reply->shared->ipv6_ppools == NULL) || (pref == NULL) ||
+ (reply->prefix != NULL))
return ISC_R_INVALIDARG;
memset(&data_pref, 0, sizeof(data_pref));
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 < num_ppools ; i++) {
- ppool = ppools[i];
+ for (i = 0 ;; i++) {
+ ppool = reply->shared->ipv6_ppools[i];
if (ppool == NULL)
- continue;
+ break;
status = try_client_v6_prefix(&reply->prefix, ppool,
&data_pref);
if (status == ISC_R_SUCCESS)
if (reply->host != NULL)
group = reply->host->group;
- else if (reply->shared != NULL)
- group = reply->shared->group;
else
- group = root_group;
+ group = reply->shared->group;
if (reply->static_prefixes > 0) {
struct iaddrcidrnetlist *l;
*/
if ((best_prefix == NULL) || (best_prefix->state == FTS_ABANDONED)) {
status = pick_v6_prefix(&reply->prefix, reply->preflen,
- &reply->client_id);
+ reply->shared, &reply->client_id);
} else if (best_prefix != NULL) {
iaprefix_reference(&reply->prefix, best_prefix, MDL);
status = ISC_R_SUCCESS;
log_fatal("Impossible condition at %s:%d.", MDL);
scope = &reply->prefix->scope;
- if (reply->shared != NULL) {
- group = reply->shared->group;
- } else {
- group = root_group;
- }
+ group = reply->shared->group;
send_pref.lo_addr.len = 16;
memcpy(send_pref.lo_addr.iabuf, &reply->prefix->pref, 16);
/* Find a DHCPv6 packet's shared network from hints in the packet.
*/
-static void
+static isc_result_t
shared_network_from_packet6(struct shared_network **shared,
struct packet *packet)
{
const struct in6_addr *link_addr, *first_link_addr;
struct iaddr tmp_addr;
struct subnet *subnet;
+ isc_result_t status;
- if ((shared == NULL) || (*shared != NULL) || (packet == NULL)) {
- log_error("shared_network_from_packet6: invalid arg.");
- return;
- }
+ if ((shared == NULL) || (*shared != NULL) || (packet == NULL))
+ return ISC_R_INVALIDARG;
/*
* First, find the link address where the packet from the client
if (!find_subnet(&subnet, tmp_addr, MDL)) {
log_debug("No subnet found for link-address %s.",
piaddr(tmp_addr));
- return;
+ return ISC_R_NOTFOUND;
}
- shared_network_reference(shared, subnet->shared_network, MDL);
+ status = shared_network_reference(shared,
+ subnet->shared_network, MDL);
subnet_dereference(&subnet, MDL);
/*
* that this packet came in on to pick the shared_network.
*/
} else {
- shared_network_reference(shared,
+ status = shared_network_reference(shared,
packet->interface->shared_network,
MDL);
}
+
+ return status;
}
/*
* network the client is on.
*/
shared = NULL;
- shared_network_from_packet6(&shared, packet);
- if (shared == NULL)
+ if ((shared_network_from_packet6(&shared, packet) != ISC_R_SUCCESS) ||
+ (shared == NULL))
goto exit;
/* If there are no recorded subnets, then we have no
struct host_decl *seek, *hold = NULL;
/*
- * Seek forward through fixed addresses for the right broadcast
- * domain.
+ * Seek forward through fixed addresses for the right link.
+ *
+ * Note: how to do this for fixed prefixes???
*/
host_reference(&hold, *hp, MDL);
host_dereference(hp, MDL);