<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
body {
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        padding:1em;
        margin:auto;
        background:#fefefe;
}

h1, h2, h3, h4, h5, h6 {
        font-weight: bold;
}

h1 {
        color: #000000;
        font-size: 28pt;
}

h2 {
        border-bottom: 1px solid #CCCCCC;
        color: #000000;
        font-size: 24px;
}

h3 {
        font-size: 18px;
}

h4 {
        font-size: 16px;
}

h5 {
        font-size: 14px;
}

h6 {
        color: #777777;
        background-color: inherit;
        font-size: 14px;
}

hr {
        height: 0.2em;
        border: 0;
        color: #CCCCCC;
        background-color: #CCCCCC;
    display: inherit;
}

p, blockquote, ul, ol, dl, li, table, pre {
        margin: 15px 0;
}

a, a:visited {
        color: #4183C4;
        background-color: inherit;
        text-decoration: none;
}

#message {
        border-radius: 6px;
        border: 1px solid #ccc;
        display:block;
        width:100%;
        height:60px;
        margin:6px 0px;
}

button, #ws {
        font-size: 12 pt;
        padding: 4px 6px;
        border-radius: 5px;
        border: 1px solid #bbb;
        background-color: #eee;
}

code, pre, #ws, #message {
        font-family: Monaco;
        font-size: 10pt;
        border-radius: 3px;
        background-color: #F8F8F8;
        color: inherit;
}

code {
        border: 1px solid #EAEAEA;
        margin: 0 2px;
        padding: 0 5px;
}

pre {
        border: 1px solid #CCCCCC;
        overflow: auto;
        padding: 4px 8px;
}

pre > code {
        border: 0;
        margin: 0;
        padding: 0;
}

#ws { background-color: #f8f8f8; }


.bloop_markdown table {
border-collapse: collapse;  
font-family: Helvetica, arial, freesans, clean, sans-serif;  
color: rgb(51, 51, 51);  
font-size: 15px; line-height: 25px;
padding: 0; }

.bloop_markdown table tr {
border-top: 1px solid #cccccc;
background-color: white;
margin: 0;
padding: 0; }
     
.bloop_markdown table tr:nth-child(2n) {
background-color: #f8f8f8; }

.bloop_markdown table tr th {
font-weight: bold;
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }

.bloop_markdown table tr td {
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }

.bloop_markdown table tr th :first-child, table tr td :first-child {
margin-top: 0; }

.bloop_markdown table tr th :last-child, table tr td :last-child {
margin-bottom: 0; }

.bloop_markdown blockquote{
  border-left: 4px solid #dddddd;
  padding: 0 15px;
  color: #777777; }
  blockquote > :first-child {
    margin-top: 0; }
  blockquote > :last-child {
    margin-bottom: 0; }

code, pre, #ws, #message {
    word-break: normal;
    word-wrap: normal;
}

hr {
    display: inherit;
}

.bloop_markdown :first-child {
    -webkit-margin-before: 0;
}

code, pre, #ws, #message {
    font-family: Menlo, Consolas, Liberation Mono, Courier, monospace;
}


