-# Copyright (c) 2004-2009 by Internet Systems Consortium, Inc. ("ISC")
+# Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC")
# Copyright (c) 1995-2003 by Internet Software Consortium
#
# Permission to use, copy, modify, and distribute this software for any
This is supported using a new 'rewind state' record on the dhcpd.leases
entry for each lease.
+- Fix the trace code which was broken by the changes to the DDNS code.
+
Changes since 4.1.0 (new features)
- Failover port configuration can now be left to defaults (port 647) as
q->when.tv_sec = when->tv_sec;
q->when.tv_usec = when->tv_usec;
+#if defined (TRACING)
+ if (trace_playback()) {
+ /*
+ * If we are doing playback we need to handle the timers
+ * within this code rather than having the isclib handle
+ * them for us. We need to keep the timer list in order
+ * to allow us to find the ones to timeout.
+ *
+ * By using a different timer setup in the playback we may
+ * have variations between the orginal and the playback but
+ * it's the best we can do for now.
+ */
+
+ /* Beginning of list? */
+ if (!timeouts || (timeouts->when.tv_sec > q-> when.tv_sec) ||
+ ((timeouts->when.tv_sec == q->when.tv_sec) &&
+ (timeouts->when.tv_usec > q->when.tv_usec))) {
+ q->next = timeouts;
+ timeouts = q;
+ return;
+ }
+
+ /* Middle of list? */
+ for (t = timeouts; t->next; t = t->next) {
+ if ((t->next->when.tv_sec > q->when.tv_sec) ||
+ ((t->next->when.tv_sec == q->when.tv_sec) &&
+ (t->next->when.tv_usec > q->when.tv_usec))) {
+ q->next = t->next;
+ t->next = q;
+ return;
+ }
+ }
+
+ /* End of list. */
+ t->next = q;
+ q->next = (struct timeout *)0;
+ return;
+ }
+#endif
/*
* Don't bother sorting the DHCP list, just add it to the front.
* Eventually the list should be removed as we migrate the callers
t = q;
}
- /* If we found the timeout, cancel it and put it on the free list. */
+ /*
+ * If we found the timeout, cancel it and put it on the free list.
+ * The TRACING stuff is ugly but we don't add a timer when doing
+ * playback so we don't want to remove them then either.
+ */
if (q) {
- isc_timer_detach(&q->isc_timeout);
+#if defined (TRACING)
+ if (!trace_playback()) {
+#endif
+ isc_timer_detach(&q->isc_timeout);
+#if defined (TRACING)
+ }
+#endif
if (q->unref)
(*q->unref) (&q->what, MDL);
Domain Name Service subroutines. */
/*
- * Copyright (c) 2004-2007, 2009 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2009-2010 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 2001-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
#if defined (NSUPDATE)
+void ddns_interlude(isc_task_t *, isc_event_t *);
+
+
+#if defined (TRACING)
+/*
+ * Code to support tracing DDNS packets. We trace packets going to and
+ * coming from the libdns code but don't try to track the packets
+ * exchanged between the libdns code and the dns server(s) it contacts.
+ *
+ * The code is split into two sets of routines
+ * input refers to messages received from the dns module
+ * output refers to messages sent to the dns module
+ * Currently there are three routines in each set
+ * write is used to write information about the message to the trace file
+ * this routine is called directly from the proper place in the code.
+ * read is used to read information about a message from the trace file
+ * this routine is called from the trace loop as it reads through
+ * the file and is registered via the trace_type_register routine.
+ * When playing back a trace file we shall absorb records of output
+ * messages as part of processing the write function, therefore
+ * any output messages we encounter are flagged as errors.
+ * stop isn't currently used in this code but is needed for the register
+ * routine.
+ *
+ * We pass a pointer to a control block to the dns module which it returns
+ * to use as part of the result. As the pointer may vary between traces
+ * we need to map between those from the trace file and the new ones during
+ * playback.
+ *
+ * The mapping is complicated a little as a pointer could be 4 or 8 bytes
+ * long. We treat the old pointer as an 8 byte quantity and pad and compare
+ * as necessary.
+ */
+
+/*
+ * Structure used to map old pointers to new pointers.
+ * Old pointers are 8 bytes long as we don't know if the trace was
+ * done on a 64 bit or 32 bit machine.
+ */
+#define TRACE_PTR_LEN 8
+
+typedef struct dhcp_ddns_map {
+ char old_pointer[TRACE_PTR_LEN];
+ void *new_pointer;
+ struct dhcp_ddns_map *next;
+} dhcp_ddns_map_t;
+
+/* The starting point for the map structure */
+static dhcp_ddns_map_t *ddns_map;
+
+trace_type_t *trace_ddns_input;
+trace_type_t *trace_ddns_output;
+
+/*
+ * The data written to the trace file is:
+ * 32 bits result from dns
+ * 64 bits pointer of cb
+ */
+
+void
+trace_ddns_input_write(dhcp_ddns_cb_t *ddns_cb, isc_result_t result)
+{
+ trace_iov_t iov[2];
+ u_int32_t old_result;
+ char old_pointer[TRACE_PTR_LEN];
+
+ old_result = htonl((u_int32_t)result);
+ memset(old_pointer, 0, TRACE_PTR_LEN);
+ memcpy(old_pointer, &ddns_cb, sizeof(ddns_cb));
+
+ iov[0].len = sizeof(old_result);
+ iov[0].buf = (char *)&old_result;
+ iov[1].len = TRACE_PTR_LEN;
+ iov[1].buf = old_pointer;
+ trace_write_packet_iov(trace_ddns_input, 2, iov, MDL);
+}
+
+/*
+ * Process the result and pointer from the trace file.
+ * We use the pointer map to find the proper pointer for this instance.
+ * Then we need to construct an event to pass along to the interlude
+ * function.
+ */
+static void
+trace_ddns_input_read(trace_type_t *ttype, unsigned length,
+ char *buf)
+{
+ u_int32_t old_result;
+ char old_pointer[TRACE_PTR_LEN];
+ dns_clientupdateevent_t *eventp;
+ void *new_pointer;
+ dhcp_ddns_map_t *ddns_map_ptr;
+
+ if (length < (sizeof(old_result) + TRACE_PTR_LEN)) {
+ log_error("trace_ddns_input_read: data too short");
+ return;
+ }
+
+ memcpy(&old_result, buf, sizeof(old_result));
+ memcpy(old_pointer, buf + sizeof(old_result), TRACE_PTR_LEN);
+
+ /* map the old pointer to a new pointer */
+ for (ddns_map_ptr = ddns_map;
+ ddns_map_ptr != NULL;
+ ddns_map_ptr = ddns_map_ptr->next) {
+ if ((ddns_map_ptr->new_pointer != NULL) &&
+ memcmp(ddns_map_ptr->old_pointer,
+ old_pointer, TRACE_PTR_LEN) == 0) {
+ new_pointer = ddns_map_ptr->new_pointer;
+ ddns_map_ptr->new_pointer = NULL;
+ memset(ddns_map_ptr->old_pointer, 0, TRACE_PTR_LEN);
+ break;
+ }
+ }
+ if (ddns_map_ptr == NULL) {
+ log_error("trace_dns_input_read: unable to map cb pointer");
+ return;
+ }
+
+ eventp = (dns_clientupdateevent_t *)
+ isc_event_allocate(dhcp_gbl_ctx.mctx,
+ dhcp_gbl_ctx.task,
+ 0,
+ ddns_interlude,
+ new_pointer,
+ sizeof(dns_clientupdateevent_t));
+ if (eventp == NULL) {
+ log_error("trace_ddns_input_read: unable to allocate event");
+ return;
+ }
+ eventp->result = ntohl(old_result);
+
+
+ ddns_interlude(dhcp_gbl_ctx.task, (isc_event_t *)eventp);
+
+ return;
+}
+
+static void
+trace_ddns_input_stop(trace_type_t *ttype)
+{
+}
+
+/*
+ * We use the same arguments as for the dns startupdate function to
+ * allows us to choose between the two via a macro. If tracing isn't
+ * in use we simply call the dns function directly.
+ *
+ * If we are doing playback we read the next packet from the file
+ * and compare the type. If it matches we extract the results and pointer
+ * from the trace file. The results are returned to the caller as if
+ * they had called the dns routine. The pointer is used to construct a
+ * map for when the "reply" is processed.
+ *
+ * The data written to trace file is:
+ * 32 bits result
+ * 64 bits pointer of cb (DDNS Control block)
+ * contents of cb
+ */
+
+isc_result_t
+trace_ddns_output_write(dns_client_t *client, dns_rdataclass_t rdclass,
+ dns_name_t *zonename, dns_namelist_t *prerequisites,
+ dns_namelist_t *updates, isc_sockaddrlist_t *servers,
+ dns_tsec_t *tsec, unsigned int options,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ dns_clientupdatetrans_t **transp)
+{
+ isc_result_t result;
+ u_int32_t old_result;
+ char old_pointer[TRACE_PTR_LEN];
+ dhcp_ddns_map_t *ddns_map_ptr;
+
+ if (trace_playback() != 0) {
+ /* We are doing playback, extract the entry from the file */
+ unsigned buflen = 0;
+ char *inbuf = NULL;
+
+ result = trace_get_packet(&trace_ddns_output,
+ &buflen, &inbuf);
+ if (result != ISC_R_SUCCESS) {
+ log_error("trace_ddns_output_write: no input found");
+ return (ISC_R_FAILURE);
+ }
+ if (buflen < (sizeof(old_result) + TRACE_PTR_LEN)) {
+ log_error("trace_ddns_output_write: data too short");
+ dfree(inbuf, MDL);
+ return (ISC_R_FAILURE);
+ }
+ memcpy(&old_result, inbuf, sizeof(old_result));
+ result = ntohl(old_result);
+ memcpy(old_pointer, inbuf + sizeof(old_result), TRACE_PTR_LEN);
+ dfree(inbuf, MDL);
+
+ /* add the pointer to the pointer map */
+ for (ddns_map_ptr = ddns_map;
+ ddns_map_ptr != NULL;
+ ddns_map_ptr = ddns_map_ptr->next) {
+ if (ddns_map_ptr->new_pointer == NULL) {
+ break;
+ }
+ }
+
+ /*
+ * If we didn't find an empty entry, allocate an entry and
+ * link it into the list. The list isn't ordered.
+ */
+ if (ddns_map_ptr == NULL) {
+ ddns_map_ptr = dmalloc(sizeof(*ddns_map_ptr), MDL);
+ if (ddns_map_ptr == NULL) {
+ log_error("trace_ddns_output_write: "
+ "unable to allocate map entry");
+ return(ISC_R_FAILURE);
+ }
+ ddns_map_ptr->next = ddns_map;
+ ddns_map = ddns_map_ptr;
+ }
+
+ memcpy(ddns_map_ptr->old_pointer, old_pointer, TRACE_PTR_LEN);
+ ddns_map_ptr->new_pointer = arg;
+ }
+ else {
+ /* We aren't doing playback, make the actual call */
+ result = dns_client_startupdate(client, rdclass, zonename,
+ prerequisites, updates,
+ servers, tsec, options,
+ task, action, arg, transp);
+ }
+
+ if (trace_record() != 0) {
+ /* We are recording, save the information to the file */
+ trace_iov_t iov[3];
+ old_result = htonl((u_int32_t)result);
+ memset(old_pointer, 0, TRACE_PTR_LEN);
+ memcpy(old_pointer, &arg, sizeof(arg));
+ iov[0].len = sizeof(old_result);
+ iov[0].buf = (char *)&old_result;
+ iov[1].len = TRACE_PTR_LEN;
+ iov[1].buf = old_pointer;
+
+ /* Write out the entire cb, in case we want to look at it */
+ iov[2].len = sizeof(dhcp_ddns_cb_t);
+ iov[2].buf = (char *)arg;
+
+ trace_write_packet_iov(trace_ddns_output, 3, iov, MDL);
+ }
+
+ return(result);
+}
+
+static void
+trace_ddns_output_read(trace_type_t *ttype, unsigned length,
+ char *buf)
+{
+ log_error("unaccounted for ddns output.");
+}
+
+static void
+trace_ddns_output_stop(trace_type_t *ttype)
+{
+}
+
+void
+trace_ddns_init()
+{
+ trace_ddns_output = trace_type_register("ddns-output", NULL,
+ trace_ddns_output_read,
+ trace_ddns_output_stop, MDL);
+ trace_ddns_input = trace_type_register("ddns-input", NULL,
+ trace_ddns_input_read,
+ trace_ddns_input_stop, MDL);
+ ddns_map = NULL;
+}
+
+#define ddns_update trace_ddns_output_write
+#else
+#define ddns_update dns_client_startupdate
+#endif /* TRACING */
+
/*
* 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.
* the event block.*/
isc_event_free(&eventp);
+#if defined (TRACING)
+ if (trace_record()) {
+ trace_ddns_input_write(ddns_cb, eresult);
+ }
+#endif
/* This transaction is complete, clear the value */
ddns_cb->transaction = NULL;
ISC_LIST_APPEND(updatelist, uname, link);
/* send the message, cleanup and return the result */
- result = dns_client_startupdate(dhcp_gbl_ctx.dnsclient,
- dns_rdataclass_in, zname,
- &prereqlist, &updatelist,
- zlist, tsec_key,
- DNS_CLIENTRESOPT_ALLOWRUN,
- dhcp_gbl_ctx.task,
- ddns_interlude,
- (void *)ddns_cb,
- &ddns_cb->transaction);
+ result = ddns_update(dhcp_gbl_ctx.dnsclient,
+ dns_rdataclass_in, zname,
+ &prereqlist, &updatelist,
+ zlist, tsec_key,
+ DNS_CLIENTRESOPT_ALLOWRUN,
+ dhcp_gbl_ctx.task,
+ ddns_interlude,
+ (void *)ddns_cb,
+ &ddns_cb->transaction);
cleanup:
if (dataspace != NULL) {
* and we wanted to retry it.
*/
/* send the message, cleanup and return the result */
- result = dns_client_startupdate((dns_client_t *)dhcp_gbl_ctx.dnsclient,
- dns_rdataclass_in, zname,
- NULL, &updatelist,
- zlist, tsec_key,
- DNS_CLIENTRESOPT_ALLOWRUN,
- dhcp_gbl_ctx.task,
- ddns_interlude, (void *)ddns_cb,
- &ddns_cb->transaction);
+ result = ddns_update((dns_client_t *)dhcp_gbl_ctx.dnsclient,
+ dns_rdataclass_in, zname,
+ NULL, &updatelist,
+ zlist, tsec_key,
+ DNS_CLIENTRESOPT_ALLOWRUN,
+ dhcp_gbl_ctx.task,
+ ddns_interlude, (void *)ddns_cb,
+ &ddns_cb->transaction);
+
cleanup:
if (dataspace != NULL) {
isc_mem_put(dhcp_gbl_ctx.mctx, dataspace,
}
#if defined (NSUPDATE)
-#if 0
-void print_dns_status (int status, ns_updque *uq)
-{
- char obuf [1024];
- char *s = &obuf [0], *end = &obuf [1022];
- ns_updrec *u;
- int position;
- int ttlp;
- const char *predicate = "if", *en, *op;
- int errorp;
-
- for (u = ISC_LIST_HEAD (*uq); u; u = ISC_LIST_NEXT (u, r_link)) {
- ttlp = 0;
-
- switch (u -> r_opcode)
- {
- case NXRRSET:
- op = "rrset doesn't exist";
- position = 1;
- break;
- case YXRRSET:
- op = "rrset exists";
- position = 1;
- break;
- case NXDOMAIN:
- op = "domain doesn't exist";
- position = 1;
- break;
- case YXDOMAIN:
- op = "domain exists";
- position = 1;
- break;
- case ADD:
- op = "add";
- position = 0;
- ttlp = 1;
- break;
- case DELETE:
- op = "delete";
- position = 0;
- break;
- default:
- op = "unknown";
- position = 0;
- break;
- }
- if (!position) {
- if (s != &obuf [0] && s + 1 < end)
- *s++ = ' ';
- if (s + strlen (op) < end) {
- strcpy (s, op);
- s += strlen (s);
- }
- } else {
- if (s != &obuf [0] && s + 1 < end)
- *s++ = ' ';
- if (s + strlen (predicate) < end) {
- strcpy (s, predicate);
- s += strlen (s);
- }
- predicate = "and";
- }
- if (u -> r_dname) {
- if (s + 1 < end)
- *s++ = ' ';
- if (s + strlen (u -> r_dname) < end) {
- strcpy (s, u -> r_dname);
- s += strlen (s);
- }
- }
- if (ttlp) {
- if (s + 1 < end)
- *s++ = ' ';
- /* 27 is as big as a ttl can get. */
- if (s + 27 < end) {
- sprintf (s, "%lu",
- (unsigned long)(u -> r_ttl));
- s += strlen (s);
- }
- }
- switch (u -> r_class) {
- case C_IN:
- en = "IN";
- break;
- case C_CHAOS:
- en = "CHAOS";
- break;
- case C_HS:
- en = "HS";
- break;
- default:
- en = "UNKNOWN";
- break;
- }
- if (s + strlen (en) < end) {
- if (s + 1 < end)
- *s++ = ' ';
- strcpy (s, en);
- s += strlen (en);
- }
- switch (u -> r_type) {
- case T_A:
- en = "A";
- break;
- case T_AAAA:
- en = "AAAA";
- break;
- case T_PTR:
- en = "PTR";
- break;
- case T_MX:
- en = "MX";
- break;
- case T_TXT:
- en = "TXT";
- break;
- case T_KEY:
- en = "KEY";
- break;
- case T_CNAME:
- en = "CNAME";
- break;
- default:
- en = "UNKNOWN";
- break;
- }
- if (s + strlen (en) < end) {
- if (s + 1 < end)
- *s++ = ' ';
- strcpy (s, en);
- s += strlen (en);
- }
- if (u -> r_data) {
- if (s + 1 < end)
- *s++ = ' ';
- if (u -> r_type == T_TXT) {
- if (s + 1 < end)
- *s++ = '"';
- }
- if(u->r_type == T_KEY) {
- strcat(s, "<keydata>");
- s+=strlen("<keydata>");
- }
- else {
- if (s + u -> r_size < end) {
- memcpy (s, u -> r_data, u -> r_size);
- s += u -> r_size;
- if (u -> r_type == T_TXT) {
- if (s + 1 < end)
- *s++ = '"';
- }
- }
- }
- }
- if (position) {
- if (s + 1 < end)
- *s++ = ' ';
- if (s + strlen (op) < end) {
- strcpy (s, op);
- s += strlen (s);
- }
- }
- if (u == ISC_LIST_TAIL (*uq))
- break;
- }
- if (s == &obuf [0]) {
- strcpy (s, "empty update");
- s += strlen (s);
- }
- if (status == NOERROR)
- errorp = 0;
- else
- errorp = 1;
- en = isc_result_totext (status);
-#if 0
- switch (status) {
- case -1:
- en = "resolver failed";
- break;
-
- case FORMERR:
- en = "format error";
- break;
-
- case NOERROR:
- en = "succeeded";
- errorp = 0;
- break;
-
- case NOTAUTH:
- en = "not authorized";
- break;
-
- case NOTIMP:
- en = "not implemented";
- break;
-
- case NOTZONE:
- en = "not a single valid zone";
- break;
-
- case NXDOMAIN:
- en = "no such domain";
- break;
-
- case NXRRSET:
- en = "no such record";
- break;
-
- case REFUSED:
- en = "refused";
- break;
-
- case SERVFAIL:
- en = "server failed";
- break;
-
- case YXDOMAIN:
- en = "domain exists";
- break;
-
- case YXRRSET:
- en = "record exists";
- break;
-
- default:
- en = "unknown error";
- break;
- }
-#endif
-
- if (s + 2 < end) {
- *s++ = ':';
- *s++ = ' ';
- }
- if (s + strlen (en) < end) {
- strcpy (s, en);
- s += strlen (en);
- }
- if (s + 1 < end)
- *s++ = '.';
- *s++ = 0;
- if (errorp)
- log_error ("%s", obuf);
- else
- log_info ("%s", obuf);
-}
-#endif
+/*
+ * Place holder for debug information for ddns.
+ *
+ */
#endif /* NSUPDATE */
/* Format the given time as "A; # B", where A is the format
int ddns_updates(struct packet *, struct lease *, struct lease *,
struct iasubopt *, struct iasubopt *, struct option_state *);
int ddns_removals(struct lease *, struct iasubopt *, struct dhcp_ddns_cb *);
+#if defined (TRACING)
+void trace_ddns_init(void);
+#endif
/* parse.c */
void add_enumeration (struct enumeration *);
void omapi_buffer_trace_setup (void);
void omapi_connection_register (omapi_connection_object_t *,
const char *, int);
-void trace_mr_init (void);
-
OMAPI_ARRAY_TYPE_DECL(omapi_listener, omapi_listener_object_t);
OMAPI_ARRAY_TYPE_DECL(omapi_connection, omapi_connection_object_t);
libomapi_a_SOURCES = protocol.c buffer.c alloc.c result.c connection.c \
errwarn.c listener.c dispatch.c generic.c support.c \
handle.c message.c convert.c hash.c auth.c inet_addr.c \
- array.c trace.c mrtrace.c toisc.c iscprint.c isclib.c
+ array.c trace.c toisc.c iscprint.c isclib.c
man_MANS = omapi.3
EXTRA_DIST = $(man_MANS)
-/* mrtrace.c
-
- Subroutines that support minires tracing... */
-
-/*
- * Copyright (c) 2004,2007,2009 by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 2001-2003 by Internet Software Consortium
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Internet Systems Consortium, Inc.
- * 950 Charter Street
- * Redwood City, CA 94063
- * <info@isc.org>
- * https://www.isc.org/
- *
- * This software has been written for Internet Systems Consortium
- * by Ted Lemon, as part of a project for Nominum, Inc. To learn more
- * about Internet Systems Consortium, see https://www.isc.org/. To
- * learn more about Nominum, Inc., see ``http://www.nominum.com''.
- */
-
-#include "dhcpd.h"
-#include <omapip/omapip_p.h>
-
-#include "minires.h"
-#include "arpa/nameser.h"
-
-#include <errno.h>
-
-#if defined(TRACING)
-static void trace_mr_output_input (trace_type_t *, unsigned, char *);
-static void trace_mr_output_stop (trace_type_t *);
-static void trace_mr_input_input (trace_type_t *, unsigned, char *);
-static void trace_mr_input_stop (trace_type_t *);
-static void trace_mr_statp_input (trace_type_t *, unsigned, char *);
-static void trace_mr_statp_stop (trace_type_t *);
-static void trace_mr_randomid_input (trace_type_t *, unsigned, char *);
-static void trace_mr_randomid_stop (trace_type_t *);
-#endif /* TRACING */
-trace_type_t *trace_mr_output;
-trace_type_t *trace_mr_input;
-trace_type_t *trace_mr_statp;
-trace_type_t *trace_mr_randomid;
-ssize_t trace_mr_send (int, void *, size_t, int);
-ssize_t trace_mr_read_playback (struct sockaddr_in *, void *, size_t);
-void trace_mr_read_record (struct sockaddr_in *, void *, ssize_t);
-ssize_t trace_mr_recvfrom (int s, void *, size_t, int,
- struct sockaddr *, SOCKLEN_T *);
-ssize_t trace_mr_read (int, void *, size_t);
-int trace_mr_connect (int s, struct sockaddr *, SOCKLEN_T);
-int trace_mr_socket (int, int, int);
-int trace_mr_bind (int, struct sockaddr *, SOCKLEN_T);
-int trace_mr_close (int);
-time_t trace_mr_time (time_t *);
-int trace_mr_select (int, fd_set *, fd_set *, fd_set *, struct timeval *);
-unsigned int trace_mr_res_randomid (unsigned int);
-
-#if defined (TRACING)
-void trace_mr_init ()
-{
- trace_mr_output = trace_type_register ("mr-output", (void *)0,
- trace_mr_output_input,
- trace_mr_output_stop, MDL);
- trace_mr_input = trace_type_register ("mr-input", (void *)0,
- trace_mr_input_input,
- trace_mr_input_stop, MDL);
- trace_mr_statp = trace_type_register ("mr-statp", (void *)0,
- trace_mr_statp_input,
- trace_mr_statp_stop, MDL);
- trace_mr_randomid = trace_type_register ("mr-randomid", (void *)0,
- trace_mr_randomid_input,
- trace_mr_randomid_stop, MDL);
-}
-
-#if 0
-void trace_mr_statp_setup (res_state statp)
-{
- unsigned buflen = 0;
- char *buf = (char *)0;
- isc_result_t status;
- int i;
-
- if (trace_playback ()) {
- int nscount;
- status = trace_get_packet (&trace_mr_statp, &buflen, &buf);
- if (status != ISC_R_SUCCESS) {
- log_error ("trace_mr_statp: no statp packet found.");
- return;
- }
- nscount = buflen / sizeof (struct in_addr);
- if (nscount * (sizeof (struct in_addr)) != buflen ||
- nscount < 1) {
- log_error ("trace_mr_statp: bogus length: %d",
- buflen);
- return;
- }
- if (nscount > MAXNS)
- nscount = MAXNS;
- for (i = 0; i < nscount; i++) {
-#if defined (HAVE_SA_LEN)
- statp -> nsaddr_list [i].sin_len =
- sizeof (struct sockaddr_in);
-#endif
- memset (&statp -> nsaddr_list [i].sin_zero, 0,
- sizeof statp -> nsaddr_list [i].sin_zero);
- statp -> nsaddr_list [i].sin_port = htons (53); /*XXX*/
- statp -> nsaddr_list [i].sin_family = AF_INET;
- memcpy (&statp -> nsaddr_list [i].sin_addr,
- (buf + i * (sizeof (struct in_addr))),
- sizeof (struct in_addr));
- }
- statp -> nscount = nscount;
- dfree (buf, MDL);
- buf = (char *)0;
- }
- if (trace_record ()) {
- trace_iov_t *iov;
- iov = dmalloc ((statp -> nscount *
- sizeof (trace_iov_t)), MDL);
- if (!iov) {
- trace_stop ();
- log_error ("No memory for statp iov.");
- return;
- }
- for (i = 0; i < statp -> nscount; i++) {
- iov [i].buf =
- (char *)&statp -> nsaddr_list [i].sin_addr;
- iov [i].len = sizeof (struct in_addr);
- }
- trace_write_packet_iov (trace_mr_statp, i, iov, MDL);
- dfree (iov, MDL);
- }
-}
-#endif
-#endif
-
-ssize_t trace_mr_send (int fd, void *msg, size_t len, int flags)
-{
- ssize_t rv;
-#if defined (TRACING)
- isc_result_t status;
- unsigned buflen = 0;
- char *inbuf = (char *)0;
- u_int32_t result;
- u_int32_t sflags;
-
- if (trace_playback()) {
- status = trace_get_packet (&trace_mr_output, &buflen, &inbuf);
- if (status != ISC_R_SUCCESS) {
- log_error ("trace_mr_recvfrom: no input found.");
- errno = ECONNREFUSED;
- return -1;
- }
- if (buflen < sizeof result) {
- log_error ("trace_mr_recvfrom: data too short.");
- errno = ECONNREFUSED;
- dfree (inbuf, MDL);
- return -1;
- }
- memcpy (&result, inbuf, sizeof result);
- rv = ntohl (result);
- dfree (inbuf, MDL);
- } else
-#endif
- rv = send (fd, msg, len, flags);
-#if defined (TRACING)
- if (trace_record ()) {
- trace_iov_t iov [3];
- result = htonl (rv);
- sflags = htonl (flags);
- iov [0].len = sizeof result;
- iov [0].buf = (char *)&result;
- iov [1].len = sizeof sflags;
- iov [1].buf = (char *)&flags;
- iov [2].len = len;
- iov [2].buf = msg;
- trace_write_packet_iov (trace_mr_output, 3, iov, MDL);
- }
-#endif
- return rv;
-}
-
-#if defined (TRACING)
-ssize_t trace_mr_read_playback (struct sockaddr_in *from,
- void *buf, size_t nbytes)
-{
- isc_result_t status;
- unsigned buflen = 0, left;
- char *inbuf = (char *)0;
- char *bufp;
- u_int32_t result;
-
- status = trace_get_packet (&trace_mr_input, &buflen, &inbuf);
- if (status != ISC_R_SUCCESS) {
- log_error ("trace_mr_recvfrom: no input found.");
- errno = ECONNREFUSED;
- return -1;
- }
- if (buflen < sizeof result) {
- log_error ("trace_mr_recvfrom: data too short.");
- errno = ECONNREFUSED;
- dfree (inbuf, MDL);
- return -1;
- }
- bufp = inbuf;
- left = buflen;
- memcpy (&result, bufp, sizeof result);
- result = ntohl (result);
- bufp += sizeof result;
- left -= sizeof result;
- if (result == 0) {
- if (left < ((sizeof from -> sin_port) +
- sizeof (from -> sin_addr))) {
- log_error ("trace_mr_recvfrom: data too short.");
- errno = ECONNREFUSED;
- dfree (inbuf, MDL);
- return -1;
- }
- if (from)
- memcpy (&from -> sin_addr, bufp,
- sizeof from -> sin_addr);
- bufp += sizeof from -> sin_addr;
- left -= sizeof from -> sin_addr;
- if (from)
- memcpy (&from -> sin_port, bufp,
- sizeof from -> sin_port);
- bufp += sizeof from -> sin_port;
- left -= sizeof from -> sin_port;
- if (from) {
- from -> sin_family = AF_INET;
-#if defined(HAVE_SA_LEN)
- from -> sin_len = sizeof (struct sockaddr_in);
-#endif
- memset (from -> sin_zero, 0, sizeof from -> sin_zero);
- }
- if (left > nbytes) {
- log_error ("trace_mr_recvfrom: too much%s",
- " data.");
- errno = ECONNREFUSED;
- dfree (inbuf, MDL);
- return -1;
- }
- memcpy (buf, bufp, left);
- dfree (inbuf, MDL);
- return left;
- }
- errno = ECONNREFUSED;
- return -1;
-}
-
-void trace_mr_read_record (struct sockaddr_in *from, void *buf, ssize_t rv)
-{
- trace_iov_t iov [4];
- u_int32_t result;
- int iolen = 0;
- static char zero [4] = { 0, 0, 0, 0 };
-
- if (rv < 0)
- result = htonl (errno); /* XXX */
- else
- result = 0;
- iov [iolen].buf = (char *)&result;
- iov [iolen++].len = sizeof result;
- if (rv > 0) {
- if (from) {
- iov [iolen].buf = (char *)&from -> sin_addr;
- iov [iolen++].len = sizeof from -> sin_addr;
- iov [iolen].buf = (char *)&from -> sin_port;
- iov [iolen++].len = sizeof from -> sin_port;
- } else {
- iov [iolen].buf = zero;
- iov [iolen++].len = sizeof from -> sin_addr;
- iov [iolen].buf = zero;
- iov [iolen++].len = sizeof from -> sin_port;
- }
-
- iov [iolen].buf = buf;
- iov [iolen++].len = rv;
- }
- trace_write_packet_iov (trace_mr_input, iolen, iov, MDL);
-}
-#endif
-
-ssize_t trace_mr_recvfrom (int s, void *buf, size_t len, int flags,
- struct sockaddr *from, SOCKLEN_T *fromlen)
-{
- ssize_t rv;
-
-#if defined (TRACING)
- if (trace_playback ())
- rv = trace_mr_read_playback ((struct sockaddr_in *)from,
- buf, len);
- else
-#endif
- rv = recvfrom (s, buf, len, flags, from, fromlen);
-#if defined (TRACING)
- if (trace_record ()) {
- trace_mr_read_record ((struct sockaddr_in *)from, buf, rv);
- }
-#endif
- return rv;
-}
-
-ssize_t trace_mr_read (int d, void *buf, size_t nbytes)
-{
- ssize_t rv;
-
-#if defined (TRACING)
- if (trace_playback ())
- rv = trace_mr_read_playback ((struct sockaddr_in *)0,
- buf, nbytes);
- else
-#endif
- rv = read (d, buf, nbytes);
-#if defined (TRACING)
- if (trace_record ()) {
- trace_mr_read_record ((struct sockaddr_in *)0, buf, rv);
- }
-#endif
- return rv;
-}
-
-int trace_mr_connect (int s, struct sockaddr *name, SOCKLEN_T namelen)
-{
-#if defined (TRACING)
- if (!trace_playback ())
-#endif
- return connect (s, name, namelen);
-#if defined (TRACING)
- return 0;
-#endif
-}
-
-int trace_mr_socket (int domain, int type, int protocol)
-{
-#if defined (TRACING)
- if (!trace_playback ())
-#endif
- return socket (domain, type, protocol);
-#if defined (TRACING)
- return 100;
-#endif
-}
-
-int trace_mr_bind (int s, struct sockaddr *name, SOCKLEN_T namelen)
-{
-#if defined (TRACING)
- if (!trace_playback ())
-#endif
- return bind (s, name, namelen);
-#if defined (TRACING)
- return 0;
-#endif
-}
-
-int trace_mr_close (int s)
-{
-#if defined (TRACING)
- if (!trace_playback ())
-#endif
- return close (s);
-#if defined (TRACING)
- return 0;
-#endif
-}
-
-time_t trace_mr_time (time_t *tp)
-{
-#if defined (TRACING)
- if (trace_playback ()) {
- if (tp)
- *tp = cur_time;
- return cur_time;
- }
-#endif
- return time (tp);
-}
-
-int trace_mr_select (int s, fd_set *r, fd_set *w, fd_set *x, struct timeval *t)
-{
-#if defined (TRACING)
- trace_type_t *ttp = (trace_type_t *)0;
-
- if (trace_playback ()) {
- time_t nct = trace_snoop_time (&ttp);
- time_t secr = t -> tv_sec;
- t -> tv_sec = nct - cur_time;
- if (t -> tv_sec > secr)
- return 0;
- if (ttp == trace_mr_input)
- return 1;
- return 0;
- }
-#endif
- return select (s, r, w, x, t);
-}
-
-unsigned int trace_mr_res_randomid (unsigned int oldid)
-{
- int rid = oldid;
-#if defined (TRACING)
- u_int32_t id;
- unsigned buflen = 0;
- char *buf = (char *)0;
- isc_result_t status;
-
- if (trace_playback ()) {
- status = trace_get_packet (&trace_mr_randomid, &buflen, &buf);
- if (status != ISC_R_SUCCESS) {
- log_error ("trace_mr_statp: no statp packet found.");
- return oldid;
- }
- if (buflen != sizeof id) {
- log_error ("trace_mr_randomid: bogus length: %d",
- buflen);
- return oldid;
- }
- memcpy (&id, buf, sizeof id);
- dfree (buf, MDL);
- buf = (char *)0;
- rid = ntohl (id);
- }
- if (trace_record ()) {
- id = htonl (rid);
- trace_write_packet (trace_mr_randomid,
- sizeof id, (char *)&id, MDL);
- }
-#endif
- return rid;
-}
-
-#if defined (TRACING)
-static void trace_mr_output_input (trace_type_t *ttype,
- unsigned length, char *buf)
-{
-}
-
-static void trace_mr_output_stop (trace_type_t *ttype)
-{
-}
-
-static void trace_mr_input_input (trace_type_t *ttype,
- unsigned length, char *buf)
-{
- log_error ("unaccounted-for minires input.");
-}
-
-static void trace_mr_input_stop (trace_type_t *ttype)
-{
-}
-
-static void trace_mr_statp_input (trace_type_t *ttype,
- unsigned length, char *buf)
-{
- log_error ("unaccounted-for minires statp input.");
-}
-
-static void trace_mr_statp_stop (trace_type_t *ttype)
-{
-}
-
-static void trace_mr_randomid_input (trace_type_t *ttype,
- unsigned length, char *buf)
-{
- log_error ("unaccounted-for minires randomid input.");
-}
-
-static void trace_mr_randomid_stop (trace_type_t *ttype)
-{
-}
-#endif
omapi_listener_trace_setup ();
omapi_connection_trace_setup ();
omapi_buffer_trace_setup ();
- trace_mr_init ();
#endif
/* This seems silly, but leave it. */
return(ISC_R_SUCCESS);
}
-
-#if 0
-isc_result_t
-ddns_get_lease(dhcp_ddns_cb_t *ddns_cb)
-{
- isc_result_t result = ISC_R_FAILURE;
-
- if (ddns_cb->address.len == 4) {
- struct lease **lease = (struct lease **)(&(ddns_cb->lease));
- if (find_lease_by_ip_addr(lease, ddns_cb->address, MDL) != 0) {
- ddns_cb->scope = &((*lease)->scope);
- result = ISC_R_SUCCESS;
- }
- }
- else if (ddns_cb->address.len == 16) {
- struct ipv6_pool *pool = NULL;
- struct iasubopt **lease = (struct iasubopt **)(&(ddns_cb->lease));
- struct in6_addr addr;
-
- memcpy(&addr, &ddns_cb->address.iabuf, 16);
- if ((find_ipv6_pool(&pool, D6O_IA_TA, &addr) !=
- ISC_R_SUCCESS) &&
- (find_ipv6_pool(&pool, D6O_IA_NA, &addr) !=
- ISC_R_SUCCESS)) {
- return(ISC_R_FAILURE);
- }
-
- if (iasubopt_hash_lookup(lease, pool->leases,
- &addr, 16, MDL)) {
- ddns_cb->scope = &((*lease)->scope);
- result = ISC_R_SUCCESS;
- }
- ipv6_pool_dereference(&pool, MDL);
- }
- else {
- log_fatal("Impossible condition at %s:%d.", MDL);
- }
-
- return(result);
-}
-
-isc_result_t
-ddns_write_lease(dhcp_ddns_cb_t *ddns_cb)
-{
-
- if (ddns_cb->address.len == 4) {
- struct lease **lease = (struct lease **)(&(ddns_cb->lease));
-
- write_lease(*lease);
- ddns_cb->scope = NULL;
- lease_dereference(lease, MDL);
- }
- else if (ddns_cb->address.len == 16) {
- struct iasubopt **lease = (struct iasubopt **)(&(ddns_cb->lease));
- /*sar*/
- /* Hmmm, this seems to be what we do elsewhere, but I'm
- not sure this is writing the scope info */
- write_ia((*lease)->ia);
- ddns_cb->scope = NULL;
- iasubopt_dereference(lease, MDL);
- }
- else {
- log_fatal("Impossible condition at %s:%d.", MDL);
- }
-
- return(ISC_R_SUCCESS);
-}
-#endif
-
/*
* Utility function to update the pointer to the DDNS control block
* in a lease.
isc_result_t eresult)
{
if (eresult == ISC_R_SUCCESS) {
- log_info("added reverse map from %.*s to %.*s",
+ log_info("Added reverse map from %.*s to %.*s",
(int)ddns_cb->rev_name.len,
(const char *)ddns_cb->rev_name.data,
(int)ddns_cb->fwd_name.len,
ddns_update_lease_text(ddns_cb, NULL);
} else {
- log_error("unable to add reverse map from %.*s to %.*s: %s",
+ log_error("Unable to add reverse map from %.*s to %.*s: %s",
(int)ddns_cb->rev_name.len,
(const char *)ddns_cb->rev_name.data,
(int)ddns_cb->fwd_name.len,
switch(eresult) {
case ISC_R_SUCCESS:
- log_info("removed reverse map on %.*s",
+ log_info("Removed reverse map on %.*s",
(int)ddns_cb->rev_name.len,
(const char *)ddns_cb->rev_name.data);
/* fall through */
break;
default:
- log_error("can't remove reverse map on %.*s: %s",
+ log_error("Can't remove reverse map on %.*s: %s",
(int)ddns_cb->rev_name.len,
(const char *)ddns_cb->rev_name.data,
isc_result_totext (eresult));
isc_result_t eresult)
{
isc_result_t result = eresult;
+ char ddns_address[
+ sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
switch(eresult) {
case ISC_R_SUCCESS:
+ /* Construct a printable form of the address for logging */
+ strcpy(ddns_address, piaddr(ddns_cb->address));
+ log_info("Removed forward map from %.*s to %s",
+ (int)ddns_cb->fwd_name.len,
+ (const char*)ddns_cb->fwd_name.data,
+ ddns_address);
+
/* Do the second step of the FWD removal */
ddns_cb->state = DDNS_STATE_REM_FW_NXRR;
ddns_cb->cur_func = ddns_fwd_srv_rem2;
trace_srandom = trace_type_register ("random-seed", (void *)0,
trace_seed_input,
trace_seed_stop, MDL);
+ trace_ddns_init();
#endif
#if defined (PARANOIA)