3 Subroutines that support minires tracing... */
6 * Copyright (c) 2001 Internet Software Consortium.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 * of its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon, as part of a project for Nominum, Inc. To learn more
38 * about the Internet Software Consortium, see http://www.isc.org/. To
39 * learn more about Nominum, Inc., see ``http://www.nominum.com''.
42 #include <omapip/omapip_p.h>
44 #include "minires/minires.h"
45 #include "arpa/nameser.h"
47 static void trace_mr_output_input (trace_type_t *, unsigned, char *);
48 static void trace_mr_output_stop (trace_type_t *);
49 static void trace_mr_input_input (trace_type_t *, unsigned, char *);
50 static void trace_mr_input_stop (trace_type_t *);
51 static void trace_mr_statp_input (trace_type_t *, unsigned, char *);
52 static void trace_mr_statp_stop (trace_type_t *);
53 static void trace_mr_randomid_input (trace_type_t *, unsigned, char *);
54 static void trace_mr_randomid_stop (trace_type_t *);
55 trace_type_t *trace_mr_output;
56 trace_type_t *trace_mr_input;
57 trace_type_t *trace_mr_statp;
58 trace_type_t *trace_mr_randomid;
59 ssize_t trace_mr_send (int, void *, size_t, int);
60 ssize_t trace_mr_read_playback (struct sockaddr_in *, void *, size_t);
61 void trace_mr_read_record (struct sockaddr_in *, void *, ssize_t);
62 ssize_t trace_mr_recvfrom (int s, void *, size_t, int,
63 struct sockaddr *, SOCKLEN_T *);
64 ssize_t trace_mr_read (int, void *, size_t);
65 int trace_mr_connect (int s, struct sockaddr *, SOCKLEN_T);
66 int trace_mr_socket (int, int, int);
67 int trace_mr_bind (int, struct sockaddr *, SOCKLEN_T);
68 int trace_mr_close (int);
69 time_t trace_mr_time (time_t *);
70 int trace_mr_select (int, fd_set *, fd_set *, fd_set *, struct timeval *);
71 unsigned int trace_mr_res_randomid (unsigned int);
73 extern time_t cur_time;
78 trace_mr_output = trace_type_register ("mr-output", (void *)0,
79 trace_mr_output_input,
80 trace_mr_output_stop, MDL);
81 trace_mr_input = trace_type_register ("mr-input", (void *)0,
83 trace_mr_input_stop, MDL);
84 trace_mr_statp = trace_type_register ("mr-statp", (void *)0,
86 trace_mr_statp_stop, MDL);
87 trace_mr_randomid = trace_type_register ("mr-randomid", (void *)0,
88 trace_mr_randomid_input,
89 trace_mr_randomid_stop, MDL);
92 void trace_mr_statp_setup (res_state statp)
95 char *buf = (char *)0;
100 if (trace_playback ()) {
102 status = trace_get_packet (&trace_mr_statp, &buflen, &buf);
103 if (status != ISC_R_SUCCESS) {
104 log_error ("trace_mr_statp: no statp packet found.");
107 nscount = buflen / sizeof (struct in_addr);
108 if (nscount * (sizeof (struct in_addr)) != buflen ||
110 log_error ("trace_mr_statp: bogus length: %d",
116 for (i = 0; i < nscount; i++) {
117 #if defined (HAVE_SA_LEN)
118 statp -> nsaddr_list [i].sin_len =
119 sizeof (struct sockaddr_in);
121 memset (&statp -> nsaddr_list [i].sin_zero, 0,
122 sizeof statp -> nsaddr_list [i].sin_zero);
123 statp -> nsaddr_list [i].sin_port = htons (53); /*XXX*/
124 statp -> nsaddr_list [i].sin_family = AF_INET;
125 memcpy (&statp -> nsaddr_list [i].sin_addr,
126 (buf + i * (sizeof (struct in_addr))),
127 sizeof (struct in_addr));
129 statp -> nscount = nscount;
133 if (trace_record ()) {
135 iov = dmalloc ((statp -> nscount *
136 sizeof (trace_iov_t)), MDL);
139 log_error ("No memory for statp iov.");
142 for (i = 0; i < statp -> nscount; i++) {
144 (char *)&statp -> nsaddr_list [i].sin_addr;
145 iov [i].len = sizeof (struct in_addr);
147 trace_write_packet_iov (trace_mr_statp, i, iov, MDL);
153 ssize_t trace_mr_send (int fd, void *msg, size_t len, int flags)
156 #if defined (TRACING)
159 char *inbuf = (char *)0;
163 if (trace_playback()) {
164 status = trace_get_packet (&trace_mr_output, &buflen, &inbuf);
165 if (status != ISC_R_SUCCESS) {
166 log_error ("trace_mr_recvfrom: no input found.");
167 errno = ECONNREFUSED;
170 if (buflen < sizeof result) {
171 log_error ("trace_mr_recvfrom: data too short.");
172 errno = ECONNREFUSED;
176 memcpy (&result, inbuf, sizeof result);
181 rv = send (fd, msg, len, flags);
182 #if defined (TRACING)
183 if (trace_record ()) {
186 sflags = htonl (flags);
187 iov [0].len = sizeof result;
188 iov [0].buf = (char *)&result;
189 iov [1].len = sizeof sflags;
190 iov [1].buf = (char *)&flags;
193 trace_write_packet_iov (trace_mr_output, 2, iov, MDL);
199 #if defined (TRACING)
200 ssize_t trace_mr_read_playback (struct sockaddr_in *from,
201 void *buf, size_t nbytes)
204 unsigned buflen = 0, left;
205 char *inbuf = (char *)0;
209 status = trace_get_packet (&trace_mr_input, &buflen, &inbuf);
210 if (status != ISC_R_SUCCESS) {
211 log_error ("trace_mr_recvfrom: no input found.");
212 errno = ECONNREFUSED;
215 if (buflen < sizeof result) {
216 log_error ("trace_mr_recvfrom: data too short.");
217 errno = ECONNREFUSED;
223 memcpy (&result, bufp, sizeof result);
224 result = ntohl (result);
225 bufp += sizeof result;
226 left -= sizeof result;
228 if (left < ((sizeof from -> sin_port) +
229 sizeof (from -> sin_addr))) {
230 log_error ("trace_mr_recvfrom: data too short.");
231 errno = ECONNREFUSED;
236 memcpy (&from -> sin_addr, bufp,
237 sizeof from -> sin_addr);
238 bufp += sizeof from -> sin_addr;
239 left -= sizeof from -> sin_addr;
241 memcpy (&from -> sin_port, bufp,
242 sizeof from -> sin_port);
243 bufp += sizeof from -> sin_port;
244 left -= sizeof from -> sin_port;
246 from -> sin_family = AF_INET;
247 #if defined(HAVE_SA_LEN)
248 from -> sin_len = sizeof (struct sockaddr_in);
250 memset (from -> sin_zero, 0, sizeof from -> sin_zero);
253 log_error ("trace_mr_recvfrom: too much%s",
255 errno = ECONNREFUSED;
259 memcpy (buf, bufp, left);
263 errno = ECONNREFUSED;
267 void trace_mr_read_record (struct sockaddr_in *from, void *buf, ssize_t rv)
272 static char zero [4] = { 0, 0, 0, 0 };
275 result = htonl (errno); /* XXX */
278 iov [iolen].buf = (char *)&result;
279 iov [iolen++].len = sizeof result;
282 iov [iolen].buf = (char *)&from -> sin_addr;
283 iov [iolen++].len = sizeof from -> sin_addr;
284 iov [iolen].buf = (char *)&from -> sin_port;
285 iov [iolen++].len = sizeof from -> sin_port;
287 iov [iolen].buf = zero;
288 iov [iolen++].len = sizeof from -> sin_addr;
289 iov [iolen].buf = zero;
290 iov [iolen++].len = sizeof from -> sin_port;
293 iov [iolen].buf = buf;
294 iov [iolen++].len = rv;
296 trace_write_packet_iov (trace_mr_input, iolen, iov, MDL);
300 ssize_t trace_mr_recvfrom (int s, void *buf, size_t len, int flags,
301 struct sockaddr *from, SOCKLEN_T *fromlen)
305 #if defined (TRACING)
306 if (trace_playback ())
307 rv = trace_mr_read_playback ((struct sockaddr_in *)from,
311 rv = recvfrom (s, buf, len, flags, from, fromlen);
312 #if defined (TRACING)
313 if (trace_record ()) {
314 trace_mr_read_record ((struct sockaddr_in *)from, buf, rv);
320 ssize_t trace_mr_read (int d, void *buf, size_t nbytes)
324 #if defined (TRACING)
325 if (trace_playback ())
326 rv = trace_mr_read_playback ((struct sockaddr_in *)0,
330 rv = read (d, buf, nbytes);
331 #if defined (TRACING)
332 if (trace_record ()) {
333 trace_mr_read_record ((struct sockaddr_in *)0, buf, rv);
339 int trace_mr_connect (int s, struct sockaddr *name, SOCKLEN_T namelen)
341 #if defined (TRACING)
342 if (!trace_playback ())
344 return connect (s, name, namelen);
345 #if defined (TRACING)
350 int trace_mr_socket (int domain, int type, int protocol)
352 #if defined (TRACING)
353 if (!trace_playback ())
355 return socket (domain, type, protocol);
356 #if defined (TRACING)
361 int trace_mr_bind (int s, struct sockaddr *name, SOCKLEN_T namelen)
363 #if defined (TRACING)
364 if (!trace_playback ())
366 return bind (s, name, namelen);
367 #if defined (TRACING)
372 int trace_mr_close (int s)
374 #if defined (TRACING)
375 if (!trace_playback ())
378 #if defined (TRACING)
383 time_t trace_mr_time (time_t *tp)
385 #if defined (TRACING)
386 if (trace_playback ()) {
395 int trace_mr_select (int s, fd_set *r, fd_set *w, fd_set *x, struct timeval *t)
397 #if defined (TRACING)
398 trace_type_t *ttp = (trace_type_t *)0;
400 if (trace_playback ()) {
401 time_t nct = trace_snoop_time (&ttp);
402 time_t secr = t -> tv_sec;
403 t -> tv_sec = nct - cur_time;
404 if (t -> tv_sec > secr)
406 if (ttp == trace_mr_input)
411 return select (s, r, w, x, t);
414 unsigned int trace_mr_res_randomid (unsigned int oldid)
418 #if defined (TRACING)
420 char *buf = (char *)0;
423 if (trace_playback ()) {
425 status = trace_get_packet (&trace_mr_randomid, &buflen, &buf);
426 if (status != ISC_R_SUCCESS) {
427 log_error ("trace_mr_statp: no statp packet found.");
430 if (buflen != sizeof id) {
431 log_error ("trace_mr_randomid: bogus length: %d",
435 memcpy (&id, buf, sizeof id);
440 if (trace_record ()) {
442 trace_write_packet (trace_mr_randomid,
443 sizeof id, (char *)&id, MDL);
449 #if defined (TRACING)
450 static void trace_mr_output_input (trace_type_t *ttype,
451 unsigned length, char *buf)
455 static void trace_mr_output_stop (trace_type_t *ttype)
459 static void trace_mr_input_input (trace_type_t *ttype,
460 unsigned length, char *buf)
462 log_error ("unaccounted-for minires input.");
465 static void trace_mr_input_stop (trace_type_t *ttype)
469 static void trace_mr_statp_input (trace_type_t *ttype,
470 unsigned length, char *buf)
472 log_error ("unaccounted-for minires statp input.");
475 static void trace_mr_statp_stop (trace_type_t *ttype)
479 static void trace_mr_randomid_input (trace_type_t *ttype,
480 unsigned length, char *buf)
482 log_error ("unaccounted-for minires randomid input.");
485 static void trace_mr_randomid_stop (trace_type_t *ttype)