|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* ! 26: * Copyright (c) 1993 NeXT Computer, Inc. All rights reserved. ! 27: * ! 28: * kdp_udp.c -- Kernel Debugging Protocol UDP implementation. ! 29: * ! 30: * History: ! 31: * 10 Nov 1997 Herb Ruth [[email protected]] ! 32: * Added extern declarations for implicit function ! 33: * declarations. ! 34: * ! 35: */ ! 36: ! 37: #import <mach/boolean.h> ! 38: #import <mach/exception.h> ! 39: ! 40: #import <sys/param.h> ! 41: #import <sys/systm.h> ! 42: #import <sys/socket.h> ! 43: #import <sys/reboot.h> ! 44: ! 45: #import <net/if.h> ! 46: #import <net/route.h> ! 47: ! 48: #import <netinet/in.h> ! 49: #import <netinet/in_systm.h> ! 50: #import <netinet/in_var.h> ! 51: #import <net/etherdefs.h> ! 52: #import <netinet/ip.h> ! 53: #import <netinet/ip_var.h> ! 54: #import <netinet/in_pcb.h> ! 55: #import <netinet/udp.h> ! 56: #import <netinet/udp_var.h> ! 57: ! 58: #import <kern/kdp_internal.h> ! 59: #import <kern/miniMon.h> ! 60: #import <kern/kdp_en_debugger.h> ! 61: ! 62: /* 10 Nov 1997 */ ! 63: #warning extern declarations -- FIXME XXX ! 64: extern void kprintf(const char *format, ...); ! 65: ! 66: ! 67: #define DO_ALIGN 1 /* align all packet data accesses */ ! 68: ! 69: #if NOTYET ! 70: #import <bsd/dev/km.h> // not yet ! 71: #else ! 72: extern int kmtrygetc(void); ! 73: #endif ! 74: ! 75: /* @(#)udp_usrreq.c 2.2 88/05/23 4.0NFSSRC SMI; from UCB 7.1 6/5/86 */ ! 76: ! 77: /* ! 78: * UDP protocol implementation. ! 79: * Per RFC 768, August, 1980. ! 80: */ ! 81: #define UDP_TTL 60 /* deflt time to live for UDP packets */ ! 82: int udp_ttl=UDP_TTL; ! 83: static unsigned char exception_seq; ! 84: ! 85: static struct { ! 86: unsigned char data[ETHERMAXPACKET]; ! 87: unsigned int off, len; ! 88: boolean_t input; ! 89: } pkt, saved_reply; ! 90: ! 91: struct { ! 92: struct { ! 93: struct in_addr in; ! 94: struct ether_addr ea; ! 95: } loc; ! 96: struct { ! 97: struct in_addr in; ! 98: struct ether_addr ea; ! 99: } rmt; ! 100: } adr; ! 101: ! 102: static char ! 103: *exception_message[] = { ! 104: "Unknown", ! 105: "Memory access", /* EXC_BAD_ACCESS */ ! 106: "Failed instruction", /* EXC_BAD_INSTRUCTION */ ! 107: "Arithmetic", /* EXC_ARITHMETIC */ ! 108: "Emulation", /* EXC_EMULATION */ ! 109: "Software", /* EXC_SOFTWARE */ ! 110: "Breakpoint" /* EXC_BREAKPOINT */ ! 111: }; ! 112: ! 113: static kdp_send_t kdp_en_send_pkt = 0; ! 114: static kdp_receive_t kdp_en_recv_pkt = 0; ! 115: ! 116: void ! 117: kdp_register_send_receive(kdp_send_t send, kdp_receive_t receive) ! 118: { ! 119: if (kdp_en_send_pkt == 0) { /* the first to register is the debugger */ ! 120: kdp_en_send_pkt = send; ! 121: kdp_en_recv_pkt = receive; ! 122: } ! 123: } ! 124: ! 125: static ! 126: void ! 127: kdp_handler( ! 128: void * ! 129: ); ! 130: ! 131: ! 132: static inline ! 133: void ! 134: enaddr_copy( ! 135: void *src, ! 136: void *dst ! 137: ) ! 138: { ! 139: bcopy((caddr_t)src, (caddr_t)dst, sizeof(struct ether_addr)); ! 140: } ! 141: ! 142: static inline ! 143: unsigned short ! 144: ip_sum( ! 145: unsigned char *c, ! 146: unsigned int hlen ! 147: ) ! 148: { ! 149: unsigned int high, low, sum; ! 150: ! 151: high = low = 0; ! 152: while (hlen-- > 0) { ! 153: low += c[1] + c[3]; ! 154: high += c[0] + c[2]; ! 155: ! 156: c += sizeof (int); ! 157: } ! 158: ! 159: sum = (high << 8) + low; ! 160: sum = (sum >> 16) + (sum & 65535); ! 161: ! 162: return (sum > 65535 ? sum - 65535 : sum); ! 163: } ! 164: ! 165: static ! 166: void ! 167: kdp_reply( ! 168: unsigned short reply_port ! 169: ) ! 170: { ! 171: struct udpiphdr aligned_ui, *ui = &aligned_ui; ! 172: struct ip aligned_ip, *ip = &aligned_ip; ! 173: struct in_addr tmp_ipaddr; ! 174: struct ether_addr tmp_enaddr; ! 175: struct ether_header *eh; ! 176: ! 177: if (!pkt.input) ! 178: kdp_panic("kdp_reply"); ! 179: ! 180: pkt.off -= sizeof (struct udpiphdr); ! 181: ! 182: #if DO_ALIGN ! 183: bcopy(&pkt.data[pkt.off], ui, sizeof(*ui)); ! 184: #else ! 185: ui = (struct udpiphdr *)&pkt.data[pkt.off]; ! 186: #endif ! 187: ui->ui_next = ui->ui_prev = 0; ! 188: ui->ui_x1 = 0; ! 189: ui->ui_pr = IPPROTO_UDP; ! 190: ui->ui_len = htons((u_short)pkt.len + sizeof (struct udphdr)); ! 191: tmp_ipaddr = ui->ui_src; ! 192: ui->ui_src = ui->ui_dst; ! 193: ui->ui_dst = tmp_ipaddr; ! 194: ui->ui_sport = htons(KDP_REMOTE_PORT); ! 195: ui->ui_dport = reply_port; ! 196: ui->ui_ulen = ui->ui_len; ! 197: ui->ui_sum = 0; ! 198: #if DO_ALIGN ! 199: bcopy(ui, &pkt.data[pkt.off], sizeof(*ui)); ! 200: ! 201: bcopy(&pkt.data[pkt.off], ip, sizeof(*ip)); ! 202: #else ! 203: ip = (struct ip *)&pkt.data[pkt.off]; ! 204: #endif ! 205: ip->ip_len = htons(sizeof (struct udpiphdr) + pkt.len); ! 206: ip->ip_v = IPVERSION; ! 207: ip->ip_id = htons(ip_id++); ! 208: ip->ip_hl = sizeof (struct ip) >> 2; ! 209: ip->ip_ttl = udp_ttl; ! 210: ip->ip_sum = 0; ! 211: ip->ip_sum = htons(~ip_sum((unsigned char *)ip, ip->ip_hl)); ! 212: #if DO_ALIGN ! 213: bcopy(ip, &pkt.data[pkt.off], sizeof(*ip)); ! 214: #endif ! 215: ! 216: pkt.len += sizeof (struct udpiphdr); ! 217: ! 218: pkt.off -= sizeof (struct ether_header); ! 219: ! 220: eh = (struct ether_header *)&pkt.data[pkt.off]; ! 221: enaddr_copy(eh->ether_shost, &tmp_enaddr); ! 222: enaddr_copy(eh->ether_dhost, eh->ether_shost); ! 223: enaddr_copy(&tmp_enaddr, eh->ether_dhost); ! 224: eh->ether_type = htons(ETHERTYPE_IP); ! 225: ! 226: pkt.len += sizeof (struct ether_header); ! 227: ! 228: // save reply for possible retransmission ! 229: bcopy(&pkt, &saved_reply, sizeof(pkt)); ! 230: ! 231: (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len); ! 232: ! 233: // increment expected sequence number ! 234: exception_seq++; ! 235: } ! 236: ! 237: static ! 238: void ! 239: kdp_send( ! 240: unsigned short remote_port ! 241: ) ! 242: { ! 243: struct udpiphdr aligned_ui, *ui = &aligned_ui; ! 244: struct ip aligned_ip, *ip = &aligned_ip; ! 245: struct ether_header *eh; ! 246: ! 247: if (pkt.input) ! 248: kdp_panic("kdp_send"); ! 249: ! 250: pkt.off -= sizeof (struct udpiphdr); ! 251: ! 252: #if DO_ALIGN ! 253: bcopy(&pkt.data[pkt.off], ui, sizeof(*ui)); ! 254: #else ! 255: ui = (struct udpiphdr *)&pkt.data[pkt.off]; ! 256: #endif ! 257: ui->ui_next = ui->ui_prev = 0; ! 258: ui->ui_x1 = 0; ! 259: ui->ui_pr = IPPROTO_UDP; ! 260: ui->ui_len = htons((u_short)pkt.len + sizeof (struct udphdr)); ! 261: ui->ui_src = adr.loc.in; ! 262: ui->ui_dst = adr.rmt.in; ! 263: ui->ui_sport = htons(KDP_REMOTE_PORT); ! 264: ui->ui_dport = remote_port; ! 265: ui->ui_ulen = ui->ui_len; ! 266: ui->ui_sum = 0; ! 267: #if DO_ALIGN ! 268: bcopy(ui, &pkt.data[pkt.off], sizeof(*ui)); ! 269: ! 270: bcopy(&pkt.data[pkt.off], ip, sizeof(*ip)); ! 271: #else ! 272: ip = (struct ip *)&pkt.data[pkt.off]; ! 273: #endif ! 274: ip->ip_len = htons(sizeof (struct udpiphdr) + pkt.len); ! 275: ip->ip_v = IPVERSION; ! 276: ip->ip_id = htons(ip_id++); ! 277: ip->ip_hl = sizeof (struct ip) >> 2; ! 278: ip->ip_ttl = udp_ttl; ! 279: ip->ip_sum = 0; ! 280: ip->ip_sum = htons(~ip_sum((unsigned char *)ip, ip->ip_hl)); ! 281: #if DO_ALIGN ! 282: bcopy(ip, &pkt.data[pkt.off], sizeof(*ip)); ! 283: #endif ! 284: ! 285: pkt.len += sizeof (struct udpiphdr); ! 286: ! 287: pkt.off -= sizeof (struct ether_header); ! 288: ! 289: eh = (struct ether_header *)&pkt.data[pkt.off]; ! 290: enaddr_copy(&adr.loc.ea, eh->ether_shost); ! 291: enaddr_copy(&adr.rmt.ea, eh->ether_dhost); ! 292: eh->ether_type = htons(ETHERTYPE_IP); ! 293: ! 294: pkt.len += sizeof (struct ether_header); ! 295: ! 296: (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len); ! 297: } ! 298: ! 299: static ! 300: void ! 301: kdp_poll( ! 302: void ! 303: ) ! 304: { ! 305: struct ether_header *eh; ! 306: struct udpiphdr aligned_ui, *ui = &aligned_ui; ! 307: struct ip aligned_ip, *ip = &aligned_ip; ! 308: ! 309: if (pkt.input) ! 310: kdp_panic("kdp_poll"); ! 311: ! 312: if (!kdp_en_recv_pkt || !kdp_en_send_pkt) ! 313: kdp_panic("kdp_poll: no debugger device\n"); ! 314: ! 315: pkt.off = 0; ! 316: (*kdp_en_recv_pkt)(pkt.data, &pkt.len, 3/* ms */); ! 317: ! 318: if (pkt.len == 0) ! 319: return; ! 320: ! 321: if (pkt.len < (sizeof (struct ether_header) + sizeof (struct udpiphdr))) ! 322: return; ! 323: ! 324: eh = (struct ether_header *)&pkt.data[pkt.off]; ! 325: pkt.off += sizeof (struct ether_header); ! 326: if (ntohs(eh->ether_type) != ETHERTYPE_IP) { ! 327: return; ! 328: } ! 329: ! 330: #if DO_ALIGN ! 331: bcopy(&pkt.data[pkt.off], ui, sizeof(*ui)); ! 332: bcopy(&pkt.data[pkt.off], ip, sizeof(*ip)); ! 333: #else ! 334: ui = (struct udpiphdr *)&pkt.data[pkt.off]; ! 335: ip = (struct ip *)&pkt.data[pkt.off]; ! 336: #endif ! 337: ! 338: pkt.off += sizeof (struct udpiphdr); ! 339: if (ui->ui_pr != IPPROTO_UDP) { ! 340: return; ! 341: } ! 342: ! 343: if (ip->ip_hl > (sizeof (struct ip) >> 2)) { ! 344: return; ! 345: } ! 346: ! 347: if (ntohs(ui->ui_dport) != KDP_REMOTE_PORT) { ! 348: return; ! 349: } ! 350: ! 351: if (!kdp.is_conn) { ! 352: enaddr_copy(eh->ether_dhost, &adr.loc.ea); ! 353: adr.loc.in = ui->ui_dst; ! 354: ! 355: enaddr_copy(eh->ether_shost, &adr.rmt.ea); ! 356: adr.rmt.in = ui->ui_src; ! 357: } ! 358: ! 359: /* ! 360: * Calculate kdp packet length. ! 361: */ ! 362: pkt.len = ntohs((u_short)ui->ui_ulen) - sizeof (struct udphdr); ! 363: pkt.input = TRUE; ! 364: } ! 365: ! 366: static ! 367: void ! 368: kdp_handler( ! 369: void *saved_state ! 370: ) ! 371: { ! 372: unsigned short reply_port; ! 373: kdp_hdr_t aligned_hdr, *hdr = &aligned_hdr; ! 374: ! 375: ! 376: kdp.saved_state = saved_state; // see comment in kdp_raise_exception ! 377: ! 378: do { ! 379: while (!pkt.input) ! 380: kdp_poll(); ! 381: ! 382: #if DO_ALIGN ! 383: bcopy(&pkt.data[pkt.off], hdr, sizeof(*hdr)); ! 384: #else ! 385: hdr = (kdp_hdr_t *)&pkt.data[pkt.off]; ! 386: #endif ! 387: ! 388: // ignore replies -- we're not expecting them anyway. ! 389: if (hdr->is_reply) { ! 390: goto again; ! 391: } ! 392: ! 393: // check for retransmitted request ! 394: if (hdr->seq == (exception_seq - 1)) { ! 395: /* retransmit last reply */ ! 396: (*kdp_en_send_pkt)(&saved_reply.data[saved_reply.off], ! 397: saved_reply.len); ! 398: goto again; ! 399: } else if (hdr->seq != exception_seq) { ! 400: safe_prf("kdp: bad sequence %d (want %d)\n", ! 401: hdr->seq, exception_seq); ! 402: goto again; ! 403: } ! 404: ! 405: if (kdp_packet(&pkt.data[pkt.off], &pkt.len, &reply_port)) { ! 406: kdp_reply(reply_port); ! 407: } ! 408: ! 409: again: ! 410: pkt.input = FALSE; ! 411: } while (kdp.is_halted); ! 412: } ! 413: ! 414: static ! 415: void ! 416: kdp_connection_wait( ! 417: void ! 418: ) ! 419: { ! 420: unsigned short reply_port; ! 421: ! 422: safe_prf("Waiting for remote debugger connection.\n"); ! 423: safe_prf("(Type 'c' to continue or 'r' to reboot)\n"); ! 424: ! 425: exception_seq = 0; ! 426: do { ! 427: kdp_hdr_t aligned_hdr, *hdr = &aligned_hdr; ! 428: ! 429: while (!pkt.input) { ! 430: int c; ! 431: c = kmtrygetc(); ! 432: switch(c) { ! 433: case 'c': ! 434: safe_prf("Continuing...\n"); ! 435: return; ! 436: case 'r': ! 437: safe_prf("Rebooting...\n"); ! 438: kdp_reboot(); ! 439: break; ! 440: default: ! 441: break; ! 442: } ! 443: kdp_poll(); ! 444: } ! 445: ! 446: // check for sequence number of 0 ! 447: #if DO_ALIGN ! 448: bcopy(&pkt.data[pkt.off], hdr, sizeof(*hdr)); ! 449: #else ! 450: hdr = (kdp_hdr_t *)&pkt.data[pkt.off]; ! 451: #endif ! 452: if ((hdr->request == KDP_CONNECT) && ! 453: !hdr->is_reply && (hdr->seq == exception_seq)) { ! 454: if (kdp_packet(&pkt.data[pkt.off], &pkt.len, &reply_port)) ! 455: kdp_reply(reply_port); ! 456: } ! 457: ! 458: pkt.input = FALSE; ! 459: } while (!kdp.is_conn); ! 460: ! 461: safe_prf("Connected to remote debugger.\n"); ! 462: } ! 463: ! 464: static ! 465: void ! 466: kdp_send_exception( ! 467: unsigned int exception, ! 468: unsigned int code, ! 469: unsigned int subcode ! 470: ) ! 471: { ! 472: unsigned short remote_port; ! 473: unsigned int timeout_count; ! 474: ! 475: timeout_count = 300; // should be about 30 seconds ! 476: do { ! 477: pkt.off = sizeof (struct ether_header) + sizeof (struct udpiphdr); ! 478: kdp_exception(&pkt.data[pkt.off], &pkt.len, &remote_port, ! 479: exception, code, subcode); ! 480: ! 481: kdp_send(remote_port); ! 482: ! 483: kdp_poll(); ! 484: ! 485: if (pkt.input) ! 486: kdp_exception_ack(&pkt.data[pkt.off], pkt.len); ! 487: ! 488: pkt.input = FALSE; ! 489: if (kdp.exception_ack_needed) ! 490: kdp_us_spin(100000); // 1/10 sec ! 491: ! 492: } while (kdp.exception_ack_needed && timeout_count--); ! 493: ! 494: if (kdp.exception_ack_needed) { ! 495: // give up & disconnect ! 496: safe_prf("kdp: exception ack timeout\n"); ! 497: kdp_reset(); ! 498: } ! 499: } ! 500: ! 501: int ! 502: kdp_processing_packet(void) ! 503: { ! 504: return pkt.input; ! 505: } ! 506: ! 507: void ! 508: kdp_raise_exception( ! 509: unsigned int exception, ! 510: unsigned int code, ! 511: unsigned int subcode, ! 512: void *saved_state ! 513: ) ! 514: { ! 515: int s = kdp_intr_disbl(); ! 516: int index; ! 517: ! 518: if (saved_state == 0) ! 519: safe_prf("kdp_raise_exception: saved_state is NULL!\n"); ! 520: ! 521: index = exception; ! 522: if (exception != EXC_BREAKPOINT) { ! 523: if (exception > EXC_BREAKPOINT || exception < EXC_BAD_ACCESS) { ! 524: index = 0; ! 525: kprintf("kdp_raise_exception: unknown exception value (%d), changing to zero.\n", exception); ! 526: } ! 527: kprintf("kdp_raise_exception: %s exception (exception = %x, code = %x, subcode = %x)\n", ! 528: exception_message[index], ! 529: exception, ! 530: code, ! 531: subcode); ! 532: safe_prf("%s exception (%x,%x,%x)\n", ! 533: exception_message[index], ! 534: exception, code, subcode); ! 535: } ! 536: ! 537: kdp_flush_cache(); ! 538: ! 539: /* XXX WMG it seems that sometimes it doesn't work to let kdp_handler ! 540: * do this. I think the client and the host can get out of sync. ! 541: */ ! 542: kdp.saved_state = saved_state; ! 543: ! 544: if (pkt.input) ! 545: kdp_panic("kdp_raise_exception"); ! 546: ! 547: if (!kdp.is_conn) ! 548: kdp_connection_wait(); ! 549: else ! 550: kdp_send_exception(exception, code, subcode); ! 551: ! 552: if (kdp.is_conn) { ! 553: kdp.is_halted = TRUE; /* XXX */ ! 554: ! 555: kdp_handler(saved_state); ! 556: ! 557: if (!kdp.is_conn) ! 558: safe_prf("Remote debugger disconnected.\n"); ! 559: } ! 560: ! 561: kdp_flush_cache(); ! 562: kdp_intr_enbl(s); ! 563: } ! 564: ! 565: void ! 566: kdp_reset(void) ! 567: { ! 568: kdp.reply_port = kdp.exception_port = 0; ! 569: kdp.is_halted = kdp.is_conn = FALSE; ! 570: kdp.exception_seq = kdp.conn_seq = 0; ! 571: } ! 572:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.