1*83ee113eSDavid van Moolenbroek /* $NetBSD: trace.c,v 1.1.1.3 2014/07/12 11:58:01 spz Exp $ */
2*83ee113eSDavid van Moolenbroek /* trace.c
3*83ee113eSDavid van Moolenbroek
4*83ee113eSDavid van Moolenbroek Subroutines that support tracing of OMAPI wire transactions and
5*83ee113eSDavid van Moolenbroek provide a mechanism for programs using OMAPI to trace their own
6*83ee113eSDavid van Moolenbroek transactions... */
7*83ee113eSDavid van Moolenbroek
8*83ee113eSDavid van Moolenbroek /*
9*83ee113eSDavid van Moolenbroek * Copyright (c) 2012,2014 by Internet Systems Consortium, Inc. ("ISC")
10*83ee113eSDavid van Moolenbroek * Copyright (c) 2009-2010 by Internet Systems Consortium, Inc. ("ISC")
11*83ee113eSDavid van Moolenbroek * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
12*83ee113eSDavid van Moolenbroek * Copyright (c) 2001-2003 by Internet Software Consortium
13*83ee113eSDavid van Moolenbroek *
14*83ee113eSDavid van Moolenbroek * Permission to use, copy, modify, and distribute this software for any
15*83ee113eSDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
16*83ee113eSDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
17*83ee113eSDavid van Moolenbroek *
18*83ee113eSDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
19*83ee113eSDavid van Moolenbroek * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
20*83ee113eSDavid van Moolenbroek * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
21*83ee113eSDavid van Moolenbroek * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22*83ee113eSDavid van Moolenbroek * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
23*83ee113eSDavid van Moolenbroek * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
24*83ee113eSDavid van Moolenbroek * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25*83ee113eSDavid van Moolenbroek *
26*83ee113eSDavid van Moolenbroek * Internet Systems Consortium, Inc.
27*83ee113eSDavid van Moolenbroek * 950 Charter Street
28*83ee113eSDavid van Moolenbroek * Redwood City, CA 94063
29*83ee113eSDavid van Moolenbroek * <info@isc.org>
30*83ee113eSDavid van Moolenbroek * https://www.isc.org/
31*83ee113eSDavid van Moolenbroek *
32*83ee113eSDavid van Moolenbroek */
33*83ee113eSDavid van Moolenbroek
34*83ee113eSDavid van Moolenbroek #include <sys/cdefs.h>
35*83ee113eSDavid van Moolenbroek __RCSID("$NetBSD: trace.c,v 1.1.1.3 2014/07/12 11:58:01 spz Exp $");
36*83ee113eSDavid van Moolenbroek
37*83ee113eSDavid van Moolenbroek #include "dhcpd.h"
38*83ee113eSDavid van Moolenbroek #include <omapip/omapip_p.h>
39*83ee113eSDavid van Moolenbroek #include <errno.h>
40*83ee113eSDavid van Moolenbroek
41*83ee113eSDavid van Moolenbroek #if defined (TRACING)
42*83ee113eSDavid van Moolenbroek void (*trace_set_time_hook) (TIME);
43*83ee113eSDavid van Moolenbroek static int tracing_stopped;
44*83ee113eSDavid van Moolenbroek static int traceoutfile;
45*83ee113eSDavid van Moolenbroek static int traceindex;
46*83ee113eSDavid van Moolenbroek static trace_type_t **trace_types;
47*83ee113eSDavid van Moolenbroek static int trace_type_count;
48*83ee113eSDavid van Moolenbroek static int trace_type_max;
49*83ee113eSDavid van Moolenbroek static trace_type_t *new_trace_types;
50*83ee113eSDavid van Moolenbroek static FILE *traceinfile;
51*83ee113eSDavid van Moolenbroek static tracefile_header_t tracefile_header;
52*83ee113eSDavid van Moolenbroek static int trace_playback_flag;
53*83ee113eSDavid van Moolenbroek trace_type_t trace_time_marker;
54*83ee113eSDavid van Moolenbroek
55*83ee113eSDavid van Moolenbroek #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
56*83ee113eSDavid van Moolenbroek extern omapi_array_t *trace_listeners;
57*83ee113eSDavid van Moolenbroek extern omapi_array_t *omapi_connections;
58*83ee113eSDavid van Moolenbroek
59*83ee113eSDavid van Moolenbroek extern int errno;
60*83ee113eSDavid van Moolenbroek
trace_free_all()61*83ee113eSDavid van Moolenbroek void trace_free_all ()
62*83ee113eSDavid van Moolenbroek {
63*83ee113eSDavid van Moolenbroek trace_type_t *tp;
64*83ee113eSDavid van Moolenbroek int i;
65*83ee113eSDavid van Moolenbroek tp = new_trace_types;
66*83ee113eSDavid van Moolenbroek while (tp) {
67*83ee113eSDavid van Moolenbroek new_trace_types = tp -> next;
68*83ee113eSDavid van Moolenbroek if (tp -> name) {
69*83ee113eSDavid van Moolenbroek dfree (tp -> name, MDL);
70*83ee113eSDavid van Moolenbroek tp -> name = (char *)0;
71*83ee113eSDavid van Moolenbroek }
72*83ee113eSDavid van Moolenbroek dfree (tp, MDL);
73*83ee113eSDavid van Moolenbroek tp = new_trace_types;
74*83ee113eSDavid van Moolenbroek }
75*83ee113eSDavid van Moolenbroek for (i = 0; i < trace_type_count; i++) {
76*83ee113eSDavid van Moolenbroek if (trace_types [i]) {
77*83ee113eSDavid van Moolenbroek if (trace_types [i] -> name)
78*83ee113eSDavid van Moolenbroek dfree (trace_types [i] -> name, MDL);
79*83ee113eSDavid van Moolenbroek dfree (trace_types [i], MDL);
80*83ee113eSDavid van Moolenbroek }
81*83ee113eSDavid van Moolenbroek }
82*83ee113eSDavid van Moolenbroek dfree (trace_types, MDL);
83*83ee113eSDavid van Moolenbroek trace_types = (trace_type_t **)0;
84*83ee113eSDavid van Moolenbroek trace_type_count = trace_type_max = 0;
85*83ee113eSDavid van Moolenbroek
86*83ee113eSDavid van Moolenbroek omapi_array_free (&trace_listeners, MDL);
87*83ee113eSDavid van Moolenbroek omapi_array_free (&omapi_connections, MDL);
88*83ee113eSDavid van Moolenbroek }
89*83ee113eSDavid van Moolenbroek #endif
90*83ee113eSDavid van Moolenbroek
91*83ee113eSDavid van Moolenbroek static isc_result_t trace_type_record (trace_type_t *,
92*83ee113eSDavid van Moolenbroek unsigned, const char *, int);
93*83ee113eSDavid van Moolenbroek
trace_playback()94*83ee113eSDavid van Moolenbroek int trace_playback ()
95*83ee113eSDavid van Moolenbroek {
96*83ee113eSDavid van Moolenbroek return trace_playback_flag;
97*83ee113eSDavid van Moolenbroek }
98*83ee113eSDavid van Moolenbroek
trace_record()99*83ee113eSDavid van Moolenbroek int trace_record ()
100*83ee113eSDavid van Moolenbroek {
101*83ee113eSDavid van Moolenbroek if (traceoutfile && !tracing_stopped)
102*83ee113eSDavid van Moolenbroek return 1;
103*83ee113eSDavid van Moolenbroek return 0;
104*83ee113eSDavid van Moolenbroek }
105*83ee113eSDavid van Moolenbroek
trace_init(void (* set_time)(TIME),const char * file,int line)106*83ee113eSDavid van Moolenbroek isc_result_t trace_init (void (*set_time) (TIME),
107*83ee113eSDavid van Moolenbroek const char *file, int line)
108*83ee113eSDavid van Moolenbroek {
109*83ee113eSDavid van Moolenbroek trace_type_t *root_type;
110*83ee113eSDavid van Moolenbroek static int root_setup = 0;
111*83ee113eSDavid van Moolenbroek
112*83ee113eSDavid van Moolenbroek if (root_setup)
113*83ee113eSDavid van Moolenbroek return ISC_R_SUCCESS;
114*83ee113eSDavid van Moolenbroek
115*83ee113eSDavid van Moolenbroek trace_set_time_hook = set_time;
116*83ee113eSDavid van Moolenbroek
117*83ee113eSDavid van Moolenbroek root_type = trace_type_register ("trace-index-mapping",
118*83ee113eSDavid van Moolenbroek (void *)0, trace_index_map_input,
119*83ee113eSDavid van Moolenbroek trace_index_stop_tracing, file, line);
120*83ee113eSDavid van Moolenbroek if (!root_type)
121*83ee113eSDavid van Moolenbroek return ISC_R_UNEXPECTED;
122*83ee113eSDavid van Moolenbroek if (new_trace_types == root_type)
123*83ee113eSDavid van Moolenbroek new_trace_types = new_trace_types -> next;
124*83ee113eSDavid van Moolenbroek root_type -> index = 0;
125*83ee113eSDavid van Moolenbroek trace_type_stash (root_type);
126*83ee113eSDavid van Moolenbroek
127*83ee113eSDavid van Moolenbroek root_setup = 1;
128*83ee113eSDavid van Moolenbroek return ISC_R_SUCCESS;
129*83ee113eSDavid van Moolenbroek }
130*83ee113eSDavid van Moolenbroek
trace_begin(const char * filename,const char * file,int line)131*83ee113eSDavid van Moolenbroek isc_result_t trace_begin (const char *filename,
132*83ee113eSDavid van Moolenbroek const char *file, int line)
133*83ee113eSDavid van Moolenbroek {
134*83ee113eSDavid van Moolenbroek tracefile_header_t tfh;
135*83ee113eSDavid van Moolenbroek int status;
136*83ee113eSDavid van Moolenbroek trace_type_t *tptr, *next;
137*83ee113eSDavid van Moolenbroek isc_result_t result;
138*83ee113eSDavid van Moolenbroek
139*83ee113eSDavid van Moolenbroek if (traceoutfile) {
140*83ee113eSDavid van Moolenbroek log_error ("%s(%d): trace_begin called twice",
141*83ee113eSDavid van Moolenbroek file, line);
142*83ee113eSDavid van Moolenbroek return DHCP_R_INVALIDARG;
143*83ee113eSDavid van Moolenbroek }
144*83ee113eSDavid van Moolenbroek
145*83ee113eSDavid van Moolenbroek traceoutfile = open (filename, O_CREAT | O_WRONLY | O_EXCL, 0600);
146*83ee113eSDavid van Moolenbroek if (traceoutfile < 0 && errno == EEXIST) {
147*83ee113eSDavid van Moolenbroek log_error ("WARNING: Overwriting trace file \"%s\"", filename);
148*83ee113eSDavid van Moolenbroek traceoutfile = open (filename, O_WRONLY | O_EXCL | O_TRUNC,
149*83ee113eSDavid van Moolenbroek 0600);
150*83ee113eSDavid van Moolenbroek }
151*83ee113eSDavid van Moolenbroek
152*83ee113eSDavid van Moolenbroek if (traceoutfile < 0) {
153*83ee113eSDavid van Moolenbroek log_error ("%s(%d): trace_begin: %s: %m",
154*83ee113eSDavid van Moolenbroek file, line, filename);
155*83ee113eSDavid van Moolenbroek return ISC_R_UNEXPECTED;
156*83ee113eSDavid van Moolenbroek }
157*83ee113eSDavid van Moolenbroek #if defined (HAVE_SETFD)
158*83ee113eSDavid van Moolenbroek if (fcntl (traceoutfile, F_SETFD, 1) < 0)
159*83ee113eSDavid van Moolenbroek log_error ("Can't set close-on-exec on %s: %m", filename);
160*83ee113eSDavid van Moolenbroek #endif
161*83ee113eSDavid van Moolenbroek
162*83ee113eSDavid van Moolenbroek tfh.magic = htonl (TRACEFILE_MAGIC);
163*83ee113eSDavid van Moolenbroek tfh.version = htonl (TRACEFILE_VERSION);
164*83ee113eSDavid van Moolenbroek tfh.hlen = htonl (sizeof (tracefile_header_t));
165*83ee113eSDavid van Moolenbroek tfh.phlen = htonl (sizeof (tracepacket_t));
166*83ee113eSDavid van Moolenbroek
167*83ee113eSDavid van Moolenbroek status = write (traceoutfile, &tfh, sizeof tfh);
168*83ee113eSDavid van Moolenbroek if (status < 0) {
169*83ee113eSDavid van Moolenbroek log_error ("%s(%d): trace_begin write failed: %m", file, line);
170*83ee113eSDavid van Moolenbroek return ISC_R_UNEXPECTED;
171*83ee113eSDavid van Moolenbroek } else if (status != sizeof tfh) {
172*83ee113eSDavid van Moolenbroek log_error ("%s(%d): trace_begin: short write (%d:%ld)",
173*83ee113eSDavid van Moolenbroek file, line, status, (long)(sizeof tfh));
174*83ee113eSDavid van Moolenbroek trace_stop ();
175*83ee113eSDavid van Moolenbroek return ISC_R_UNEXPECTED;
176*83ee113eSDavid van Moolenbroek }
177*83ee113eSDavid van Moolenbroek
178*83ee113eSDavid van Moolenbroek /* Stash all the types that have already been set up. */
179*83ee113eSDavid van Moolenbroek if (new_trace_types) {
180*83ee113eSDavid van Moolenbroek next = new_trace_types;
181*83ee113eSDavid van Moolenbroek new_trace_types = (trace_type_t *)0;
182*83ee113eSDavid van Moolenbroek for (tptr = next; tptr; tptr = next) {
183*83ee113eSDavid van Moolenbroek next = tptr -> next;
184*83ee113eSDavid van Moolenbroek if (tptr -> index != 0) {
185*83ee113eSDavid van Moolenbroek result = (trace_type_record
186*83ee113eSDavid van Moolenbroek (tptr,
187*83ee113eSDavid van Moolenbroek strlen (tptr -> name), file, line));
188*83ee113eSDavid van Moolenbroek if (result != ISC_R_SUCCESS)
189*83ee113eSDavid van Moolenbroek return status;
190*83ee113eSDavid van Moolenbroek }
191*83ee113eSDavid van Moolenbroek }
192*83ee113eSDavid van Moolenbroek }
193*83ee113eSDavid van Moolenbroek
194*83ee113eSDavid van Moolenbroek return ISC_R_SUCCESS;
195*83ee113eSDavid van Moolenbroek }
196*83ee113eSDavid van Moolenbroek
trace_write_packet(trace_type_t * ttype,unsigned length,const char * buf,const char * file,int line)197*83ee113eSDavid van Moolenbroek isc_result_t trace_write_packet (trace_type_t *ttype, unsigned length,
198*83ee113eSDavid van Moolenbroek const char *buf, const char *file, int line)
199*83ee113eSDavid van Moolenbroek {
200*83ee113eSDavid van Moolenbroek trace_iov_t iov;
201*83ee113eSDavid van Moolenbroek
202*83ee113eSDavid van Moolenbroek iov.buf = buf;
203*83ee113eSDavid van Moolenbroek iov.len = length;
204*83ee113eSDavid van Moolenbroek return trace_write_packet_iov (ttype, 1, &iov, file, line);
205*83ee113eSDavid van Moolenbroek }
206*83ee113eSDavid van Moolenbroek
trace_write_packet_iov(trace_type_t * ttype,int count,trace_iov_t * iov,const char * file,int line)207*83ee113eSDavid van Moolenbroek isc_result_t trace_write_packet_iov (trace_type_t *ttype,
208*83ee113eSDavid van Moolenbroek int count, trace_iov_t *iov,
209*83ee113eSDavid van Moolenbroek const char *file, int line)
210*83ee113eSDavid van Moolenbroek {
211*83ee113eSDavid van Moolenbroek tracepacket_t tmp;
212*83ee113eSDavid van Moolenbroek int status;
213*83ee113eSDavid van Moolenbroek int i;
214*83ee113eSDavid van Moolenbroek int length;
215*83ee113eSDavid van Moolenbroek
216*83ee113eSDavid van Moolenbroek /* Really shouldn't get called here, but it may be hard to turn off
217*83ee113eSDavid van Moolenbroek tracing midstream if the trace file write fails or something. */
218*83ee113eSDavid van Moolenbroek if (tracing_stopped)
219*83ee113eSDavid van Moolenbroek return 0;
220*83ee113eSDavid van Moolenbroek
221*83ee113eSDavid van Moolenbroek if (!ttype) {
222*83ee113eSDavid van Moolenbroek log_error ("%s(%d): trace_write_packet with null trace type",
223*83ee113eSDavid van Moolenbroek file ? file : "<unknown file>", line);
224*83ee113eSDavid van Moolenbroek return DHCP_R_INVALIDARG;
225*83ee113eSDavid van Moolenbroek }
226*83ee113eSDavid van Moolenbroek if (!traceoutfile) {
227*83ee113eSDavid van Moolenbroek log_error ("%s(%d): trace_write_packet with no tracefile.",
228*83ee113eSDavid van Moolenbroek file ? file : "<unknown file>", line);
229*83ee113eSDavid van Moolenbroek return DHCP_R_INVALIDARG;
230*83ee113eSDavid van Moolenbroek }
231*83ee113eSDavid van Moolenbroek
232*83ee113eSDavid van Moolenbroek /* Compute the total length of the iov. */
233*83ee113eSDavid van Moolenbroek length = 0;
234*83ee113eSDavid van Moolenbroek for (i = 0; i < count; i++)
235*83ee113eSDavid van Moolenbroek length += iov [i].len;
236*83ee113eSDavid van Moolenbroek
237*83ee113eSDavid van Moolenbroek /* We have to swap out the data, because it may be read back on a
238*83ee113eSDavid van Moolenbroek machine of different endianness. */
239*83ee113eSDavid van Moolenbroek memset(&tmp, 0, sizeof(tmp));
240*83ee113eSDavid van Moolenbroek tmp.type_index = htonl (ttype -> index);
241*83ee113eSDavid van Moolenbroek tmp.when = htonl (time ((time_t *)0)); /* XXX */
242*83ee113eSDavid van Moolenbroek tmp.length = htonl (length);
243*83ee113eSDavid van Moolenbroek
244*83ee113eSDavid van Moolenbroek status = write (traceoutfile, &tmp, sizeof tmp);
245*83ee113eSDavid van Moolenbroek if (status < 0) {
246*83ee113eSDavid van Moolenbroek log_error ("%s(%d): trace_write_packet write failed: %m",
247*83ee113eSDavid van Moolenbroek file, line);
248*83ee113eSDavid van Moolenbroek return ISC_R_UNEXPECTED;
249*83ee113eSDavid van Moolenbroek } else if (status != sizeof tmp) {
250*83ee113eSDavid van Moolenbroek log_error ("%s(%d): trace_write_packet: short write (%d:%ld)",
251*83ee113eSDavid van Moolenbroek file, line, status, (long)(sizeof tmp));
252*83ee113eSDavid van Moolenbroek trace_stop ();
253*83ee113eSDavid van Moolenbroek }
254*83ee113eSDavid van Moolenbroek
255*83ee113eSDavid van Moolenbroek for (i = 0; i < count; i++) {
256*83ee113eSDavid van Moolenbroek status = write (traceoutfile, iov [i].buf, iov [i].len);
257*83ee113eSDavid van Moolenbroek if (status < 0) {
258*83ee113eSDavid van Moolenbroek log_error ("%s(%d): %s write failed: %m",
259*83ee113eSDavid van Moolenbroek file, line, "trace_write_packet");
260*83ee113eSDavid van Moolenbroek return ISC_R_UNEXPECTED;
261*83ee113eSDavid van Moolenbroek } else if (status != iov [i].len) {
262*83ee113eSDavid van Moolenbroek log_error ("%s(%d): %s: short write (%d:%d)",
263*83ee113eSDavid van Moolenbroek file, line,
264*83ee113eSDavid van Moolenbroek "trace_write_packet", status, length);
265*83ee113eSDavid van Moolenbroek trace_stop ();
266*83ee113eSDavid van Moolenbroek }
267*83ee113eSDavid van Moolenbroek }
268*83ee113eSDavid van Moolenbroek
269*83ee113eSDavid van Moolenbroek /* Write padding on the end of the packet to align the next
270*83ee113eSDavid van Moolenbroek packet to an 8-byte boundary. This is in case we decide to
271*83ee113eSDavid van Moolenbroek use mmap in some clever way later on. */
272*83ee113eSDavid van Moolenbroek if (length % 8) {
273*83ee113eSDavid van Moolenbroek static char zero [] = { 0, 0, 0, 0, 0, 0, 0 };
274*83ee113eSDavid van Moolenbroek unsigned padl = 8 - (length % 8);
275*83ee113eSDavid van Moolenbroek
276*83ee113eSDavid van Moolenbroek status = write (traceoutfile, zero, padl);
277*83ee113eSDavid van Moolenbroek if (status < 0) {
278*83ee113eSDavid van Moolenbroek log_error ("%s(%d): trace_write_packet write failed: %m",
279*83ee113eSDavid van Moolenbroek file, line);
280*83ee113eSDavid van Moolenbroek return ISC_R_UNEXPECTED;
281*83ee113eSDavid van Moolenbroek } else if (status != padl) {
282*83ee113eSDavid van Moolenbroek log_error ("%s(%d): trace_write_packet: short write (%d:%d)",
283*83ee113eSDavid van Moolenbroek file, line, status, padl);
284*83ee113eSDavid van Moolenbroek trace_stop ();
285*83ee113eSDavid van Moolenbroek }
286*83ee113eSDavid van Moolenbroek }
287*83ee113eSDavid van Moolenbroek
288*83ee113eSDavid van Moolenbroek return ISC_R_SUCCESS;
289*83ee113eSDavid van Moolenbroek }
290*83ee113eSDavid van Moolenbroek
trace_type_stash(trace_type_t * tptr)291*83ee113eSDavid van Moolenbroek void trace_type_stash (trace_type_t *tptr)
292*83ee113eSDavid van Moolenbroek {
293*83ee113eSDavid van Moolenbroek trace_type_t **vec;
294*83ee113eSDavid van Moolenbroek int delta;
295*83ee113eSDavid van Moolenbroek if (trace_type_max <= tptr -> index) {
296*83ee113eSDavid van Moolenbroek delta = tptr -> index - trace_type_max + 10;
297*83ee113eSDavid van Moolenbroek vec = dmalloc (((trace_type_max + delta) *
298*83ee113eSDavid van Moolenbroek sizeof (trace_type_t *)), MDL);
299*83ee113eSDavid van Moolenbroek if (!vec)
300*83ee113eSDavid van Moolenbroek return;
301*83ee113eSDavid van Moolenbroek memset (&vec [trace_type_max], 0,
302*83ee113eSDavid van Moolenbroek (sizeof (trace_type_t *)) * delta);
303*83ee113eSDavid van Moolenbroek trace_type_max += delta;
304*83ee113eSDavid van Moolenbroek if (trace_types) {
305*83ee113eSDavid van Moolenbroek memcpy (vec, trace_types,
306*83ee113eSDavid van Moolenbroek trace_type_count * sizeof (trace_type_t *));
307*83ee113eSDavid van Moolenbroek dfree (trace_types, MDL);
308*83ee113eSDavid van Moolenbroek }
309*83ee113eSDavid van Moolenbroek trace_types = vec;
310*83ee113eSDavid van Moolenbroek }
311*83ee113eSDavid van Moolenbroek trace_types [tptr -> index] = tptr;
312*83ee113eSDavid van Moolenbroek if (tptr -> index >= trace_type_count)
313*83ee113eSDavid van Moolenbroek trace_type_count = tptr -> index + 1;
314*83ee113eSDavid van Moolenbroek }
315*83ee113eSDavid van Moolenbroek
trace_type_register(const char * name,void * baggage,void (* have_packet)(trace_type_t *,unsigned,char *),void (* stop_tracing)(trace_type_t *),const char * file,int line)316*83ee113eSDavid van Moolenbroek trace_type_t *trace_type_register (const char *name,
317*83ee113eSDavid van Moolenbroek void *baggage,
318*83ee113eSDavid van Moolenbroek void (*have_packet) (trace_type_t *,
319*83ee113eSDavid van Moolenbroek unsigned, char *),
320*83ee113eSDavid van Moolenbroek void (*stop_tracing) (trace_type_t *),
321*83ee113eSDavid van Moolenbroek const char *file, int line)
322*83ee113eSDavid van Moolenbroek {
323*83ee113eSDavid van Moolenbroek trace_type_t *ttmp;
324*83ee113eSDavid van Moolenbroek unsigned slen = strlen (name);
325*83ee113eSDavid van Moolenbroek isc_result_t status;
326*83ee113eSDavid van Moolenbroek
327*83ee113eSDavid van Moolenbroek ttmp = dmalloc (sizeof *ttmp, file, line);
328*83ee113eSDavid van Moolenbroek if (!ttmp)
329*83ee113eSDavid van Moolenbroek return ttmp;
330*83ee113eSDavid van Moolenbroek ttmp -> index = -1;
331*83ee113eSDavid van Moolenbroek ttmp -> name = dmalloc (slen + 1, file, line);
332*83ee113eSDavid van Moolenbroek if (!ttmp -> name) {
333*83ee113eSDavid van Moolenbroek dfree (ttmp, file, line);
334*83ee113eSDavid van Moolenbroek return (trace_type_t *)0;
335*83ee113eSDavid van Moolenbroek }
336*83ee113eSDavid van Moolenbroek strcpy (ttmp -> name, name);
337*83ee113eSDavid van Moolenbroek ttmp -> have_packet = have_packet;
338*83ee113eSDavid van Moolenbroek ttmp -> stop_tracing = stop_tracing;
339*83ee113eSDavid van Moolenbroek
340*83ee113eSDavid van Moolenbroek if (traceoutfile) {
341*83ee113eSDavid van Moolenbroek status = trace_type_record (ttmp, slen, file, line);
342*83ee113eSDavid van Moolenbroek if (status != ISC_R_SUCCESS) {
343*83ee113eSDavid van Moolenbroek dfree (ttmp -> name, file, line);
344*83ee113eSDavid van Moolenbroek dfree (ttmp, file, line);
345*83ee113eSDavid van Moolenbroek return (trace_type_t *)0;
346*83ee113eSDavid van Moolenbroek }
347*83ee113eSDavid van Moolenbroek } else {
348*83ee113eSDavid van Moolenbroek ttmp -> next = new_trace_types;
349*83ee113eSDavid van Moolenbroek new_trace_types = ttmp;
350*83ee113eSDavid van Moolenbroek }
351*83ee113eSDavid van Moolenbroek
352*83ee113eSDavid van Moolenbroek return ttmp;
353*83ee113eSDavid van Moolenbroek }
354*83ee113eSDavid van Moolenbroek
trace_type_record(trace_type_t * ttmp,unsigned slen,const char * file,int line)355*83ee113eSDavid van Moolenbroek static isc_result_t trace_type_record (trace_type_t *ttmp, unsigned slen,
356*83ee113eSDavid van Moolenbroek const char *file, int line)
357*83ee113eSDavid van Moolenbroek {
358*83ee113eSDavid van Moolenbroek trace_index_mapping_t *tim;
359*83ee113eSDavid van Moolenbroek isc_result_t status;
360*83ee113eSDavid van Moolenbroek
361*83ee113eSDavid van Moolenbroek tim = dmalloc (slen + TRACE_INDEX_MAPPING_SIZE, file, line);
362*83ee113eSDavid van Moolenbroek if (!tim)
363*83ee113eSDavid van Moolenbroek return ISC_R_NOMEMORY;
364*83ee113eSDavid van Moolenbroek ttmp -> index = ++traceindex;
365*83ee113eSDavid van Moolenbroek trace_type_stash (ttmp);
366*83ee113eSDavid van Moolenbroek tim -> index = htonl (ttmp -> index);
367*83ee113eSDavid van Moolenbroek memcpy (tim -> name, ttmp -> name, slen);
368*83ee113eSDavid van Moolenbroek status = trace_write_packet (trace_types [0],
369*83ee113eSDavid van Moolenbroek slen + TRACE_INDEX_MAPPING_SIZE,
370*83ee113eSDavid van Moolenbroek (char *)tim, file, line);
371*83ee113eSDavid van Moolenbroek dfree (tim, file, line);
372*83ee113eSDavid van Moolenbroek return status;
373*83ee113eSDavid van Moolenbroek }
374*83ee113eSDavid van Moolenbroek
375*83ee113eSDavid van Moolenbroek /* Stop all registered trace types from trying to trace. */
376*83ee113eSDavid van Moolenbroek
trace_stop(void)377*83ee113eSDavid van Moolenbroek void trace_stop (void)
378*83ee113eSDavid van Moolenbroek {
379*83ee113eSDavid van Moolenbroek int i;
380*83ee113eSDavid van Moolenbroek
381*83ee113eSDavid van Moolenbroek for (i = 0; i < trace_type_count; i++)
382*83ee113eSDavid van Moolenbroek if (trace_types [i] -> stop_tracing)
383*83ee113eSDavid van Moolenbroek (*(trace_types [i] -> stop_tracing))
384*83ee113eSDavid van Moolenbroek (trace_types [i]);
385*83ee113eSDavid van Moolenbroek tracing_stopped = 1;
386*83ee113eSDavid van Moolenbroek }
387*83ee113eSDavid van Moolenbroek
trace_index_map_input(trace_type_t * ttype,unsigned length,char * buf)388*83ee113eSDavid van Moolenbroek void trace_index_map_input (trace_type_t *ttype, unsigned length, char *buf)
389*83ee113eSDavid van Moolenbroek {
390*83ee113eSDavid van Moolenbroek trace_index_mapping_t *tmap;
391*83ee113eSDavid van Moolenbroek unsigned len;
392*83ee113eSDavid van Moolenbroek trace_type_t *tptr, **prev;
393*83ee113eSDavid van Moolenbroek
394*83ee113eSDavid van Moolenbroek if (length < TRACE_INDEX_MAPPING_SIZE) {
395*83ee113eSDavid van Moolenbroek log_error ("short trace index mapping");
396*83ee113eSDavid van Moolenbroek return;
397*83ee113eSDavid van Moolenbroek }
398*83ee113eSDavid van Moolenbroek tmap = (trace_index_mapping_t *)buf;
399*83ee113eSDavid van Moolenbroek
400*83ee113eSDavid van Moolenbroek prev = &new_trace_types;
401*83ee113eSDavid van Moolenbroek for (tptr = new_trace_types; tptr; tptr = tptr -> next) {
402*83ee113eSDavid van Moolenbroek len = strlen (tptr -> name);
403*83ee113eSDavid van Moolenbroek if (len == length - TRACE_INDEX_MAPPING_SIZE &&
404*83ee113eSDavid van Moolenbroek !memcmp (tptr -> name, tmap -> name, len)) {
405*83ee113eSDavid van Moolenbroek tptr -> index = ntohl (tmap -> index);
406*83ee113eSDavid van Moolenbroek trace_type_stash (tptr);
407*83ee113eSDavid van Moolenbroek *prev = tptr -> next;
408*83ee113eSDavid van Moolenbroek return;
409*83ee113eSDavid van Moolenbroek }
410*83ee113eSDavid van Moolenbroek prev = &tptr -> next;
411*83ee113eSDavid van Moolenbroek }
412*83ee113eSDavid van Moolenbroek
413*83ee113eSDavid van Moolenbroek log_error ("No registered trace type for type name %.*s",
414*83ee113eSDavid van Moolenbroek (int)length - TRACE_INDEX_MAPPING_SIZE, tmap -> name);
415*83ee113eSDavid van Moolenbroek return;
416*83ee113eSDavid van Moolenbroek }
417*83ee113eSDavid van Moolenbroek
trace_index_stop_tracing(trace_type_t * ttype)418*83ee113eSDavid van Moolenbroek void trace_index_stop_tracing (trace_type_t *ttype) { }
419*83ee113eSDavid van Moolenbroek
trace_replay_init(void)420*83ee113eSDavid van Moolenbroek void trace_replay_init (void)
421*83ee113eSDavid van Moolenbroek {
422*83ee113eSDavid van Moolenbroek trace_playback_flag = 1;
423*83ee113eSDavid van Moolenbroek }
424*83ee113eSDavid van Moolenbroek
trace_file_replay(const char * filename)425*83ee113eSDavid van Moolenbroek void trace_file_replay (const char *filename)
426*83ee113eSDavid van Moolenbroek {
427*83ee113eSDavid van Moolenbroek tracepacket_t *tpkt = NULL;
428*83ee113eSDavid van Moolenbroek int status;
429*83ee113eSDavid van Moolenbroek char *buf = NULL;
430*83ee113eSDavid van Moolenbroek unsigned buflen;
431*83ee113eSDavid van Moolenbroek unsigned bufmax = 0;
432*83ee113eSDavid van Moolenbroek trace_type_t *ttype = NULL;
433*83ee113eSDavid van Moolenbroek isc_result_t result;
434*83ee113eSDavid van Moolenbroek int len;
435*83ee113eSDavid van Moolenbroek
436*83ee113eSDavid van Moolenbroek traceinfile = fopen (filename, "r");
437*83ee113eSDavid van Moolenbroek if (!traceinfile) {
438*83ee113eSDavid van Moolenbroek log_error("Can't open tracefile %s: %m", filename);
439*83ee113eSDavid van Moolenbroek return;
440*83ee113eSDavid van Moolenbroek }
441*83ee113eSDavid van Moolenbroek #if defined (HAVE_SETFD)
442*83ee113eSDavid van Moolenbroek if (fcntl (fileno(traceinfile), F_SETFD, 1) < 0)
443*83ee113eSDavid van Moolenbroek log_error("Can't set close-on-exec on %s: %m", filename);
444*83ee113eSDavid van Moolenbroek #endif
445*83ee113eSDavid van Moolenbroek status = fread(&tracefile_header, 1,
446*83ee113eSDavid van Moolenbroek sizeof tracefile_header, traceinfile);
447*83ee113eSDavid van Moolenbroek if (status < sizeof tracefile_header) {
448*83ee113eSDavid van Moolenbroek if (ferror(traceinfile))
449*83ee113eSDavid van Moolenbroek log_error("Error reading trace file header: %m");
450*83ee113eSDavid van Moolenbroek else
451*83ee113eSDavid van Moolenbroek log_error("Short read on trace file header: %d %ld.",
452*83ee113eSDavid van Moolenbroek status, (long)(sizeof tracefile_header));
453*83ee113eSDavid van Moolenbroek goto out;
454*83ee113eSDavid van Moolenbroek }
455*83ee113eSDavid van Moolenbroek tracefile_header.magic = ntohl(tracefile_header.magic);
456*83ee113eSDavid van Moolenbroek tracefile_header.version = ntohl(tracefile_header.version);
457*83ee113eSDavid van Moolenbroek tracefile_header.hlen = ntohl(tracefile_header.hlen);
458*83ee113eSDavid van Moolenbroek tracefile_header.phlen = ntohl(tracefile_header.phlen);
459*83ee113eSDavid van Moolenbroek
460*83ee113eSDavid van Moolenbroek if (tracefile_header.magic != TRACEFILE_MAGIC) {
461*83ee113eSDavid van Moolenbroek log_error("%s: not a dhcp trace file.", filename);
462*83ee113eSDavid van Moolenbroek goto out;
463*83ee113eSDavid van Moolenbroek }
464*83ee113eSDavid van Moolenbroek if (tracefile_header.version > TRACEFILE_VERSION) {
465*83ee113eSDavid van Moolenbroek log_error ("tracefile version %ld > current %ld.",
466*83ee113eSDavid van Moolenbroek (long int)tracefile_header.version,
467*83ee113eSDavid van Moolenbroek (long int)TRACEFILE_VERSION);
468*83ee113eSDavid van Moolenbroek goto out;
469*83ee113eSDavid van Moolenbroek }
470*83ee113eSDavid van Moolenbroek if (tracefile_header.phlen < sizeof *tpkt) {
471*83ee113eSDavid van Moolenbroek log_error("tracefile packet size too small - %ld < %ld",
472*83ee113eSDavid van Moolenbroek (long int)tracefile_header.phlen,
473*83ee113eSDavid van Moolenbroek (long int)sizeof *tpkt);
474*83ee113eSDavid van Moolenbroek goto out;
475*83ee113eSDavid van Moolenbroek }
476*83ee113eSDavid van Moolenbroek len = (sizeof tracefile_header) - tracefile_header.hlen;
477*83ee113eSDavid van Moolenbroek if (len < 0) {
478*83ee113eSDavid van Moolenbroek log_error("tracefile header size too small - %ld < %ld",
479*83ee113eSDavid van Moolenbroek (long int)tracefile_header.hlen,
480*83ee113eSDavid van Moolenbroek (long int)sizeof tracefile_header);
481*83ee113eSDavid van Moolenbroek goto out;
482*83ee113eSDavid van Moolenbroek }
483*83ee113eSDavid van Moolenbroek if (len > 0) {
484*83ee113eSDavid van Moolenbroek status = fseek(traceinfile, (long)len, SEEK_CUR);
485*83ee113eSDavid van Moolenbroek if (status < 0) {
486*83ee113eSDavid van Moolenbroek log_error("can't seek past header: %m");
487*83ee113eSDavid van Moolenbroek goto out;
488*83ee113eSDavid van Moolenbroek }
489*83ee113eSDavid van Moolenbroek }
490*83ee113eSDavid van Moolenbroek
491*83ee113eSDavid van Moolenbroek tpkt = dmalloc((unsigned)tracefile_header.phlen, MDL);
492*83ee113eSDavid van Moolenbroek if (tpkt == NULL) {
493*83ee113eSDavid van Moolenbroek log_error ("can't allocate trace packet header.");
494*83ee113eSDavid van Moolenbroek goto out;
495*83ee113eSDavid van Moolenbroek }
496*83ee113eSDavid van Moolenbroek
497*83ee113eSDavid van Moolenbroek while ((result = trace_get_next_packet(&ttype, tpkt, &buf, &buflen,
498*83ee113eSDavid van Moolenbroek &bufmax)) == ISC_R_SUCCESS) {
499*83ee113eSDavid van Moolenbroek (*ttype->have_packet)(ttype, tpkt->length, buf);
500*83ee113eSDavid van Moolenbroek ttype = NULL;
501*83ee113eSDavid van Moolenbroek }
502*83ee113eSDavid van Moolenbroek out:
503*83ee113eSDavid van Moolenbroek fclose(traceinfile);
504*83ee113eSDavid van Moolenbroek if (buf != NULL)
505*83ee113eSDavid van Moolenbroek dfree(buf, MDL);
506*83ee113eSDavid van Moolenbroek if (tpkt != NULL)
507*83ee113eSDavid van Moolenbroek dfree(tpkt, MDL);
508*83ee113eSDavid van Moolenbroek }
509*83ee113eSDavid van Moolenbroek
510*83ee113eSDavid van Moolenbroek /* Get the next packet from the file. If ttp points to a nonzero pointer
511*83ee113eSDavid van Moolenbroek to a trace type structure, check the next packet to see if it's of the
512*83ee113eSDavid van Moolenbroek expected type, and back off if not. */
513*83ee113eSDavid van Moolenbroek
trace_get_next_packet(trace_type_t ** ttp,tracepacket_t * tpkt,char ** buf,unsigned * buflen,unsigned * bufmax)514*83ee113eSDavid van Moolenbroek isc_result_t trace_get_next_packet (trace_type_t **ttp,
515*83ee113eSDavid van Moolenbroek tracepacket_t *tpkt,
516*83ee113eSDavid van Moolenbroek char **buf, unsigned *buflen,
517*83ee113eSDavid van Moolenbroek unsigned *bufmax)
518*83ee113eSDavid van Moolenbroek {
519*83ee113eSDavid van Moolenbroek trace_type_t *ttype;
520*83ee113eSDavid van Moolenbroek unsigned paylen;
521*83ee113eSDavid van Moolenbroek int status, curposok = 0;
522*83ee113eSDavid van Moolenbroek fpos_t curpos;
523*83ee113eSDavid van Moolenbroek
524*83ee113eSDavid van Moolenbroek while(1) {
525*83ee113eSDavid van Moolenbroek curposok = 0;
526*83ee113eSDavid van Moolenbroek status = fgetpos(traceinfile, &curpos);
527*83ee113eSDavid van Moolenbroek if (status < 0) {
528*83ee113eSDavid van Moolenbroek log_error("Can't save tracefile position: %m");
529*83ee113eSDavid van Moolenbroek } else {
530*83ee113eSDavid van Moolenbroek curposok = 1;
531*83ee113eSDavid van Moolenbroek }
532*83ee113eSDavid van Moolenbroek
533*83ee113eSDavid van Moolenbroek status = fread(tpkt, 1, (size_t)tracefile_header.phlen,
534*83ee113eSDavid van Moolenbroek traceinfile);
535*83ee113eSDavid van Moolenbroek if (status < tracefile_header.phlen) {
536*83ee113eSDavid van Moolenbroek if (ferror(traceinfile))
537*83ee113eSDavid van Moolenbroek log_error("Error reading trace packet header: "
538*83ee113eSDavid van Moolenbroek "%m");
539*83ee113eSDavid van Moolenbroek else if (status == 0)
540*83ee113eSDavid van Moolenbroek return ISC_R_EOF;
541*83ee113eSDavid van Moolenbroek else
542*83ee113eSDavid van Moolenbroek log_error ("Short read on trace packet header:"
543*83ee113eSDavid van Moolenbroek " %ld %ld.",
544*83ee113eSDavid van Moolenbroek (long int)status,
545*83ee113eSDavid van Moolenbroek (long int)tracefile_header.phlen);
546*83ee113eSDavid van Moolenbroek return DHCP_R_PROTOCOLERROR;
547*83ee113eSDavid van Moolenbroek }
548*83ee113eSDavid van Moolenbroek
549*83ee113eSDavid van Moolenbroek /* Swap the packet. */
550*83ee113eSDavid van Moolenbroek tpkt->type_index = ntohl(tpkt -> type_index);
551*83ee113eSDavid van Moolenbroek tpkt->length = ntohl(tpkt -> length);
552*83ee113eSDavid van Moolenbroek tpkt->when = ntohl(tpkt -> when);
553*83ee113eSDavid van Moolenbroek
554*83ee113eSDavid van Moolenbroek /* See if there's a handler for this packet type. */
555*83ee113eSDavid van Moolenbroek if (tpkt->type_index < trace_type_count &&
556*83ee113eSDavid van Moolenbroek trace_types[tpkt->type_index])
557*83ee113eSDavid van Moolenbroek ttype = trace_types[tpkt->type_index];
558*83ee113eSDavid van Moolenbroek else {
559*83ee113eSDavid van Moolenbroek log_error ("Trace packet with unknown index %ld",
560*83ee113eSDavid van Moolenbroek (long int)tpkt->type_index);
561*83ee113eSDavid van Moolenbroek return DHCP_R_PROTOCOLERROR;
562*83ee113eSDavid van Moolenbroek }
563*83ee113eSDavid van Moolenbroek
564*83ee113eSDavid van Moolenbroek /*
565*83ee113eSDavid van Moolenbroek * Determine if we should try to expire any timer events.
566*83ee113eSDavid van Moolenbroek * We do so if:
567*83ee113eSDavid van Moolenbroek * we aren't looking for a specific type of packet
568*83ee113eSDavid van Moolenbroek * we have a hook to use to update the timer
569*83ee113eSDavid van Moolenbroek * the timestamp on the packet doesn't match the current time
570*83ee113eSDavid van Moolenbroek * When we do so we rewind the file to the beginning of this
571*83ee113eSDavid van Moolenbroek * packet and then try for a new packet. This allows
572*83ee113eSDavid van Moolenbroek * any code triggered by a timeout to get the current packet
573*83ee113eSDavid van Moolenbroek * while we get the next one.
574*83ee113eSDavid van Moolenbroek */
575*83ee113eSDavid van Moolenbroek
576*83ee113eSDavid van Moolenbroek if ((ttp != NULL) && (*ttp == NULL) &&
577*83ee113eSDavid van Moolenbroek (tpkt->when != cur_tv.tv_sec) &&
578*83ee113eSDavid van Moolenbroek (trace_set_time_hook != NULL)) {
579*83ee113eSDavid van Moolenbroek if (curposok == 0) {
580*83ee113eSDavid van Moolenbroek log_error("no curpos for fsetpos in "
581*83ee113eSDavid van Moolenbroek "tracefile");
582*83ee113eSDavid van Moolenbroek return DHCP_R_PROTOCOLERROR;
583*83ee113eSDavid van Moolenbroek }
584*83ee113eSDavid van Moolenbroek
585*83ee113eSDavid van Moolenbroek status = fsetpos(traceinfile, &curpos);
586*83ee113eSDavid van Moolenbroek if (status < 0) {
587*83ee113eSDavid van Moolenbroek log_error("fsetpos in tracefile failed: %m");
588*83ee113eSDavid van Moolenbroek return DHCP_R_PROTOCOLERROR;
589*83ee113eSDavid van Moolenbroek }
590*83ee113eSDavid van Moolenbroek
591*83ee113eSDavid van Moolenbroek (*trace_set_time_hook) (tpkt->when);
592*83ee113eSDavid van Moolenbroek continue;
593*83ee113eSDavid van Moolenbroek }
594*83ee113eSDavid van Moolenbroek break;
595*83ee113eSDavid van Moolenbroek }
596*83ee113eSDavid van Moolenbroek
597*83ee113eSDavid van Moolenbroek /* If we were supposed to get a particular kind of packet,
598*83ee113eSDavid van Moolenbroek check to see that we got the right kind. */
599*83ee113eSDavid van Moolenbroek if (ttp && *ttp && ttype != *ttp) {
600*83ee113eSDavid van Moolenbroek log_error ("Read packet type %s when expecting %s",
601*83ee113eSDavid van Moolenbroek ttype -> name, (*ttp) -> name);
602*83ee113eSDavid van Moolenbroek status = fsetpos (traceinfile, &curpos);
603*83ee113eSDavid van Moolenbroek if (status < 0) {
604*83ee113eSDavid van Moolenbroek log_error ("fsetpos in tracefile failed: %m");
605*83ee113eSDavid van Moolenbroek return DHCP_R_PROTOCOLERROR;
606*83ee113eSDavid van Moolenbroek }
607*83ee113eSDavid van Moolenbroek return ISC_R_UNEXPECTEDTOKEN;
608*83ee113eSDavid van Moolenbroek }
609*83ee113eSDavid van Moolenbroek
610*83ee113eSDavid van Moolenbroek paylen = tpkt -> length;
611*83ee113eSDavid van Moolenbroek if (paylen % 8)
612*83ee113eSDavid van Moolenbroek paylen += 8 - (tpkt -> length % 8);
613*83ee113eSDavid van Moolenbroek if (paylen > (*bufmax)) {
614*83ee113eSDavid van Moolenbroek if ((*buf))
615*83ee113eSDavid van Moolenbroek dfree ((*buf), MDL);
616*83ee113eSDavid van Moolenbroek (*bufmax) = ((paylen + 1023) & ~1023U);
617*83ee113eSDavid van Moolenbroek (*buf) = dmalloc ((*bufmax), MDL);
618*83ee113eSDavid van Moolenbroek if (!(*buf)) {
619*83ee113eSDavid van Moolenbroek log_error ("Can't allocate input buffer sized %d",
620*83ee113eSDavid van Moolenbroek (*bufmax));
621*83ee113eSDavid van Moolenbroek return ISC_R_NOMEMORY;
622*83ee113eSDavid van Moolenbroek }
623*83ee113eSDavid van Moolenbroek }
624*83ee113eSDavid van Moolenbroek
625*83ee113eSDavid van Moolenbroek status = fread ((*buf), 1, paylen, traceinfile);
626*83ee113eSDavid van Moolenbroek if (status < paylen) {
627*83ee113eSDavid van Moolenbroek if (ferror (traceinfile))
628*83ee113eSDavid van Moolenbroek log_error ("Error reading trace payload: %m");
629*83ee113eSDavid van Moolenbroek else
630*83ee113eSDavid van Moolenbroek log_error ("Short read on trace payload: %d %d.",
631*83ee113eSDavid van Moolenbroek status, paylen);
632*83ee113eSDavid van Moolenbroek return DHCP_R_PROTOCOLERROR;
633*83ee113eSDavid van Moolenbroek }
634*83ee113eSDavid van Moolenbroek
635*83ee113eSDavid van Moolenbroek /* Store the actual length of the payload. */
636*83ee113eSDavid van Moolenbroek *buflen = tpkt -> length;
637*83ee113eSDavid van Moolenbroek
638*83ee113eSDavid van Moolenbroek if (ttp)
639*83ee113eSDavid van Moolenbroek *ttp = ttype;
640*83ee113eSDavid van Moolenbroek return ISC_R_SUCCESS;
641*83ee113eSDavid van Moolenbroek }
642*83ee113eSDavid van Moolenbroek
trace_get_packet(trace_type_t ** ttp,unsigned * buflen,char ** buf)643*83ee113eSDavid van Moolenbroek isc_result_t trace_get_packet (trace_type_t **ttp,
644*83ee113eSDavid van Moolenbroek unsigned *buflen, char **buf)
645*83ee113eSDavid van Moolenbroek {
646*83ee113eSDavid van Moolenbroek tracepacket_t *tpkt;
647*83ee113eSDavid van Moolenbroek unsigned bufmax = 0;
648*83ee113eSDavid van Moolenbroek isc_result_t status;
649*83ee113eSDavid van Moolenbroek
650*83ee113eSDavid van Moolenbroek if (!buf || *buf)
651*83ee113eSDavid van Moolenbroek return DHCP_R_INVALIDARG;
652*83ee113eSDavid van Moolenbroek
653*83ee113eSDavid van Moolenbroek tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL);
654*83ee113eSDavid van Moolenbroek if (!tpkt) {
655*83ee113eSDavid van Moolenbroek log_error ("can't allocate trace packet header.");
656*83ee113eSDavid van Moolenbroek return ISC_R_NOMEMORY;
657*83ee113eSDavid van Moolenbroek }
658*83ee113eSDavid van Moolenbroek
659*83ee113eSDavid van Moolenbroek status = trace_get_next_packet (ttp, tpkt, buf, buflen, &bufmax);
660*83ee113eSDavid van Moolenbroek
661*83ee113eSDavid van Moolenbroek dfree (tpkt, MDL);
662*83ee113eSDavid van Moolenbroek return status;
663*83ee113eSDavid van Moolenbroek }
664*83ee113eSDavid van Moolenbroek
665*83ee113eSDavid van Moolenbroek /* Get a packet from the trace input file that contains a file with the
666*83ee113eSDavid van Moolenbroek specified name. We don't hunt for the packet - it should be the next
667*83ee113eSDavid van Moolenbroek packet in the tracefile. If it's not, or something else bad happens,
668*83ee113eSDavid van Moolenbroek return an error code. */
669*83ee113eSDavid van Moolenbroek
trace_get_file(trace_type_t * ttype,const char * filename,unsigned * len,char ** buf)670*83ee113eSDavid van Moolenbroek isc_result_t trace_get_file (trace_type_t *ttype,
671*83ee113eSDavid van Moolenbroek const char *filename, unsigned *len, char **buf)
672*83ee113eSDavid van Moolenbroek {
673*83ee113eSDavid van Moolenbroek fpos_t curpos;
674*83ee113eSDavid van Moolenbroek unsigned max = 0;
675*83ee113eSDavid van Moolenbroek tracepacket_t *tpkt;
676*83ee113eSDavid van Moolenbroek int status;
677*83ee113eSDavid van Moolenbroek isc_result_t result;
678*83ee113eSDavid van Moolenbroek
679*83ee113eSDavid van Moolenbroek /* Disallow some obvious bogosities. */
680*83ee113eSDavid van Moolenbroek if (!buf || !len || *buf)
681*83ee113eSDavid van Moolenbroek return DHCP_R_INVALIDARG;
682*83ee113eSDavid van Moolenbroek
683*83ee113eSDavid van Moolenbroek /* Save file position in case of filename mismatch. */
684*83ee113eSDavid van Moolenbroek status = fgetpos (traceinfile, &curpos);
685*83ee113eSDavid van Moolenbroek if (status < 0)
686*83ee113eSDavid van Moolenbroek log_error ("Can't save tracefile position: %m");
687*83ee113eSDavid van Moolenbroek
688*83ee113eSDavid van Moolenbroek tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL);
689*83ee113eSDavid van Moolenbroek if (!tpkt) {
690*83ee113eSDavid van Moolenbroek log_error ("can't allocate trace packet header.");
691*83ee113eSDavid van Moolenbroek return ISC_R_NOMEMORY;
692*83ee113eSDavid van Moolenbroek }
693*83ee113eSDavid van Moolenbroek
694*83ee113eSDavid van Moolenbroek result = trace_get_next_packet (&ttype, tpkt, buf, len, &max);
695*83ee113eSDavid van Moolenbroek /* done with tpkt, free it */
696*83ee113eSDavid van Moolenbroek dfree (tpkt, MDL);
697*83ee113eSDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
698*83ee113eSDavid van Moolenbroek if (*buf) {
699*83ee113eSDavid van Moolenbroek dfree (*buf, MDL);
700*83ee113eSDavid van Moolenbroek *buf = NULL;
701*83ee113eSDavid van Moolenbroek }
702*83ee113eSDavid van Moolenbroek return result;
703*83ee113eSDavid van Moolenbroek }
704*83ee113eSDavid van Moolenbroek
705*83ee113eSDavid van Moolenbroek /* Make sure the filename is right. */
706*83ee113eSDavid van Moolenbroek if (strcmp (filename, *buf)) {
707*83ee113eSDavid van Moolenbroek log_error ("Read file %s when expecting %s", *buf, filename);
708*83ee113eSDavid van Moolenbroek dfree (*buf, MDL);
709*83ee113eSDavid van Moolenbroek *buf = NULL;
710*83ee113eSDavid van Moolenbroek
711*83ee113eSDavid van Moolenbroek status = fsetpos (traceinfile, &curpos);
712*83ee113eSDavid van Moolenbroek if (status < 0) {
713*83ee113eSDavid van Moolenbroek log_error ("fsetpos in tracefile failed: %m");
714*83ee113eSDavid van Moolenbroek return DHCP_R_PROTOCOLERROR;
715*83ee113eSDavid van Moolenbroek }
716*83ee113eSDavid van Moolenbroek return ISC_R_UNEXPECTEDTOKEN;
717*83ee113eSDavid van Moolenbroek }
718*83ee113eSDavid van Moolenbroek
719*83ee113eSDavid van Moolenbroek return ISC_R_SUCCESS;
720*83ee113eSDavid van Moolenbroek }
721*83ee113eSDavid van Moolenbroek #endif /* TRACING */
722