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