aboutsummaryrefslogtreecommitdiff
path: root/contrib/isc-dhcp/omapip/mrtrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/isc-dhcp/omapip/mrtrace.c')
-rw-r--r--contrib/isc-dhcp/omapip/mrtrace.c488
1 files changed, 488 insertions, 0 deletions
diff --git a/contrib/isc-dhcp/omapip/mrtrace.c b/contrib/isc-dhcp/omapip/mrtrace.c
new file mode 100644
index 000000000000..c3539900edfe
--- /dev/null
+++ b/contrib/isc-dhcp/omapip/mrtrace.c
@@ -0,0 +1,488 @@
+/* mrtrace.c
+
+ Subroutines that support minires tracing... */
+
+/*
+ * Copyright (c) 2001 Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon, as part of a project for Nominum, Inc. To learn more
+ * about the Internet Software Consortium, see http://www.isc.org/. To
+ * learn more about Nominum, Inc., see ``http://www.nominum.com''.
+ */
+
+#include <omapip/omapip_p.h>
+
+#include "minires/minires.h"
+#include "arpa/nameser.h"
+
+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 *);
+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);
+
+extern time_t cur_time;
+
+#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);
+}
+
+void trace_mr_statp_setup (res_state statp)
+{
+ unsigned buflen = 0;
+ char *buf = (char *)0;
+ isc_result_t status;
+ u_int32_t id;
+ 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
+
+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, 2, 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)
+{
+ u_int32_t id;
+ int rid = oldid;
+#if defined (TRACING)
+ unsigned buflen = 0;
+ char *buf = (char *)0;
+ isc_result_t status;
+
+ if (trace_playback ()) {
+ int nscount;
+ 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