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