BIND 10 trac3207, updated. d130cf2cb4c0d294a43d47d989732e466a8be24a [3207] Replaced selected subnet with lease address in user check output

BIND 10 source code commits bind10-changes at lists.isc.org
Fri Oct 25 10:36:44 UTC 2013


The branch, trac3207 has been updated
       via  d130cf2cb4c0d294a43d47d989732e466a8be24a (commit)
      from  327d9ff442bd25fa742c3ea03aa4630440c00661 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit d130cf2cb4c0d294a43d47d989732e466a8be24a
Author: Thomas Markwalder <tmark at isc.org>
Date:   Fri Oct 25 06:31:05 2013 -0400

    [3207] Replaced selected subnet with lease address in user check output
    
    User check hook library's outcome output is now generated in pkt_send
    callout allowing the output of lease address (or prefix) in place
    of selected subnet.

-----------------------------------------------------------------------

Summary of changes:
 src/hooks/dhcp/user_chk/pkt_send_co.cc |  279 ++++++++++++++++++++++++--------
 1 file changed, 212 insertions(+), 67 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/hooks/dhcp/user_chk/pkt_send_co.cc b/src/hooks/dhcp/user_chk/pkt_send_co.cc
index 7be2562..4e9c6b6 100644
--- a/src/hooks/dhcp/user_chk/pkt_send_co.cc
+++ b/src/hooks/dhcp/user_chk/pkt_send_co.cc
@@ -16,8 +16,12 @@
 
 #include <asiolink/io_address.h>
 #include <hooks/hooks.h>
-#include <dhcp/pkt4.h>
 #include <dhcp/dhcp6.h>
+#include <dhcp/option_custom.h>
+#include <dhcp/option6_ia.h>
+#include <dhcp/option6_iaaddr.h>
+#include <dhcp/option6_iaprefix.h>
+#include <dhcp/pkt4.h>
 #include <dhcp/pkt6.h>
 #include <user_chk.h>
 
