Initial import from FreeBSD RELENG_4:
[games.git] / contrib / isc-dhcp / common / ctrace.c
1 /* trace.c
2
3    Subroutines that support dhcp tracing... */
4
5 /*
6  * Copyright (c) 2001-2002 Internet Software Consortium.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
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.
21  *
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
34  * SUCH DAMAGE.
35  *
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''.
40  */
41
42 #include "dhcpd.h"
43
44 #if defined (TRACING)
45 void trace_interface_register (trace_type_t *ttype, struct interface_info *ip)
46 {
47         trace_interface_packet_t tipkt;
48
49         if (trace_record ()) {
50                 memset (&tipkt, 0, sizeof tipkt);
51                 memcpy (&tipkt.hw_address,
52                         &ip -> hw_address, sizeof ip -> hw_address);
53                 memcpy (&tipkt.primary_address,
54                         &ip -> primary_address, sizeof ip -> primary_address);
55                 memcpy (tipkt.name, ip -> name, sizeof ip -> name);
56                 tipkt.index = htonl (ip -> index);
57
58                 trace_write_packet (ttype, sizeof tipkt, (char *)&tipkt, MDL);
59         }       
60 }
61
62 void trace_interface_input (trace_type_t *ttype, unsigned len, char *buf)
63 {
64         trace_interface_packet_t *tipkt;
65         struct interface_info *ip;
66         struct sockaddr_in *sin;
67         struct iaddr addr;
68         isc_result_t status;
69
70         if (len != sizeof *tipkt) {
71                 log_error ("trace interface packet size mismatch: %ld != %d",
72                            (long)(sizeof *tipkt), len);
73                 return;
74         }
75         tipkt = (trace_interface_packet_t *)buf;
76         
77         ip = (struct interface_info *)0;
78         status = interface_allocate (&ip, MDL);
79         if (status != ISC_R_SUCCESS) {
80               foo:
81                 log_error ("trace_interface_input: %s.",
82                            isc_result_totext (status));
83                 return;
84         }
85         ip -> ifp = dmalloc (sizeof *(ip -> ifp), MDL);
86         if (!ip -> ifp) {
87                 interface_dereference (&ip, MDL);
88                 status = ISC_R_NOMEMORY;
89                 goto foo;
90         }
91
92         memcpy (&ip -> hw_address, &tipkt -> hw_address,
93                 sizeof ip -> hw_address);
94         memcpy (&ip -> primary_address, &tipkt -> primary_address,
95                 sizeof ip -> primary_address);
96         memcpy (ip -> name, tipkt -> name, sizeof ip -> name);
97         ip -> index = ntohl (tipkt -> index);
98
99         interface_snorf (ip, 0);
100         if (dhcp_interface_discovery_hook)
101                 (*dhcp_interface_discovery_hook) (ip);
102
103         /* Fake up an ifp. */
104         memcpy (ip -> ifp -> ifr_name, ip -> name, sizeof ip -> name);
105 #ifdef HAVE_SA_LEN
106         ip -> ifp -> ifr_addr.sa_len = sizeof (struct sockaddr_in);
107 #endif
108         sin = (struct sockaddr_in *)&ip -> ifp -> ifr_addr;
109         sin -> sin_addr = ip -> primary_address;
110
111         addr.len = 4;
112         memcpy (addr.iabuf, &sin -> sin_addr.s_addr, addr.len);
113         if (dhcp_interface_setup_hook)
114                 (*dhcp_interface_setup_hook) (ip, &addr);
115         interface_stash (ip);
116
117         if (!quiet_interface_discovery) {
118                 log_info ("Listening on Trace/%s/%s%s%s",
119                           ip -> name,
120                           print_hw_addr (ip -> hw_address.hbuf [0],
121                                          ip -> hw_address.hlen - 1,
122                                          &ip -> hw_address.hbuf [1]),
123                           (ip -> shared_network ? "/" : ""),
124                           (ip -> shared_network ?
125                            ip -> shared_network -> name : ""));
126                 if (strcmp (ip -> name, "fallback")) {
127                         log_info ("Sending   on Trace/%s/%s%s%s",
128                                   ip -> name,
129                                   print_hw_addr (ip -> hw_address.hbuf [0],
130                                                  ip -> hw_address.hlen - 1,
131                                                  &ip -> hw_address.hbuf [1]),
132                                   (ip -> shared_network ? "/" : ""),
133                                   (ip -> shared_network ?
134                                    ip -> shared_network -> name : ""));
135                 }
136         }
137         interface_dereference (&ip, MDL);
138 }
139
140 void trace_interface_stop (trace_type_t *ttype) {
141         /* XXX */
142 }
143
144 void trace_inpacket_stash (struct interface_info *interface,
145                            struct dhcp_packet *packet,
146                            unsigned len,
147                            unsigned int from_port,
148                            struct iaddr from,
149                            struct hardware *hfrom)
150 {
151         trace_inpacket_t tip;
152         trace_iov_t iov [2];
153
154         if (!trace_record ())
155                 return;
156         tip.from_port = from_port;
157         tip.from = from;
158         if (hfrom) {
159                 tip.hfrom = *hfrom;
160                 tip.havehfrom = 1;
161         } else {
162                 memset (&tip.hfrom, 0, sizeof tip.hfrom);
163                 tip.havehfrom = 0;
164         }
165         tip.index = htonl (interface -> index);
166
167         iov [0].buf = (char *)&tip;
168         iov [0].len = sizeof tip;
169         iov [1].buf = (char *)packet;
170         iov [1].len = len;
171         trace_write_packet_iov (inpacket_trace, 2, iov, MDL);
172 }
173
174 void trace_inpacket_input (trace_type_t *ttype, unsigned len, char *buf)
175 {
176         trace_inpacket_t *tip;
177         int index;
178
179         if (len < sizeof *tip) {
180                 log_error ("trace_input_packet: too short - %d", len);
181                 return;
182         }
183         tip = (trace_inpacket_t *)buf;
184         index = ntohl (tip -> index);
185         
186         if (index > interface_count ||
187             index < 0 ||
188             !interface_vector [index]) {
189                 log_error ("trace_input_packet: unknown interface index %d",
190                            index);
191                 return;
192         }
193
194         if (!bootp_packet_handler) {
195                 log_error ("trace_input_packet: no bootp packet handler.");
196                 return;
197         }
198
199         (*bootp_packet_handler) (interface_vector [index],
200                                  (struct dhcp_packet *)(tip + 1),
201                                  len - sizeof *tip,
202                                  tip -> from_port,
203                                  tip -> from,
204                                  (tip -> havehfrom ?
205                                   &tip -> hfrom
206                                   : (struct hardware *)0));
207 }
208
209 void trace_inpacket_stop (trace_type_t *ttype) { }
210
211 ssize_t trace_packet_send (struct interface_info *interface,
212                            struct packet *packet,
213                            struct dhcp_packet *raw,
214                            size_t len,
215                            struct in_addr from,
216                            struct sockaddr_in *to,
217                            struct hardware *hto)
218 {
219         trace_outpacket_t tip;
220         trace_iov_t iov [2];
221
222         if (trace_record ()) {
223                 if (hto) {
224                         tip.hto = *hto;
225                         tip.havehto = 1;
226                 } else {
227                         memset (&tip.hto, 0, sizeof tip.hto);
228                         tip.havehto = 0;
229                 }
230                 tip.from.len = 4;
231                 memcpy (tip.from.iabuf, &from, 4);
232                 tip.to.len = 4;
233                 memcpy (tip.to.iabuf, &to -> sin_addr, 4);
234                 tip.to_port = to -> sin_port;
235                 tip.index = htonl (interface -> index);
236
237                 iov [0].buf = (char *)&tip;
238                 iov [0].len = sizeof tip;
239                 iov [1].buf = (char *)raw;
240                 iov [1].len = len;
241                 trace_write_packet_iov (outpacket_trace, 2, iov, MDL);
242         }
243         if (!trace_playback ()) {
244                 return send_packet (interface, packet, raw, len,
245                                     from, to, hto);
246         }
247         return len;
248 }
249
250 void trace_outpacket_input (trace_type_t *ttype, unsigned len, char *buf)
251 {
252         trace_outpacket_t *tip;
253         int index;
254
255         if (len < sizeof *tip) {
256                 log_error ("trace_input_packet: too short - %d", len);
257                 return;
258         }
259         tip = (trace_outpacket_t *)buf;
260         index = ntohl (tip -> index);
261         
262         if (index > interface_count ||
263             index < 0 ||
264             !interface_vector [index]) {
265                 log_error ("trace_input_packet: unknown interface index %d",
266                            index);
267                 return;
268         }
269
270         /* XXX would be nice to somehow take notice of these. */
271 }
272
273 void trace_outpacket_stop (trace_type_t *ttype) { }
274
275 void trace_seed_stash (trace_type_t *ttype, unsigned seed)
276 {
277         u_int32_t outseed;
278         if (!trace_record ())
279                 return;
280         outseed = htonl (seed);
281         trace_write_packet (ttype, sizeof outseed, (char *)&outseed, MDL);
282         return;
283 }
284
285 void trace_seed_input (trace_type_t *ttype, unsigned length, char *buf)
286 {
287         u_int32_t *seed;
288
289         if (length != sizeof seed) {
290                 log_error ("trace_seed_input: wrong size (%d)", length);
291         }
292         seed = (u_int32_t *)buf;
293         srandom (ntohl (*seed));
294 }
295
296 void trace_seed_stop (trace_type_t *ttype) { }
297 #endif /* TRACING */