|
|
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.