@@ -30,64 +34,14 @@ using namespace std;
 // issues related to namespaces.
 extern "C" {
 
-/// @brief Adds an entry to the end of the user check outcome file.
-///
-/// Each user entry is written in an ini-like format, with one name-value pair
-/// per line as follows:
-///
-/// id_type=<id type>
-/// client=<id str>
-/// subnet=<subnet str>
-/// registered=<is registered>"
-///
-/// where:
-/// <id type> text label of the id type: "HW_ADDR" or "DUID"
-/// <id str> user's id formatted as either isc::dhcp::Hwaddr.toText() or
-/// isc::dhcp::DUID.toText()
-/// <subnet str> selected subnet formatted as isc::dhcp::Subnet4::toText() or
-/// isc::dhcp::Subnet6::toText() as appropriate.
-/// <is registered> "yes" or "no"
-///
-/// Sample IPv4 entry would like this:
-///
-/// @code
-/// id_type=DUID
-/// client=00:01:00:01:19:ef:e6:3b:00:0c:01:02:03:04
-/// subnet=2001:db8:2::/64
-/// registered=yes
-/// id_type=duid
-/// @endcode
-///
-/// Sample IPv4 entry would like this:
-///
-/// @code
-/// id_type=DUID
-/// id_type=HW_ADDR
-/// client=hwtype=1 00:0c:01:02:03:05
-/// subnet=152.77.5.0/24
-/// registered=no
-/// @endcode
-///
-/// @param id_type_str text label identify the id type
-/// @param id_val_str text representation of the user id
-/// @param subnet_str text representation  of the selected subnet
-/// @param registered boolean indicating if the user is registered or not
-void generate_output_record(const std::string& id_type_str,
+extern void generate_output_record(const std::string& id_type_str,
                             const std::string& id_val_str,
                             const std::string& addr_str,
-                            const bool& registered)
-{
-    user_chk_output << "id_type=" << id_type_str << std::endl
-                    << "client=" << id_val_str << std::endl
-                    << "addr=" << addr_str << std::endl
-                    << "registered=" << (registered ? "yes" : "no")
-                    << std::endl;
-
-    // @todo Flush is here to ensure output is immediate for demo purposes.
-    // Performance would generally dictate not using it.
-    flush(user_chk_output);
-}
-
+                            const bool& registered);
+extern std::string getV6AddrStr (Pkt6Ptr response);
+extern std::string getAddrStrIA_NA(OptionPtr options);
+extern std::string getAddrStrIA_PD(OptionPtr options);
+extern bool checkIAStatus(boost::shared_ptr<Option6IA>& ia_opt);
 
 /// @brief  This callout is called at the "pkt4_send" hook.
 ///
@@ -102,9 +56,22 @@ int pkt4_send(CalloutHandle& handle) {
         Pkt4Ptr response;
         handle.getArgument("response4", response);
 
+        // @todo do we need to filter on type?
+#if 0
+        uint8_t packet_type = response->getType();
+        std::cout << "PACKET TYPE IS: " <<
+                  static_cast<int>(packet_type) << std::endl;
+
+        if ((packet_type != DHCPOFFER) && (packet_type != DHCPACK)) {
+            std::cout << "SKIPPING PACKET TYPE IS: "
+                      << static_cast<int>(packet_type) << std::endl;
+            return (0);
+        }
+#endif
+
         // Get the user id saved from the query packet.
         HWAddrPtr hwaddr;
-        handle.setContext(query_user_id_label, hwaddr);
+        handle.getContext(query_user_id_label, hwaddr);
 
         // Get registered_user pointer.
         UserPtr registered_user;
@@ -123,9 +90,9 @@ int pkt4_send(CalloutHandle& handle) {
             generate_output_record(UserId::HW_ADDRESS_STR, hwaddr->toText(),
                                    addr.toText(), true);
         } else {
-            // add default options based 
+            // add default options based
             // then generate not registered output record
-            std::cout << "DHCP UserCheckHook : pkt4_send no registered_user" 
+            std::cout << "DHCP UserCheckHook : pkt4_send no registered_user"
                       << std::endl;
             // Add the outcome entry to the output file.
             generate_output_record(UserId::HW_ADDRESS_STR, hwaddr->toText(),
@@ -153,12 +120,32 @@ int pkt6_send(CalloutHandle& handle) {
         Pkt6Ptr response;
         handle.getArgument("response6", response);
 
-        // Fetch the lease address. @todo
-        isc::asiolink::IOAddress addr("0.0.0.0");
+        // @todo do we need to filter on type?
+#if 0
+        uint8_t packet_type = response->getType();
+        std::cout << "PACKET TYPE IS: " <<
+                  static_cast<int>(packet_type) << std::endl;
+
+        if ((packet_type != DHCPV6_ADVERTISE) &&
+            (packet_type != DHCPV6_REPLY)) {
+            std::cout << "SKIPPING PACKET TYPE IS: "
+                      << static_cast<int>(packet_type) << std::endl;
+            return (0);
+        }
+#endif
+
+        // Fetch the lease address as a string
+        std::string addr_str = getV6AddrStr(response);
+        if (addr_str.empty()) {
+            // packet did not contain an address, must be failed.
+            std::cout << "pkt6_send: Skipping packet address is blank"
+                      << std::endl;
+            return (0);
+        }
 
         // Get the user id saved from the query packet.
         DuidPtr duid;
-        handle.setContext(query_user_id_label, duid);
+        handle.getContext(query_user_id_label, duid);
 
         // Get registered_user pointer.
         UserPtr registered_user;
@@ -171,15 +158,15 @@ int pkt6_send(CalloutHandle& handle) {
                       << registered_user->getUserId() << std::endl;
             // Add the outcome entry to the output file.
             generate_output_record(UserId::DUID_STR, duid->toText(),
-                                   addr.toText(), true);
+                                   addr_str, true);
         } else {
-            // add default options based 
+            // add default options based
             // then generate not registered output record
-            std::cout << "DHCP UserCheckHook : pkt6_send no registered_user" 
+            std::cout << "DHCP UserCheckHook : pkt6_send no registered_user"
                       << std::endl;
             // Add the outcome entry to the output file.
             generate_output_record(UserId::DUID_STR, duid->toText(),
-                                   addr.toText(), false);
+                                   addr_str, false);
         }
     } catch (const std::exception& ex) {
         std::cout << "DHCP UserCheckHook : pkt6_send unexpected error: "
@@ -190,4 +177,162 @@ int pkt6_send(CalloutHandle& handle) {
     return (0);
 }
 
+/// @brief Adds an entry to the end of the user check outcome file.
+///
+/// Each user entry is written in an ini-like format, with one name-value pair
+/// per line as follows:
+///
+/// id_type=<id type>
+/// client=<id str>
+/// subnet=<subnet str>
+/// registered=<is registered>"
+///
+/// where:
+/// <id type> text label of the id type: "HW_ADDR" or "DUID"
+/// <id str> user's id formatted as either isc::dhcp::Hwaddr.toText() or
+/// isc::dhcp::DUID.toText()
+/// <subnet str> selected subnet formatted as isc::dhcp::Subnet4::toText() or
+/// isc::dhcp::Subnet6::toText() as appropriate.
+/// <is registered> "yes" or "no"
+///
+/// Sample IPv4 entry would like this:
+///
+/// @code
+/// id_type=DUID
+/// client=00:01:00:01:19:ef:e6:3b:00:0c:01:02:03:04
+/// subnet=2001:db8:2::/64
+/// registered=yes
+/// id_type=duid
+/// @endcode
+///
+/// Sample IPv4 entry would like this:
+///
+/// @code
+/// id_type=DUID
+/// id_type=HW_ADDR
+/// client=hwtype=1 00:0c:01:02:03:05
+/// subnet=152.77.5.0/24
+/// registered=no
+/// @endcode
+///
+/// @param id_type_str text label identify the id type
+/// @param id_val_str text representation of the user id
+/// @param subnet_str text representation  of the selected subnet
+/// @param registered boolean indicating if the user is registered or not
+void generate_output_record(const std::string& id_type_str,
+                            const std::string& id_val_str,
+                            const std::string& addr_str,
+                            const bool& registered)
+{
+    user_chk_output << "id_type=" << id_type_str << std::endl
+                    << "client=" << id_val_str << std::endl
+                    << "addr=" << addr_str << std::endl
+                    << "registered=" << (registered ? "yes" : "no")
+                    << std::endl;
+
+    // @todo Flush is here to ensure output is immediate for demo purposes.
+    // Performance would generally dictate not using it.
+    flush(user_chk_output);
+}
+
+/// @brief Stringify the lease address or prefix IPv6 response packet
+std::string getV6AddrStr (Pkt6Ptr response) {
+    OptionPtr tmp = response->getOption(D6O_IA_NA);
+    if (tmp) {
+        return(getAddrStrIA_NA(tmp));
+    }
+
+    // IA_NA not there so try IA_PD
+    tmp = response->getOption(D6O_IA_PD);
+    if (!tmp) {
+        isc_throw (isc::BadValue, "Response has neither IA_NA nor IA_PD");
+    }
+
+    return(getAddrStrIA_PD(tmp));
+}
+
+/// @brief Stringify the lease address in an D6O_IA_NA option set
+/// @todo fill out this out
+std::string getAddrStrIA_NA(OptionPtr options) {
+    boost::shared_ptr<Option6IA> ia =
+        boost::dynamic_pointer_cast<Option6IA>(options);
+
+    if (!ia) {
+        isc_throw (isc::BadValue, "D6O_IA_NA option invalid");
+    }
+
+    // If status indicates a failure return a blank string.
+    if (!checkIAStatus(ia)) {
+        return (std::string(""));
+    }
+
+    options = ia->getOption(D6O_IAADDR);
+    if (!options) {
+        isc_throw (isc::BadValue, "D6O_IAADDR option missing");
+    }
+
+    boost::shared_ptr<Option6IAAddr> addr_option;
+    addr_option  = boost::dynamic_pointer_cast<Option6IAAddr>(options);
+    if (!addr_option) {
+        isc_throw (isc::BadValue, "D6O_IAADDR Option6IAAddr missing");
+    }
+
+    isc::asiolink::IOAddress addr = addr_option->getAddress();
+    return (addr.toText());
+}
+
+/// @brief Stringify the delegated prefix in an D6O_IA_DP option set
+std::string getAddrStrIA_PD(OptionPtr options) {
+    boost::shared_ptr<Option6IA> ia =
+        boost::dynamic_pointer_cast<Option6IA>(options);
+
+    if (!ia) {
+        isc_throw (isc::BadValue, "D6O_IA_PD option invalid");
+    }
+
+    // If status indicates a failure return a blank string.
+    if (!checkIAStatus(ia)) {
+        return (std::string(""));
+    }
+
+    options = ia->getOption(D6O_IAPREFIX);
+    if (!options) {
+        isc_throw(isc::BadValue, "D60_IAPREFIX option is missing");
+    }
+
+    boost::shared_ptr<Option6IAPrefix> addr_option;
+    addr_option = boost::dynamic_pointer_cast<Option6IAPrefix>(options);
+    if (!addr_option) {
+        isc_throw (isc::BadValue, "D6O_IA_PD addr option bad");
+    }
+
+    isc::asiolink::IOAddress addr = addr_option->getAddress();
+    uint8_t prefix_len = addr_option->getLength();
+
+    stringstream buf;
+    buf << addr.toText() << "/" << static_cast<int>(prefix_len);
+    return (buf.str());
+}
+
+/// @brief Tests given IA option set for successful status.
+/// @todo fill out this out
+bool checkIAStatus(boost::shared_ptr<Option6IA>& ia) {
+    OptionCustomPtr status =
+            boost::dynamic_pointer_cast
+                <OptionCustom>(ia->getOption(D6O_STATUS_CODE));
+
+   // If a non-zero status is present, bail.
+   if (status) {
+        int status_val = status->readInteger<uint16_t>(0);
+        if (status_val != 0) {
+            std::cout << "SKIPPING PACKET STATUS is not success:"
+                      << status_val << std::endl;
+            return (false);
+        }
+    }
+
+    return (true);
+}
+
+
 } // end extern "C"



More information about the bind10-changes mailing list