Parcourir la source

[5272] lease4-add, lease6-add implemented

Tomek Mrugalski il y a 7 ans
Parent
commit
92280f3da1

+ 4 - 0
src/hooks/dhcp/lease_cmds/.gitignore

@@ -0,0 +1,4 @@
+/lease_cmds_messages.cc
+/lease_cmds_messages.h
+/s-messages
+/html

+ 112 - 69
src/hooks/dhcp/lease_cmds/lease_cmds.cc

@@ -57,7 +57,7 @@ public:
         TYPE_HWADDR,  ///< query by hardware address (v4 only)
         TYPE_DUID     ///< query by DUID (v6 only)
     } Type;
-    
+
     /// @brief Specifies subnet-id (always used)
     SubnetID subnet_id;
 
@@ -71,13 +71,31 @@ public:
     /// @brief Specifies identifier value (used when query_by_addr is false)
     isc::dhcp::DuidPtr duid;
 
+    static Type txtToType(const std::string& txt) {
+        if (txt == "address") {
+            return (Parameters::TYPE_ADDR);
+        } else if (txt == "hw-address") {
+            return (Parameters::TYPE_HWADDR);
+        } else if (txt == "duid") {
+            return (Parameters::TYPE_DUID);
+        } else {
+            isc_throw(BadValue, "Incorrect identifier type: "
+                      << txt << ", the only supported values are: "
+                      "address, hw-address, duid");
+        }
+    }
+
     /// @brief specifies parameter types (true = query by address, false =
     ///         query by indetifier-type,identifier)
     Type query_type;
 
+    Lease::Type lease_type;
+
+    uint32_t iaid;
+
     /// @brief Default contstructor.
     Parameters()
-        :addr("::"), query_type(TYPE_ADDR) {
+        :addr("::"), query_type(TYPE_ADDR), lease_type(Lease::TYPE_NA), iaid(0) {
     }
 };
 
@@ -135,8 +153,8 @@ private:
     ///         "valid-lft": 3600,
     ///         "expire": 1499282530,
     ///         "subnet-id": 1,
-    ///         "fdqn_fwd": true,
-    ///         "fqdn_rev": true,
+    ///         "fdqn-fwd": true,
+    ///         "fqdn-rev": true,
     ///         "hostname": "myhost.example.org",
     ///         "state": 0
     ///     }
