File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcp / omapip / mrtrace.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:06:54 2012 UTC (11 years, 9 months ago) by misho
Branches: dhcp, MAIN
CVS tags: v4_1_R7p0, v4_1_R7, v4_1_R4, HEAD
dhcp 4.1 r7

    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>