]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kdp/kdp_udp.c
xnu-1228.5.18.tar.gz
[apple/xnu.git] / osfmk / kdp / kdp_udp.c
CommitLineData
1c79356b 1/*
2d21ac55 2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b 27 */
2d21ac55 28
1c79356b 29/*
9bccf70c
A
30 * Copyright (c) 1982, 1986, 1993
31 * The Regents of the University of California. All rights reserved.
32 */
33
34/*
35 * Kernel Debugging Protocol UDP implementation.
1c79356b
A
36 */
37
38#include <mach_kdb.h>
39#include <mach/boolean.h>
de355530 40#include <mach/mach_types.h>
55e303ae 41#include <mach/exception_types.h>
9bccf70c 42#include <kern/cpu_data.h>
1c79356b
A
43#include <kern/debug.h>
44
0c530ab8 45#include <kdp/kdp_core.h>
1c79356b
A
46#include <kdp/kdp_internal.h>
47#include <kdp/kdp_en_debugger.h>
48#include <kdp/kdp_udp.h>
49
55e303ae 50#include <vm/vm_map.h>
91447636 51#include <vm/vm_protos.h>
0c530ab8 52#include <vm/vm_kern.h> /* kernel_map */
91447636 53
55e303ae
A
54#include <mach/memory_object_types.h>
55
56#include <string.h>
57
1c79356b
A
58#define DO_ALIGN 1 /* align all packet data accesses */
59
60extern int kdp_getc(void);
9bccf70c 61extern int reattach_wait;
1c79356b 62
9bccf70c 63static u_short ip_id; /* ip packet ctr, for ids */
1c79356b
A
64
65/* @(#)udp_usrreq.c 2.2 88/05/23 4.0NFSSRC SMI; from UCB 7.1 6/5/86 */
66
67/*
68 * UDP protocol implementation.
69 * Per RFC 768, August, 1980.
70 */
71#define UDP_TTL 60 /* deflt time to live for UDP packets */
55e303ae 72int udp_ttl = UDP_TTL;
1c79356b
A
73static unsigned char exception_seq;
74
75static struct {
76 unsigned char data[KDP_MAXPACKET];
77 unsigned int off, len;
78 boolean_t input;
79} pkt, saved_reply;
80
81struct {
82 struct {
83 struct in_addr in;
84 struct ether_addr ea;
85 } loc;
86 struct {
87 struct in_addr in;
88 struct ether_addr ea;
89 } rmt;
90} adr;
91
0c530ab8 92static const char
1c79356b
A
93*exception_message[] = {
94 "Unknown",
95 "Memory access", /* EXC_BAD_ACCESS */
96 "Failed instruction", /* EXC_BAD_INSTRUCTION */
97 "Arithmetic", /* EXC_ARITHMETIC */
98 "Emulation", /* EXC_EMULATION */
99 "Software", /* EXC_SOFTWARE */
100 "Breakpoint" /* EXC_BREAKPOINT */
101};
102
0c530ab8 103volatile int kdp_flag = 0;
9bccf70c 104
2d21ac55
A
105static kdp_send_t kdp_en_send_pkt;
106static kdp_receive_t kdp_en_recv_pkt;
1c79356b 107
9bccf70c 108
55e303ae 109static u_long kdp_current_ip_address = 0;
9bccf70c 110static struct ether_addr kdp_current_mac_address = {{0, 0, 0, 0, 0, 0}};
2d21ac55 111static void *kdp_current_ifp;
9bccf70c 112
55e303ae
A
113static void kdp_handler( void *);
114
0c530ab8
A
115static uint32_t panic_server_ip = 0;
116static uint32_t parsed_router_ip = 0;
117static uint32_t router_ip = 0;
118static uint32_t target_ip = 0;
119
120static volatile boolean_t panicd_specified = FALSE;
121static boolean_t router_specified = FALSE;
122static unsigned int panicd_port = CORE_REMOTE_PORT;
123
0c530ab8 124static struct ether_addr etherbroadcastaddr = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
55e303ae
A
125
126static struct ether_addr router_mac = {{0, 0, 0 , 0, 0, 0}};
0c530ab8
A
127static struct ether_addr destination_mac = {{0, 0, 0 , 0, 0, 0}};
128static struct ether_addr temp_mac = {{0, 0, 0 , 0, 0, 0}};
129static struct ether_addr current_resolved_MAC = {{0, 0, 0 , 0, 0, 0}};
4452a7af 130
0c530ab8
A
131static boolean_t flag_panic_dump_in_progress = FALSE;
132static boolean_t flag_router_mac_initialized = FALSE;
133
134static boolean_t flag_arp_resolved = FALSE;
55e303ae
A
135
136static unsigned int panic_timeout = 100000;
137static unsigned int last_panic_port = CORE_REMOTE_PORT;
138
139unsigned int SEGSIZE = 512;
140
0c530ab8 141__unused static unsigned int PANIC_PKTSIZE = 518;
55e303ae
A
142static char panicd_ip_str[20];
143static char router_ip_str[20];
144
145static unsigned int panic_block = 0;
2d21ac55
A
146volatile unsigned int kdp_trigger_core_dump = 0;
147__private_extern__ volatile unsigned int flag_kdp_trigger_reboot = 0;
55e303ae
A
148
149extern unsigned int not_in_kdp;
1c79356b 150
0c530ab8
A
151extern unsigned int disableConsoleOutput;
152
153extern int kdp_vm_read( caddr_t, caddr_t, unsigned int);
154extern void kdp_call(void);
155extern boolean_t kdp_call_kdb(void);
156extern int kern_dump(void);
157
158void * kdp_get_interface(void);
159void kdp_set_gateway_mac(void *);
160void kdp_set_ip_and_mac_addresses(struct in_addr *, struct ether_addr *);
161void kdp_set_interface(void *);
162
163void kdp_disable_arp(void);
164static void kdp_arp_reply(struct ether_arp *);
165static void kdp_process_arp_reply(struct ether_arp *);
166static boolean_t kdp_arp_resolve(uint32_t, struct ether_addr *);
167
2d21ac55
A
168static volatile unsigned kdp_reentry_deadline;
169
0c530ab8
A
170static boolean_t gKDPDebug = FALSE;
171#define KDP_DEBUG(...) if (gKDPDebug) printf(__VA_ARGS__);
172
173int kdp_snapshot = 0;
174static int stack_snapshot_ret = 0;
175static unsigned stack_snapshot_bytes_traced = 0;
176
177static void *stack_snapshot_buf;
178static uint32_t stack_snapshot_bufsize;
179static int stack_snapshot_pid;
180static uint32_t stack_snapshot_options;
181
2d21ac55
A
182static unsigned int old_debugger;
183
0c530ab8
A
184void
185kdp_snapshot_preflight(int pid, void * tracebuf, uint32_t tracebuf_size,
186 uint32_t options);
187
188void
189kdp_snapshot_postflight(void);
190
191extern int
2d21ac55 192kdp_stackshot(int pid, void *tracebuf, uint32_t tracebuf_size,
0c530ab8
A
193 unsigned trace_options, uint32_t *pbytesTraced);
194
195int
196kdp_stack_snapshot_geterror(void);
197
198int
199kdp_stack_snapshot_bytes_traced(void);
91447636 200
2d21ac55
A
201static thread_call_t
202kdp_timer_call;
203
204static void
205kdp_ml_enter_debugger_wrapper(__unused void *param0, __unused void *param1) {
206 kdp_ml_enter_debugger();
207}
208
209static void
210kdp_timer_callout_init(void) {
211 kdp_timer_call = thread_call_allocate(kdp_ml_enter_debugger_wrapper, NULL);
212}
213
214
1c79356b 215void
9bccf70c 216kdp_register_send_receive(
55e303ae 217 kdp_send_t send,
9bccf70c 218 kdp_receive_t receive)
1c79356b 219{
2d21ac55 220 unsigned int debug = 0;
1c79356b
A
221
222 kdp_en_send_pkt = send;
223 kdp_en_recv_pkt = receive;
55e303ae 224
9bccf70c 225 debug_log_init();
55e303ae 226
2d21ac55
A
227 kdp_timer_callout_init();
228
9bccf70c 229 PE_parse_boot_arg("debug", &debug);
55e303ae 230
2d21ac55
A
231
232 if (!debug)
233 return;
234
9bccf70c
A
235 if (debug & DB_KDP_BP_DIS)
236 kdp_flag |= KDP_BP_DIS;
55e303ae
A
237 if (debug & DB_KDP_GETC_ENA)
238 kdp_flag |= KDP_GETC_ENA;
239 if (debug & DB_ARP)
2d21ac55 240 kdp_flag |= KDP_ARP;
55e303ae
A
241
242 if (debug & DB_KERN_DUMP_ON_PANIC)
2d21ac55 243 kdp_flag |= KDP_PANIC_DUMP_ENABLED;
55e303ae 244 if (debug & DB_KERN_DUMP_ON_NMI)
2d21ac55
A
245 kdp_flag |= PANIC_CORE_ON_NMI;
246
55e303ae 247 if (debug & DB_DBG_POST_CORE)
2d21ac55
A
248 kdp_flag |= DBG_POST_CORE;
249
55e303ae 250 if (debug & DB_PANICLOG_DUMP)
2d21ac55
A
251 kdp_flag |= PANIC_LOG_DUMP;
252
55e303ae 253 if (PE_parse_boot_arg ("_panicd_ip", panicd_ip_str))
2d21ac55 254 panicd_specified = TRUE;
0c530ab8 255
55e303ae 256 if (PE_parse_boot_arg ("_router_ip", router_ip_str))
2d21ac55 257 router_specified = TRUE;
0c530ab8
A
258
259 if (!PE_parse_boot_arg ("panicd_port", &panicd_port))
260 panicd_port = CORE_REMOTE_PORT;
9bccf70c 261
1c79356b
A
262 kdp_flag |= KDP_READY;
263 if (current_debugger == NO_CUR_DB)
264 current_debugger = KDP_CUR_DB;
2d21ac55 265 if ((kdp_current_ip_address != 0) && halt_in_debugger) {
1c79356b
A
266 kdp_call();
267 halt_in_debugger=0;
268 }
269}
270
1c79356b 271void
9bccf70c 272kdp_unregister_send_receive(
0c530ab8
A
273 __unused kdp_send_t send,
274 __unused kdp_receive_t receive)
9bccf70c
A
275{
276 if (current_debugger == KDP_CUR_DB)
277 current_debugger = NO_CUR_DB;
278 kdp_flag &= ~KDP_READY;
279 kdp_en_send_pkt = NULL;
280 kdp_en_recv_pkt = NULL;
281}
282
0c530ab8
A
283/* Cache stack snapshot parameters in preparation for a trace */
284void
285kdp_snapshot_preflight(int pid, void * tracebuf, uint32_t tracebuf_size, uint32_t options)
286{
287 stack_snapshot_pid = pid;
288 stack_snapshot_buf = tracebuf;
289 stack_snapshot_bufsize = tracebuf_size;
290 stack_snapshot_options = options;
291 kdp_snapshot++;
2d21ac55
A
292 /* Mark this debugger as active, since the polled mode driver that
293 * ordinarily does this may not be enabled (yet), or since KDB may be
294 * the primary debugger.
295 */
296 old_debugger = current_debugger;
297 if (old_debugger != KDP_CUR_DB) {
298 current_debugger = KDP_CUR_DB;
299 }
0c530ab8
A
300}
301
302void
303kdp_snapshot_postflight(void)
304{
305 kdp_snapshot--;
2d21ac55
A
306 if ((kdp_en_send_pkt == NULL) || (old_debugger == KDB_CUR_DB))
307 current_debugger = old_debugger;
0c530ab8
A
308}
309
310int
311kdp_stack_snapshot_geterror(void)
312{
313 return stack_snapshot_ret;
314}
315
316int
317kdp_stack_snapshot_bytes_traced(void)
318{
319 return stack_snapshot_bytes_traced;
320}
321
2d21ac55
A
322static void
323kdp_schedule_debugger_reentry(unsigned interval) {
324 uint64_t deadline;;
325
326 clock_interval_to_deadline(interval, 1000 * 1000, &deadline);
327 thread_call_enter_delayed(kdp_timer_call, deadline);
328}
329
9bccf70c 330static void
1c79356b 331enaddr_copy(
9bccf70c
A
332 void *src,
333 void *dst
1c79356b
A
334)
335{
9bccf70c 336 bcopy((char *)src, (char *)dst, sizeof (struct ether_addr));
1c79356b
A
337}
338
9bccf70c 339static unsigned short
1c79356b 340ip_sum(
9bccf70c
A
341 unsigned char *c,
342 unsigned int hlen
0c530ab8 343 )
1c79356b 344{
0c530ab8 345 unsigned int high, low, sum;
1c79356b 346
0c530ab8
A
347 high = low = 0;
348 while (hlen-- > 0) {
349 low += c[1] + c[3];
350 high += c[0] + c[2];
1c79356b 351
0c530ab8
A
352 c += sizeof (int);
353 }
1c79356b 354
0c530ab8
A
355 sum = (high << 8) + low;
356 sum = (sum >> 16) + (sum & 65535);
1c79356b 357
0c530ab8 358 return (sum > 65535 ? sum - 65535 : sum);
1c79356b
A
359}
360
9bccf70c 361static void
1c79356b 362kdp_reply(
9bccf70c 363 unsigned short reply_port
0c530ab8 364 )
1c79356b 365{
0c530ab8
A
366 struct udpiphdr aligned_ui, *ui = &aligned_ui;
367 struct ip aligned_ip, *ip = &aligned_ip;
368 struct in_addr tmp_ipaddr;
369 struct ether_addr tmp_enaddr;
370 struct ether_header *eh = NULL;
1c79356b 371
0c530ab8
A
372 if (!pkt.input)
373 kdp_panic("kdp_reply");
1c79356b 374
0c530ab8 375 pkt.off -= sizeof (struct udpiphdr);
1c79356b
A
376
377#if DO_ALIGN
0c530ab8 378 bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui));
1c79356b 379#else
0c530ab8 380 ui = (struct udpiphdr *)&pkt.data[pkt.off];
1c79356b 381#endif
2d21ac55 382 ui->ui_next = ui->ui_prev = NULL;
0c530ab8
A
383 ui->ui_x1 = 0;
384 ui->ui_pr = IPPROTO_UDP;
385 ui->ui_len = htons((u_short)pkt.len + sizeof (struct udphdr));
386 tmp_ipaddr = ui->ui_src;
387 ui->ui_src = ui->ui_dst;
388 ui->ui_dst = tmp_ipaddr;
389 ui->ui_sport = htons(KDP_REMOTE_PORT);
390 ui->ui_dport = reply_port;
391 ui->ui_ulen = ui->ui_len;
392 ui->ui_sum = 0;
1c79356b 393#if DO_ALIGN
0c530ab8
A
394 bcopy((char *)ui, (char *)&pkt.data[pkt.off], sizeof(*ui));
395 bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip));
1c79356b 396#else
0c530ab8 397 ip = (struct ip *)&pkt.data[pkt.off];
1c79356b 398#endif
0c530ab8
A
399 ip->ip_len = htons(sizeof (struct udpiphdr) + pkt.len);
400 ip->ip_v = IPVERSION;
401 ip->ip_id = htons(ip_id++);
402 ip->ip_hl = sizeof (struct ip) >> 2;
403 ip->ip_ttl = udp_ttl;
404 ip->ip_sum = 0;
405 ip->ip_sum = htons(~ip_sum((unsigned char *)ip, ip->ip_hl));
1c79356b 406#if DO_ALIGN
0c530ab8 407 bcopy((char *)ip, (char *)&pkt.data[pkt.off], sizeof(*ip));
1c79356b
A
408#endif
409
0c530ab8 410 pkt.len += sizeof (struct udpiphdr);
1c79356b 411
0c530ab8 412 pkt.off -= sizeof (struct ether_header);
1c79356b 413
0c530ab8
A
414 eh = (struct ether_header *)&pkt.data[pkt.off];
415 enaddr_copy(eh->ether_shost, &tmp_enaddr);
416 enaddr_copy(eh->ether_dhost, eh->ether_shost);
417 enaddr_copy(&tmp_enaddr, eh->ether_dhost);
418 eh->ether_type = htons(ETHERTYPE_IP);
1c79356b 419
0c530ab8 420 pkt.len += sizeof (struct ether_header);
1c79356b 421
0c530ab8
A
422 // save reply for possible retransmission
423 bcopy((char *)&pkt, (char *)&saved_reply, sizeof(pkt));
1c79356b 424
0c530ab8 425 (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len);
1c79356b 426
0c530ab8
A
427 // increment expected sequence number
428 exception_seq++;
1c79356b
A
429}
430
9bccf70c 431static void
1c79356b
A
432kdp_send(
433 unsigned short remote_port
434)
435{
436 struct udpiphdr aligned_ui, *ui = &aligned_ui;
437 struct ip aligned_ip, *ip = &aligned_ip;
438 struct ether_header *eh;
439
440 if (pkt.input)
441 kdp_panic("kdp_send");
442
443 pkt.off -= sizeof (struct udpiphdr);
444
445#if DO_ALIGN
446 bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui));
447#else
448 ui = (struct udpiphdr *)&pkt.data[pkt.off];
449#endif
2d21ac55 450 ui->ui_next = ui->ui_prev = NULL;
1c79356b
A
451 ui->ui_x1 = 0;
452 ui->ui_pr = IPPROTO_UDP;
453 ui->ui_len = htons((u_short)pkt.len + sizeof (struct udphdr));
454 ui->ui_src = adr.loc.in;
455 ui->ui_dst = adr.rmt.in;
456 ui->ui_sport = htons(KDP_REMOTE_PORT);
457 ui->ui_dport = remote_port;
458 ui->ui_ulen = ui->ui_len;
459 ui->ui_sum = 0;
460#if DO_ALIGN
461 bcopy((char *)ui, (char *)&pkt.data[pkt.off], sizeof(*ui));
462 bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip));
463#else
464 ip = (struct ip *)&pkt.data[pkt.off];
465#endif
466 ip->ip_len = htons(sizeof (struct udpiphdr) + pkt.len);
467 ip->ip_v = IPVERSION;
468 ip->ip_id = htons(ip_id++);
469 ip->ip_hl = sizeof (struct ip) >> 2;
470 ip->ip_ttl = udp_ttl;
471 ip->ip_sum = 0;
472 ip->ip_sum = htons(~ip_sum((unsigned char *)ip, ip->ip_hl));
473#if DO_ALIGN
474 bcopy((char *)ip, (char *)&pkt.data[pkt.off], sizeof(*ip));
475#endif
476
477 pkt.len += sizeof (struct udpiphdr);
478
479 pkt.off -= sizeof (struct ether_header);
480
481 eh = (struct ether_header *)&pkt.data[pkt.off];
482 enaddr_copy(&adr.loc.ea, eh->ether_shost);
483 enaddr_copy(&adr.rmt.ea, eh->ether_dhost);
484 eh->ether_type = htons(ETHERTYPE_IP);
485
486 pkt.len += sizeof (struct ether_header);
1c79356b
A
487 (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len);
488}
489
4a249263
A
490/* We don't interpret this pointer, we just give it to the
491bsd stack so it can decide when to set the MAC and IP info. */
492void
493kdp_set_interface(void *ifp)
494{
495 kdp_current_ifp = ifp;
496}
497
498void *
2d21ac55 499kdp_get_interface(void)
4a249263
A
500{
501 return kdp_current_ifp;
502}
9bccf70c
A
503
504void
505kdp_set_ip_and_mac_addresses(
506 struct in_addr *ipaddr,
507 struct ether_addr *macaddr)
1c79356b 508{
9bccf70c
A
509 kdp_current_ip_address = ipaddr->s_addr;
510 kdp_current_mac_address = *macaddr;
2d21ac55
A
511 if ((current_debugger == KDP_CUR_DB) && halt_in_debugger) {
512 kdp_call();
513 halt_in_debugger=0;
514 }
9bccf70c
A
515}
516
55e303ae
A
517void
518kdp_set_gateway_mac(void *gatewaymac)
519{
520 router_mac = *(struct ether_addr *)gatewaymac;
0c530ab8 521 flag_router_mac_initialized = TRUE;
55e303ae
A
522}
523
9bccf70c
A
524struct ether_addr
525kdp_get_mac_addr(void)
526{
527 return kdp_current_mac_address;
528}
529
530unsigned int
531kdp_get_ip_address(void)
532{
533 return kdp_current_ip_address;
534}
535
0c530ab8
A
536void
537kdp_disable_arp(void)
538{
539 kdp_flag &= ~(DB_ARP);
540}
541
542static void
543kdp_arp_dispatch(void)
544{
545 struct ether_arp aligned_ea, *ea = &aligned_ea;
546 unsigned arp_header_offset;
547
548 arp_header_offset = sizeof(struct ether_header) + pkt.off;
549 memcpy((void *)ea, (void *)&pkt.data[arp_header_offset], sizeof(*ea));
550
551 switch(ntohs(ea->arp_op)) {
552 case ARPOP_REQUEST:
553 kdp_arp_reply(ea);
554 break;
555 case ARPOP_REPLY:
556 kdp_process_arp_reply(ea);
557 break;
558 default:
559 return;
560 }
561}
562
563static void
564kdp_process_arp_reply(struct ether_arp *ea)
565{
566 /* Are we interested in ARP replies? */
567 if (flag_arp_resolved == TRUE)
568 return;
569
570 /* Did we receive a reply from the right source? */
571 if (((struct in_addr *)(ea->arp_spa))->s_addr != target_ip)
572 return;
573
574 flag_arp_resolved = TRUE;
575 current_resolved_MAC = *(struct ether_addr *) (ea->arp_sha);
576
577 return;
578}
579
9bccf70c 580/* ARP responses are enabled when the DB_ARP bit of the debug boot arg
0c530ab8
A
581 * is set.
582 */
583
9bccf70c 584static void
0c530ab8 585kdp_arp_reply(struct ether_arp *ea)
9bccf70c
A
586{
587 struct ether_header *eh;
9bccf70c
A
588
589 struct in_addr isaddr, itaddr, myaddr;
55e303ae 590 struct ether_addr my_enaddr;
9bccf70c
A
591
592 eh = (struct ether_header *)&pkt.data[pkt.off];
593 pkt.off += sizeof(struct ether_header);
594
55e303ae
A
595 if(ntohs(ea->arp_op) != ARPOP_REQUEST)
596 return;
9bccf70c
A
597
598 myaddr.s_addr = kdp_get_ip_address();
599 my_enaddr = kdp_get_mac_addr();
600
0c530ab8
A
601 if ((ntohl(myaddr.s_addr) == 0) ||
602 ((my_enaddr.ether_addr_octet[0] & 0xff) == 0
603 && (my_enaddr.ether_addr_octet[1] & 0xff) == 0
604 && (my_enaddr.ether_addr_octet[2] & 0xff) == 0
605 && (my_enaddr.ether_addr_octet[3] & 0xff) == 0
606 && (my_enaddr.ether_addr_octet[4] & 0xff) == 0
607 && (my_enaddr.ether_addr_octet[5] & 0xff) == 0
608 ))
9bccf70c
A
609 return;
610
611 (void)memcpy((void *)&isaddr, (void *)ea->arp_spa, sizeof (isaddr));
612 (void)memcpy((void *)&itaddr, (void *)ea->arp_tpa, sizeof (itaddr));
0c530ab8 613
9bccf70c
A
614 if (itaddr.s_addr == myaddr.s_addr) {
615 (void)memcpy((void *)ea->arp_tha, (void *)ea->arp_sha, sizeof(ea->arp_sha));
616 (void)memcpy((void *)ea->arp_sha, (void *)&my_enaddr, sizeof(ea->arp_sha));
617
618 (void)memcpy((void *)ea->arp_tpa, (void *) ea->arp_spa, sizeof(ea->arp_spa));
619 (void)memcpy((void *)ea->arp_spa, (void *) &itaddr, sizeof(ea->arp_spa));
620
621 ea->arp_op = htons(ARPOP_REPLY);
622 ea->arp_pro = htons(ETHERTYPE_IP);
623 (void)memcpy(eh->ether_dhost, ea->arp_tha, sizeof(eh->ether_dhost));
624 (void)memcpy(eh->ether_shost, &my_enaddr, sizeof(eh->ether_shost));
625 eh->ether_type = htons(ETHERTYPE_ARP);
626 (void)memcpy(&pkt.data[pkt.off], ea, sizeof(*ea));
627 pkt.off -= sizeof (struct ether_header);
628 /* pkt.len is still the length we want, ether_header+ether_arp */
629 (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len);
630 }
631}
632
633static void
634kdp_poll(void)
635{
0c530ab8
A
636 struct ether_header *eh = NULL;
637 struct udpiphdr aligned_ui, *ui = &aligned_ui;
638 struct ip aligned_ip, *ip = &aligned_ip;
639 static int msg_printed;
8f6c56a5 640
0c530ab8
A
641 if (pkt.input)
642 kdp_panic("kdp_poll");
1c79356b 643
0c530ab8
A
644 if (!kdp_en_recv_pkt || !kdp_en_send_pkt) {
645 if( msg_printed == 0) {
646 msg_printed = 1;
647 printf("kdp_poll: no debugger device\n");
648 }
649 return;
1c79356b 650 }
1c79356b 651
0c530ab8
A
652 pkt.off = pkt.len = 0;
653 (*kdp_en_recv_pkt)(pkt.data, &pkt.len, 3/* ms */);
8f6c56a5 654
0c530ab8 655 if (pkt.len == 0)
4452a7af 656 return;
21362eb3 657
0c530ab8
A
658 if (pkt.len >= sizeof(struct ether_header))
659 {
660 eh = (struct ether_header *)&pkt.data[pkt.off];
661
662 if (kdp_flag & KDP_ARP)
663 {
664 if (ntohs(eh->ether_type) == ETHERTYPE_ARP)
665 {
666 kdp_arp_dispatch();
667 return;
668 }
669 }
670 }
671
672 if (pkt.len < (sizeof (struct ether_header) + sizeof (struct udpiphdr)))
673 return;
6601e61a 674
0c530ab8
A
675 pkt.off += sizeof (struct ether_header);
676 if (ntohs(eh->ether_type) != ETHERTYPE_IP) {
677 return;
678 }
1c79356b
A
679
680#if DO_ALIGN
0c530ab8
A
681 bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui));
682 bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip));
1c79356b 683#else
0c530ab8
A
684 ui = (struct udpiphdr *)&pkt.data[pkt.off];
685 ip = (struct ip *)&pkt.data[pkt.off];
1c79356b
A
686#endif
687
0c530ab8
A
688 pkt.off += sizeof (struct udpiphdr);
689 if (ui->ui_pr != IPPROTO_UDP) {
690 return;
691 }
1c79356b 692
0c530ab8
A
693 if (ip->ip_hl > (sizeof (struct ip) >> 2)) {
694 return;
695 }
4452a7af 696
0c530ab8
A
697 if (ntohs(ui->ui_dport) != KDP_REMOTE_PORT) {
698 if (panicd_port == (ntohs(ui->ui_dport)) &&
699 flag_panic_dump_in_progress) {
700 last_panic_port = ui->ui_sport;
701 }
702 else
703 return;
89b3af67 704 }
0c530ab8
A
705 /* If we receive a kernel debugging packet whilst a
706 * core dump is in progress, abort the transfer and
707 * enter the debugger.
708 */
709 else
710 if (flag_panic_dump_in_progress)
711 {
712 abort_panic_transfer();
713 return;
714 }
715
716 if (!kdp.is_conn && !flag_panic_dump_in_progress) {
717 enaddr_copy(eh->ether_dhost, &adr.loc.ea);
718 adr.loc.in = ui->ui_dst;
719
720 enaddr_copy(eh->ether_shost, &adr.rmt.ea);
721 adr.rmt.in = ui->ui_src;
4452a7af
A
722 }
723
0c530ab8
A
724 /*
725 * Calculate kdp packet length.
726 */
727 pkt.len = ntohs((u_short)ui->ui_ulen) - sizeof (struct udphdr);
728 pkt.input = TRUE;
729}
4452a7af 730
0c530ab8
A
731/* Create and transmit an ARP resolution request for the target IP address.
732 * This is modeled on ether_inet_arp()/RFC 826.
733 */
4452a7af 734
0c530ab8
A
735static void
736transmit_ARP_request(uint32_t ip_addr)
737{
738 struct ether_header *eh = (struct ether_header *) &pkt.data[0];
739 struct ether_arp *ea = (struct ether_arp *) &pkt.data[sizeof(struct ether_header)];
740
741 KDP_DEBUG("Transmitting ARP request\n");
742 /* Populate the ether_header */
743 eh->ether_type = htons(ETHERTYPE_ARP);
744 enaddr_copy(&kdp_current_mac_address, eh->ether_shost);
745 enaddr_copy(&etherbroadcastaddr, eh->ether_dhost);
746
747 /* Populate the ARP header */
748 ea->arp_pro = htons(ETHERTYPE_IP);
749 ea->arp_hln = sizeof(ea->arp_sha);
750 ea->arp_pln = sizeof(ea->arp_spa);
751 ea->arp_hrd = htons(ARPHRD_ETHER);
752 ea->arp_op = htons(ARPOP_REQUEST);
753
754 /* Target fields */
755 enaddr_copy(&etherbroadcastaddr, ea->arp_tha);
756 memcpy(ea->arp_tpa, (void *) &ip_addr, sizeof(ip_addr));
757
758 /* Source fields */
759 enaddr_copy(&kdp_current_mac_address, ea->arp_sha);
760 memcpy(ea->arp_spa, (void *) &kdp_current_ip_address, sizeof(kdp_current_ip_address));
761
762 pkt.off = 0;
763 pkt.len = sizeof(struct ether_header) + sizeof(struct ether_arp);
764 /* Transmit */
765 (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len);
766}
767
768static boolean_t
769kdp_arp_resolve(uint32_t arp_target_ip, struct ether_addr *resolved_MAC)
770{
771 int poll_count = 256; /* ~770 ms modulo broadcast/delayed traffic? */
772 char tretries = 0;
773
774#define NUM_ARP_TX_RETRIES 5
775
776 target_ip = arp_target_ip;
777 flag_arp_resolved = FALSE;
778
779TRANSMIT_RETRY:
780 pkt.off = pkt.len = 0;
781
782 tretries++;
783
784 if (tretries >= NUM_ARP_TX_RETRIES) {
785 return FALSE;
786 }
787
788 KDP_DEBUG("ARP TX attempt #%d \n", tretries);
789
790 transmit_ARP_request(arp_target_ip);
791
792 while (!pkt.input && !flag_arp_resolved && flag_panic_dump_in_progress && --poll_count) {
793 kdp_poll();
794 }
795
796 if (flag_arp_resolved) {
797 *resolved_MAC = current_resolved_MAC;
798 return TRUE;
799 }
800
801 if (!flag_panic_dump_in_progress || pkt.input) /* we received a debugging packet, bail*/
802 {
803 printf("Received a debugger packet,transferring control to debugger\n");
804 /* Indicate that we should wait in the debugger when we return */
805 kdp_flag |= DBG_POST_CORE;
806 pkt.input = FALSE;
807 return FALSE;
808 }
809 else /* We timed out */
810 if (0 == poll_count) {
811 poll_count = 256;
812 goto TRANSMIT_RETRY;
813 }
814 return FALSE;
1c79356b
A
815}
816
9bccf70c 817static void
1c79356b 818kdp_handler(
9bccf70c 819 void *saved_state
1c79356b
A
820)
821{
822 unsigned short reply_port;
823 kdp_hdr_t aligned_hdr, *hdr = &aligned_hdr;
824
1c79356b
A
825 kdp.saved_state = saved_state; // see comment in kdp_raise_exception
826
827 do {
828 while (!pkt.input)
829 kdp_poll();
830
831#if DO_ALIGN
832 bcopy((char *)&pkt.data[pkt.off], (char *)hdr, sizeof(*hdr));
833#else
834 hdr = (kdp_hdr_t *)&pkt.data[pkt.off];
835#endif
836
837 // ignore replies -- we're not expecting them anyway.
838 if (hdr->is_reply) {
839 goto again;
840 }
841
9bccf70c
A
842 if (hdr->request == KDP_REATTACH)
843 exception_seq = hdr->seq;
844
1c79356b
A
845 // check for retransmitted request
846 if (hdr->seq == (exception_seq - 1)) {
847 /* retransmit last reply */
848 (*kdp_en_send_pkt)(&saved_reply.data[saved_reply.off],
849 saved_reply.len);
850 goto again;
851 } else if (hdr->seq != exception_seq) {
852 printf("kdp: bad sequence %d (want %d)\n",
853 hdr->seq, exception_seq);
854 goto again;
855 }
856
857 if (kdp_packet((unsigned char*)&pkt.data[pkt.off],
858 (int *)&pkt.len,
859 (unsigned short *)&reply_port)) {
860 kdp_reply(reply_port);
861 }
862
863again:
864 pkt.input = FALSE;
865 } while (kdp.is_halted);
866}
867
9bccf70c
A
868static void
869kdp_connection_wait(void)
1c79356b 870{
55e303ae 871 unsigned short reply_port;
55e303ae
A
872 struct ether_addr kdp_mac_addr = kdp_get_mac_addr();
873 unsigned int ip_addr = ntohl(kdp_get_ip_address());
9bccf70c 874
0c530ab8
A
875 /*
876 * Do both a printf() and a kprintf() of the MAC and IP so that
877 * they will print out on headless machines but not be added to
878 * the panic.log
879 */
880
9bccf70c
A
881 printf( "ethernet MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
882 kdp_mac_addr.ether_addr_octet[0] & 0xff,
883 kdp_mac_addr.ether_addr_octet[1] & 0xff,
884 kdp_mac_addr.ether_addr_octet[2] & 0xff,
885 kdp_mac_addr.ether_addr_octet[3] & 0xff,
886 kdp_mac_addr.ether_addr_octet[4] & 0xff,
887 kdp_mac_addr.ether_addr_octet[5] & 0xff);
888
0c530ab8
A
889 kprintf( "ethernet MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
890 kdp_mac_addr.ether_addr_octet[0] & 0xff,
891 kdp_mac_addr.ether_addr_octet[1] & 0xff,
892 kdp_mac_addr.ether_addr_octet[2] & 0xff,
893 kdp_mac_addr.ether_addr_octet[3] & 0xff,
894 kdp_mac_addr.ether_addr_octet[4] & 0xff,
895 kdp_mac_addr.ether_addr_octet[5] & 0xff);
896
9bccf70c
A
897 printf( "ip address: %d.%d.%d.%d\n",
898 (ip_addr & 0xff000000) >> 24,
899 (ip_addr & 0xff0000) >> 16,
900 (ip_addr & 0xff00) >> 8,
901 (ip_addr & 0xff));
902
0c530ab8
A
903 kprintf( "ip address: %d.%d.%d.%d\n",
904 (ip_addr & 0xff000000) >> 24,
905 (ip_addr & 0xff0000) >> 16,
906 (ip_addr & 0xff00) >> 8,
907 (ip_addr & 0xff));
908
55e303ae
A
909 printf("\nWaiting for remote debugger connection.\n");
910
2d21ac55 911
55e303ae
A
912 if (reattach_wait == 0) {
913 if((kdp_flag & KDP_GETC_ENA) && (0 != kdp_getc()))
914 {
915 printf("Options..... Type\n");
916 printf("------------ ----\n");
917 printf("continue.... 'c'\n");
918 printf("reboot...... 'r'\n");
1c79356b 919#if MACH_KDB
55e303ae 920 printf("enter kdb... 'k'\n");
1c79356b 921#endif
55e303ae
A
922 }
923 } else
924 reattach_wait = 0;
9bccf70c 925
55e303ae
A
926 exception_seq = 0;
927
928 do {
929 kdp_hdr_t aligned_hdr, *hdr = &aligned_hdr;
1c79356b 930
55e303ae
A
931 while (!pkt.input) {
932 if (kdp_flag & KDP_GETC_ENA) {
933 switch(kdp_getc()) {
934 case 'c':
935 printf("Continuing...\n");
936 return;
937 case 'r':
938 printf("Rebooting...\n");
939 kdp_reboot();
940 break;
1c79356b 941#if MACH_KDB
55e303ae
A
942 case 'k':
943 printf("calling kdb...\n");
944 if (kdp_call_kdb())
945 return;
946 else
947 printf("not implemented...\n");
1c79356b 948#endif
55e303ae
A
949 default:
950 break;
951 }
952 }
953 kdp_poll();
954 }
1c79356b 955
1c79356b 956#if DO_ALIGN
55e303ae 957 bcopy((char *)&pkt.data[pkt.off], (char *)hdr, sizeof(*hdr));
1c79356b 958#else
55e303ae 959 hdr = (kdp_hdr_t *)&pkt.data[pkt.off];
1c79356b 960#endif
55e303ae
A
961 if (hdr->request == KDP_HOSTREBOOT) {
962 kdp_reboot();
963 /* should not return! */
964 }
965 if (((hdr->request == KDP_CONNECT) || (hdr->request == KDP_REATTACH)) &&
966 !hdr->is_reply && (hdr->seq == exception_seq)) {
967 if (kdp_packet((unsigned char *)&pkt.data[pkt.off],
968 (int *)&pkt.len,
969 (unsigned short *)&reply_port))
970 kdp_reply(reply_port);
971 if (hdr->request == KDP_REATTACH) {
972 reattach_wait = 0;
973 hdr->request=KDP_DISCONNECT;
974 exception_seq = 0;
975 }
976 }
977
978 pkt.input = FALSE;
979 } while (!kdp.is_conn);
1c79356b 980
55e303ae
A
981 if (current_debugger == KDP_CUR_DB)
982 active_debugger=1;
983 printf("Connected to remote debugger.\n");
1c79356b
A
984}
985
9bccf70c 986static void
1c79356b
A
987kdp_send_exception(
988 unsigned int exception,
989 unsigned int code,
990 unsigned int subcode
991)
992{
993 unsigned short remote_port;
9bccf70c
A
994 unsigned int timeout_count = 100;
995 unsigned int poll_timeout;
1c79356b 996
1c79356b
A
997 do {
998 pkt.off = sizeof (struct ether_header) + sizeof (struct udpiphdr);
999 kdp_exception((unsigned char *)&pkt.data[pkt.off],
1000 (int *)&pkt.len,
1001 (unsigned short *)&remote_port,
1002 (unsigned int)exception,
1003 (unsigned int)code,
1004 (unsigned int)subcode);
9bccf70c 1005
1c79356b
A
1006 kdp_send(remote_port);
1007
9bccf70c
A
1008 poll_timeout = 50;
1009 while(!pkt.input && poll_timeout)
1010 {
1011 kdp_poll();
1012 poll_timeout--;
1013 }
1014
1c79356b
A
1015 if (pkt.input) {
1016 if (!kdp_exception_ack(&pkt.data[pkt.off], pkt.len)) {
1017 pkt.input = FALSE;
1c79356b 1018 }
1c79356b 1019 }
9bccf70c 1020
1c79356b 1021 pkt.input = FALSE;
9bccf70c 1022
1c79356b 1023 if (kdp.exception_ack_needed)
9bccf70c 1024 kdp_us_spin(250000);
1c79356b
A
1025
1026 } while (kdp.exception_ack_needed && timeout_count--);
1027
1028 if (kdp.exception_ack_needed) {
1029 // give up & disconnect
1030 printf("kdp: exception ack timeout\n");
9bccf70c
A
1031 if (current_debugger == KDP_CUR_DB)
1032 active_debugger=0;
1c79356b
A
1033 kdp_reset();
1034 }
1035}
1036
1037void
1038kdp_raise_exception(
1039 unsigned int exception,
1040 unsigned int code,
1041 unsigned int subcode,
1042 void *saved_state
1043)
1044{
1c79356b
A
1045 int index;
1046
2d21ac55
A
1047 /* Was a system trace requested ? */
1048 if (kdp_snapshot && (!panic_active()) && (panic_caller == 0)) {
1049 stack_snapshot_ret = kdp_stackshot(stack_snapshot_pid,
1050 stack_snapshot_buf, stack_snapshot_bufsize,
1051 stack_snapshot_options, &stack_snapshot_bytes_traced);
1052 return;
1053 }
1054
9bccf70c
A
1055 disable_preemption();
1056
1c79356b
A
1057 if (saved_state == 0)
1058 printf("kdp_raise_exception with NULL state\n");
1059
1060 index = exception;
1061 if (exception != EXC_BREAKPOINT) {
1062 if (exception > EXC_BREAKPOINT || exception < EXC_BAD_ACCESS) {
1063 index = 0;
1064 }
1065 printf("%s exception (%x,%x,%x)\n",
1066 exception_message[index],
1067 exception, code, subcode);
1068 }
1069
1070 kdp_sync_cache();
1071
1072 /* XXX WMG it seems that sometimes it doesn't work to let kdp_handler
1073 * do this. I think the client and the host can get out of sync.
1074 */
1075 kdp.saved_state = saved_state;
cf7d32b8
A
1076 kdp.kdp_cpu = cpu_number();
1077 kdp.kdp_thread = current_thread();
1078
1c79356b
A
1079 if (pkt.input)
1080 kdp_panic("kdp_raise_exception");
55e303ae 1081
0c530ab8 1082
55e303ae
A
1083 if (((kdp_flag & KDP_PANIC_DUMP_ENABLED) || (kdp_flag & PANIC_LOG_DUMP))
1084 && (panicstr != (char *) 0)) {
1085
0c530ab8 1086 kdp_panic_dump();
55e303ae
A
1087 }
1088 else
1089 if ((kdp_flag & PANIC_CORE_ON_NMI) && (panicstr == (char *) 0) &&
1090 !kdp.is_conn) {
1091
2d21ac55 1092 disable_debug_output = disableConsoleOutput = FALSE;
55e303ae
A
1093 kdp_panic_dump();
1094
1095 if (!(kdp_flag & DBG_POST_CORE))
1096 goto exit_raise_exception;
1097 }
1098
9bccf70c 1099 again:
1c79356b
A
1100 if (!kdp.is_conn)
1101 kdp_connection_wait();
55e303ae 1102 else {
1c79356b 1103 kdp_send_exception(exception, code, subcode);
55e303ae 1104 if (kdp.exception_ack_needed) {
9bccf70c
A
1105 kdp.exception_ack_needed = FALSE;
1106 kdp_remove_all_breakpoints();
1107 printf("Remote debugger disconnected.\n");
1108 }
1109 }
1c79356b
A
1110
1111 if (kdp.is_conn) {
1112 kdp.is_halted = TRUE; /* XXX */
1113 kdp_handler(saved_state);
1114 if (!kdp.is_conn)
9bccf70c
A
1115 {
1116 kdp_remove_all_breakpoints();
1c79356b 1117 printf("Remote debugger disconnected.\n");
9bccf70c 1118 }
1c79356b 1119 }
55e303ae
A
1120 /* Allow triggering a panic core dump when connected to the machine
1121 * Continuing after setting kdp_trigger_core_dump should do the
1122 * trick.
1123 */
91447636 1124
55e303ae
A
1125 if (1 == kdp_trigger_core_dump) {
1126 kdp_flag &= ~PANIC_LOG_DUMP;
1127 kdp_flag |= KDP_PANIC_DUMP_ENABLED;
1128 kdp_panic_dump();
2d21ac55 1129 kdp_trigger_core_dump = 0;
55e303ae 1130 }
1c79356b 1131
91447636
A
1132/* Trigger a reboot if the user has set this flag through the
1133 * debugger.Ideally, this would be done through the HOSTREBOOT packet
1134 * in the protocol,but that will need gdb support,and when it's
1135 * available, it should work automatically.
1136 */
1137 if (1 == flag_kdp_trigger_reboot) {
1138 kdp_reboot();
1139 /* If we're still around, reset the flag */
1140 flag_kdp_trigger_reboot = 0;
1141 }
2d21ac55
A
1142
1143 if (kdp_reentry_deadline) {
1144 kdp_schedule_debugger_reentry(kdp_reentry_deadline);
1145 printf("Debugger re-entry scheduled in %d milliseconds\n", kdp_reentry_deadline);
1146 kdp_reentry_deadline = 0;
1147 }
1148
1c79356b 1149 kdp_sync_cache();
9bccf70c
A
1150
1151 if (reattach_wait == 1)
1152 goto again;
91447636
A
1153
1154exit_raise_exception:
9bccf70c 1155 enable_preemption();
1c79356b
A
1156}
1157
1158void
1159kdp_reset(void)
1160{
9bccf70c
A
1161 kdp.reply_port = kdp.exception_port = 0;
1162 kdp.is_halted = kdp.is_conn = FALSE;
1163 kdp.exception_seq = kdp.conn_seq = 0;
1c79356b
A
1164}
1165
55e303ae
A
1166struct corehdr *
1167create_panic_header(unsigned int request, const char *corename,
0c530ab8 1168 unsigned length, unsigned int block)
55e303ae 1169{
0c530ab8
A
1170 struct udpiphdr aligned_ui, *ui = &aligned_ui;
1171 struct ip aligned_ip, *ip = &aligned_ip;
1172 struct ether_header *eh;
1173 struct corehdr *coreh;
1174 const char *mode = "octet";
1175 char modelen = strlen(mode);
55e303ae 1176
0c530ab8
A
1177 pkt.off = sizeof (struct ether_header);
1178 pkt.len = length + ((request == KDP_WRQ) ? modelen : 0) +
1179 (corename ? strlen(corename): 0) + sizeof(struct corehdr);
55e303ae
A
1180
1181#if DO_ALIGN
0c530ab8 1182 bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui));
55e303ae 1183#else
0c530ab8 1184 ui = (struct udpiphdr *)&pkt.data[pkt.off];
55e303ae 1185#endif
2d21ac55 1186 ui->ui_next = ui->ui_prev = NULL;
0c530ab8
A
1187 ui->ui_x1 = 0;
1188 ui->ui_pr = IPPROTO_UDP;
1189 ui->ui_len = htons((u_short)pkt.len + sizeof (struct udphdr));
1190 ui->ui_src.s_addr = kdp_current_ip_address;
1191 /* Already in network byte order via inet_aton() */
1192 ui->ui_dst.s_addr = panic_server_ip;
1193 ui->ui_sport = htons(panicd_port);
1194 ui->ui_dport = ((request == KDP_WRQ) ? htons(panicd_port) : last_panic_port);
1195 ui->ui_ulen = ui->ui_len;
1196 ui->ui_sum = 0;
55e303ae 1197#if DO_ALIGN
0c530ab8
A
1198 bcopy((char *)ui, (char *)&pkt.data[pkt.off], sizeof(*ui));
1199 bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip));
55e303ae 1200#else
0c530ab8 1201 ip = (struct ip *)&pkt.data[pkt.off];
55e303ae 1202#endif
0c530ab8
A
1203 ip->ip_len = htons(sizeof (struct udpiphdr) + pkt.len);
1204 ip->ip_v = IPVERSION;
1205 ip->ip_id = htons(ip_id++);
1206 ip->ip_hl = sizeof (struct ip) >> 2;
1207 ip->ip_ttl = udp_ttl;
1208 ip->ip_sum = 0;
1209 ip->ip_sum = htons(~ip_sum((unsigned char *)ip, ip->ip_hl));
55e303ae 1210#if DO_ALIGN
0c530ab8 1211 bcopy((char *)ip, (char *)&pkt.data[pkt.off], sizeof(*ip));
55e303ae
A
1212#endif
1213
0c530ab8 1214 pkt.len += sizeof (struct udpiphdr);
55e303ae 1215
0c530ab8 1216 pkt.off += sizeof (struct udpiphdr);
55e303ae 1217
0c530ab8
A
1218 coreh = (struct corehdr *) &pkt.data[pkt.off];
1219 coreh->th_opcode = htons((u_short)request);
55e303ae 1220
0c530ab8
A
1221 if (request == KDP_WRQ)
1222 {
2d21ac55 1223 char *cp;
0c530ab8
A
1224
1225 cp = coreh->th_u.tu_rpl;
2d21ac55 1226 cp += strlcpy (cp, corename, KDP_MAXPACKET);
0c530ab8 1227 *cp++ = '\0';
2d21ac55 1228 cp += strlcpy (cp, mode, KDP_MAXPACKET - strlen(corename));
0c530ab8
A
1229 *cp++ = '\0';
1230 }
1231 else
1232 {
1233 coreh->th_block = htonl((unsigned int) block);
1234 }
55e303ae 1235
0c530ab8
A
1236 pkt.off -= sizeof (struct udpiphdr);
1237 pkt.off -= sizeof (struct ether_header);
55e303ae 1238
0c530ab8
A
1239 eh = (struct ether_header *)&pkt.data[pkt.off];
1240 enaddr_copy(&kdp_current_mac_address, eh->ether_shost);
1241 enaddr_copy(&destination_mac, eh->ether_dhost);
1242 eh->ether_type = htons(ETHERTYPE_IP);
55e303ae 1243
0c530ab8
A
1244 pkt.len += sizeof (struct ether_header);
1245 return coreh;
55e303ae
A
1246}
1247
0c530ab8
A
1248int kdp_send_crashdump_data(unsigned int request, char *corename,
1249 unsigned int length, caddr_t txstart)
55e303ae 1250{
0c530ab8
A
1251 caddr_t txend = txstart + length;
1252 int panic_error = 0;
55e303ae 1253
0c530ab8
A
1254 if (length <= SEGSIZE) {
1255 if ((panic_error = kdp_send_crashdump_pkt(request, corename, length, (caddr_t) txstart)) < 0) {
1256 printf ("kdp_send_crashdump_pkt failed with error %d\n", panic_error);
1257 return panic_error ;
1258 }
4452a7af 1259 }
0c530ab8
A
1260 else
1261 {
1262 while (txstart <= (txend - SEGSIZE)) {
1263 if ((panic_error = kdp_send_crashdump_pkt(KDP_DATA, NULL, SEGSIZE, txstart)) < 0) {
1264 printf ("kdp_send_crashdump_pkt failed with error %d\n", panic_error);
1265 return panic_error;
1266 }
1267 txstart += SEGSIZE;
1268 if (!(panic_block % 2000))
1269 printf(".");
1270 }
1271 if (txstart < txend) {
1272 kdp_send_crashdump_pkt(request, corename, (txend - txstart), txstart);
1273 }
1274 }
1275 return 0;
55e303ae
A
1276}
1277
0c530ab8
A
1278int
1279kdp_send_crashdump_pkt(unsigned int request, char *corename,
1280 unsigned int length, void *panic_data)
55e303ae 1281{
0c530ab8
A
1282 struct corehdr *th = NULL;
1283 int poll_count = 2500;
55e303ae 1284
0c530ab8
A
1285 char rretries = 0, tretries = 0;
1286
1287 pkt.off = pkt.len = 0;
55e303ae 1288
0c530ab8
A
1289 if (request == KDP_WRQ) /* longer timeout for initial request */
1290 poll_count += 1000;
55e303ae
A
1291
1292TRANSMIT_RETRY:
0c530ab8 1293 tretries++;
8f6c56a5 1294
0c530ab8
A
1295 if (tretries >=15) {
1296/* The crashdump server is unreachable for some reason. This could be a network
1297 * issue or, if we've been especially unfortunate, we've hit Radar 2760413,
1298 * which is a long standing problem with the IOKit polled mode network driver
1299 * shim which can prevent transmits/receives completely.
1300 */
1301 printf ("Cannot contact panic server, timing out.\n");
1302 return (-3);
1303 }
8f6c56a5 1304
0c530ab8
A
1305 if (tretries > 2)
1306 printf("TX retry #%d ", tretries );
1307
1308 th = create_panic_header(request, corename, length, panic_block);
21362eb3 1309
0c530ab8
A
1310 if (request == KDP_DATA) {
1311 if (!kdp_vm_read((caddr_t) panic_data, (caddr_t) th->th_data, length)) {
1312 memset ((caddr_t) th->th_data, 'X', length);
1313 }
1314 }
1315 else if (request == KDP_SEEK) {
1316 *(unsigned int *) th->th_data = htonl(*(unsigned int *) panic_data);
1317 }
21362eb3 1318
0c530ab8 1319 (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len);
6601e61a 1320
0c530ab8
A
1321 /* Listen for the ACK */
1322RECEIVE_RETRY:
1323 while (!pkt.input && flag_panic_dump_in_progress && poll_count) {
1324 kdp_poll();
1325 poll_count--;
1326 }
6601e61a 1327
0c530ab8 1328 if (pkt.input) {
55e303ae 1329
0c530ab8 1330 pkt.input = FALSE;
55e303ae 1331
0c530ab8 1332 th = (struct corehdr *) &pkt.data[pkt.off];
55e303ae 1333
0c530ab8
A
1334 if (ntohs(th->th_opcode) == KDP_ACK && ntohl(th->th_block) == panic_block) {
1335 }
1336 else
1337 if (ntohs(th->th_opcode) == KDP_ERROR) {
1338 printf("Panic server returned error %d, retrying\n", ntohl(th->th_code));
1339 poll_count = 1000;
1340 goto TRANSMIT_RETRY;
1341 }
1342 else
1343 if (ntohl(th->th_block) == (panic_block - 1)) {
1344 printf("RX retry ");
1345 if (++rretries > 1)
1346 goto TRANSMIT_RETRY;
1347 else
1348 goto RECEIVE_RETRY;
1349 }
55e303ae 1350 }
0c530ab8
A
1351 else
1352 if (!flag_panic_dump_in_progress) /* we received a debugging packet, bail*/
1353 {
1354 printf("Received a debugger packet,transferring control to debugger\n");
1355 /* Configure that if not set ..*/
1356 kdp_flag |= DBG_POST_CORE;
1357 return (-2);
1358 }
1359 else /* We timed out */
1360 if (0 == poll_count) {
1361 poll_count = 1000;
1362 kdp_us_spin ((tretries%4) * panic_timeout); /* capped linear backoff */
1363 goto TRANSMIT_RETRY;
1364 }
55e303ae 1365
0c530ab8 1366 panic_block++;
55e303ae 1367
0c530ab8
A
1368 if (request == KDP_EOF)
1369 printf("\nTotal number of packets transmitted: %d\n", panic_block);
55e303ae 1370
0c530ab8 1371 return 1;
55e303ae
A
1372}
1373
55e303ae
A
1374static int
1375isdigit (char c)
1376{
1377 return ((c > 47) && (c < 58));
1378}
1379/* From user mode Libc - this ought to be in a library */
1380static char *
0c530ab8 1381strnstr(char *s, const char *find, size_t slen)
55e303ae
A
1382{
1383 char c, sc;
1384 size_t len;
1385
1386 if ((c = *find++) != '\0') {
1387 len = strlen(find);
1388 do {
1389 do {
1390 if ((sc = *s++) == '\0' || slen-- < 1)
1391 return (NULL);
1392 } while (sc != c);
1393 if (len > slen)
1394 return (NULL);
1395 } while (strncmp(s, find, len) != 0);
1396 s--;
1397 }
2d21ac55 1398 return (s);
55e303ae
A
1399}
1400
0c530ab8
A
1401extern char version[];
1402
55e303ae
A
1403/* Horrid hack to extract xnu version if possible - a much cleaner approach
1404 * would be to have the integrator run a script which would copy the
1405 * xnu version into a string or an int somewhere at project submission
1406 * time - makes assumptions about sizeof(version), but will not fail if
1407 * it changes, but may be incorrect.
1408 */
0c530ab8
A
1409/* 2006: Incorporated a change from Darwin user P. Lovell to extract
1410 * the minor kernel version numbers from the version string.
1411 */
55e303ae
A
1412static int
1413kdp_get_xnu_version(char *versionbuf)
1414{
0c530ab8
A
1415 char *versionpos;
1416 char vstr[20];
1417 int retval = -1;
1418 char *vptr;
1419
2d21ac55 1420 strlcpy(vstr, "custom", 10);
cf7d32b8
A
1421 if (strlcpy(versionbuf, version, 95) < 95) {
1422 versionpos = strnstr(versionbuf, "xnu-", 90);
1423 if (versionpos) {
1424 strncpy(vstr, versionpos, sizeof(vstr));
1425 vstr[sizeof(vstr)-1] = '\0';
1426 vptr = vstr + 4; /* Begin after "xnu-" */
1427 while (*vptr && (isdigit(*vptr) || *vptr == '.'))
1428 vptr++;
1429 *vptr = '\0';
1430 /* Remove trailing period, if any */
1431 if (*(--vptr) == '.')
0c530ab8 1432 *vptr = '\0';
cf7d32b8 1433 retval = 0;
0c530ab8
A
1434 }
1435 }
2d21ac55 1436 strlcpy(versionbuf, vstr, KDP_MAXPACKET);
0c530ab8 1437 return retval;
55e303ae 1438}
91447636 1439
0c530ab8
A
1440extern char *inet_aton(const char *cp, struct in_addr *pin);
1441extern int snprintf(char *str, size_t size, const char *format, ...);
1442
55e303ae
A
1443/* Primary dispatch routine for the system dump */
1444void
2d21ac55 1445kdp_panic_dump(void)
55e303ae 1446{
0c530ab8
A
1447 char corename[50];
1448 char coreprefix[10];
1449 int panic_error;
55e303ae 1450
0c530ab8
A
1451 uint64_t abstime;
1452 uint32_t current_ip = ntohl(kdp_current_ip_address);
c0fea474 1453
0c530ab8
A
1454 if (flag_panic_dump_in_progress) {
1455 printf("System dump aborted.\n");
1456 goto panic_dump_exit;
1457 }
1458
1459 printf("Entering system dump routine\n");
8f6c56a5 1460
0c530ab8
A
1461 if (!panicd_specified) {
1462 printf("A dump server was not specified in the boot-args, terminating kernel core dump.\n");
1463 goto panic_dump_exit;
1464 }
8f6c56a5 1465
0c530ab8
A
1466 flag_panic_dump_in_progress = TRUE;
1467 not_in_kdp = 0;
55e303ae 1468
0c530ab8
A
1469 if (pkt.input)
1470 kdp_panic("kdp_panic_dump: unexpected pending input packet");
55e303ae 1471
0c530ab8 1472 kdp_get_xnu_version((char *) &pkt.data[0]);
55e303ae 1473
0c530ab8
A
1474 /* Panic log bit takes precedence over core dump bit */
1475 if ((panicstr != (char *) 0) && (kdp_flag & PANIC_LOG_DUMP))
1476 strncpy(coreprefix, "paniclog", sizeof(coreprefix));
1477 else
1478 strncpy(coreprefix, "core", sizeof(coreprefix));
55e303ae 1479
0c530ab8
A
1480 abstime = mach_absolute_time();
1481 pkt.data[20] = '\0';
1482 snprintf (corename, sizeof(corename), "%s-%s-%d.%d.%d.%d-%x",
55e303ae 1483 coreprefix, &pkt.data[0],
0c530ab8
A
1484 (current_ip & 0xff000000) >> 24,
1485 (current_ip & 0xff0000) >> 16,
1486 (current_ip & 0xff00) >> 8,
1487 (current_ip & 0xff),
1488 (unsigned int) (abstime & 0xffffffff));
1489
1490 if (0 == inet_aton(panicd_ip_str, (struct in_addr *) &panic_server_ip)) {
1491 printf("inet_aton() failed interpreting %s as a panic server IP\n", panicd_ip_str);
1492 }
1493 else
1494 printf("Attempting connection to panic server configured at IP %s, port %d\n", panicd_ip_str, panicd_port);
4452a7af 1495
0c530ab8
A
1496 destination_mac = router_mac;
1497
1498 if (kdp_arp_resolve(panic_server_ip, &temp_mac)) {
1499 printf("Resolved %s's (or proxy's) link level address\n", panicd_ip_str);
1500 destination_mac = temp_mac;
55e303ae 1501 }
0c530ab8
A
1502 else {
1503 if (!flag_panic_dump_in_progress) goto panic_dump_exit;
1504 if (router_specified) {
1505 if (0 == inet_aton(router_ip_str, (struct in_addr *) &parsed_router_ip))
1506 printf("inet_aton() failed interpreting %s as an IP\n", router_ip_str);
1507 else {
1508 router_ip = parsed_router_ip;
1509 if (kdp_arp_resolve(router_ip, &temp_mac)) {
1510 destination_mac = temp_mac;
1511 printf("Routing through specified router IP %s (%d)\n", router_ip_str, router_ip);
1512 }
1513 }
1514 }
55e303ae 1515 }
91447636 1516
0c530ab8 1517 if (!flag_panic_dump_in_progress) goto panic_dump_exit;
5d5c5d0d 1518
0c530ab8
A
1519 printf("Transmitting packets to link level address: %02x:%02x:%02x:%02x:%02x:%02x\n",
1520 destination_mac.ether_addr_octet[0] & 0xff,
1521 destination_mac.ether_addr_octet[1] & 0xff,
1522 destination_mac.ether_addr_octet[2] & 0xff,
1523 destination_mac.ether_addr_octet[3] & 0xff,
1524 destination_mac.ether_addr_octet[4] & 0xff,
1525 destination_mac.ether_addr_octet[5] & 0xff);
89b3af67 1526
0c530ab8
A
1527 printf("Kernel map size is %llu\n", (unsigned long long) get_vmmap_size(kernel_map));
1528 printf("Sending write request for %s\n", corename);
4452a7af 1529
0c530ab8
A
1530 if ((panic_error = kdp_send_crashdump_pkt(KDP_WRQ, corename, 0 , NULL)) < 0) {
1531 printf ("kdp_send_crashdump_pkt failed with error %d\n", panic_error);
1532 goto panic_dump_exit;
1533 }
1534
1535 /* Just the panic log requested */
1536 if ((panicstr != (char *) 0) && (kdp_flag & PANIC_LOG_DUMP)) {
1537 printf("Transmitting panic log, please wait: ");
1538 kdp_send_crashdump_data(KDP_DATA, corename, (debug_buf_ptr - debug_buf), debug_buf);
1539 kdp_send_crashdump_pkt (KDP_EOF, NULL, 0, ((void *) 0));
1540 printf("Please file a bug report on this panic, if possible.\n");
1541 goto panic_dump_exit;
1542 }
55e303ae 1543
0c530ab8
A
1544 /* We want a core dump if we're here */
1545 kern_dump();
55e303ae 1546panic_dump_exit:
0c530ab8
A
1547 abort_panic_transfer();
1548 pkt.input = FALSE;
1549 pkt.len = 0;
1550 kdp_reset();
1551 return;
55e303ae
A
1552}
1553
1554void
0c530ab8 1555abort_panic_transfer(void)
55e303ae 1556{
0c530ab8
A
1557 flag_panic_dump_in_progress = FALSE;
1558 not_in_kdp = 1;
1559 panic_block = 0;
55e303ae 1560}