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