X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/4a2492630c73add3c3aa8a805ba4ff343d4a58ea..0c530ab8987f0ae6a1a3d9284f40182b88852816:/osfmk/kdp/kdp_udp.c?ds=sidebyside diff --git a/osfmk/kdp/kdp_udp.c b/osfmk/kdp/kdp_udp.c index 885adfca7..df1ec3f67 100644 --- a/osfmk/kdp/kdp_udp.c +++ b/osfmk/kdp/kdp_udp.c @@ -3,22 +3,19 @@ * * @APPLE_LICENSE_HEADER_START@ * - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. * * @APPLE_LICENSE_HEADER_END@ */ @@ -38,13 +35,15 @@ #include #include +#include #include #include #include -#include - #include +#include +#include /* kernel_map */ + #include #include @@ -83,7 +82,7 @@ struct { } rmt; } adr; -static char +static const char *exception_message[] = { "Unknown", "Memory access", /* EXC_BAD_ACCESS */ @@ -94,7 +93,7 @@ static char "Breakpoint" /* EXC_BREAKPOINT */ }; -int kdp_flag = 0; +volatile int kdp_flag = 0; static kdp_send_t kdp_en_send_pkt = 0; static kdp_receive_t kdp_en_recv_pkt = 0; @@ -106,37 +105,96 @@ static void *kdp_current_ifp = 0; static void kdp_handler( void *); -static unsigned int panic_server_ip = 0; -static unsigned int parsed_router_ip = 0; -static unsigned int router_ip = 0; -static unsigned int panicd_specified = 0; -static unsigned int router_specified = 0; +static uint32_t panic_server_ip = 0; +static uint32_t parsed_router_ip = 0; +static uint32_t router_ip = 0; +static uint32_t target_ip = 0; + +static volatile boolean_t panicd_specified = FALSE; +static boolean_t router_specified = FALSE; +static unsigned int panicd_port = CORE_REMOTE_PORT; + +/* As in bsd/net/ether_if_module.c */ +static struct ether_addr etherbroadcastaddr = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; static struct ether_addr router_mac = {{0, 0, 0 , 0, 0, 0}}; +static struct ether_addr destination_mac = {{0, 0, 0 , 0, 0, 0}}; +static struct ether_addr temp_mac = {{0, 0, 0 , 0, 0, 0}}; +static struct ether_addr current_resolved_MAC = {{0, 0, 0 , 0, 0, 0}}; -static u_char flag_panic_dump_in_progress = 0; -static u_char flag_router_mac_initialized = 0; +static boolean_t flag_panic_dump_in_progress = FALSE; +static boolean_t flag_router_mac_initialized = FALSE; + +static boolean_t flag_arp_resolved = FALSE; static unsigned int panic_timeout = 100000; static unsigned int last_panic_port = CORE_REMOTE_PORT; unsigned int SEGSIZE = 512; -static unsigned int PANIC_PKTSIZE = 518; +__unused static unsigned int PANIC_PKTSIZE = 518; static char panicd_ip_str[20]; static char router_ip_str[20]; static unsigned int panic_block = 0; static volatile unsigned int kdp_trigger_core_dump = 0; +static volatile unsigned int flag_kdp_trigger_reboot = 0; extern unsigned int not_in_kdp; +extern unsigned long panic_caller; +extern unsigned int disableConsoleOutput; + +extern int kdp_vm_read( caddr_t, caddr_t, unsigned int); +extern void kdp_call(void); +extern boolean_t kdp_call_kdb(void); +extern int kern_dump(void); + +void * kdp_get_interface(void); +void kdp_set_gateway_mac(void *); +void kdp_set_ip_and_mac_addresses(struct in_addr *, struct ether_addr *); +void kdp_set_interface(void *); + +void kdp_disable_arp(void); +static void kdp_arp_reply(struct ether_arp *); +static void kdp_process_arp_reply(struct ether_arp *); +static boolean_t kdp_arp_resolve(uint32_t, struct ether_addr *); + +static boolean_t gKDPDebug = FALSE; +#define KDP_DEBUG(...) if (gKDPDebug) printf(__VA_ARGS__); + +int kdp_snapshot = 0; +static int stack_snapshot_ret = 0; +static unsigned stack_snapshot_bytes_traced = 0; + +static void *stack_snapshot_buf; +static uint32_t stack_snapshot_bufsize; +static int stack_snapshot_pid; +static uint32_t stack_snapshot_options; + +void +kdp_snapshot_preflight(int pid, void * tracebuf, uint32_t tracebuf_size, + uint32_t options); + +void +kdp_snapshot_postflight(void); + +extern int +kdp_stackshot(int pid, uint32_t tracebuf, uint32_t tracebuf_size, + unsigned trace_options, uint32_t *pbytesTraced); + +int +kdp_stack_snapshot_geterror(void); + +int +kdp_stack_snapshot_bytes_traced(void); + void kdp_register_send_receive( kdp_send_t send, kdp_receive_t receive) { - unsigned int debug; + unsigned int debug=0; kdp_en_send_pkt = send; kdp_en_recv_pkt = receive; @@ -164,10 +222,13 @@ kdp_register_send_receive( kdp_flag |= PANIC_LOG_DUMP; if (PE_parse_boot_arg ("_panicd_ip", panicd_ip_str)) - panicd_specified = 1; - /* For the future, currently non-functional */ + panicd_specified = TRUE; + if (PE_parse_boot_arg ("_router_ip", router_ip_str)) - router_specified = 1; + router_specified = TRUE; + + if (!PE_parse_boot_arg ("panicd_port", &panicd_port)) + panicd_port = CORE_REMOTE_PORT; kdp_flag |= KDP_READY; if (current_debugger == NO_CUR_DB) @@ -180,8 +241,8 @@ kdp_register_send_receive( void kdp_unregister_send_receive( - kdp_send_t send, - kdp_receive_t receive) + __unused kdp_send_t send, + __unused kdp_receive_t receive) { if (current_debugger == KDP_CUR_DB) current_debugger = NO_CUR_DB; @@ -190,6 +251,35 @@ kdp_unregister_send_receive( kdp_en_recv_pkt = NULL; } +/* Cache stack snapshot parameters in preparation for a trace */ +void +kdp_snapshot_preflight(int pid, void * tracebuf, uint32_t tracebuf_size, uint32_t options) +{ + stack_snapshot_pid = pid; + stack_snapshot_buf = tracebuf; + stack_snapshot_bufsize = tracebuf_size; + stack_snapshot_options = options; + kdp_snapshot++; +} + +void +kdp_snapshot_postflight(void) +{ + kdp_snapshot--; +} + +int +kdp_stack_snapshot_geterror(void) +{ + return stack_snapshot_ret; +} + +int +kdp_stack_snapshot_bytes_traced(void) +{ + return stack_snapshot_bytes_traced; +} + static void enaddr_copy( void *src, @@ -203,92 +293,92 @@ static unsigned short ip_sum( unsigned char *c, unsigned int hlen -) + ) { - unsigned int high, low, sum; + unsigned int high, low, sum; - high = low = 0; - while (hlen-- > 0) { - low += c[1] + c[3]; - high += c[0] + c[2]; + high = low = 0; + while (hlen-- > 0) { + low += c[1] + c[3]; + high += c[0] + c[2]; - c += sizeof (int); - } + c += sizeof (int); + } - sum = (high << 8) + low; - sum = (sum >> 16) + (sum & 65535); + sum = (high << 8) + low; + sum = (sum >> 16) + (sum & 65535); - return (sum > 65535 ? sum - 65535 : sum); + return (sum > 65535 ? sum - 65535 : sum); } static void kdp_reply( unsigned short reply_port -) + ) { - struct udpiphdr aligned_ui, *ui = &aligned_ui; - struct ip aligned_ip, *ip = &aligned_ip; - struct in_addr tmp_ipaddr; - struct ether_addr tmp_enaddr; - struct ether_header *eh; + struct udpiphdr aligned_ui, *ui = &aligned_ui; + struct ip aligned_ip, *ip = &aligned_ip; + struct in_addr tmp_ipaddr; + struct ether_addr tmp_enaddr; + struct ether_header *eh = NULL; - if (!pkt.input) - kdp_panic("kdp_reply"); + if (!pkt.input) + kdp_panic("kdp_reply"); - pkt.off -= sizeof (struct udpiphdr); + pkt.off -= sizeof (struct udpiphdr); #if DO_ALIGN - bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui)); + bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui)); #else - ui = (struct udpiphdr *)&pkt.data[pkt.off]; + ui = (struct udpiphdr *)&pkt.data[pkt.off]; #endif - ui->ui_next = ui->ui_prev = 0; - ui->ui_x1 = 0; - ui->ui_pr = IPPROTO_UDP; - ui->ui_len = htons((u_short)pkt.len + sizeof (struct udphdr)); - tmp_ipaddr = ui->ui_src; - ui->ui_src = ui->ui_dst; - ui->ui_dst = tmp_ipaddr; - ui->ui_sport = htons(KDP_REMOTE_PORT); - ui->ui_dport = reply_port; - ui->ui_ulen = ui->ui_len; - ui->ui_sum = 0; + ui->ui_next = ui->ui_prev = 0; + ui->ui_x1 = 0; + ui->ui_pr = IPPROTO_UDP; + ui->ui_len = htons((u_short)pkt.len + sizeof (struct udphdr)); + tmp_ipaddr = ui->ui_src; + ui->ui_src = ui->ui_dst; + ui->ui_dst = tmp_ipaddr; + ui->ui_sport = htons(KDP_REMOTE_PORT); + ui->ui_dport = reply_port; + ui->ui_ulen = ui->ui_len; + ui->ui_sum = 0; #if DO_ALIGN - bcopy((char *)ui, (char *)&pkt.data[pkt.off], sizeof(*ui)); - bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip)); + bcopy((char *)ui, (char *)&pkt.data[pkt.off], sizeof(*ui)); + bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip)); #else - ip = (struct ip *)&pkt.data[pkt.off]; + ip = (struct ip *)&pkt.data[pkt.off]; #endif - ip->ip_len = htons(sizeof (struct udpiphdr) + pkt.len); - ip->ip_v = IPVERSION; - ip->ip_id = htons(ip_id++); - ip->ip_hl = sizeof (struct ip) >> 2; - ip->ip_ttl = udp_ttl; - ip->ip_sum = 0; - ip->ip_sum = htons(~ip_sum((unsigned char *)ip, ip->ip_hl)); + ip->ip_len = htons(sizeof (struct udpiphdr) + pkt.len); + ip->ip_v = IPVERSION; + ip->ip_id = htons(ip_id++); + ip->ip_hl = sizeof (struct ip) >> 2; + ip->ip_ttl = udp_ttl; + ip->ip_sum = 0; + ip->ip_sum = htons(~ip_sum((unsigned char *)ip, ip->ip_hl)); #if DO_ALIGN - bcopy((char *)ip, (char *)&pkt.data[pkt.off], sizeof(*ip)); + bcopy((char *)ip, (char *)&pkt.data[pkt.off], sizeof(*ip)); #endif - pkt.len += sizeof (struct udpiphdr); + pkt.len += sizeof (struct udpiphdr); - pkt.off -= sizeof (struct ether_header); + pkt.off -= sizeof (struct ether_header); - eh = (struct ether_header *)&pkt.data[pkt.off]; - enaddr_copy(eh->ether_shost, &tmp_enaddr); - enaddr_copy(eh->ether_dhost, eh->ether_shost); - enaddr_copy(&tmp_enaddr, eh->ether_dhost); - eh->ether_type = htons(ETHERTYPE_IP); + eh = (struct ether_header *)&pkt.data[pkt.off]; + enaddr_copy(eh->ether_shost, &tmp_enaddr); + enaddr_copy(eh->ether_dhost, eh->ether_shost); + enaddr_copy(&tmp_enaddr, eh->ether_dhost); + eh->ether_type = htons(ETHERTYPE_IP); - pkt.len += sizeof (struct ether_header); + pkt.len += sizeof (struct ether_header); - // save reply for possible retransmission - bcopy((char *)&pkt, (char *)&saved_reply, sizeof(pkt)); + // save reply for possible retransmission + bcopy((char *)&pkt, (char *)&saved_reply, sizeof(pkt)); - (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len); + (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len); - // increment expected sequence number - exception_seq++; + // increment expected sequence number + exception_seq++; } static void @@ -369,8 +459,6 @@ kdp_set_ip_and_mac_addresses( struct in_addr *ipaddr, struct ether_addr *macaddr) { - unsigned int debug = 0; - kdp_current_ip_address = ipaddr->s_addr; kdp_current_mac_address = *macaddr; } @@ -379,6 +467,7 @@ void kdp_set_gateway_mac(void *gatewaymac) { router_mac = *(struct ether_addr *)gatewaymac; + flag_router_mac_initialized = TRUE; } struct ether_addr @@ -393,16 +482,58 @@ kdp_get_ip_address(void) return kdp_current_ip_address; } +void +kdp_disable_arp(void) +{ + kdp_flag &= ~(DB_ARP); +} + +static void +kdp_arp_dispatch(void) +{ + struct ether_arp aligned_ea, *ea = &aligned_ea; + unsigned arp_header_offset; + + arp_header_offset = sizeof(struct ether_header) + pkt.off; + memcpy((void *)ea, (void *)&pkt.data[arp_header_offset], sizeof(*ea)); + + switch(ntohs(ea->arp_op)) { + case ARPOP_REQUEST: + kdp_arp_reply(ea); + break; + case ARPOP_REPLY: + kdp_process_arp_reply(ea); + break; + default: + return; + } +} + +static void +kdp_process_arp_reply(struct ether_arp *ea) +{ + /* Are we interested in ARP replies? */ + if (flag_arp_resolved == TRUE) + return; + + /* Did we receive a reply from the right source? */ + if (((struct in_addr *)(ea->arp_spa))->s_addr != target_ip) + return; + + flag_arp_resolved = TRUE; + current_resolved_MAC = *(struct ether_addr *) (ea->arp_sha); + + return; +} + /* ARP responses are enabled when the DB_ARP bit of the debug boot arg - is set. A workaround if you don't want to reboot is to set - kdpDEBUGFlag &= DB_ARP when connected (but that certainly isn't a published - interface!) -*/ + * is set. + */ + static void -kdp_arp_reply(void) +kdp_arp_reply(struct ether_arp *ea) { struct ether_header *eh; - struct ether_arp aligned_ea, *ea = &aligned_ea; struct in_addr isaddr, itaddr, myaddr; struct ether_addr my_enaddr; @@ -410,20 +541,25 @@ kdp_arp_reply(void) eh = (struct ether_header *)&pkt.data[pkt.off]; pkt.off += sizeof(struct ether_header); - memcpy((void *)ea, (void *)&pkt.data[pkt.off],sizeof(*ea)); - if(ntohs(ea->arp_op) != ARPOP_REQUEST) return; myaddr.s_addr = kdp_get_ip_address(); my_enaddr = kdp_get_mac_addr(); - if (!(myaddr.s_addr) || !(my_enaddr.ether_addr_octet[1])) + if ((ntohl(myaddr.s_addr) == 0) || + ((my_enaddr.ether_addr_octet[0] & 0xff) == 0 + && (my_enaddr.ether_addr_octet[1] & 0xff) == 0 + && (my_enaddr.ether_addr_octet[2] & 0xff) == 0 + && (my_enaddr.ether_addr_octet[3] & 0xff) == 0 + && (my_enaddr.ether_addr_octet[4] & 0xff) == 0 + && (my_enaddr.ether_addr_octet[5] & 0xff) == 0 + )) return; (void)memcpy((void *)&isaddr, (void *)ea->arp_spa, sizeof (isaddr)); (void)memcpy((void *)&itaddr, (void *)ea->arp_tpa, sizeof (itaddr)); - + if (itaddr.s_addr == myaddr.s_addr) { (void)memcpy((void *)ea->arp_tha, (void *)ea->arp_sha, sizeof(ea->arp_sha)); (void)memcpy((void *)ea->arp_sha, (void *)&my_enaddr, sizeof(ea->arp_sha)); @@ -446,100 +582,185 @@ kdp_arp_reply(void) static void kdp_poll(void) { - struct ether_header *eh; - struct udpiphdr aligned_ui, *ui = &aligned_ui; - struct ip aligned_ip, *ip = &aligned_ip; - static int msg_printed; - + struct ether_header *eh = NULL; + struct udpiphdr aligned_ui, *ui = &aligned_ui; + struct ip aligned_ip, *ip = &aligned_ip; + static int msg_printed; - if (pkt.input) - kdp_panic("kdp_poll"); + if (pkt.input) + kdp_panic("kdp_poll"); - if (!kdp_en_recv_pkt || !kdp_en_send_pkt) { - if( msg_printed == 0) { - msg_printed = 1; - printf("kdp_poll: no debugger device\n"); + if (!kdp_en_recv_pkt || !kdp_en_send_pkt) { + if( msg_printed == 0) { + msg_printed = 1; + printf("kdp_poll: no debugger device\n"); + } + return; } - return; - } - pkt.off = pkt.len = 0; - (*kdp_en_recv_pkt)(pkt.data, &pkt.len, 3/* ms */); - - if (pkt.len == 0) - return; + pkt.off = pkt.len = 0; + (*kdp_en_recv_pkt)(pkt.data, &pkt.len, 3/* ms */); - if (pkt.len >= sizeof(struct ether_header)) - { - eh = (struct ether_header *)&pkt.data[pkt.off]; - - if (kdp_flag & KDP_ARP) - { - if (ntohs(eh->ether_type) == ETHERTYPE_ARP) - { - kdp_arp_reply(); + if (pkt.len == 0) return; - } - } - } - if (pkt.len < (sizeof (struct ether_header) + sizeof (struct udpiphdr))) - return; + if (pkt.len >= sizeof(struct ether_header)) + { + eh = (struct ether_header *)&pkt.data[pkt.off]; + + if (kdp_flag & KDP_ARP) + { + if (ntohs(eh->ether_type) == ETHERTYPE_ARP) + { + kdp_arp_dispatch(); + return; + } + } + } - pkt.off += sizeof (struct ether_header); - if (ntohs(eh->ether_type) != ETHERTYPE_IP) { - return; - } + if (pkt.len < (sizeof (struct ether_header) + sizeof (struct udpiphdr))) + return; + + pkt.off += sizeof (struct ether_header); + if (ntohs(eh->ether_type) != ETHERTYPE_IP) { + return; + } #if DO_ALIGN - bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui)); - bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip)); + bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui)); + bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip)); #else - ui = (struct udpiphdr *)&pkt.data[pkt.off]; - ip = (struct ip *)&pkt.data[pkt.off]; + ui = (struct udpiphdr *)&pkt.data[pkt.off]; + ip = (struct ip *)&pkt.data[pkt.off]; #endif - pkt.off += sizeof (struct udpiphdr); - if (ui->ui_pr != IPPROTO_UDP) { - return; - } + pkt.off += sizeof (struct udpiphdr); + if (ui->ui_pr != IPPROTO_UDP) { + return; + } - if (ip->ip_hl > (sizeof (struct ip) >> 2)) { - return; - } + if (ip->ip_hl > (sizeof (struct ip) >> 2)) { + return; + } - if (ntohs(ui->ui_dport) != KDP_REMOTE_PORT) { - if (CORE_REMOTE_PORT == (ntohs(ui->ui_dport)) && - flag_panic_dump_in_progress) { - last_panic_port = ui->ui_sport; + if (ntohs(ui->ui_dport) != KDP_REMOTE_PORT) { + if (panicd_port == (ntohs(ui->ui_dport)) && + flag_panic_dump_in_progress) { + last_panic_port = ui->ui_sport; + } + else + return; } - else - return; - } - /* If we receive a kernel debugging packet whilst a - * core dump is in progress, abort the transfer and - * enter the debugger. - */ - else - if (flag_panic_dump_in_progress) - { - abort_panic_transfer(); - return; + /* If we receive a kernel debugging packet whilst a + * core dump is in progress, abort the transfer and + * enter the debugger. + */ + else + if (flag_panic_dump_in_progress) + { + abort_panic_transfer(); + return; + } + + if (!kdp.is_conn && !flag_panic_dump_in_progress) { + enaddr_copy(eh->ether_dhost, &adr.loc.ea); + adr.loc.in = ui->ui_dst; + + enaddr_copy(eh->ether_shost, &adr.rmt.ea); + adr.rmt.in = ui->ui_src; } - if (!kdp.is_conn && !flag_panic_dump_in_progress) { - enaddr_copy(eh->ether_dhost, &adr.loc.ea); - adr.loc.in = ui->ui_dst; + /* + * Calculate kdp packet length. + */ + pkt.len = ntohs((u_short)ui->ui_ulen) - sizeof (struct udphdr); + pkt.input = TRUE; +} - enaddr_copy(eh->ether_shost, &adr.rmt.ea); - adr.rmt.in = ui->ui_src; - } +/* Create and transmit an ARP resolution request for the target IP address. + * This is modeled on ether_inet_arp()/RFC 826. + */ - /* - * Calculate kdp packet length. - */ - pkt.len = ntohs((u_short)ui->ui_ulen) - sizeof (struct udphdr); - pkt.input = TRUE; +static void +transmit_ARP_request(uint32_t ip_addr) +{ + struct ether_header *eh = (struct ether_header *) &pkt.data[0]; + struct ether_arp *ea = (struct ether_arp *) &pkt.data[sizeof(struct ether_header)]; + + KDP_DEBUG("Transmitting ARP request\n"); + /* Populate the ether_header */ + eh->ether_type = htons(ETHERTYPE_ARP); + enaddr_copy(&kdp_current_mac_address, eh->ether_shost); + enaddr_copy(ðerbroadcastaddr, eh->ether_dhost); + + /* Populate the ARP header */ + ea->arp_pro = htons(ETHERTYPE_IP); + ea->arp_hln = sizeof(ea->arp_sha); + ea->arp_pln = sizeof(ea->arp_spa); + ea->arp_hrd = htons(ARPHRD_ETHER); + ea->arp_op = htons(ARPOP_REQUEST); + + /* Target fields */ + enaddr_copy(ðerbroadcastaddr, ea->arp_tha); + memcpy(ea->arp_tpa, (void *) &ip_addr, sizeof(ip_addr)); + + /* Source fields */ + enaddr_copy(&kdp_current_mac_address, ea->arp_sha); + memcpy(ea->arp_spa, (void *) &kdp_current_ip_address, sizeof(kdp_current_ip_address)); + + pkt.off = 0; + pkt.len = sizeof(struct ether_header) + sizeof(struct ether_arp); + /* Transmit */ + (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len); +} + +static boolean_t +kdp_arp_resolve(uint32_t arp_target_ip, struct ether_addr *resolved_MAC) +{ + int poll_count = 256; /* ~770 ms modulo broadcast/delayed traffic? */ + char tretries = 0; + +#define NUM_ARP_TX_RETRIES 5 + + target_ip = arp_target_ip; + flag_arp_resolved = FALSE; + +TRANSMIT_RETRY: + pkt.off = pkt.len = 0; + + tretries++; + + if (tretries >= NUM_ARP_TX_RETRIES) { + return FALSE; + } + + KDP_DEBUG("ARP TX attempt #%d \n", tretries); + + transmit_ARP_request(arp_target_ip); + + while (!pkt.input && !flag_arp_resolved && flag_panic_dump_in_progress && --poll_count) { + kdp_poll(); + } + + if (flag_arp_resolved) { + *resolved_MAC = current_resolved_MAC; + return TRUE; + } + + if (!flag_panic_dump_in_progress || pkt.input) /* we received a debugging packet, bail*/ + { + printf("Received a debugger packet,transferring control to debugger\n"); + /* Indicate that we should wait in the debugger when we return */ + kdp_flag |= DBG_POST_CORE; + pkt.input = FALSE; + return FALSE; + } + else /* We timed out */ + if (0 == poll_count) { + poll_count = 256; + goto TRANSMIT_RETRY; + } + return FALSE; } static void @@ -550,7 +771,6 @@ kdp_handler( unsigned short reply_port; kdp_hdr_t aligned_hdr, *hdr = &aligned_hdr; - kdp.saved_state = saved_state; // see comment in kdp_raise_exception do { @@ -598,10 +818,15 @@ static void kdp_connection_wait(void) { unsigned short reply_port; - boolean_t kdp_call_kdb(); struct ether_addr kdp_mac_addr = kdp_get_mac_addr(); unsigned int ip_addr = ntohl(kdp_get_ip_address()); + /* + * Do both a printf() and a kprintf() of the MAC and IP so that + * they will print out on headless machines but not be added to + * the panic.log + */ + printf( "ethernet MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", kdp_mac_addr.ether_addr_octet[0] & 0xff, kdp_mac_addr.ether_addr_octet[1] & 0xff, @@ -610,12 +835,26 @@ kdp_connection_wait(void) kdp_mac_addr.ether_addr_octet[4] & 0xff, kdp_mac_addr.ether_addr_octet[5] & 0xff); + kprintf( "ethernet MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", + kdp_mac_addr.ether_addr_octet[0] & 0xff, + kdp_mac_addr.ether_addr_octet[1] & 0xff, + kdp_mac_addr.ether_addr_octet[2] & 0xff, + kdp_mac_addr.ether_addr_octet[3] & 0xff, + kdp_mac_addr.ether_addr_octet[4] & 0xff, + kdp_mac_addr.ether_addr_octet[5] & 0xff); + printf( "ip address: %d.%d.%d.%d\n", (ip_addr & 0xff000000) >> 24, (ip_addr & 0xff0000) >> 16, (ip_addr & 0xff00) >> 8, (ip_addr & 0xff)); + kprintf( "ip address: %d.%d.%d.%d\n", + (ip_addr & 0xff000000) >> 24, + (ip_addr & 0xff0000) >> 16, + (ip_addr & 0xff00) >> 8, + (ip_addr & 0xff)); + printf("\nWaiting for remote debugger connection.\n"); if (reattach_wait == 0) { @@ -753,9 +992,6 @@ kdp_raise_exception( { int index; - extern unsigned int disableDebugOuput; - extern unsigned int disableConsoleOutput; - disable_preemption(); if (saved_state == 0) @@ -781,11 +1017,19 @@ kdp_raise_exception( if (pkt.input) kdp_panic("kdp_raise_exception"); + /* Was a system trace requested ? */ + if (kdp_snapshot && (panicstr == ((char *) 0)) && (panic_caller == 0) && !kdp.is_conn) { + /* XXX This should be reworked to take a pointer to the buffer */ + stack_snapshot_ret = kdp_stackshot(stack_snapshot_pid, + (uint32_t) stack_snapshot_buf, stack_snapshot_bufsize, + stack_snapshot_options, &stack_snapshot_bytes_traced); + goto exit_raise_exception; + } + if (((kdp_flag & KDP_PANIC_DUMP_ENABLED) || (kdp_flag & PANIC_LOG_DUMP)) && (panicstr != (char *) 0)) { - kdp_panic_dump(); - + kdp_panic_dump(); } else if ((kdp_flag & PANIC_CORE_ON_NMI) && (panicstr == (char *) 0) && @@ -823,17 +1067,30 @@ kdp_raise_exception( * Continuing after setting kdp_trigger_core_dump should do the * trick. */ + if (1 == kdp_trigger_core_dump) { kdp_flag &= ~PANIC_LOG_DUMP; kdp_flag |= KDP_PANIC_DUMP_ENABLED; kdp_panic_dump(); } +/* Trigger a reboot if the user has set this flag through the + * debugger.Ideally, this would be done through the HOSTREBOOT packet + * in the protocol,but that will need gdb support,and when it's + * available, it should work automatically. + */ + if (1 == flag_kdp_trigger_reboot) { + kdp_reboot(); + /* If we're still around, reset the flag */ + flag_kdp_trigger_reboot = 0; + } + kdp_sync_cache(); if (reattach_wait == 1) goto again; - exit_raise_exception: + +exit_raise_exception: enable_preemption(); } @@ -847,217 +1104,214 @@ kdp_reset(void) struct corehdr * create_panic_header(unsigned int request, const char *corename, - unsigned length, unsigned int block) + unsigned length, unsigned int block) { - struct udpiphdr aligned_ui, *ui = &aligned_ui; - struct ip aligned_ip, *ip = &aligned_ip; - struct ether_header *eh; - struct corehdr *coreh; - const char *mode = "octet"; - char modelen = strlen(mode); + struct udpiphdr aligned_ui, *ui = &aligned_ui; + struct ip aligned_ip, *ip = &aligned_ip; + struct ether_header *eh; + struct corehdr *coreh; + const char *mode = "octet"; + char modelen = strlen(mode); - pkt.off = sizeof (struct ether_header); - pkt.len = length + ((request == KDP_WRQ) ? modelen : 0) + - (corename ? strlen(corename): 0) + sizeof(struct corehdr); + pkt.off = sizeof (struct ether_header); + pkt.len = length + ((request == KDP_WRQ) ? modelen : 0) + + (corename ? strlen(corename): 0) + sizeof(struct corehdr); #if DO_ALIGN - bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui)); + bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui)); #else - ui = (struct udpiphdr *)&pkt.data[pkt.off]; + ui = (struct udpiphdr *)&pkt.data[pkt.off]; #endif - ui->ui_next = ui->ui_prev = 0; - ui->ui_x1 = 0; - ui->ui_pr = IPPROTO_UDP; - ui->ui_len = htons((u_short)pkt.len + sizeof (struct udphdr)); - ui->ui_src.s_addr = htonl(kdp_current_ip_address); - ui->ui_dst.s_addr = panic_server_ip; - ui->ui_sport = htons(CORE_REMOTE_PORT); - ui->ui_dport = ((request == KDP_WRQ) ? htons(CORE_REMOTE_PORT) : last_panic_port); - ui->ui_ulen = ui->ui_len; - ui->ui_sum = 0; + ui->ui_next = ui->ui_prev = 0; + ui->ui_x1 = 0; + ui->ui_pr = IPPROTO_UDP; + ui->ui_len = htons((u_short)pkt.len + sizeof (struct udphdr)); + ui->ui_src.s_addr = kdp_current_ip_address; + /* Already in network byte order via inet_aton() */ + ui->ui_dst.s_addr = panic_server_ip; + ui->ui_sport = htons(panicd_port); + ui->ui_dport = ((request == KDP_WRQ) ? htons(panicd_port) : last_panic_port); + ui->ui_ulen = ui->ui_len; + ui->ui_sum = 0; #if DO_ALIGN - bcopy((char *)ui, (char *)&pkt.data[pkt.off], sizeof(*ui)); - bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip)); + bcopy((char *)ui, (char *)&pkt.data[pkt.off], sizeof(*ui)); + bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip)); #else - ip = (struct ip *)&pkt.data[pkt.off]; + ip = (struct ip *)&pkt.data[pkt.off]; #endif - ip->ip_len = htons(sizeof (struct udpiphdr) + pkt.len); - ip->ip_v = IPVERSION; - ip->ip_id = htons(ip_id++); - ip->ip_hl = sizeof (struct ip) >> 2; - ip->ip_ttl = udp_ttl; - ip->ip_sum = 0; - ip->ip_sum = htons(~ip_sum((unsigned char *)ip, ip->ip_hl)); + ip->ip_len = htons(sizeof (struct udpiphdr) + pkt.len); + ip->ip_v = IPVERSION; + ip->ip_id = htons(ip_id++); + ip->ip_hl = sizeof (struct ip) >> 2; + ip->ip_ttl = udp_ttl; + ip->ip_sum = 0; + ip->ip_sum = htons(~ip_sum((unsigned char *)ip, ip->ip_hl)); #if DO_ALIGN - bcopy((char *)ip, (char *)&pkt.data[pkt.off], sizeof(*ip)); + bcopy((char *)ip, (char *)&pkt.data[pkt.off], sizeof(*ip)); #endif - pkt.len += sizeof (struct udpiphdr); + pkt.len += sizeof (struct udpiphdr); - pkt.off += sizeof (struct udpiphdr); + pkt.off += sizeof (struct udpiphdr); - coreh = (struct corehdr *) &pkt.data[pkt.off]; - coreh->th_opcode = htons((u_short)request); + coreh = (struct corehdr *) &pkt.data[pkt.off]; + coreh->th_opcode = htons((u_short)request); - if (request == KDP_WRQ) - { - register char *cp; - - cp = coreh->th_u.tu_rpl; - strcpy (cp, corename); - cp += strlen(corename); - *cp++ = '\0'; - strcpy (cp, mode); - cp+= modelen; - *cp++ = '\0'; - } - else - { - coreh->th_block = htonl((unsigned int) block); - } + if (request == KDP_WRQ) + { + register char *cp; + + cp = coreh->th_u.tu_rpl; + strcpy (cp, corename); + cp += strlen(corename); + *cp++ = '\0'; + strcpy (cp, mode); + cp+= modelen; + *cp++ = '\0'; + } + else + { + coreh->th_block = htonl((unsigned int) block); + } - pkt.off -= sizeof (struct udpiphdr); - pkt.off -= sizeof (struct ether_header); + pkt.off -= sizeof (struct udpiphdr); + pkt.off -= sizeof (struct ether_header); - eh = (struct ether_header *)&pkt.data[pkt.off]; - enaddr_copy(&kdp_current_mac_address, eh->ether_shost); - enaddr_copy(&router_mac, eh->ether_dhost); - eh->ether_type = htons(ETHERTYPE_IP); + eh = (struct ether_header *)&pkt.data[pkt.off]; + enaddr_copy(&kdp_current_mac_address, eh->ether_shost); + enaddr_copy(&destination_mac, eh->ether_dhost); + eh->ether_type = htons(ETHERTYPE_IP); - pkt.len += sizeof (struct ether_header); - return coreh; + pkt.len += sizeof (struct ether_header); + return coreh; } -int kdp_send_panic_packets (unsigned int request, char *corename, - unsigned int length, unsigned int txstart) +int kdp_send_crashdump_data(unsigned int request, char *corename, + unsigned int length, caddr_t txstart) { - unsigned int txend = txstart + length; - int panic_error = 0; + caddr_t txend = txstart + length; + int panic_error = 0; - if (length <= SEGSIZE) { - if ((panic_error = kdp_send_panic_pkt (request, corename, length, (caddr_t) txstart)) < 0) { - printf ("kdp_send_panic_pkt failed with error %d\n", panic_error); - return panic_error ; - } - } - else - { - while (txstart <= (txend - SEGSIZE)) { - if ((panic_error = kdp_send_panic_pkt (KDP_DATA, NULL, SEGSIZE, (caddr_t) txstart)) < 0) { - printf ("kdp_send_panic_pkt failed with error %d\n", panic_error); - return panic_error; + if (length <= SEGSIZE) { + if ((panic_error = kdp_send_crashdump_pkt(request, corename, length, (caddr_t) txstart)) < 0) { + printf ("kdp_send_crashdump_pkt failed with error %d\n", panic_error); + return panic_error ; + } } - txstart += SEGSIZE; - if (!(panic_block % 2000)) - printf("."); - } - if (txstart < txend) { - kdp_send_panic_pkt(request, corename, (txend - txstart), (caddr_t) txstart); - } - } + else + { + while (txstart <= (txend - SEGSIZE)) { + if ((panic_error = kdp_send_crashdump_pkt(KDP_DATA, NULL, SEGSIZE, txstart)) < 0) { + printf ("kdp_send_crashdump_pkt failed with error %d\n", panic_error); + return panic_error; + } + txstart += SEGSIZE; + if (!(panic_block % 2000)) + printf("."); + } + if (txstart < txend) { + kdp_send_crashdump_pkt(request, corename, (txend - txstart), txstart); + } + } + return 0; } -int -kdp_send_panic_pkt (unsigned int request, char *corename, - unsigned int length, void *panic_data) +int +kdp_send_crashdump_pkt(unsigned int request, char *corename, + unsigned int length, void *panic_data) { - struct corehdr *th = NULL; - int poll_count = 2500; + struct corehdr *th = NULL; + int poll_count = 2500; - char rretries = 0, tretries = 0; - /* - extern signed long gIODebuggerSemaphore; - */ - pkt.off = pkt.len = 0; + char rretries = 0, tretries = 0; + + pkt.off = pkt.len = 0; - if (request == KDP_WRQ) /* longer timeout for initial request */ - poll_count += 1000; + if (request == KDP_WRQ) /* longer timeout for initial request */ + poll_count += 1000; TRANSMIT_RETRY: - tretries++; + tretries++; - if (tretries > 2) - printf("TX retry #%d ", tretries ); - - if (tretries >=15) { - /* This iokit layer issue can potentially - *cause a hang, uncomment to check if it's happening. - */ - /* - if (gIODebuggerSemaphore) - printf("The gIODebuggerSemaphore is raised, preventing packet transmission (2760413)\n"); - */ - - printf ("Cannot contact panic server, timing out.\n"); - return (-3); - } - - th = create_panic_header(request, corename, length, panic_block); + if (tretries >=15) { +/* The crashdump server is unreachable for some reason. This could be a network + * issue or, if we've been especially unfortunate, we've hit Radar 2760413, + * which is a long standing problem with the IOKit polled mode network driver + * shim which can prevent transmits/receives completely. + */ + printf ("Cannot contact panic server, timing out.\n"); + return (-3); + } - if (request == KDP_DATA || request == KDP_SEEK) { - if (!kdp_vm_read ((caddr_t) panic_data, (caddr_t) th->th_data, length)) { - memset ((caddr_t) th->th_data, 'X', length); - } - } + if (tretries > 2) + printf("TX retry #%d ", tretries ); + + th = create_panic_header(request, corename, length, panic_block); - (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len); + if (request == KDP_DATA) { + if (!kdp_vm_read((caddr_t) panic_data, (caddr_t) th->th_data, length)) { + memset ((caddr_t) th->th_data, 'X', length); + } + } + else if (request == KDP_SEEK) { + *(unsigned int *) th->th_data = htonl(*(unsigned int *) panic_data); + } - /* Now we have to listen for the ACK */ - RECEIVE_RETRY: + (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len); - while (!pkt.input && flag_panic_dump_in_progress && poll_count) { - kdp_poll(); - poll_count--; - } + /* Listen for the ACK */ +RECEIVE_RETRY: + while (!pkt.input && flag_panic_dump_in_progress && poll_count) { + kdp_poll(); + poll_count--; + } - if (pkt.input) { + if (pkt.input) { - pkt.input = FALSE; + pkt.input = FALSE; - th = (struct corehdr *) &pkt.data[pkt.off]; - /* These will eventually have to be ntoh[ls]'ed as appropriate */ + th = (struct corehdr *) &pkt.data[pkt.off]; - if (th->th_opcode == KDP_ACK && th->th_block == panic_block) { - } - else - if (th->th_opcode == KDP_ERROR) { - printf("Panic server returned error %d, retrying\n", th->th_code); - poll_count = 1000; - goto TRANSMIT_RETRY; - } - else - if (th->th_block == (panic_block -1)) { - printf("RX retry "); - if (++rretries > 1) - goto TRANSMIT_RETRY; - else - goto RECEIVE_RETRY; + if (ntohs(th->th_opcode) == KDP_ACK && ntohl(th->th_block) == panic_block) { + } + else + if (ntohs(th->th_opcode) == KDP_ERROR) { + printf("Panic server returned error %d, retrying\n", ntohl(th->th_code)); + poll_count = 1000; + goto TRANSMIT_RETRY; + } + else + if (ntohl(th->th_block) == (panic_block - 1)) { + printf("RX retry "); + if (++rretries > 1) + goto TRANSMIT_RETRY; + else + goto RECEIVE_RETRY; + } } - } - else - if (!flag_panic_dump_in_progress) /* we received a debugging packet, bail*/ - { - printf("Received a debugger packet,transferring control to debugger\n"); - /* Configure that if not set ..*/ - kdp_flag |= DBG_POST_CORE; - return (-2); - } - else /* We timed out */ - if (0 == poll_count) { - poll_count = 1000; - kdp_us_spin ((tretries%4) * panic_timeout); /* capped linear backoff */ - goto TRANSMIT_RETRY; - } + else + if (!flag_panic_dump_in_progress) /* we received a debugging packet, bail*/ + { + printf("Received a debugger packet,transferring control to debugger\n"); + /* Configure that if not set ..*/ + kdp_flag |= DBG_POST_CORE; + return (-2); + } + else /* We timed out */ + if (0 == poll_count) { + poll_count = 1000; + kdp_us_spin ((tretries%4) * panic_timeout); /* capped linear backoff */ + goto TRANSMIT_RETRY; + } - panic_block++; + panic_block++; - if (request == KDP_EOF) - printf ("\nTotal number of packets transmitted: %d\n", panic_block); + if (request == KDP_EOF) + printf("\nTotal number of packets transmitted: %d\n", panic_block); - return 1; + return 1; } -/* Since we don't seem to have an isdigit() .. */ static int isdigit (char c) { @@ -1065,10 +1319,7 @@ isdigit (char c) } /* From user mode Libc - this ought to be in a library */ static char * -strnstr(s, find, slen) - const char *s; - const char *find; - size_t slen; +strnstr(char *s, const char *find, size_t slen) { char c, sc; size_t len; @@ -1088,149 +1339,167 @@ strnstr(s, find, slen) return ((char *)s); } +extern char version[]; + /* Horrid hack to extract xnu version if possible - a much cleaner approach * would be to have the integrator run a script which would copy the * xnu version into a string or an int somewhere at project submission * time - makes assumptions about sizeof(version), but will not fail if * it changes, but may be incorrect. */ - +/* 2006: Incorporated a change from Darwin user P. Lovell to extract + * the minor kernel version numbers from the version string. + */ static int kdp_get_xnu_version(char *versionbuf) { - extern const char version[]; - char *versionpos; - char vstr[10]; - int retval = -1; - - strcpy(vstr, "custom"); - if (version) { - if (kdp_vm_read(version, versionbuf, 90)) { - - versionbuf[89] = '\0'; - - versionpos = strnstr(versionbuf, "xnu-", 80); - - if (versionpos) { - strncpy (vstr, versionpos, (isdigit (versionpos[7]) ? 8 : 7)); - vstr[(isdigit (versionpos[7]) ? 8 : 7)] = '\0'; - retval = 0; - } - } - } - strcpy(versionbuf, vstr); - return retval; + + char *versionpos; + char vstr[20]; + int retval = -1; + char *vptr; + + strcpy(vstr, "custom"); + if (version) { + if (kdp_vm_read(version, versionbuf, 95)) { + versionbuf[94] = '\0'; + versionpos = strnstr(versionbuf, "xnu-", 90); + if (versionpos) { + strncpy(vstr, versionpos, sizeof(vstr)); + vstr[sizeof(vstr)-1] = '\0'; + vptr = vstr + 4; /* Begin after "xnu-" */ + while (*vptr && (isdigit(*vptr) || *vptr == '.')) + vptr++; + *vptr = '\0'; + /* Remove trailing period, if any */ + if (*(--vptr) == '.') + *vptr = '\0'; + retval = 0; + } + } + } + strcpy(versionbuf, vstr); + return retval; } + +extern char *inet_aton(const char *cp, struct in_addr *pin); +extern int snprintf(char *str, size_t size, const char *format, ...); + /* Primary dispatch routine for the system dump */ void kdp_panic_dump() { - char corename[50]; - char coreprefix[10]; - int panic_error; - extern char *debug_buf; - extern vm_map_t kernel_map; + char corename[50]; + char coreprefix[10]; + int panic_error; - extern char *inet_aton(const char *cp, struct in_addr *pin); + uint64_t abstime; + uint32_t current_ip = ntohl(kdp_current_ip_address); - extern char *debug_buf; - extern char *debug_buf_ptr; - uint64_t abstime; - - printf ("Entering system dump routine\n"); + if (flag_panic_dump_in_progress) { + printf("System dump aborted.\n"); + goto panic_dump_exit; + } + + printf("Entering system dump routine\n"); - if (!panicd_specified) { - printf ("A panic server was not specified in the boot-args, terminating kernel core dump.\n"); - goto panic_dump_exit; - } + if (!panicd_specified) { + printf("A dump server was not specified in the boot-args, terminating kernel core dump.\n"); + goto panic_dump_exit; + } - flag_panic_dump_in_progress = 1; - not_in_kdp = 0; + flag_panic_dump_in_progress = TRUE; + not_in_kdp = 0; - if (pkt.input) - kdp_panic("kdp_panic_dump"); + if (pkt.input) + kdp_panic("kdp_panic_dump: unexpected pending input packet"); - kdp_get_xnu_version((char *) &pkt.data[0]); + kdp_get_xnu_version((char *) &pkt.data[0]); - /* Panic log bit takes precedence over core dump bit */ - if ((panicstr != (char *) 0) && (kdp_flag & PANIC_LOG_DUMP)) - strncpy(coreprefix, "paniclog", sizeof(coreprefix)); - else - strncpy(coreprefix, "core", sizeof(coreprefix)); + /* Panic log bit takes precedence over core dump bit */ + if ((panicstr != (char *) 0) && (kdp_flag & PANIC_LOG_DUMP)) + strncpy(coreprefix, "paniclog", sizeof(coreprefix)); + else + strncpy(coreprefix, "core", sizeof(coreprefix)); - abstime = mach_absolute_time(); - pkt.data[10] = '\0'; - snprintf (corename, sizeof(corename), "%s-%s-%d.%d.%d.%d-%x", + abstime = mach_absolute_time(); + pkt.data[20] = '\0'; + snprintf (corename, sizeof(corename), "%s-%s-%d.%d.%d.%d-%x", coreprefix, &pkt.data[0], - (kdp_current_ip_address & 0xff000000) >> 24, - (kdp_current_ip_address & 0xff0000) >> 16, - (kdp_current_ip_address & 0xff00) >> 8, - (kdp_current_ip_address & 0xff), - (unsigned int) (abstime & 0xffffffff)); - - if (0 == inet_aton(panicd_ip_str, (struct in_addr *) &panic_server_ip)) { - printf("inet_aton() failed interpreting %s as a panic server IP\n", - panicd_ip_str); - } - else - printf("Attempting connection to panic server configured at IP %s\n", - panicd_ip_str); + (current_ip & 0xff000000) >> 24, + (current_ip & 0xff0000) >> 16, + (current_ip & 0xff00) >> 8, + (current_ip & 0xff), + (unsigned int) (abstime & 0xffffffff)); + + if (0 == inet_aton(panicd_ip_str, (struct in_addr *) &panic_server_ip)) { + printf("inet_aton() failed interpreting %s as a panic server IP\n", panicd_ip_str); + } + else + printf("Attempting connection to panic server configured at IP %s, port %d\n", panicd_ip_str, panicd_port); + + destination_mac = router_mac; - if (router_specified) { - if (0 == inet_aton(router_ip_str, (struct in_addr *) &parsed_router_ip)){ - printf("inet_aton() failed interpreting %s as an IP\n", router_ip); + if (kdp_arp_resolve(panic_server_ip, &temp_mac)) { + printf("Resolved %s's (or proxy's) link level address\n", panicd_ip_str); + destination_mac = temp_mac; } - else { - router_ip = parsed_router_ip; - printf("Routing through specified router IP %s (%d)\n", router_ip_str, router_ip); - /* We will eventually need to resolve the router's MAC ourselves, - * if one is specified,rather than being set through the BSD callback - * but the _router_ip option does not function currently - */ + else { + if (!flag_panic_dump_in_progress) goto panic_dump_exit; + if (router_specified) { + if (0 == inet_aton(router_ip_str, (struct in_addr *) &parsed_router_ip)) + printf("inet_aton() failed interpreting %s as an IP\n", router_ip_str); + else { + router_ip = parsed_router_ip; + if (kdp_arp_resolve(router_ip, &temp_mac)) { + destination_mac = temp_mac; + printf("Routing through specified router IP %s (%d)\n", router_ip_str, router_ip); + } + } + } } - } - /* These & 0xffs aren't necessary,but cut&paste is ever so convenient */ - printf("Routing via router MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", - router_mac.ether_addr_octet[0] & 0xff, - router_mac.ether_addr_octet[1] & 0xff, - router_mac.ether_addr_octet[2] & 0xff, - router_mac.ether_addr_octet[3] & 0xff, - router_mac.ether_addr_octet[4] & 0xff, - router_mac.ether_addr_octet[5] & 0xff); - - printf("Kernel map size is %d\n", get_vmmap_size(kernel_map)); - printf ("Sending write request for %s\n", corename); - - if ((panic_error = kdp_send_panic_pkt (KDP_WRQ, corename, 0 , NULL) < 0)) { - printf ("kdp_send_panic_pkt failed with error %d\n", panic_error); - goto panic_dump_exit; - } - /* Just the panic log requested */ - if ((panicstr != (char *) 0) && (kdp_flag & PANIC_LOG_DUMP)) { - printf("Transmitting panic log, please wait: "); - kdp_send_panic_packets (KDP_DATA, corename, (debug_buf_ptr - debug_buf), (unsigned int) debug_buf); - kdp_send_panic_pkt (KDP_EOF, NULL, 0, ((void *) 0)); - printf("Please file a bug report on this panic, if possible.\n"); - goto panic_dump_exit; - } + if (!flag_panic_dump_in_progress) goto panic_dump_exit; + + printf("Transmitting packets to link level address: %02x:%02x:%02x:%02x:%02x:%02x\n", + destination_mac.ether_addr_octet[0] & 0xff, + destination_mac.ether_addr_octet[1] & 0xff, + destination_mac.ether_addr_octet[2] & 0xff, + destination_mac.ether_addr_octet[3] & 0xff, + destination_mac.ether_addr_octet[4] & 0xff, + destination_mac.ether_addr_octet[5] & 0xff); + + printf("Kernel map size is %llu\n", (unsigned long long) get_vmmap_size(kernel_map)); + printf("Sending write request for %s\n", corename); + + if ((panic_error = kdp_send_crashdump_pkt(KDP_WRQ, corename, 0 , NULL)) < 0) { + printf ("kdp_send_crashdump_pkt failed with error %d\n", panic_error); + goto panic_dump_exit; + } + + /* Just the panic log requested */ + if ((panicstr != (char *) 0) && (kdp_flag & PANIC_LOG_DUMP)) { + printf("Transmitting panic log, please wait: "); + kdp_send_crashdump_data(KDP_DATA, corename, (debug_buf_ptr - debug_buf), debug_buf); + kdp_send_crashdump_pkt (KDP_EOF, NULL, 0, ((void *) 0)); + printf("Please file a bug report on this panic, if possible.\n"); + goto panic_dump_exit; + } - /* We want a core dump if we're here */ - kern_dump(); + /* We want a core dump if we're here */ + kern_dump(); panic_dump_exit: - not_in_kdp = 1; - flag_panic_dump_in_progress = 0; - panic_block = 0; - pkt.input = FALSE; - pkt.len = 0; - kdp_reset(); - return; + abort_panic_transfer(); + pkt.input = FALSE; + pkt.len = 0; + kdp_reset(); + return; } void -abort_panic_transfer() +abort_panic_transfer(void) { - flag_panic_dump_in_progress = 0; - not_in_kdp = 1; - panic_block = 0; + flag_panic_dump_in_progress = FALSE; + not_in_kdp = 1; + panic_block = 0; }