]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kdp/kdp_udp.c
xnu-517.7.7.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 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
e5568f75
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
1c79356b 11 *
e5568f75
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
e5568f75
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
9bccf70c
A
23 * Copyright (c) 1982, 1986, 1993
24 * The Regents of the University of California. All rights reserved.
25 */
26
27/*
28 * Kernel Debugging Protocol UDP implementation.
1c79356b
A
29 */
30
31#include <mach_kdb.h>
32#include <mach/boolean.h>
de355530 33#include <mach/mach_types.h>
55e303ae 34#include <mach/exception_types.h>
9bccf70c 35#include <kern/cpu_data.h>
1c79356b
A
36#include <kern/debug.h>
37
38#include <kdp/kdp_internal.h>
39#include <kdp/kdp_en_debugger.h>
40#include <kdp/kdp_udp.h>
41
55e303ae
A
42#include <kdp/kdp_core.h>
43
44#include <vm/vm_map.h>
45#include <mach/memory_object_types.h>
46
47#include <string.h>
48
1c79356b
A
49#define DO_ALIGN 1 /* align all packet data accesses */
50
51extern int kdp_getc(void);
9bccf70c 52extern int reattach_wait;
1c79356b 53
9bccf70c 54static u_short ip_id; /* ip packet ctr, for ids */
1c79356b
A
55
56/* @(#)udp_usrreq.c 2.2 88/05/23 4.0NFSSRC SMI; from UCB 7.1 6/5/86 */
57
58/*
59 * UDP protocol implementation.
60 * Per RFC 768, August, 1980.
61 */
62#define UDP_TTL 60 /* deflt time to live for UDP packets */
55e303ae 63int udp_ttl = UDP_TTL;
1c79356b
A
64static unsigned char exception_seq;
65
66static struct {
67 unsigned char data[KDP_MAXPACKET];
68 unsigned int off, len;
69 boolean_t input;
70} pkt, saved_reply;
71
72struct {
73 struct {
74 struct in_addr in;
75 struct ether_addr ea;
76 } loc;
77 struct {
78 struct in_addr in;
79 struct ether_addr ea;
80 } rmt;
81} adr;
82
83static char
84*exception_message[] = {
85 "Unknown",
86 "Memory access", /* EXC_BAD_ACCESS */
87 "Failed instruction", /* EXC_BAD_INSTRUCTION */
88 "Arithmetic", /* EXC_ARITHMETIC */
89 "Emulation", /* EXC_EMULATION */
90 "Software", /* EXC_SOFTWARE */
91 "Breakpoint" /* EXC_BREAKPOINT */
92};
93
9bccf70c
A
94int kdp_flag = 0;
95
1c79356b
A
96static kdp_send_t kdp_en_send_pkt = 0;
97static kdp_receive_t kdp_en_recv_pkt = 0;
98
9bccf70c 99
55e303ae 100static u_long kdp_current_ip_address = 0;
9bccf70c 101static struct ether_addr kdp_current_mac_address = {{0, 0, 0, 0, 0, 0}};
4a249263 102static void *kdp_current_ifp = 0;
9bccf70c 103
55e303ae
A
104static void kdp_handler( void *);
105
106static unsigned int panic_server_ip = 0;
107static unsigned int parsed_router_ip = 0;
108static unsigned int router_ip = 0;
109static unsigned int panicd_specified = 0;
110static unsigned int router_specified = 0;
111
112static struct ether_addr router_mac = {{0, 0, 0 , 0, 0, 0}};
113
114static u_char flag_panic_dump_in_progress = 0;
115static u_char flag_router_mac_initialized = 0;
116
117static unsigned int panic_timeout = 100000;
118static unsigned int last_panic_port = CORE_REMOTE_PORT;
119
120unsigned int SEGSIZE = 512;
121
122static unsigned int PANIC_PKTSIZE = 518;
123static char panicd_ip_str[20];
124static char router_ip_str[20];
125
126static unsigned int panic_block = 0;
127static volatile unsigned int kdp_trigger_core_dump = 0;
128
129extern unsigned int not_in_kdp;
1c79356b
A
130
131void
9bccf70c 132kdp_register_send_receive(
55e303ae 133 kdp_send_t send,
9bccf70c 134 kdp_receive_t receive)
1c79356b 135{
9bccf70c 136 unsigned int debug;
1c79356b
A
137
138 kdp_en_send_pkt = send;
139 kdp_en_recv_pkt = receive;
55e303ae 140
9bccf70c 141 debug_log_init();
55e303ae 142
9bccf70c 143 PE_parse_boot_arg("debug", &debug);
55e303ae 144
9bccf70c
A
145 if (debug & DB_KDP_BP_DIS)
146 kdp_flag |= KDP_BP_DIS;
55e303ae
A
147 if (debug & DB_KDP_GETC_ENA)
148 kdp_flag |= KDP_GETC_ENA;
149 if (debug & DB_ARP)
150 kdp_flag |= KDP_ARP;
151
152 if (debug & DB_KERN_DUMP_ON_PANIC)
153 kdp_flag |= KDP_PANIC_DUMP_ENABLED;
154 if (debug & DB_KERN_DUMP_ON_NMI)
155 kdp_flag |= PANIC_CORE_ON_NMI;
156
157 if (debug & DB_DBG_POST_CORE)
158 kdp_flag |= DBG_POST_CORE;
159
160 if (debug & DB_PANICLOG_DUMP)
161 kdp_flag |= PANIC_LOG_DUMP;
162
163 if (PE_parse_boot_arg ("_panicd_ip", panicd_ip_str))
164 panicd_specified = 1;
165 /* For the future, currently non-functional */
166 if (PE_parse_boot_arg ("_router_ip", router_ip_str))
167 router_specified = 1;
9bccf70c 168
1c79356b
A
169 kdp_flag |= KDP_READY;
170 if (current_debugger == NO_CUR_DB)
171 current_debugger = KDP_CUR_DB;
172 if (halt_in_debugger) {
173 kdp_call();
174 halt_in_debugger=0;
175 }
176}
177
1c79356b 178void
9bccf70c
A
179kdp_unregister_send_receive(
180 kdp_send_t send,
181 kdp_receive_t receive)
182{
183 if (current_debugger == KDP_CUR_DB)
184 current_debugger = NO_CUR_DB;
185 kdp_flag &= ~KDP_READY;
186 kdp_en_send_pkt = NULL;
187 kdp_en_recv_pkt = NULL;
188}
189
190static void
1c79356b 191enaddr_copy(
9bccf70c
A
192 void *src,
193 void *dst
1c79356b
A
194)
195{
9bccf70c 196 bcopy((char *)src, (char *)dst, sizeof (struct ether_addr));
1c79356b
A
197}
198
9bccf70c 199static unsigned short
1c79356b 200ip_sum(
9bccf70c
A
201 unsigned char *c,
202 unsigned int hlen
1c79356b
A
203)
204{
205 unsigned int high, low, sum;
206
207 high = low = 0;
208 while (hlen-- > 0) {
209 low += c[1] + c[3];
210 high += c[0] + c[2];
211
212 c += sizeof (int);
213 }
214
215 sum = (high << 8) + low;
216 sum = (sum >> 16) + (sum & 65535);
217
218 return (sum > 65535 ? sum - 65535 : sum);
219}
220
9bccf70c 221static void
1c79356b 222kdp_reply(
9bccf70c 223 unsigned short reply_port
1c79356b
A
224)
225{
226 struct udpiphdr aligned_ui, *ui = &aligned_ui;
227 struct ip aligned_ip, *ip = &aligned_ip;
228 struct in_addr tmp_ipaddr;
229 struct ether_addr tmp_enaddr;
230 struct ether_header *eh;
231
232 if (!pkt.input)
233 kdp_panic("kdp_reply");
234
235 pkt.off -= sizeof (struct udpiphdr);
236
237#if DO_ALIGN
238 bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui));
239#else
240 ui = (struct udpiphdr *)&pkt.data[pkt.off];
241#endif
242 ui->ui_next = ui->ui_prev = 0;
243 ui->ui_x1 = 0;
244 ui->ui_pr = IPPROTO_UDP;
245 ui->ui_len = htons((u_short)pkt.len + sizeof (struct udphdr));
246 tmp_ipaddr = ui->ui_src;
247 ui->ui_src = ui->ui_dst;
248 ui->ui_dst = tmp_ipaddr;
249 ui->ui_sport = htons(KDP_REMOTE_PORT);
250 ui->ui_dport = reply_port;
251 ui->ui_ulen = ui->ui_len;
252 ui->ui_sum = 0;
253#if DO_ALIGN
254 bcopy((char *)ui, (char *)&pkt.data[pkt.off], sizeof(*ui));
1c79356b
A
255 bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip));
256#else
257 ip = (struct ip *)&pkt.data[pkt.off];
258#endif
259 ip->ip_len = htons(sizeof (struct udpiphdr) + pkt.len);
260 ip->ip_v = IPVERSION;
261 ip->ip_id = htons(ip_id++);
262 ip->ip_hl = sizeof (struct ip) >> 2;
263 ip->ip_ttl = udp_ttl;
264 ip->ip_sum = 0;
265 ip->ip_sum = htons(~ip_sum((unsigned char *)ip, ip->ip_hl));
266#if DO_ALIGN
267 bcopy((char *)ip, (char *)&pkt.data[pkt.off], sizeof(*ip));
268#endif
269
270 pkt.len += sizeof (struct udpiphdr);
271
272 pkt.off -= sizeof (struct ether_header);
273
274 eh = (struct ether_header *)&pkt.data[pkt.off];
275 enaddr_copy(eh->ether_shost, &tmp_enaddr);
276 enaddr_copy(eh->ether_dhost, eh->ether_shost);
277 enaddr_copy(&tmp_enaddr, eh->ether_dhost);
278 eh->ether_type = htons(ETHERTYPE_IP);
279
280 pkt.len += sizeof (struct ether_header);
281
282 // save reply for possible retransmission
283 bcopy((char *)&pkt, (char *)&saved_reply, sizeof(pkt));
284
285 (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len);
286
287 // increment expected sequence number
288 exception_seq++;
289}
290
9bccf70c 291static void
1c79356b
A
292kdp_send(
293 unsigned short remote_port
294)
295{
296 struct udpiphdr aligned_ui, *ui = &aligned_ui;
297 struct ip aligned_ip, *ip = &aligned_ip;
298 struct ether_header *eh;
299
300 if (pkt.input)
301 kdp_panic("kdp_send");
302
303 pkt.off -= sizeof (struct udpiphdr);
304
305#if DO_ALIGN
306 bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui));
307#else
308 ui = (struct udpiphdr *)&pkt.data[pkt.off];
309#endif
310 ui->ui_next = ui->ui_prev = 0;
311 ui->ui_x1 = 0;
312 ui->ui_pr = IPPROTO_UDP;
313 ui->ui_len = htons((u_short)pkt.len + sizeof (struct udphdr));
314 ui->ui_src = adr.loc.in;
315 ui->ui_dst = adr.rmt.in;
316 ui->ui_sport = htons(KDP_REMOTE_PORT);
317 ui->ui_dport = remote_port;
318 ui->ui_ulen = ui->ui_len;
319 ui->ui_sum = 0;
320#if DO_ALIGN
321 bcopy((char *)ui, (char *)&pkt.data[pkt.off], sizeof(*ui));
322 bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip));
323#else
324 ip = (struct ip *)&pkt.data[pkt.off];
325#endif
326 ip->ip_len = htons(sizeof (struct udpiphdr) + pkt.len);
327 ip->ip_v = IPVERSION;
328 ip->ip_id = htons(ip_id++);
329 ip->ip_hl = sizeof (struct ip) >> 2;
330 ip->ip_ttl = udp_ttl;
331 ip->ip_sum = 0;
332 ip->ip_sum = htons(~ip_sum((unsigned char *)ip, ip->ip_hl));
333#if DO_ALIGN
334 bcopy((char *)ip, (char *)&pkt.data[pkt.off], sizeof(*ip));
335#endif
336
337 pkt.len += sizeof (struct udpiphdr);
338
339 pkt.off -= sizeof (struct ether_header);
340
341 eh = (struct ether_header *)&pkt.data[pkt.off];
342 enaddr_copy(&adr.loc.ea, eh->ether_shost);
343 enaddr_copy(&adr.rmt.ea, eh->ether_dhost);
344 eh->ether_type = htons(ETHERTYPE_IP);
345
346 pkt.len += sizeof (struct ether_header);
1c79356b
A
347 (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len);
348}
349
4a249263
A
350/* We don't interpret this pointer, we just give it to the
351bsd stack so it can decide when to set the MAC and IP info. */
352void
353kdp_set_interface(void *ifp)
354{
355 kdp_current_ifp = ifp;
356}
357
358void *
359kdp_get_interface()
360{
361 return kdp_current_ifp;
362}
9bccf70c
A
363
364void
365kdp_set_ip_and_mac_addresses(
366 struct in_addr *ipaddr,
367 struct ether_addr *macaddr)
1c79356b 368{
9bccf70c
A
369 unsigned int debug = 0;
370
371 kdp_current_ip_address = ipaddr->s_addr;
372 kdp_current_mac_address = *macaddr;
9bccf70c
A
373}
374
55e303ae
A
375void
376kdp_set_gateway_mac(void *gatewaymac)
377{
378 router_mac = *(struct ether_addr *)gatewaymac;
379}
380
9bccf70c
A
381struct ether_addr
382kdp_get_mac_addr(void)
383{
384 return kdp_current_mac_address;
385}
386
387unsigned int
388kdp_get_ip_address(void)
389{
390 return kdp_current_ip_address;
391}
392
393/* ARP responses are enabled when the DB_ARP bit of the debug boot arg
394 is set. A workaround if you don't want to reboot is to set
395 kdpDEBUGFlag &= DB_ARP when connected (but that certainly isn't a published
396 interface!)
397*/
9bccf70c
A
398static void
399kdp_arp_reply(void)
400{
401 struct ether_header *eh;
55e303ae 402 struct ether_arp aligned_ea, *ea = &aligned_ea;
9bccf70c
A
403
404 struct in_addr isaddr, itaddr, myaddr;
55e303ae 405 struct ether_addr my_enaddr;
9bccf70c
A
406
407 eh = (struct ether_header *)&pkt.data[pkt.off];
408 pkt.off += sizeof(struct ether_header);
409
55e303ae 410 memcpy((void *)ea, (void *)&pkt.data[pkt.off],sizeof(*ea));
9bccf70c 411
55e303ae
A
412 if(ntohs(ea->arp_op) != ARPOP_REQUEST)
413 return;
9bccf70c
A
414
415 myaddr.s_addr = kdp_get_ip_address();
416 my_enaddr = kdp_get_mac_addr();
417
418 if (!(myaddr.s_addr) || !(my_enaddr.ether_addr_octet[1]))
419 return;
420
421 (void)memcpy((void *)&isaddr, (void *)ea->arp_spa, sizeof (isaddr));
422 (void)memcpy((void *)&itaddr, (void *)ea->arp_tpa, sizeof (itaddr));
423
424 if (itaddr.s_addr == myaddr.s_addr) {
425 (void)memcpy((void *)ea->arp_tha, (void *)ea->arp_sha, sizeof(ea->arp_sha));
426 (void)memcpy((void *)ea->arp_sha, (void *)&my_enaddr, sizeof(ea->arp_sha));
427
428 (void)memcpy((void *)ea->arp_tpa, (void *) ea->arp_spa, sizeof(ea->arp_spa));
429 (void)memcpy((void *)ea->arp_spa, (void *) &itaddr, sizeof(ea->arp_spa));
430
431 ea->arp_op = htons(ARPOP_REPLY);
432 ea->arp_pro = htons(ETHERTYPE_IP);
433 (void)memcpy(eh->ether_dhost, ea->arp_tha, sizeof(eh->ether_dhost));
434 (void)memcpy(eh->ether_shost, &my_enaddr, sizeof(eh->ether_shost));
435 eh->ether_type = htons(ETHERTYPE_ARP);
436 (void)memcpy(&pkt.data[pkt.off], ea, sizeof(*ea));
437 pkt.off -= sizeof (struct ether_header);
438 /* pkt.len is still the length we want, ether_header+ether_arp */
439 (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len);
440 }
441}
442
443static void
444kdp_poll(void)
445{
446 struct ether_header *eh;
55e303ae
A
447 struct udpiphdr aligned_ui, *ui = &aligned_ui;
448 struct ip aligned_ip, *ip = &aligned_ip;
449 static int msg_printed;
9bccf70c 450
1c79356b
A
451
452 if (pkt.input)
453 kdp_panic("kdp_poll");
454
455 if (!kdp_en_recv_pkt || !kdp_en_send_pkt) {
456 if( msg_printed == 0) {
457 msg_printed = 1;
458 printf("kdp_poll: no debugger device\n");
459 }
460 return;
461 }
462
9bccf70c 463 pkt.off = pkt.len = 0;
1c79356b 464 (*kdp_en_recv_pkt)(pkt.data, &pkt.len, 3/* ms */);
9bccf70c 465
1c79356b
A
466 if (pkt.len == 0)
467 return;
9bccf70c
A
468
469 if (pkt.len >= sizeof(struct ether_header))
470 {
471 eh = (struct ether_header *)&pkt.data[pkt.off];
472
473 if (kdp_flag & KDP_ARP)
474 {
475 if (ntohs(eh->ether_type) == ETHERTYPE_ARP)
476 {
477 kdp_arp_reply();
478 return;
479 }
480 }
481 }
482
1c79356b
A
483 if (pkt.len < (sizeof (struct ether_header) + sizeof (struct udpiphdr)))
484 return;
9bccf70c 485
1c79356b
A
486 pkt.off += sizeof (struct ether_header);
487 if (ntohs(eh->ether_type) != ETHERTYPE_IP) {
488 return;
489 }
490
491#if DO_ALIGN
492 bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui));
493 bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip));
494#else
495 ui = (struct udpiphdr *)&pkt.data[pkt.off];
496 ip = (struct ip *)&pkt.data[pkt.off];
497#endif
498
499 pkt.off += sizeof (struct udpiphdr);
500 if (ui->ui_pr != IPPROTO_UDP) {
501 return;
502 }
503
504 if (ip->ip_hl > (sizeof (struct ip) >> 2)) {
505 return;
506 }
507
508 if (ntohs(ui->ui_dport) != KDP_REMOTE_PORT) {
55e303ae
A
509 if (CORE_REMOTE_PORT == (ntohs(ui->ui_dport)) &&
510 flag_panic_dump_in_progress) {
511 last_panic_port = ui->ui_sport;
512 }
513 else
1c79356b
A
514 return;
515 }
55e303ae
A
516 /* If we receive a kernel debugging packet whilst a
517 * core dump is in progress, abort the transfer and
518 * enter the debugger.
519 */
520 else
521 if (flag_panic_dump_in_progress)
522 {
523 abort_panic_transfer();
524 return;
525 }
526
527 if (!kdp.is_conn && !flag_panic_dump_in_progress) {
1c79356b
A
528 enaddr_copy(eh->ether_dhost, &adr.loc.ea);
529 adr.loc.in = ui->ui_dst;
530
531 enaddr_copy(eh->ether_shost, &adr.rmt.ea);
532 adr.rmt.in = ui->ui_src;
533 }
534
535 /*
536 * Calculate kdp packet length.
537 */
538 pkt.len = ntohs((u_short)ui->ui_ulen) - sizeof (struct udphdr);
539 pkt.input = TRUE;
1c79356b
A
540}
541
9bccf70c 542static void
1c79356b 543kdp_handler(
9bccf70c 544 void *saved_state
1c79356b
A
545)
546{
547 unsigned short reply_port;
548 kdp_hdr_t aligned_hdr, *hdr = &aligned_hdr;
549
550
551 kdp.saved_state = saved_state; // see comment in kdp_raise_exception
552
553 do {
554 while (!pkt.input)
555 kdp_poll();
556
557#if DO_ALIGN
558 bcopy((char *)&pkt.data[pkt.off], (char *)hdr, sizeof(*hdr));
559#else
560 hdr = (kdp_hdr_t *)&pkt.data[pkt.off];
561#endif
562
563 // ignore replies -- we're not expecting them anyway.
564 if (hdr->is_reply) {
565 goto again;
566 }
567
9bccf70c
A
568 if (hdr->request == KDP_REATTACH)
569 exception_seq = hdr->seq;
570
1c79356b
A
571 // check for retransmitted request
572 if (hdr->seq == (exception_seq - 1)) {
573 /* retransmit last reply */
574 (*kdp_en_send_pkt)(&saved_reply.data[saved_reply.off],
575 saved_reply.len);
576 goto again;
577 } else if (hdr->seq != exception_seq) {
578 printf("kdp: bad sequence %d (want %d)\n",
579 hdr->seq, exception_seq);
580 goto again;
581 }
582
583 if (kdp_packet((unsigned char*)&pkt.data[pkt.off],
584 (int *)&pkt.len,
585 (unsigned short *)&reply_port)) {
586 kdp_reply(reply_port);
587 }
588
589again:
590 pkt.input = FALSE;
591 } while (kdp.is_halted);
592}
593
9bccf70c
A
594static void
595kdp_connection_wait(void)
1c79356b 596{
55e303ae
A
597 unsigned short reply_port;
598 boolean_t kdp_call_kdb();
599 struct ether_addr kdp_mac_addr = kdp_get_mac_addr();
600 unsigned int ip_addr = ntohl(kdp_get_ip_address());
9bccf70c
A
601
602 printf( "ethernet MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
603 kdp_mac_addr.ether_addr_octet[0] & 0xff,
604 kdp_mac_addr.ether_addr_octet[1] & 0xff,
605 kdp_mac_addr.ether_addr_octet[2] & 0xff,
606 kdp_mac_addr.ether_addr_octet[3] & 0xff,
607 kdp_mac_addr.ether_addr_octet[4] & 0xff,
608 kdp_mac_addr.ether_addr_octet[5] & 0xff);
609
610 printf( "ip address: %d.%d.%d.%d\n",
611 (ip_addr & 0xff000000) >> 24,
612 (ip_addr & 0xff0000) >> 16,
613 (ip_addr & 0xff00) >> 8,
614 (ip_addr & 0xff));
615
55e303ae
A
616 printf("\nWaiting for remote debugger connection.\n");
617
618 if (reattach_wait == 0) {
619 if((kdp_flag & KDP_GETC_ENA) && (0 != kdp_getc()))
620 {
621 printf("Options..... Type\n");
622 printf("------------ ----\n");
623 printf("continue.... 'c'\n");
624 printf("reboot...... 'r'\n");
1c79356b 625#if MACH_KDB
55e303ae 626 printf("enter kdb... 'k'\n");
1c79356b 627#endif
55e303ae
A
628 }
629 } else
630 reattach_wait = 0;
9bccf70c 631
55e303ae
A
632 exception_seq = 0;
633
634 do {
635 kdp_hdr_t aligned_hdr, *hdr = &aligned_hdr;
1c79356b 636
55e303ae
A
637 while (!pkt.input) {
638 if (kdp_flag & KDP_GETC_ENA) {
639 switch(kdp_getc()) {
640 case 'c':
641 printf("Continuing...\n");
642 return;
643 case 'r':
644 printf("Rebooting...\n");
645 kdp_reboot();
646 break;
1c79356b 647#if MACH_KDB
55e303ae
A
648 case 'k':
649 printf("calling kdb...\n");
650 if (kdp_call_kdb())
651 return;
652 else
653 printf("not implemented...\n");
1c79356b 654#endif
55e303ae
A
655 default:
656 break;
657 }
658 }
659 kdp_poll();
660 }
1c79356b 661
1c79356b 662#if DO_ALIGN
55e303ae 663 bcopy((char *)&pkt.data[pkt.off], (char *)hdr, sizeof(*hdr));
1c79356b 664#else
55e303ae 665 hdr = (kdp_hdr_t *)&pkt.data[pkt.off];
1c79356b 666#endif
55e303ae
A
667 if (hdr->request == KDP_HOSTREBOOT) {
668 kdp_reboot();
669 /* should not return! */
670 }
671 if (((hdr->request == KDP_CONNECT) || (hdr->request == KDP_REATTACH)) &&
672 !hdr->is_reply && (hdr->seq == exception_seq)) {
673 if (kdp_packet((unsigned char *)&pkt.data[pkt.off],
674 (int *)&pkt.len,
675 (unsigned short *)&reply_port))
676 kdp_reply(reply_port);
677 if (hdr->request == KDP_REATTACH) {
678 reattach_wait = 0;
679 hdr->request=KDP_DISCONNECT;
680 exception_seq = 0;
681 }
682 }
683
684 pkt.input = FALSE;
685 } while (!kdp.is_conn);
1c79356b 686
55e303ae
A
687 if (current_debugger == KDP_CUR_DB)
688 active_debugger=1;
689 printf("Connected to remote debugger.\n");
1c79356b
A
690}
691
9bccf70c 692static void
1c79356b
A
693kdp_send_exception(
694 unsigned int exception,
695 unsigned int code,
696 unsigned int subcode
697)
698{
699 unsigned short remote_port;
9bccf70c
A
700 unsigned int timeout_count = 100;
701 unsigned int poll_timeout;
1c79356b 702
1c79356b
A
703 do {
704 pkt.off = sizeof (struct ether_header) + sizeof (struct udpiphdr);
705 kdp_exception((unsigned char *)&pkt.data[pkt.off],
706 (int *)&pkt.len,
707 (unsigned short *)&remote_port,
708 (unsigned int)exception,
709 (unsigned int)code,
710 (unsigned int)subcode);
9bccf70c 711
1c79356b
A
712 kdp_send(remote_port);
713
9bccf70c
A
714 poll_timeout = 50;
715 while(!pkt.input && poll_timeout)
716 {
717 kdp_poll();
718 poll_timeout--;
719 }
720
1c79356b
A
721 if (pkt.input) {
722 if (!kdp_exception_ack(&pkt.data[pkt.off], pkt.len)) {
723 pkt.input = FALSE;
1c79356b 724 }
1c79356b 725 }
9bccf70c 726
1c79356b 727 pkt.input = FALSE;
9bccf70c 728
1c79356b 729 if (kdp.exception_ack_needed)
9bccf70c 730 kdp_us_spin(250000);
1c79356b
A
731
732 } while (kdp.exception_ack_needed && timeout_count--);
733
734 if (kdp.exception_ack_needed) {
735 // give up & disconnect
736 printf("kdp: exception ack timeout\n");
9bccf70c
A
737 if (current_debugger == KDP_CUR_DB)
738 active_debugger=0;
1c79356b
A
739 kdp_reset();
740 }
741}
742
743void
744kdp_raise_exception(
745 unsigned int exception,
746 unsigned int code,
747 unsigned int subcode,
748 void *saved_state
749)
750{
1c79356b
A
751 int index;
752
55e303ae
A
753 extern unsigned int disableDebugOuput;
754 extern unsigned int disableConsoleOutput;
755
9bccf70c
A
756 disable_preemption();
757
1c79356b
A
758 if (saved_state == 0)
759 printf("kdp_raise_exception with NULL state\n");
760
761 index = exception;
762 if (exception != EXC_BREAKPOINT) {
763 if (exception > EXC_BREAKPOINT || exception < EXC_BAD_ACCESS) {
764 index = 0;
765 }
766 printf("%s exception (%x,%x,%x)\n",
767 exception_message[index],
768 exception, code, subcode);
769 }
770
771 kdp_sync_cache();
772
773 /* XXX WMG it seems that sometimes it doesn't work to let kdp_handler
774 * do this. I think the client and the host can get out of sync.
775 */
776 kdp.saved_state = saved_state;
55e303ae 777
1c79356b
A
778 if (pkt.input)
779 kdp_panic("kdp_raise_exception");
55e303ae
A
780
781 if (((kdp_flag & KDP_PANIC_DUMP_ENABLED) || (kdp_flag & PANIC_LOG_DUMP))
782 && (panicstr != (char *) 0)) {
783
784 kdp_panic_dump();
785
786 }
787 else
788 if ((kdp_flag & PANIC_CORE_ON_NMI) && (panicstr == (char *) 0) &&
789 !kdp.is_conn) {
790
791 disableDebugOuput = disableConsoleOutput = FALSE;
792 kdp_panic_dump();
793
794 if (!(kdp_flag & DBG_POST_CORE))
795 goto exit_raise_exception;
796 }
797
9bccf70c 798 again:
1c79356b
A
799 if (!kdp.is_conn)
800 kdp_connection_wait();
55e303ae 801 else {
1c79356b 802 kdp_send_exception(exception, code, subcode);
55e303ae 803 if (kdp.exception_ack_needed) {
9bccf70c
A
804 kdp.exception_ack_needed = FALSE;
805 kdp_remove_all_breakpoints();
806 printf("Remote debugger disconnected.\n");
807 }
808 }
1c79356b
A
809
810 if (kdp.is_conn) {
811 kdp.is_halted = TRUE; /* XXX */
812 kdp_handler(saved_state);
813 if (!kdp.is_conn)
9bccf70c
A
814 {
815 kdp_remove_all_breakpoints();
1c79356b 816 printf("Remote debugger disconnected.\n");
9bccf70c 817 }
1c79356b 818 }
55e303ae
A
819 /* Allow triggering a panic core dump when connected to the machine
820 * Continuing after setting kdp_trigger_core_dump should do the
821 * trick.
822 */
823 if (1 == kdp_trigger_core_dump) {
824 kdp_flag &= ~PANIC_LOG_DUMP;
825 kdp_flag |= KDP_PANIC_DUMP_ENABLED;
826 kdp_panic_dump();
827 }
1c79356b
A
828
829 kdp_sync_cache();
9bccf70c
A
830
831 if (reattach_wait == 1)
832 goto again;
55e303ae 833 exit_raise_exception:
9bccf70c 834 enable_preemption();
1c79356b
A
835}
836
837void
838kdp_reset(void)
839{
9bccf70c
A
840 kdp.reply_port = kdp.exception_port = 0;
841 kdp.is_halted = kdp.is_conn = FALSE;
842 kdp.exception_seq = kdp.conn_seq = 0;
1c79356b
A
843}
844
55e303ae
A
845struct corehdr *
846create_panic_header(unsigned int request, const char *corename,
847 unsigned length, unsigned int block)
848{
849 struct udpiphdr aligned_ui, *ui = &aligned_ui;
850 struct ip aligned_ip, *ip = &aligned_ip;
851 struct ether_header *eh;
852 struct corehdr *coreh;
853 const char *mode = "octet";
854 char modelen = strlen(mode);
855
856 pkt.off = sizeof (struct ether_header);
857 pkt.len = length + ((request == KDP_WRQ) ? modelen : 0) +
858 (corename ? strlen(corename): 0) + sizeof(struct corehdr);
859
860#if DO_ALIGN
861 bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui));
862#else
863 ui = (struct udpiphdr *)&pkt.data[pkt.off];
864#endif
865 ui->ui_next = ui->ui_prev = 0;
866 ui->ui_x1 = 0;
867 ui->ui_pr = IPPROTO_UDP;
868 ui->ui_len = htons((u_short)pkt.len + sizeof (struct udphdr));
869 ui->ui_src.s_addr = htonl(kdp_current_ip_address);
870 ui->ui_dst.s_addr = panic_server_ip;
871 ui->ui_sport = htons(CORE_REMOTE_PORT);
872 ui->ui_dport = ((request == KDP_WRQ) ? htons(CORE_REMOTE_PORT) : last_panic_port);
873 ui->ui_ulen = ui->ui_len;
874 ui->ui_sum = 0;
875#if DO_ALIGN
876 bcopy((char *)ui, (char *)&pkt.data[pkt.off], sizeof(*ui));
877 bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip));
878#else
879 ip = (struct ip *)&pkt.data[pkt.off];
880#endif
881 ip->ip_len = htons(sizeof (struct udpiphdr) + pkt.len);
882 ip->ip_v = IPVERSION;
883 ip->ip_id = htons(ip_id++);
884 ip->ip_hl = sizeof (struct ip) >> 2;
885 ip->ip_ttl = udp_ttl;
886 ip->ip_sum = 0;
887 ip->ip_sum = htons(~ip_sum((unsigned char *)ip, ip->ip_hl));
888#if DO_ALIGN
889 bcopy((char *)ip, (char *)&pkt.data[pkt.off], sizeof(*ip));
890#endif
891
892 pkt.len += sizeof (struct udpiphdr);
893
894 pkt.off += sizeof (struct udpiphdr);
895
896 coreh = (struct corehdr *) &pkt.data[pkt.off];
897 coreh->th_opcode = htons((u_short)request);
898
899 if (request == KDP_WRQ)
900 {
901 register char *cp;
902
903 cp = coreh->th_u.tu_rpl;
904 strcpy (cp, corename);
905 cp += strlen(corename);
906 *cp++ = '\0';
907 strcpy (cp, mode);
908 cp+= modelen;
909 *cp++ = '\0';
910 }
911 else
912 {
913 coreh->th_block = htonl((unsigned int) block);
914 }
915
916 pkt.off -= sizeof (struct udpiphdr);
917 pkt.off -= sizeof (struct ether_header);
918
919 eh = (struct ether_header *)&pkt.data[pkt.off];
920 enaddr_copy(&kdp_current_mac_address, eh->ether_shost);
921 enaddr_copy(&router_mac, eh->ether_dhost);
922 eh->ether_type = htons(ETHERTYPE_IP);
923
924 pkt.len += sizeof (struct ether_header);
925 return coreh;
926}
927
928int kdp_send_panic_packets (unsigned int request, char *corename,
929 unsigned int length, unsigned int txstart)
930{
931 unsigned int txend = txstart + length;
932 int panic_error = 0;
933
934 if (length <= SEGSIZE) {
935 if ((panic_error = kdp_send_panic_pkt (request, corename, length, (caddr_t) txstart)) < 0) {
936 printf ("kdp_send_panic_pkt failed with error %d\n", panic_error);
937 return panic_error ;
938 }
939 }
940 else
941 {
942 while (txstart <= (txend - SEGSIZE)) {
943 if ((panic_error = kdp_send_panic_pkt (KDP_DATA, NULL, SEGSIZE, (caddr_t) txstart)) < 0) {
944 printf ("kdp_send_panic_pkt failed with error %d\n", panic_error);
945 return panic_error;
946 }
947 txstart += SEGSIZE;
948 if (!(panic_block % 2000))
949 printf(".");
950 }
951 if (txstart < txend) {
952 kdp_send_panic_pkt(request, corename, (txend - txstart), (caddr_t) txstart);
953 }
954 }
955}
956
957int
958kdp_send_panic_pkt (unsigned int request, char *corename,
959 unsigned int length, void *panic_data)
960{
961 struct corehdr *th = NULL;
962 int poll_count = 2500;
963
964 char rretries = 0, tretries = 0;
965 /*
966 extern signed long gIODebuggerSemaphore;
967 */
968 pkt.off = pkt.len = 0;
969
970 if (request == KDP_WRQ) /* longer timeout for initial request */
971 poll_count += 1000;
972
973TRANSMIT_RETRY:
974 tretries++;
975
976 if (tretries > 2)
977 printf("TX retry #%d ", tretries );
978
979 if (tretries >=15) {
980 /* This iokit layer issue can potentially
981 *cause a hang, uncomment to check if it's happening.
982 */
983 /*
984 if (gIODebuggerSemaphore)
985 printf("The gIODebuggerSemaphore is raised, preventing packet transmission (2760413)\n");
986 */
987
988 printf ("Cannot contact panic server, timing out.\n");
989 return (-3);
990 }
991
992 th = create_panic_header(request, corename, length, panic_block);
993
994 if (request == KDP_DATA || request == KDP_SEEK) {
995 if (!kdp_vm_read ((caddr_t) panic_data, (caddr_t) th->th_data, length)) {
996 memset ((caddr_t) th->th_data, 'X', length);
997 }
998 }
999
1000 (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len);
1001
1002 /* Now we have to listen for the ACK */
1003 RECEIVE_RETRY:
1004
1005 while (!pkt.input && flag_panic_dump_in_progress && poll_count) {
1006 kdp_poll();
1007 poll_count--;
1008 }
1009
1010 if (pkt.input) {
1011
1012 pkt.input = FALSE;
1013
1014 th = (struct corehdr *) &pkt.data[pkt.off];
1015 /* These will eventually have to be ntoh[ls]'ed as appropriate */
1016
1017 if (th->th_opcode == KDP_ACK && th->th_block == panic_block) {
1018 }
1019 else
1020 if (th->th_opcode == KDP_ERROR) {
1021 printf("Panic server returned error %d, retrying\n", th->th_code);
1022 poll_count = 1000;
1023 goto TRANSMIT_RETRY;
1024 }
1025 else
1026 if (th->th_block == (panic_block -1)) {
1027 printf("RX retry ");
1028 if (++rretries > 1)
1029 goto TRANSMIT_RETRY;
1030 else
1031 goto RECEIVE_RETRY;
1032 }
1033 }
1034 else
1035 if (!flag_panic_dump_in_progress) /* we received a debugging packet, bail*/
1036 {
1037 printf("Received a debugger packet,transferring control to debugger\n");
1038 /* Configure that if not set ..*/
1039 kdp_flag |= DBG_POST_CORE;
1040 return (-2);
1041 }
1042 else /* We timed out */
1043 if (0 == poll_count) {
1044 poll_count = 1000;
1045 kdp_us_spin ((tretries%4) * panic_timeout); /* capped linear backoff */
1046 goto TRANSMIT_RETRY;
1047 }
1048
1049 panic_block++;
1050
1051 if (request == KDP_EOF)
1052 printf ("\nTotal number of packets transmitted: %d\n", panic_block);
1053
1054 return 1;
1055}
1056
1057/* Since we don't seem to have an isdigit() .. */
1058static int
1059isdigit (char c)
1060{
1061 return ((c > 47) && (c < 58));
1062}
1063/* From user mode Libc - this ought to be in a library */
1064static char *
1065strnstr(s, find, slen)
1066 const char *s;
1067 const char *find;
1068 size_t slen;
1069{
1070 char c, sc;
1071 size_t len;
1072
1073 if ((c = *find++) != '\0') {
1074 len = strlen(find);
1075 do {
1076 do {
1077 if ((sc = *s++) == '\0' || slen-- < 1)
1078 return (NULL);
1079 } while (sc != c);
1080 if (len > slen)
1081 return (NULL);
1082 } while (strncmp(s, find, len) != 0);
1083 s--;
1084 }
1085 return ((char *)s);
1086}
1087
1088/* Horrid hack to extract xnu version if possible - a much cleaner approach
1089 * would be to have the integrator run a script which would copy the
1090 * xnu version into a string or an int somewhere at project submission
1091 * time - makes assumptions about sizeof(version), but will not fail if
1092 * it changes, but may be incorrect.
1093 */
1094
1095static int
1096kdp_get_xnu_version(char *versionbuf)
1097{
1098 extern const char version[];
1099 char *versionpos;
1100 char vstr[10];
1101 int retval = -1;
1102
1103 strcpy(vstr, "custom");
1104 if (version) {
1105 if (kdp_vm_read(version, versionbuf, 90)) {
1106
1107 versionbuf[89] = '\0';
1108
1109 versionpos = strnstr(versionbuf, "xnu-", 80);
1110
1111 if (versionpos) {
1112 strncpy (vstr, versionpos, (isdigit (versionpos[7]) ? 8 : 7));
1113 vstr[(isdigit (versionpos[7]) ? 8 : 7)] = '\0';
1114 retval = 0;
1115 }
1116 }
1117 }
1118 strcpy(versionbuf, vstr);
1119 return retval;
1120}
1121/* Primary dispatch routine for the system dump */
1122void
1123kdp_panic_dump()
1124{
1125 char corename[50];
1126 char coreprefix[10];
1127 int panic_error;
1128 extern char *debug_buf;
1129 extern vm_map_t kernel_map;
1130
1131 extern char *inet_aton(const char *cp, struct in_addr *pin);
1132
1133 extern char *debug_buf;
1134 extern char *debug_buf_ptr;
1135 uint64_t abstime;
1136
1137 printf ("Entering system dump routine\n");
1138
1139 if (!panicd_specified) {
1140 printf ("A panic server was not specified in the boot-args, terminating kernel core dump.\n");
1141 goto panic_dump_exit;
1142 }
1143
1144 flag_panic_dump_in_progress = 1;
1145 not_in_kdp = 0;
1146
1147 if (pkt.input)
1148 kdp_panic("kdp_panic_dump");
1149
1150 kdp_get_xnu_version((char *) &pkt.data[0]);
1151
1152 /* Panic log bit takes precedence over core dump bit */
1153 if ((panicstr != (char *) 0) && (kdp_flag & PANIC_LOG_DUMP))
1154 strncpy(coreprefix, "paniclog", sizeof(coreprefix));
1155 else
1156 strncpy(coreprefix, "core", sizeof(coreprefix));
1157
1158 abstime = mach_absolute_time();
1159 pkt.data[10] = '\0';
1160 snprintf (corename, sizeof(corename), "%s-%s-%d.%d.%d.%d-%x",
1161 coreprefix, &pkt.data[0],
1162 (kdp_current_ip_address & 0xff000000) >> 24,
1163 (kdp_current_ip_address & 0xff0000) >> 16,
1164 (kdp_current_ip_address & 0xff00) >> 8,
1165 (kdp_current_ip_address & 0xff),
1166 (unsigned int) (abstime & 0xffffffff));
1167
1168 if (0 == inet_aton(panicd_ip_str, (struct in_addr *) &panic_server_ip)) {
1169 printf("inet_aton() failed interpreting %s as a panic server IP\n",
1170 panicd_ip_str);
1171 }
1172 else
1173 printf("Attempting connection to panic server configured at IP %s\n",
1174 panicd_ip_str);
1175
1176 if (router_specified) {
1177 if (0 == inet_aton(router_ip_str, (struct in_addr *) &parsed_router_ip)){
1178 printf("inet_aton() failed interpreting %s as an IP\n", router_ip);
1179 }
1180 else {
1181 router_ip = parsed_router_ip;
1182 printf("Routing through specified router IP %s (%d)\n", router_ip_str, router_ip);
1183 /* We will eventually need to resolve the router's MAC ourselves,
1184 * if one is specified,rather than being set through the BSD callback
1185 * but the _router_ip option does not function currently
1186 */
1187 }
1188 }
1189 /* These & 0xffs aren't necessary,but cut&paste is ever so convenient */
1190 printf("Routing via router MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
1191 router_mac.ether_addr_octet[0] & 0xff,
1192 router_mac.ether_addr_octet[1] & 0xff,
1193 router_mac.ether_addr_octet[2] & 0xff,
1194 router_mac.ether_addr_octet[3] & 0xff,
1195 router_mac.ether_addr_octet[4] & 0xff,
1196 router_mac.ether_addr_octet[5] & 0xff);
1197
1198 printf("Kernel map size is %d\n", get_vmmap_size(kernel_map));
1199 printf ("Sending write request for %s\n", corename);
1200
1201 if ((panic_error = kdp_send_panic_pkt (KDP_WRQ, corename, 0 , NULL) < 0)) {
1202 printf ("kdp_send_panic_pkt failed with error %d\n", panic_error);
1203 goto panic_dump_exit;
1204 }
1205
1206 /* Just the panic log requested */
1207 if ((panicstr != (char *) 0) && (kdp_flag & PANIC_LOG_DUMP)) {
1208 printf("Transmitting panic log, please wait: ");
1209 kdp_send_panic_packets (KDP_DATA, corename, (debug_buf_ptr - debug_buf), (unsigned int) debug_buf);
1210 kdp_send_panic_pkt (KDP_EOF, NULL, 0, ((void *) 0));
1211 printf("Please file a bug report on this panic, if possible.\n");
1212 goto panic_dump_exit;
1213 }
1214
1215 /* We want a core dump if we're here */
1216 kern_dump();
1217panic_dump_exit:
1218 not_in_kdp = 1;
1219 flag_panic_dump_in_progress = 0;
1220 panic_block = 0;
1221 pkt.input = FALSE;
1222 pkt.len = 0;
1223 kdp_reset();
1224 return;
1225}
1226
1227void
1228abort_panic_transfer()
1229{
1230 flag_panic_dump_in_progress = 0;
1231 not_in_kdp = 1;
1232 panic_block = 0;
1233}