summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--RELNOTES8
-rw-r--r--client/Makefile.am4
-rw-r--r--client/Makefile.in7
-rw-r--r--common/dns.c737
-rw-r--r--common/tests/Makefile.am4
-rw-r--r--common/tests/Makefile.in6
-rw-r--r--dhcpctl/Makefile.am6
-rw-r--r--dhcpctl/Makefile.in12
-rw-r--r--includes/dhcpd.h3
-rw-r--r--includes/omapip/isclib.h2
-rw-r--r--includes/site.h4
-rw-r--r--omapip/Makefile.am3
-rw-r--r--omapip/Makefile.in7
-rw-r--r--omapip/isclib.c56
-rw-r--r--relay/Makefile.am3
-rw-r--r--relay/Makefile.in6
-rw-r--r--server/Makefile.am4
-rw-r--r--server/Makefile.in7
-rw-r--r--server/tests/Makefile.am5
-rw-r--r--server/tests/Makefile.in5
-rw-r--r--util/bind.sh3
21 files changed, 847 insertions, 45 deletions
diff --git a/RELNOTES b/RELNOTES
index 5b4dbeb8..8e47c262 100644
--- a/RELNOTES
+++ b/RELNOTES
@@ -109,6 +109,14 @@ work on other platforms. Please report any problems and suggested fixes to
man page for a description.
[ISC-Bugs #19598]
+- When doing DDNS if there isn't an appropriate zone statement attempt
+ to find a reasoanble nameserver via a DNS resolver. This restores
+ some functionality that was lost in the transition to asynchronous
+ DDNS. Due to the lack of security and increase in fragility of the
+ system when using this feature we strongly recommend the use of
+ appropriate zone statements rather than using this functionality.
+ [ISC-Bugs #30461]
+
Changes since 4.2.5
- Address static analysis warnings.
diff --git a/client/Makefile.am b/client/Makefile.am
index 39ddf6f6..59364aa0 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -4,8 +4,8 @@ dhclient_SOURCES = clparse.c dhclient.c dhc6.c \
scripts/bsdos scripts/freebsd scripts/linux scripts/macos \
scripts/netbsd scripts/nextstep scripts/openbsd \
scripts/solaris scripts/openwrt
-dhclient_LDADD = ../common/libdhcp.a ../omapip/libomapi.a \
- ../bind/lib/libdns.a ../bind/lib/libisc.a
+dhclient_LDADD = ../common/libdhcp.a ../omapip/libomapi.a ../bind/lib/libirs.a \
+ ../bind/lib/libdns.a ../bind/lib/libisccfg.a ../bind/lib/libisc.a
man_MANS = dhclient.8 dhclient-script.8 dhclient.conf.5 dhclient.leases.5
EXTRA_DIST = $(man_MANS)
diff --git a/client/Makefile.in b/client/Makefile.in
index 6c39b326..8971e99b 100644
--- a/client/Makefile.in
+++ b/client/Makefile.in
@@ -98,7 +98,8 @@ am_dhclient_OBJECTS = clparse.$(OBJEXT) dhclient.$(OBJEXT) \
dhc6.$(OBJEXT)
dhclient_OBJECTS = $(am_dhclient_OBJECTS)
dhclient_DEPENDENCIES = ../common/libdhcp.a ../omapip/libomapi.a \
- ../bind/lib/libdns.a ../bind/lib/libisc.a
+ ../bind/lib/libirs.a ../bind/lib/libdns.a \
+ ../bind/lib/libisccfg.a ../bind/lib/libisc.a
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
@@ -294,8 +295,8 @@ dhclient_SOURCES = clparse.c dhclient.c dhc6.c \
scripts/netbsd scripts/nextstep scripts/openbsd \
scripts/solaris scripts/openwrt
-dhclient_LDADD = ../common/libdhcp.a ../omapip/libomapi.a \
- ../bind/lib/libdns.a ../bind/lib/libisc.a
+dhclient_LDADD = ../common/libdhcp.a ../omapip/libomapi.a ../bind/lib/libirs.a \
+ ../bind/lib/libdns.a ../bind/lib/libisccfg.a ../bind/lib/libisc.a
man_MANS = dhclient.8 dhclient-script.8 dhclient.conf.5 dhclient.leases.5
EXTRA_DIST = $(man_MANS)
diff --git a/common/dns.c b/common/dns.c
index 2bb3686b..2bb02710 100644
--- a/common/dns.c
+++ b/common/dns.c
@@ -157,9 +157,122 @@ typedef struct dhcp_ddns_rdata {
} dhcp_ddns_data_t;
#if defined (NSUPDATE)
+#if defined (DNS_ZONE_LOOKUP)
-void ddns_interlude(isc_task_t *, isc_event_t *);
+/*
+ * The structure used to find a nameserver if there wasn't a zone entry.
+ * Currently we assume we won't have many of these outstanding at any
+ * time so we go with a simple linked list.
+ * In use find_zone_start() will fill in the oname with the name
+ * requested by the DDNS code. zname will point to it and be
+ * advanced as labels are removed. If the DNS client code returns
+ * a set of name servers eventp and rdataset will be set. Then
+ * the code will walk through the nameservers in namelist and
+ * find addresses that are stored in addrs and addrs6.
+ */
+
+typedef struct dhcp_ddns_ns {
+ struct dhcp_ddns_ns *next;
+ struct data_string oname; /* the original name for DDNS */
+ char *zname; /* a pointer into the original name for
+ the zone we are checking */
+ dns_clientresevent_t *eventp; /* pointer to the event that provided the
+ namelist, we can't free the eventp
+ until we free the namelist */
+ dns_name_t *ns_name; /* current name server we are examining */
+ dns_rdataset_t *rdataset;
+ dns_rdatatype_t rdtype; /* type of address we want */
+
+ struct in_addr addrs[DHCP_MAXNS]; /* space for v4 addresses */
+ struct in6_addr addrs6[DHCP_MAXNS]; /* space for v6 addresses */
+ int num_addrs;
+ int num_addrs6;
+ int ttl;
+
+ void *transaction; /* transaction id for DNS calls */
+} dhcp_ddns_ns_t;
+
+/*
+ * The list of DDNS names for which we are attempting to find a name server.
+ * This list is used for finding the name server, it doesn't include the
+ * information necessary to do the DDNS request after finding a name server.
+ * The code attempts to minimize duplicate requests by examining the list
+ * to see if we are already trying to find a substring of the new request.
+ * For example imagine the first request is "a.b.c.d.e." and the server has
+ * already discarded the first two lables and is trying "c.d.e.". If the
+ * next request is for "x.y.c.d.e." the code assumes the in progress
+ * request is sufficient and doesn't add a new request for the second name.
+ * If the next request was for "x.y.z.d.e." the code doesn't assume they
+ * will use the same nameserver and starts a second request.
+ * This strategy will not eliminate all duplicates but is simple and
+ * should be sufficient.
+ */
+dhcp_ddns_ns_t *dns_outstanding_ns = NULL;
+
+/*
+ * Routines to manipulate the list of outstanding searches
+ *
+ * add_to_ns_queue() - adds the given control block to the queue
+ *
+ * remove_from_ns_queue() - removes the given control block from
+ * the queue
+ *
+ * find_in_ns_queue() compares the name from the given control
+ * block with the control blocks in the queue. It returns
+ * success if a matching entry is found. In order to match
+ * the entry already on the queue must be shorter than the
+ * incoming name must match the ending substring of the name.
+ */
+
+void
+add_to_ns_queue(dhcp_ddns_ns_t *ns_cb)
+{
+ ns_cb->next = dns_outstanding_ns;
+ dns_outstanding_ns = ns_cb;
+}
+
+
+void
+remove_from_ns_queue(dhcp_ddns_ns_t *ns_cb)
+{
+ dhcp_ddns_ns_t **foo;
+
+ foo = &dns_outstanding_ns;
+ while (*foo) {
+ if (*foo == ns_cb) {
+ *foo = ns_cb->next;
+ break;
+ }
+ foo = &((*foo)->next);
+ }
+ ns_cb->next = NULL;
+}
+
+isc_result_t
+find_in_ns_queue(dhcp_ddns_ns_t *ns_cb)
+{
+ dhcp_ddns_ns_t *temp_cb;
+ int in_len, temp_len;
+
+ in_len = strlen(ns_cb->zname);
+
+ for(temp_cb = dns_outstanding_ns;
+ temp_cb != NULL;
+ temp_cb = temp_cb->next) {
+ temp_len = strlen(temp_cb->zname);
+ if (temp_len > in_len)
+ continue;
+ if (strcmp(temp_cb->zname,
+ ns_cb->zname + (in_len - temp_len)) == 0)
+ return(ISC_R_SUCCESS);
+ }
+ return(ISC_R_NOTFOUND);
+}
+
+void cache_found_zone (dhcp_ddns_ns_t *);
+#endif
+void ddns_interlude(isc_task_t *, isc_event_t *);
#if defined (TRACING)
/*
@@ -437,6 +550,8 @@ trace_ddns_init()
#define ddns_update dns_client_startupdate
#endif /* TRACING */
+#define zone_resolve dns_client_startresolve
+
/*
* Code to allocate and free a dddns control block. This block is used
* to pass and track the information associated with a DDNS update request.
@@ -548,6 +663,21 @@ void tkey_free (ns_tsig_key **key)
}
#endif
+isc_result_t remove_dns_zone (struct dns_zone *zone)
+{
+ struct dns_zone *tz = NULL;
+
+ if (dns_zone_hash) {
+ dns_zone_hash_lookup(&tz, dns_zone_hash, zone->name, 0, MDL);
+ if (tz != NULL) {
+ dns_zone_hash_delete(dns_zone_hash, tz->name, 0, MDL);
+ dns_zone_dereference(&tz, MDL);
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
isc_result_t enter_dns_zone (struct dns_zone *zone)
{
struct dns_zone *tz = (struct dns_zone *)0;
@@ -594,7 +724,11 @@ isc_result_t dns_zone_lookup (struct dns_zone **zone, const char *name)
}
if (!dns_zone_hash_lookup (zone, dns_zone_hash, name, 0, MDL))
status = ISC_R_NOTFOUND;
- else
+ else if ((*zone)->timeout && (*zone)->timeout < cur_time) {
+ dns_zone_hash_delete(dns_zone_hash, (*zone)->name, 0, MDL);
+ dns_zone_dereference(zone, MDL);
+ status = ISC_R_NOTFOUND;
+ } else
status = ISC_R_SUCCESS;
if (tname)
@@ -654,6 +788,456 @@ int dns_zone_dereference (ptr, file, line)
}
#if defined (NSUPDATE)
+#if defined (DNS_ZONE_LOOKUP)
+
+/* Helper function to copy the address from an rdataset to
+ * the nameserver control block. Mostly to avoid really long
+ * lines in the nested for loops
+ */
+void
+zone_addr_to_ns(dhcp_ddns_ns_t *ns_cb,
+ dns_rdataset_t *rdataset)
+{
+ dns_rdata_t rdata;
+ dns_rdata_in_a_t a;
+ dns_rdata_in_aaaa_t aaaa;
+
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(rdataset, &rdata);
+ switch (rdataset->type) {
+ case dns_rdatatype_a:
+ (void) dns_rdata_tostruct(&rdata, &a, NULL);
+ memcpy(&ns_cb->addrs[ns_cb->num_addrs], &a.in_addr, 4);
+ ns_cb->num_addrs++;
+ dns_rdata_freestruct(&a);
+ break;
+ case dns_rdatatype_aaaa:
+ (void) dns_rdata_tostruct(&rdata, &aaaa, NULL);
+ memcpy(&ns_cb->addrs6[ns_cb->num_addrs6], &aaaa.in6_addr, 16);
+ ns_cb->num_addrs6++;
+ dns_rdata_freestruct(&aaaa);
+ break;
+ default:
+ break;
+ }
+
+ if ((ns_cb->ttl == 0) || (ns_cb->ttl > rdataset->ttl))
+ ns_cb->ttl = rdataset->ttl;
+}
+
+/*
+ * The following three routines co-operate to find the addresses of
+ * the nameservers to use for a zone if we don't have a zone statement.
+ * We strongly suggest the use of a zone statement to avoid problmes
+ * and to allow for the use of TSIG and therefore better security, but
+ * include this functionality for those that don't want such statements.
+ *
+ * find_zone_start(ddns_cb, direction)
+ * This is the first of the routines, it is called from the rest of
+ * the ddns code when we have received a request for DDNS for a name
+ * and don't have a zone entry that would cover that name. The name
+ * is in the ddns_cb as specified by the direction (forward or reverse).
+ * The start function pulls the name out and constructs the name server
+ * block then starts the process by calling the DNS client code.
+ *
+ * find_zone_ns(taskp, eventp)
+ * This is the second step of the process. The DNS client code will
+ * call this when it has gotten a response or timed out. If the response
+ * doesn't have a list of nameservers we remove another label from the
+ * zone name and try again. If the response does include a list of
+ * nameservers we start walking through the list attempting to get
+ * addresses for the nameservers.
+ *
+ * find_zone_addrs(taskp, eventp)
+ * This is the third step of the process. In find_zone_ns we got
+ * a list of nameserves and started walking through them. This continues
+ * the walk and if we get back any addresses it adds them to our list.
+ * When we get enough addresses or run out of nameservers we construct
+ * a zone entry and insert it into the zone hash for the rest of the
+ * DDNS code to use.
+ */
+void
+find_zone_addrs(isc_task_t *taskp,
+ isc_event_t *eventp)
+{
+ dns_clientresevent_t *ddns_event = (dns_clientresevent_t *)eventp;
+ dhcp_ddns_ns_t *ns_cb = (dhcp_ddns_ns_t *)eventp->ev_arg;
+ dns_name_t *ns_name = NULL;
+ dns_rdataset_t *rdataset;
+ isc_result_t result;
+ dns_name_t *name;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_ns_t ns;
+
+
+ /* the transaction is done, get rid of the tag */
+ dns_client_destroyrestrans(&ns_cb->transaction);
+
+ /* If we succeeded we try and extract the addresses, if we can
+ * and we have enough we are done. If we didn't succeed or
+ * we don't have enough addresses afterwards we drop through
+ * and try the next item on the list.
+ */
+ if (ddns_event->result == ISC_R_SUCCESS) {
+
+ for (name = ISC_LIST_HEAD(ddns_event->answerlist);
+ name != NULL;
+ name = ISC_LIST_NEXT(name, link)) {
+
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+
+ /* add address to cb */
+ zone_addr_to_ns(ns_cb, rdataset);
+
+ /* We are done if we have
+ * enough addresses
+ */
+ if (ns_cb->num_addrs +
+ ns_cb->num_addrs6 >= DHCP_MAXNS)
+ goto done;
+ }
+ }
+ }
+ }
+
+ /* We need more addresses.
+ * We restart the loop we were in before.
+ */
+
+ for (ns_name = ns_cb->ns_name;
+ ns_name != NULL;
+ ns_name = ISC_LIST_NEXT(ns_name, link)) {
+
+ if (ns_name == ns_cb->ns_name) {
+ /* first time through, use saved state */
+ rdataset = ns_cb->rdataset;
+ } else {
+ rdataset = ISC_LIST_HEAD(ns_name->list);
+ }
+
+ for (;
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+
+ if (rdataset->type != dns_rdatatype_ns)
+ continue;
+ dns_rdata_init(&rdata);
+
+ if (rdataset == ns_cb->rdataset) {
+ /* first time through use the saved state */
+ if (ns_cb->rdtype == dns_rdatatype_a) {
+ ns_cb->rdtype = dns_rdatatype_aaaa;
+ } else {
+ ns_cb->rdtype = dns_rdatatype_a;
+ if (dns_rdataset_next(rdataset) !=
+ ISC_R_SUCCESS)
+ continue;
+ }
+ } else {
+ if ((!dns_rdataset_isassociated(rdataset)) ||
+ (dns_rdataset_first(rdataset) !=
+ ISC_R_SUCCESS))
+ continue;
+ }
+
+ dns_rdataset_current(rdataset, &rdata);
+ if (dns_rdata_tostruct(&rdata, &ns, NULL) !=
+ ISC_R_SUCCESS)
+ continue;
+
+ /* Save our current state */
+ ns_cb->ns_name = ns_name;
+ ns_cb->rdataset = rdataset;
+
+ /* And call out to DNS */
+ result = zone_resolve(dhcp_gbl_ctx.dnsclient, &ns.name,
+ dns_rdataclass_in,
+ ns_cb->rdtype,
+ DNS_CLIENTRESOPT_NODNSSEC,
+ dhcp_gbl_ctx.task,
+ find_zone_addrs,
+ (void *)ns_cb,
+ &ns_cb->transaction);
+
+ /* do we need to clean this? */
+ dns_rdata_freestruct(&ns);
+
+ if (result == ISC_R_SUCCESS)
+ /* we have started the next step, cleanup
+ * the structures associated with this call
+ * but leave the cb for the next round
+ */
+ goto cleanup;
+
+ log_error("find_zone_ns: unable to continue "
+ "resolve: %s %s",
+ ns_cb->zname,
+ isc_result_totext(result));
+
+ /* The call to start a resolve transaction failed,
+ * should we try to continue with any other names?
+ * For now let's not, but let's use whatever we
+ * may already have.
+ */
+ goto done;
+ }
+ }
+
+ done:
+ /* we've either gotten our max number of addresses or
+ * run out of nameservers to try. Convert the cb into
+ * a zone and insert it into the zone hash. Then
+ * we need to clean up the saved state.
+ */
+ if ((ns_cb->num_addrs != 0) ||
+ (ns_cb->num_addrs6 != 0))
+ cache_found_zone(ns_cb);
+
+ dns_client_freeresanswer(dhcp_gbl_ctx.dnsclient,
+ &ns_cb->eventp->answerlist);
+ isc_event_free((isc_event_t **)&ns_cb->eventp);
+
+ remove_from_ns_queue(ns_cb);
+ data_string_forget(&ns_cb->oname, MDL);
+ dfree(ns_cb, MDL);
+
+ cleanup:
+ /* cleanup any of the new state information */
+
+ dns_client_freeresanswer(dhcp_gbl_ctx.dnsclient,
+ &ddns_event->answerlist);
+ isc_event_free(&eventp);
+
+ return;
+
+}
+
+/*
+ * Routine to continue the process of finding a nameserver via the DNS
+ * This is routine is called when we are still trying to get a list
+ * of nameservers to process.
+ */
+
+void
+find_zone_ns(isc_task_t *taskp,
+ isc_event_t *eventp)
+{
+ dns_clientresevent_t *ddns_event = (dns_clientresevent_t *)eventp;
+ dhcp_ddns_ns_t *ns_cb = (dhcp_ddns_ns_t *)eventp->ev_arg;
+ dns_fixedname_t zname0;
+ dns_name_t *zname = NULL, *ns_name = NULL;
+ dns_rdataset_t *rdataset;
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_ns_t ns;
+
+ /* the transaction is done, get rid of the tag */
+ dns_client_destroyrestrans(&ns_cb->transaction);
+
+ if (ddns_event->result != ISC_R_SUCCESS) {
+ /* We didn't find any nameservers, try again */
+
+ /* Remove a label and continue */
+ ns_cb->zname = strchr(ns_cb->zname, '.');
+ if ((ns_cb->zname == NULL) ||
+ (ns_cb->zname[1] == 0)) {
+ /* No more labels, all done */
+ goto cleanup;
+ }
+ ns_cb->zname++;
+
+ /* Create a DNS version of the zone name and call the
+ * resolver code */
+ if (((result = dhcp_isc_name((unsigned char *)ns_cb->zname,
+ &zname0, &zname))
+ != ISC_R_SUCCESS) ||
+ ((result = zone_resolve(dhcp_gbl_ctx.dnsclient,
+ zname, dns_rdataclass_in,
+ dns_rdatatype_ns,
+ DNS_CLIENTRESOPT_NODNSSEC,
+ dhcp_gbl_ctx.task,
+ find_zone_ns,
+ (void *)ns_cb,
+ &ns_cb->transaction))
+ != ISC_R_SUCCESS)) {
+ log_error("find_zone_ns: Unable to build "
+ "name or start resolve: %s %s",
+ ns_cb->zname,
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+ /* we have successfully started the next iteration
+ * of this step, clean up from the call and continue */
+ dns_client_freeresanswer(dhcp_gbl_ctx.dnsclient,
+ &ddns_event->answerlist);
+ isc_event_free(&eventp);
+ return;
+ }
+
+ /* We did get a set of nameservers, save the information and
+ * start trying to get addresses
+ */
+ ns_cb->eventp = ddns_event;
+ for (ns_name = ISC_LIST_HEAD(ddns_event->answerlist);
+ ns_name != NULL;
+ ns_name = ISC_LIST_NEXT(ns_name, link)) {
+
+ for (rdataset = ISC_LIST_HEAD(ns_name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+
+ if (rdataset->type != dns_rdatatype_ns)
+ continue;
+
+ if ((!dns_rdataset_isassociated(rdataset)) ||
+ (dns_rdataset_first(rdataset) !=
+ ISC_R_SUCCESS))
+ continue;
+
+ dns_rdataset_current(rdataset, &rdata);
+ if (dns_rdata_tostruct(&rdata, &ns, NULL) !=
+ ISC_R_SUCCESS)
+ continue;
+
+ /* Save our current state */
+ ns_cb->ns_name = ns_name;
+ ns_cb->rdataset = rdataset;
+
+ /* And call out to DNS */
+ result = zone_resolve(dhcp_gbl_ctx.dnsclient, &ns.name,
+ dns_rdataclass_in,
+ ns_cb->rdtype,
+ DNS_CLIENTRESOPT_NODNSSEC,
+ dhcp_gbl_ctx.task,
+ find_zone_addrs,
+ (void *)ns_cb,
+ &ns_cb->transaction);
+
+ /* do we need to clean this? */
+ dns_rdata_freestruct(&ns);
+
+ if (result == ISC_R_SUCCESS)
+ /* We have successfully started the next step
+ * we don't cleanup the eventp block as we are
+ * still using it.
+ */
+ return;
+
+ log_error("find_zone_ns: unable to continue "
+ "resolve: %s %s",
+ ns_cb->zname,
+ isc_result_totext(result));
+
+ /* The call to start a resolve transaction failed,
+ * should we try to continue with any other names?
+ * For now let's not
+ */
+ goto cleanup;
+ }
+ }
+
+ cleanup:
+ /* When we add a queue to manage the DDNS
+ * requests we will need to remove any that
+ * were waiting for this resolution */
+
+ dns_client_freeresanswer(dhcp_gbl_ctx.dnsclient,
+ &ddns_event->answerlist);
+ isc_event_free(&eventp);
+
+ remove_from_ns_queue(ns_cb);
+
+ data_string_forget(&ns_cb->oname, MDL);
+ dfree(ns_cb, MDL);
+ return;
+
+}
+
+/*
+ * Start the process of finding nameservers via the DNS because
+ * we don't have a zone entry already.
+ * We construct a control block and fill in the DDNS name. As
+ * the process continues we shall move the zname pointer to
+ * indicate which labels we are still using. The rest of
+ * the control block will be filled in as we continue processing.
+ */
+isc_result_t
+find_zone_start(dhcp_ddns_cb_t *ddns_cb, int direction)
+{
+ isc_result_t status = ISC_R_NOTFOUND;
+ dhcp_ddns_ns_t *ns_cb;
+ dns_fixedname_t zname0;
+ dns_name_t *zname = NULL;
+
+ /*
+ * We don't validate np as that was already done in find_cached_zone()
+ */
+
+ /* Allocate the control block for this request */
+ ns_cb = dmalloc(sizeof(*ns_cb), MDL);
+ if (ns_cb == NULL) {
+ log_error("find_zone_start: unable to allocate cb");
+ return(ISC_R_FAILURE);
+ }
+ ns_cb->rdtype = dns_rdatatype_a;
+
+ /* Copy the data string so the NS lookup is independent of the DDNS */
+ if (direction == FIND_FORWARD) {
+ data_string_copy(&ns_cb->oname, &ddns_cb->fwd_name, MDL);
+ } else {
+ data_string_copy(&ns_cb->oname, &ddns_cb->rev_name, MDL);
+ }
+ ns_cb->zname = (char *)ns_cb->oname.data;
+
+ /*
+ * Check the dns_outstanding_ns queue to see if we are
+ * already processing something that would cover this name
+ */
+ if (find_in_ns_queue(ns_cb) == ISC_R_SUCCESS) {
+ data_string_forget(&ns_cb->oname, MDL);
+ dfree(ns_cb, MDL);
+ return (ISC_R_SUCCESS);
+ }
+
+ /* Create a DNS version of the zone name and call the
+ * resolver code */
+ if (((status = dhcp_isc_name((unsigned char *)ns_cb->zname,
+ &zname0, &zname))
+ != ISC_R_SUCCESS) ||
+ ((status = zone_resolve(dhcp_gbl_ctx.dnsclient,
+ zname, dns_rdataclass_in,
+ dns_rdatatype_ns,
+ DNS_CLIENTRESOPT_NODNSSEC,
+ dhcp_gbl_ctx.task,
+ find_zone_ns,
+ (void *)ns_cb,
+ &ns_cb->transaction))
+ != ISC_R_SUCCESS)) {
+ log_error("find_zone_start: Unable to build "
+ "name or start resolve: %s %s",
+ ns_cb->zname,
+ isc_result_totext(status));
+
+ /* We failed to start the process, clean up */
+ data_string_forget(&ns_cb->oname, MDL);
+ dfree(ns_cb, MDL);
+ } else {
+ /* We started the process, attach the control block
+ * to the queue */
+ add_to_ns_queue(ns_cb);
+ }
+
+ return (status);
+}
+#endif
+
isc_result_t
find_cached_zone(dhcp_ddns_cb_t *ddns_cb, int direction)
{
@@ -693,10 +1277,13 @@ find_cached_zone(dhcp_ddns_cb_t *ddns_cb, int direction)
if (status != ISC_R_SUCCESS)
return (status);
- /* Make sure the zone is valid. */
- if (zone->timeout && zone->timeout < cur_time) {
+ /* Make sure the zone is valid, we've already gotten
+ * rid of expired dynamic zones. Check to see if
+ * we repudiated this zone. If so give up.
+ */
+ if ((zone->flags & DNS_ZONE_INACTIVE) != 0) {
dns_zone_dereference(&zone, MDL);
- return (ISC_R_CANCELED);
+ return (ISC_R_FAILURE);
}
/* Make sure the zone name will fit. */
@@ -809,21 +1396,97 @@ void forget_zone (struct dns_zone **zone)
void repudiate_zone (struct dns_zone **zone)
{
- /* XXX Currently we're not differentiating between a cached
- XXX zone and a zone that's been repudiated, which means
- XXX that if we reap cached zones, we blow away repudiated
- XXX zones. This isn't a big problem since we're not yet
- XXX caching zones... :'} */
-
/* verify that we have a pointer at least */
if ((zone == NULL) || (*zone == NULL)) {
log_info("Null argument to repudiate zone");
return;
}
- (*zone) -> timeout = cur_time - 1;
- dns_zone_dereference (zone, MDL);
+ (*zone)->flags |= DNS_ZONE_INACTIVE;
+ dns_zone_dereference(zone, MDL);
+}
+
+#if defined (DNS_ZONE_LOOKUP)
+void cache_found_zone(dhcp_ddns_ns_t *ns_cb)
+{
+ struct dns_zone *zone = NULL;
+ int len, remove_zone = 0;
+
+ /* See if there's already such a zone. */
+ if (dns_zone_lookup(&zone, ns_cb->zname) == ISC_R_SUCCESS) {
+ /* If it's not a dynamic zone, leave it alone. */
+ if (zone->timeout == 0)
+ return;
+
+ /* Remove any old addresses in case they've changed */
+ if (zone->primary)
+ option_cache_dereference(&zone->primary, MDL);
+ if (zone->primary6)
+ option_cache_dereference(&zone->primary6, MDL);
+
+ /* Set the flag to remove the zone from the hash if
+ we have problems */
+ remove_zone = 1;
+ } else if (dns_zone_allocate(&zone, MDL) == 0) {
+ return;
+ } else {
+ /* We've just allocated the zone, now we need
+ * to allocate space for the name and addresses
+ */
+
+ /* allocate space for the name */
+ len = strlen(ns_cb->zname);
+ zone->name = dmalloc(len + 2, MDL);
+ if (zone->name == NULL) {
+ goto cleanup;
+ }
+
+ /* Copy the name and add a trailing '.' if necessary */
+ strcpy(zone->name, ns_cb->zname);
+ if (zone->name[len-1] != '.') {
+ zone->name[len] = '.';
+ zone->name[len+1] = 0;
+ }
+ }
+
+ zone->timeout = cur_time + ns_cb->ttl;
+
+ if (ns_cb->num_addrs != 0) {
+ len = ns_cb->num_addrs * sizeof(struct in_addr);
+ if ((!option_cache_allocate(&zone->primary, MDL)) ||
+ (!buffer_allocate(&zone->primary->data.buffer,
+ len, MDL))) {
+ if (remove_zone == 1)
+ remove_dns_zone(zone);
+ goto cleanup;
+ }
+ memcpy(zone->primary->data.buffer->data, ns_cb->addrs, len);
+ zone->primary->data.data =
+ &zone->primary->data.buffer->data[0];
+ zone->primary->data.len = len;
+ }
+ if (ns_cb->num_addrs6 != 0) {
+ len = ns_cb->num_addrs6 * sizeof(struct in6_addr);
+ if ((!option_cache_allocate(&zone->primary6, MDL)) ||
+ (!buffer_allocate(&zone->primary6->data.buffer,
+ len, MDL))) {
+ if (remove_zone == 1)
+ remove_dns_zone(zone);
+ goto cleanup;
+ }
+ memcpy(zone->primary6->data.buffer->data, ns_cb->addrs6, len);
+ zone->primary6->data.data =
+ &zone->primary6->data.buffer->data[0];
+ zone->primary6->data.len = len;
+ }
+
+ enter_dns_zone(zone);
+
+ cleanup:
+ dns_zone_dereference(&zone, MDL);
+ return;
}
+#endif
/*!
* \brief Create an id for a client
@@ -1143,7 +1806,7 @@ ddns_modify_fwd_add1(dhcp_ddns_cb_t *ddns_cb,
/* Construct the update list */
/* Add the A RR */
result = make_dns_dataset(dns_rdataclass_in, ddns_cb->address_type,
- dataspace,
+ dataspace,
(unsigned char *)ddns_cb->address.iabuf,
ddns_cb->address.len, ddns_cb->ttl);
if (result != ISC_R_SUCCESS) {
@@ -1513,6 +2176,28 @@ ddns_modify_fwd(dhcp_ddns_cb_t *ddns_cb, const char *file, int line)
if (ddns_cb->zone == NULL) {
result = find_cached_zone(ddns_cb, FIND_FORWARD);
+#if defined (DNS_ZONE_LOOKUP)
+ if (result == ISC_R_NOTFOUND) {
+ /*
+ * We didn't find a cached zone, see if we can
+ * can find a nameserver and create a zone.
+ */
+ if (find_zone_start(ddns_cb, FIND_FORWARD)
+ == ISC_R_SUCCESS) {
+ /*
+ * We have started the process to find a zone
+ * queue the ddns_cb for processing after we
+ * create the zone
+ */
+ /* sar - not yet implemented, currently we just
+ * arrange for things to get cleaned up
+ */
+ goto cleanup;
+ }
+ }
+#endif
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
}
/*
@@ -1685,6 +2370,30 @@ ddns_modify_ptr(dhcp_ddns_cb_t *ddns_cb, const char *file, int line)
* have a pre-existing zone.
*/
result = find_cached_zone(ddns_cb, FIND_REVERSE);
+
+#if defined (DNS_ZONE_LOOKUP)
+ if (result == ISC_R_NOTFOUND) {
+ /*
+ * We didn't find a cached zone, see if we can
+ * can find a nameserver and create a zone.
+ */
+ if (find_zone_start(ddns_cb, FIND_REVERSE) == ISC_R_SUCCESS) {
+ /*
+ * We have started the process to find a zone
+ * queue the ddns_cb for processing after we
+ * create the zone
+ */
+ /* sar - not yet implemented, currently we just
+ * arrange for things to get cleaned up
+ */
+ goto cleanup;
+ }
+ }
+#endif
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+
if ((result == ISC_R_SUCCESS) &&
!(ISC_LIST_EMPTY(ddns_cb->zone_server_list))) {
/* Set up the zone name for use by DNS */
diff --git a/common/tests/Makefile.am b/common/tests/Makefile.am
index 233c293c..ddb2e9da 100644
--- a/common/tests/Makefile.am
+++ b/common/tests/Makefile.am
@@ -13,8 +13,8 @@ ATF_TESTS += alloc_unittest dns_unittest
alloc_unittest_SOURCES = test_alloc.c $(top_srcdir)/tests/t_api_dhcp.c
alloc_unittest_LDADD = $(ATF_LDFLAGS)
alloc_unittest_LDADD += ../libdhcp.a \
- ../../omapip/libomapi.a ../../bind/lib/libdns.a \
- ../../bind/lib/libisc.a
+ ../../omapip/libomapi.a ../../bind/lib/libirs.a \
+ ../../bind/lib/libdns.a ../bind/lib/libisccfg.a ../../bind/lib/libisc.a
dns_unittest_SOURCES = dns_unittest.c $(top_srcdir)/tests/t_api_dhcp.c
dns_unittest_LDADD = $(ATF_LDFLAGS)
diff --git a/common/tests/Makefile.in b/common/tests/Makefile.in
index 6f81a86e..467a0545 100644
--- a/common/tests/Makefile.in
+++ b/common/tests/Makefile.in
@@ -101,7 +101,8 @@ alloc_unittest_OBJECTS = $(am_alloc_unittest_OBJECTS)
am__DEPENDENCIES_1 =
@HAVE_ATF_TRUE@alloc_unittest_DEPENDENCIES = $(am__DEPENDENCIES_1) \
@HAVE_ATF_TRUE@ ../libdhcp.a ../../omapip/libomapi.a \
-@HAVE_ATF_TRUE@ ../../bind/lib/libdns.a ../../bind/lib/libisc.a
+@HAVE_ATF_TRUE@ ../../bind/lib/libirs.a ../../bind/lib/libdns.a \
+@HAVE_ATF_TRUE@ ../bind/lib/libisccfg.a ../../bind/lib/libisc.a
am__dns_unittest_SOURCES_DIST = dns_unittest.c \
$(top_srcdir)/tests/t_api_dhcp.c
@HAVE_ATF_TRUE@am_dns_unittest_OBJECTS = dns_unittest.$(OBJEXT) \
@@ -320,7 +321,8 @@ EXTRA_DIST = Atffile
ATF_TESTS = $(am__append_1)
@HAVE_ATF_TRUE@alloc_unittest_SOURCES = test_alloc.c $(top_srcdir)/tests/t_api_dhcp.c
@HAVE_ATF_TRUE@alloc_unittest_LDADD = $(ATF_LDFLAGS) ../libdhcp.a \
-@HAVE_ATF_TRUE@ ../../omapip/libomapi.a ../../bind/lib/libdns.a \
+@HAVE_ATF_TRUE@ ../../omapip/libomapi.a ../../bind/lib/libirs.a \
+@HAVE_ATF_TRUE@ ../../bind/lib/libdns.a ../bind/lib/libisccfg.a \
@HAVE_ATF_TRUE@ ../../bind/lib/libisc.a
@HAVE_ATF_TRUE@dns_unittest_SOURCES = dns_unittest.c $(top_srcdir)/tests/t_api_dhcp.c
@HAVE_ATF_TRUE@dns_unittest_LDADD = $(ATF_LDFLAGS) ../libdhcp.a \
diff --git a/dhcpctl/Makefile.am b/dhcpctl/Makefile.am
index 61049bea..dfa47095 100644
--- a/dhcpctl/Makefile.am
+++ b/dhcpctl/Makefile.am
@@ -6,10 +6,12 @@ EXTRA_DIST = $(man_MANS)
omshell_SOURCES = omshell.c
omshell_LDADD = libdhcpctl.a ../common/libdhcp.a ../omapip/libomapi.a \
- ../bind/lib/libdns.a ../bind/lib/libisc.a
+ ../bind/lib/libirs.a ../bind/lib/libdns.a \
+ ../bind/lib/libisccfg.a ../bind/lib/libisc.a
libdhcpctl_a_SOURCES = dhcpctl.c callback.c remote.c
cltest_SOURCES = cltest.c
cltest_LDADD = libdhcpctl.a ../common/libdhcp.a ../omapip/libomapi.a \
- ../bind/lib/libdns.a ../bind/lib/libisc.a \ No newline at end of file
+ ../bind/lib/libirs.a ../bind/lib/libdns.a \
+ ../bind/lib/libisccfg.a ../bind/lib/libisc.a
diff --git a/dhcpctl/Makefile.in b/dhcpctl/Makefile.in
index afb76047..61cfcf12 100644
--- a/dhcpctl/Makefile.in
+++ b/dhcpctl/Makefile.in
@@ -137,11 +137,13 @@ PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
am_cltest_OBJECTS = cltest.$(OBJEXT)
cltest_OBJECTS = $(am_cltest_OBJECTS)
cltest_DEPENDENCIES = libdhcpctl.a ../common/libdhcp.a \
- ../omapip/libomapi.a ../bind/lib/libdns.a ../bind/lib/libisc.a
+ ../omapip/libomapi.a ../bind/lib/libirs.a ../bind/lib/libdns.a \
+ ../bind/lib/libisccfg.a ../bind/lib/libisc.a
am_omshell_OBJECTS = omshell.$(OBJEXT)
omshell_OBJECTS = $(am_omshell_OBJECTS)
omshell_DEPENDENCIES = libdhcpctl.a ../common/libdhcp.a \
- ../omapip/libomapi.a ../bind/lib/libdns.a ../bind/lib/libisc.a
+ ../omapip/libomapi.a ../bind/lib/libirs.a ../bind/lib/libdns.a \
+ ../bind/lib/libisccfg.a ../bind/lib/libisc.a
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
@@ -309,12 +311,14 @@ man_MANS = omshell.1 dhcpctl.3
EXTRA_DIST = $(man_MANS)
omshell_SOURCES = omshell.c
omshell_LDADD = libdhcpctl.a ../common/libdhcp.a ../omapip/libomapi.a \
- ../bind/lib/libdns.a ../bind/lib/libisc.a
+ ../bind/lib/libirs.a ../bind/lib/libdns.a \
+ ../bind/lib/libisccfg.a ../bind/lib/libisc.a
libdhcpctl_a_SOURCES = dhcpctl.c callback.c remote.c
cltest_SOURCES = cltest.c
cltest_LDADD = libdhcpctl.a ../common/libdhcp.a ../omapip/libomapi.a \
- ../bind/lib/libdns.a ../bind/lib/libisc.a
+ ../bind/lib/libirs.a ../bind/lib/libdns.a \
+ ../bind/lib/libisccfg.a ../bind/lib/libisc.a
all: all-am
diff --git a/includes/dhcpd.h b/includes/dhcpd.h
index c74fab35..7d0cfb1b 100644
--- a/includes/dhcpd.h
+++ b/includes/dhcpd.h
@@ -1371,6 +1371,8 @@ struct dns_query {
int backoff; /* Current backoff, in seconds. */
};
+#define DNS_ZONE_ACTIVE 0
+#define DNS_ZONE_INACTIVE 1
struct dns_zone {
int refcnt;
TIME timeout;
@@ -1380,6 +1382,7 @@ struct dns_zone {
struct option_cache *primary6;
struct option_cache *secondary6;
struct auth_key *key;
+ u_int16_t flags;
};
struct icmp_state {
diff --git a/includes/omapip/isclib.h b/includes/omapip/isclib.h
index fc45ef3d..fbd0d652 100644
--- a/includes/omapip/isclib.h
+++ b/includes/omapip/isclib.h
@@ -61,6 +61,8 @@
#include <isc/heap.h>
#include <isc/random.h>
+#include <irs/resconf.h>
+
#include <dns/client.h>
#include <dns/fixedname.h>
#include <dns/keyvalues.h>
diff --git a/includes/site.h b/includes/site.h
index a45453a8..7576e1d8 100644
--- a/includes/site.h
+++ b/includes/site.h
@@ -117,6 +117,10 @@
#define NSUPDATE
+/* Define this if you want to enable the DHCP server attempting to
+ find a nameserver to use for DDNS updates. */
+#define DNS_ZONE_LOOKUP
+
/* Define this if you want the dhcpd.pid file to go somewhere other than
the default (which varies from system to system, but is usually either
/etc or /var/run. */
diff --git a/omapip/Makefile.am b/omapip/Makefile.am
index 595950ad..8237de0e 100644
--- a/omapip/Makefile.am
+++ b/omapip/Makefile.am
@@ -10,5 +10,6 @@ man_MANS = omapi.3
EXTRA_DIST = $(man_MANS)
svtest_SOURCES = test.c
-svtest_LDADD = libomapi.a ../bind/lib/libdns.a ../bind/lib/libisc.a
+svtest_LDADD = libomapi.a ../bind/lib/libirs.a ../bind/lib/libdns.a \
+ ../bind/lib/libisccfg.a ../bind/lib/libisc.a
diff --git a/omapip/Makefile.in b/omapip/Makefile.in
index e327a4a7..c7fff53c 100644
--- a/omapip/Makefile.in
+++ b/omapip/Makefile.in
@@ -140,7 +140,8 @@ libomapi_a_OBJECTS = $(am_libomapi_a_OBJECTS)
PROGRAMS = $(noinst_PROGRAMS)
am_svtest_OBJECTS = test.$(OBJEXT)
svtest_OBJECTS = $(am_svtest_OBJECTS)
-svtest_DEPENDENCIES = libomapi.a ../bind/lib/libdns.a \
+svtest_DEPENDENCIES = libomapi.a ../bind/lib/libirs.a \
+ ../bind/lib/libdns.a ../bind/lib/libisccfg.a \
../bind/lib/libisc.a
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
@@ -311,7 +312,9 @@ libomapi_a_SOURCES = protocol.c buffer.c alloc.c result.c connection.c \
man_MANS = omapi.3
EXTRA_DIST = $(man_MANS)
svtest_SOURCES = test.c
-svtest_LDADD = libomapi.a ../bind/lib/libdns.a ../bind/lib/libisc.a
+svtest_LDADD = libomapi.a ../bind/lib/libirs.a ../bind/lib/libdns.a \
+ ../bind/lib/libisccfg.a ../bind/lib/libisc.a
+
all: all-am
.SUFFIXES:
diff --git a/omapip/isclib.c b/omapip/isclib.c
index afab262c..7ef1591f 100644
--- a/omapip/isclib.c
+++ b/omapip/isclib.c
@@ -33,6 +33,57 @@
dhcp_context_t dhcp_gbl_ctx;
int shutdown_signal = 0;
+#if defined (NSUPDATE)
+
+/* This routine will open up the /etc/resolv.conf file and
+ * send any nameservers it finds to the DNS client code.
+ * It may be moved to be part of the dns client code instead
+ * of being in the DHCP code
+ */
+isc_result_t
+dhcp_dns_client_setservers(void)
+{
+ isc_result_t result;
+ irs_resconf_t *resconf = NULL;
+ isc_sockaddrlist_t *nameservers;
+ isc_sockaddr_t *sa;
+
+ result = irs_resconf_load(dhcp_gbl_ctx.mctx, _PATH_RESOLV_CONF,
+ &resconf);
+ if (result != ISC_R_SUCCESS) {
+ log_error("irs_resconf_load failed: %d.", result);
+ return (result);
+ }
+
+ nameservers = irs_resconf_getnameservers(resconf);
+
+ /* Initialize port numbers */
+ for (sa = ISC_LIST_HEAD(*nameservers);
+ sa != NULL;
+ sa = ISC_LIST_NEXT(sa, link)) {
+ switch (sa->type.sa.sa_family) {
+ case AF_INET:
+ sa->type.sin.sin_port = htons(NS_DEFAULTPORT);
+ break;
+ case AF_INET6:
+ sa->type.sin6.sin6_port = htons(NS_DEFAULTPORT);
+ break;
+ default:
+ break;
+ }
+ }
+
+ result = dns_client_setservers(dhcp_gbl_ctx.dnsclient,
+ dns_rdataclass_in,
+ NULL, nameservers);
+ if (result != ISC_R_SUCCESS) {
+ log_error("dns_client_setservers failed: %d.",
+ result);
+ }
+ return (result);
+}
+#endif
+
void
isclib_cleanup(void)
{
@@ -142,6 +193,11 @@ dhcp_context_create(void) {
&dhcp_gbl_ctx.dnsclient);
if (result != ISC_R_SUCCESS)
goto cleanup;
+
+ result = dhcp_dns_client_setservers();
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
#else
/* The dst library is inited as part of dns_lib_init, we don't
* need it if NSUPDATE is enabled */
diff --git a/relay/Makefile.am b/relay/Makefile.am
index d8757cac..198d5cd6 100644
--- a/relay/Makefile.am
+++ b/relay/Makefile.am
@@ -3,7 +3,8 @@ AM_CPPFLAGS = -DLOCALSTATEDIR='"@localstatedir@"'
sbin_PROGRAMS = dhcrelay
dhcrelay_SOURCES = dhcrelay.c
dhcrelay_LDADD = ../common/libdhcp.a ../omapip/libomapi.a \
- ../bind/lib/libdns.a ../bind/lib/libisc.a
+ ../bind/lib/libirs.a ../bind/lib/libdns.a \
+ ../bind/lib/libisccfg.a ../bind/lib/libisc.a
man_MANS = dhcrelay.8
EXTRA_DIST = $(man_MANS)
diff --git a/relay/Makefile.in b/relay/Makefile.in
index 199631a8..be95fb71 100644
--- a/relay/Makefile.in
+++ b/relay/Makefile.in
@@ -95,7 +95,8 @@ PROGRAMS = $(sbin_PROGRAMS)
am_dhcrelay_OBJECTS = dhcrelay.$(OBJEXT)
dhcrelay_OBJECTS = $(am_dhcrelay_OBJECTS)
dhcrelay_DEPENDENCIES = ../common/libdhcp.a ../omapip/libomapi.a \
- ../bind/lib/libdns.a ../bind/lib/libisc.a
+ ../bind/lib/libirs.a ../bind/lib/libdns.a \
+ ../bind/lib/libisccfg.a ../bind/lib/libisc.a
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
@@ -286,7 +287,8 @@ top_srcdir = @top_srcdir@
AM_CPPFLAGS = -DLOCALSTATEDIR='"@localstatedir@"'
dhcrelay_SOURCES = dhcrelay.c
dhcrelay_LDADD = ../common/libdhcp.a ../omapip/libomapi.a \
- ../bind/lib/libdns.a ../bind/lib/libisc.a
+ ../bind/lib/libirs.a ../bind/lib/libdns.a \
+ ../bind/lib/libisccfg.a ../bind/lib/libisc.a
man_MANS = dhcrelay.8
EXTRA_DIST = $(man_MANS)
diff --git a/server/Makefile.am b/server/Makefile.am
index dc5d4f3d..8e8ce889 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -14,8 +14,8 @@ dhcpd_SOURCES = dhcpd.c dhcp.c bootp.c confpars.c db.c class.c failover.c \
dhcpd_CFLAGS = $(LDAP_CFLAGS)
dhcpd_LDADD = ../common/libdhcp.a ../omapip/libomapi.a \
- ../dhcpctl/libdhcpctl.a ../bind/lib/libdns.a \
- ../bind/lib/libisc.a
+ ../dhcpctl/libdhcpctl.a ../bind/lib/libirs.a \
+ ../bind/lib/libdns.a ../bind/lib/libisccfg.a ../bind/lib/libisc.a
man_MANS = dhcpd.8 dhcpd.conf.5 dhcpd.leases.5
EXTRA_DIST = $(man_MANS)
diff --git a/server/Makefile.in b/server/Makefile.in
index 4e6d01df..b7e74146 100644
--- a/server/Makefile.in
+++ b/server/Makefile.in
@@ -105,7 +105,8 @@ am_dhcpd_OBJECTS = dhcpd-dhcpd.$(OBJEXT) dhcpd-dhcp.$(OBJEXT) \
dhcpd-ldap_casa.$(OBJEXT)
dhcpd_OBJECTS = $(am_dhcpd_OBJECTS)
dhcpd_DEPENDENCIES = ../common/libdhcp.a ../omapip/libomapi.a \
- ../dhcpctl/libdhcpctl.a ../bind/lib/libdns.a \
+ ../dhcpctl/libdhcpctl.a ../bind/lib/libirs.a \
+ ../bind/lib/libdns.a ../bind/lib/libisccfg.a \
../bind/lib/libisc.a
dhcpd_LINK = $(CCLD) $(dhcpd_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
@@ -358,8 +359,8 @@ dhcpd_SOURCES = dhcpd.c dhcp.c bootp.c confpars.c db.c class.c failover.c \
dhcpd_CFLAGS = $(LDAP_CFLAGS)
dhcpd_LDADD = ../common/libdhcp.a ../omapip/libomapi.a \
- ../dhcpctl/libdhcpctl.a ../bind/lib/libdns.a \
- ../bind/lib/libisc.a
+ ../dhcpctl/libdhcpctl.a ../bind/lib/libirs.a \
+ ../bind/lib/libdns.a ../bind/lib/libisccfg.a ../bind/lib/libisc.a
man_MANS = dhcpd.8 dhcpd.conf.5 dhcpd.leases.5
EXTRA_DIST = $(man_MANS)
diff --git a/server/tests/Makefile.am b/server/tests/Makefile.am
index d9945a12..1b257462 100644
--- a/server/tests/Makefile.am
+++ b/server/tests/Makefile.am
@@ -18,8 +18,9 @@ DHCPSRC = ../dhcp.c ../bootp.c ../confpars.c ../db.c ../class.c \
../ldap.c ../ldap_casa.c ../dhcpd.c
DHCPLIBS = $(top_builddir)/common/libdhcp.a $(top_builddir)/omapip/libomapi.a \
- $(top_builddir)/dhcpctl/libdhcpctl.a $(top_builddir)/bind/lib/libdns.a \
- $(top_builddir)/bind/lib/libisc.a
+ $(top_builddir)/dhcpctl/libdhcpctl.a $(top_builddir)/bind/lib/libirs.a \
+ $(top_builddir)/bind/lib/libdns.a $(top_builddir/bind/lib/libisccfg.a \
+ $(top_builddir)/bind/lib/libisc.a
ATF_TESTS =
TESTS =
diff --git a/server/tests/Makefile.in b/server/tests/Makefile.in
index e5250b30..5c100a33 100644
--- a/server/tests/Makefile.in
+++ b/server/tests/Makefile.in
@@ -565,8 +565,9 @@ DHCPSRC = ../dhcp.c ../bootp.c ../confpars.c ../db.c ../class.c \
../ldap.c ../ldap_casa.c ../dhcpd.c
DHCPLIBS = $(top_builddir)/common/libdhcp.a $(top_builddir)/omapip/libomapi.a \
- $(top_builddir)/dhcpctl/libdhcpctl.a $(top_builddir)/bind/lib/libdns.a \
- $(top_builddir)/bind/lib/libisc.a
+ $(top_builddir)/dhcpctl/libdhcpctl.a $(top_builddir)/bind/lib/libirs.a \
+ $(top_builddir)/bind/lib/libdns.a $(top_builddir/bind/lib/libisccfg.a \
+ $(top_builddir)/bind/lib/libisc.a
ATF_TESTS = $(am__append_1)
@HAVE_ATF_TRUE@dhcpd_unittests_SOURCES = $(DHCPSRC) simple_unittest.c
diff --git a/util/bind.sh b/util/bind.sh
index 8704fe1c..59ca3426 100644
--- a/util/bind.sh
+++ b/util/bind.sh
@@ -58,7 +58,8 @@ case $# in
### For ease of use, this records the sticky tag of versions
### released with each point release.
###
- 4.2.5b1|4.2.5rc1) BINDTAG=v9_8_4_P1 ;;
+ 4.2.6b1) BINDTAG=v9_8_6 ;;
+ 4.2.5b1|4.2.5rc1) BINDTAG=v9_8_4_P1 ;;
4.2.4rc2|4.2.4) BINDTAG=v9_8_3 ;;
4.2.4b1|4.2.4rc1) BINDTAG=v9_8_2 ;;
4.2.3-P1|4.2.3-P2) BINDTAG=v9_8_1_P1 ;;