From: Tomek Mrugalski Date: Fri, 9 Aug 2013 15:10:08 +0000 (+0200) Subject: [master] Merge branch 'trac2984' (additional DHCPv6 hooks) X-Git-Tag: bind10-1.2.0beta1-release~284 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fef265b2e3bfae238c91bfd820bed760efc748aa;p=thirdparty%2Fkea.git [master] Merge branch 'trac2984' (additional DHCPv6 hooks) Conflicts: ChangeLog src/bin/dhcp6/dhcp6_srv.cc --- fef265b2e3bfae238c91bfd820bed760efc748aa diff --cc ChangeLog index 35ce15084a,8ac46c95b2..53e650c7cd --- a/ChangeLog +++ b/ChangeLog @@@ -1,67 -1,10 +1,72 @@@ - 655. [func] tmark -6XX. [func] tomek ++656. [func] tomek + Additional hooks (buffer6_receive, lease6_renew, + lease6_release, buffer6_send) added to the DHCPv6 server. - (Trac #2984, git ABCD) ++ (Trac #2984, git 540dd0449121094a56f294c500c2ed811f6016b6) ++ ++655. [func] tmark + Added D2UpdateMgr class to b10-dhcp-ddns. This class is the b10-dhcp-ddns + task master, instantiating and supervising transactions that carry out the + DNS updates needed to fulfill the requests (NameChangeRequests) received + from b10-dhcp-ddns clients (e.g. DHCP servers). - (Trac #3059 git d72675617d6b60e3eb6160305738771f015849ba) ++ (Trac #3059 git d72675617d6b60e3eb6160305738771f015849ba) + +654. [bug] stephen + Always clear "skip" flag before calling any callouts on a hook. + (Trac# 3050, git ff0b9b45869b1d9a4b99e785fbce421e184c2e93) + +653. [func] tmark + Added initial implementation of D2QueueMgr to + b10-dhcp-ddns. This class manages the receipt and + queueing of requests received by b10-dhcp-ddns from + its clients (e.g. DHCP servers) + (Trac# 3052, git a970f6c5255e000c053a2dc47926cea7cec2761c) + +652. [doc] stephen + Added the "Hook Developer's Guide" to the BIND 10 developer + documentation. + (Trac# 2982, git 26a805c7e49a9ec85ee825f179cda41a2358f4c6) + +651. [bug] muks + A race condition when creating cmdctl certificates caused corruption + of these certificates in rare cases. This has now been fixed. + (Trac# 2962, git 09f557d871faef090ed444ebeee7f13e142184a0) + +650. [func] muks + The DomainTree rebalancing code has been updated to be more + understandable. This ChangeLog entry is made just to make a note + of this change. The change should not cause any observable + difference whatsoever. + (Trac# 2811, git 7c0bad1643af13dedf9356e9fb3a51264b7481de) + +649. [func] muks + The default b10-xfrout also_notify port has been changed from + 0 to 53. + (Trac# 2925, git 8acbf043daf590a9f2ad003e715cd4ffb0b3f979) + +648. [func] tmark + Moved classes pertaining to sending and receiving + NameChangeRequests from src/bin/d2 into their own library, + libdhcp_ddns, in src/lib/dhcp_ddns. This allows the + classes to be shared between DHDCP-DDNS and its clients, + such as the DHCP servers. + (Trac# 3065, git 3d39bccaf3f0565152ef73ec3e2cd03e77572c56) + +647. [func] tmark + Added initial implementation of classes for sending + and receiving NameChangeRequests between DHCP-DDNS + and its clients such as DHCP. This includes both + abstract classes and a derivation which traffics + requests across UDP sockets. + (Trac #3008, git b54530b4539cec4476986442e72c047dddba7b48) + +646. [func] stephen + Extended the hooks framework to add a "validate libraries" function. + This will be used to check libraries specified during BIND 10 + configuration. + (Trac #3054, git 0f845ed94f462dee85b67f056656b2a197878b04) 645. [func] tomek - Added initial set of hooks (pk4_receive, subnet4_select, + Added initial set of hooks (pkt4_receive, subnet4_select, lease4_select, pkt4_send) to the DHCPv6 server. (Trac #2994, git be65cfba939a6a7abd3c93931ce35c33d3e8247b) diff --cc src/bin/dhcp6/dhcp6_srv.cc index b2ba67bc1c,1d028f6f92..90c37165fc --- a/src/bin/dhcp6/dhcp6_srv.cc +++ b/src/bin/dhcp6/dhcp6_srv.cc @@@ -191,148 -192,230 +192,238 @@@ bool Dhcpv6Srv::run() LOG_ERROR(dhcp6_logger, DHCP6_PACKET_RECEIVE_FAIL).arg(e.what()); } - if (query) { - if (!query->unpack()) { - LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, - DHCP6_PACKET_PARSE_FAIL); - continue; - } - LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_PACKET_RECEIVED) - .arg(query->getName()); - LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL_DATA, DHCP6_QUERY_DATA) - .arg(static_cast(query->getType())) - .arg(query->getBuffer().getLength()) - .arg(query->toText()); - - // Let's execute all callouts registered for packet_received - if (HooksManager::getHooksManager().calloutsPresent(hook_index_pkt6_receive_)) { - CalloutHandlePtr callout_handle = getCalloutHandle(query); + // Timeout may be reached or signal received, which breaks select() with no packet received + if (!query) { + continue; + } - // Delete previously set arguments - callout_handle->deleteAllArguments(); + bool skip_unpack = false; - // Pass incoming packet as argument - callout_handle->setArgument("query6", query); + // The packet has just been received so contains the uninterpreted wire + // data; execute callouts registered for buffer6_receive. + if (HooksManager::getHooksManager().calloutsPresent(Hooks.hook_index_buffer6_receive_)) { + CalloutHandlePtr callout_handle = getCalloutHandle(query); - // Call callouts - HooksManager::callCallouts(hook_index_pkt6_receive_, *callout_handle); + // Delete previously set arguments + callout_handle->deleteAllArguments(); - // Callouts decided to skip the next processing step. The next - // processing step would to process the packet, so skip at this - // stage means drop. - if (callout_handle->getSkip()) { - LOG_DEBUG(dhcp6_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_PACKET_RCVD_SKIP); - continue; - } + // Pass incoming packet as argument + callout_handle->setArgument("query6", query); - callout_handle->getArgument("query6", query); + // Call callouts + HooksManager::callCallouts(Hooks.hook_index_buffer6_receive_, *callout_handle); + + // Callouts decided to skip the next processing step. The next + // processing step would to parse the packet, so skip at this + // stage means that callouts did the parsing already, so server + // should skip parsing. + if (callout_handle->getSkip()) { + LOG_DEBUG(dhcp6_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_BUFFER_RCVD_SKIP); + skip_unpack = true; } - try { - switch (query->getType()) { - case DHCPV6_SOLICIT: - rsp = processSolicit(query); - break; + callout_handle->getArgument("query6", query); + } - case DHCPV6_REQUEST: - rsp = processRequest(query); - break; + // Unpack the packet information unless the buffer6_receive callouts + // indicated they did it + if (!skip_unpack) { + if (!query->unpack()) { + LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, + DHCP6_PACKET_PARSE_FAIL); + continue; + } + } + LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_PACKET_RECEIVED) + .arg(query->getName()); + LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL_DATA, DHCP6_QUERY_DATA) + .arg(static_cast(query->getType())) + .arg(query->getBuffer().getLength()) + .arg(query->toText()); + + // At this point the information in the packet has been unpacked into + // the various packet fields and option objects has been cretated. + // Execute callouts registered for packet6_receive. + if (HooksManager::getHooksManager().calloutsPresent(Hooks.hook_index_pkt6_receive_)) { + CalloutHandlePtr callout_handle = getCalloutHandle(query); + + // Delete previously set arguments + callout_handle->deleteAllArguments(); + + // Pass incoming packet as argument + callout_handle->setArgument("query6", query); + + // Call callouts + HooksManager::callCallouts(Hooks.hook_index_pkt6_receive_, *callout_handle); + + // Callouts decided to skip the next processing step. The next + // processing step would to process the packet, so skip at this + // stage means drop. + if (callout_handle->getSkip()) { + LOG_DEBUG(dhcp6_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_PACKET_RCVD_SKIP); + continue; + } - case DHCPV6_RENEW: - rsp = processRenew(query); - break; + callout_handle->getArgument("query6", query); + } - case DHCPV6_REBIND: - rsp = processRebind(query); + try { + switch (query->getType()) { + case DHCPV6_SOLICIT: + rsp = processSolicit(query); break; - case DHCPV6_CONFIRM: - rsp = processConfirm(query); - break; + case DHCPV6_REQUEST: + rsp = processRequest(query); + break; + + case DHCPV6_RENEW: + rsp = processRenew(query); + break; + + case DHCPV6_REBIND: + rsp = processRebind(query); + break; + + case DHCPV6_CONFIRM: + rsp = processConfirm(query); + break; + + case DHCPV6_RELEASE: + rsp = processRelease(query); + break; + + case DHCPV6_DECLINE: + rsp = processDecline(query); + break; + + case DHCPV6_INFORMATION_REQUEST: + rsp = processInfRequest(query); + break; + + default: + // We received a packet type that we do not recognize. + LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_UNKNOWN_MSG_RECEIVED) + .arg(static_cast(query->getType())) + .arg(query->getIface()); + // Only action is to output a message if debug is enabled, + // and that will be covered by the debug statement before + // the "switch" statement. + ; + } - case DHCPV6_RELEASE: - rsp = processRelease(query); - break; + } catch (const RFCViolation& e) { + LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_REQUIRED_OPTIONS_CHECK_FAIL) + .arg(query->getName()) + .arg(query->getRemoteAddr().toText()) + .arg(e.what()); + + } catch (const isc::Exception& e) { + + // Catch-all exception (at least for ones based on the isc + // Exception class, which covers more or less all that + // are explicitly raised in the BIND 10 code). Just log + // the problem and ignore the packet. (The problem is logged + // as a debug message because debug is disabled by default - + // it prevents a DDOS attack based on the sending of problem + // packets.) + LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_PACKET_PROCESS_FAIL) + .arg(query->getName()) + .arg(query->getRemoteAddr().toText()) + .arg(e.what()); + } - case DHCPV6_DECLINE: - rsp = processDecline(query); - break; + if (rsp) { + rsp->setRemoteAddr(query->getRemoteAddr()); + rsp->setLocalAddr(query->getLocalAddr()); + rsp->setRemotePort(DHCP6_CLIENT_PORT); + rsp->setLocalPort(DHCP6_SERVER_PORT); + rsp->setIndex(query->getIndex()); + rsp->setIface(query->getIface()); + + // Specifies if server should do the packing + bool skip_pack = false; + + // Server's reply packet now has all options and fields set. + // Options are represented by individual objects, but the + // output wire data has not been prepared yet. + // Execute all callouts registered for packet6_send + if (HooksManager::getHooksManager().calloutsPresent(Hooks.hook_index_pkt6_send_)) { + CalloutHandlePtr callout_handle = getCalloutHandle(query); - case DHCPV6_INFORMATION_REQUEST: - rsp = processInfRequest(query); - break; + // Delete all previous arguments + callout_handle->deleteAllArguments(); + + // Set our response + callout_handle->setArgument("response6", rsp); - default: - // Only action is to output a message if debug is enabled, - // and that will be covered by the debug statement before - // the "switch" statement. - ; + // Call all installed callouts + HooksManager::callCallouts(Hooks.hook_index_pkt6_send_, *callout_handle); + + // Callouts decided to skip the next processing step. The next + // processing step would to pack the packet (create wire data). + // That step will be skipped if any callout sets skip flag. + // It essentially means that the callout already did packing, + // so the server does not have to do it again. + if (callout_handle->getSkip()) { + LOG_DEBUG(dhcp6_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_PACKET_SEND_SKIP); + skip_pack = true; } + } - } catch (const RFCViolation& e) { - LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_REQUIRED_OPTIONS_CHECK_FAIL) - .arg(query->getName()) - .arg(query->getRemoteAddr().toText()) - .arg(e.what()); + LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL_DATA, + DHCP6_RESPONSE_DATA) + .arg(static_cast(rsp->getType())).arg(rsp->toText()); - } catch (const isc::Exception& e) { - - // Catch-all exception (at least for ones based on the isc - // Exception class, which covers more or less all that - // are explicitly raised in the BIND 10 code). Just log - // the problem and ignore the packet. (The problem is logged - // as a debug message because debug is disabled by default - - // it prevents a DDOS attack based on the sending of problem - // packets.) - LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_PACKET_PROCESS_FAIL) - .arg(query->getName()) - .arg(query->getRemoteAddr().toText()) - .arg(e.what()); + if (!skip_pack) { - if (!rsp->pack()) { - LOG_ERROR(dhcp6_logger, DHCP6_PACK_FAIL); ++ try { ++ rsp->pack(); ++ } catch (const std::exception& e) { ++ LOG_ERROR(dhcp6_logger, DHCP6_PACK_FAIL) ++ .arg(e.what()); + continue; + } } - if (rsp) { - rsp->setRemoteAddr(query->getRemoteAddr()); - rsp->setLocalAddr(query->getLocalAddr()); - rsp->setRemotePort(DHCP6_CLIENT_PORT); - rsp->setLocalPort(DHCP6_SERVER_PORT); - rsp->setIndex(query->getIndex()); - rsp->setIface(query->getIface()); + try { - // Execute all callouts registered for packet6_send - if (HooksManager::getHooksManager().calloutsPresent(hook_index_pkt6_send_)) { + // Now all fields and options are constructed into output wire buffer. + // Option objects modification does not make sense anymore. Hooks + // can only manipulate wire buffer at this stage. + // Let's execute all callouts registered for buffer6_send + if (HooksManager::getHooksManager().calloutsPresent(Hooks.hook_index_buffer6_send_)) { CalloutHandlePtr callout_handle = getCalloutHandle(query); - // Delete all previous arguments + // Delete previously set arguments callout_handle->deleteAllArguments(); - // Set our response + // Pass incoming packet as argument callout_handle->setArgument("response6", rsp); - - // Call all installed callouts - HooksManager::callCallouts(hook_index_pkt6_send_, *callout_handle); - + + // Call callouts + HooksManager::callCallouts(Hooks.hook_index_buffer6_send_, *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". + // processing step would to parse the packet, so skip at this + // stage means drop. if (callout_handle->getSkip()) { - LOG_DEBUG(dhcp6_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_PACKET_SEND_SKIP); + LOG_DEBUG(dhcp6_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_BUFFER_SEND_SKIP); continue; } + + callout_handle->getArgument("response6", rsp); } - + + LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL_DATA, + DHCP6_RESPONSE_DATA) + .arg(static_cast(rsp->getType())).arg(rsp->toText()); + - try { - rsp->pack(); - sendPacket(rsp); - } catch (const std::exception& e) { - LOG_ERROR(dhcp6_logger, DHCP6_PACKET_SEND_FAIL) - .arg(e.what()); - } + sendPacket(rsp); + } catch (const std::exception& e) { - LOG_ERROR(dhcp6_logger, DHCP6_PACKET_SEND_FAIL).arg(e.what()); ++ LOG_ERROR(dhcp6_logger, DHCP6_PACKET_SEND_FAIL) ++ .arg(e.what()); } - } + } } return (true);