Annotation of researchv9/sys/boot/stand/inet.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)inet.c     1.1 86/02/03    Copyr 1984 Sun Micro";
                      3: #endif
                      4: 
                      5: /*
                      6:  * Copyright (c) 1985 by Sun Microsystems, Inc.
                      7:  */
                      8: 
                      9: /*
                     10:  * Standalone IP send and receive - specific to Ethernet
                     11:  * Includes ARP and Reverse ARP
                     12:  */
                     13: #include "saio.h"
                     14: #include "../h/socket.h"
                     15: #include "../net/if.h"
                     16: #include "../netinet/in.h"
                     17: #include "../netinet/if_ether.h"
                     18: #include "../netinet/in_systm.h"
                     19: #include "../netinet/ip.h"
                     20: #include "sainet.h"
                     21: #include "../mon/sunromvec.h"
                     22: #include "../mon/idprom.h"
                     23: 
                     24: #define millitime() (*romp->v_nmiclock)
                     25: 
                     26: struct ether_addr etherbroadcastaddr = { 
                     27:        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
                     28: };
                     29: 
                     30: struct arp_packet {
                     31:        struct ether_header     arp_eh;
                     32:        struct ether_arp        arp_ea;
                     33: #define        used_size (sizeof (struct ether_header)+sizeof(struct ether_arp))
                     34:        char    filler[ETHERMIN - sizeof(struct ether_arp)];
                     35: };
                     36: 
                     37: #define WAITCNT        2       /* 4 seconds before bitching about arp/revarp */
                     38: 
                     39: /*
                     40:  * Fetch our Ethernet address from the ID prom
                     41:  */
                     42: myetheraddr(ea)
                     43:        struct ether_addr *ea;
                     44: {
                     45:        struct idprom id;
                     46: 
                     47:        if (idprom(IDFORM_1, &id) != IDFORM_1) {
                     48:                printf("ERROR: missing or invalid ID prom\n");
                     49:                return;
                     50:        }
                     51:        *ea = *(struct ether_addr *)id.id_ether;
                     52: }
                     53: 
                     54: /*
                     55:  * Initialize IP state
                     56:  * Find out our Ethernet address and call Reverse ARP
                     57:  * to find out our Internet address
                     58:  * Set the ARP cache to the broadcast host
                     59:  */
                     60: inet_init(sip, sain, tmpbuf)
                     61:        register struct saioreq *sip;
                     62:        register struct sainet *sain;
                     63:        char *tmpbuf;
                     64: {
                     65:        myetheraddr(&sain->sain_myether);
                     66:        sain->sain_hisaddr.s_addr = 0;
                     67:        sain->sain_hisether = etherbroadcastaddr;
                     68:        revarp(sip, sain, tmpbuf);
                     69: }
                     70: 
                     71: 
                     72: /*
                     73:  * Output an IP packet
                     74:  * Cause ARP to be invoked if necessary
                     75:  */
                     76: ip_output(sip, buf, len, sain, tmpbuf)
                     77:        register struct saioreq *sip;
                     78:        caddr_t buf, tmpbuf;
                     79:        short len;
                     80:        register struct sainet *sain;
                     81: {
                     82:        register struct ether_header *eh;
                     83:        register struct ip *ip;
                     84: 
                     85:        eh = (struct ether_header *)buf;
                     86:        ip = (struct ip *)(buf + sizeof(struct ether_header));
                     87:        if (ip->ip_dst.s_addr != sain->sain_hisaddr.s_addr) {
                     88:                sain->sain_hisaddr.s_addr = ip->ip_dst.s_addr;
                     89:                arp(sip, sain, tmpbuf);
                     90:        }
                     91:        eh->ether_type = ETHERPUP_IPTYPE;
                     92:        eh->ether_shost = sain->sain_myether;
                     93:        eh->ether_dhost = sain->sain_hisether;
                     94:        /* checksum the packet */
                     95:        ip->ip_sum = 0;
                     96:        ip->ip_sum = ipcksum((caddr_t)ip, sizeof (struct ip));
                     97:        if (len < ETHERMIN+sizeof(struct ether_header))
                     98:                len = ETHERMIN+sizeof(struct ether_header);
                     99:        return (*sip->si_sif->sif_xmit)(sip->si_devdata, buf, len);
                    100: }
                    101: 
                    102: /*
                    103:  * Check incoming packets for IP packets
                    104:  * addressed to us. Also, respond to ARP packets
                    105:  * that wish to know about us.
                    106:  * Returns a length for any IP packet addressed to us, 0 otherwise.
                    107:  */
                    108: ip_input(sip, buf, sain)
                    109:        register struct saioreq *sip;
                    110:        caddr_t buf;
                    111:        register struct sainet *sain;
                    112: {
                    113:        register short len;
                    114:        register struct ether_header *eh;
                    115:        register struct ip *ip;
                    116:        register struct ether_arp *ea;
                    117: 
                    118:        len = (*sip->si_sif->sif_poll)(sip->si_devdata, buf);
                    119:        eh = (struct ether_header *)buf;
                    120:        if (eh->ether_type == ETHERPUP_IPTYPE &&
                    121:            len >= sizeof(struct ether_header)+sizeof(struct ip)) {
                    122:                ip = (struct ip *)(buf + sizeof(struct ether_header));
                    123: #ifdef NOREVARP
                    124:                if ((sain->sain_hisaddr.s_addr & 0xFF000000) == 0 &&
                    125:                    bcmp((caddr_t)&etherbroadcastaddr,
                    126:                                (caddr_t)&eh->ether_dhost, 6) != 0 &&
                    127:                    (in_broadaddr(sain->sain_hisaddr) ||
                    128:                    in_lnaof(ip->ip_src) == in_lnaof(sain->sain_hisaddr))) {
                    129:                        sain->sain_myaddr = ip->ip_dst;
                    130:                        sain->sain_hisaddr = ip->ip_src;
                    131:                        sain->sain_hisether = eh->ether_shost;
                    132:                }
                    133: #endif
                    134:                if (ip->ip_dst.s_addr != sain->sain_myaddr.s_addr) 
                    135:                        return (0);
                    136:                return (len);
                    137:        }
                    138:        if (eh->ether_type == ETHERPUP_ARPTYPE &&
                    139:            len >= sizeof(struct ether_header)+sizeof(struct ether_arp)) {
                    140:                ea = (struct ether_arp *)(buf + sizeof(struct ether_header));
                    141:                if (ea->arp_pro != ETHERPUP_IPTYPE)
                    142:                        return (0);
                    143:                if (arp_spa(ea).s_addr == sain->sain_hisaddr.s_addr)
                    144:                        sain->sain_hisether = arp_sha(ea);
                    145:                if (ea->arp_op == ARPOP_REQUEST &&
                    146:                    arp_tpa(ea).s_addr == sain->sain_myaddr.s_addr) {
                    147:                        ea->arp_op = ARPOP_REPLY;
                    148:                        eh->ether_dhost = arp_sha(ea);
                    149:                        eh->ether_shost = sain->sain_myether;
                    150:                        arp_tha(ea) = arp_sha(ea);
                    151:                        arp_tpa(ea) = arp_spa(ea);
                    152:                        arp_sha(ea) = sain->sain_myether;
                    153:                        arp_spa(ea) = sain->sain_myaddr;
                    154:                        (*sip->si_sif->sif_xmit)(sip->si_devdata, buf, 
                    155:                                                sizeof(struct arp_packet));
                    156:                }
                    157:                return (0);
                    158:        }
                    159:        return (0);
                    160: }
                    161: 
                    162: /*
                    163:  * arp
                    164:  * Broadcasts to determine Ethernet address given IP address
                    165:  * See RFC 826
                    166:  */
                    167: arp(sip, sain, tmpbuf)
                    168:        register struct saioreq *sip;
                    169:        register struct sainet *sain;
                    170:        char *tmpbuf;
                    171: {
                    172:        struct arp_packet out;
                    173: 
                    174:        if (in_broadaddr(sain->sain_hisaddr)
                    175: #ifdef NOREVARP
                    176:            || (sain->sain_hisaddr.s_addr & 0xFF000000) == 0
                    177: #endif
                    178:            ) {
                    179:                sain->sain_hisether = etherbroadcastaddr;
                    180:                return;
                    181:        }
                    182:        out.arp_eh.ether_type = ETHERPUP_ARPTYPE;
                    183:        out.arp_ea.arp_op = ARPOP_REQUEST;
                    184:        arp_tha(&out.arp_ea) = etherbroadcastaddr;      /* what we want */
                    185:        arp_tpa(&out.arp_ea).s_addr = sain->sain_hisaddr.s_addr;
                    186:        comarp(sip, sain, &out, tmpbuf);
                    187: }
                    188: 
                    189: /*
                    190:  * Reverse ARP client side
                    191:  * Determine our Internet address given our Ethernet address
                    192:  * See RFC 903
                    193:  */
                    194: revarp(sip, sain, tmpbuf)
                    195:        register struct saioreq *sip;
                    196:        register struct sainet *sain;
                    197:        char *tmpbuf;
                    198: {
                    199:        struct arp_packet out;
                    200: 
                    201: #ifdef NOREVARP
                    202:        sain->sain_myaddr.s_addr = 0;
                    203:        bcopy((caddr_t)&sain->sain_myether.ether_addr_octet[3],
                    204:                (caddr_t)(&sain->sain_myaddr)+1, 3);
                    205: #else
                    206:        out.arp_eh.ether_type = ETHERPUP_REVARPTYPE;
                    207:        out.arp_ea.arp_op = REVARP_REQUEST;
                    208:        arp_tha(&out.arp_ea) = sain->sain_myether;
                    209:        arp_tpa(&out.arp_ea).s_addr = 0;/* what we want to find out */
                    210:        comarp(sip, sain, &out, tmpbuf);
                    211: #endif
                    212: }
                    213: 
                    214: /*
                    215:  * Common ARP code 
                    216:  * Broadcast the packet and wait for the right response.
                    217:  * Fills in *sain with the results
                    218:  */
                    219: comarp(sip, sain, out, tmpbuf)
                    220:        register struct saioreq *sip;
                    221:        register struct sainet *sain;
                    222:        register struct arp_packet *out;
                    223:        char *tmpbuf;
                    224: {
                    225:        register struct arp_packet *in = (struct arp_packet *)tmpbuf;
                    226:        register int e, count, time, feedback,len, delay = 2;
                    227:        char    *ind = "-\|/";
                    228: 
                    229:        out->arp_eh.ether_dhost = etherbroadcastaddr;
                    230:        out->arp_eh.ether_shost = sain->sain_myether;
                    231:        out->arp_ea.arp_hrd =  ARPHRD_ETHER;
                    232:        out->arp_ea.arp_pro = ETHERPUP_IPTYPE;
                    233:        out->arp_ea.arp_hln = sizeof(struct ether_addr);
                    234:        out->arp_ea.arp_pln = sizeof(struct in_addr);
                    235:        arp_sha(&out->arp_ea) = sain->sain_myether;
                    236:        arp_spa(&out->arp_ea).s_addr = sain->sain_myaddr.s_addr;
                    237:        feedback = 0;
                    238: 
                    239:        for (count=0; ; count++) {
                    240:                if (count == WAITCNT) {
                    241:                        if (out->arp_ea.arp_op == ARPOP_REQUEST) {
                    242:                                printf("\nRequesting Ethernet address for ");
                    243:                                inet_print(arp_tpa(&out->arp_ea));
                    244:                        } else {
                    245:                                printf("\nRequesting Internet address for ");
                    246:                                ether_print(&arp_tha(&out->arp_ea));
                    247:                        }
                    248:                }
                    249:                e = (*sip->si_sif->sif_xmit)(sip->si_devdata, (caddr_t)out,
                    250:                        sizeof *out);
                    251:                if (e)
                    252:                        printf("X\b");
                    253:                else
                    254:                        printf("%c\b", ind[feedback++ % 4]); /* Show activity */
                    255: 
                    256:                time = millitime() + (delay * 1000);    /* broadcast delay */
                    257:                while (millitime() <= time) {
                    258:                        len = (*sip->si_sif->sif_poll)(sip->si_devdata, tmpbuf);
                    259:                        if (len < used_size)
                    260:                                continue;
                    261:                        if (in->arp_ea.arp_pro != ETHERPUP_IPTYPE)
                    262:                                continue;
                    263:                        if (out->arp_ea.arp_op == ARPOP_REQUEST) {
                    264:                                if (in->arp_eh.ether_type != ETHERPUP_ARPTYPE)
                    265:                                        continue;
                    266:                                if (in->arp_ea.arp_op != ARPOP_REPLY)
                    267:                                        continue;
                    268:                                if (arp_spa(&in->arp_ea).s_addr !=
                    269:                                    arp_tpa(&out->arp_ea).s_addr)
                    270:                                        continue;
                    271:                                if (count >= WAITCNT) {
                    272:                                        printf("Found at ");
                    273:                                        ether_print(&arp_sha(&in->arp_ea));
                    274:                                }
                    275:                                sain->sain_hisether = arp_sha(&in->arp_ea);
                    276:                                return;
                    277:                        } else {                /* Reverse ARP */
                    278:                                if (in->arp_eh.ether_type !=ETHERPUP_REVARPTYPE)
                    279:                                        continue;
                    280:                                if (in->arp_ea.arp_op != REVARP_REPLY)
                    281:                                        continue;
                    282:                                if (bcmp((caddr_t)&arp_tha(&in->arp_ea),
                    283:                                    (caddr_t)&arp_tha(&out->arp_ea), 
                    284:                                    sizeof (struct ether_addr)) != 0)
                    285:                                        continue;
                    286: 
                    287:                                if (count >= WAITCNT) {
                    288:                                        printf("Internet address is ");
                    289:                                        inet_print(arp_tpa(&in->arp_ea));
                    290:                                }
                    291:                                sain->sain_myaddr = arp_tpa(&in->arp_ea);
                    292:                                /* short circuit first ARP */
                    293:                                sain->sain_hisaddr = arp_spa(&in->arp_ea);
                    294:                                sain->sain_hisether = arp_sha(&in->arp_ea);
                    295:                                return;
                    296:                        }
                    297:                }
                    298: 
                    299:                delay = delay * 2;      /* Double the request delay */
                    300:                if (delay > 64)         /* maximum delay is 64 seconds */
                    301:                        delay = 64;
                    302: 
                    303:                (*sip->si_sif->sif_reset)(sip->si_devdata);
                    304:        }
                    305:        /* NOTREACHED */
                    306: }
                    307: 
                    308: /*
                    309:  * Return the host portion of an internet address.
                    310:  */
                    311: in_lnaof(in)
                    312:        struct in_addr in;
                    313: {
                    314:        register u_long i = ntohl(in.s_addr);
                    315: 
                    316:        if (IN_CLASSA(i))
                    317:                return ((i)&IN_CLASSA_HOST);
                    318:        else if (IN_CLASSB(i))
                    319:                return ((i)&IN_CLASSB_HOST);
                    320:        else
                    321:                return ((i)&IN_CLASSC_HOST);
                    322: }
                    323: 
                    324: /*
                    325:  * Test for broadcast IP address
                    326:  */
                    327: in_broadaddr(in)
                    328:        struct in_addr in;
                    329: {
                    330:        register u_long i = ntohl(in.s_addr);
                    331: 
                    332:        if (IN_CLASSA(i)) {
                    333:                i &= IN_CLASSA_HOST;
                    334:                return (i == 0 || i == 0xFFFFFF);
                    335:        } else if (IN_CLASSB(i)) {
                    336:                i &= IN_CLASSB_HOST;
                    337:                return (i == 0 || i == 0xFFFF);
                    338:        } else if (IN_CLASSC(i)) {
                    339:                i &= IN_CLASSC_HOST;
                    340:                return (i == 0 || i == 0xFF);
                    341:        }
                    342:        /* NOTREACHED */
                    343: }
                    344: 
                    345: /*
                    346:  * Compute one's complement checksum
                    347:  * for IP packet headers 
                    348:  */
                    349: ipcksum(cp, count)
                    350:        caddr_t cp;
                    351:        register unsigned short count;
                    352: {
                    353:        register unsigned short *sp = (unsigned short *)cp;
                    354:        register unsigned long  sum = 0;
                    355:        register unsigned long  oneword = 0x00010000;
                    356: 
                    357:        count >>= 1;
                    358:        while (count--) {
                    359:                sum += *sp++;
                    360:                if (sum >= oneword) {           /* Wrap carries into low bit */
                    361:                        sum -= oneword;
                    362:                        sum++;
                    363:                }
                    364:        }
                    365:        return (~sum);
                    366: }
                    367: 
                    368: inet_print(s)
                    369:        struct in_addr s;
                    370: {
                    371:        printf("%d.%d.%d.%d\n",
                    372:                s.S_un.S_un_b.s_b1, s.S_un.S_un_b.s_b2, 
                    373:                s.S_un.S_un_b.s_b3, s.S_un.S_un_b.s_b4);
                    374: }
                    375: 
                    376: ether_print(ea)
                    377:        struct ether_addr *ea;
                    378: {
                    379:        register u_char *p = &ea->ether_addr_octet[0];
                    380: 
                    381:        printf("%x:%x:%x:%x:%x:%x\n", p[0], p[1], p[2], p[3], p[4], p[5]);
                    382: }

unix.superglobalmegacorp.com

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