From: Tomek Mrugalski Date: Fri, 4 Oct 2013 18:57:29 +0000 (+0200) Subject: [3153] Support for PD in Release implemented X-Git-Tag: bind10-1.2.0beta1-release~189^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4da14c5ca0e659263f2abd8bcee8a79ad79e3722;p=thirdparty%2Fkea.git [3153] Support for PD in Release implemented --- diff --git a/src/bin/dhcp6/dhcp6_messages.mes b/src/bin/dhcp6/dhcp6_messages.mes index 9ca8243578..4f8753ae6c 100644 --- a/src/bin/dhcp6/dhcp6_messages.mes +++ b/src/bin/dhcp6/dhcp6_messages.mes @@ -132,7 +132,15 @@ client requested renewal of multiples leases (by sending multiple IA options), the server will skip the renewal of the one in question and will proceed with other renewals as usual. -% DHCP6_HOOK_LEASE6_RELEASE_SKIP DHCPv6 lease was not released because a callout set the skip flag. +% DHCP6_HOOK_LEASE6_RELEASE_NA_SKIP DHCPv6 address lease was not released because a callout set the skip flag. +This debug message is printed when a callout installed on lease6_release +hook point set the skip flag. For this particular hook point, the +setting of the flag by a callout instructs the server to not release +a lease. If client requested release of multiples leases (by sending +multiple IA options), the server will retains this particular lease and +will proceed with other renewals as usual. + +% DHCP6_HOOK_LEASE6_RELEASE_PD_SKIP DHCPv6 prefix lease was not released because a callout set the skip flag. This debug message is printed when a callout installed on lease6_release hook point set the skip flag. For this particular hook point, the setting of the flag by a callout instructs the server to not release @@ -209,13 +217,20 @@ This message indicates that the server failed to grant (in response to received REQUEST) a prefix lease for a given client. There may be many reasons for such failure. Each specific failure is logged in a separate log entry. -% DHCP6_LEASE_WITHOUT_DUID lease for address %1 does not have a DUID +% DHCP6_LEASE_NA_WITHOUT_DUID address lease for address %1 does not have a DUID This error message indicates a database consistency failure. The lease database has an entry indicating that the given address is in use, but the lease does not contain any client identification. This is most likely due to a software error: please raise a bug report. As a temporary workaround, manually remove the lease entry from the database. +% DHCP6_LEASE_PD_WITHOUT_DUID prefix lease for address %1 does not have a DUID +This error message indicates a database consistency failure. The lease +database has an entry indicating that the given prefix is in use, +but the lease does not contain any client identification. This is most +likely due to a software error: please raise a bug report. As a temporary +workaround, manually remove the lease entry from the database. + % DHCP6_NOT_RUNNING IPv6 DHCP server is not running A warning message is issued when an attempt is made to shut down the IPv6 DHCP server but it is not running. @@ -312,31 +327,56 @@ as a hint for possible requested prefix. % DHCP6_QUERY_DATA received packet length %1, data length %2, data is %3 A debug message listing the data received from the client or relay. -% DHCP6_RELEASE address %1 belonging to client duid=%2, iaid=%3 was released properly. +% DHCP6_RELEASE_NA address %1 belonging to client duid=%2, iaid=%3 was released properly. This debug message indicates that an address was released properly. It is a normal operation during client shutdown. -% DHCP6_RELEASE_FAIL failed to remove lease for address %1 for duid=%2, iaid=%3 -This error message indicates that the software failed to remove a +% DHCP6_RELEASE_PD prefix %1 belonging to client duid=%2, iaid=%3 was released properly. +This debug message indicates that a prefix was released properly. It +is a normal operation during client shutdown. + +% DHCP6_RELEASE_NA_FAIL failed to remove address lease for address %1 for duid=%2, iaid=%3 +This error message indicates that the software failed to remove an address lease from the lease database. It probably due to an error during a database operation: resolution will most likely require administrator intervention (e.g. check if DHCP process has sufficient privileges to update the database). It may also be triggered if a lease was manually removed from the database during RELEASE message processing. -% DHCP6_RELEASE_FAIL_WRONG_DUID client (duid=%1) tried to release address %2, but it belongs to client (duid=%3) +% DHCP6_RELEASE_PD_FAIL failed to remove prefix lease for address %1 for duid=%2, iaid=%3 +This error message indicates that the software failed to remove a prefix +lease from the lease database. It probably due to an error during a +database operation: resolution will most likely require administrator +intervention (e.g. check if DHCP process has sufficient privileges to +update the database). It may also be triggered if a lease was manually +removed from the database during RELEASE message processing. + +% DHCP6_RELEASE_NA_FAIL_WRONG_DUID client (duid=%1) tried to release address %2, but it belongs to client (duid=%3) This warning message indicates that client tried to release an address that belongs to a different client. This should not happen in normal circumstances and may indicate a misconfiguration of the client. However, since the client releasing the address will stop using it anyway, there is a good chance that the situation will correct itself. -% DHCP6_RELEASE_FAIL_WRONG_IAID client (duid=%1) tried to release address %2, but it used wrong IAID (expected %3, but got %4) +% DHCP6_RELEASE_PD_FAIL_WRONG_DUID client (duid=%1) tried to release prefix %2, but it belongs to client (duid=%3) +This warning message indicates that client tried to release a prefix +that belongs to a different client. This should not happen in normal +circumstances and may indicate a misconfiguration of the client. However, +since the client releasing the prefix will stop using it anyway, there +is a good chance that the situation will correct itself. + +% DHCP6_RELEASE_NA_FAIL_WRONG_IAID client (duid=%1) tried to release address %2, but it used wrong IAID (expected %3, but got %4) This warning message indicates that client tried to release an address that does belong to it, but the address was expected to be in a different IA (identity association) container. This probably means that the client's support for multiple addresses is flawed. +% DHCP6_RELEASE_PD_FAIL_WRONG_IAID client (duid=%1) tried to release prefix %2, but it used wrong IAID (expected %3, but got %4) +This warning message indicates that client tried to release a prefix +that does belong to it, but the address was expected to be in a different +IA (identity association) container. This probably means that the client's +support for multiple prefixes is flawed. + % DHCP6_RELEASE_MISSING_CLIENTID client (address=%1) sent RELEASE message without mandatory client-id This warning message indicates that client sent RELEASE message without mandatory client-id option. This is most likely caused by a buggy client @@ -447,9 +487,14 @@ That could either mean missing functionality or invalid or broken relay or clien The list of formally defined message types is available here: www.iana.org/assignments/dhcpv6-parameters. -% DHCP6_UNKNOWN_RELEASE received RELEASE from unknown client (duid=%1, iaid=%2) -This warning message is printed when client attempts to release a lease, -but no such lease is known by the server. See DHCP6_UNKNOWN_RENEW for +% DHCP6_UNKNOWN_RELEASE_NA received RELEASE from unknown client (IA_NA, duid=%1, iaid=%2) +This warning message is printed when client attempts to release an address lease, +but no such lease is known by the server. See DHCP6_UNKNOWN_RENEW_NA for +possible reasons for such behavior. + +% DHCP6_UNKNOWN_RELEASE_PD received RELEASE from unknown client (IA_PD, duid=%1, iaid=%2) +This warning message is printed when client attempts to release an prefix lease, +but no such lease is known by the server. See DHCP6_UNKNOWN_RENEW_PD for possible reasons for such behavior. % DHCP6_UNKNOWN_RENEW_NA received unknown IA_NA RENEW from client (duid=%1, iaid=%2) in subnet %3 diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc index 9eb3b0f768..a07b31333b 100644 --- a/src/bin/dhcp6/dhcp6_srv.cc +++ b/src/bin/dhcp6/dhcp6_srv.cc @@ -1777,7 +1777,14 @@ Dhcpv6Srv::releaseLeases(const Pkt6Ptr& release, Pkt6Ptr& reply) { } break; } - // @todo: add support for IA_PD + case D6O_IA_PD: { + OptionPtr answer_opt = releaseIA_PD(duid, release, general_status, + boost::dynamic_pointer_cast(opt->second)); + if (answer_opt) { + reply->addOption(answer_opt); + } + break; + } // @todo: add support for IA_TA default: // remaining options are stateless and thus ignored in this context @@ -1827,7 +1834,7 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query, "Sorry, no known leases for this duid/iaid, can't release.")); general_status = STATUS_NoBinding; - LOG_INFO(dhcp6_logger, DHCP6_UNKNOWN_RELEASE) + LOG_INFO(dhcp6_logger, DHCP6_UNKNOWN_RELEASE_NA) .arg(duid->toText()) .arg(ia->getIAID()); @@ -1839,7 +1846,7 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query, // have mandatory DUID information attached. Someone was messing with our // database. - LOG_ERROR(dhcp6_logger, DHCP6_LEASE_WITHOUT_DUID) + LOG_ERROR(dhcp6_logger, DHCP6_LEASE_NA_WITHOUT_DUID) .arg(release_addr->getAddress().toText()); general_status = STATUS_UnspecFail; @@ -1849,9 +1856,9 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query, } if (*duid != *(lease->duid_)) { - // Sorry, it's not your address. You can't release it. - LOG_INFO(dhcp6_logger, DHCP6_RELEASE_FAIL_WRONG_DUID) + // Sorry, it's not your address. You can't release it. + LOG_INFO(dhcp6_logger, DHCP6_RELEASE_NA_FAIL_WRONG_DUID) .arg(duid->toText()) .arg(release_addr->getAddress().toText()) .arg(lease->duid_->toText()); @@ -1864,7 +1871,7 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query, if (ia->getIAID() != lease->iaid_) { // This address belongs to this client, but to a different IA - LOG_WARN(dhcp6_logger, DHCP6_RELEASE_FAIL_WRONG_IAID) + LOG_WARN(dhcp6_logger, DHCP6_RELEASE_PD_FAIL_WRONG_IAID) .arg(duid->toText()) .arg(release_addr->getAddress().toText()) .arg(lease->iaid_) @@ -1900,7 +1907,7 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query, // stage means "drop response". if (callout_handle->getSkip()) { skip = true; - LOG_DEBUG(dhcp6_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_LEASE6_RELEASE_SKIP); + LOG_DEBUG(dhcp6_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_LEASE6_RELEASE_NA_SKIP); } } @@ -1918,7 +1925,7 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query, ia_rsp->addOption(createStatusCode(STATUS_UnspecFail, "Server failed to release a lease")); - LOG_ERROR(dhcp6_logger, DHCP6_RELEASE_FAIL) + LOG_ERROR(dhcp6_logger, DHCP6_RELEASE_NA_FAIL) .arg(lease->addr_.toText()) .arg(duid->toText()) .arg(lease->iaid_); @@ -1926,7 +1933,7 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query, return (ia_rsp); } else { - LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_RELEASE) + LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_RELEASE_NA) .arg(lease->addr_.toText()) .arg(duid->toText()) .arg(lease->iaid_); @@ -1943,6 +1950,152 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query, } } +OptionPtr +Dhcpv6Srv::releaseIA_PD(const DuidPtr& duid, const Pkt6Ptr& query, + int& general_status, boost::shared_ptr ia) { + // Release can be done in one of two ways: + // Approach 1: extract address from client's IA_NA and see if it belongs + // to this particular client. + // Approach 2: find a subnet for this client, get a lease for + // this subnet/duid/iaid and check if its content matches to what the + // client is asking us to release. + // + // This method implements approach 1. + + // That's our response + boost::shared_ptr ia_rsp(new Option6IA(D6O_IA_PD, ia->getIAID())); + + boost::shared_ptr release_prefix = boost::dynamic_pointer_cast + (ia->getOption(D6O_IAPREFIX)); + if (!release_prefix) { + ia_rsp->addOption(createStatusCode(STATUS_NoBinding, + "You did not include address in your RELEASE")); + general_status = STATUS_NoBinding; + return (ia_rsp); + } + + Lease6Ptr lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_PD, + release_prefix->getAddress()); + + if (!lease) { + // client releasing a lease that we don't know about. + + // Insert status code NoAddrsAvail. + ia_rsp->addOption(createStatusCode(STATUS_NoBinding, + "Sorry, no known leases for this duid/iaid, can't release.")); + general_status = STATUS_NoBinding; + + LOG_INFO(dhcp6_logger, DHCP6_UNKNOWN_RELEASE_PD) + .arg(duid->toText()) + .arg(ia->getIAID()); + + return (ia_rsp); + } + + if (!lease->duid_) { + // Something is gravely wrong here. We do have a lease, but it does not + // have mandatory DUID information attached. Someone was messing with our + // database. + + LOG_ERROR(dhcp6_logger, DHCP6_LEASE_PD_WITHOUT_DUID) + .arg(release_prefix->getAddress().toText()); + + general_status = STATUS_UnspecFail; + ia_rsp->addOption(createStatusCode(STATUS_UnspecFail, + "Database consistency check failed when trying to RELEASE")); + return (ia_rsp); + } + + if (*duid != *(lease->duid_)) { + // Sorry, it's not your address. You can't release it. + + LOG_INFO(dhcp6_logger, DHCP6_RELEASE_PD_FAIL_WRONG_DUID) + .arg(duid->toText()) + .arg(release_prefix->getAddress().toText()) + .arg(lease->duid_->toText()); + + general_status = STATUS_NoBinding; + ia_rsp->addOption(createStatusCode(STATUS_NoBinding, + "This address does not belong to you, you can't release it")); + return (ia_rsp); + } + + if (ia->getIAID() != lease->iaid_) { + // This address belongs to this client, but to a different IA + LOG_WARN(dhcp6_logger, DHCP6_RELEASE_PD_FAIL_WRONG_IAID) + .arg(duid->toText()) + .arg(release_prefix->getAddress().toText()) + .arg(lease->iaid_) + .arg(ia->getIAID()); + ia_rsp->addOption(createStatusCode(STATUS_NoBinding, + "This is your address, but you used wrong IAID")); + general_status = STATUS_NoBinding; + return (ia_rsp); + } + + // It is not necessary to check if the address matches as we used + // getLease6(addr) method that is supposed to return a proper lease. + + bool skip = false; + // Execute all callouts registered for packet6_send + if (HooksManager::getHooksManager().calloutsPresent(Hooks.hook_index_lease6_release_)) { + CalloutHandlePtr callout_handle = getCalloutHandle(query); + + // Delete all previous arguments + callout_handle->deleteAllArguments(); + + // Pass the original packet + callout_handle->setArgument("query6", query); + + // Pass the lease to be updated + callout_handle->setArgument("lease6", lease); + + // Call all installed callouts + HooksManager::callCallouts(Hooks.hook_index_lease6_release_, *callout_handle); + + // Callouts decided to skip the next processing step. The next + // processing step would to send the packet, so skip at this + // stage means "drop response". + if (callout_handle->getSkip()) { + skip = true; + LOG_DEBUG(dhcp6_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_LEASE6_RELEASE_PD_SKIP); + } + } + + // Ok, we've passed all checks. Let's release this prefix. + bool success = false; // was the removal operation succeessful? + + if (!skip) { + success = LeaseMgrFactory::instance().deleteLease(lease->addr_); + } + + // Here the success should be true if we removed lease successfully + // and false if skip flag was set or the removal failed for whatever reason + + if (!success) { + ia_rsp->addOption(createStatusCode(STATUS_UnspecFail, + "Server failed to release a lease")); + + LOG_ERROR(dhcp6_logger, DHCP6_RELEASE_PD_FAIL) + .arg(lease->addr_.toText()) + .arg(duid->toText()) + .arg(lease->iaid_); + general_status = STATUS_UnspecFail; + + return (ia_rsp); + } else { + LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_RELEASE_PD) + .arg(lease->addr_.toText()) + .arg(duid->toText()) + .arg(lease->iaid_); + + ia_rsp->addOption(createStatusCode(STATUS_Success, + "Lease released. Thank you, please come again.")); + + return (ia_rsp); + } +} + Pkt6Ptr Dhcpv6Srv::processSolicit(const Pkt6Ptr& solicit) { diff --git a/src/bin/dhcp6/dhcp6_srv.h b/src/bin/dhcp6/dhcp6_srv.h index 495c3254e0..26fc5df5c8 100644 --- a/src/bin/dhcp6/dhcp6_srv.h +++ b/src/bin/dhcp6/dhcp6_srv.h @@ -286,12 +286,28 @@ protected: /// @param duid client's duid /// @param query client's message /// @param general_status a global status (it may be updated in case of errors) - /// @param ia IA_NA option that is being renewed + /// @param ia IA_NA option that is being released /// @return IA_NA option (server's response) OptionPtr releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query, int& general_status, boost::shared_ptr ia); + /// @brief Releases specific IA_PD option + /// + /// Generates response to IA_PD in Release message. This covers finding and + /// removal of a lease that corresponds to the received prefix(es). If no such + /// lease is found, an IA_PD response is generated with an appropriate + /// status code. + /// + /// @param duid client's duid + /// @param query client's message + /// @param general_status a global status (it may be updated in case of errors) + /// @param ia IA_PD option that is being released + /// @return IA_PD option (server's response) + OptionPtr releaseIA_PD(const DuidPtr& duid, const Pkt6Ptr& query, + int& general_status, + boost::shared_ptr ia); + /// @brief Copies required options from client message to server answer. /// /// Copies options that must appear in any server response (ADVERTISE, REPLY)