@@ -236,6 +254,7 @@ private:
 };
 
 LeaseCmdsImpl::LeaseCmdsImpl() {
+    /// @todo: Remove family_
     family_ = CfgMgr::instance().getFamily();
 
     registerCommands();
@@ -311,32 +330,34 @@ LeaseCmdsImpl::leaseAddHandler(const std::string& name,
             isc_throw(isc::BadValue, "'lease' parameters must be specified");
         }
 
+        ConstSrvConfigPtr config = CfgMgr::instance().getCurrentCfg();
+
         Lease4Ptr lease4;
         Lease6Ptr lease6;
         if (v4) {
-            LeaseDataParser4 parser;
-            lease4 = parser.parse(lease_data);
+            Lease4Parser parser;
+            lease4 = parser.parse(config, lease_data);
 
-            checkLeaseIntegrity(lease4);
+            // checkLeaseIntegrity(config, lease4);
 
             if (lease4) {
-                LeaseMgrFactory::instance().add(lease4);
+                LeaseMgrFactory::instance().addLease(lease4);
             }
             
         } else {
-            LeaseDataParser6 parser;
-            lease6 = parser.parse(lease_data);
+            Lease6Parser parser;
+            lease6 = parser.parse(config, lease_data);
 
-            checkLeaseIntegrity(lease6);
+            // checkLeaseIntegrity(config, lease6);
 
             if (lease6) {
-                LeaseMgrFactory::instance().add(lease6);
+                LeaseMgrFactory::instance().addLease(lease6);
             }
         }
 
 
     } catch (const std::exception& ex) {
-        LOG_ERROR(lease_cmds_logger, LEASE_CMDS_RESERV_ADD_FAILED)
+        LOG_ERROR(lease_cmds_logger, v4 ? LEASE_CMDS_ADD4_FAILED : LEASE_CMDS_ADD6_FAILED)
             .arg(txt)
             .arg(ex.what());
         return (createAnswer(CONTROL_RESULT_ERROR, ex.what()));
@@ -366,15 +387,14 @@ LeaseCmdsImpl::getParameters(const ConstElementPtr& params) {
     }
     x.subnet_id = tmp->intValue();
 
-    tmp = params->get("ip-address");
-    ConstLeasePtr host;
+    tmp = params->get("address");
     if (tmp) {
         if (tmp->getType() != Element::string) {
-            isc_throw(BadValue, "'ip-address' is not a string.");
+            isc_throw(BadValue, "'address' is not a string.");
         }
 
         x.addr = IOAddress(tmp->stringValue());
-        x.query_by_addr = true;
+        x.query_type = Parameters::TYPE_ADDR;
         return (x);
     }
 
@@ -394,32 +414,29 @@ LeaseCmdsImpl::getParameters(const ConstElementPtr& params) {
     }
 
     // Got the parameters. Let's see if their values make sense.
-
-    // Try to parse the identifier value first.
-    try {
-        x.ident = util::str::quotedStringToBinary(ident->stringValue());
-        if (x.ident.empty()) {
-            util::str::decodeFormattedHexString(ident->stringValue(),
-                                                x.ident);
-        }
-    } catch (...) {
-        // The string doesn't match any known pattern, so we have to
-        // report an error at this point.
-        isc_throw(BadValue, "Unable to parse 'identifier' value.");
+    // Try to convert identifier-type
+    x.query_type = Parameters::txtToType(type->stringValue());
+
+    switch (x.query_type) {
+    case Parameters::TYPE_HWADDR: {
+        HWAddr hw = HWAddr::fromText(ident->stringValue());
+        x.hwaddr = HWAddrPtr(new HWAddr(hw));
+        break;
     }
-
-    if (x.ident.empty()) {
-        isc_throw(BadValue, "Unable to query for empty 'identifier'.");
+    case Parameters::TYPE_DUID: {
+        DUID duid = DUID::fromText(ident->stringValue());
+        x.duid = DuidPtr(new DUID(duid));
+    }
+    case Parameters::TYPE_ADDR: {
+        // We should never get here. The address clause should have been caught
+        // earlier.
+        return (x);
+    }
+    default: {
+        isc_throw(BadValue, "Identifier type " << type->stringValue() <<
+                  " is not supported.");
     }
-
-    // Next, try to convert identifier-type
-    try {
-        x.type = Lease::getIdentifierType(type->stringValue());
-    } catch (const std::exception& ex) {
-        isc_throw(BadValue, "Value of 'identifier-type' was not recognized.");
     }
-
-    x.query_by_addr = false;
     return (x);
 }
 
@@ -433,77 +450,93 @@ LeaseCmdsImpl::leaseGetHandler(const std::string& name, ConstElementPtr params)
         p = getParameters(params);
 
         switch (p.query_type) {
-        case TYPE_ADDR: {
+        case Parameters::TYPE_ADDR: {
             // Query by address
             if (v4) {
-                lease4 = LeaseMgr::instance().getLease4(p.subnet_id, p.addr);
+                lease4 = LeaseMgrFactory::instance().getLease4(p.addr);
             } else {
-                lease6 = LeaseMgr::instance().getLease6(p.subnet_id, p.addr);
+                lease6 = LeaseMgrFactory::instance().getLease6(p.lease_type, p.addr);
             }
             break;
         }
-        case TYPE_HWADDR:
+        case Parameters::TYPE_HWADDR:
             if (v4) {
-                lease4 = LeaseMgr::instance().getLease4(p.subnet_id, p.hwaddr);
+                if (!p.hwaddr) {
+                    return (createAnswer(CONTROL_RESULT_ERROR,
+                                         "Program error: Query by hw-address "
+                                         "requires hwaddr to be specified"));
+                }
+                lease4 = LeaseMgrFactory::instance().getLease4(*p.hwaddr, p.subnet_id);
             } else {
                 return (createAnswer(CONTROL_RESULT_ERROR,
                                      "Query by hw-address is not allowed in v6."));
             }
-        case TYPE_DUID:
-            if (v6) {
-                lease6 = LeaseMgr::instance().getLease6(p.subnet_id, p.duid);
+        case Parameters::TYPE_DUID:
+            if (!v4) {
+                if (!p.duid) {
+                    return (createAnswer(CONTROL_RESULT_ERROR,
+                                         "Program error: Query by duid "
+                                         "requires duid to be specified"));
+                }
+                lease6 = LeaseMgrFactory::instance().getLease6(p.lease_type, *p.duid,
+                                                               p.iaid, p.subnet_id);
             } else {
                 return (createAnswer(CONTROL_RESULT_ERROR,
                                      "Query by duid is not allowed in v4."));
             }
-        default:
-            return (createAnswer(CONTROL_RESULT_ERROR,
-                                 "Unknown query type: " << static_cast<int>(p.query_type)));
+        default: {
+            stringstream tmp;
+            tmp << "Unknown query type: " << static_cast<int>(p.query_type);
+            return (createAnswer(CONTROL_RESULT_ERROR, tmp.str()));
+        }
         }
     } catch (const std::exception& ex) {
-        return (createAnswer(CONTROL_RESULT_ERROR,
-                             "Failure during leaseX-get: " << ex.what()));
+        stringstream tmp;
+        tmp << "Failure during leaseX-get: " << ex.what();
+        return (createAnswer(CONTROL_RESULT_ERROR, tmp.str()));
     }
 
     ElementPtr lease_json;
     if (v4 && lease4) {
-        lease_json = lease4->toElement4();
+        lease_json = lease4->toElement();
+        return (createAnswer(CONTROL_RESULT_SUCCESS, "DHCPv4 lease found.", lease_json));
     }
     if (!v4 && lease6) {
-        lease_json = lease6->toElement6();
+        lease_json = lease6->toElement();
+        return (createAnswer(CONTROL_RESULT_SUCCESS, "DHCPv6 lease found.", lease_json));
         
     }
-    if (lease) {
-        return (createAnswer(CONTROL_RESULT_SUCCESS, "Lease found.", lease_json));
-    } else {
-        return (createAnswer(CONTROL_RESULT_SUCCESS, "Lease not found."));
-    }
+
+    // If we got here, the lease has not been found.
+    return (createAnswer(CONTROL_RESULT_EMPTY, "Lease not found."));
 }
 
 ConstElementPtr
-LeaseCmdsImpl::reservationDelHandler(const std::string& /*name*/,
-                                    ConstElementPtr params) {
+LeaseCmdsImpl::leaseDelHandler(const std::string& name,
+                               ConstElementPtr params) {
     Parameters p;
-    bool deleted;
+    bool deleted = false;
+#if 0    
     try {
         p = getParameters(params);
 
         if (p.query_by_addr) {
             // try to delete by address
-            deleted = LeaseMgr::instance().del(p.subnet_id, p.addr);
+            deleted = LeaseMgrFactory::instance().del(p.subnet_id, p.addr);
         } else {
             // try to delete by identifier
             if (family_ == AF_INET) {
-                deleted = LeaseMgr::instance().del4(p.subnet_id, p.type,
-                                                   &p.ident[0], p.ident.size());
+                deleted = LeaseMgrFactory::instance().del4(p.subnet_id, p.type,
+                                                           &p.ident[0], p.ident.size());
             } else {
-                deleted = LeaseMgr::instance().del6(p.subnet_id, p.type,
-                                                   &p.ident[0], p.ident.size());
+                deleted = LeaseMgrFactory::instance().del6(p.subnet_id, p.type,
+                                                           &p.ident[0], p.ident.size());
             }
         }
     } catch (const std::exception& ex) {
         return (createAnswer(CONTROL_RESULT_ERROR, ex.what()));
     }
+#endif
 
     if (deleted) {
         return (createAnswer(CONTROL_RESULT_SUCCESS, "Lease deleted."));
@@ -513,8 +546,18 @@ LeaseCmdsImpl::reservationDelHandler(const std::string& /*name*/,
     }
 }
 
+ConstElementPtr
+LeaseCmdsImpl::leaseUpdateHandler(const string& command, ConstElementPtr args) {
+    return (createAnswer(CONTROL_RESULT_ERROR, "not implemented yet."));
+}
+
+ConstElementPtr
+LeaseCmdsImpl::leaseWipeHandler(const string& command, ConstElementPtr args) {
+    return (createAnswer(CONTROL_RESULT_ERROR, "not implemented yet."));
+}
+
+
 uint16_t LeaseCmdsImpl::family_ = AF_INET;
-LeaseDataSourcePtr LeaseCmdsImpl::db_storage_;
 
 LeaseCmds::LeaseCmds()
     :impl_(new LeaseCmdsImpl()) {

+ 2 - 2
src/hooks/dhcp/lease_cmds/lease_cmds_messages.mes

@@ -18,11 +18,11 @@ the log message.
 This info message indicates that the Lease Commands hooks library has been
 removed successfully.
 
-% LEASE_CMDS_ADD4_FAILED Lease4-add command failed (parameters: %1, reason: %2)
+% LEASE_CMDS_ADD4_FAILED lease4-add command failed (parameters: %1, reason: %2)
 The lease4-add command has failed. Both the reason as well as the
 parameters passed are logged.
 
-% LEASE_CMDS_ADD6_FAILED Lease4-add command failed (parameters: %1, reason: %2)
+% LEASE_CMDS_ADD6_FAILED Lease6-add command failed (parameters: %1, reason: %2)
 The lease6-add command has failed. Both the reason as well as the
 parameters passed are logged.
 

+ 234 - 6
src/hooks/dhcp/lease_cmds/lease_parser.cc

@@ -4,14 +4,242 @@
 // License, v. 2.0. If a copy of the MPL was not distributed with this
 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+#include <cc/data.h>
+#include <dhcp/hwaddr.h>
+#include <asiolink/io_address.h>
+#include <dhcpsrv/lease.h>
+#include <lease_parser.h>
 
-// V4:
-// address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname,state
+#include <config.h>
 
-// V6:
-// address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,state
+using namespace std;
+using namespace isc::dhcp;
+using namespace isc::data;
+using namespace isc::asiolink;
 
-#include <config.h>
+// Can't use a constructor as a function
+namespace {
+IOAddress buildIOAddress(const std::string& str) { return (IOAddress(str)); }
+};
+
+namespace isc {
+namespace lease_cmds {
+
+IOAddress
+LeaseParser::getIOAddress(const ConstElementPtr& scope,
+                           const std::string& name) {
+    return (getAndConvert<IOAddress,
+            buildIOAddress>(scope, name, "address"));
+}
+
+Lease4Ptr
+Lease4Parser::parse(ConstSrvConfigPtr& cfg,
+                    const ConstElementPtr& lease_info) {
+    if (!lease_info) {
+        isc_throw(BadValue, "lease information missing");
+    }
+
+    // These are mandatory parameters.
+    IOAddress addr = getIOAddress(lease_info, "ip-address");
+    SubnetID subnet_id = getUint32(lease_info, "subnet-id");
+
+    if (!addr.isV4()) {
+        isc_throw(BadValue, "Non-IPv4 address specified: " << addr);
+    }
+
+    // Not a most straightforward conversion, but it works.
+    string hwaddr_txt = getString(lease_info, "hw-address");
+    HWAddr hwaddr = HWAddr::fromText(hwaddr_txt);
+    HWAddrPtr hwaddr_ptr = HWAddrPtr(new HWAddr(hwaddr));
+
+    Subnet4Ptr subnet = cfg->getCfgSubnets4()->getSubnet(subnet_id);
+    if (!subnet) {
+        isc_throw(BadValue, "Invalid subnet-id: No IPv4 subnet with subnet-id="
+                  << subnet_id << " currently configured.");
+    }
+
+    // Client-id is optional.
+    ClientIdPtr client_id;
+    if (lease_info->contains("client-id")) {
+        string txt = getString(lease_info, "client-id");
+        client_id = ClientId::fromText(txt);
+    }
+
+    // These parameters are optional. If not specified, we'll derive them from
+    // the current subnet configuration, if possible.
+    uint32_t valid_lft = 0;
+    if (lease_info->contains("valid-lft")) {
+        valid_lft = getUint32(lease_info, "valid-lft");
+    } else {
+        valid_lft = subnet->getValid();
+    }
+
+    /// Let's calculate client last transmission time (cltt). If expiration
+    /// timestamp is specified explicitly, we will use that. Note there are no
+    /// checks whether this is in the past. There may be valid cases when user
+    /// wants to insert expired leases, e.g. when migrating from one DHCP server
+    /// to another and wants to migrate the database as is, without disarding
+    /// any leases.
+    time_t cltt;
+    if (lease_info->contains("expire")) {
+        int64_t tmp = getUint32(lease_info, "expire");
+        cltt = static_cast<time_t>(tmp - valid_lft);
+    } else {
+        cltt = time(NULL);
+    }
+
+    bool fqdn_fwd = false;
+    if (lease_info->contains("fqdn-fwd")) {
+        fqdn_fwd = getBoolean(lease_info, "fqdn-fwd");
+    }
+    bool fqdn_rev = false;
+    if (lease_info->contains("fqdn-rev")) {
+        fqdn_rev = getBoolean(lease_info, "fqdn-rev");
+    }
+    string hostname;
+    if (lease_info->contains("hostname")) {
+        hostname = getString(lease_info, "hostname");
+    }
+    if (hostname.empty() && (fqdn_fwd || fqdn_rev)) {
+        isc_throw(BadValue, "No hostname specified and either forward or reverse"
+                  " fqdn was set to true.");
+    }
+
+    uint32_t state = 0;
+    if (lease_info->contains("state")) {
+        state = getUint8(lease_info, "state");
+    }
+
+    // Let's fabricate some data and we're ready to go.
+    uint32_t t1 = subnet->getT1();
+    uint32_t t2 = subnet->getT2();
+
+    Lease4Ptr l(new Lease4(addr, hwaddr_ptr, client_id, valid_lft, t1, t2,
+                           cltt, subnet_id,
+                           fqdn_fwd, fqdn_rev, hostname));
+    l->state_ = state;
+    return (l);
+}
+
+Lease6Ptr
+Lease6Parser::parse(ConstSrvConfigPtr& cfg,
+                    const ConstElementPtr& lease_info) {
+    if (!lease_info) {
+        isc_throw(BadValue, "lease information missing");
+    }
+
+    // These are mandatory parameters.
+    IOAddress addr = getIOAddress(lease_info, "ip-address");
+    SubnetID subnet_id = getUint32(lease_info, "subnet-id");
+
+    if (addr.isV4()) {
+        isc_throw(BadValue, "Non-IPv6 address specified: " << addr);
+    }
+
+    // Not a most straightforward conversion, but it works.
+    string duid_txt = getString(lease_info, "duid");
+    DUID duid = DUID::fromText(duid_txt);
+    DuidPtr duid_ptr = DuidPtr(new DUID(duid));
+
+    Subnet6Ptr subnet = cfg->getCfgSubnets6()->getSubnet(subnet_id);
+    if (!subnet) {
+        isc_throw(BadValue, "Invalid subnet-id: No IPv6 subnet with subnet-id="
+                  << subnet_id << " currently configured.");
+    }
+
+    Lease::Type type = Lease::TYPE_NA;
+    uint8_t prefix_len = 128;
+    if (lease_info->contains("type")) {
+        string txt = getString(lease_info, "type");
+        if (txt == "IA_NA") {
+            type = Lease::TYPE_NA;
+        } else if (txt == "IA_TA") {
+            type = Lease::TYPE_TA;
+        } else if (txt == "IA_PD") {
+            type = Lease::TYPE_PD;
+
+            prefix_len = getUint8(lease_info, "prefix-len");
+        } else {
+            isc_throw(BadValue, "Incorrect lease type: " << txt << ", the only "
+                      "supported values are: na, ta and pd");
+        }
+    }
+
+    uint32_t iaid = getUint32(lease_info, "iaid");
+
+    // Hw-address is optional in v6 leases.
+    HWAddrPtr hwaddr_ptr;
+    if (lease_info->contains("hw-address")) {
+        string hwaddr_txt = getString(lease_info, "hw-address");
+        HWAddr hwaddr = HWAddr::fromText(hwaddr_txt);
+        hwaddr_ptr = HWAddrPtr(new HWAddr(hwaddr));
+    }
+
+    // These parameters are optional. If not specified, we'll derive them
+    // from the current subnet configuration, if possible.
+    uint32_t valid_lft = 0;
+    if (lease_info->contains("valid-lft")) {
+        valid_lft = getUint32(lease_info, "valid-lft");
+    } else {
+        valid_lft = subnet->getValid();
+    }
+
+    // These parameters are optional. If not specified, we'll derive them
+    // from the current subnet configuration, if possible.
+    uint32_t pref_lft = 0;
+    if (lease_info->contains("preferred-lft")) {
+        pref_lft = getUint32(lease_info, "preferred-lft");
+    } else {
+        pref_lft = subnet->getValid();
+    }
+
+    /// Let's calculate client last transmission time (cltt). If expiration
+    /// timestamp is specified explicitly, we will use that. Note there are
+    /// no checks whether this is in the past. There may be valid cases when
+    /// user wants to insert expired leases, e.g. when migrating from one
+    /// DHCP server to another and wants to migrate the database as is, without
+    /// disarding any leases.
+    time_t cltt;
+    if (lease_info->contains("expire")) {
+        int64_t tmp = getUint32(lease_info, "expire");
+        cltt = static_cast<time_t>(tmp - valid_lft);
+    } else {
+        cltt = time(NULL);
+    }
+
+    bool fqdn_fwd = false;
+    if (lease_info->contains("fqdn-fwd")) {
+        fqdn_fwd = getBoolean(lease_info, "fqdn-fwd");
+    }
+    bool fqdn_rev = false;
+    if (lease_info->contains("fqdn-rev")) {
+        fqdn_rev = getBoolean(lease_info, "fqdn-rev");
+    }
+    string hostname;
+    if (lease_info->contains("hostname")) {
+        hostname = getString(lease_info, "hostname");
+    }
+    if (hostname.empty() && (fqdn_fwd || fqdn_rev)) {
+        isc_throw(BadValue, "No hostname specified and either forward or reverse"
+                  " fqdn was set to true.");
+    }
+
+    uint32_t state = 0;
+    if (lease_info->contains("state")) {
+        state = getUint8(lease_info, "state");
+    }
+
+    // Let's fabricate some data and we're ready to go.
+    uint32_t t1 = subnet->getT1();
+    uint32_t t2 = subnet->getT2();
 
+    Lease6Ptr l(new Lease6(type, addr, duid_ptr, iaid, pref_lft, valid_lft, t1, t2,
+                           subnet_id, fqdn_fwd, fqdn_rev, hostname,
+                           hwaddr_ptr, prefix_len));
+    l->cltt_ = cltt;
+    l->state_ = state;
+    return (l);
+}
 
-    
+};
+};

+ 74 - 6
src/hooks/dhcp/lease_cmds/lease_parser.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -10,28 +10,96 @@
 #include <cc/data.h>
 #include <cc/simple_parser.h>
 #include <dhcpsrv/lease.h>
+#include <dhcpsrv/srv_config.h>
 
 namespace isc {
 namespace lease_cmds {
 
-/// @brief Parser for a single Lease information.
+/// @brief Base class for Lease4 and Lease6 parsers
 class LeaseParser : public isc::data::SimpleParser {
+protected:
+
+    /// @brief Returns an address from JSON structure
+    ///
+    /// @param scope a map the element will be searched at
+    /// @param name key name to be searched for
+    /// @return IOAddress representation
+    isc::asiolink::IOAddress getIOAddress(const isc::data::ConstElementPtr& scope,
+                                          const std::string& name);
 };
 
+/// @brief Parser for Lease4 structure
+///
+/// It expects the data in the following format:
+/// {
+///     "ip-address": "192.0.2.1",
+///     "hw-address": "00:01:02:03:04:05",
+///     "client-id": "this-is-a-client",
+///     "valid-lft": 3600,
+///     "cltt": 12345678,
+///     "expire": 1499282530,
+///     "subnet-id": 1,
+///     "fdqn-fwd": true,
+///     "fqdn-rev": true,
+///     "hostname": "myhost.example.org",
+///     "state": 0
+/// }
 class Lease4Parser : public LeaseParser {
 public:
-    virtual isc::dhcp::Lease4Ptr parse(const isc::data::ConstElementPtr& lease_info);
+
+    /// @brief Parses Element tree and tries to convert to Lease4
+    ///
+    /// See @ref Lease6Parser class description for expected format.
+    ///
+    /// @param cfg Currently running config (used for sanity checks and defaults)
+    /// @param lease_info structure to be parsed
+    /// @return A pointer to Lease4
+    /// @throw BadValue if any of the parameters is invalid
+    /// @throw DhcpConfigError if mandatory parameter is missing
+    virtual isc::dhcp::Lease4Ptr parse(isc::dhcp::ConstSrvConfigPtr& cfg,
+                                       const isc::data::ConstElementPtr& lease_info);
+
+    /// @brief virtual dtor (does nothing)
     virtual ~Lease4Parser() {}
 };
 
+/// @brief Parser for Lease6 structure
+///
+/// {
+///     "address": "2001:db8::1",
+///     "duid": "00:01:02:03:04:05",
+///     "type": "IA_NA",
+///     "cltt": 12345678,
+///     "preferred-lft": 3600,
+///     "valid-lft": 3600,
+///     "expire": 1499282530,
+///     "subnet-id": 1,
+///     "fdqn-fwd": true,
+///     "fqdn-rev": true,
+///     "hostname": "myhost.example.org",
+///     "state": 0
+/// }
+
+/// It expects the input data to use the following format:
 class Lease6Parser : public LeaseParser {
 public:
-    virtual isc::dhcp::Lease6Ptr parse(const isc::data::ConstElementPtr& lease_info);
+    /// @brief Parses Element tree and tries to convert to Lease4
+    ///
+    /// See @ref Lease6Parser class description for expected format.
+    ///
+    /// @param cfg Currently running config (used for sanity checks and defaults)
+    /// @param lease_info structure to be parsed
+    /// @return A pointer to Lease4
+    /// @throw BadValue if any of the parameters is invalid
+    /// @throw DhcpConfigError if mandatory parameter is missing
+    virtual isc::dhcp::Lease6Ptr parse(isc::dhcp::ConstSrvConfigPtr& cfg,
+                                       const isc::data::ConstElementPtr& lease_info);
+
+    /// @brief virtual dtor (does nothing)
     virtual ~Lease6Parser() {}
 };
-    
+
 }; // end of isc::dhcp namespace
 }; // end of isc namespace
 
 #endif
-    

+ 5 - 0
src/hooks/dhcp/lease_cmds/tests/.gitignore

@@ -0,0 +1,5 @@
+host_cmds_unittests
+host_cmds_unittests.log
+host_cmds_unittests.trs
+test-suite.log
+*~

+ 17 - 0
src/hooks/dhcp/lease_cmds/version.cc

@@ -0,0 +1,17 @@
+// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+#include <hooks/hooks.h>
+
+extern "C" {
+
+/// @brief returns Kea hooks version.
+int version() {
+    return (KEA_HOOKS_VERSION);
+}
+
+}