|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)if_ether.c 7.1.1.1 (Berkeley) 2/27/87
7: */
8:
9: /*
10: * Ethernet address resolution protocol.
11: */
12:
13: #include "param.h"
14: #include "systm.h"
15: #include "mbuf.h"
16: #include "socket.h"
17: #include "time.h"
18: #include "kernel.h"
19: #include "errno.h"
20: #include "ioctl.h"
21: #include "syslog.h"
22:
23: #include "../net/if.h"
24: #include "in.h"
25: #include "in_systm.h"
26: #include "ip.h"
27: #include "if_ether.h"
28:
29: #define ARPTAB_BSIZ 9 /* bucket size */
30: #define ARPTAB_NB 19 /* number of buckets */
31: #define ARPTAB_SIZE (ARPTAB_BSIZ * ARPTAB_NB)
32: struct arptab arptab[ARPTAB_SIZE];
33: int arptab_size = ARPTAB_SIZE; /* for arp command */
34:
35: /*
36: * ARP trailer negotiation. Trailer protocol is not IP specific,
37: * but ARP request/response use IP addresses.
38: */
39: #define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL
40:
41: #define ARPTAB_HASH(a) \
42: ((u_long)(a) % ARPTAB_NB)
43:
44: #define ARPTAB_LOOK(at,addr) { \
45: register n; \
46: at = &arptab[ARPTAB_HASH(addr) * ARPTAB_BSIZ]; \
47: for (n = 0 ; n < ARPTAB_BSIZ ; n++,at++) \
48: if (at->at_iaddr.s_addr == addr) \
49: break; \
50: if (n >= ARPTAB_BSIZ) \
51: at = 0; \
52: }
53:
54: /* timer values */
55: #define ARPT_AGE (60*1) /* aging timer, 1 min. */
56: #define ARPT_KILLC 20 /* kill completed entry in 20 mins. */
57: #define ARPT_KILLI 3 /* kill incomplete entry in 3 minutes */
58:
59: u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
60: extern struct ifnet loif;
61:
62: /*
63: * Timeout routine. Age arp_tab entries once a minute.
64: */
65: arptimer()
66: {
67: register struct arptab *at;
68: register i;
69:
70: timeout(arptimer, (caddr_t)0, ARPT_AGE * hz);
71: at = &arptab[0];
72: for (i = 0; i < ARPTAB_SIZE; i++, at++) {
73: if (at->at_flags == 0 || (at->at_flags & ATF_PERM))
74: continue;
75: if (++at->at_timer < ((at->at_flags&ATF_COM) ?
76: ARPT_KILLC : ARPT_KILLI))
77: continue;
78: /* timer has expired, clear entry */
79: arptfree(at);
80: }
81: }
82:
83: /*
84: * Broadcast an ARP packet, asking who has addr on interface ac.
85: */
86: arpwhohas(ac, addr)
87: register struct arpcom *ac;
88: struct in_addr *addr;
89: {
90: register struct mbuf *m;
91: register struct ether_header *eh;
92: register struct ether_arp *ea;
93: struct sockaddr sa;
94:
95: if ((m = m_get(M_DONTWAIT, MT_DATA)) == NULL)
96: return;
97: m->m_len = sizeof *ea;
98: m->m_off = MMAXOFF - m->m_len;
99: ea = mtod(m, struct ether_arp *);
100: eh = (struct ether_header *)sa.sa_data;
101: bzero((caddr_t)ea, sizeof (*ea));
102: bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
103: sizeof(eh->ether_dhost));
104: eh->ether_type = ETHERTYPE_ARP; /* if_output will swap */
105: ea->arp_hrd = htons(ARPHRD_ETHER);
106: ea->arp_pro = htons(ETHERTYPE_IP);
107: ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */
108: ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */
109: ea->arp_op = htons(ARPOP_REQUEST);
110: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,
111: sizeof(ea->arp_sha));
112: bcopy((caddr_t)&ac->ac_ipaddr, (caddr_t)ea->arp_spa,
113: sizeof(ea->arp_spa));
114: bcopy((caddr_t)addr, (caddr_t)ea->arp_tpa, sizeof(ea->arp_tpa));
115: sa.sa_family = AF_UNSPEC;
116: (*ac->ac_if.if_output)(&ac->ac_if, m, &sa);
117: }
118:
119: int useloopback = 1; /* use loopback interface for local traffic */
120:
121: /*
122: * Resolve an IP address into an ethernet address. If success,
123: * desten is filled in. If there is no entry in arptab,
124: * set one up and broadcast a request for the IP address.
125: * Hold onto this mbuf and resend it once the address
126: * is finally resolved. A return value of 1 indicates
127: * that desten has been filled in and the packet should be sent
128: * normally; a 0 return indicates that the packet has been
129: * taken over here, either now or for later transmission.
130: *
131: * We do some (conservative) locking here at splimp, since
132: * arptab is also altered from input interrupt service (ecintr/ilintr
133: * calls arpinput when ETHERTYPE_ARP packets come in).
134: */
135: arpresolve(ac, m, destip, desten, usetrailers)
136: register struct arpcom *ac;
137: struct mbuf *m;
138: register struct in_addr *destip;
139: register u_char *desten;
140: int *usetrailers;
141: {
142: register struct arptab *at;
143: register struct ifnet *ifp;
144: struct sockaddr_in sin;
145: int s, lna;
146:
147: *usetrailers = 0;
148: if (in_broadcast(*destip)) { /* broadcast address */
149: bcopy((caddr_t)etherbroadcastaddr, (caddr_t)desten,
150: sizeof(etherbroadcastaddr));
151: return (1);
152: }
153: lna = in_lnaof(*destip);
154: ifp = &ac->ac_if;
155: /* if for us, use software loopback driver if up */
156: if (destip->s_addr == ac->ac_ipaddr.s_addr) {
157: if (useloopback) {
158: sin.sin_family = AF_INET;
159: sin.sin_addr = *destip;
160: (void) looutput(&loif, m, (struct sockaddr *)&sin);
161: /*
162: * The packet has already been sent and freed.
163: */
164: return (0);
165: } else {
166: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)desten,
167: sizeof(ac->ac_enaddr));
168: return (1);
169: }
170: }
171: s = splimp();
172: ARPTAB_LOOK(at, destip->s_addr);
173: if (at == 0) { /* not found */
174: if (ifp->if_flags & IFF_NOARP) {
175: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)desten, 3);
176: desten[3] = (lna >> 16) & 0x7f;
177: desten[4] = (lna >> 8) & 0xff;
178: desten[5] = lna & 0xff;
179: splx(s);
180: return (1);
181: } else {
182: at = arptnew(destip);
183: at->at_hold = m;
184: arpwhohas(ac, destip);
185: splx(s);
186: return (0);
187: }
188: }
189: at->at_timer = 0; /* restart the timer */
190: if (at->at_flags & ATF_COM) { /* entry IS complete */
191: bcopy((caddr_t)at->at_enaddr, (caddr_t)desten,
192: sizeof(at->at_enaddr));
193: if (at->at_flags & ATF_USETRAILERS)
194: *usetrailers = 1;
195: splx(s);
196: return (1);
197: }
198: /*
199: * There is an arptab entry, but no ethernet address
200: * response yet. Replace the held mbuf with this
201: * latest one.
202: */
203: if (at->at_hold)
204: m_freem(at->at_hold);
205: at->at_hold = m;
206: arpwhohas(ac, destip); /* ask again */
207: splx(s);
208: return (0);
209: }
210:
211: /*
212: * Called from 10 Mb/s Ethernet interrupt handlers
213: * when ether packet type ETHERTYPE_ARP
214: * is received. Common length and type checks are done here,
215: * then the protocol-specific routine is called.
216: */
217: arpinput(ac, m)
218: struct arpcom *ac;
219: struct mbuf *m;
220: {
221: register struct arphdr *ar;
222:
223: if (ac->ac_if.if_flags & IFF_NOARP)
224: goto out;
225: IF_ADJ(m);
226: if (m->m_len < sizeof(struct arphdr))
227: goto out;
228: ar = mtod(m, struct arphdr *);
229: if (ntohs(ar->ar_hrd) != ARPHRD_ETHER)
230: goto out;
231: if (m->m_len < sizeof(struct arphdr) + 2 * ar->ar_hln + 2 * ar->ar_pln)
232: goto out;
233:
234: switch (ntohs(ar->ar_pro)) {
235:
236: case ETHERTYPE_IP:
237: case ETHERTYPE_IPTRAILERS:
238: in_arpinput(ac, m);
239: return;
240:
241: default:
242: break;
243: }
244: out:
245: m_freem(m);
246: }
247:
248: /*
249: * ARP for Internet protocols on 10 Mb/s Ethernet.
250: * Algorithm is that given in RFC 826.
251: * In addition, a sanity check is performed on the sender
252: * protocol address, to catch impersonators.
253: * We also handle negotiations for use of trailer protocol:
254: * ARP replies for protocol type ETHERTYPE_TRAIL are sent
255: * along with IP replies if we want trailers sent to us,
256: * and also send them in response to IP replies.
257: * This allows either end to announce the desire to receive
258: * trailer packets.
259: * We reply to requests for ETHERTYPE_TRAIL protocol as well,
260: * but don't normally send requests.
261: */
262: in_arpinput(ac, m)
263: register struct arpcom *ac;
264: struct mbuf *m;
265: {
266: register struct ether_arp *ea;
267: struct ether_header *eh;
268: register struct arptab *at; /* same as "merge" flag */
269: struct mbuf *mcopy = 0;
270: struct sockaddr_in sin;
271: struct sockaddr sa;
272: struct in_addr isaddr, itaddr, myaddr;
273: int proto, op, s;
274:
275: myaddr = ac->ac_ipaddr;
276: ea = mtod(m, struct ether_arp *);
277: proto = ntohs(ea->arp_pro);
278: op = ntohs(ea->arp_op);
279: isaddr.s_addr = ((struct in_addr *)ea->arp_spa)->s_addr;
280: itaddr.s_addr = ((struct in_addr *)ea->arp_tpa)->s_addr;
281: if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr,
282: sizeof (ea->arp_sha)))
283: goto out; /* it's from me, ignore it. */
284: if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr,
285: sizeof (ea->arp_sha))) {
286: log(LOG_ERR,
287: "arp: ether address is broadcast for IP address %x!\n",
288: ntohl(isaddr.s_addr));
289: goto out;
290: }
291: if (isaddr.s_addr == myaddr.s_addr) {
292: log(LOG_ERR, "%s: %s\n",
293: "duplicate IP address!! sent from ethernet address",
294: ether_sprintf(ea->arp_sha));
295: itaddr = myaddr;
296: if (op == ARPOP_REQUEST)
297: goto reply;
298: goto out;
299: }
300: s = splimp();
301: ARPTAB_LOOK(at, isaddr.s_addr);
302: if (at) {
303: bcopy((caddr_t)ea->arp_sha, (caddr_t)at->at_enaddr,
304: sizeof(ea->arp_sha));
305: at->at_flags |= ATF_COM;
306: if (at->at_hold) {
307: sin.sin_family = AF_INET;
308: sin.sin_addr = isaddr;
309: (*ac->ac_if.if_output)(&ac->ac_if,
310: at->at_hold, (struct sockaddr *)&sin);
311: at->at_hold = 0;
312: }
313: }
314: if (at == 0 && itaddr.s_addr == myaddr.s_addr) {
315: /* ensure we have a table entry */
316: at = arptnew(&isaddr);
317: bcopy((caddr_t)ea->arp_sha, (caddr_t)at->at_enaddr,
318: sizeof(ea->arp_sha));
319: at->at_flags |= ATF_COM;
320: }
321: splx(s);
322: reply:
323: switch (proto) {
324:
325: case ETHERTYPE_IPTRAILERS:
326: /* partner says trailers are OK */
327: if (at)
328: at->at_flags |= ATF_USETRAILERS;
329: /*
330: * Reply to request iff we want trailers.
331: */
332: if (op != ARPOP_REQUEST || ac->ac_if.if_flags & IFF_NOTRAILERS)
333: goto out;
334: break;
335:
336: case ETHERTYPE_IP:
337: /*
338: * Reply if this is an IP request, or if we want to send
339: * a trailer response.
340: */
341: if (op != ARPOP_REQUEST && ac->ac_if.if_flags & IFF_NOTRAILERS)
342: goto out;
343: }
344: if (itaddr.s_addr == myaddr.s_addr) {
345: /* I am the target */
346: bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha,
347: sizeof(ea->arp_sha));
348: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,
349: sizeof(ea->arp_sha));
350: } else {
351: ARPTAB_LOOK(at, itaddr.s_addr);
352: if (at == NULL || (at->at_flags & ATF_PUBL) == 0)
353: goto out;
354: bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha,
355: sizeof(ea->arp_sha));
356: bcopy((caddr_t)at->at_enaddr, (caddr_t)ea->arp_sha,
357: sizeof(ea->arp_sha));
358: }
359:
360: bcopy((caddr_t)ea->arp_spa, (caddr_t)ea->arp_tpa,
361: sizeof(ea->arp_spa));
362: bcopy((caddr_t)&itaddr, (caddr_t)ea->arp_spa,
363: sizeof(ea->arp_spa));
364: ea->arp_op = htons(ARPOP_REPLY);
365: /*
366: * If incoming packet was an IP reply,
367: * we are sending a reply for type IPTRAILERS.
368: * If we are sending a reply for type IP
369: * and we want to receive trailers,
370: * send a trailer reply as well.
371: */
372: if (op == ARPOP_REPLY)
373: ea->arp_pro = htons(ETHERTYPE_IPTRAILERS);
374: else if (proto == ETHERTYPE_IP &&
375: (ac->ac_if.if_flags & IFF_NOTRAILERS) == 0)
376: mcopy = m_copy(m, 0, (int)M_COPYALL);
377: eh = (struct ether_header *)sa.sa_data;
378: bcopy((caddr_t)ea->arp_tha, (caddr_t)eh->ether_dhost,
379: sizeof(eh->ether_dhost));
380: eh->ether_type = ETHERTYPE_ARP;
381: sa.sa_family = AF_UNSPEC;
382: (*ac->ac_if.if_output)(&ac->ac_if, m, &sa);
383: if (mcopy) {
384: ea = mtod(mcopy, struct ether_arp *);
385: ea->arp_pro = htons(ETHERTYPE_IPTRAILERS);
386: (*ac->ac_if.if_output)(&ac->ac_if, mcopy, &sa);
387: }
388: return;
389: out:
390: m_freem(m);
391: return;
392: }
393:
394: /*
395: * Free an arptab entry.
396: */
397: arptfree(at)
398: register struct arptab *at;
399: {
400: int s = splimp();
401:
402: if (at->at_hold)
403: m_freem(at->at_hold);
404: at->at_hold = 0;
405: at->at_timer = at->at_flags = 0;
406: at->at_iaddr.s_addr = 0;
407: splx(s);
408: }
409:
410: /*
411: * Enter a new address in arptab, pushing out the oldest entry
412: * from the bucket if there is no room.
413: * This always succeeds since no bucket can be completely filled
414: * with permanent entries (except from arpioctl when testing whether
415: * another permanent entry will fit).
416: */
417: struct arptab *
418: arptnew(addr)
419: struct in_addr *addr;
420: {
421: register n;
422: int oldest = -1;
423: register struct arptab *at, *ato = NULL;
424: static int first = 1;
425:
426: if (first) {
427: first = 0;
428: timeout(arptimer, (caddr_t)0, hz);
429: }
430: at = &arptab[ARPTAB_HASH(addr->s_addr) * ARPTAB_BSIZ];
431: for (n = 0; n < ARPTAB_BSIZ; n++,at++) {
432: if (at->at_flags == 0)
433: goto out; /* found an empty entry */
434: if (at->at_flags & ATF_PERM)
435: continue;
436: if (at->at_timer > oldest) {
437: oldest = at->at_timer;
438: ato = at;
439: }
440: }
441: if (ato == NULL)
442: return (NULL);
443: at = ato;
444: arptfree(at);
445: out:
446: at->at_iaddr = *addr;
447: at->at_flags = ATF_INUSE;
448: return (at);
449: }
450:
451: arpioctl(cmd, data)
452: int cmd;
453: caddr_t data;
454: {
455: register struct arpreq *ar = (struct arpreq *)data;
456: register struct arptab *at;
457: register struct sockaddr_in *sin;
458: int s;
459:
460: if (ar->arp_pa.sa_family != AF_INET ||
461: ar->arp_ha.sa_family != AF_UNSPEC)
462: return (EAFNOSUPPORT);
463: sin = (struct sockaddr_in *)&ar->arp_pa;
464: s = splimp();
465: ARPTAB_LOOK(at, sin->sin_addr.s_addr);
466: if (at == NULL) { /* not found */
467: if (cmd != SIOCSARP) {
468: splx(s);
469: return (ENXIO);
470: }
471: if (ifa_ifwithnet(&ar->arp_pa) == NULL) {
472: splx(s);
473: return (ENETUNREACH);
474: }
475: }
476: switch (cmd) {
477:
478: case SIOCSARP: /* set entry */
479: if (at == NULL) {
480: at = arptnew(&sin->sin_addr);
481: if (ar->arp_flags & ATF_PERM) {
482: /* never make all entries in a bucket permanent */
483: register struct arptab *tat;
484:
485: /* try to re-allocate */
486: tat = arptnew(&sin->sin_addr);
487: if (tat == NULL) {
488: arptfree(at);
489: splx(s);
490: return (EADDRNOTAVAIL);
491: }
492: arptfree(tat);
493: }
494: }
495: bcopy((caddr_t)ar->arp_ha.sa_data, (caddr_t)at->at_enaddr,
496: sizeof(at->at_enaddr));
497: at->at_flags = ATF_COM | ATF_INUSE |
498: (ar->arp_flags & (ATF_PERM|ATF_PUBL));
499: at->at_timer = 0;
500: break;
501:
502: case SIOCDARP: /* delete entry */
503: arptfree(at);
504: break;
505:
506: case SIOCGARP: /* get entry */
507: bcopy((caddr_t)at->at_enaddr, (caddr_t)ar->arp_ha.sa_data,
508: sizeof(at->at_enaddr));
509: ar->arp_flags = at->at_flags;
510: break;
511: }
512: splx(s);
513: return (0);
514: }
515:
516: /*
517: * Convert Ethernet address to printable (loggable) representation.
518: */
519: char *
520: ether_sprintf(ap)
521: register u_char *ap;
522: {
523: register i;
524: static char etherbuf[18];
525: register char *cp = etherbuf;
526: static char digits[] = "0123456789abcdef";
527:
528: for (i = 0; i < 6; i++) {
529: *cp++ = digits[*ap >> 4];
530: *cp++ = digits[*ap++ & 0xf];
531: *cp++ = ':';
532: }
533: *--cp = 0;
534: return (etherbuf);
535: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.