aboutsummaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/bootp.c59
-rw-r--r--server/confpars.c171
-rw-r--r--server/db.c8
-rw-r--r--server/ddns.c230
-rw-r--r--server/dhcp.c78
-rw-r--r--server/dhcpd.c4
-rw-r--r--server/dhcpd.conf.59
-rw-r--r--server/dhcpleasequery.c15
-rw-r--r--server/dhcpv6.c152
-rw-r--r--server/failover.c22
-rw-r--r--server/mdb.c53
-rw-r--r--server/mdb6.c262
-rw-r--r--server/omapi.c60
13 files changed, 801 insertions, 322 deletions
diff --git a/server/bootp.c b/server/bootp.c
index c88fab8..f0b787c 100644
--- a/server/bootp.c
+++ b/server/bootp.c
@@ -3,7 +3,8 @@
BOOTP Protocol support. */
/*
- * Copyright (c) 2004,2005,2007,2009 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2009,2012 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004,2005,2007 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1995-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
@@ -176,11 +177,12 @@ void bootp (packet)
}
/* Execute the host statements. */
- execute_statements_in_scope ((struct binding_value **)0,
- packet, lease, (struct client_state *)0,
- packet -> options, options,
- &lease -> scope,
- hp -> group, lease -> subnet -> group);
+ if (hp != NULL) {
+ execute_statements_in_scope (NULL, packet, lease, NULL,
+ packet->options, options,
+ &lease->scope,
+ hp->group, lease->subnet->group);
+ }
/* Drop the request if it's not allowed for this client. */
if ((oc = lookup_option (&server_universe, options, SV_ALLOW_BOOTP)) &&
@@ -361,15 +363,16 @@ void bootp (packet)
}
/* Report what we're doing... */
- log_info ("%s", msgbuf);
- log_info ("BOOTREPLY for %s to %s (%s) via %s",
- piaddr (lease->ip_addr), hp -> name,
- print_hw_addr (packet -> raw -> htype,
- packet -> raw -> hlen,
- packet -> raw -> chaddr),
- packet -> raw -> giaddr.s_addr
- ? inet_ntoa (packet -> raw -> giaddr)
- : packet -> interface -> name);
+ log_info("%s", msgbuf);
+ log_info("BOOTREPLY for %s to %s (%s) via %s",
+ piaddr(lease->ip_addr),
+ ((hp != NULL) && (hp->name != NULL)) ? hp -> name : "unknown",
+ print_hw_addr (packet->raw->htype,
+ packet->raw->hlen,
+ packet->raw->chaddr),
+ packet->raw->giaddr.s_addr
+ ? inet_ntoa (packet->raw->giaddr)
+ : packet->interface->name);
/* Set up the parts of the address that are in common. */
to.sin_family = AF_INET;
@@ -384,10 +387,16 @@ void bootp (packet)
to.sin_port = local_port;
if (fallback_interface) {
- result = send_packet (fallback_interface,
- (struct packet *)0,
- &raw, outgoing.packet_length,
- from, &to, &hto);
+ result = send_packet (fallback_interface, NULL, &raw,
+ outgoing.packet_length, from,
+ &to, &hto);
+ if (result < 0) {
+ log_error ("%s:%d: Failed to send %d byte long "
+ "packet over %s interface.", MDL,
+ outgoing.packet_length,
+ fallback_interface->name);
+ }
+
goto out;
}
@@ -407,10 +416,16 @@ void bootp (packet)
}
errno = 0;
- result = send_packet (packet -> interface,
- packet, &raw, outgoing.packet_length,
- from, &to, &hto);
+ result = send_packet(packet->interface, packet, &raw,
+ outgoing.packet_length, from, &to, &hto);
+ if (result < 0) {
+ log_error ("%s:%d: Failed to send %d byte long packet over %s"
+ " interface.", MDL, outgoing.packet_length,
+ packet->interface->name);
+ }
+
out:
+
if (options)
option_state_dereference (&options, MDL);
if (lease)
diff --git a/server/confpars.c b/server/confpars.c
index c0742d4..1c9c480 100644
--- a/server/confpars.c
+++ b/server/confpars.c
@@ -3,7 +3,7 @@
Parser for dhcpd config file... */
/*
- * Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2012 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1995-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
@@ -2724,84 +2724,83 @@ void parse_group_declaration (cfile, group)
enum dhcp_token token;
struct group *g;
int declaration = 0;
- struct group_object *t;
+ struct group_object *t = NULL;
isc_result_t status;
char *name = NULL;
int deletedp = 0;
int dynamicp = 0;
int staticp = 0;
- g = (struct group *)0;
- if (!clone_group (&g, group, MDL))
- log_fatal ("no memory for explicit group.");
+ g = NULL;
+ if (!clone_group(&g, group, MDL))
+ log_fatal("no memory for explicit group.");
- token = peek_token (&val, (unsigned *)0, cfile);
+ token = peek_token(&val, NULL, cfile);
if (is_identifier (token) || token == STRING) {
- next_token (&val, (unsigned *)0, cfile);
+ next_token(&val, NULL, cfile);
- name = dmalloc (strlen (val) + 1, MDL);
+ name = dmalloc(strlen(val) + 1, MDL);
if (!name)
- log_fatal ("no memory for group decl name %s", val);
- strcpy (name, val);
+ log_fatal("no memory for group decl name %s", val);
+ strcpy(name, val);
}
- if (!parse_lbrace (cfile)) {
- group_dereference (&g, MDL);
+ if (!parse_lbrace(cfile)) {
+ group_dereference(&g, MDL);
return;
}
do {
- token = peek_token (&val, (unsigned *)0, cfile);
+ token = peek_token(&val, NULL, cfile);
if (token == RBRACE) {
- token = next_token (&val, (unsigned *)0, cfile);
+ token = next_token(&val, NULL, cfile);
break;
} else if (token == END_OF_FILE) {
- token = next_token (&val, (unsigned *)0, cfile);
- parse_warn (cfile, "unexpected end of file");
+ token = next_token(&val, NULL, cfile);
+ parse_warn(cfile, "unexpected end of file");
break;
} else if (token == TOKEN_DELETED) {
- token = next_token (&val, (unsigned *)0, cfile);
- parse_semi (cfile);
+ token = next_token(&val, NULL, cfile);
+ parse_semi(cfile);
deletedp = 1;
} else if (token == DYNAMIC) {
- token = next_token (&val, (unsigned *)0, cfile);
- parse_semi (cfile);
+ token = next_token(&val, NULL, cfile);
+ parse_semi(cfile);
dynamicp = 1;
} else if (token == STATIC) {
- token = next_token (&val, (unsigned *)0, cfile);
- parse_semi (cfile);
+ token = next_token(&val, NULL, cfile);
+ parse_semi(cfile);
staticp = 1;
}
- declaration = parse_statement (cfile, g, GROUP_DECL,
- (struct host_decl *)0,
- declaration);
+ declaration = parse_statement(cfile, g, GROUP_DECL,
+ NULL, declaration);
} while (1);
if (name) {
if (deletedp) {
if (group_name_hash) {
- t = (struct group_object *)0;
- if (group_hash_lookup (&t, group_name_hash,
- name,
- strlen (name), MDL)) {
- delete_group (t, 0);
+ t = NULL;
+ if (group_hash_lookup(&t, group_name_hash,
+ name,
+ strlen(name), MDL)) {
+ delete_group(t, 0);
}
}
} else {
- t = (struct group_object *)0;
- status = group_object_allocate (&t, MDL);
+ t = NULL;
+ status = group_object_allocate(&t, MDL);
if (status != ISC_R_SUCCESS)
- log_fatal ("no memory for group decl %s: %s",
- val, isc_result_totext (status));
- group_reference (&t -> group, g, MDL);
- t -> name = name;
- t -> flags = ((staticp ? GROUP_OBJECT_STATIC : 0) |
- (dynamicp ? GROUP_OBJECT_DYNAMIC : 0) |
- (deletedp ? GROUP_OBJECT_DELETED : 0));
- supersede_group (t, 0);
- }
- if (t)
- group_object_dereference (&t, MDL);
+ log_fatal("no memory for group decl %s: %s",
+ val, isc_result_totext(status));
+ group_reference(&t->group, g, MDL);
+ t->name = name;
+ t->flags = ((staticp ? GROUP_OBJECT_STATIC : 0) |
+ (dynamicp ? GROUP_OBJECT_DYNAMIC : 0) |
+ (deletedp ? GROUP_OBJECT_DELETED : 0));
+ supersede_group(t, 0);
+ }
+ if (t != NULL)
+ group_object_dereference(&t, MDL);
}
}
@@ -4441,21 +4440,39 @@ parse_ia_na_declaration(struct parse *cfile) {
binding_scope_dereference(&scope, MDL);
}
- /* add to our various structures */
- ia_add_iasubopt(ia, iaaddr, MDL);
- ia_reference(&iaaddr->ia, ia, MDL);
+ /* find the pool this address is in */
pool = NULL;
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",
+ parse_warn(cfile, "no pool found for address %s",
addr_buf);
return;
}
- add_lease6(pool, iaaddr, end_time);
- ipv6_pool_dereference(&pool, MDL);
+
+ /* remove old information */
+ if (cleanup_lease6(ia_na_active, pool,
+ iaaddr, ia) != ISC_R_SUCCESS) {
+ inet_ntop(AF_INET6, &iaaddr->addr,
+ addr_buf, sizeof(addr_buf));
+ parse_warn(cfile, "duplicate na lease for address %s",
+ addr_buf);
+ }
+
+ /*
+ * if we like the lease we add it to our various structues
+ * otherwise we leave it and it will get cleaned when we
+ * do the iasubopt_dereference.
+ */
+ if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
+ ia_add_iasubopt(ia, iaaddr, MDL);
+ ia_reference(&iaaddr->ia, ia, MDL);
+ add_lease6(pool, iaaddr, end_time);
+ }
+
iasubopt_dereference(&iaaddr, MDL);
+ ipv6_pool_dereference(&pool, MDL);
}
/*
@@ -4804,19 +4821,37 @@ parse_ia_ta_declaration(struct parse *cfile) {
binding_scope_dereference(&scope, MDL);
}
- /* add to our various structures */
- ia_add_iasubopt(ia, iaaddr, MDL);
- ia_reference(&iaaddr->ia, ia, MDL);
+ /* find the pool this address is in */
pool = NULL;
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",
+ parse_warn(cfile, "no pool found for address %s",
addr_buf);
return;
}
- add_lease6(pool, iaaddr, end_time);
+
+ /* remove old information */
+ if (cleanup_lease6(ia_ta_active, pool,
+ iaaddr, ia) != ISC_R_SUCCESS) {
+ inet_ntop(AF_INET6, &iaaddr->addr,
+ addr_buf, sizeof(addr_buf));
+ parse_warn(cfile, "duplicate ta lease for address %s",
+ addr_buf);
+ }
+
+ /*
+ * if we like the lease we add it to our various structues
+ * otherwise we leave it and it will get cleaned when we
+ * do the iasubopt_dereference.
+ */
+ if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
+ ia_add_iasubopt(ia, iaaddr, MDL);
+ ia_reference(&iaaddr->ia, ia, MDL);
+ add_lease6(pool, iaaddr, end_time);
+ }
+
ipv6_pool_dereference(&pool, MDL);
iasubopt_dereference(&iaaddr, MDL);
}
@@ -5168,19 +5203,37 @@ parse_ia_pd_declaration(struct parse *cfile) {
binding_scope_dereference(&scope, MDL);
}
- /* add to our various structures */
- ia_add_iasubopt(ia, iapref, MDL);
- ia_reference(&iapref->ia, ia, MDL);
+ /* find the pool this address is in */
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 pool found for address %s",
+ parse_warn(cfile, "no pool found for address %s",
addr_buf);
return;
}
- add_lease6(pool, iapref, end_time);
+
+ /* remove old information */
+ if (cleanup_lease6(ia_pd_active, pool,
+ iapref, ia) != ISC_R_SUCCESS) {
+ inet_ntop(AF_INET6, &iapref->addr,
+ addr_buf, sizeof(addr_buf));
+ parse_warn(cfile, "duplicate pd lease for address %s",
+ addr_buf);
+ }
+
+ /*
+ * if we like the lease we add it to our various structues
+ * otherwise we leave it and it will get cleaned when we
+ * do the iasubopt_dereference.
+ */
+ if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
+ ia_add_iasubopt(ia, iapref, MDL);
+ ia_reference(&iapref->ia, ia, MDL);
+ add_lease6(pool, iapref, end_time);
+ }
+
ipv6_pool_dereference(&pool, MDL);
iasubopt_dereference(&iapref, MDL);
}
diff --git a/server/db.c b/server/db.c
index 107d0b6..d41aa48 100644
--- a/server/db.c
+++ b/server/db.c
@@ -3,7 +3,7 @@
Persistent database management routines for DHCPD... */
/*
- * Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2010,2012 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1995-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
@@ -1021,7 +1021,11 @@ void db_startup (testp)
/* Read in the existing lease file... */
status = read_conf_file (path_dhcpd_db,
(struct group *)0, 0, 1);
- /* XXX ignore status? */
+ if (status != ISC_R_SUCCESS) {
+ /* XXX ignore status? */
+ ;
+ }
+
#if defined (TRACING)
}
#endif
diff --git a/server/ddns.c b/server/ddns.c
index 2387e04..0c93073 100644
--- a/server/ddns.c
+++ b/server/ddns.c
@@ -3,7 +3,7 @@
Dynamic DNS updates. */
/*
- * Copyright (c) 2009-2011 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2009-2012 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 2000-2003 by Internet Software Consortium
*
@@ -80,7 +80,6 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
struct option_cache *oc;
int s1, s2;
int result = 0;
- isc_result_t rcode1 = ISC_R_SUCCESS;
int server_updates_a = 1;
//int server_updates_ptr = 1;
struct buffer *bp = (struct buffer *)0;
@@ -103,12 +102,12 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
if (lease != NULL) {
if ((old != NULL) && (old->ddns_cb != NULL)) {
- ddns_cancel(old->ddns_cb);
+ ddns_cancel(old->ddns_cb, MDL);
old->ddns_cb = NULL;
}
} else if (lease6 != NULL) {
if ((old6 != NULL) && (old6->ddns_cb != NULL)) {
- ddns_cancel(old6->ddns_cb);
+ ddns_cancel(old6->ddns_cb, MDL);
old6->ddns_cb = NULL;
}
} else {
@@ -123,8 +122,12 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
if (ddns_cb == NULL) {
return(0);
}
- /* assume that we shall update both the A and ptr records */
- ddns_cb->flags = DDNS_UPDATE_ADDR | DDNS_UPDATE_PTR;
+ /*
+ * Assume that we shall update both the A and ptr records and,
+ * as this is an update, set the active flag
+ */
+ ddns_cb->flags = DDNS_UPDATE_ADDR | DDNS_UPDATE_PTR |
+ DDNS_ACTIVE_LEASE;
/*
* For v4 we flag static leases so we don't try
@@ -329,7 +332,7 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
/* If desired do the removals */
if (do_remove != 0) {
- (void) ddns_removals(lease, lease6, NULL);
+ (void) ddns_removals(lease, lease6, NULL, ISC_TRUE);
}
goto out;
}
@@ -531,7 +534,11 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
* the ddns messages. Currently we don't.
*/
if (do_remove) {
- rcode1 = ddns_removals(lease, lease6, ddns_cb);
+ /*
+ * We should log a more specific error closer to the actual
+ * error if we want one. ddns_removal failure not logged here.
+ */
+ (void) ddns_removals(lease, lease6, ddns_cb, ISC_TRUE);
}
else {
ddns_fwd_srv_connector(lease, lease6, scope, ddns_cb,
@@ -709,7 +716,7 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
return result;
}
-/*
+/*%<
* Utility function to update text strings within a lease.
*
* The first issue is to find the proper scope. Sometimes we shall be
@@ -719,6 +726,19 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
* Lastly, if we needed to find the scope we write it out, if we used a
* scope that was passed as an argument we don't write it, assuming that
* our caller (or his ...) will do the write.
+ *
+ *\li ddns_cb - the control block for the DDNS request
+ *
+ *\li inscope - a pointer to the scope to update. This may be NULL
+ * in which case we use the control block to find the lease and
+ * then the scope.
+ *
+ * Returns
+ *\li ISC_R_SUCCESS
+ *
+ *\li ISC_R_FAILURE - The routine was unable to find an expected scope.
+ * In some cases (static and inactive leases) we don't expect a scope
+ * and return success.
*/
isc_result_t
@@ -739,6 +759,14 @@ ddns_update_lease_text(dhcp_ddns_cb_t *ddns_cb,
if (ddns_cb->flags & DDNS_STATIC_LEASE)
return (ISC_R_SUCCESS);
+ /*
+ * If we are processing an expired or released v6 lease
+ * or some types of v4 leases we don't actually have a
+ * scope to update
+ */
+ if ((ddns_cb->flags & DDNS_ACTIVE_LEASE) == 0)
+ return (ISC_R_SUCCESS);
+
if (inscope != NULL) {
scope = inscope;
} else if (ddns_cb->address.len == 4) {
@@ -1084,6 +1112,15 @@ ddns_update_lease_ptr(struct lease *lease,
return (ISC_R_SUCCESS);
}
+ /*
+ * If we are processing an expired or released v6 lease
+ * we don't actually have a lease to update
+ */
+ if ((ddns_cb->address.len == 16) &&
+ ((ddns_cb->flags & DDNS_ACTIVE_LEASE) == 0)) {
+ return (ISC_R_SUCCESS);
+ }
+
if (lease != NULL) {
safe_lease_update(lease, ddns_cb, ddns_cb_set,
file, line);
@@ -1131,7 +1168,7 @@ ddns_update_lease_ptr(struct lease *lease,
ISC_R_SUCCESS) &&
(find_ipv6_pool(&pool, D6O_IA_NA, &addr) !=
ISC_R_SUCCESS)) {
- inet_ntop(AF_INET6, &lease6->addr, addrbuf,
+ inet_ntop(AF_INET6, &addr, addrbuf,
MAX_ADDRESS_STRING_LEN);
log_error("%s(%d): Pool for lease %s not found.",
file, line, addrbuf);
@@ -1151,7 +1188,7 @@ ddns_update_lease_ptr(struct lease *lease,
find_lease6->ddns_cb = ddns_cb_set;
iasubopt_dereference(&find_lease6, MDL);
} else {
- inet_ntop(AF_INET6, &lease6->addr, addrbuf,
+ inet_ntop(AF_INET6, &addr, addrbuf,
MAX_ADDRESS_STRING_LEN);
log_error("%s(%d): Lease %s not found within pool.",
file, line, addrbuf);
@@ -1240,6 +1277,11 @@ ddns_ptr_remove(dhcp_ddns_cb_t *ddns_cb,
/* trigger any add operation */
result = ISC_R_SUCCESS;
+#if defined (DEBUG_DNS_UPDATES)
+ log_info("DDNS: removed map or no reverse map to remove %.*s",
+ (int)ddns_cb->rev_name.len,
+ (const char *)ddns_cb->rev_name.data);
+#endif
break;
default:
@@ -1314,7 +1356,7 @@ ddns_fwd_srv_add2(dhcp_ddns_cb_t *ddns_cb,
ddns_cb->state = DDNS_STATE_ADD_PTR;
ddns_cb->cur_func = ddns_ptr_add;
- result = ddns_modify_ptr(ddns_cb);
+ result = ddns_modify_ptr(ddns_cb, MDL);
if (result == ISC_R_SUCCESS) {
return;
}
@@ -1387,12 +1429,11 @@ ddns_fwd_srv_add1(dhcp_ddns_cb_t *ddns_cb,
ddns_cb->state = DDNS_STATE_ADD_PTR;
ddns_cb->cur_func = ddns_ptr_add;
- result = ddns_modify_ptr(ddns_cb);
+ result = ddns_modify_ptr(ddns_cb, MDL);
if (result == ISC_R_SUCCESS) {
return;
}
}
-
break;
case DNS_R_YXDOMAIN:
@@ -1400,11 +1441,10 @@ ddns_fwd_srv_add1(dhcp_ddns_cb_t *ddns_cb,
ddns_cb->state = DDNS_STATE_ADD_FW_YXDHCID;
ddns_cb->cur_func = ddns_fwd_srv_add2;
- result = ddns_modify_fwd(ddns_cb);
+ result = ddns_modify_fwd(ddns_cb, MDL);
if (result == ISC_R_SUCCESS) {
return;
}
-
break;
default:
@@ -1455,12 +1495,12 @@ ddns_fwd_srv_connector(struct lease *lease,
if (ddns_cb->flags & DDNS_UPDATE_ADDR) {
ddns_cb->state = DDNS_STATE_ADD_FW_NXDOMAIN;
ddns_cb->cur_func = ddns_fwd_srv_add1;
- result = ddns_modify_fwd(ddns_cb);
+ result = ddns_modify_fwd(ddns_cb, MDL);
} else if ((ddns_cb->flags & DDNS_UPDATE_PTR) &&
(ddns_cb->rev_name.len != 0)) {
ddns_cb->state = DDNS_STATE_ADD_PTR;
ddns_cb->cur_func = ddns_ptr_add;
- result = ddns_modify_ptr(ddns_cb);
+ result = ddns_modify_ptr(ddns_cb, MDL);
} else {
ddns_update_lease_text(ddns_cb, inscope);
}
@@ -1505,7 +1545,7 @@ ddns_fwd_srv_rem2(dhcp_ddns_cb_t *ddns_cb,
ddns_cb->state = DDNS_STATE_REM_PTR;
ddns_cb->cur_func = ddns_ptr_remove;
- eresult = ddns_modify_ptr(ddns_cb);
+ eresult = ddns_modify_ptr(ddns_cb, MDL);
if (eresult == ISC_R_SUCCESS) {
return;
}
@@ -1545,7 +1585,7 @@ ddns_fwd_srv_rem1(dhcp_ddns_cb_t *ddns_cb,
/* Do the second step of the FWD removal */
ddns_cb->state = DDNS_STATE_REM_FW_NXRR;
ddns_cb->cur_func = ddns_fwd_srv_rem2;
- result = ddns_modify_fwd(ddns_cb);
+ result = ddns_modify_fwd(ddns_cb, MDL);
if (result == ISC_R_SUCCESS) {
return;
}
@@ -1555,6 +1595,10 @@ ddns_fwd_srv_rem1(dhcp_ddns_cb_t *ddns_cb,
case DNS_R_NXDOMAIN:
ddns_update_lease_text(ddns_cb, NULL);
+#if defined (DEBUG_DNS_UPDATES)
+ log_info("DDNS: no forward map to remove. %p", ddns_cb);
+#endif
+
/* Do the next operation */
if ((ddns_cb->flags & DDNS_UPDATE_PTR) != 0) {
/* if we have zone information get rid of it */
@@ -1565,7 +1609,7 @@ ddns_fwd_srv_rem1(dhcp_ddns_cb_t *ddns_cb,
ddns_cb->state = DDNS_STATE_REM_PTR;
ddns_cb->cur_func = ddns_ptr_remove;
- result = ddns_modify_ptr(ddns_cb);
+ result = ddns_modify_ptr(ddns_cb, MDL);
if (result == ISC_R_SUCCESS) {
return;
}
@@ -1585,39 +1629,124 @@ ddns_fwd_srv_rem1(dhcp_ddns_cb_t *ddns_cb,
ddns_cb_free(ddns_cb, MDL);
}
-
-/*
+/*%<
* Remove relevant entries from DNS.
*
- * Return values:
- * 0 - badness occurred and we weren't able to do what was wanted
- * 1 - we were able to do stuff but it's in progress
+ * \li lease - lease to start with if this is for v4
+ *
+ * \li lease6 - lease to start with if this is for v6
+ *
+ * \li add_ddns_cb - control block for additional DDNS work. This
+ * is used when the code is going to add a DDNS entry after removing
+ * the current entry.
+ *
+ * \li active - indication about the status of the lease. It is
+ * ISC_TRUE if the lease is still active, and FALSE if the lease
+ * is inactive. This is used to indicate if the lease is inactive or going
+ * to inactive so we can avoid trying to update the lease with cb pointers
+ * and text information if it isn't useful.
+ *
+ * Returns
+ * \li #ISC_R_FAILURE - badness occurred and we weren't able to do what was wanted
+ * \li #ISC_R_SUCCESS - we were able to do stuff but it's in progress
+ *
* in both cases any additional block has been passed on to it's handler
*/
-int
+isc_result_t
ddns_removals(struct lease *lease,
struct iasubopt *lease6,
- dhcp_ddns_cb_t *add_ddns_cb)
+ dhcp_ddns_cb_t *add_ddns_cb,
+ isc_boolean_t active)
{
isc_result_t rcode, execute_add = ISC_R_FAILURE;
struct binding_scope **scope = NULL;
- int result = 0;
+ isc_result_t result = ISC_R_FAILURE;
dhcp_ddns_cb_t *ddns_cb = NULL;
struct data_string leaseid;
/*
- * Cancel any outstanding requests. When called
- * from within the DNS code we probably will have
- * already done the cancel but if called from outside
- * - for example as part of a lease expiry - we won't.
+ * See if we need to cancel an outstanding request. Mostly this is
+ * used to handle the case where this routine is called twice for
+ * the same release or abandon event.
+ *
+ * When called from the dns code as part of an update request
+ * (add_ddns_cb != NULL) any outstanding requests will have already
+ * been cancelled.
+ *
+ * If the new request is just a removal and we have an outstanding
+ * request we have several options:
+ *
+ * - we are doing an update or we are doing a removal and the active
+ * flag has changed from TRUE to FALSE. In these cases we need to
+ * cancel the old request and start the new one.
+ *
+ * - other wise we are doing a removal with the active flag unchanged.
+ * In this case we can let the current removal continue and do not need
+ * to start a new one. If the old request included an update to be
+ * done after the removal we need to kill the update part of the
+ * request.
*/
- if ((lease != NULL) && (lease->ddns_cb != NULL)) {
- ddns_cancel(lease->ddns_cb);
- lease->ddns_cb = NULL;
- } else if ((lease6 != NULL) && (lease6->ddns_cb != NULL)) {
- ddns_cancel(lease6->ddns_cb);
- lease6->ddns_cb = NULL;
+
+ if (add_ddns_cb == NULL) {
+ if ((lease != NULL) && (lease->ddns_cb != NULL)) {
+ ddns_cb = lease->ddns_cb;
+
+ /*
+ * Is the old request an update or did the
+ * the active flag change?
+ */
+ if (((ddns_cb->state == DDNS_STATE_ADD_PTR) ||
+ (ddns_cb->state == DDNS_STATE_ADD_FW_NXDOMAIN) ||
+ (ddns_cb->state == DDNS_STATE_ADD_FW_YXDHCID)) ||
+ ((active == ISC_FALSE) &&
+ ((ddns_cb->flags & DDNS_ACTIVE_LEASE) != 0))) {
+ /* Cancel the current request */
+ ddns_cancel(lease->ddns_cb, MDL);
+ lease->ddns_cb = NULL;
+ } else {
+ /* Remvoval, check and remove updates */
+ if (ddns_cb->next_op != NULL) {
+ ddns_cb_free(ddns_cb->next_op, MDL);
+ ddns_cb->next_op = NULL;
+ }
+#if defined (DEBUG_DNS_UPDATES)
+ log_info("DDNS %s(%d): removal already in "
+ "progress new ddns_cb=%p",
+ MDL, ddns_cb);
+#endif
+ return (ISC_R_SUCCESS);
+ }
+ } else if ((lease6 != NULL) && (lease6->ddns_cb != NULL)) {
+ ddns_cb = lease6->ddns_cb;
+
+ /*
+ * Is the old request an update or did the
+ * the active flag change?
+ */
+ if (((ddns_cb->state == DDNS_STATE_ADD_PTR) ||
+ (ddns_cb->state == DDNS_STATE_ADD_FW_NXDOMAIN) ||
+ (ddns_cb->state == DDNS_STATE_ADD_FW_YXDHCID)) ||
+ ((active == ISC_FALSE) &&
+ ((ddns_cb->flags & DDNS_ACTIVE_LEASE) != 0))) {
+ /* Cancel the current request */
+ ddns_cancel(lease6->ddns_cb, MDL);
+ lease6->ddns_cb = NULL;
+ } else {
+ /* Remvoval, check and remove updates */
+ if (ddns_cb->next_op != NULL) {
+ ddns_cb_free(ddns_cb->next_op, MDL);
+ ddns_cb->next_op = NULL;
+ }
+#if defined (DEBUG_DNS_UPDATES)
+ log_info("DDNS %s(%d): removal already in "
+ "progress new ddns_cb=%p",
+ MDL, ddns_cb);
+#endif
+ return (ISC_R_SUCCESS);
+ }
+ }
+ ddns_cb = NULL;
}
/* allocate our control block */
@@ -1643,6 +1772,17 @@ ddns_removals(struct lease *lease,
} else
goto cleanup;
+ /*
+ * Set the flag bit if the lease is active, that is it isn't
+ * expired or released. This is used to determine if we need
+ * to update the scope information for both v4 and v6 and
+ * the lease information for v6 when the response
+ * from the DNS code is processed.
+ */
+ if (active == ISC_TRUE) {
+ ddns_cb->flags |= DDNS_ACTIVE_LEASE;
+ }
+
/* No scope implies that DDNS has not been performed for this lease. */
if (*scope == NULL)
goto cleanup;
@@ -1727,11 +1867,11 @@ ddns_removals(struct lease *lease,
ddns_cb->state = DDNS_STATE_REM_FW_YXDHCID;
ddns_cb->cur_func = ddns_fwd_srv_rem1;
- rcode = ddns_modify_fwd(ddns_cb);
+ rcode = ddns_modify_fwd(ddns_cb, MDL);
if (rcode == ISC_R_SUCCESS) {
ddns_update_lease_ptr(lease, lease6, ddns_cb,
ddns_cb, MDL);
- return(1);
+ return (ISC_R_SUCCESS);
}
/*
@@ -1764,14 +1904,14 @@ ddns_removals(struct lease *lease,
add_ddns_cb = NULL;
}
else {
- result = 1;
+ result = ISC_R_SUCCESS;
}
- rcode = ddns_modify_ptr(ddns_cb);
+ rcode = ddns_modify_ptr(ddns_cb, MDL);
if (rcode == ISC_R_SUCCESS) {
ddns_update_lease_ptr(lease, lease6, ddns_cb, ddns_cb,
MDL);
- return(result);
+ return (result);
}
/* We weren't able to process the request tag the
@@ -1791,7 +1931,7 @@ ddns_removals(struct lease *lease,
if (ddns_cb != NULL)
ddns_cb_free(ddns_cb, MDL);
- return(result);
+ return (result);
}
#endif /* NSUPDATE */
diff --git a/server/dhcp.c b/server/dhcp.c
index da4585f..2357175 100644
--- a/server/dhcp.c
+++ b/server/dhcp.c
@@ -3,7 +3,7 @@
DHCP Protocol engine. */
/*
- * Copyright (c) 2004-2011 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2012 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1995-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
@@ -419,7 +419,6 @@ void dhcprequest (packet, ms_nulltp, ip_lease)
#if defined (FAILOVER_PROTOCOL)
dhcp_failover_state_t *peer;
#endif
- int have_server_identifier = 0;
int have_requested_addr = 0;
oc = lookup_option (&dhcp_universe, packet -> options,
@@ -473,7 +472,6 @@ void dhcprequest (packet, ms_nulltp, ip_lease)
* safe.
*/
sprintf (smbuf, " (%s)", piaddr (sip));
- have_server_identifier = 1;
} else
smbuf [0] = 0;
@@ -969,6 +967,8 @@ void dhcpinform (packet, ms_nulltp)
struct sockaddr_in to;
struct in_addr from;
isc_boolean_t zeroed_ciaddr;
+ struct interface_info *interface;
+ int result;
/* The client should set ciaddr to its IP address, but apparently
it's common for clients not to do this, so we'll use their IP
@@ -1169,7 +1169,7 @@ void dhcpinform (packet, ms_nulltp)
packet -> options, options,
&global_scope, oc, MDL)) {
struct universe *u = (struct universe *)0;
-
+
if (!universe_hash_lookup (&u, universe_hash,
(const char *)d1.data, d1.len,
MDL)) {
@@ -1314,10 +1314,17 @@ void dhcpinform (packet, ms_nulltp)
packet->interface->name);
errno = 0;
- send_packet ((fallback_interface
- ? fallback_interface : packet -> interface),
- &outgoing, &raw, outgoing.packet_length,
- from, &to, (struct hardware *)0);
+ interface = (fallback_interface ? fallback_interface
+ : packet -> interface);
+ result = send_packet(interface, &outgoing, &raw,
+ outgoing.packet_length, from, &to, NULL);
+ if (result < 0) {
+ log_error ("%s:%d: Failed to send %d byte long packet over %s "
+ "interface.", MDL, outgoing.packet_length,
+ interface->name);
+ }
+
+
if (subnet)
subnet_dereference (&subnet, MDL);
}
@@ -1464,6 +1471,13 @@ void nak_lease (packet, cip)
result = send_packet(fallback_interface, packet, &raw,
outgoing.packet_length, from, &to,
NULL);
+ if (result < 0) {
+ log_error ("%s:%d: Failed to send %d byte long "
+ "packet over %s interface.", MDL,
+ outgoing.packet_length,
+ fallback_interface->name);
+ }
+
return;
}
} else {
@@ -1474,6 +1488,12 @@ void nak_lease (packet, cip)
errno = 0;
result = send_packet(packet->interface, packet, &raw,
outgoing.packet_length, from, &to, NULL);
+ if (result < 0) {
+ log_error ("%s:%d: Failed to send %d byte long packet over %s "
+ "interface.", MDL, outgoing.packet_length,
+ packet->interface->name);
+ }
+
}
void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
@@ -3164,11 +3184,16 @@ void dhcp_reply (lease)
to.sin_port = remote_port; /* For debugging. */
if (fallback_interface) {
- result = send_packet (fallback_interface,
- (struct packet *)0,
- &raw, packet_length,
- raw.siaddr, &to,
- (struct hardware *)0);
+ result = send_packet(fallback_interface, NULL, &raw,
+ packet_length, raw.siaddr, &to,
+ NULL);
+ if (result < 0) {
+ log_error ("%s:%d: Failed to send %d byte long "
+ "packet over %s interface.", MDL,
+ packet_length,
+ fallback_interface->name);
+ }
+
free_lease_state (state, MDL);
lease -> state = (struct lease_state *)0;
@@ -3197,11 +3222,16 @@ void dhcp_reply (lease)
to.sin_port = remote_port;
if (fallback_interface) {
- result = send_packet (fallback_interface,
- (struct packet *)0,
- &raw, packet_length,
- raw.siaddr, &to,
- (struct hardware *)0);
+ result = send_packet(fallback_interface, NULL, &raw,
+ packet_length, raw.siaddr, &to,
+ NULL);
+ if (result < 0) {
+ log_error("%s:%d: Failed to send %d byte long"
+ " packet over %s interface.", MDL,
+ packet_length,
+ fallback_interface->name);
+ }
+
free_lease_state (state, MDL);
lease -> state = (struct lease_state *)0;
return;
@@ -3226,10 +3256,14 @@ void dhcp_reply (lease)
memcpy (&from, state -> from.iabuf, sizeof from);
- result = send_packet (state -> ip,
- (struct packet *)0, &raw, packet_length,
- from, &to,
- unicastp ? &hto : (struct hardware *)0);
+ result = send_packet(state->ip, NULL, &raw, packet_length,
+ from, &to, unicastp ? &hto : NULL);
+ if (result < 0) {
+ log_error ("%s:%d: Failed to send %d byte long "
+ "packet over %s interface.", MDL,
+ packet_length, state->ip->name);
+ }
+
/* Free all of the entries in the option_state structure
now that we're done with them. */
diff --git a/server/dhcpd.c b/server/dhcpd.c
index 448e164..b5c28d4 100644
--- a/server/dhcpd.c
+++ b/server/dhcpd.c
@@ -3,7 +3,7 @@
DHCP Server Daemon. */
/*
- * Copyright (c) 2004-2011 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2012 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1996-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
@@ -33,7 +33,7 @@
*/
static const char copyright[] =
-"Copyright 2004-2011 Internet Systems Consortium.";
+"Copyright 2004-2012 Internet Systems Consortium.";
static const char arr [] = "All rights reserved.";
static const char message [] = "Internet Systems Consortium DHCP Server";
static const char url [] =
diff --git a/server/dhcpd.conf.5 b/server/dhcpd.conf.5
index 2da8d9e..d1d6295 100644
--- a/server/dhcpd.conf.5
+++ b/server/dhcpd.conf.5
@@ -1,6 +1,6 @@
.\" dhcpd.conf.5
.\"
-.\" Copyright (c) 2004-2011 by Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (c) 2004-2012 by Internet Systems Consortium, Inc. ("ISC")
.\" Copyright (c) 1996-2003 by Internet Software Consortium
.\"
.\" Permission to use, copy, modify, and distribute this software for any
@@ -27,7 +27,7 @@
.\" Support and other services are available for ISC products - see
.\" https://www.isc.org for more information or to learn more about ISC.
.\"
-.\" $Id: dhcpd.conf.5,v 1.106.18.7 2011-09-21 20:43:10 sar Exp $
+.\" $Id: dhcpd.conf.5,v 1.106.18.8 2012-04-02 22:51:02 sar Exp $
.\"
.TH dhcpd.conf 5
.SH NAME
@@ -1744,11 +1744,6 @@ The \fBbootp\fR flag is used to tell dhcpd whether
or not to respond to bootp queries. Bootp queries are \fBallow\fRed
by default.
.PP
-This option does not satisfy the requirement of failover peers for denying
-dynamic bootp clients. The \fBdeny dynamic bootp clients;\fR option should
-be used instead. See the ALLOW AND DENY WITHIN POOL DECLARATIONS section
-of this man page for more details.
-.PP
.B The
.I booting
.B keyword
diff --git a/server/dhcpleasequery.c b/server/dhcpleasequery.c
index 9daff89..09913c2 100644
--- a/server/dhcpleasequery.c
+++ b/server/dhcpleasequery.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2011-2012 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2006-2007,2009 by Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and distribute this software for any
@@ -454,10 +455,7 @@ dhcpleasequery(struct packet *packet, int ms_nulltp) {
(lease_duration / 8);
if (time_renewal > cur_time) {
- if (time_renewal < cur_time)
- time_renewal = 0;
- else
- time_renewal = htonl(time_renewal - cur_time);
+ time_renewal = htonl(time_renewal - cur_time);
if (!add_option(options,
DHO_DHCP_RENEWAL_TIME,
@@ -487,15 +485,8 @@ dhcpleasequery(struct packet *packet, int ms_nulltp) {
}
if (lease->ends > cur_time) {
- if (time_expiry < cur_time) {
- log_error("Impossible condition at %s:%d.",
- MDL);
-
- option_state_dereference(&options, MDL);
- lease_dereference(&lease, MDL);
- return;
- }
time_expiry = htonl(lease->ends - cur_time);
+
if (!add_option(options,
DHO_DHCP_LEASE_TIME,
&time_expiry,
diff --git a/server/dhcpv6.c b/server/dhcpv6.c
index 4538882..70f3981 100644
--- a/server/dhcpv6.c
+++ b/server/dhcpv6.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2011 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2006-2012 by Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -1092,7 +1092,8 @@ try_client_v6_prefix(struct iasubopt **pref,
return DHCP_R_INVALIDARG;
}
tmp_plen = (int) requested_pref->data[0];
- if ((tmp_plen < 3) || (tmp_plen > 128)) {
+ if ((tmp_plen < 3) || (tmp_plen > 128) ||
+ ((int)tmp_plen != pool->units)) {
return ISC_R_FAILURE;
}
memcpy(&tmp_pref, requested_pref->data + 1, sizeof(tmp_pref));
@@ -1105,9 +1106,8 @@ try_client_v6_prefix(struct iasubopt **pref,
return ISC_R_FAILURE;
}
- if (((int)tmp_plen != pool->units) ||
- !ipv6_in_pool(&tmp_pref, pool)) {
- return ISC_R_FAILURE;
+ if (!ipv6_in_pool(&tmp_pref, pool)) {
+ return ISC_R_ADDRNOTAVAIL;
}
if (prefix6_exists(pool, &tmp_pref, tmp_plen)) {
@@ -1239,7 +1239,9 @@ lease_to_client(struct data_string *reply_ret,
static struct reply_state reply;
struct option_cache *oc;
struct data_string packet_oro;
- isc_boolean_t no_resources_avail;
+#if defined (RFC3315_PRE_ERRATA_2010_08)
+ isc_boolean_t no_resources_avail = ISC_FALSE;
+#endif
/* Locate the client. */
if (shared_network_from_packet6(&reply.shared,
@@ -1297,7 +1299,7 @@ lease_to_client(struct data_string *reply_ret,
/* Process the client supplied IA's onto the reply buffer. */
reply.ia_count = 0;
oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
- no_resources_avail = ISC_FALSE;
+
for (; oc != NULL ; oc = oc->next) {
isc_result_t status;
@@ -1315,12 +1317,14 @@ lease_to_client(struct data_string *reply_ret,
(status != ISC_R_NORESOURCES))
goto exit;
+#if defined (RFC3315_PRE_ERRATA_2010_08)
/*
* If any address cannot be given to any IA, then set the
* NoAddrsAvail status code.
*/
if (reply.client_resources == 0)
no_resources_avail = ISC_TRUE;
+#endif
}
oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_TA);
for (; oc != NULL ; oc = oc->next) {
@@ -1340,12 +1344,14 @@ lease_to_client(struct data_string *reply_ret,
(status != ISC_R_NORESOURCES))
goto exit;
+#if defined (RFC3315_PRE_ERRATA_2010_08)
/*
* If any address cannot be given to any IA, then set the
* NoAddrsAvail status code.
*/
if (reply.client_resources == 0)
no_resources_avail = ISC_TRUE;
+#endif
}
/* Same for IA_PD's. */
@@ -1367,13 +1373,6 @@ lease_to_client(struct data_string *reply_ret,
if ((status != ISC_R_SUCCESS) &&
(status != ISC_R_NORESOURCES))
goto exit;
-
- /*
- * If any prefix cannot be given to any IA_PD, then
- * set the NoPrefixAvail status code.
- */
- if (reply.client_resources == 0)
- no_resources_avail = ISC_TRUE;
}
/*
@@ -1429,6 +1428,7 @@ lease_to_client(struct data_string *reply_ret,
* the server.
* Sends a Renew/Rebind if the IA is not in the Reply message.
*/
+#if defined (RFC3315_PRE_ERRATA_2010_08)
if (no_resources_avail && (reply.ia_count != 0) &&
(reply.packet->dhcpv6_msg_type == DHCPV6_SOLICIT))
{
@@ -1459,36 +1459,6 @@ lease_to_client(struct data_string *reply_ret,
reply.opt_state, reply.packet,
required_opts_NAA,
NULL);
- } else if (no_resources_avail && (reply.ia_count == 0) &&
- (reply.packet->dhcpv6_msg_type == DHCPV6_SOLICIT))
- {
- /* Set the NoPrefixAvail status code. */
- if (!set_status_code(STATUS_NoPrefixAvail,
- "No prefixes available for this "
- "interface.", reply.opt_state)) {
- log_error("lease_to_client: Unable to set "
- "NoPrefixAvail status code.");
- goto exit;
- }
-
- /* Rewind the cursor to the start. */
- reply.cursor = REPLY_OPTIONS_INDEX;
-
- /*
- * Produce an advertise that includes only:
- *
- * Status code.
- * Server DUID.
- * Client DUID.
- */
- reply.buf.reply.msg_type = DHCPV6_ADVERTISE;
- reply.cursor += store_options6((char *)reply.buf.data +
- reply.cursor,
- sizeof(reply.buf) -
- reply.cursor,
- reply.opt_state, reply.packet,
- required_opts_NAA,
- NULL);
} else {
/*
* Having stored the client's IA's, store any options that
@@ -1502,6 +1472,17 @@ lease_to_client(struct data_string *reply_ret,
required_opts_solicit,
&packet_oro);
}
+#else /* defined (RFC3315_PRE_ERRATA_2010_08) */
+ /*
+ * Having stored the client's IA's, store any options that
+ * will fit in the remaining space.
+ */
+ reply.cursor += store_options6((char *)reply.buf.data + reply.cursor,
+ sizeof(reply.buf) - reply.cursor,
+ reply.opt_state, reply.packet,
+ required_opts_solicit,
+ &packet_oro);
+#endif /* defined (RFC3315_PRE_ERRATA_2010_08) */
/* Return our reply to the caller. */
reply_ret->len = reply.cursor;
@@ -2228,13 +2209,13 @@ address_is_owned(struct reply_state *reply, struct iaddr *addr) {
log_fatal("Impossible condition at %s:%d.", MDL);
if (memcmp(addr->iabuf, reply->fixed.data, 16) == 0)
- return ISC_TRUE;
+ return (ISC_TRUE);
- return ISC_FALSE;
+ return (ISC_FALSE);
}
if ((reply->old_ia == NULL) || (reply->old_ia->num_iasubopt == 0))
- return ISC_FALSE;
+ return (ISC_FALSE);
for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
struct iasubopt *tmp;
@@ -2242,12 +2223,15 @@ address_is_owned(struct reply_state *reply, struct iaddr *addr) {
tmp = reply->old_ia->iasubopt[i];
if (memcmp(addr->iabuf, &tmp->addr, 16) == 0) {
+ if (lease6_usable(tmp) == ISC_FALSE) {
+ return (ISC_FALSE);
+ }
iasubopt_reference(&reply->lease, tmp, MDL);
- return ISC_TRUE;
+ return (ISC_TRUE);
}
}
- return ISC_FALSE;
+ return (ISC_FALSE);
}
/* Process a client-supplied IA_TA. This may append options to the tail of
@@ -2703,15 +2687,17 @@ 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_NORESOURCES;
+ isc_result_t status = ISC_R_ADDRNOTAVAIL;
struct ipv6_pool *pool;
int i;
struct data_string data_addr;
if ((reply == NULL) || (reply->shared == NULL) ||
- (reply->shared->ipv6_pools == NULL) || (addr == NULL) ||
- (reply->lease != NULL))
- return DHCP_R_INVALIDARG;
+ (addr == NULL) || (reply->lease != NULL))
+ return (DHCP_R_INVALIDARG);
+
+ if (reply->shared->ipv6_pools == NULL)
+ return (ISC_R_ADDRNOTAVAIL);
memset(&data_addr, 0, sizeof(data_addr));
data_addr.len = addr->len;
@@ -2729,7 +2715,7 @@ reply_process_try_addr(struct reply_state *reply, struct iaddr *addr) {
/* Note that this is just pedantry. There is no allocation to free. */
data_string_forget(&data_addr, MDL);
/* Return just the most recent status... */
- return status;
+ return (status);
}
/* Look around for an address to give the client. First, look through the
@@ -2769,7 +2755,8 @@ find_client_address(struct reply_state *reply) {
* Look for the best lease on the client's shared
* network.
*/
- if (candidate_shared == reply->shared) {
+ if ((candidate_shared == reply->shared) &&
+ (lease6_usable(lease) == ISC_TRUE)) {
best_lease = lease_compare(lease, best_lease);
}
}
@@ -2780,7 +2767,7 @@ find_client_address(struct reply_state *reply) {
*/
if ((best_lease == NULL) || (best_lease->state == FTS_ABANDONED)) {
status = pick_v6_address(&reply->lease, reply->shared,
- &reply->client_id);
+ &reply->ia->iaid_duid);
} else if (best_lease != NULL) {
iasubopt_reference(&reply->lease, best_lease, MDL);
status = ISC_R_SUCCESS;
@@ -3224,7 +3211,9 @@ reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia) {
if (status == ISC_R_CANCELED)
break;
- if ((status != ISC_R_SUCCESS) && (status != ISC_R_ADDRINUSE))
+ if ((status != ISC_R_SUCCESS) &&
+ (status != ISC_R_ADDRINUSE) &&
+ (status != ISC_R_ADDRNOTAVAIL))
goto cleanup;
}
@@ -3503,8 +3492,9 @@ reply_process_prefix(struct reply_state *reply, struct option_cache *pref) {
status = reply_process_try_prefix(reply, &tmp_pref);
/* Either error out or skip this prefix. */
- if ((status != ISC_R_SUCCESS) &&
- (status != ISC_R_ADDRINUSE))
+ if ((status != ISC_R_SUCCESS) &&
+ (status != ISC_R_ADDRINUSE) &&
+ (status != ISC_R_ADDRNOTAVAIL))
goto cleanup;
if (reply->lease == NULL) {
@@ -3652,14 +3642,14 @@ prefix_is_owned(struct reply_state *reply, struct iaddrcidrnet *pref) {
if ((pref->bits == l->cidrnet.bits) &&
(memcmp(pref->lo_addr.iabuf,
l->cidrnet.lo_addr.iabuf, 16) == 0))
- return ISC_TRUE;
+ return (ISC_TRUE);
}
- return ISC_FALSE;
+ return (ISC_FALSE);
}
if ((reply->old_ia == NULL) ||
(reply->old_ia->num_iasubopt == 0))
- return ISC_FALSE;
+ return (ISC_FALSE);
for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
struct iasubopt *tmp;
@@ -3667,13 +3657,16 @@ prefix_is_owned(struct reply_state *reply, struct iaddrcidrnet *pref) {
tmp = reply->old_ia->iasubopt[i];
if ((pref->bits == (int) tmp->plen) &&
- memcmp(pref->lo_addr.iabuf, &tmp->addr, 16) == 0) {
+ (memcmp(pref->lo_addr.iabuf, &tmp->addr, 16) == 0)) {
+ if (lease6_usable(tmp) == ISC_FALSE) {
+ return (ISC_FALSE);
+ }
iasubopt_reference(&reply->lease, tmp, MDL);
- return ISC_TRUE;
+ return (ISC_TRUE);
}
}
- return ISC_FALSE;
+ return (ISC_FALSE);
}
/*
@@ -3683,21 +3676,23 @@ 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_NORESOURCES;
+ isc_result_t status = ISC_R_ADDRNOTAVAIL;
struct ipv6_pool *pool;
int i;
struct data_string data_pref;
if ((reply == NULL) || (reply->shared == NULL) ||
- (reply->shared->ipv6_pools == NULL) || (pref == NULL) ||
- (reply->lease != NULL))
- return DHCP_R_INVALIDARG;
+ (pref == NULL) || (reply->lease != NULL))
+ return (DHCP_R_INVALIDARG);
+
+ if (reply->shared->ipv6_pools == NULL)
+ return (ISC_R_ADDRNOTAVAIL);
memset(&data_pref, 0, sizeof(data_pref));
data_pref.len = 17;
if (!buffer_allocate(&data_pref.buffer, data_pref.len, MDL)) {
log_error("reply_process_try_prefix: out of memory.");
- return ISC_R_NOMEMORY;
+ return (ISC_R_NOMEMORY);
}
data_pref.data = data_pref.buffer->data;
data_pref.buffer->data[0] = (u_int8_t) pref->bits;
@@ -3716,7 +3711,7 @@ reply_process_try_prefix(struct reply_state *reply,
data_string_forget(&data_pref, MDL);
/* Return just the most recent status... */
- return status;
+ return (status);
}
/* Look around for a prefix to give the client. First, look through the old
@@ -3767,8 +3762,9 @@ find_client_prefix(struct reply_state *reply) {
* if it is scoped in a pool under the client's shared
* network.
*/
- if (candidate_shared == NULL ||
- candidate_shared == reply->shared) {
+ if (((candidate_shared == NULL) ||
+ (candidate_shared == reply->shared)) &&
+ (lease6_usable(prefix) == ISC_TRUE)) {
best_prefix = prefix_compare(reply, prefix,
best_prefix);
}
@@ -4617,7 +4613,6 @@ iterate_over_ia_na(struct data_string *reply_ret,
struct option_state *host_opt_state;
struct data_string iaaddr;
struct data_string fixed_addr;
- int iaaddr_is_found;
char reply_data[65536];
struct dhcpv6_packet *reply = (struct dhcpv6_packet *)reply_data;
int reply_ofs = (int)(offsetof(struct dhcpv6_packet, options));
@@ -4724,7 +4719,6 @@ iterate_over_ia_na(struct data_string *reply_ret,
*/
for (ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
ia != NULL; ia = ia->next) {
- iaaddr_is_found = 0;
if (!get_encapsulated_IA_state(&cli_enc_opt_state,
&cli_enc_opt_data,
@@ -5136,7 +5130,6 @@ iterate_over_ia_pd(struct data_string *reply_ret,
struct host_decl *host;
struct option_state *host_opt_state;
struct data_string iaprefix;
- int iaprefix_is_found;
char reply_data[65536];
int reply_ofs;
struct iasubopt *prefix;
@@ -5203,7 +5196,6 @@ iterate_over_ia_pd(struct data_string *reply_ret,
*/
for (ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
ia != NULL; ia = ia->next) {
- iaprefix_is_found = 0;
if (!get_encapsulated_IA_state(&cli_enc_opt_state,
&cli_enc_opt_data,
@@ -5531,6 +5523,7 @@ dhcpv6_relay_forw(struct data_string *reply_ret, struct packet *packet) {
msg_type = enc_opt_data.data[0];
if ((msg_type == DHCPV6_RELAY_FORW) ||
(msg_type == DHCPV6_RELAY_REPL)) {
+ int relaylen = (int)(offsetof(struct dhcpv6_relay_packet, options));
relay = (struct dhcpv6_relay_packet *)enc_opt_data.data;
enc_packet->dhcpv6_msg_type = relay->msg_type;
@@ -5543,13 +5536,14 @@ dhcpv6_relay_forw(struct data_string *reply_ret, struct packet *packet) {
if (!parse_option_buffer(enc_packet->options,
relay->options,
- enc_opt_data.len-sizeof(*relay),
+ enc_opt_data.len - relaylen,
&dhcpv6_universe)) {
/* no logging here, as parse_option_buffer() logs all
cases where it fails */
goto exit;
}
} else {
+ int msglen = (int)(offsetof(struct dhcpv6_packet, options));
msg = (struct dhcpv6_packet *)enc_opt_data.data;
enc_packet->dhcpv6_msg_type = msg->msg_type;
@@ -5560,7 +5554,7 @@ dhcpv6_relay_forw(struct data_string *reply_ret, struct packet *packet) {
if (!parse_option_buffer(enc_packet->options,
msg->options,
- enc_opt_data.len-sizeof(*msg),
+ enc_opt_data.len - msglen,
&dhcpv6_universe)) {
/* no logging here, as parse_option_buffer() logs all
cases where it fails */
diff --git a/server/failover.c b/server/failover.c
index 97e7d73..45e6b62 100644
--- a/server/failover.c
+++ b/server/failover.c
@@ -3,7 +3,7 @@
Failover protocol support code... */
/*
- * Copyright (c) 2004-2011 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2012 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1999-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
@@ -32,6 +32,7 @@
* ``http://www.nominum.com''.
*/
+#include "cdefs.h"
#include "dhcpd.h"
#include <omapip/omapip_p.h>
@@ -2412,7 +2413,8 @@ dhcp_failover_pool_dobalance(dhcp_failover_state_t *state,
struct shared_network *s;
struct pool *p;
binding_state_t peer_lease_state;
- binding_state_t my_lease_state;
+ /* binding_state_t my_lease_state; */
+ /* XXX Why is this my_lease_state never used? */
struct lease **lq;
int (*log_func)(const char *, ...);
const char *result, *reqlog;
@@ -2436,12 +2438,12 @@ dhcp_failover_pool_dobalance(dhcp_failover_state_t *state,
if (p->failover_peer->i_am == primary) {
lts = (p->free_leases - p->backup_leases) / 2;
peer_lease_state = FTS_BACKUP;
- my_lease_state = FTS_FREE;
+ /* my_lease_state = FTS_FREE; */
lq = &p->free;
} else {
lts = (p->backup_leases - p->free_leases) / 2;
peer_lease_state = FTS_FREE;
- my_lease_state = FTS_BACKUP;
+ /* my_lease_state = FTS_BACKUP; */
lq = &p->backup;
}
@@ -3257,13 +3259,13 @@ isc_result_t dhcp_failover_state_stuff (omapi_object_t *c,
omapi_object_t *id,
omapi_object_t *h)
{
+ /* In this function c should be a (omapi_connection_object_t *) */
+
dhcp_failover_state_t *s;
- omapi_connection_object_t *conn;
isc_result_t status;
if (c -> type != omapi_type_connection)
return DHCP_R_INVALIDARG;
- conn = (omapi_connection_object_t *)c;
if (h -> type != dhcp_type_failover_state)
return DHCP_R_INVALIDARG;
@@ -4306,6 +4308,8 @@ void dhcp_failover_send_contact (void *vstate)
if (obufix) {
log_debug ("%s", obuf);
}
+#else
+ IGNORE_UNUSED(status);
#endif
return;
}
@@ -4354,6 +4358,8 @@ isc_result_t dhcp_failover_send_state (dhcp_failover_state_t *state)
if (obufix) {
log_debug ("%s", obuf);
}
+#else
+ IGNORE_UNUSED(status);
#endif
return ISC_R_SUCCESS;
}
@@ -4490,7 +4496,6 @@ isc_result_t dhcp_failover_send_disconnect (omapi_object_t *l,
const char *message)
{
dhcp_failover_link_t *link;
- dhcp_failover_state_t *state;
isc_result_t status;
#if defined (DEBUG_FAILOVER_MESSAGES)
char obuf [64];
@@ -4505,7 +4510,6 @@ isc_result_t dhcp_failover_send_disconnect (omapi_object_t *l,
if (!l || l -> type != dhcp_type_failover_link)
return DHCP_R_INVALIDARG;
link = (dhcp_failover_link_t *)l;
- state = link -> state_object;
if (!l -> outer || l -> outer -> type != omapi_type_connection)
return DHCP_R_INVALIDARG;
@@ -5218,7 +5222,7 @@ isc_result_t dhcp_failover_process_bind_update (dhcp_failover_state_t *state,
*/
if (msg->binding_status == FTS_ACTIVE &&
(chaddr_changed || ident_changed)) {
- ddns_removals(lease, NULL, NULL);
+ (void) ddns_removals(lease, NULL, NULL, ISC_FALSE);
if (lease->scope != NULL)
binding_scope_dereference(&lease->scope, MDL);
diff --git a/server/mdb.c b/server/mdb.c
index c5bf73e..5a3052a 100644
--- a/server/mdb.c
+++ b/server/mdb.c
@@ -3,7 +3,7 @@
Server-specific in-memory database support. */
/*
- * Copyright (c) 2004-2011 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2012 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1996-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
@@ -1445,7 +1445,7 @@ void make_binding_state_transition (struct lease *lease)
lease -> binding_state == FTS_ACTIVE &&
lease -> next_binding_state != FTS_RELEASED))) {
#if defined (NSUPDATE)
- ddns_removals(lease, NULL, NULL);
+ (void) ddns_removals(lease, NULL, NULL, ISC_TRUE);
#endif
if (lease -> on_expiry) {
execute_statements ((struct binding_value **)0,
@@ -1511,7 +1511,7 @@ void make_binding_state_transition (struct lease *lease)
* release message. This is not true of expiry, where the
* peer may have extended the lease.
*/
- ddns_removals(lease, NULL, NULL);
+ (void) ddns_removals(lease, NULL, NULL, ISC_TRUE);
#endif
if (lease -> on_release) {
execute_statements ((struct binding_value **)0,
@@ -1680,7 +1680,7 @@ void release_lease (lease, packet)
/* If there are statements to execute when the lease is
released, execute them. */
#if defined (NSUPDATE)
- ddns_removals(lease, NULL, NULL);
+ (void) ddns_removals(lease, NULL, NULL, ISC_FALSE);
#endif
if (lease -> on_release) {
execute_statements ((struct binding_value **)0,
@@ -1754,7 +1754,7 @@ void abandon_lease (lease, message)
{
struct lease *lt = (struct lease *)0;
#if defined (NSUPDATE)
- ddns_removals(lease, NULL, NULL);
+ (void) ddns_removals(lease, NULL, NULL, ISC_FALSE);
#endif
if (!lease_copy (&lt, lease, MDL))
@@ -1778,6 +1778,14 @@ void abandon_lease (lease, message)
lease_dereference (&lt, MDL);
}
+#if 0
+/*
+ * This doesn't appear to be in use for anything anymore.
+ * I'm ifdeffing it now and if there are no complaints in
+ * the future it will be removed.
+ * SAR
+ */
+
/* Abandon the specified lease (set its timeout to infinity and its
particulars to zero, and re-hash it as appropriate. */
@@ -1786,7 +1794,7 @@ void dissociate_lease (lease)
{
struct lease *lt = (struct lease *)0;
#if defined (NSUPDATE)
- ddns_removals(lease, NULL, NULL);
+ (void) ddns_removals(lease, NULL, NULL, ISC_FALSE);
#endif
if (!lease_copy (&lt, lease, MDL))
@@ -1811,6 +1819,7 @@ void dissociate_lease (lease)
supersede_lease (lease, lt, 1, 1, 1);
lease_dereference (&lt, MDL);
}
+#endif
/* Timer called when a lease in a particular pool expires. */
void pool_timer (vpool)
@@ -1961,9 +1970,17 @@ int find_lease_by_hw_addr (struct lease **lp,
const char *file, int line)
{
if (hwlen == 0)
- return 0;
- return lease_id_hash_lookup(lp, lease_hw_addr_hash, hwaddr, hwlen,
- file, line);
+ return (0);
+
+ /*
+ * If it's an infiniband address don't bother
+ * as we don't have a useful address to hash.
+ */
+ if ((hwlen == 1) && (hwaddr[0] == HTYPE_INFINIBAND))
+ return (0);
+
+ return (lease_id_hash_lookup(lp, lease_hw_addr_hash, hwaddr, hwlen,
+ file, line));
}
/* If the lease is preferred over the candidate, return truth. The
@@ -2128,6 +2145,8 @@ void uid_hash_delete (lease)
}
/* Add the specified lease to the hardware address hash. */
+/* We don't add leases with infiniband addresses to the
+ * hash as there isn't any address to hash on. */
void
hw_hash_add(struct lease *lease)
@@ -2137,6 +2156,14 @@ hw_hash_add(struct lease *lease)
struct lease *prev = NULL;
struct lease *next = NULL;
+ /*
+ * If it's an infiniband address don't bother
+ * as we don't have a useful address to hash.
+ */
+ if ((lease->hardware_addr.hlen == 1) &&
+ (lease->hardware_addr.hbuf[0] == HTYPE_INFINIBAND))
+ return;
+
/* If it's not in the hash, just add it. */
if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
lease -> hardware_addr.hlen, MDL))
@@ -2208,6 +2235,14 @@ void hw_hash_delete (lease)
struct lease *head = (struct lease *)0;
struct lease *next = (struct lease *)0;
+ /*
+ * If it's an infiniband address don't bother
+ * as we don't have a useful address to hash.
+ */
+ if ((lease->hardware_addr.hlen == 1) &&
+ (lease->hardware_addr.hbuf[0] == HTYPE_INFINIBAND))
+ return;
+
/* If it's not in the hash, we have no work to do. */
if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
lease -> hardware_addr.hlen, MDL)) {
diff --git a/server/mdb6.c b/server/mdb6.c
index 9d410f5..e6d0a1a 100644
--- a/server/mdb6.c
+++ b/server/mdb6.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2011 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2007-2012 by Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -14,9 +14,68 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* TODO: assert() */
-/* TODO: simplify functions, as pool is now in iaaddr */
+/*!
+ * \todo assert()
+ * \todo simplify functions, as pool is now in iaaddr
+ */
+/*! \file server/mdb6.c
+ *
+ * \page ipv6structures IPv6 Structures Overview
+ *
+ * A brief description of the IPv6 structures as reverse engineered.
+ *
+ * There are three major data strucutes involved in the database:
+ * ipv6_pool - this contains information about a pool of addresses or prefixes
+ * that the server is using. This includes a hash table that
+ * tracks the active items and a pair of heap tables one for
+ * active items and one for non-active items. The heap tables
+ * are used to determine the next items to be modified due to
+ * timing events (expire mostly).
+ * ia_xx - this contains information about a single IA from a request
+ * normally it will contain one pointer to a lease for the client
+ * but it may contain more in some circumstances. There are 3
+ * hash tables to aid in accessing these one each for NA, TA and PD
+ * iasubopt - the v6 lease structure. These are creaeted dynamically when
+ * a client asks for something and will eventually be destroyed
+ * if the client doesn't re-ask for that item. A lease has space
+ * for backpointers to the IA and to the pool to which it belongs.
+ * The pool backpointer is always filled, the IA pointer may not be
+ *
+ * In normal use we then have something like this:
+ *
+ * ia hash tables
+ * ia_na_active +----------------+
+ * ia_ta_active +------------+ | pool |
+ * ia_pd_active | iasubopt |<--| active hash |
+ * +-----------------+ | aka lease |<--| active heap |
+ * | ia_xx | | pool ptr |-->| |
+ * | iasubopt array |<---| iaptr |<--| inactive heap |
+ * | lease ptr |--->| | | |
+ * +-----------------+ +------------+ +----------------+
+ *
+ * For the pool either the inactive heap will have a pointer
+ * or both the active heap and the active hash will have pointers.
+ *
+ * I think there are several major items to notice. The first is
+ * that as a lease moves around it will be added to and removed
+ * from the address hash table in the pool and between the active
+ * and inactive hash tables. The hash table and the active heap
+ * are used when the lease is either active or abandoned. The
+ * inactive heap is used for all other states. In particular a
+ * lease that has expired or been released will be cleaned
+ * (DDNS removal etc) and then moved to the inactive heap. After
+ * some time period (currently 1 hour) it will be freed.
+ *
+ * The second is that when a client requests specific addresses,
+ * either because it previously owned them or if the server supplied
+ * them as part of a solicit, the server will try to lookup the ia_xx
+ * associated with the client and find the addresses there. If it
+ * does find appropriate leases it moves them from the old IA to
+ * a new IA and eventually replaces the old IA with the new IA
+ * in the IA hash tables.
+ *
+ */
#include "config.h"
#include <sys/types.h>
@@ -808,15 +867,14 @@ create_lease6(struct ipv6_pool *pool, struct iasubopt **addr,
}
/*
- * Avoid reserved interface IDs.
- * (cf. draft-krishnan-ipv6-reserved-iids-02.txt)
+ * Avoid reserved interface IDs. (cf. RFC 5453)
*/
reserved_iid = ISC_FALSE;
- if (memcmp(&tmp.s6_addr[8], &rtany, 8) == 0) {
+ if (memcmp(&tmp.s6_addr[8], &rtany.s6_addr[8], 8) == 0) {
reserved_iid = ISC_TRUE;
}
if (!reserved_iid &&
- (memcmp(&tmp.s6_addr[8], &resany, 7) == 0) &&
+ (memcmp(&tmp.s6_addr[8], &resany.s6_addr[8], 7) == 0) &&
((tmp.s6_addr[15] & 0x80) == 0x80)) {
reserved_iid = ISC_TRUE;
}
@@ -875,6 +933,145 @@ create_lease6(struct ipv6_pool *pool, struct iasubopt **addr,
return result;
}
+
+/*! \file server/mdb6.c
+ *
+ * \brief Cleans up leases when reading from a lease file
+ *
+ * This function is only expected to be run when reading leases in from a file.
+ * It checks to see if a lease already exists for the new leases's address.
+ * We don't add expired leases to the structures when reading a lease file
+ * which limits what can happen. We have two variables the owners of the leases
+ * being the same or different and the new lease being active or non-active:
+ * Owners active
+ * same no remove old lease and its connections
+ * same yes nothing to do, other code will update the structures.
+ * diff no nothing to do
+ * diff yes this combination shouldn't happen, we should only have a
+ * single active lease per address at a time and that lease
+ * should move to non-active before any other lease can
+ * become active for that address.
+ * Currently we delete the previous lease and pass an error
+ * to the caller who should log an error.
+ *
+ * When we remove a lease we remove it from the hash table and active heap
+ * (remember only active leases are in the structures at this time) for the
+ * pool, and from the IA's array. If, after we've removed the pointer from
+ * IA's array to the lease, the IA has no more pointers we remove it from
+ * the appropriate hash table as well.
+ *
+ * \param[in] ia_table = the hash table for the IA
+ * \param[in] pool = the pool to update
+ * \param[in] lease = the new lease we want to add
+ * \param[in] ia = the new ia we are building
+ *
+ * \return
+ * ISC_R_SUCCESS = the incoming lease and any previous lease were in
+ * an expected state - one of the first 3 options above.
+ * If necessary the old lease was removed.
+ * ISC_R_FAILURE = there is already an active lease for the address in
+ * the incoming lease. This shouldn't happen if it does
+ * flag an error for the caller to log.
+ */
+
+isc_result_t
+cleanup_lease6(ia_hash_t *ia_table,
+ struct ipv6_pool *pool,
+ struct iasubopt *lease,
+ struct ia_xx *ia) {
+
+ struct iasubopt *test_iasubopt, *tmp_iasubopt;
+ struct ia_xx *old_ia;
+ isc_result_t status = ISC_R_SUCCESS;
+
+ test_iasubopt = NULL;
+ old_ia = NULL;
+
+ /*
+ * Look up the address - if we don't find a lease
+ * we don't need to do anything.
+ */
+ if (iasubopt_hash_lookup(&test_iasubopt, pool->leases,
+ &lease->addr, sizeof(lease->addr),
+ MDL) == 0) {
+ return (ISC_R_SUCCESS);
+ }
+
+ if (test_iasubopt->ia == NULL) {
+ /* no old ia, no work to do */
+ iasubopt_dereference(&test_iasubopt, MDL);
+ return (status);
+ }
+
+ ia_reference(&old_ia, test_iasubopt->ia, MDL);
+
+ if ((old_ia->iaid_duid.len == ia->iaid_duid.len) &&
+ (memcmp((unsigned char *)ia->iaid_duid.data,
+ (unsigned char *)old_ia->iaid_duid.data,
+ ia->iaid_duid.len) == 0)) {
+ /* same IA */
+ if ((lease->state == FTS_ACTIVE) ||
+ (lease->state == FTS_ABANDONED)) {
+ /* still active, no need to delete */
+ goto cleanup;
+ }
+ } else {
+ /* different IA */
+ if ((lease->state != FTS_ACTIVE) &&
+ (lease->state != FTS_ABANDONED)) {
+ /* new lease isn't active, no work */
+ goto cleanup;
+ }
+
+ /*
+ * We appear to have two active leases, this shouldn't happen.
+ * Before a second lease can be set to active the first lease
+ * should be set to inactive (released, expired etc). For now
+ * delete the previous lease and indicate a failure to the
+ * caller so it can generate a warning.
+ * In the future we may try and determine which is the better
+ * lease to keep.
+ */
+
+ status = ISC_R_FAILURE;
+ }
+
+ /*
+ * Remove the old lease from the active heap and from the hash table
+ * then remove the lease from the IA and clean up the IA if necessary.
+ */
+ isc_heap_delete(pool->active_timeouts, test_iasubopt->heap_index);
+ pool->num_active--;
+
+ iasubopt_hash_delete(pool->leases, &test_iasubopt->addr,
+ sizeof(test_iasubopt->addr), MDL);
+ ia_remove_iasubopt(old_ia, test_iasubopt, MDL);
+ if (old_ia->num_iasubopt <= 0) {
+ ia_hash_delete(ia_table,
+ (unsigned char *)old_ia->iaid_duid.data,
+ old_ia->iaid_duid.len, MDL);
+ }
+
+ /*
+ * We derefenrece the subopt here as we've just removed it from
+ * the hash table in the pool. We need to make a copy as we
+ * need to derefernece it again later.
+ */
+ tmp_iasubopt = test_iasubopt;
+ iasubopt_dereference(&tmp_iasubopt, MDL);
+
+ cleanup:
+ ia_dereference(&old_ia, MDL);
+
+ /*
+ * Clean up the reference, this is in addition to the deference
+ * above after removing the entry from the hash table
+ */
+ iasubopt_dereference(&test_iasubopt, MDL);
+
+ return (status);
+}
+
/*
* Put a lease in the pool directly. This is intended to be used when
* loading leases from the file.
@@ -985,6 +1182,38 @@ lease6_exists(const struct ipv6_pool *pool, const struct in6_addr *addr) {
}
}
+/*!
+ *
+ * \brief Check if address is available to a lease
+ *
+ * Determine if the address in the lease is available to that
+ * lease. Either the address isn't in use or it is in use
+ * but by that lease.
+ *
+ * \param[in] lease = lease to check
+ *
+ * \return
+ * ISC_TRUE = The lease is allowed to use that address
+ * ISC_FALSE = The lease isn't allowed to use that address
+ */
+isc_boolean_t
+lease6_usable(struct iasubopt *lease) {
+ struct iasubopt *test_iaaddr;
+ isc_boolean_t status = ISC_TRUE;
+
+ test_iaaddr = NULL;
+ if (iasubopt_hash_lookup(&test_iaaddr, lease->ipv6_pool->leases,
+ (void *)&lease->addr,
+ sizeof(lease->addr), MDL)) {
+ if (test_iaaddr != lease) {
+ status = ISC_FALSE;
+ }
+ iasubopt_dereference(&test_iaaddr, MDL);
+ }
+
+ return (status);
+}
+
/*
* Put the lease on our active pool.
*/
@@ -1058,7 +1287,7 @@ move_lease_to_inactive(struct ipv6_pool *pool, struct iasubopt *lease,
#if defined (NSUPDATE)
/* Process events upon expiration. */
if (pool->pool_type != D6O_IA_PD) {
- ddns_removals(NULL, lease, NULL);
+ (void) ddns_removals(NULL, lease, NULL, ISC_FALSE);
}
#endif
@@ -1466,6 +1695,11 @@ lease_timeout_support(void *vpool) {
* Note that if there are no leases in the pool,
* expire_lease6() will return ISC_R_SUCCESS with
* a NULL lease.
+ *
+ * expire_lease6() will call move_lease_to_inactive() which
+ * calls ddns_removals() do we want that on the standard
+ * expiration timer or a special 'depref' timer? Original
+ * query from DH, moved here by SAR.
*/
lease = NULL;
if (expire_lease6(&lease, pool, cur_time) != ISC_R_SUCCESS) {
@@ -1475,18 +1709,6 @@ lease_timeout_support(void *vpool) {
break;
}
- /* Look to see if there were ddns updates, and if
- * so, drop them.
- *
- * DH: Do we want to do this on a special 'depref'
- * timer rather than expiration timer?
- */
-#if defined (NSUPDATE)
- if (pool->pool_type != D6O_IA_PD) {
- ddns_removals(NULL, lease, NULL);
- }
-#endif
-
write_ia(lease->ia);
iasubopt_dereference(&lease, MDL);
diff --git a/server/omapi.c b/server/omapi.c
index bbddaf9..ca03cd1 100644
--- a/server/omapi.c
+++ b/server/omapi.c
@@ -3,7 +3,7 @@
OMAPI object interfaces for the DHCP server. */
/*
- * Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2010,2012 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1999-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
@@ -480,12 +480,11 @@ isc_result_t dhcp_lease_destroy (omapi_object_t *h, const char *file, int line)
isc_result_t dhcp_lease_signal_handler (omapi_object_t *h,
const char *name, va_list ap)
{
- struct lease *lease;
+ /* h should point to (struct lease *) */
isc_result_t status;
if (h -> type != dhcp_type_lease)
return DHCP_R_INVALIDARG;
- lease = (struct lease *)h;
if (!strcmp (name, "updated"))
return ISC_R_SUCCESS;
@@ -985,20 +984,21 @@ isc_result_t dhcp_host_set_value (omapi_object_t *h,
if (!omapi_ds_strcmp (name, "hardware-type")) {
int type;
- if (value && (value -> type == omapi_datatype_data &&
- value -> u.buffer.len == sizeof type)) {
- if (value -> u.buffer.len > sizeof type)
- return DHCP_R_INVALIDARG;
- memcpy (&type,
- value -> u.buffer.value,
- value -> u.buffer.len);
- type = ntohl (type);
- } else if (value -> type == omapi_datatype_int)
- type = value -> u.integer;
+ if ((value != NULL) &&
+ ((value->type == omapi_datatype_data) &&
+ (value->u.buffer.len == sizeof(type)))) {
+ if (value->u.buffer.len > sizeof(type))
+ return (DHCP_R_INVALIDARG);
+ memcpy(&type, value->u.buffer.value,
+ value->u.buffer.len);
+ type = ntohl(type);
+ } else if ((value != NULL) &&
+ (value->type == omapi_datatype_int))
+ type = value->u.integer;
else
- return DHCP_R_INVALIDARG;
- host -> interface.hbuf [0] = type;
- return ISC_R_SUCCESS;
+ return (DHCP_R_INVALIDARG);
+ host->interface.hbuf[0] = type;
+ return (ISC_R_SUCCESS);
}
if (!omapi_ds_strcmp (name, "dhcp-client-identifier")) {
@@ -1175,14 +1175,13 @@ isc_result_t dhcp_host_get_value (omapi_object_t *h, omapi_object_t *id,
isc_result_t dhcp_host_destroy (omapi_object_t *h, const char *file, int line)
{
- struct host_decl *host;
if (h -> type != dhcp_type_host)
return DHCP_R_INVALIDARG;
- host = (struct host_decl *)h;
#if defined (DEBUG_MEMORY_LEAKAGE) || \
defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
+ struct host_decl *host = (struct host_decl *)h;
if (host -> n_ipaddr)
host_dereference (&host -> n_ipaddr, file, line);
if (host -> n_dynamic)
@@ -1388,7 +1387,7 @@ isc_result_t dhcp_host_lookup (omapi_object_t **lp,
tv -> value -> u.buffer.value,
tv -> value -> u.buffer.len, MDL);
omapi_value_dereference (&tv, MDL);
-
+
if (*lp && *lp != (omapi_object_t *)host) {
omapi_object_dereference (lp, MDL);
if (host)
@@ -1594,12 +1593,11 @@ isc_result_t dhcp_pool_set_value (omapi_object_t *h,
omapi_data_string_t *name,
omapi_typed_data_t *value)
{
- struct pool *pool;
+ /* h should point to (struct pool *) */
isc_result_t status;
if (h -> type != dhcp_type_pool)
return DHCP_R_INVALIDARG;
- pool = (struct pool *)h;
/* No values to set yet. */
@@ -1619,12 +1617,11 @@ isc_result_t dhcp_pool_get_value (omapi_object_t *h, omapi_object_t *id,
omapi_data_string_t *name,
omapi_value_t **value)
{
- struct pool *pool;
+ /* h should point to (struct pool *) */
isc_result_t status;
if (h -> type != dhcp_type_pool)
return DHCP_R_INVALIDARG;
- pool = (struct pool *)h;
/* No values to get yet. */
@@ -1640,7 +1637,6 @@ isc_result_t dhcp_pool_get_value (omapi_object_t *h, omapi_object_t *id,
isc_result_t dhcp_pool_destroy (omapi_object_t *h, const char *file, int line)
{
- struct pool *pool;
#if defined (DEBUG_MEMORY_LEAKAGE) || \
defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
struct permit *pc, *pn;
@@ -1648,10 +1644,10 @@ isc_result_t dhcp_pool_destroy (omapi_object_t *h, const char *file, int line)
if (h -> type != dhcp_type_pool)
return DHCP_R_INVALIDARG;
- pool = (struct pool *)h;
#if defined (DEBUG_MEMORY_LEAKAGE) || \
defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
+ struct pool *pool = (struct pool *)h;
if (pool -> next)
pool_dereference (&pool -> next, file, line);
if (pool -> group)
@@ -1692,13 +1688,12 @@ isc_result_t dhcp_pool_destroy (omapi_object_t *h, const char *file, int line)
isc_result_t dhcp_pool_signal_handler (omapi_object_t *h,
const char *name, va_list ap)
{
- struct pool *pool;
+ /* h should point to (struct pool *) */
isc_result_t status;
int updatep = 0;
if (h -> type != dhcp_type_pool)
return DHCP_R_INVALIDARG;
- pool = (struct pool *)h;
/* Can't write pools yet. */
@@ -1718,12 +1713,11 @@ isc_result_t dhcp_pool_stuff_values (omapi_object_t *c,
omapi_object_t *id,
omapi_object_t *h)
{
- struct pool *pool;
+ /* h should point to (struct pool *) */
isc_result_t status;
if (h -> type != dhcp_type_pool)
return DHCP_R_INVALIDARG;
- pool = (struct pool *)h;
/* Can't stuff pool values yet. */
@@ -1951,14 +1945,13 @@ isc_result_t dhcp_class_get_value (omapi_object_t *h, omapi_object_t *id,
isc_result_t dhcp_class_destroy (omapi_object_t *h, const char *file, int line)
{
- struct class *class;
if (h -> type != dhcp_type_class && h -> type != dhcp_type_subclass)
return DHCP_R_INVALIDARG;
- class = (struct class *)h;
#if defined (DEBUG_MEMORY_LEAKAGE) || \
defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
+ struct class *class = (struct class *)h;
if (class -> nic)
class_dereference (&class -> nic, file, line);
if (class -> superclass)
@@ -2065,7 +2058,7 @@ class_signal_handler(omapi_object_t *h,
if (updatep)
return ISC_R_SUCCESS;
-
+
return ISC_R_NOTFOUND;
}
@@ -2083,12 +2076,11 @@ isc_result_t dhcp_class_stuff_values (omapi_object_t *c,
omapi_object_t *id,
omapi_object_t *h)
{
- struct class *class;
+ /* h should point to (struct class *) */
isc_result_t status;
if (h -> type != dhcp_type_class)
return DHCP_R_INVALIDARG;
- class = (struct class *)h;
/* Can't stuff class values yet. */