|
|
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.