Fix warning:
[dragonfly.git] / contrib / dhcp-3.0 / omapip / mrtrace.c
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
38 static void trace_mr_output_input (trace_type_t *, unsigned, char *);
39 static void trace_mr_output_stop (trace_type_t *);
40 static void trace_mr_input_input (trace_type_t *, unsigned, char *);
41 static void trace_mr_input_stop (trace_type_t *);
42 static void trace_mr_statp_input (trace_type_t *, unsigned, char *);
43 static void trace_mr_statp_stop (trace_type_t *);
44 static void trace_mr_randomid_input (trace_type_t *, unsigned, char *);
45 static void trace_mr_randomid_stop (trace_type_t *);
46 trace_type_t *trace_mr_output;
47 trace_type_t *trace_mr_input;
48 trace_type_t *trace_mr_statp;
49 trace_type_t *trace_mr_randomid;
50 ssize_t trace_mr_send (int, void *, size_t, int);
51 ssize_t trace_mr_read_playback (struct sockaddr_in *, void *, size_t);
52 void trace_mr_read_record (struct sockaddr_in *, void *, ssize_t);
53 ssize_t trace_mr_recvfrom (int s, void *, size_t, int,
54                            struct sockaddr *, SOCKLEN_T *);
55 ssize_t trace_mr_read (int, void *, size_t);
56 int trace_mr_connect (int s, struct sockaddr *, SOCKLEN_T);
57 int trace_mr_socket (int, int, int);
58 int trace_mr_bind (int, struct sockaddr *, SOCKLEN_T);
59 int trace_mr_close (int);
60 time_t trace_mr_time (time_t *);
61 int trace_mr_select (int, fd_set *, fd_set *, fd_set *, struct timeval *);
62 unsigned int trace_mr_res_randomid (unsigned int);
63
64 extern TIME cur_time;
65
66 #if defined (TRACING)
67 void 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
83 void trace_mr_statp_setup (res_state statp)
84 {
85         unsigned buflen = 0;
86         char *buf = (char *)0;
87         isc_result_t status;
88         u_int32_t id;
89         int i;
90
91         if (trace_playback ()) {
92                 int nscount;
93                 status = trace_get_packet (&trace_mr_statp, &buflen, &buf);
94                 if (status != ISC_R_SUCCESS) {
95                         log_error ("trace_mr_statp: no statp packet found.");
96                         return;
97                 }
98                 nscount = buflen / sizeof (struct in_addr);
99                 if (nscount * (sizeof (struct in_addr)) != buflen ||
100                     nscount < 1) {
101                         log_error ("trace_mr_statp: bogus length: %d",
102                                    buflen);
103                         return;
104                 }
105                 if (nscount > MAXNS)
106                         nscount = MAXNS;
107                 for (i = 0; i < nscount; i++) {
108 #if defined (HAVE_SA_LEN)
109                         statp -> nsaddr_list [i].sin_len =
110                                 sizeof (struct sockaddr_in);
111 #endif
112                         memset (&statp -> nsaddr_list [i].sin_zero, 0,
113                                 sizeof statp -> nsaddr_list [i].sin_zero);
114                         statp -> nsaddr_list [i].sin_port = htons (53); /*XXX*/
115                         statp -> nsaddr_list [i].sin_family = AF_INET;
116                         memcpy (&statp -> nsaddr_list [i].sin_addr,
117                                 (buf + i * (sizeof (struct in_addr))),
118                                 sizeof (struct in_addr));
119                 }
120                 statp -> nscount = nscount;
121                 dfree (buf, MDL);
122                 buf = (char *)0;
123         }
124         if (trace_record ()) {
125                 trace_iov_t *iov;
126                 iov = dmalloc ((statp -> nscount *
127                                 sizeof (trace_iov_t)), MDL);
128                 if (!iov) {
129                         trace_stop ();
130                         log_error ("No memory for statp iov.");
131                         return;
132                 }
133                 for (i = 0; i < statp -> nscount; i++) {
134                         iov [i].buf =
135                                 (char *)&statp -> nsaddr_list [i].sin_addr;
136                         iov [i].len = sizeof (struct in_addr);
137                 }
138                 trace_write_packet_iov (trace_mr_statp, i, iov, MDL);
139                 dfree (iov, MDL);
140         }
141 }
142 #endif
143
144 ssize_t trace_mr_send (int fd, void *msg, size_t len, int flags)
145 {
146         ssize_t rv;
147 #if defined (TRACING)
148         isc_result_t status;
149         unsigned buflen = 0;
150         char *inbuf = (char *)0;
151         u_int32_t result;
152         u_int32_t sflags;
153
154         if (trace_playback()) {
155                 status = trace_get_packet (&trace_mr_output, &buflen, &inbuf);
156                 if (status != ISC_R_SUCCESS) {
157                         log_error ("trace_mr_recvfrom: no input found.");
158                         errno = ECONNREFUSED;
159                         return -1;
160                 }
161                 if (buflen < sizeof result) {
162                         log_error ("trace_mr_recvfrom: data too short.");
163                         errno = ECONNREFUSED;
164                         dfree (inbuf, MDL);
165                         return -1;
166                 }
167                 memcpy (&result, inbuf, sizeof result);
168                 rv = ntohl (result);
169                 dfree (inbuf, MDL);
170         } else
171 #endif
172                 rv = send (fd, msg, len, flags);
173 #if defined (TRACING)
174         if (trace_record ()) {
175                 trace_iov_t iov [3];
176                 result = htonl (rv);
177                 sflags = htonl (flags);
178                 iov [0].len = sizeof result;
179                 iov [0].buf = (char *)&result;
180                 iov [1].len = sizeof sflags;
181                 iov [1].buf = (char *)&flags;
182                 iov [2].len = len;
183                 iov [2].buf = msg;
184                 trace_write_packet_iov (trace_mr_output, 3, iov, MDL);
185         }
186 #endif
187         return rv;
188 }
189
190 #if defined (TRACING)
191 ssize_t trace_mr_read_playback (struct sockaddr_in *from,
192                                 void *buf, size_t nbytes)
193 {
194         isc_result_t status;
195         unsigned buflen = 0, left;
196         char *inbuf = (char *)0;
197         char *bufp;
198         u_int32_t result;
199
200         status = trace_get_packet (&trace_mr_input, &buflen, &inbuf);
201         if (status != ISC_R_SUCCESS) {
202                 log_error ("trace_mr_recvfrom: no input found.");
203                 errno = ECONNREFUSED;
204                 return -1;
205         }
206         if (buflen < sizeof result) {
207                 log_error ("trace_mr_recvfrom: data too short.");
208                 errno = ECONNREFUSED;
209                 dfree (inbuf, MDL);
210                 return -1;
211         }
212         bufp = inbuf;
213         left = buflen;
214         memcpy (&result, bufp, sizeof result);
215         result = ntohl (result);
216         bufp += sizeof result;
217         left -= sizeof result;
218         if (result == 0) {
219                 if (left < ((sizeof from -> sin_port) +
220                             sizeof (from -> sin_addr))) {
221                         log_error ("trace_mr_recvfrom: data too short.");
222                         errno = ECONNREFUSED;
223                         dfree (inbuf, MDL);
224                         return -1;
225                 }
226                 if (from)
227                         memcpy (&from -> sin_addr, bufp,
228                                 sizeof from -> sin_addr);
229                 bufp += sizeof from -> sin_addr;
230                 left -= sizeof from -> sin_addr;
231                 if (from)
232                         memcpy (&from -> sin_port, bufp,
233                                 sizeof from -> sin_port);
234                 bufp += sizeof from -> sin_port;
235                 left -= sizeof from -> sin_port;
236                 if (from) {
237                         from -> sin_family = AF_INET;
238 #if defined(HAVE_SA_LEN)
239                         from -> sin_len = sizeof (struct sockaddr_in);
240 #endif
241                         memset (from -> sin_zero, 0, sizeof from -> sin_zero);
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
258 void 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
291 ssize_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
311 ssize_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
330 int 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
341 int 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
352 int 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
363 int 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
374 time_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
386 int 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
405 unsigned 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                 int nscount;
416                 status = trace_get_packet (&trace_mr_randomid, &buflen, &buf);
417                 if (status != ISC_R_SUCCESS) {
418                         log_error ("trace_mr_statp: no statp packet found.");
419                         return oldid;
420                 }
421                 if (buflen != sizeof id) {
422                         log_error ("trace_mr_randomid: bogus length: %d",
423                                    buflen);
424                         return oldid;
425                 }
426                 memcpy (&id, buf, sizeof id);
427                 dfree (buf, MDL);
428                 buf = (char *)0;
429                 rid = ntohl (id);
430         }
431         if (trace_record ()) {
432                 id = htonl (rid);
433                 trace_write_packet (trace_mr_randomid,
434                                     sizeof id, (char *)&id, MDL);
435         }
436 #endif
437         return rid;
438 }
439
440 #if defined (TRACING)
441 static void trace_mr_output_input (trace_type_t *ttype,
442                                    unsigned length, char *buf)
443 {
444 }
445
446 static void trace_mr_output_stop (trace_type_t *ttype)
447 {
448 }
449
450 static void trace_mr_input_input (trace_type_t *ttype,
451                                   unsigned length, char *buf)
452 {
453         log_error ("unaccounted-for minires input.");
454 }
455
456 static void trace_mr_input_stop (trace_type_t *ttype)
457 {
458 }
459
460 static void trace_mr_statp_input (trace_type_t *ttype,
461                                   unsigned length, char *buf)
462 {
463         log_error ("unaccounted-for minires statp input.");
464 }
465
466 static void trace_mr_statp_stop (trace_type_t *ttype)
467 {
468 }
469
470 static void trace_mr_randomid_input (trace_type_t *ttype,
471                                      unsigned length, char *buf)
472 {
473         log_error ("unaccounted-for minires randomid input.");
474 }
475
476 static void trace_mr_randomid_stop (trace_type_t *ttype)
477 {
478 }
479 #endif