|
|
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)ðerbroadcastaddr, ! 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.