|
|
1.1 root 1: /* if_ether.c 6.2 83/08/28 */
2:
3: /*
4: * Ethernet address resolution protocol.
5: */
6:
7: #include "../h/param.h"
8: #include "../h/systm.h"
9: #include "../h/mbuf.h"
10: #include "../h/socket.h"
11: #include "../h/time.h"
12: #include "../h/kernel.h"
13: #include "../h/errno.h"
14:
15: #include "../net/if.h"
16: #include "../netinet/in.h"
17: #include "../netinet/if_ether.h"
1.1.1.2 ! root 18: #include "../tahoeif/if_acereg.h"
! 19: #include "../tahoeif/if_enp.h"
1.1 root 20:
21: /*
22: * changes:
23: *
24: * . always return 0 after calling looutput().
25: *
26: * . forces messages going to net if flag gotoether is set.
27: * (set this flag through "adb" for debugging purposes).
28: *
29: * . add symbolic return code to arpresolve(). See comments in
30: * arpresolve().
1.1.1.2 ! root 31: *
! 32: * . add test to check if the broadcast message originated from
! 33: * the other controllers on the same host. If so, there is no
! 34: * need to print out error message that warns about duplicate
! 35: * ip address.
1.1 root 36: */
37:
38: /*
39: * Internet to ethernet address resolution table.
40: */
41: struct arptab {
42: struct in_addr at_iaddr; /* internet address */
43: u_char at_enaddr[6]; /* ethernet address */
44: struct mbuf *at_hold; /* last packet until resolved/timeout */
45: u_char at_timer; /* minutes since last reference */
46: u_char at_flags; /* flags */
47: };
48: /* at_flags field values */
49: #define ATF_INUSE 1 /* entry in use */
50: #define ATF_COM 2 /* completed entry (enaddr valid) */
51:
52: #define ARPTAB_BSIZ 5 /* bucket size */
53: #define ARPTAB_NB 19 /* number of buckets */
54: #define ARPTAB_SIZE (ARPTAB_BSIZ * ARPTAB_NB)
55: struct arptab arptab[ARPTAB_SIZE];
56:
57: #define ARPTAB_HASH(a) \
58: ((short)((((a) >> 16) ^ (a)) & 0x7fff) % ARPTAB_NB)
59:
60: #define ARPTAB_LOOK(at,addr) { \
61: register n; \
62: at = &arptab[ARPTAB_HASH(addr) * ARPTAB_BSIZ]; \
63: for (n = 0 ; n < ARPTAB_BSIZ ; n++,at++) \
64: if (at->at_iaddr.s_addr == addr) \
65: break; \
66: if (n >= ARPTAB_BSIZ) \
67: at = 0; }
68:
69: struct arpcom *arpcom; /* chain of active ether interfaces */
70: int arpt_age; /* aging timer */
71: int gotoether; /* force traffic to Ethernet; no software
72: loopback */
73:
74: /* timer values */
75: #define ARPT_AGE (60*1) /* aging timer, 1 min. */
76: #define ARPT_KILLC 20 /* kill completed entry in 20 mins. */
77: #define ARPT_KILLI 3 /* kill incomplete entry in 3 minutes */
78:
79: u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
80: extern struct ifnet loif;
1.1.1.2 ! root 81: extern struct ace_softc ace_softc[];
! 82: extern struct enp_softc enp_softc[];
! 83: extern int numace;
! 84: extern int numenp;
1.1 root 85: /*------------- debug tools ---------------*/
86: #ifdef ARPPRINTFS
87: int arpprintfs;
88: # define ARPTRACE(X) {if (arpprintfs) X }
89: #else ARPPRINTFS
90: # define ARPTRACE(X)
91: #endif ARPPRINTFS
92:
93: /*
94: * Local addresses in the range oldmap to infinity are
95: * mapped according to the old mapping scheme. That is,
96: * mapping of Internet to Ethernet addresses is performed
97: * by taking the high three bytes of the network interface's
98: * address and the low three bytes of the local address part.
99: * This only allows boards from the same manufacturer to
100: * communicate unless the on-board address is overridden
101: * (not possible in many manufacture's hardware).
102: *
103: * NB: setting oldmap to zero completely disables ARP
104: * (i.e. identical to setting IFF_NOARP with an ioctl).
105: */
1.1.1.2 ! root 106: /* int oldmap = 1024; we remove this reference for ARP usr */
1.1 root 107:
108: /*
109: * Attach an ethernet interface to the list "arpcom" where
110: * arptimer() can find it. If first time
111: * initialization, start arptimer().
112: */
113: arpattach(ac)
114: register struct arpcom *ac;
115: {
116: register struct arpcom *acp;
117:
118: for (acp = arpcom; acp != (struct arpcom *)0; acp = acp->ac_ac)
119: if (acp == ac) /* if already on list */
120: return;
121: ac->ac_ac = arpcom;
122: arpcom = ac;
123: if (arpcom->ac_ac == 0) /* very first time */
124: arptimer();
125: }
126:
127: /*
128: * Timeout routine. Age arp_tab entries once a minute.
129: */
130: arptimer()
131: {
132: register struct arptab *at;
133: register i;
134:
135: timeout(arptimer, (caddr_t)0, hz);
136: #ifdef notdef
137: if (++arpt_sanity > ARPT_SANITY) {
138: register struct arpcom *ac;
139:
140: /*
141: * Randomize sanity timer based on my host address.
142: * Ask who has my own address; if someone else replies,
143: * then they are impersonating me.
144: */
145: arpt_sanity = arpcom->ac_enaddr[5] & 0x3f;
146: for (ac = arpcom; ac != (struct arpcom *)-1; ac = ac->ac_ac)
147: arpwhohas(ac, &((struct sockaddr_in *)
148: &ac->ac_if.if_addr)->sin_addr);
149: }
150: #endif
151: if (++arpt_age > ARPT_AGE) {
152: arpt_age = 0;
153: at = &arptab[0];
154: for (i = 0; i < ARPTAB_SIZE; i++, at++) {
155: if (at->at_flags == 0)
156: continue;
157: if (++at->at_timer < ((at->at_flags&ATF_COM) ?
158: ARPT_KILLC : ARPT_KILLI))
159: continue;
160: /* timer has expired, clear entry */
161: arptfree(at);
162: }
163: }
164: }
165:
166: /*
167: * Broadcast an ARP packet, asking who has addr on interface ac.
168: */
169: arpwhohas(ac, addr)
170: register struct arpcom *ac;
171: struct in_addr *addr;
172: {
173: register struct mbuf *m;
174: register struct ether_header *eh;
175: register struct ether_arp *ea;
176: struct sockaddr sa;
177:
178: m = m_get(M_DONTWAIT, MT_DATA);
179: MBUFNULL(5,m); /* for debugging */
180: if (m == NULL)
181: return;
182: m->m_len = sizeof *ea + SIZEOF_ETHEADER;
183: m->m_off = MMAXOFF - m->m_len;
184: ea = mtod(m, struct ether_arp *);
185: eh = (struct ether_header *)sa.sa_data;
186: bzero((caddr_t)ea, sizeof (*ea));
187: bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
188: sizeof (etherbroadcastaddr));
189: eh->ether_type = ETHERPUP_ARPTYPE; /* if_output will swap */
190: ea->arp_hrd = htons(ARPHRD_ETHER);
191: ea->arp_pro = htons(ETHERPUP_IPTYPE);
192: ea->arp_hln = sizeof ea->arp_sha; /* hardware address length */
193: ea->arp_pln = sizeof ea->arp_spa; /* protocol address length */
194: ea->arp_op = htons(ARPOP_REQUEST);
195: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,
196: sizeof (ea->arp_sha));
197: bcopy((caddr_t)&((struct sockaddr_in *)&ac->ac_if.if_addr)->sin_addr,
198: (caddr_t)ea->arp_spa, sizeof (ea->arp_spa));
199: bcopy((caddr_t)addr, (caddr_t)ea->arp_tpa, sizeof (ea->arp_tpa));
200: sa.sa_family = AF_UNSPEC;
201: ARPTRACE(printf("arpwhohas:broadcast through %s%d for addr %lx\n",
202: ac->ac_if.if_name, ac->ac_if.if_unit, addr->s_addr);)
203: (void) (*ac->ac_if.if_output)(&ac->ac_if, m, &sa);
204: }
205:
206: /*
207: *
208: * Resolve an IP address into an ethernet address. If success,
209: * desten is filled in and 1 is returned. If there is no entry
210: * in arptab, set one up and broadcast a request
211: * for the IP address; return 0. Hold onto this mbuf and
212: * resend it once the address is finally resolved.
213: *
214: * We do some (conservative) locking here at splimp, since
215: * arptab is also altered from input interrupt service (ecintr/ilintr
216: * calls arpinput when ETHERPUP_ARPTYPE packets come in).
217: *
218: * Returns:
219: *
220: * ARPRESOLVE_WILLSEND
221: * arpresolve() cannot resolve the address. It will send the
222: * packet when it the address is resolved. However, if the
223: * destination is same as origination, arpresolve() does not
224: * resolve address, it routes the packet to software loopback.
225: *
226: * ARPRESOLVE_OK
227: * arpresolve() successfully resolves the address. The calling
228: * routine is responsible for sending out the packet. Address
229: * is not a wild-card (not broadcast).
230: *
231: * ARPRESOLVE_BROADCAST
232: * arpresovle() successfully resolves the address which is
233: * a wildcard. If the controller is NOT capable of listening to
234: * its own broadcast, the device driver is responsible for
235: * routing a copy of the packet to the software loopback.
236: *
237: */
238: arpresolve(ac, m, destip, desten)
239: register struct arpcom *ac;
240: struct mbuf *m;
241: register struct in_addr *destip;
242: register u_char *desten;
243: {
244: register struct arptab *at;
245: register struct ifnet *ifp;
246: struct sockaddr_in sin;
247: int s, lna;
248:
249: lna = in_lnaof(*destip);
250: if (lna == INADDR_ANY) { /* broadcast address */
251: bcopy((caddr_t)etherbroadcastaddr, (caddr_t)desten,
252: sizeof (etherbroadcastaddr));
1.1.1.2 ! root 253:
! 254: ARPTRACE(printf("\tarpresolve(%s%d)target: %lx, %x.%x.%x.%x.%x.%x\n",
! 255: ac->ac_if.if_name, ac->ac_if.if_unit,
! 256: destip->s_addr,
! 257: desten[0] & 0xff, desten[1] & 0xff,
! 258: desten[2] & 0xff, desten[3] & 0xff,
! 259: desten[4] & 0xff, desten[5] & 0xff);)
! 260:
1.1 root 261: return (ARPRESOLVE_BROADCAST);
262: }
263: ifp = &ac->ac_if;
264: /* if for us, then use software loopback driver */
265: if ((destip->s_addr ==
266: ((struct sockaddr_in *)&ifp->if_addr)-> sin_addr.s_addr) &&
267: (gotoether==0)) {
268: sin.sin_family = AF_INET;
269: sin.sin_addr = *destip;
270: looutput(&loif, m, (struct sockaddr *)&sin);
271: return(ARPRESOLVE_WILLSEND);
272: }
1.1.1.2 ! root 273: /* if ((ifp->if_flags & IFF_NOARP) || lna >= oldmap) { */
! 274: if (ifp->if_flags & IFF_NOARP) {
1.1 root 275: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)desten, 3);
276: desten[3] = (lna >> 16) & 0x7f;
277: desten[4] = (lna >> 8) & 0xff;
278: desten[5] = lna & 0xff;
1.1.1.2 ! root 279: ARPTRACE(printf("\tarpresolve2(%s%d)target: %lx, %x.%x.%x.%x.%x.%x\n",
! 280: ac->ac_if.if_name, ac->ac_if.if_unit,
! 281: destip->s_addr,
! 282: desten[0] & 0xff, desten[1] & 0xff,
! 283: desten[2] & 0xff, desten[3] & 0xff,
! 284: desten[4] & 0xff, desten[5] & 0xff);)
! 285:
1.1 root 286: return (ARPRESOLVE_OK);
287: }
288: s = splimp();
289: ARPTAB_LOOK(at, destip->s_addr);
290: if (at == 0) { /* not found */
291: at = arptnew(destip);
292: ARPTRACE(printf("arpresolve(%s%d) (m=%lx), arptab empty\n",
293: ac->ac_if.if_name, ac->ac_if.if_unit, m);)
294:
295: ARPTRACE(if (at->at_hold)
296: printf("arpresolve: LOOSE mbuf %lx\n",m);)
297: at->at_hold = m;
298: arpwhohas(ac, destip);
299: splx(s);
300: return (ARPRESOLVE_WILLSEND);
301: }
302: at->at_timer = 0; /* restart the timer */
303: if (at->at_flags & ATF_COM) { /* entry IS complete */
304: bcopy((caddr_t)at->at_enaddr, (caddr_t)desten, 6);
305: splx(s);
1.1.1.2 ! root 306:
! 307: ARPTRACE(printf("\tarpresolve3(%s%d)target: %lx, %x.%x.%x.%x.%x.%x\n",
! 308: ac->ac_if.if_name, ac->ac_if.if_unit,
! 309: destip->s_addr,
! 310: desten[0] & 0xff, desten[1] & 0xff,
! 311: desten[2] & 0xff, desten[3] & 0xff,
! 312: desten[4] & 0xff, desten[5] & 0xff);)
! 313:
1.1 root 314: return (ARPRESOLVE_OK);
315: }
316: /*
317: * There is an arptab entry, but no ethernet address
318: * response yet. Replace the held mbuf with this
319: * latest one.
320: */
321: ARPTRACE(printf("arpresolve(%s%d) (m=%lx), arptab not completed\n",
322: ac->ac_if.if_name, ac->ac_if.if_unit, m);)
323: if (at->at_hold)
324: m_freem(at->at_hold);
325: at->at_hold = m;
326: arpwhohas(ac, destip); /* ask again */
327: splx(s);
328: return (ARPRESOLVE_WILLSEND);
329: }
330:
331: /*
332: * Find my own IP address. It will either be waiting for us in
333: * monitor RAM, or can be obtained via broadcast to the file/boot
334: * server (not necessarily using the ARP packet format).
335: *
336: * Unimplemented at present, return 0 and assume that the host
337: * will set his own IP address via the SIOCSIFADDR ioctl.
338: */
339: /*ARGSUSED*/
340: struct in_addr
341: arpmyaddr(ac)
342: register struct arpcom *ac;
343: {
344: static struct in_addr addr;
345:
346: #ifdef lint
347: ac = ac;
348: #endif
349: addr.s_addr = 0;
350: return (addr);
351: }
352:
353: /*
354: * Called from ecintr/ilintr when ether packet type ETHERPUP_ARP
355: * is received. Algorithm is exactly that given in RFC 826.
356: * In addition, a sanity check is performed on the sender
357: * protocol address, to catch impersonators.
358: */
359: arpinput(ac, m)
360: register struct arpcom *ac;
361: struct mbuf *m;
362: {
363: register struct ether_arp *ea;
364: struct ether_header *eh;
365: register struct arptab *at = 0; /* same as "merge" flag */
366: struct sockaddr_in sin;
367: struct sockaddr sa;
368: struct mbuf *mhold;
369: struct in_addr isaddr,itaddr,myaddr;
370:
1.1.1.2 ! root 371: ARPTRACE(printf("arpinput through %s%d (m=%lx, m->m_len=%d)\n",
! 372: ac->ac_if.if_name, ac->ac_if.if_unit, m,m->m_len);)
1.1 root 373:
374: if (m->m_len < sizeof *ea)
375: goto out;
376:
377: myaddr = ((struct sockaddr_in *)&ac->ac_if.if_addr)->sin_addr;
378: ea = mtod(m, struct ether_arp *);
379: if (ntohs(ea->arp_pro) != ETHERPUP_IPTYPE)
380: goto out;
381: bcopy((caddr_t)ea->arp_spa, (caddr_t)&isaddr.s_addr,
382: sizeof (ea->arp_spa));
383: /* isaddr.s_addr = ((struct in_addr *)ea->arp_spa)->s_addr;*/
384: bcopy((caddr_t)ea->arp_tpa, (caddr_t)&itaddr.s_addr,
385: sizeof (ea->arp_spa));
386: /* itaddr.s_addr = ((struct in_addr *)ea->arp_tpa)->s_addr;*/
387: if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr,
388: sizeof (ac->ac_enaddr)))
389: goto out; /* it's from me, ignore it. */
390:
1.1.1.2 ! root 391: ARPTRACE(printf("\tarpinput (%s%d) sender: %lx, %x.%x.%x.%x.%x.%x, target: %lx\n",
1.1 root 392: ac->ac_if.if_name, ac->ac_if.if_unit,
393: isaddr.s_addr,
394: ea->arp_sha[0] & 0xff, ea->arp_sha[1] & 0xff,
395: ea->arp_sha[2] & 0xff, ea->arp_sha[3] & 0xff,
396: ea->arp_sha[4] & 0xff, ea->arp_sha[5] & 0xff,
1.1.1.2 ! root 397: itaddr.s_addr );)
1.1 root 398:
399: if (isaddr.s_addr == myaddr.s_addr) {
1.1.1.2 ! root 400: if (!fromme(ea->arp_sha)) {
! 401: printf("duplicate IP address!! sent from ethernet address: ");
! 402: printf("%x %x %x %x %x %x\n", ea->arp_sha[0], ea->arp_sha[1],
! 403: ea->arp_sha[2], ea->arp_sha[3],
! 404: ea->arp_sha[4], ea->arp_sha[5]);
! 405: if (ntohs(ea->arp_op) == ARPOP_REQUEST)
! 406: goto reply;
! 407: goto out;
! 408: }
1.1 root 409: }
410: ARPTAB_LOOK(at, isaddr.s_addr);
411: if (at) {
412: bcopy((caddr_t)ea->arp_sha, (caddr_t)at->at_enaddr,
413: sizeof (ea->arp_sha));
414: ARPTRACE(printf("\tarpinput(%s%d). Update sender addr\n",
415: ac->ac_if.if_name, ac->ac_if.if_unit);)
416:
417: at->at_flags |= ATF_COM;
418: if (at->at_hold) {
419: mhold = at->at_hold;
420: at->at_hold = 0;
421: sin.sin_family = AF_INET;
422: sin.sin_addr = isaddr;
423: (*ac->ac_if.if_output)(&ac->ac_if,
424: mhold, (struct sockaddr *)&sin);
425: }
426: }
427: if (itaddr.s_addr != myaddr.s_addr) {
428: ARPTRACE(printf("\tarpinput(%s%d) Iam not the target\n",
429: ac->ac_if.if_name, ac->ac_if.if_unit);)
430: goto out; /* if I am not the target */
431: }
432: if (at == 0) { /* ensure we have a table entry */
433: ARPTRACE(printf("\tarpinput(%s%d). New entry for sender addr\n",
434: ac->ac_if.if_name, ac->ac_if.if_unit);)
435: at = arptnew(&isaddr);
436: bcopy((caddr_t)ea->arp_sha, (caddr_t)at->at_enaddr,
437: sizeof (ea->arp_sha));
438: at->at_flags |= ATF_COM;
439: }
440: if (ntohs(ea->arp_op) != ARPOP_REQUEST)
441: goto out;
442: reply:
443: bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha,
444: sizeof (ea->arp_sha));
445: bcopy((caddr_t)ea->arp_spa, (caddr_t)ea->arp_tpa,
446: sizeof (ea->arp_spa));
447: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,
448: sizeof (ea->arp_sha));
449: bcopy((caddr_t)&myaddr, (caddr_t)ea->arp_spa,
450: sizeof (ea->arp_spa));
451: ea->arp_op = htons(ARPOP_REPLY);
452: eh = (struct ether_header *)sa.sa_data;
453: bcopy((caddr_t)ea->arp_tha, (caddr_t)eh->ether_dhost,
454: sizeof (eh->ether_dhost));
455: eh->ether_type = ETHERPUP_ARPTYPE;
456: sa.sa_family = AF_UNSPEC;
457:
458: ARPTRACE(bcopy((caddr_t)ea->arp_tpa, (caddr_t)&itaddr.s_addr,
459: sizeof (ea->arp_tpa));)
460: ARPTRACE(printf("\tarpinput(%s%d). Send reply to %lx\n",
461: ac->ac_if.if_name, ac->ac_if.if_unit,itaddr.s_addr);)
462:
463: (*ac->ac_if.if_output)(&ac->ac_if, m, &sa);
464: return;
465: out:
466: m_freem(m);
467: return;
468: }
469:
470: /*
471: * Free an arptab entry.
472: */
473: arptfree(at)
474: register struct arptab *at;
475: {
476: int s = splimp();
477:
478: if (at->at_hold)
479: m_freem(at->at_hold);
480: at->at_hold = 0;
481: at->at_timer = at->at_flags = 0;
482: at->at_iaddr.s_addr = 0;
483: splx(s);
484: }
485:
486: /*
487: * Enter a new address in arptab, pushing out the oldest entry
488: * from the bucket if there is no room.
489: */
490: struct arptab *
491: arptnew(addr)
492: struct in_addr *addr;
493: {
494: register n;
495: int oldest = 0;
496: register struct arptab *at, *ato;
497:
498: ato = at = &arptab[ARPTAB_HASH(addr->s_addr) * ARPTAB_BSIZ];
499: for (n = 0 ; n < ARPTAB_BSIZ ; n++,at++) {
500: if (at->at_flags == 0)
501: goto out; /* found an empty entry */
502: if (at->at_timer > oldest) {
503: oldest = at->at_timer;
504: ato = at;
505: }
506: }
507: at = ato;
508: arptfree(at);
509: out:
510: at->at_iaddr = *addr;
511: at->at_flags = ATF_INUSE;
512: return (at);
513: }
514:
515: arpremove(addr)
516: struct sockaddr *addr;
517: {
518: register struct arptab *at;
519: struct in_addr *idst;
520: register long x;
521:
522: idst = &((struct sockaddr_in *)addr)->sin_addr;
523: x = splimp();
524: ARPTAB_LOOK(at, idst->s_addr);
525: if (at) arptfree(at);
526: splx(x);
527: }
528:
1.1.1.2 ! root 529: fromme(ea)
! 530: char *ea;
! 531: {
! 532: int i;
! 533:
! 534: for (i = 0; i < numace; i++) {
! 535: if (!bcmp(ea, ace_softc[i].is_addr, 6))
! 536: return(1);
! 537: }
! 538: for (i = 0; i < numenp; i++) {
! 539: if (!bcmp(ea, enp_softc[i].es_enaddr, 6))
! 540: return(1);
! 541: }
! 542: return(0);
! 543: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.