Annotation of embedaddon/dhcp/omapip/mrtrace.c, revision 1.1
1.1 ! misho 1: /* mrtrace.c
! 2:
! 3: Subroutines that support minires tracing... */
! 4:
! 5: /*
! 6: * Copyright (c) 2004,2007,2009 by Internet Systems Consortium, Inc. ("ISC")
! 7: * Copyright (c) 2001-2003 by Internet Software Consortium
! 8: *
! 9: * Permission to use, copy, modify, and distribute this software for any
! 10: * purpose with or without fee is hereby granted, provided that the above
! 11: * copyright notice and this permission notice appear in all copies.
! 12: *
! 13: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
! 14: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 15: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
! 16: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 17: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 18: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
! 19: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 20: *
! 21: * Internet Systems Consortium, Inc.
! 22: * 950 Charter Street
! 23: * Redwood City, CA 94063
! 24: * <info@isc.org>
! 25: * https://www.isc.org/
! 26: *
! 27: * This software has been written for Internet Systems Consortium
! 28: * by Ted Lemon, as part of a project for Nominum, Inc. To learn more
! 29: * about Internet Systems Consortium, see https://www.isc.org/. To
! 30: * learn more about Nominum, Inc., see ``http://www.nominum.com''.
! 31: */
! 32:
! 33: #include "dhcpd.h"
! 34: #include <omapip/omapip_p.h>
! 35:
! 36: #include "minires/minires.h"
! 37: #include "arpa/nameser.h"
! 38:
! 39: #include <errno.h>
! 40:
! 41: #if defined(TRACING)
! 42: static void trace_mr_output_input (trace_type_t *, unsigned, char *);
! 43: static void trace_mr_output_stop (trace_type_t *);
! 44: static void trace_mr_input_input (trace_type_t *, unsigned, char *);
! 45: static void trace_mr_input_stop (trace_type_t *);
! 46: static void trace_mr_statp_input (trace_type_t *, unsigned, char *);
! 47: static void trace_mr_statp_stop (trace_type_t *);
! 48: static void trace_mr_randomid_input (trace_type_t *, unsigned, char *);
! 49: static void trace_mr_randomid_stop (trace_type_t *);
! 50: #endif /* TRACING */
! 51: trace_type_t *trace_mr_output;
! 52: trace_type_t *trace_mr_input;
! 53: trace_type_t *trace_mr_statp;
! 54: trace_type_t *trace_mr_randomid;
! 55: ssize_t trace_mr_send (int, void *, size_t, int);
! 56: ssize_t trace_mr_read_playback (struct sockaddr_in *, void *, size_t);
! 57: void trace_mr_read_record (struct sockaddr_in *, void *, ssize_t);
! 58: ssize_t trace_mr_recvfrom (int s, void *, size_t, int,
! 59: struct sockaddr *, SOCKLEN_T *);
! 60: ssize_t trace_mr_read (int, void *, size_t);
! 61: int trace_mr_connect (int s, struct sockaddr *, SOCKLEN_T);
! 62: int trace_mr_socket (int, int, int);
! 63: int trace_mr_bind (int, struct sockaddr *, SOCKLEN_T);
! 64: int trace_mr_close (int);
! 65: time_t trace_mr_time (time_t *);
! 66: int trace_mr_select (int, fd_set *, fd_set *, fd_set *, struct timeval *);
! 67: unsigned int trace_mr_res_randomid (unsigned int);
! 68:
! 69: #if defined (TRACING)
! 70: void trace_mr_init ()
! 71: {
! 72: trace_mr_output = trace_type_register ("mr-output", (void *)0,
! 73: trace_mr_output_input,
! 74: trace_mr_output_stop, MDL);
! 75: trace_mr_input = trace_type_register ("mr-input", (void *)0,
! 76: trace_mr_input_input,
! 77: trace_mr_input_stop, MDL);
! 78: trace_mr_statp = trace_type_register ("mr-statp", (void *)0,
! 79: trace_mr_statp_input,
! 80: trace_mr_statp_stop, MDL);
! 81: trace_mr_randomid = trace_type_register ("mr-randomid", (void *)0,
! 82: trace_mr_randomid_input,
! 83: trace_mr_randomid_stop, MDL);
! 84: }
! 85:
! 86: void trace_mr_statp_setup (res_state statp)
! 87: {
! 88: unsigned buflen = 0;
! 89: char *buf = (char *)0;
! 90: isc_result_t status;
! 91: int i;
! 92:
! 93: if (trace_playback ()) {
! 94: int nscount;
! 95: status = trace_get_packet (&trace_mr_statp, &buflen, &buf);
! 96: if (status != ISC_R_SUCCESS) {
! 97: log_error ("trace_mr_statp: no statp packet found.");
! 98: return;
! 99: }
! 100: nscount = buflen / sizeof (struct in_addr);
! 101: if (nscount * (sizeof (struct in_addr)) != buflen ||
! 102: nscount < 1) {
! 103: log_error ("trace_mr_statp: bogus length: %d",
! 104: buflen);
! 105: return;
! 106: }
! 107: if (nscount > MAXNS)
! 108: nscount = MAXNS;
! 109: for (i = 0; i < nscount; i++) {
! 110: #if defined (HAVE_SA_LEN)
! 111: statp -> nsaddr_list [i].sin_len =
! 112: sizeof (struct sockaddr_in);
! 113: #endif
! 114: memset (&statp -> nsaddr_list [i].sin_zero, 0,
! 115: sizeof statp -> nsaddr_list [i].sin_zero);
! 116: statp -> nsaddr_list [i].sin_port = htons (53); /*XXX*/
! 117: statp -> nsaddr_list [i].sin_family = AF_INET;
! 118: memcpy (&statp -> nsaddr_list [i].sin_addr,
! 119: (buf + i * (sizeof (struct in_addr))),
! 120: sizeof (struct in_addr));
! 121: }
! 122: statp -> nscount = nscount;
! 123: dfree (buf, MDL);
! 124: buf = (char *)0;
! 125: }
! 126: if (trace_record ()) {
! 127: trace_iov_t *iov;
! 128: iov = dmalloc ((statp -> nscount *
! 129: sizeof (trace_iov_t)), MDL);
! 130: if (!iov) {
! 131: trace_stop ();
! 132: log_error ("No memory for statp iov.");
! 133: return;
! 134: }
! 135: for (i = 0; i < statp -> nscount; i++) {
! 136: iov [i].buf =
! 137: (char *)&statp -> nsaddr_list [i].sin_addr;
! 138: iov [i].len = sizeof (struct in_addr);
! 139: }
! 140: trace_write_packet_iov (trace_mr_statp, i, iov, MDL);
! 141: dfree (iov, MDL);
! 142: }
! 143: }
! 144: #endif
! 145:
! 146: ssize_t trace_mr_send (int fd, void *msg, size_t len, int flags)
! 147: {
! 148: ssize_t rv;
! 149: #if defined (TRACING)
! 150: isc_result_t status;
! 151: unsigned buflen = 0;
! 152: char *inbuf = (char *)0;
! 153: u_int32_t result;
! 154: u_int32_t sflags;
! 155:
! 156: if (trace_playback()) {
! 157: status = trace_get_packet (&trace_mr_output, &buflen, &inbuf);
! 158: if (status != ISC_R_SUCCESS) {
! 159: log_error ("trace_mr_recvfrom: no input found.");
! 160: errno = ECONNREFUSED;
! 161: return -1;
! 162: }
! 163: if (buflen < sizeof result) {
! 164: log_error ("trace_mr_recvfrom: data too short.");
! 165: errno = ECONNREFUSED;
! 166: dfree (inbuf, MDL);
! 167: return -1;
! 168: }
! 169: memcpy (&result, inbuf, sizeof result);
! 170: rv = ntohl (result);
! 171: dfree (inbuf, MDL);
! 172: } else
! 173: #endif
! 174: rv = send (fd, msg, len, flags);
! 175: #if defined (TRACING)
! 176: if (trace_record ()) {
! 177: trace_iov_t iov [3];
! 178: result = htonl (rv);
! 179: sflags = htonl (flags);
! 180: iov [0].len = sizeof result;
! 181: iov [0].buf = (char *)&result;
! 182: iov [1].len = sizeof sflags;
! 183: iov [1].buf = (char *)&flags;
! 184: iov [2].len = len;
! 185: iov [2].buf = msg;
! 186: trace_write_packet_iov (trace_mr_output, 3, iov, MDL);
! 187: }
! 188: #endif
! 189: return rv;
! 190: }
! 191:
! 192: #if defined (TRACING)
! 193: ssize_t trace_mr_read_playback (struct sockaddr_in *from,
! 194: void *buf, size_t nbytes)
! 195: {
! 196: isc_result_t status;
! 197: unsigned buflen = 0, left;
! 198: char *inbuf = (char *)0;
! 199: char *bufp;
! 200: u_int32_t result;
! 201:
! 202: status = trace_get_packet (&trace_mr_input, &buflen, &inbuf);
! 203: if (status != ISC_R_SUCCESS) {
! 204: log_error ("trace_mr_recvfrom: no input found.");
! 205: errno = ECONNREFUSED;
! 206: return -1;
! 207: }
! 208: if (buflen < sizeof result) {
! 209: log_error ("trace_mr_recvfrom: data too short.");
! 210: errno = ECONNREFUSED;
! 211: dfree (inbuf, MDL);
! 212: return -1;
! 213: }
! 214: bufp = inbuf;
! 215: left = buflen;
! 216: memcpy (&result, bufp, sizeof result);
! 217: result = ntohl (result);
! 218: bufp += sizeof result;
! 219: left -= sizeof result;
! 220: if (result == 0) {
! 221: if (left < ((sizeof from -> sin_port) +
! 222: sizeof (from -> sin_addr))) {
! 223: log_error ("trace_mr_recvfrom: data too short.");
! 224: errno = ECONNREFUSED;
! 225: dfree (inbuf, MDL);
! 226: return -1;
! 227: }
! 228: if (from)
! 229: memcpy (&from -> sin_addr, bufp,
! 230: sizeof from -> sin_addr);
! 231: bufp += sizeof from -> sin_addr;
! 232: left -= sizeof from -> sin_addr;
! 233: if (from)
! 234: memcpy (&from -> sin_port, bufp,
! 235: sizeof from -> sin_port);
! 236: bufp += sizeof from -> sin_port;
! 237: left -= sizeof from -> sin_port;
! 238: if (from) {
! 239: from -> sin_family = AF_INET;
! 240: #if defined(HAVE_SA_LEN)
! 241: from -> sin_len = sizeof (struct sockaddr_in);
! 242: #endif
! 243: memset (from -> sin_zero, 0, sizeof from -> sin_zero);
! 244: }
! 245: if (left > nbytes) {
! 246: log_error ("trace_mr_recvfrom: too much%s",
! 247: " data.");
! 248: errno = ECONNREFUSED;
! 249: dfree (inbuf, MDL);
! 250: return -1;
! 251: }
! 252: memcpy (buf, bufp, left);
! 253: dfree (inbuf, MDL);
! 254: return left;
! 255: }
! 256: errno = ECONNREFUSED;
! 257: return -1;
! 258: }
! 259:
! 260: void trace_mr_read_record (struct sockaddr_in *from, void *buf, ssize_t rv)
! 261: {
! 262: trace_iov_t iov [4];
! 263: u_int32_t result;
! 264: int iolen = 0;
! 265: static char zero [4] = { 0, 0, 0, 0 };
! 266:
! 267: if (rv < 0)
! 268: result = htonl (errno); /* XXX */
! 269: else
! 270: result = 0;
! 271: iov [iolen].buf = (char *)&result;
! 272: iov [iolen++].len = sizeof result;
! 273: if (rv > 0) {
! 274: if (from) {
! 275: iov [iolen].buf = (char *)&from -> sin_addr;
! 276: iov [iolen++].len = sizeof from -> sin_addr;
! 277: iov [iolen].buf = (char *)&from -> sin_port;
! 278: iov [iolen++].len = sizeof from -> sin_port;
! 279: } else {
! 280: iov [iolen].buf = zero;
! 281: iov [iolen++].len = sizeof from -> sin_addr;
! 282: iov [iolen].buf = zero;
! 283: iov [iolen++].len = sizeof from -> sin_port;
! 284: }
! 285:
! 286: iov [iolen].buf = buf;
! 287: iov [iolen++].len = rv;
! 288: }
! 289: trace_write_packet_iov (trace_mr_input, iolen, iov, MDL);
! 290: }
! 291: #endif
! 292:
! 293: ssize_t trace_mr_recvfrom (int s, void *buf, size_t len, int flags,
! 294: struct sockaddr *from, SOCKLEN_T *fromlen)
! 295: {
! 296: ssize_t rv;
! 297:
! 298: #if defined (TRACING)
! 299: if (trace_playback ())
! 300: rv = trace_mr_read_playback ((struct sockaddr_in *)from,
! 301: buf, len);
! 302: else
! 303: #endif
! 304: rv = recvfrom (s, buf, len, flags, from, fromlen);
! 305: #if defined (TRACING)
! 306: if (trace_record ()) {
! 307: trace_mr_read_record ((struct sockaddr_in *)from, buf, rv);
! 308: }
! 309: #endif
! 310: return rv;
! 311: }
! 312:
! 313: ssize_t trace_mr_read (int d, void *buf, size_t nbytes)
! 314: {
! 315: ssize_t rv;
! 316:
! 317: #if defined (TRACING)
! 318: if (trace_playback ())
! 319: rv = trace_mr_read_playback ((struct sockaddr_in *)0,
! 320: buf, nbytes);
! 321: else
! 322: #endif
! 323: rv = read (d, buf, nbytes);
! 324: #if defined (TRACING)
! 325: if (trace_record ()) {
! 326: trace_mr_read_record ((struct sockaddr_in *)0, buf, rv);
! 327: }
! 328: #endif
! 329: return rv;
! 330: }
! 331:
! 332: int trace_mr_connect (int s, struct sockaddr *name, SOCKLEN_T namelen)
! 333: {
! 334: #if defined (TRACING)
! 335: if (!trace_playback ())
! 336: #endif
! 337: return connect (s, name, namelen);
! 338: #if defined (TRACING)
! 339: return 0;
! 340: #endif
! 341: }
! 342:
! 343: int trace_mr_socket (int domain, int type, int protocol)
! 344: {
! 345: #if defined (TRACING)
! 346: if (!trace_playback ())
! 347: #endif
! 348: return socket (domain, type, protocol);
! 349: #if defined (TRACING)
! 350: return 100;
! 351: #endif
! 352: }
! 353:
! 354: int trace_mr_bind (int s, struct sockaddr *name, SOCKLEN_T namelen)
! 355: {
! 356: #if defined (TRACING)
! 357: if (!trace_playback ())
! 358: #endif
! 359: return bind (s, name, namelen);
! 360: #if defined (TRACING)
! 361: return 0;
! 362: #endif
! 363: }
! 364:
! 365: int trace_mr_close (int s)
! 366: {
! 367: #if defined (TRACING)
! 368: if (!trace_playback ())
! 369: #endif
! 370: return close (s);
! 371: #if defined (TRACING)
! 372: return 0;
! 373: #endif
! 374: }
! 375:
! 376: time_t trace_mr_time (time_t *tp)
! 377: {
! 378: #if defined (TRACING)
! 379: if (trace_playback ()) {
! 380: if (tp)
! 381: *tp = cur_time;
! 382: return cur_time;
! 383: }
! 384: #endif
! 385: return time (tp);
! 386: }
! 387:
! 388: int trace_mr_select (int s, fd_set *r, fd_set *w, fd_set *x, struct timeval *t)
! 389: {
! 390: #if defined (TRACING)
! 391: trace_type_t *ttp = (trace_type_t *)0;
! 392:
! 393: if (trace_playback ()) {
! 394: time_t nct = trace_snoop_time (&ttp);
! 395: time_t secr = t -> tv_sec;
! 396: t -> tv_sec = nct - cur_time;
! 397: if (t -> tv_sec > secr)
! 398: return 0;
! 399: if (ttp == trace_mr_input)
! 400: return 1;
! 401: return 0;
! 402: }
! 403: #endif
! 404: return select (s, r, w, x, t);
! 405: }
! 406:
! 407: unsigned int trace_mr_res_randomid (unsigned int oldid)
! 408: {
! 409: int rid = oldid;
! 410: #if defined (TRACING)
! 411: u_int32_t id;
! 412: unsigned buflen = 0;
! 413: char *buf = (char *)0;
! 414: isc_result_t status;
! 415:
! 416: if (trace_playback ()) {
! 417: status = trace_get_packet (&trace_mr_randomid, &buflen, &buf);
! 418: if (status != ISC_R_SUCCESS) {
! 419: log_error ("trace_mr_statp: no statp packet found.");
! 420: return oldid;
! 421: }
! 422: if (buflen != sizeof id) {
! 423: log_error ("trace_mr_randomid: bogus length: %d",
! 424: buflen);
! 425: return oldid;
! 426: }
! 427: memcpy (&id, buf, sizeof id);
! 428: dfree (buf, MDL);
! 429: buf = (char *)0;
! 430: rid = ntohl (id);
! 431: }
! 432: if (trace_record ()) {
! 433: id = htonl (rid);
! 434: trace_write_packet (trace_mr_randomid,
! 435: sizeof id, (char *)&id, MDL);
! 436: }
! 437: #endif
! 438: return rid;
! 439: }
! 440:
! 441: #if defined (TRACING)
! 442: static void trace_mr_output_input (trace_type_t *ttype,
! 443: unsigned length, char *buf)
! 444: {
! 445: }
! 446:
! 447: static void trace_mr_output_stop (trace_type_t *ttype)
! 448: {
! 449: }
! 450:
! 451: static void trace_mr_input_input (trace_type_t *ttype,
! 452: unsigned length, char *buf)
! 453: {
! 454: log_error ("unaccounted-for minires input.");
! 455: }
! 456:
! 457: static void trace_mr_input_stop (trace_type_t *ttype)
! 458: {
! 459: }
! 460:
! 461: static void trace_mr_statp_input (trace_type_t *ttype,
! 462: unsigned length, char *buf)
! 463: {
! 464: log_error ("unaccounted-for minires statp input.");
! 465: }
! 466:
! 467: static void trace_mr_statp_stop (trace_type_t *ttype)
! 468: {
! 469: }
! 470:
! 471: static void trace_mr_randomid_input (trace_type_t *ttype,
! 472: unsigned length, char *buf)
! 473: {
! 474: log_error ("unaccounted-for minires randomid input.");
! 475: }
! 476:
! 477: static void trace_mr_randomid_stop (trace_type_t *ttype)
! 478: {
! 479: }
! 480: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>