- <b>Next step status</b>: Not applicable, its value will be ignored.
+@subsection dhcpv6HookRegister6 register6
+
+ - @b Arguments:
+ - name: @b query6, type: isc::dhcp::Pkt6Ptr, direction: <b>in</b>
+ - name: @b response6, type: isc::dhcp::Pkt6Ptr, direction: <b>in</b>
+ - name: @b address6, type: isc::asiolink::IOAddress, direction: <b>in</b>
+ - name: @b old_lease6, type: isc::dhcp::Lease6Ptr, direction: <b>in</b>
+ - name: @b new_lease6, type: isc::dhcp::Lease6Ptr, direction: <b>in/out<b>
+
+ - @b Description: this callout is executed when an addr-reg-inform was
+ received and successfully processed. When the new_lease is cleared
+ this instructs the server to make stateless registration i.e. address
+ registration is used only for side effects and does not maintain state.
+
+ - <b>Next step status</b>: If any callout sets the status to SKIP or DROP,
+ the server will cancel current packet processing.
+
@subsection dhcpv6Leases6Committed leases6_committed
- @b Arguments:
extern const isc::log::MessageID DHCP6_ADDITIONAL_CLASS_NO_TEST = "DHCP6_ADDITIONAL_CLASS_NO_TEST";
extern const isc::log::MessageID DHCP6_ADDITIONAL_CLASS_UNDEFINED = "DHCP6_ADDITIONAL_CLASS_UNDEFINED";
extern const isc::log::MessageID DHCP6_ADD_GLOBAL_STATUS_CODE = "DHCP6_ADD_GLOBAL_STATUS_CODE";
+extern const isc::log::MessageID DHCP6_ADD_REG_INFORM_CLIENT_CHANGE = "DHCP6_ADD_REG_INFORM_CLIENT_CHANGE";
+extern const isc::log::MessageID DHCP6_ADD_REG_INFORM_FAIL = "DHCP6_ADD_REG_INFORM_FAIL";
extern const isc::log::MessageID DHCP6_ADD_STATUS_CODE_FOR_IA = "DHCP6_ADD_STATUS_CODE_FOR_IA";
extern const isc::log::MessageID DHCP6_ALREADY_RUNNING = "DHCP6_ALREADY_RUNNING";
extern const isc::log::MessageID DHCP6_BUFFER_RECEIVED = "DHCP6_BUFFER_RECEIVED";
extern const isc::log::MessageID DHCP6_HOOK_PACKET_RCVD_SKIP = "DHCP6_HOOK_PACKET_RCVD_SKIP";
extern const isc::log::MessageID DHCP6_HOOK_PACKET_SEND_DROP = "DHCP6_HOOK_PACKET_SEND_DROP";
extern const isc::log::MessageID DHCP6_HOOK_PACKET_SEND_SKIP = "DHCP6_HOOK_PACKET_SEND_SKIP";
+extern const isc::log::MessageID DHCP6_HOOK_REGISTER6_SKIP = "DHCP6_HOOK_REGISTER6_SKIP";
extern const isc::log::MessageID DHCP6_HOOK_SUBNET6_SELECT_DROP = "DHCP6_HOOK_SUBNET6_SELECT_DROP";
extern const isc::log::MessageID DHCP6_HOOK_SUBNET6_SELECT_PARK = "DHCP6_HOOK_SUBNET6_SELECT_PARK";
extern const isc::log::MessageID DHCP6_HOOK_SUBNET6_SELECT_SKIP = "DHCP6_HOOK_SUBNET6_SELECT_SKIP";
"DHCP6_ADDITIONAL_CLASS_NO_TEST", "additional class %1 has no test expression, adding it to client's classes unconditionally",
"DHCP6_ADDITIONAL_CLASS_UNDEFINED", "additional class %1 has no definition",
"DHCP6_ADD_GLOBAL_STATUS_CODE", "%1: adding Status Code to DHCPv6 packet: %2",
+ "DHCP6_ADD_REG_INFORM_CLIENT_CHANGE", "received an add-reg-inform for %1 from client '%2' but the address was registered by another client '%3'",
+ "DHCP6_ADD_REG_INFORM_FAIL", "error on add-reg-inform from client %1: %2",
"DHCP6_ADD_STATUS_CODE_FOR_IA", "%1: adding Status Code to IA with iaid=%2: %3",
"DHCP6_ALREADY_RUNNING", "%1 already running? %2",
"DHCP6_BUFFER_RECEIVED", "received buffer from %1:%2 to %3:%4 over interface %5",
"DHCP6_HOOK_PACKET_RCVD_SKIP", "%1: packet is dropped, because a callout set the next step to SKIP",
"DHCP6_HOOK_PACKET_SEND_DROP", "%1: prepared DHCPv6 response was not sent because a callout set the next ste to DROP",
"DHCP6_HOOK_PACKET_SEND_SKIP", "%1: prepared DHCPv6 response is not built because a callout set the next step to SKIP",
+ "DHCP6_HOOK_REGISTER6_SKIP", "%1: add-reg-inform for %2 is dropped, because a callout set the next step to SKIP",
"DHCP6_HOOK_SUBNET6_SELECT_DROP", "%1: packet was dropped because a callout set the drop flag",
"DHCP6_HOOK_SUBNET6_SELECT_PARK", "%1: packet was parked",
"DHCP6_HOOK_SUBNET6_SELECT_SKIP", "%1: no subnet was selected because a callout set the next step to SKIP",
extern const isc::log::MessageID DHCP6_ADDITIONAL_CLASS_NO_TEST;
extern const isc::log::MessageID DHCP6_ADDITIONAL_CLASS_UNDEFINED;
extern const isc::log::MessageID DHCP6_ADD_GLOBAL_STATUS_CODE;
+extern const isc::log::MessageID DHCP6_ADD_REG_INFORM_CLIENT_CHANGE;
+extern const isc::log::MessageID DHCP6_ADD_REG_INFORM_FAIL;
extern const isc::log::MessageID DHCP6_ADD_STATUS_CODE_FOR_IA;
extern const isc::log::MessageID DHCP6_ALREADY_RUNNING;
extern const isc::log::MessageID DHCP6_BUFFER_RECEIVED;
extern const isc::log::MessageID DHCP6_HOOK_PACKET_RCVD_SKIP;
extern const isc::log::MessageID DHCP6_HOOK_PACKET_SEND_DROP;
extern const isc::log::MessageID DHCP6_HOOK_PACKET_SEND_SKIP;
+extern const isc::log::MessageID DHCP6_HOOK_REGISTER6_SKIP;
extern const isc::log::MessageID DHCP6_HOOK_SUBNET6_SELECT_DROP;
extern const isc::log::MessageID DHCP6_HOOK_SUBNET6_SELECT_PARK;
extern const isc::log::MessageID DHCP6_HOOK_SUBNET6_SELECT_SKIP;
transaction identification information. The second argument includes
the details of the status code.
+% DHCP6_ADD_REG_INFORM_FAIL error on add-reg-inform from client %1: %2
+This information message is issued when the processing of an add-reg-inform
+message failed. The address of the client, usually also the address to
+register, and the description of the problem are printed.
+
+% DHCP6_ADD_REG_INFORM_CLIENT_CHANGE received an add-reg-inform for %1 from client '%2' but the address was registered by another client '%3'
+This information message is issued when a lease for another client already
+exists for an address being registered. The address, the new client and
+previous client identifiers are printed.
+
% DHCP6_ADD_STATUS_CODE_FOR_IA %1: adding Status Code to IA with iaid=%2: %3
Logged at debug log level 50.
This message is logged when the server is adding the Status Code
book. The argument specifies the client and transaction identification
information.
+% DHCP6_HOOK_REGISTER6_SKIP %1: add-reg-inform for %2 is dropped, because a callout set the next step to SKIP
+Logged at debug log level 40.
+This debug message is printed when a callout installed on the register6
+hook point sets the next step to SKIP. For this particular hook point, the
+value setting instructs the server to cancel the address registration and
+drop the packet.
+
% DHCP6_HOOK_SUBNET6_SELECT_DROP %1: packet was dropped because a callout set the drop flag
Logged at debug log level 40.
This debug message is printed when a callout installed on the
int hook_index_lease6_decline_; ///< index for "lease6_decline" hook point
int hook_index_host6_identifier_; ///< index for "host6_identifier" hook point
int hook_index_ddns6_update_; ///< index for "ddns6_update" hook point
+ int hook_index_register6_; ///< index for "register6" hook point
/// Constructor that registers hook points for DHCPv6 engine
Dhcp6Hooks() {
hook_index_lease6_decline_ = HooksManager::registerHook("lease6_decline");
hook_index_host6_identifier_ = HooksManager::registerHook("host6_identifier");
hook_index_ddns6_update_ = HooksManager::registerHook("ddns6_update");
+ hook_index_register6_ = HooksManager::registerHook("register6");
}
};
ctx.createIAContext();
ctx.currentIA().type_ = Lease::TYPE_NA;
ctx.currentIA().iaid_ = ia->getIAID();
+ ctx.currentIA().ia_rsp_ = ia;
// Get IAADDR from the IA_NA. There must be the only option.
OptionCollection iaaddrs = ia->getOptions();
if (!iaaddr) {
isc_throw(RFCViolation, "Can't get the IAADDR sub-option");
}
- ctx.currentIA().addHint(iaaddr);
// Client and IADDR addresses must match.
if (addr != iaaddr->getAddress()) {
isc_throw(RFCViolation, "Address " << addr << " is reserved");
}
} catch (const std::exception &ex) {
- // log
+ // Incoming processing failed.
+ LOG_INFO(packet6_logger, DHCP6_ADD_REG_INFORM_FAIL)
+ .arg(addr)
+ .arg(ex.what());
return (Pkt6Ptr());
}
+ // Record if it is a registration renewal.
+ bool renewal = !!old_lease;
+
// Check if the client is the same.
- if (old_lease && old_lease->duid_ && *ctx.duid_ != *(old_lease->duid_)) {
- // log
+ if (old_lease) {
+ if (old_lease->duid_ && (*ctx.duid_ != *(old_lease->duid_))) {
+ LOG_INFO(packet6_logger, DHCP6_ADD_REG_INFORM_CLIENT_CHANGE)
+ .arg(addr)
+ .arg(ctx.duid_->toText())
+ .arg(old_lease->duid_->toText());
+ }
+ if (old_lease->subnet_id_ != subnet->getID()) {
+ renewal = false;
+ }
}
// Build response.
appendRequestedOptions(add_reg_inf, add_reg_rep, co_list);
appendRequestedVendorOptions(add_reg_inf, add_reg_rep, ctx, co_list);
- // call the new callout
+ // Handle the "register6" callout point.
+ if (HooksManager::calloutsPresent(Hooks.hook_index_register6_)) {
+ CalloutHandlePtr callout_handle = getCalloutHandle(add_reg_inf);
+ ScopedCalloutHandleState callout_handle_state(callout_handle);
- // Add stats
- if (old_lease) {
- // Save the old lease for the lease6_committed callout.
- ctx.currentIA().old_leases_.push_back(old_lease);
- if (!lease) {
- if (!LeaseMgrFactory::instance().deleteLease(old_lease)) {
+ // Pass the query6 argument.
+ ScopedEnableOptionsCopy<Pkt6> query6_options_copy(add_reg_inf);
+ callout_handle->setArgument("query6", add_reg_inf);
+
+ // Pass the response6 argument.
+ ScopedEnableOptionsCopy<Pkt6> rsp6_options_copy(add_reg_rep);
+ callout_handle->setArgument("response6", add_reg_rep);
+
+ // Pass the address6 argument.
+ callout_handle->setArgument("address6", addr);
+
+ // Pass the old_lease argument.
+ callout_handle->setArgument("old_lease6", old_lease);
+
+ // Pass the new_lease argument.
+ callout_handle->setArgument("new_lease6", lease);
+
+ // Call callouts
+ HooksManager::callCallouts(Hooks.hook_index_register6_, *callout_handle);
+
+ // Callouts decided to skip the next processing step. This means
+ // cancel processing so drop.
+ if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
+ (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
+ LOG_DEBUG(hooks_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_REGISTER6_SKIP)
+ .arg(add_reg_inf->getLabel())
+ .arg(addr);
+ return (Pkt6Ptr());
+ }
+
+ Lease6Ptr new_lease;
+ callout_handle->getArgument("new_lease6", new_lease);
+ if (!new_lease) {
+ // Stateless registration: skip lease code.
+ lease.reset();
+ }
+ }
+
+ if (lease) {
+ // Statefull registration.
+ if (old_lease) {
+ try {
+ LeaseMgrFactory::instance().updateLease6(lease);
+ } catch (const std::exception&) {
// Assume that stats and DNS were handled by someone else.
return (add_reg_rep);
}
+ // Save the old lease for the lease6_committed callout.
+ ctx.currentIA().old_leases_.push_back(old_lease);
+ if (!renewal) {
+ // -1 on stats.
+ } else {
+ // Save the old lease for the DNS update.
+ ctx.currentIA().changed_leases_.push_back(old_lease);
+ }
} else {
- try {
- LeaseMgrFactory::instance().updateLease6(lease);
- } catch (const std::exception&) {
+ if (!LeaseMgrFactory::instance().addLease(lease)) {
// Assume that stats and DNS were handled by someone else.
return (add_reg_rep);
}
}
- } else if (lease) {
- if (!LeaseMgrFactory::instance().addLease(lease)) {
- // Assume that stats and DNS were handled by someone else.
- return (add_reg_rep);
- }
- }
- if (lease) {
// Save the new lease for the lease6_committed callout.
ctx.new_leases_.push_back(lease);
+ if (!renewal) {
+ // +1 on stats
+ }
}
+ // Deal with FQDN.
updateReservedFqdn(ctx, add_reg_rep);
+ generateFqdn(add_reg_rep, ctx);
+ createNameChangeRequests(add_reg_rep, ctx);
return (add_reg_rep);
}
% DHCP4_CLASS_ASSIGNED: 3
% DHCP4_PACKET_QUEUE_FULL: 2
% DHCP4_CONFIG_RECEIVED: 2
- % DHCP6_CLASSES_ASSIGNED: 8
+ % DHCP6_CLASSES_ASSIGNED: 9
% DHCP6_CLASS_ASSIGNED: 3
% DHCP6_PACKET_QUEUE_FULL: 2
% DHCP6_CONFIG_RECEIVED: 2