.send { color:#77bb77; }
.server { color:#7799bb; }
.error { color:#AA0000; }</style>
</head>
<body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">
<div class="bloop_markdown">
<p>Thanks. I’ll keep that in mind. It may be that the systemd service file is not quite right. But I’m just getting started with RHEL7, and systemd as a result, so I could be wrong.</p>
<p></p>
</div>
<div class="bloop_original_html"><style>body{font-family:Helvetica,Arial;font-size:13px}</style>
<div id="bloop_customfont" style="font-family:Helvetica,Arial;font-size:13px; color: rgba(0,0,0,1.0); margin: 0px; line-height: auto;">
<br>
</div>
<br>
<div id="bloop_sign_1486568011004379904" class="bloop_sign"></div>
<div class="airmail_ext_on" style="color:black"><br>
From: <span style="color:black">Bryan Perry</span> <a href="mailto:bryan@sfcn.org">
<bryan@sfcn.org></a><br>
Date: <span style="color:black">February 8, 2017 at 10:21:37 AM</span><br>
To: <span style="color:black">kea-users@lists.isc.org</span> <a href="mailto:kea-users@lists.isc.org">
<kea-users@lists.isc.org></a><br>
Subject: <span style="color:black"> Re: [Kea-users] Select subnet based on reservation?
<br>
</span></div>
<br>
<blockquote type="cite" class="clean_bq"><span>
<div>
<div></div>
<div>CentOS Linux release 7.2.1511 (Core)<br>
<br>
On 2/8/2017 8:20 AM, James Sumners wrote:<br>
> Hmm. CentOS 6 or 7? If 7, systemd (ugh) should be respawning it when it<br>
> dies.<br>
><br>
><br>
><br>
><br>
> From: Bryan Perry <bryan@sfcn.org> <mailto:bryan@sfcn.org><br>
> Date: February 8, 2017 at 10:18:20 AM<br>
> To: kea-users@lists.isc.org <kea-users@lists.isc.org><br>
> <mailto:kea-users@lists.isc.org><br>
> Subject: Re: [Kea-users] Select subnet based on reservation?<br>
><br>
>> James,<br>
>><br>
>> Since getting this library functional in May I have had roughly 6 to 8<br>
>> instances where the Kea process just dies and goes away. I am not sure<br>
>> why or if it is an issue with my library, kea itself or the CentOS<br>
>> machine it's running on. After the first two instances of this happening<br>
>> I wrote a simple script that is run as a cron job that checks Kea every<br>
>> minute and if it has died restarts it. That was the stability problem.<br>
>><br>
>> On the shared subnet handling I have another scalability challenge in my<br>
>> network. The upstream router that is acting as my DHCP relay will always<br>
>> send the client request from its primary IP address. This even killed<br>
>> regular DHCP lease responses from a second subnet since the request came<br>
>> from the first subnet ID. In order to get around this I had to enable a<br>
>> feature of that router that would try sending the DHCP requests from<br>
>> each secondary IP address after a DHCP request failure on the primary<br>
>> address. This works, but takes several seconds for the failure on the<br>
>> primary and then the request on the secondary. The time delay gets<br>
>> longer and longer the more subnets it has to get failures on while its<br>
>> going down the list. That's a painful delay trying to get an IP address<br>
>> on the network if you are in a subnet further down the list.<br>
>><br>
>> The last requirement I have that has also been handled via the library I<br>
>> wrote for Kea has been logging lease assignments to a database for<br>
>> historical purposes (summons, subpoenas, etc.).<br>
>><br>
>> Basically, until the shared subnet functionality works in Kea the way it<br>
>> does in DHCPD I don't really have a choice but to use DHCPD and put<br>
>> lease reservations for my static customers in the config file. Once upon<br>
>> a time I was also able to use DHCPD's 'on commit' functionality to write<br>
>> lease information to a database for historical tracking. I'll have to<br>
>> resurrect that as well.<br>
>><br>
>> Good luck,<br>
>> Bryan<br>
>><br>
>> On 2/8/2017 7:46 AM, James Sumners wrote:<br>
>> > Thank you Bryan for chiming in. That is exactly what I am thinking of<br>
>> > doing, and your code is a big help. I was just hoping to have a Kea API<br>
>> > for accessing the database instead of doing it directly.<br>
>> ><br>
>> > What issues have you found that have lead you to conclude it is too<br>
>> > unstable?<br>
>> ><br>
>> ><br>
>> ><br>
>> ><br>
>> > On February 8, 2017 at 9:38:18 AM, Bryan Perry (bryan@sfcn.org<br>
>> > <mailto:bryan@sfcn.org>) wrote:<br>
>> ><br>
>> >> Hi James,<br>
>> >><br>
>> >> At the risk of re-hashing this topic for everyone again... What you are<br>
>> >> facing is a very unfortunate shortcoming of Kea's ability to deal with<br>
>> >> shared subnets that I hope they solve in the future. I faced the same<br>
>> >> issue and took the approach of writing a custom library that uses Kea's<br>
>> >> hooks and intercepted the DHCP Discover, queried the database for lease<br>
>> >> reservations matching the MAC address and if found, changed the subnet<br>
>> >> ID to the correct ID and handed it back to Kea for processing.<br>
>> >><br>
>> >> So yes, it can be done, but it is not trivial and very specific to your<br>
>> >> own implementation. I am running Kea this way now, but this hasn't been<br>
>> >> the most stable approach. This along with a few other issues related to<br>
>> >> shared subnet scenarios are unfortunately going to require that I move<br>
>> >> back to the standard ISC DHCPD.<br>
>> >><br>
>> >> I am pasting below some of my final correspondence with a couple of the<br>
>> >> more knowledgeable Kea folks back in May when I got this running. The<br>
>> >> code I used to compile my library is also pasted in case it helps you<br>
>> >> see just how cumbersome of a task this was, or otherwise helps you in<br>
>> >> your project. It is certainly not anything I am an expert on or can<br>
>> >> provide technical support for, sorry, but I hope it helps.<br>
>> >><br>
>> >> -Bryan<br>
>> >><br>
>> >><br>
>> >><br>
>> >><br>
>> >><br>
>> >><br>
>> >><br>
>> >><br>
>> >> Thomas, Marcin,<br>
>> >><br>
>> >> With your help I have been able to get this working exactly as I needed<br>
>> >> it to. The subnet4_select callout checks my hosts table for a static<br>
>> >> reservation and, if found, updates the assigned subnet ID. Kea then<br>
>> >> picks up processing with the new subnet ID and can successfully assign<br>
>> >> the correct static IP address to the client.<br>
>> >><br>
>> >> Although it's surely not the most elegant, I will paste in my code below<br>
>> >> in case it is helpful for anyone else dealing with shared subnets and<br>
>> >> static reservations. If you see anything wrong with the code or problems<br>
>> >> I may cause, I'm always open to feedback, but it seems to be working<br>
>> >> great right now.<br>
>> >><br>
>> >> I also had the requirements to write some basic info out to a more human<br>
>> >> readable log as well as writing all IP address assignments out to a<br>
>> >> completely different database for required lease history tracking. I<br>
>> >> used the lease4_select callout for the lease history storage. I'll paste<br>
>> >> that code as well in case it's of any use to anyone else.<br>
>> >><br>
>> >> Hopefully later versions of Kea will have some of this functionality<br>
>> >> built in.<br>
>> >><br>
>> >> Thanks again for all your help. I couldn't have got this working without<br>
>> >> you guys.<br>
>> >><br>
>> >> -Bryan<br>
>> >><br>
>> >><br>
>> >><br>
>> >><br>
>> >><br>
>> >><br>
>> >><br>
>> >> // subnet4_select.cc<br>
>> >><br>
>> >> #include <hooks/hooks.h><br>
>> >> #include <dhcp/pkt4.h><br>
>> >> #include <dhcpsrv/subnet.h><br>
>> >> #include <dhcpsrv/mysql_connection.h><br>
>> >> #include <algorithm/string.hpp><br>
>> >> #include "library_common.h"<br>
>> >> #include <string><br>
>> >><br>
>> >> using namespace isc::dhcp;<br>
>> >> using namespace isc::hooks;<br>
>> >> using namespace std;<br>
>> >><br>
>> >> // Define a structure for the mysql connection instance<br>
>> >> struct connection_details {<br>
>> >> const char *server;<br>
>> >> const char *user;<br>
>> >> const char *password;<br>
>> >> const char *database;<br>
>> >> };<br>
>> >><br>
>> >> MYSQL_RES *Result; // The mysql query results set variable<br>
>> >><br>
>> >> // A function to establish the mysql connection<br>
>> >> MYSQL* mysql_connection_setup2(struct connection_details<br>
>> >> mysql_details) {<br>
>> >> // Create a mysql instance and initialize the variables<br>
>> >> MYSQL *connection = mysql_init(NULL);<br>
>> >><br>
>> >> // Connect to the database with the details in the connection<br>
>> >> instance<br>
>> >> if (!mysql_real_connect(connection,mysql_details.server,<br>
>> >> mysql_details.user, mysql_details.password, mysql_details.database, 0,<br>
>> >> NULL, 0)) {<br>
>> >> printf("Conection error : %s\n", mysql_error(connection));<br>
>> >> //exit(1);<br>
>> >> }<br>
>> >> return connection;<br>
>> >> }<br>
>> >><br>
>> >> // A function to run the query and return the results set<br>
>> >> MYSQL_RES* mysql_perform_query2(MYSQL *connection, const char<br>
>> >> *sql_query) {<br>
>> >> // send the query to the database<br>
>> >> // cout << sql_query << " in function mysql_perform_query2" << endl;<br>
>> >> if (mysql_query(connection, sql_query))<br>
>> >> {<br>
>> >> printf("MySQL query error : %s\n", mysql_error(connection));<br>
>> >> // exit(1);<br>
>> >> }<br>
>> >> Result = mysql_store_result(connection);<br>
>> >> int RowsReturned = mysql_num_rows( Result );<br>
>> >> // cout << "NumRows in the function: " << RowsReturned << endl;<br>
>> >> // return mysql_use_result(connection);<br>
>> >> return Result;<br>
>> >> }<br>
>> >><br>
>> >> extern "C" {<br>
>> >><br>
>> >> // This callout is called at the "subnet4_select" hook.<br>
>> >> // We will intercept the request, check the MySQL hosts table<br>
>> >> // for reservations, and if found, set the correct subnet ID<br>
>> >><br>
>> >> int subnet4_select(CalloutHandle& handle) {<br>
>> >><br>
>> >> // A pointer to the packet is passed to the callout via a "boost" smart<br>
>> >> // pointer. The include file "pkt4.h" typedefs a pointer to the Pkt4<br>
>> >> // object as Pkt4Ptr. Retrieve a pointer to the object.<br>
>> >> Pkt4Ptr query4_ptr;<br>
>> >> handle.getArgument("query4", query4_ptr);<br>
>> >><br>
>> >> // Get a pointer to the subnet4 object<br>
>> >> Subnet4Ptr subnet4_ptr;<br>
>> >> handle.getArgument("subnet4", subnet4_ptr);<br>
>> >><br>
>> >> // Get the collection of subnets from the callout argument set<br>
>> >> const isc::dhcp::Subnet4Collection* subnets;<br>
>> >> handle.getArgument("subnet4collection", subnets);<br>
>> >><br>
>> >> // Get a pointer to the hardware address.<br>
>> >> HWAddrPtr hwaddr_ptr = query4_ptr->getHWAddr();<br>
>> >><br>
>> >> // Get the subnet ID from the initial request<br>
>> >> SubnetID subnetId = subnet4_ptr->getID();<br>
>> >><br>
>> >> // Exclude hardware type from hardware address string<br>
>> >> bool include_htype=false;<br>
>> >> string colonized_hwaddr = hwaddr_ptr->toText(include_htype);<br>
>> >><br>
>> >> // Strip colons from colonized_hwaddr to get hwaddr<br>
>> >> string hwaddr = colonized_hwaddr;<br>
>> >> boost::erase_all(hwaddr, ":");<br>
>> >><br>
>> >> // Define some variables we will use<br>
>> >> int newSubnetId = 0;<br>
>> >> string ipaddr = "BLANK";<br>
>> >> long RowsReturned;<br>
>> >><br>
>> >> // cout << hwaddr << " wants subnet " << subnetId << "\n";<br>
>> >> // Use a try...catch here to help prevent MySQL errors from killing<br>
>> >> the server.<br>
>> >> try {<br>
>> >> // Here is where we query the database and set new subnet ID if<br>
>> >> necessary<br>
>> >> MYSQL *conn2; // the connection<br>
>> >> MYSQL_RES *res2; // the results<br>
>> >> MYSQL_ROW row2; // the results row (line by line)<br>
>> >><br>
>> >> struct connection_details mysqlD2;<br>
>> >> mysqlD2.server = "localhost"; // where the mysql database is<br>
>> >> mysqlD2.user = "********"; // the root user of mysql<br>
>> >> mysqlD2.password = "********"; // the password of the root user<br>
>> >> in mysql<br>
>> >> mysqlD2.database = "********"; // the databse to pick<br>
>> >><br>
>> >> // Build the query string<br>
>> >> ostringstream ss2;<br>
>> >> ss2 << "select hex(dhcp_identifier), dhcp4_subnet_id,<br>
>> >> INET_NTOA(ipv4_address), host_id from hosts where hex(dhcp_identifier) =<br>
>> >> '" << hwaddr << "' limit 1";<br>
>> >> string ss2_str = ss2.str();<br>
>> >> const char *full_query2 = ss2_str.c_str();<br>
>> >><br>
>> >> // Connect to the mysql database<br>
>> >> conn2 = mysql_connection_setup2(mysqlD2);<br>
>> >><br>
>> >> // Assign the results returned to res2 if valid<br>
>> >> if (res2 = mysql_perform_query2(conn2, full_query2)) {<br>
>> >> // Get the number of rows in the results set. Should be 0 or 1<br>
>> >> int rCount = mysql_num_rows(res2);<br>
>> >> // If we got more than 0 rows in the results then we found a<br>
>> >> reservation for that client<br>
>> >> if (rCount > 0) {<br>
>> >> while ((row2 = mysql_fetch_row(res2)) !=NULL) {<br>
>> >> // Convert the subnet ID to an integer for use further on<br>
>> >> string input(row2[1]); stringstream SS(input); SS >><br>
>> >> newSubnetId;<br>
>> >> // Handle a NULL ipv4_address field<br>
>> >> if (row2[2]) {<br>
>> >> ipaddr = row2[2];<br>
>> >> } // end if<br>
>> >> // Log that we found a reservation<br>
>> >> leaselog << "Static reservation " << ipaddr << " found for<br>
>> >> " << row2[0] << " on row " << row2[3] << ", subnet " << row2[1] << endl;<br>
>> >> }<br>
>> >> } // end if<br>
>> >> // cout << "New subnet ID: " << newSubnetId << endl;<br>
>> >><br>
>> >> // Clean up the database result set<br>
>> >> mysql_free_result(res2);<br>
>> >><br>
>> >> // Clean up the database connectio<br>
>> >> mysql_close(conn2);<br>
>> >> } // end if<br>
>> >> else {<br>
>> >> // Throw an error if something went wrong in the mysql lookup<br>
>> >> leaselog << "MySQL query failed in lookup for " << hwaddr << " --<br>
>> >> Results processing skipped." << endl;<br>
>> >> } // end else<br>
>> >><br>
>> >> } catch (...) {<br>
>> >> // Throw an error if something more serious happened<br>
>> >> leaselog << "# ERR: Caught an error in subnet4_select.cc" << endl;<br>
>> >> }<br>
>> >><br>
>> >><br>
>> >><br>
>> >> // Next, if we have to change the subnet ID, we iterate through the<br>
>> >> collection<br>
>> >> // of subnets, looking for the ID we want and then set it.<br>
>> >> if ((newSubnetId != 0) && (subnetId != newSubnetId)) {<br>
>> >> for (int i = 0; i < subnets->size(); ++i) {<br>
>> >> Subnet4Ptr new_subnet = (*subnets)[i];<br>
>> >> if (new_subnet->getID() == newSubnetId) {<br>
>> >> // id matched so replace the selected subnet by<br>
>> >> // setting the "subnet4" callout argument with<br>
>> >> // the new subnet<br>
>> >> handle.setArgument("subnet4", new_subnet);<br>
>> >> break;<br>
>> >> }<br>
>> >> }<br>
>> >> }<br>
>> >><br>
>> >> flush(leaselog);<br>
>> >> return (0);<br>
>> >><br>
>> >> };<br>
>> >><br>
>> >> }<br>
>> >><br>
>> >><br>
>> >><br>
>> >><br>
>> >><br>
>> >><br>
>> >><br>
>> >><br>
>> >> // lease4_select.cc<br>
>> >><br>
>> >> #include <hooks/hooks.h><br>
>> >> #include <dhcp/pkt4.h><br>
>> >> #include <dhcpsrv/lease.h><br>
>> >> #include <dhcpsrv/mysql_connection.h><br>
>> >> #include "library_common.h"<br>
>> >> #include <string><br>
>> >><br>
>> >> using namespace isc::dhcp;<br>
>> >> using namespace isc::hooks;<br>
>> >> using namespace std;<br>
>> >><br>
>> >> // Define a structure for the mysql connection instance<br>
>> >> struct connection_details {<br>
>> >> const char *server;<br>
>> >> const char *user;<br>
>> >> const char *password;<br>
>> >> const char *database;<br>
>> >> };<br>
>> >><br>
>> >> // A function to establish the mysql connection<br>
>> >> MYSQL* mysql_connection_setup(struct connection_details<br>
>> >> mysql_details) {<br>
>> >> // first of all create a mysql instance and initialize the<br>
>> >> variables within<br>
>> >> MYSQL *connection = mysql_init(NULL);<br>
>> >><br>
>> >> // connect to the database with the details attached.<br>
>> >> if (!mysql_real_connect(connection,mysql_details.server,<br>
>> >> mysql_details.user, mysql_details.password, mysql_details.database, 0,<br>
>> >> NULL, 0)) {<br>
>> >> printf("Conection error : %s\n", mysql_error(connection));<br>
>> >> // exit(1);<br>
>> >> }<br>
>> >> return connection;<br>
>> >> }<br>
>> >><br>
>> >> // A function to run the query and return the results set<br>
>> >> MYSQL_RES* mysql_perform_query(MYSQL *connection, const char<br>
>> >> *sql_query) {<br>
>> >> // send the query to the database<br>
>> >> // cout << sql_query << " in function mysql_perform_query" << endl;<br>
>> >> if (mysql_query(connection, sql_query))<br>
>> >> {<br>
>> >> printf("MySQL query error : %s\n", mysql_error(connection));<br>
>> >> // exit(1);<br>
>> >> }<br>
>> >> return mysql_use_result(connection);<br>
>> >> }<br>
>> >><br>
>> >><br>
>> >> extern "C" {<br>
>> >><br>
>> >> // This callout is called at the "lease4_select" hook.<br>
>> >> int lease4_select(CalloutHandle& handle) {<br>
>> >><br>
>> >> // A pointer to the object is passed to the callout via a "boost" smart<br>
>> >> // pointer. The include file "lease.h" typedefs a pointer to the Lease4<br>
>> >> // object as Lease4Ptr. Retrieve a pointer to the object.<br>
>> >> Lease4Ptr lease4_ptr;<br>
>> >> handle.getArgument("lease4", lease4_ptr);<br>
>> >> bool isFake;<br>
>> >> handle.getArgument("fake_allocation", isFake);<br>
>> >><br>
>> >> // Get a pointer to the hardware address.<br>
>> >> HWAddrPtr hwaddr_ptr = lease4_ptr->hwaddr_;<br>
>> >><br>
>> >> string ipaddr = lease4_ptr->addr_.toText();<br>
>> >> int subnetId = lease4_ptr->subnet_id_;<br>
>> >><br>
>> >> bool include_htype=false;<br>
>> >> string hwaddr = hwaddr_ptr->toText(include_htype);<br>
>> >><br>
>> >> // If it is DHCPACK and not just DHCPOFFER, write to log and database<br>
>> >> if (!isFake) {<br>
>> >><br>
>> >> leaselog << "ASSIGNED: " << ipaddr << " to " << hwaddr << "<br>
>> >> subnetID " << subnetId << "\n";<br>
>> >><br>
>> >> // Use a try...catch here to help prevent MySQL errors from killing<br>
>> >> the server.<br>
>> >> try {<br>
>> >> // Here is where we query the database and set new subnet ID if<br>
>> >> necessary<br>
>> >> MYSQL *conn; // the connection<br>
>> >> MYSQL_RES *res; // the results<br>
>> >> MYSQL_ROW row; // the results row (line by line)<br>
>> >><br>
>> >> struct connection_details mysqlD;<br>
>> >> mysqlD.server = "localhost"; // where the mysql database is<br>
>> >> mysqlD.user = "********"; // the root user of mysql<br>
>> >> mysqlD.password = "********"; // the password of the root user in<br>
>> >> mysql<br>
>> >> mysqlD.database = "********"; // the databse to pick<br>
>> >><br>
>> >> // connect to the mysql database<br>
>> >> conn = mysql_connection_setup(mysqlD);<br>
>> >><br>
>> >> // Build the query<br>
>> >> std::stringstream ss;<br>
>> >> ss << "INSERT INTO lease_history VALUES ('" << ipaddr << "', '" <<<br>
>> >> hwaddr << "', '" << subnetId << "')";<br>
>> >> const char *full_query = ss.str().c_str();<br>
>> >> // leaselog << full_query << endl;<br>
>> >><br>
>> >> // assign the results return to the MYSQL_RES pointer<br>
>> >> res = mysql_perform_query(conn, full_query);<br>
>> >><br>
>> >> // printf("MySQL Tables in mysql database:\n");<br>
>> >> // while ((row = mysql_fetch_row(res)) !=NULL)<br>
>> >> // printf("%s\n", row[0]);<br>
>> >><br>
>> >> /* clean up the database result set */<br>
>> >> mysql_free_result(res);<br>
>> >> /* clean up the database link */<br>
>> >> mysql_close(conn);<br>
>> >> } catch (...) {<br>
>> >> // Throw an error if something bad happened<br>
>> >> leaselog << "# ERR: Caught an error in lease4_select.cc" << endl;<br>
>> >> }<br>
>> >><br>
>> >><br>
>> >> } //End if (!isFake)<br>
>> >><br>
>> >> flush(leaselog);<br>
>> >> return (0);<br>
>> >> };<br>
>> >> }<br>
>> >><br>
>> >><br>
>> >><br>
>> >> On 2/8/2017 6:22 AM, James Sumners wrote:<br>
>> >> > Before I move on, would the following be available to a hook?:<br>
>> >> ><br>
>> >> > 1. The subnet identifiers for each configured subnet<br>
>> >> > 2. The database of host reservations<br>
>> >> ><br>
>> >> > Get Outlook for iOS <https://aka.ms/o0ukef><br>
>> >> ><br>
>> >> > ------------------------------------------------------------------------<br>
>> >> > *From:* Tomek Mrugalski <tomasz@isc.org><br>
>> >> > *Sent:* Tuesday, February 7, 2017 3:39:01 PM<br>
>> >> > *To:* James Sumners; kea-users@lists.isc.org<br>
>> >> > *Subject:* Re: [Kea-users] Select subnet based on reservation?<br>
>> >> ><br>
>> >> > W dniu 07.02.2017 o 21:31, James Sumners pisze:<br>
>> >> >> 1.3? 1.2 is too far off. Sadly, I’m just going to have to go back to<br>
>> >> >> looking for alternatives. That’s a shame,<br>
>> >> > Sorry to hear that. We already have our plans for 1.2 and we can't add<br>
>> >> > new features less than 3 months before the release. The shared subnets<br>
>> >> > scenario is not a trivial feature to implement, as it affects the logic<br>
>> >> > in many places.<br>
>> >> ><br>
>> >> >> because I was really liking Kea.<br>
>> >> > Thanks for your kind words. I hope you'll take a look at Kea again some<br>
>> >> > time in the future.<br>
>> >> ><br>
>> >> > Tomek<br>
>> >> ><br>
>> >> ><br>
>> >> ><br>
>> >> ><br>
>> >> ><br>
>> >> > _______________________________________________<br>
>> >> > Kea-users mailing list<br>
>> >> > Kea-users@lists.isc.org<br>
>> >> > https://lists.isc.org/mailman/listinfo/kea-users<br>
>> >> ><br>
>> >> _______________________________________________<br>
>> >> Kea-users mailing list<br>
>> >> Kea-users@lists.isc.org<br>
>> >> https://lists.isc.org/mailman/listinfo/kea-users<br>
>> ><br>
>> _______________________________________________<br>
>> Kea-users mailing list<br>
>> Kea-users@lists.isc.org<br>
>> https://lists.isc.org/mailman/listinfo/kea-users<br>
><br>
_______________________________________________<br>
Kea-users mailing list<br>
Kea-users@lists.isc.org<br>
https://lists.isc.org/mailman/listinfo/kea-users<br>
</div>
</div>
</span></blockquote>
</div>
<div class="bloop_markdown">
<p></p>
</div>
</body>
</html>