|
|
1.1 ! root 1: #include "sys/param.h" ! 2: #include "sys/systm.h" ! 3: #include "sys/ethernet.h" ! 4: #include "sys/stream.h" ! 5: #include "sys/inet/in.h" ! 6: #include "sys/inet/ip_var.h" ! 7: ! 8: /* ! 9: * Address resolution code. ip_ldout() calls arp_resolve if IFF_ARP ! 10: * is set to map an internet address into a 48 bit ethernet address. ! 11: * If arp_resolve finds the address in its tables, it prepends an ! 12: * ethernet header to the packet and returns it. Otherwise, it sends ! 13: * a message to the ipconfig waiting on the specified queue asking ! 14: * it to do all the hard work. The user process at some point will use ! 15: * the IPIORESOLVE ioctl to update the tabes. ! 16: * ! 17: * N.B. If we ever get a medium other than ethernet that needs arping, ! 18: * this code will need to be made a bit more general. ! 19: */ ! 20: ! 21: /* ! 22: * Hash table for arp entries. Collision resolution is linear search until ! 23: * encountering a hole. Replacement is LRU. ! 24: */ ! 25: /* #define NARP 128 /* number of arp entries */ ! 26: extern int arpcnt; /* number of arp entries */ ! 27: extern struct ip_arp ip_arps[]; /* arping table */ ! 28: #define HASH(x) ((x)%arpcnt) ! 29: ! 30: arp_install(in, en) ! 31: register unsigned long in; ! 32: unsigned char *en; ! 33: { ! 34: register struct ip_arp *ap, *rp, *op; ! 35: ! 36: /* find matching entry, empty entry, or oldest entry */ ! 37: op = ap = rp = &ip_arps[HASH(in)]; ! 38: do { ! 39: if (ap->inaddr==0 || ap->inaddr==in) { ! 40: op = ap; ! 41: break; ! 42: } ! 43: if (ap->time < op->time) ! 44: op = ap; ! 45: if(++ap==&ip_arps[arpcnt]) ! 46: ap = ip_arps; ! 47: } while(ap!=rp); ! 48: ! 49: /* fill in new entry */ ! 50: op->time = time; ! 51: op->inaddr = in; ! 52: bcopy((caddr_t)en, (caddr_t)op->enaddr, sizeof(op->enaddr)); ! 53: return(0); ! 54: } ! 55: ! 56: struct block * ! 57: arp_resolve(q, bp, dst) ! 58: struct queue *q; ! 59: register struct block *bp; ! 60: unsigned long dst; ! 61: { ! 62: register struct block *bp1; ! 63: struct etherpup *hp; ! 64: register struct ip_arp *ap, *rp; ! 65: ! 66: /* find matching entry */ ! 67: ap = rp = &ip_arps[HASH(dst)]; ! 68: do { ! 69: if (ap->inaddr==0 || ap->inaddr==dst) ! 70: break; ! 71: if(++ap==&ip_arps[arpcnt]) ! 72: ap = ip_arps; ! 73: } while(ap!=rp); ! 74: if (ap->inaddr!=dst) { ! 75: arp_request(q, dst); /* request an address resolution */ ! 76: bp_free(bp); /* free the packet */ ! 77: return(0); ! 78: } ! 79: ! 80: /* make a block with the ether info */ ! 81: bp1 = allocb(sizeof(struct etherpup)); ! 82: if(bp1 == 0){ ! 83: printf("no bp for arp_resolve\n"); ! 84: bp_free(bp); ! 85: return(0); ! 86: } ! 87: ap->time = time; ! 88: bp1->type = M_DATA; ! 89: bp1->wptr = bp1->rptr + sizeof(struct etherpup); ! 90: bp1->next = bp; ! 91: hp = (struct etherpup *)(bp1->rptr); ! 92: hp->type = htons(ETHERPUP_IPTYPE); ! 93: bcopy((caddr_t)(ap->enaddr), (caddr_t)(hp->dhost), 6); ! 94: return(bp1); ! 95: } ! 96: ! 97: arp_request(q, dst) ! 98: register struct queue *q; ! 99: unsigned long dst; ! 100: { ! 101: struct block *bp; ! 102: ! 103: if(q->next->flag & QFULL){ ! 104: printf("arp q full\n"); ! 105: return; ! 106: } ! 107: bp = allocb(4); ! 108: if(bp == 0) ! 109: return; ! 110: bp->type = M_DATA; ! 111: bp->wptr = bp->rptr + 4; ! 112: bp->class |= S_DELIM; ! 113: *((u_long *)(bp->rptr)) = dst; ! 114: (*q->next->qinfo->putp)(q->next, bp); ! 115: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.