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