]>
Commit | Line | Data |
---|---|---|
a568b5bc TL |
1 | /* trace.c |
2 | ||
3 | Subroutines that support dhcp tracing... */ | |
4 | ||
5 | /* | |
49a7fb58 | 6 | * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC") |
98311e4b | 7 | * Copyright (c) 2001-2003 by Internet Software Consortium |
a568b5bc | 8 | * |
7512d88b TM |
9 | * This Source Code Form is subject to the terms of the Mozilla Public |
10 | * License, v. 2.0. If a copy of the MPL was not distributed with this | |
11 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. | |
a568b5bc | 12 | * |
98311e4b DH |
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. | |
a568b5bc | 20 | * |
98311e4b | 21 | * Internet Systems Consortium, Inc. |
429a56d7 TM |
22 | * PO Box 360 |
23 | * Newmarket, NH 03857 USA | |
98311e4b | 24 | * <info@isc.org> |
2c85ac9b | 25 | * https://www.isc.org/ |
a568b5bc | 26 | * |
a568b5bc TL |
27 | */ |
28 | ||
29 | #include "dhcpd.h" | |
30 | ||
31 | #if defined (TRACING) | |
32 | void trace_interface_register (trace_type_t *ttype, struct interface_info *ip) | |
33 | { | |
34 | trace_interface_packet_t tipkt; | |
35 | ||
36 | if (trace_record ()) { | |
37 | memset (&tipkt, 0, sizeof tipkt); | |
38 | memcpy (&tipkt.hw_address, | |
39 | &ip -> hw_address, sizeof ip -> hw_address); | |
98bd7ca0 DH |
40 | if (ip->address_count) |
41 | memcpy(&tipkt.primary_address, | |
42 | ip->addresses, sizeof(*ip->addresses)); | |
a568b5bc TL |
43 | memcpy (tipkt.name, ip -> name, sizeof ip -> name); |
44 | tipkt.index = htonl (ip -> index); | |
45 | ||
46 | trace_write_packet (ttype, sizeof tipkt, (char *)&tipkt, MDL); | |
f6b8f48d | 47 | } |
a568b5bc TL |
48 | } |
49 | ||
50 | void trace_interface_input (trace_type_t *ttype, unsigned len, char *buf) | |
51 | { | |
52 | trace_interface_packet_t *tipkt; | |
53 | struct interface_info *ip; | |
54 | struct sockaddr_in *sin; | |
55 | struct iaddr addr; | |
56 | isc_result_t status; | |
57 | ||
58 | if (len != sizeof *tipkt) { | |
c4661845 TL |
59 | log_error ("trace interface packet size mismatch: %ld != %d", |
60 | (long)(sizeof *tipkt), len); | |
a568b5bc TL |
61 | return; |
62 | } | |
63 | tipkt = (trace_interface_packet_t *)buf; | |
f6b8f48d | 64 | |
a568b5bc TL |
65 | ip = (struct interface_info *)0; |
66 | status = interface_allocate (&ip, MDL); | |
67 | if (status != ISC_R_SUCCESS) { | |
68 | foo: | |
69 | log_error ("trace_interface_input: %s.", | |
70 | isc_result_totext (status)); | |
71 | return; | |
72 | } | |
73 | ip -> ifp = dmalloc (sizeof *(ip -> ifp), MDL); | |
74 | if (!ip -> ifp) { | |
75 | interface_dereference (&ip, MDL); | |
76 | status = ISC_R_NOMEMORY; | |
77 | goto foo; | |
78 | } | |
79 | ||
80 | memcpy (&ip -> hw_address, &tipkt -> hw_address, | |
81 | sizeof ip -> hw_address); | |
98bd7ca0 DH |
82 | /* XXX: Without the full addresses state it's not quite a full |
83 | * trace. | |
84 | */ | |
85 | ip->address_count = ip->address_max = 1; | |
86 | ip->addresses = dmalloc(sizeof(*ip->addresses), MDL); | |
88c3ff5d | 87 | if (!ip->addresses) { |
f6b8f48d | 88 | dfree(ip->ifp, MDL); |
88c3ff5d TM |
89 | ip->ifp = NULL; |
90 | interface_dereference (&ip, MDL); | |
91 | status = ISC_R_NOMEMORY; | |
92 | goto foo; | |
93 | } | |
98bd7ca0 | 94 | memcpy(ip->addresses, &tipkt->primary_address, sizeof(*ip->addresses)); |
a568b5bc TL |
95 | memcpy (ip -> name, tipkt -> name, sizeof ip -> name); |
96 | ip -> index = ntohl (tipkt -> index); | |
97 | ||
98 | interface_snorf (ip, 0); | |
99 | if (dhcp_interface_discovery_hook) | |
100 | (*dhcp_interface_discovery_hook) (ip); | |
101 | ||
102 | /* Fake up an ifp. */ | |
103 | memcpy (ip -> ifp -> ifr_name, ip -> name, sizeof ip -> name); | |
104 | #ifdef HAVE_SA_LEN | |
105 | ip -> ifp -> ifr_addr.sa_len = sizeof (struct sockaddr_in); | |
106 | #endif | |
107 | sin = (struct sockaddr_in *)&ip -> ifp -> ifr_addr; | |
98bd7ca0 | 108 | sin->sin_addr = ip->addresses[0]; |
a568b5bc TL |
109 | |
110 | addr.len = 4; | |
111 | memcpy (addr.iabuf, &sin -> sin_addr.s_addr, addr.len); | |
112 | if (dhcp_interface_setup_hook) | |
113 | (*dhcp_interface_setup_hook) (ip, &addr); | |
114 | interface_stash (ip); | |
115 | ||
116 | if (!quiet_interface_discovery) { | |
117 | log_info ("Listening on Trace/%s/%s%s%s", | |
118 | ip -> name, | |
119 | print_hw_addr (ip -> hw_address.hbuf [0], | |
120 | ip -> hw_address.hlen - 1, | |
121 | &ip -> hw_address.hbuf [1]), | |
122 | (ip -> shared_network ? "/" : ""), | |
123 | (ip -> shared_network ? | |
124 | ip -> shared_network -> name : "")); | |
125 | if (strcmp (ip -> name, "fallback")) { | |
126 | log_info ("Sending on Trace/%s/%s%s%s", | |
127 | ip -> name, | |
128 | print_hw_addr (ip -> hw_address.hbuf [0], | |
129 | ip -> hw_address.hlen - 1, | |
130 | &ip -> hw_address.hbuf [1]), | |
131 | (ip -> shared_network ? "/" : ""), | |
132 | (ip -> shared_network ? | |
133 | ip -> shared_network -> name : "")); | |
134 | } | |
135 | } | |
136 | interface_dereference (&ip, MDL); | |
137 | } | |
138 | ||
139 | void trace_interface_stop (trace_type_t *ttype) { | |
140 | /* XXX */ | |
141 | } | |
142 | ||
143 | void trace_inpacket_stash (struct interface_info *interface, | |
144 | struct dhcp_packet *packet, | |
145 | unsigned len, | |
146 | unsigned int from_port, | |
147 | struct iaddr from, | |
148 | struct hardware *hfrom) | |
149 | { | |
150 | trace_inpacket_t tip; | |
151 | trace_iov_t iov [2]; | |
152 | ||
153 | if (!trace_record ()) | |
154 | return; | |
155 | tip.from_port = from_port; | |
156 | tip.from = from; | |
98311e4b | 157 | tip.from.len = htonl (tip.from.len); |
a568b5bc TL |
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); | |
98311e4b | 185 | tip -> from.len = ntohl (tip -> from.len); |
f6b8f48d | 186 | |
a568b5bc TL |
187 | if (index > interface_count || |
188 | index < 0 || | |
189 | !interface_vector [index]) { | |
190 | log_error ("trace_input_packet: unknown interface index %d", | |
191 | index); | |
192 | return; | |
193 | } | |
194 | ||
195 | if (!bootp_packet_handler) { | |
196 | log_error ("trace_input_packet: no bootp packet handler."); | |
197 | return; | |
198 | } | |
199 | ||
200 | (*bootp_packet_handler) (interface_vector [index], | |
201 | (struct dhcp_packet *)(tip + 1), | |
202 | len - sizeof *tip, | |
203 | tip -> from_port, | |
204 | tip -> from, | |
205 | (tip -> havehfrom ? | |
206 | &tip -> hfrom | |
207 | : (struct hardware *)0)); | |
208 | } | |
209 | ||
210 | void trace_inpacket_stop (trace_type_t *ttype) { } | |
211 | ||
212 | ssize_t trace_packet_send (struct interface_info *interface, | |
213 | struct packet *packet, | |
214 | struct dhcp_packet *raw, | |
215 | size_t len, | |
216 | struct in_addr from, | |
217 | struct sockaddr_in *to, | |
218 | struct hardware *hto) | |
219 | { | |
220 | trace_outpacket_t tip; | |
221 | trace_iov_t iov [2]; | |
222 | ||
223 | if (trace_record ()) { | |
224 | if (hto) { | |
225 | tip.hto = *hto; | |
226 | tip.havehto = 1; | |
227 | } else { | |
228 | memset (&tip.hto, 0, sizeof tip.hto); | |
229 | tip.havehto = 0; | |
230 | } | |
231 | tip.from.len = 4; | |
232 | memcpy (tip.from.iabuf, &from, 4); | |
233 | tip.to.len = 4; | |
234 | memcpy (tip.to.iabuf, &to -> sin_addr, 4); | |
235 | tip.to_port = to -> sin_port; | |
236 | tip.index = htonl (interface -> index); | |
237 | ||
238 | iov [0].buf = (char *)&tip; | |
239 | iov [0].len = sizeof tip; | |
240 | iov [1].buf = (char *)raw; | |
241 | iov [1].len = len; | |
242 | trace_write_packet_iov (outpacket_trace, 2, iov, MDL); | |
243 | } | |
244 | if (!trace_playback ()) { | |
245 | return send_packet (interface, packet, raw, len, | |
246 | from, to, hto); | |
247 | } | |
248 | return len; | |
249 | } | |
250 | ||
251 | void trace_outpacket_input (trace_type_t *ttype, unsigned len, char *buf) | |
252 | { | |
253 | trace_outpacket_t *tip; | |
254 | int index; | |
255 | ||
256 | if (len < sizeof *tip) { | |
257 | log_error ("trace_input_packet: too short - %d", len); | |
258 | return; | |
259 | } | |
260 | tip = (trace_outpacket_t *)buf; | |
261 | index = ntohl (tip -> index); | |
f6b8f48d | 262 | |
a568b5bc TL |
263 | if (index > interface_count || |
264 | index < 0 || | |
265 | !interface_vector [index]) { | |
266 | log_error ("trace_input_packet: unknown interface index %d", | |
267 | index); | |
268 | return; | |
269 | } | |
270 | ||
271 | /* XXX would be nice to somehow take notice of these. */ | |
272 | } | |
273 | ||
274 | void trace_outpacket_stop (trace_type_t *ttype) { } | |
275 | ||
276 | void trace_seed_stash (trace_type_t *ttype, unsigned seed) | |
277 | { | |
278 | u_int32_t outseed; | |
279 | if (!trace_record ()) | |
280 | return; | |
281 | outseed = htonl (seed); | |
282 | trace_write_packet (ttype, sizeof outseed, (char *)&outseed, MDL); | |
283 | return; | |
284 | } | |
285 | ||
286 | void trace_seed_input (trace_type_t *ttype, unsigned length, char *buf) | |
287 | { | |
288 | u_int32_t *seed; | |
289 | ||
290 | if (length != sizeof seed) { | |
291 | log_error ("trace_seed_input: wrong size (%d)", length); | |
292 | } | |
80ff6258 TL |
293 | seed = (u_int32_t *)buf; |
294 | srandom (ntohl (*seed)); | |
a568b5bc TL |
295 | } |
296 | ||
297 | void trace_seed_stop (trace_type_t *ttype) { } | |
298 | #endif /* TRACING */ |