Annotation of kernel/kern/kdp_udp.c, revision 1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.