mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-29 13:28:14 +00:00
Add IA_TA and IA_PD support in server
This commit is contained in:
parent
892379eca3
commit
80c9fdb0e7
@ -1012,12 +1012,12 @@ dhc6_parse_prefs(struct dhc6_addr **ppref, struct packet *packet,
|
||||
oc, MDL) &&
|
||||
(ds.len >= 25)) {
|
||||
|
||||
pref->plen = getUChar(ds.data);
|
||||
pref->preferred_life = getULong(ds.data);
|
||||
pref->max_life = getULong(ds.data + 4);
|
||||
pref->plen = getUChar(ds.data + 8);
|
||||
pref->address.len = 16;
|
||||
memcpy(pref->address.iabuf, ds.data + 1, 16);
|
||||
memcpy(pref->address.iabuf, ds.data + 9, 16);
|
||||
pref->starts = cur_time;
|
||||
pref->preferred_life = getULong(ds.data + 17);
|
||||
pref->max_life = getULong(ds.data + 21);
|
||||
|
||||
log_debug("RCV: | | X-- IAPREFIX %s/%d",
|
||||
piaddr(pref->address), (int)pref->plen);
|
||||
|
@ -918,6 +918,8 @@ intern(char *atom, enum dhcp_token dfv) {
|
||||
return FIXED_ADDR;
|
||||
if (!strcasecmp (atom + 1, "ixed-address6"))
|
||||
return FIXED_ADDR6;
|
||||
if (!strcasecmp (atom + 1, "ixed-prefix6"))
|
||||
return FIXED_PREFIX6;
|
||||
if (!strcasecmp (atom + 1, "ddi"))
|
||||
return TOKEN_FDDI;
|
||||
if (!strcasecmp (atom + 1, "ormerr"))
|
||||
@ -1145,6 +1147,8 @@ intern(char *atom, enum dhcp_token dfv) {
|
||||
return PACKET;
|
||||
if (!strcasecmp (atom + 1, "ool"))
|
||||
return POOL;
|
||||
if (!strcasecmp (atom + 1, "refix6"))
|
||||
return PREFIX6;
|
||||
if (!strcasecmp (atom + 1, "seudo"))
|
||||
return PSEUDO;
|
||||
if (!strcasecmp (atom + 1, "eer"))
|
||||
@ -1365,6 +1369,8 @@ intern(char *atom, enum dhcp_token dfv) {
|
||||
return TSFP;
|
||||
if (!strcasecmp (atom + 1, "ransmission"))
|
||||
return TRANSMISSION;
|
||||
if (!strcasecmp(atom + 1, "emporary"))
|
||||
return TEMPORARY;
|
||||
break;
|
||||
case 'u':
|
||||
if (!strcasecmp (atom + 1, "case"))
|
||||
|
@ -622,7 +622,8 @@ struct lease_state {
|
||||
#define SV_DHCPV6_LEASE_FILE_NAME 54
|
||||
#define SV_DHCPV6_PID_FILE_NAME 55
|
||||
#define SV_LIMIT_ADDRS_PER_IA 56
|
||||
#define SV_DELAYED_ACK 57
|
||||
#define SV_LIMIT_PREFS_PER_IA 57
|
||||
#define SV_DELAYED_ACK 58
|
||||
|
||||
#if !defined (DEFAULT_PING_TIMEOUT)
|
||||
# define DEFAULT_PING_TIMEOUT 1
|
||||
@ -741,6 +742,7 @@ struct host_decl {
|
||||
not an option_cache, but it's referenced in a lot of
|
||||
places, so we'll leave it for now. */
|
||||
struct option_cache *fixed_addr;
|
||||
struct iaddrcidrnetlist *fixed_prefix;
|
||||
struct group *group;
|
||||
struct group_object *named_group;
|
||||
struct data_string auth_key_id;
|
||||
@ -1358,6 +1360,7 @@ extern ia_na_hash_t *ia_ta_active;
|
||||
struct ipv6_pool {
|
||||
int refcnt; /* reference count */
|
||||
struct in6_addr start_addr; /* first IPv6 address */
|
||||
#define POOL_IS_FOR_TEMP 0x8000
|
||||
int bits; /* number of bits, CIDR style */
|
||||
iaaddr_hash_t *addrs; /* non-free IAADDR */
|
||||
int num_active; /* count of active IAADDR */
|
||||
@ -1738,6 +1741,8 @@ int parse_ip6_prefix(struct parse *, struct iaddr *, u_int8_t *);
|
||||
void parse_address_range PROTO ((struct parse *, struct group *, int,
|
||||
struct pool *, struct lease **));
|
||||
void parse_address_range6(struct parse *cfile, struct group *group);
|
||||
void parse_prefix6(struct parse *cfile, struct group *group);
|
||||
void parse_fixed_prefix6(struct parse *cfile, struct host_decl *host_decl);
|
||||
void parse_ia_na_declaration(struct parse *);
|
||||
void parse_ia_ta_declaration(struct parse *);
|
||||
void parse_ia_pd_declaration(struct parse *);
|
||||
@ -3290,6 +3295,7 @@ 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,
|
||||
const char *file, int line);
|
||||
isc_boolean_t ia_pd_equal(const struct ia_pd *a, const struct ia_pd *b);
|
||||
|
||||
isc_result_t ipv6_pool_allocate(struct ipv6_pool **pool,
|
||||
const struct in6_addr *start_addr, int bits,
|
||||
@ -3342,13 +3348,15 @@ isc_boolean_t prefix6_exists(const struct ipv6_ppool *ppool,
|
||||
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,
|
||||
isc_result_t find_ipv6_pool(struct ipv6_pool **pool, int temp,
|
||||
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);
|
||||
@ -3362,5 +3370,6 @@ 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);
|
||||
|
||||
|
@ -349,7 +349,10 @@ enum dhcp_token {
|
||||
WHITESPACE = 652,
|
||||
TOKEN_ALSO = 653,
|
||||
AFTER = 654,
|
||||
ZEROLEN = 655
|
||||
ZEROLEN = 655,
|
||||
TEMPORARY = 656,
|
||||
PREFIX6 = 657,
|
||||
FIXED_PREFIX6 = 658
|
||||
};
|
||||
|
||||
#define is_identifier(x) ((x) >= FIRST_TOKEN && \
|
||||
|
@ -617,6 +617,30 @@ int parse_statement (cfile, group, type, host_decl, declaration)
|
||||
}
|
||||
parse_address_range6(cfile, group);
|
||||
return declaration;
|
||||
|
||||
case PREFIX6:
|
||||
next_token(NULL, NULL, cfile);
|
||||
if (type != ROOT_GROUP) {
|
||||
parse_warn (cfile,
|
||||
"prefix6 definitions may not be scoped.");
|
||||
skip_to_semi(cfile);
|
||||
return declaration;
|
||||
}
|
||||
parse_prefix6(cfile, group);
|
||||
return declaration;
|
||||
|
||||
case FIXED_PREFIX6:
|
||||
next_token(&val, NULL, cfile);
|
||||
if (!host_decl) {
|
||||
parse_warn (cfile,
|
||||
"fixed-prefix6 declaration not "
|
||||
"allowed here.");
|
||||
skip_to_semi(cfile);
|
||||
break;
|
||||
}
|
||||
parse_fixed_prefix6(cfile, host_decl);
|
||||
break;
|
||||
|
||||
#endif /* DHCPv6 */
|
||||
|
||||
case TOKEN_NOT:
|
||||
@ -3672,7 +3696,8 @@ add_ipv6_pool_to_shared_network(struct shared_network *share,
|
||||
}
|
||||
|
||||
/* address-range6-declaration :== ip-address6 ip-address6 SEMI
|
||||
| ip-address6 SLASH number SEMI */
|
||||
| ip-address6 SLASH number SEMI
|
||||
| ip-address6 TEMPORARY SEMI */
|
||||
|
||||
void
|
||||
parse_address_range6(struct parse *cfile, struct group *group) {
|
||||
@ -3707,7 +3732,7 @@ parse_address_range6(struct parse *cfile, struct group *group) {
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we we're using range or CIDR notation.
|
||||
* See if we we're using range or CIDR notation or TEMPORARY
|
||||
*/
|
||||
token = peek_token(&val, NULL, cfile);
|
||||
if (token == SLASH) {
|
||||
@ -3735,6 +3760,20 @@ parse_address_range6(struct parse *cfile, struct group *group) {
|
||||
|
||||
add_ipv6_pool_to_shared_network(share, &lo, bits);
|
||||
|
||||
} else if (token == TEMPORARY) {
|
||||
/*
|
||||
* temporary (RFC 4941)
|
||||
*/
|
||||
next_token(NULL, NULL, cfile);
|
||||
bits = 64;
|
||||
if (!is_cidr_mask_valid(&lo, bits)) {
|
||||
parse_warn(cfile, "network mask too short");
|
||||
skip_to_semi(cfile);
|
||||
return;
|
||||
}
|
||||
bits |= POOL_IS_FOR_TEMP;
|
||||
|
||||
add_ipv6_pool_to_shared_network(share, &lo, bits);
|
||||
} else {
|
||||
/*
|
||||
* No '/', so we are looking for the end address of
|
||||
@ -3769,6 +3808,196 @@ parse_address_range6(struct parse *cfile, struct group *group) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_ipv6_ppool_to_global(struct iaddr *start_addr,
|
||||
int pool_bits,
|
||||
int alloc_bits) {
|
||||
struct ipv6_ppool *ppool;
|
||||
struct in6_addr tmp_in6_addr;
|
||||
|
||||
/*
|
||||
* 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");
|
||||
}
|
||||
}
|
||||
|
||||
/* prefix6-declaration :== ip-address6 ip-address6 SLASH number SEMI */
|
||||
|
||||
void
|
||||
parse_prefix6(struct parse *cfile, struct group *group) {
|
||||
struct iaddr lo, hi;
|
||||
int bits;
|
||||
enum dhcp_token token;
|
||||
const char *val;
|
||||
struct iaddrcidrnetlist *nets;
|
||||
struct iaddrcidrnetlist *p;
|
||||
|
||||
/*
|
||||
* Read starting and ending address.
|
||||
*/
|
||||
if (!parse_ip6_addr(cfile, &lo)) {
|
||||
return;
|
||||
}
|
||||
if (!parse_ip6_addr(cfile, &hi)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Next is '/' number ';'.
|
||||
*/
|
||||
token = next_token(NULL, NULL, cfile);
|
||||
if (token != SLASH) {
|
||||
parse_warn(cfile, "expecting '/'");
|
||||
if (token != SEMI)
|
||||
skip_to_semi(cfile);
|
||||
return;
|
||||
}
|
||||
token = next_token(&val, NULL, cfile);
|
||||
if (token != NUMBER) {
|
||||
parse_warn(cfile, "expecting number");
|
||||
if (token != SEMI)
|
||||
skip_to_semi(cfile);
|
||||
return;
|
||||
}
|
||||
bits = atoi(val);
|
||||
if ((bits <= 0) || (bits >= 128)) {
|
||||
parse_warn(cfile, "networks have 0 to 128 bits (exclusive)");
|
||||
return;
|
||||
}
|
||||
if (!is_cidr_mask_valid(&lo, bits) ||
|
||||
!is_cidr_mask_valid(&hi, bits)) {
|
||||
parse_warn(cfile, "network mask too short");
|
||||
return;
|
||||
}
|
||||
token = next_token(NULL, NULL, cfile);
|
||||
if (token != SEMI) {
|
||||
parse_warn(cfile, "semicolon expected.");
|
||||
skip_to_semi(cfile);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert our range to a set of CIDR networks.
|
||||
*/
|
||||
nets = NULL;
|
||||
if (range2cidr(&nets, &lo, &hi) != ISC_R_SUCCESS) {
|
||||
log_fatal("Error converting prefix to CIDR");
|
||||
}
|
||||
|
||||
for (p = nets; p != NULL; p = p->next) {
|
||||
/* Normalize and check. */
|
||||
if (p->cidrnet.bits == 128) {
|
||||
p->cidrnet.bits = bits;
|
||||
}
|
||||
if (p->cidrnet.bits > bits) {
|
||||
parse_warn(cfile, "impossible mask length");
|
||||
continue;
|
||||
}
|
||||
add_ipv6_ppool_to_global(&p->cidrnet.lo_addr,
|
||||
p->cidrnet.bits, bits);
|
||||
}
|
||||
|
||||
free_iaddrcidrnetlist(&nets);
|
||||
}
|
||||
|
||||
/* fixed-prefix6 :== ip6-address SLASH number SEMI */
|
||||
|
||||
void
|
||||
parse_fixed_prefix6(struct parse *cfile, struct host_decl *host_decl) {
|
||||
struct iaddrcidrnetlist *ia, **h;
|
||||
enum dhcp_token token;
|
||||
const char *val;
|
||||
|
||||
/*
|
||||
* Get the head of the fixed-prefix list.
|
||||
*/
|
||||
h = &host_decl->fixed_prefix;
|
||||
|
||||
/*
|
||||
* Walk to the end.
|
||||
*/
|
||||
while (*h != NULL) {
|
||||
h = &((*h)->next);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new iaddrcidrnetlist structure.
|
||||
*/
|
||||
ia = dmalloc(sizeof(*ia), MDL);
|
||||
if (!ia) {
|
||||
log_fatal("Out of memory");
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse it.
|
||||
*/
|
||||
if (!parse_ip6_addr(cfile, &ia->cidrnet.lo_addr)) {
|
||||
dfree(ia, MDL);
|
||||
return;
|
||||
}
|
||||
token = next_token(NULL, NULL, cfile);
|
||||
if (token != SLASH) {
|
||||
dfree(ia, MDL);
|
||||
parse_warn(cfile, "expecting '/'");
|
||||
if (token != SEMI)
|
||||
skip_to_semi(cfile);
|
||||
return;
|
||||
}
|
||||
token = next_token(&val, NULL, cfile);
|
||||
if (token != NUMBER) {
|
||||
dfree(ia, MDL);
|
||||
parse_warn(cfile, "expecting number");
|
||||
if (token != SEMI)
|
||||
skip_to_semi(cfile);
|
||||
return;
|
||||
}
|
||||
token = next_token(NULL, NULL, cfile);
|
||||
if (token != SEMI) {
|
||||
dfree(ia, MDL);
|
||||
parse_warn(cfile, "semicolon expected.");
|
||||
skip_to_semi(cfile);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill it.
|
||||
*/
|
||||
ia->cidrnet.bits = atoi(val);
|
||||
if ((ia->cidrnet.bits < 0) || (ia->cidrnet.bits > 128)) {
|
||||
dfree(ia, MDL);
|
||||
parse_warn(cfile, "networks have 0 to 128 bits");
|
||||
return;
|
||||
}
|
||||
if (!is_cidr_mask_valid(&ia->cidrnet.lo_addr, ia->cidrnet.bits)) {
|
||||
dfree(ia, MDL);
|
||||
parse_warn(cfile, "network mask too short");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Store it.
|
||||
*/
|
||||
*h = ia;
|
||||
return;
|
||||
}
|
||||
#endif /* DHCPv6 */
|
||||
|
||||
/* allow-deny-keyword :== BOOTP
|
||||
@ -4099,7 +4328,7 @@ parse_ia_na_declaration(struct parse *cfile) {
|
||||
ia_na_add_iaaddr(ia, iaaddr, MDL);
|
||||
ia_na_reference(&iaaddr->ia_na, ia, MDL);
|
||||
pool = NULL;
|
||||
if (find_ipv6_pool(&pool, &iaaddr->addr) != ISC_R_SUCCESS) {
|
||||
if (find_ipv6_pool(&pool, 0, &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",
|
||||
@ -4393,7 +4622,7 @@ parse_ia_ta_declaration(struct parse *cfile) {
|
||||
ia_na_add_iaaddr(ia, iaaddr, MDL);
|
||||
ia_na_reference(&iaaddr->ia_na, ia, MDL);
|
||||
pool = NULL;
|
||||
if (find_ipv6_pool(&pool, &iaaddr->addr) != ISC_R_SUCCESS) {
|
||||
if (find_ipv6_pool(&pool, 1, &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",
|
||||
|
@ -611,6 +611,7 @@ main(int argc, char **argv) {
|
||||
*/
|
||||
if (local_family == AF_INET6) {
|
||||
mark_hosts_unavailable();
|
||||
mark_phosts_unavailable();
|
||||
mark_interfaces_unavailable();
|
||||
}
|
||||
#endif /* DHCPv6 */
|
||||
|
@ -28,7 +28,7 @@
|
||||
.\" see ``http://www.vix.com''. To learn more about Nominum, Inc., see
|
||||
.\" ``http://www.nominum.com''.
|
||||
.\"
|
||||
.\" $Id: dhcpd.conf.5,v 1.93 2008/01/24 02:43:05 each Exp $
|
||||
.\" $Id: dhcpd.conf.5,v 1.94 2008/02/20 12:45:53 fdupont Exp $
|
||||
.\"
|
||||
.TH dhcpd.conf 5
|
||||
.SH NAME
|
||||
@ -1515,6 +1515,7 @@ single address, \fIhigh-address\fR can be omitted.
|
||||
.nf
|
||||
.B range6\fR \fIlow-address\fR \fIhigh-address\fR\fB;\fR
|
||||
.B range6\fR \fIsubnet6-number\fR\fB;\fR
|
||||
.B range6\fR \fIaddress\fR \fBtemporary\fR\fB;\fR
|
||||
.fi
|
||||
.PP
|
||||
For any IPv6 subnet6 on which addresses will be assigned dynamically, there
|
||||
@ -1524,9 +1525,33 @@ use CIDR notation, specified as ip6-address/bits. All IP addresses
|
||||
in the \fIrange6\fR should be in the subnet6 in which the
|
||||
\fIrange6\fR statement is declared.
|
||||
.PP
|
||||
The \fItemporay\fR variant makes the 64 bit prefix \fIaddress\fR available
|
||||
for temporary (RFC 4941) addresses. A new address per prefix in the shared
|
||||
network is computed at each request with an IA_TA option. Release and Confirm
|
||||
ignores temporary addresses, Renew and Rebind are not defined and raise an
|
||||
error.
|
||||
.PP
|
||||
Any IPv6 addresses given to hosts with \fIfixed-address6\fR are excluded
|
||||
from the \fIrange6\fR, as are IPv6 addresses on the server itself.
|
||||
.PP
|
||||
.PP
|
||||
.B The
|
||||
.I prefix6
|
||||
.B statement
|
||||
.PP
|
||||
.nf
|
||||
.B prefix6\fR \fIlow-address\fR \fIhigh-address\fR \fB/\fR \fIbits\fR\fB;\fR
|
||||
.fi
|
||||
.PP
|
||||
The \fIprefix6\fR is the \fIrange6\fR equivalent for Prefix Delegation
|
||||
(RFC 3633). Prefixes of \fIbits\fR length are assigned between
|
||||
\fIlow-address\fR and \fIhigh-address\fR.
|
||||
.PP
|
||||
Any IPv6 prefixes given to static entries (hosts) with \fIfixed-prefix6\fR
|
||||
are excluded from the \fIprefix6\fR.
|
||||
.PP
|
||||
This statement is currently global but it should have a shared-network scope.
|
||||
.PP
|
||||
.B The
|
||||
.I host
|
||||
.B statement
|
||||
|
2113
server/dhcpv6.c
2113
server/dhcpv6.c
File diff suppressed because it is too large
Load Diff
231
server/mdb6.c
231
server/mdb6.c
@ -1149,6 +1149,50 @@ create_address(struct in6_addr *addr,
|
||||
str[8] &= ~0x02;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a temporary address by a variant of RFC 4941 algo.
|
||||
*/
|
||||
static void
|
||||
create_temporary(struct in6_addr *addr,
|
||||
const struct in6_addr *net_start_addr,
|
||||
const struct data_string *input) {
|
||||
static u_int8_t history[8];
|
||||
static u_int32_t counter = 0;
|
||||
MD5_CTX ctx;
|
||||
unsigned char md[16];
|
||||
extern int dst_s_random(u_int8_t *, unsigned);
|
||||
|
||||
/*
|
||||
* First time/time to reseed.
|
||||
* Please use a good pseudo-random generator here!
|
||||
*/
|
||||
if (counter == 0) {
|
||||
if (dst_s_random(history, 8) != 8)
|
||||
log_fatal("Random failed.");
|
||||
}
|
||||
|
||||
/*
|
||||
* Use MD5 as recommended by RFC 4941.
|
||||
*/
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, history, 8UL);
|
||||
MD5_Update(&ctx, input->data, input->len);
|
||||
MD5_Final(md, &ctx);
|
||||
|
||||
/*
|
||||
* Build the address.
|
||||
*/
|
||||
memcpy(&addr->s6_addr[0], &net_start_addr->s6_addr[0], 8);
|
||||
memcpy(&addr->s6_addr[8], md, 8);
|
||||
addr->s6_addr[8] &= ~0x02;
|
||||
|
||||
/*
|
||||
* Save history for the next call.
|
||||
*/
|
||||
memcpy(history, md + 8, 8);
|
||||
counter++;
|
||||
}
|
||||
|
||||
/* Reserved Subnet Router Anycast ::0:0:0:0. */
|
||||
static struct in6_addr rtany;
|
||||
/* Reserved Subnet Anycasts ::fdff:ffff:ffff:ff80-::fdff:ffff:ffff:ffff. */
|
||||
@ -1216,9 +1260,14 @@ activate_lease6(struct ipv6_pool *pool, struct iaaddr **addr,
|
||||
}
|
||||
|
||||
/*
|
||||
* Create an address
|
||||
* Create an address or a temporary address.
|
||||
*/
|
||||
create_address(&tmp, &pool->start_addr, pool->bits, &ds);
|
||||
if ((pool->bits & POOL_IS_FOR_TEMP) == 0) {
|
||||
create_address(&tmp, &pool->start_addr,
|
||||
pool->bits, &ds);
|
||||
} else {
|
||||
create_temporary(&tmp, &pool->start_addr, &ds);
|
||||
}
|
||||
|
||||
/*
|
||||
* Avoid reserved interface IDs.
|
||||
@ -1277,7 +1326,7 @@ activate_lease6(struct ipv6_pool *pool, struct iaaddr **addr,
|
||||
memcpy(&iaaddr->addr, &tmp, sizeof(iaaddr->addr));
|
||||
|
||||
/*
|
||||
* Add the lease to the pool.
|
||||
* Add the lease to the pool (note state is free, not active?!).
|
||||
*/
|
||||
result = add_lease6(pool, iaaddr, valid_lifetime_end_time);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
@ -1578,6 +1627,7 @@ create_prefix(struct in6_addr *pref,
|
||||
for (i=0; i<net_bytes; i++) {
|
||||
str[i] = net_str[i];
|
||||
}
|
||||
i = net_bytes;
|
||||
switch (pool_bits % 8) {
|
||||
case 1: str[i] = (str[i] & 0x7F) | (net_str[i] & 0x80); break;
|
||||
case 2: str[i] = (str[i] & 0x3F) | (net_str[i] & 0xC0); break;
|
||||
@ -1594,15 +1644,16 @@ create_prefix(struct in6_addr *pref,
|
||||
for (i=net_bytes+1; i<16; i++) {
|
||||
str[i] = 0;
|
||||
}
|
||||
i = net_bytes;
|
||||
switch (pref_bits % 8) {
|
||||
case 0: str[i] &= 0;
|
||||
case 1: str[i] &= 0x80;
|
||||
case 2: str[i] &= 0xC0;
|
||||
case 3: str[i] &= 0xE0;
|
||||
case 4: str[i] &= 0xF0;
|
||||
case 5: str[i] &= 0xF8;
|
||||
case 6: str[i] &= 0xFC;
|
||||
case 7: str[i] &= 0xFE;
|
||||
case 0: str[i] &= 0; break;
|
||||
case 1: str[i] &= 0x80; break;
|
||||
case 2: str[i] &= 0xC0; break;
|
||||
case 3: str[i] &= 0xE0; break;
|
||||
case 4: str[i] &= 0xF0; break;
|
||||
case 5: str[i] &= 0xF8; break;
|
||||
case 6: str[i] &= 0xFC; break;
|
||||
case 7: str[i] &= 0xFE; break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1628,10 +1679,10 @@ create_prefix(struct in6_addr *pref,
|
||||
* the long term.
|
||||
*/
|
||||
isc_result_t
|
||||
activate_prefix(struct ipv6_ppool *ppool, struct iaprefix **pref,
|
||||
unsigned int *attempts,
|
||||
const struct data_string *uid,
|
||||
time_t valid_lifetime_end_time) {
|
||||
activate_prefix6(struct ipv6_ppool *ppool, struct iaprefix **pref,
|
||||
unsigned int *attempts,
|
||||
const struct data_string *uid,
|
||||
time_t valid_lifetime_end_time) {
|
||||
struct data_string ds;
|
||||
struct in6_addr tmp;
|
||||
struct iaprefix *test_iapref;
|
||||
@ -1700,10 +1751,11 @@ activate_prefix(struct ipv6_ppool *ppool, struct iaprefix **pref,
|
||||
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.
|
||||
* Add the prefix to the pool (note state is free, not active?!).
|
||||
*/
|
||||
result = add_prefix6(ppool, iapref, valid_lifetime_end_time);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
@ -1976,6 +2028,27 @@ 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.
|
||||
*/
|
||||
@ -2374,7 +2447,7 @@ isc_boolean_t
|
||||
ipv6_addr_in_pool(const struct in6_addr *addr, const struct ipv6_pool *pool) {
|
||||
struct in6_addr tmp;
|
||||
|
||||
ipv6_network_portion(&tmp, addr, pool->bits);
|
||||
ipv6_network_portion(&tmp, addr, pool->bits & ~POOL_IS_FOR_TEMP);
|
||||
if (memcmp(&tmp, &pool->start_addr, sizeof(tmp)) == 0) {
|
||||
return ISC_TRUE;
|
||||
} else {
|
||||
@ -2389,7 +2462,8 @@ 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, const struct in6_addr *addr) {
|
||||
find_ipv6_pool(struct ipv6_pool **pool, int temp,
|
||||
const struct in6_addr *addr) {
|
||||
int i;
|
||||
|
||||
if (pool == NULL) {
|
||||
@ -2402,6 +2476,12 @@ find_ipv6_pool(struct ipv6_pool **pool, const struct in6_addr *addr) {
|
||||
}
|
||||
|
||||
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)) {
|
||||
continue;
|
||||
}
|
||||
if (ipv6_addr_in_pool(addr, pools[i])) {
|
||||
ipv6_pool_reference(pool, pools[i], MDL);
|
||||
return ISC_R_SUCCESS;
|
||||
@ -2421,13 +2501,21 @@ change_leases(struct ia_na *ia,
|
||||
isc_result_t renew_retval;
|
||||
struct ipv6_pool *pool;
|
||||
struct in6_addr *addr;
|
||||
int i;
|
||||
int temp, 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, addr) == ISC_R_SUCCESS) {
|
||||
if (find_ipv6_pool(&pool, temp, addr) == ISC_R_SUCCESS) {
|
||||
renew_retval = change_func(pool, ia->iaaddr[i]);
|
||||
if (renew_retval != ISC_R_SUCCESS) {
|
||||
retval = renew_retval;
|
||||
@ -2655,7 +2743,11 @@ mark_hosts_unavailable_support(const void *name, unsigned len, void *value) {
|
||||
* sit in any pool.)
|
||||
*/
|
||||
p = NULL;
|
||||
if (find_ipv6_pool(&p, &addr) == ISC_R_SUCCESS) {
|
||||
if (find_ipv6_pool(&p, 0, &addr) == ISC_R_SUCCESS) {
|
||||
mark_address_unavailable(p, &addr);
|
||||
ipv6_pool_dereference(&p, MDL);
|
||||
}
|
||||
if (find_ipv6_pool(&p, 1, &addr) == ISC_R_SUCCESS) {
|
||||
mark_address_unavailable(p, &addr);
|
||||
ipv6_pool_dereference(&p, MDL);
|
||||
}
|
||||
@ -2668,6 +2760,56 @@ mark_hosts_unavailable(void) {
|
||||
hash_foreach(host_name_hash, mark_hosts_unavailable_support);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
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;
|
||||
|
||||
h = (struct host_decl *)value;
|
||||
|
||||
/*
|
||||
* If the host has no prefix, we don't need to mark anything.
|
||||
*/
|
||||
if (h->fixed_prefix == NULL) {
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the fixed prefixes.
|
||||
*/
|
||||
for (l = h->fixed_prefix; l != NULL; l = l->next) {
|
||||
if (l->cidrnet.lo_addr.len != 16) {
|
||||
continue;
|
||||
}
|
||||
memcpy(&pref, l->cidrnet.lo_addr.iabuf, 16);
|
||||
|
||||
/*
|
||||
* Find the pool holding this host, and mark the prefix.
|
||||
* (I suppose it is arguably valid to have a host that does not
|
||||
* sit in any pool.)
|
||||
*/
|
||||
p = NULL;
|
||||
if (find_ipv6_ppool(&p, &pref) != ISC_R_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
if (l->cidrnet.bits != (int) p->alloc_plen) {
|
||||
ipv6_ppool_dereference(&p, MDL);
|
||||
continue;
|
||||
}
|
||||
mark_prefix_unavailable(p, &pref);
|
||||
ipv6_ppool_dereference(&p, MDL);
|
||||
}
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
mark_phosts_unavailable(void) {
|
||||
hash_foreach(host_name_hash, mark_phosts_unavailable_support);
|
||||
}
|
||||
|
||||
void
|
||||
mark_interfaces_unavailable(void) {
|
||||
struct interface_info *ip;
|
||||
@ -2678,7 +2820,13 @@ mark_interfaces_unavailable(void) {
|
||||
while (ip != NULL) {
|
||||
for (i=0; i<ip->v6address_count; i++) {
|
||||
p = NULL;
|
||||
if (find_ipv6_pool(&p, &ip->v6addresses[i])
|
||||
if (find_ipv6_pool(&p, 0, &ip->v6addresses[i])
|
||||
== ISC_R_SUCCESS) {
|
||||
mark_address_unavailable(p,
|
||||
&ip->v6addresses[i]);
|
||||
ipv6_pool_dereference(&p, MDL);
|
||||
}
|
||||
if (find_ipv6_pool(&p, 1, &ip->v6addresses[i])
|
||||
== ISC_R_SUCCESS) {
|
||||
mark_address_unavailable(p,
|
||||
&ip->v6addresses[i]);
|
||||
@ -3006,8 +3154,8 @@ main(int argc, char *argv[]) {
|
||||
printf("ERROR: activate_lease6() %s:%d\n", MDL);
|
||||
return 1;
|
||||
}
|
||||
if (pool->num_active != 1) {
|
||||
printf("ERROR: bad num_active %s:%d\n", MDL);
|
||||
if (pool->num_inactive != 1) {
|
||||
printf("ERROR: bad num_inactive %s:%d\n", MDL);
|
||||
return 1;
|
||||
}
|
||||
if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
|
||||
@ -3058,6 +3206,10 @@ main(int argc, char *argv[]) {
|
||||
printf("ERROR: activate_lease6() %s:%d\n", MDL);
|
||||
return 1;
|
||||
}
|
||||
if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
|
||||
printf("ERROR: renew_lease6() %s:%d\n", MDL);
|
||||
return 1;
|
||||
}
|
||||
if (pool->num_active != 1) {
|
||||
printf("ERROR: bad num_active %s:%d\n", MDL);
|
||||
return 1;
|
||||
@ -3079,6 +3231,10 @@ main(int argc, char *argv[]) {
|
||||
printf("ERROR: activate_lease6() %s:%d\n", MDL);
|
||||
return 1;
|
||||
}
|
||||
if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
|
||||
printf("ERROR: renew_lease6() %s:%d\n", MDL);
|
||||
return 1;
|
||||
}
|
||||
if (pool->num_active != 1) {
|
||||
printf("ERROR: bad num_active %s:%d\n", MDL);
|
||||
return 1;
|
||||
@ -3155,6 +3311,10 @@ main(int argc, char *argv[]) {
|
||||
printf("ERROR: activate_lease6() %s:%d\n", MDL);
|
||||
return 1;
|
||||
}
|
||||
if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
|
||||
printf("ERROR: renew_lease6() %s:%d\n", MDL);
|
||||
return 1;
|
||||
}
|
||||
if (iaaddr_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
|
||||
printf("ERROR: iaaddr_dereference() %s:%d\n", MDL);
|
||||
return 1;
|
||||
@ -3211,6 +3371,7 @@ main(int argc, char *argv[]) {
|
||||
* Test 8: small pool
|
||||
*/
|
||||
pool = NULL;
|
||||
addr.s6_addr[14] = 0x81;
|
||||
if (ipv6_pool_allocate(&pool, &addr, 127, MDL) != ISC_R_SUCCESS) {
|
||||
printf("ERROR: ipv6_pool_allocate() %s:%d\n", MDL);
|
||||
return 1;
|
||||
@ -3220,6 +3381,10 @@ main(int argc, char *argv[]) {
|
||||
printf("ERROR: activate_lease6() %s:%d\n", MDL);
|
||||
return 1;
|
||||
}
|
||||
if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
|
||||
printf("ERROR: renew_lease6() %s:%d\n", MDL);
|
||||
return 1;
|
||||
}
|
||||
if (iaaddr_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
|
||||
printf("ERROR: iaaddr_dereference() %s:%d\n", MDL);
|
||||
return 1;
|
||||
@ -3229,6 +3394,10 @@ main(int argc, char *argv[]) {
|
||||
printf("ERROR: activate_lease6() %s:%d\n", MDL);
|
||||
return 1;
|
||||
}
|
||||
if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) {
|
||||
printf("ERROR: renew_lease6() %s:%d\n", MDL);
|
||||
return 1;
|
||||
}
|
||||
if (iaaddr_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) {
|
||||
printf("ERROR: iaaddr_dereference() %s:%d\n", MDL);
|
||||
return 1;
|
||||
@ -3242,6 +3411,7 @@ main(int argc, char *argv[]) {
|
||||
printf("ERROR: ipv6_pool_dereference() %s:%d\n", MDL);
|
||||
return 1;
|
||||
}
|
||||
addr.s6_addr[14] = 0;
|
||||
|
||||
/*
|
||||
* Test 9: functions across all pools
|
||||
@ -3260,7 +3430,7 @@ main(int argc, char *argv[]) {
|
||||
return 1;
|
||||
}
|
||||
pool = NULL;
|
||||
if (find_ipv6_pool(&pool, &addr) != ISC_R_SUCCESS) {
|
||||
if (find_ipv6_pool(&pool, 0, &addr) != ISC_R_SUCCESS) {
|
||||
printf("ERROR: find_ipv6_pool() %s:%d\n", MDL);
|
||||
return 1;
|
||||
}
|
||||
@ -3270,7 +3440,7 @@ main(int argc, char *argv[]) {
|
||||
}
|
||||
inet_pton(AF_INET6, "1:2:3:4:ffff:ffff:ffff:ffff", &addr);
|
||||
pool = NULL;
|
||||
if (find_ipv6_pool(&pool, &addr) != ISC_R_SUCCESS) {
|
||||
if (find_ipv6_pool(&pool, 0, &addr) != ISC_R_SUCCESS) {
|
||||
printf("ERROR: find_ipv6_pool() %s:%d\n", MDL);
|
||||
return 1;
|
||||
}
|
||||
@ -3280,13 +3450,13 @@ main(int argc, char *argv[]) {
|
||||
}
|
||||
inet_pton(AF_INET6, "1:2:3:5::", &addr);
|
||||
pool = NULL;
|
||||
if (find_ipv6_pool(&pool, &addr) != ISC_R_NOTFOUND) {
|
||||
if (find_ipv6_pool(&pool, 0, &addr) != ISC_R_NOTFOUND) {
|
||||
printf("ERROR: find_ipv6_pool() %s:%d\n", MDL);
|
||||
return 1;
|
||||
}
|
||||
inet_pton(AF_INET6, "1:2:3:3:ffff:ffff:ffff:ffff", &addr);
|
||||
pool = NULL;
|
||||
if (find_ipv6_pool(&pool, &addr) != ISC_R_NOTFOUND) {
|
||||
if (find_ipv6_pool(&pool, 0, &addr) != ISC_R_NOTFOUND) {
|
||||
printf("ERROR: find_ipv6_pool() %s:%d\n", MDL);
|
||||
return 1;
|
||||
}
|
||||
@ -3301,11 +3471,14 @@ main(int argc, char *argv[]) {
|
||||
{
|
||||
struct in6_addr r;
|
||||
struct data_string ds;
|
||||
u_char data[16];
|
||||
char buf[64];
|
||||
int i, j;
|
||||
|
||||
memset(&ds, 0, sizeof(ds));
|
||||
memset(data, 0xaa, sizeof(data));
|
||||
ds.len = 16;
|
||||
ds.data = &addr;
|
||||
ds.data = data;
|
||||
|
||||
inet_pton(AF_INET6, "3ffe:501:ffff:100::", &addr);
|
||||
for (i = 32; i < 42; i++)
|
||||
|
@ -238,7 +238,8 @@ static struct option server_options[] = {
|
||||
{ "dhcpv6-lease-file-name", "t", &server_universe, 54, 1 },
|
||||
{ "dhcpv6-pid-file-name", "t", &server_universe, 55, 1 },
|
||||
{ "limit-addrs-per-ia", "L", &server_universe, 56, 1 },
|
||||
{ "delayed-ack", "S", &server_universe, 57, 1 },
|
||||
{ "limit-prefs-per-ia", "L", &server_universe, 57, 1 },
|
||||
{ "delayed-ack", "S", &server_universe, 58, 1 },
|
||||
{ NULL, NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user