diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/bootp.c | 59 | ||||
-rw-r--r-- | server/confpars.c | 171 | ||||
-rw-r--r-- | server/db.c | 8 | ||||
-rw-r--r-- | server/ddns.c | 230 | ||||
-rw-r--r-- | server/dhcp.c | 78 | ||||
-rw-r--r-- | server/dhcpd.c | 4 | ||||
-rw-r--r-- | server/dhcpd.conf.5 | 9 | ||||
-rw-r--r-- | server/dhcpleasequery.c | 15 | ||||
-rw-r--r-- | server/dhcpv6.c | 152 | ||||
-rw-r--r-- | server/failover.c | 22 | ||||
-rw-r--r-- | server/mdb.c | 53 | ||||
-rw-r--r-- | server/mdb6.c | 262 | ||||
-rw-r--r-- | server/omapi.c | 60 |
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 (<, lease, MDL)) @@ -1778,6 +1778,14 @@ void abandon_lease (lease, message) lease_dereference (<, 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 (<, lease, MDL)) @@ -1811,6 +1819,7 @@ void dissociate_lease (lease) supersede_lease (lease, lt, 1, 1, 1); lease_dereference (<, 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. */ |