Annotation of XNU/osfmk/kdp/kdp_udp.c, revision 1.1

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

unix.superglobalmegacorp.com

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