xref: /original-bsd/sys/netinet/if_ether.c (revision e2944021)
1 /*
2  * Copyright (c) 1982 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	6.18 (Berkeley) 03/04/86
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 /*
120  * Resolve an IP address into an ethernet address.  If success,
121  * desten is filled in.  If there is no entry in arptab,
122  * set one up and broadcast a request for the IP address.
123  * Hold onto this mbuf and resend it once the address
124  * is finally resolved.  A return value of 1 indicates
125  * that desten has been filled in and the packet should be sent
126  * normally; a 0 return indicates that the packet has been
127  * taken over here, either now or for later transmission.
128  *
129  * We do some (conservative) locking here at splimp, since
130  * arptab is also altered from input interrupt service (ecintr/ilintr
131  * calls arpinput when ETHERTYPE_ARP packets come in).
132  */
133 arpresolve(ac, m, destip, desten, usetrailers)
134 	register struct arpcom *ac;
135 	struct mbuf *m;
136 	register struct in_addr *destip;
137 	register u_char *desten;
138 	int *usetrailers;
139 {
140 	register struct arptab *at;
141 	register struct ifnet *ifp;
142 	struct sockaddr_in sin;
143 	int s, lna;
144 
145 	*usetrailers = 0;
146 	if (in_broadcast(*destip)) {	/* broadcast address */
147 		bcopy((caddr_t)etherbroadcastaddr, (caddr_t)desten,
148 		    sizeof(etherbroadcastaddr));
149 		return (1);
150 	}
151 	lna = in_lnaof(*destip);
152 	ifp = &ac->ac_if;
153 	/* if for us, use software loopback driver if up */
154 	if (destip->s_addr == ac->ac_ipaddr.s_addr) {
155 		if (loif.if_flags & IFF_UP) {
156 			sin.sin_family = AF_INET;
157 			sin.sin_addr = *destip;
158 			(void) looutput(&loif, m, (struct sockaddr *)&sin);
159 			/*
160 			 * The packet has already been sent and freed.
161 			 */
162 			return (0);
163 		} else {
164 			bcopy((caddr_t)ac->ac_enaddr, (caddr_t)desten,
165 			    sizeof(ac->ac_enaddr));
166 			return (1);
167 		}
168 	}
169 	s = splimp();
170 	ARPTAB_LOOK(at, destip->s_addr);
171 	if (at == 0) {			/* not found */
172 		if (ifp->if_flags & IFF_NOARP) {
173 			bcopy((caddr_t)ac->ac_enaddr, (caddr_t)desten, 3);
174 			desten[3] = (lna >> 16) & 0x7f;
175 			desten[4] = (lna >> 8) & 0xff;
176 			desten[5] = lna & 0xff;
177 			splx(s);
178 			return (1);
179 		} else {
180 			at = arptnew(destip);
181 			at->at_hold = m;
182 			arpwhohas(ac, destip);
183 			splx(s);
184 			return (0);
185 		}
186 	}
187 	at->at_timer = 0;		/* restart the timer */
188 	if (at->at_flags & ATF_COM) {	/* entry IS complete */
189 		bcopy((caddr_t)at->at_enaddr, (caddr_t)desten,
190 		    sizeof(at->at_enaddr));
191 		if (at->at_flags & ATF_USETRAILERS)
192 			*usetrailers = 1;
193 		splx(s);
194 		return (1);
195 	}
196 	/*
197 	 * There is an arptab entry, but no ethernet address
198 	 * response yet.  Replace the held mbuf with this
199 	 * latest one.
200 	 */
201 	if (at->at_hold)
202 		m_freem(at->at_hold);
203 	at->at_hold = m;
204 	arpwhohas(ac, destip);		/* ask again */
205 	splx(s);
206 	return (0);
207 }
208 
209 /*
210  * Called from 10 Mb/s Ethernet interrupt handlers
211  * when ether packet type ETHERTYPE_ARP
212  * is received.  Common length and type checks are done here,
213  * then the protocol-specific routine is called.
214  */
215 arpinput(ac, m)
216 	struct arpcom *ac;
217 	struct mbuf *m;
218 {
219 	register struct arphdr *ar;
220 
221 	if (ac->ac_if.if_flags & IFF_NOARP)
222 		goto out;
223 	IF_ADJ(m);
224 	if (m->m_len < sizeof(struct arphdr))
225 		goto out;
226 	ar = mtod(m, struct arphdr *);
227 	if (ntohs(ar->ar_hrd) != ARPHRD_ETHER)
228 		goto out;
229 	if (m->m_len < sizeof(struct arphdr) + 2 * ar->ar_hln + 2 * ar->ar_pln)
230 		goto out;
231 
232 	switch (ntohs(ar->ar_pro)) {
233 
234 	case ETHERTYPE_IP:
235 	case ETHERTYPE_IPTRAILERS:
236 		in_arpinput(ac, m);
237 		return;
238 
239 	default:
240 		break;
241 	}
242 out:
243 	m_freem(m);
244 }
245 
246 /*
247  * ARP for Internet protocols on 10 Mb/s Ethernet.
248  * Algorithm is that given in RFC 826.
249  * In addition, a sanity check is performed on the sender
250  * protocol address, to catch impersonators.
251  * We also handle negotiations for use of trailer protocol:
252  * ARP replies for protocol type ETHERTYPE_TRAIL are sent
253  * along with IP replies if we want trailers sent to us,
254  * and also send them in response to IP replies.
255  * This allows either end to announce the desire to receive
256  * trailer packets.
257  * We reply to requests for ETHERTYPE_TRAIL protocol as well,
258  * but don't normally send requests.
259  */
260 in_arpinput(ac, m)
261 	register struct arpcom *ac;
262 	struct mbuf *m;
263 {
264 	register struct ether_arp *ea;
265 	struct ether_header *eh;
266 	register struct arptab *at;  /* same as "merge" flag */
267 	struct mbuf *mcopy = 0;
268 	struct sockaddr_in sin;
269 	struct sockaddr sa;
270 	struct in_addr isaddr, itaddr, myaddr;
271 	int proto, op;
272 
273 	myaddr = ac->ac_ipaddr;
274 	ea = mtod(m, struct ether_arp *);
275 	proto = ntohs(ea->arp_pro);
276 	op = ntohs(ea->arp_op);
277 	isaddr.s_addr = ((struct in_addr *)ea->arp_spa)->s_addr;
278 	itaddr.s_addr = ((struct in_addr *)ea->arp_tpa)->s_addr;
279 	if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr,
280 	  sizeof (ea->arp_sha)))
281 		goto out;	/* it's from me, ignore it. */
282 	if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr,
283 	    sizeof (ea->arp_sha))) {
284 		log(LOG_ERR,
285 		    "arp: ether address is broadcast for IP address %x!\n",
286 		    ntohl(isaddr.s_addr));
287 		goto out;
288 	}
289 	if (isaddr.s_addr == myaddr.s_addr) {
290 		log(LOG_ERR, "%s: %s\n",
291 			"duplicate IP address!! sent from ethernet address",
292 			ether_sprintf(ea->arp_sha));
293 		itaddr = myaddr;
294 		if (op == ARPOP_REQUEST)
295 			goto reply;
296 		goto out;
297 	}
298 	ARPTAB_LOOK(at, isaddr.s_addr);
299 	if (at) {
300 		bcopy((caddr_t)ea->arp_sha, (caddr_t)at->at_enaddr,
301 		    sizeof(ea->arp_sha));
302 		at->at_flags |= ATF_COM;
303 		if (at->at_hold) {
304 			sin.sin_family = AF_INET;
305 			sin.sin_addr = isaddr;
306 			(*ac->ac_if.if_output)(&ac->ac_if,
307 			    at->at_hold, (struct sockaddr *)&sin);
308 			at->at_hold = 0;
309 		}
310 	}
311 	if (at == 0 && itaddr.s_addr == myaddr.s_addr) {
312 		/* ensure we have a table entry */
313 		at = arptnew(&isaddr);
314 		bcopy((caddr_t)ea->arp_sha, (caddr_t)at->at_enaddr,
315 		    sizeof(ea->arp_sha));
316 		at->at_flags |= ATF_COM;
317 	}
318 reply:
319 	switch (proto) {
320 
321 	case ETHERTYPE_IPTRAILERS:
322 		/* partner says trailers are OK */
323 		if (at)
324 			at->at_flags |= ATF_USETRAILERS;
325 		/*
326 		 * Reply to request iff we want trailers.
327 		 */
328 		if (op != ARPOP_REQUEST || ac->ac_if.if_flags & IFF_NOTRAILERS)
329 			goto out;
330 		break;
331 
332 	case ETHERTYPE_IP:
333 		/*
334 		 * Reply if this is an IP request, or if we want to send
335 		 * a trailer response.
336 		 */
337 		if (op != ARPOP_REQUEST && ac->ac_if.if_flags & IFF_NOTRAILERS)
338 			goto out;
339 	}
340 	if (itaddr.s_addr == myaddr.s_addr) {
341 		/* I am the target */
342 		bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha,
343 		    sizeof(ea->arp_sha));
344 		bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,
345 		    sizeof(ea->arp_sha));
346 	} else {
347 		ARPTAB_LOOK(at, itaddr.s_addr);
348 		if (at == NULL || (at->at_flags & ATF_PUBL) == 0)
349 			goto out;
350 		bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha,
351 		    sizeof(ea->arp_sha));
352 		bcopy((caddr_t)at->at_enaddr, (caddr_t)ea->arp_sha,
353 		    sizeof(ea->arp_sha));
354 	}
355 
356 	bcopy((caddr_t)ea->arp_spa, (caddr_t)ea->arp_tpa,
357 	    sizeof(ea->arp_spa));
358 	bcopy((caddr_t)&itaddr, (caddr_t)ea->arp_spa,
359 	    sizeof(ea->arp_spa));
360 	ea->arp_op = htons(ARPOP_REPLY);
361 	/*
362 	 * If incoming packet was an IP reply,
363 	 * we are sending a reply for type IPTRAILERS.
364 	 * If we are sending a reply for type IP
365 	 * and we want to receive trailers,
366 	 * send a trailer reply as well.
367 	 */
368 	if (op == ARPOP_REPLY)
369 		ea->arp_pro = htons(ETHERTYPE_IPTRAILERS);
370 	else if (proto == ETHERTYPE_IP &&
371 	    (ac->ac_if.if_flags & IFF_NOTRAILERS) == 0)
372 		mcopy = m_copy(m, 0, (int)M_COPYALL);
373 	eh = (struct ether_header *)sa.sa_data;
374 	bcopy((caddr_t)ea->arp_tha, (caddr_t)eh->ether_dhost,
375 	    sizeof(eh->ether_dhost));
376 	eh->ether_type = ETHERTYPE_ARP;
377 	sa.sa_family = AF_UNSPEC;
378 	(*ac->ac_if.if_output)(&ac->ac_if, m, &sa);
379 	if (mcopy) {
380 		ea = mtod(mcopy, struct ether_arp *);
381 		ea->arp_pro = htons(ETHERTYPE_IPTRAILERS);
382 		(*ac->ac_if.if_output)(&ac->ac_if, mcopy, &sa);
383 	}
384 	return;
385 out:
386 	m_freem(m);
387 	return;
388 }
389 
390 /*
391  * Free an arptab entry.
392  */
393 arptfree(at)
394 	register struct arptab *at;
395 {
396 	int s = splimp();
397 
398 	if (at->at_hold)
399 		m_freem(at->at_hold);
400 	at->at_hold = 0;
401 	at->at_timer = at->at_flags = 0;
402 	at->at_iaddr.s_addr = 0;
403 	splx(s);
404 }
405 
406 /*
407  * Enter a new address in arptab, pushing out the oldest entry
408  * from the bucket if there is no room.
409  * This always succeeds since no bucket can be completely filled
410  * with permanent entries (except from arpioctl when testing whether
411  * another permanent entry will fit).
412  */
413 struct arptab *
414 arptnew(addr)
415 	struct in_addr *addr;
416 {
417 	register n;
418 	int oldest = -1;
419 	register struct arptab *at, *ato = NULL;
420 	static int first = 1;
421 
422 	if (first) {
423 		first = 0;
424 		timeout(arptimer, (caddr_t)0, hz);
425 	}
426 	at = &arptab[ARPTAB_HASH(addr->s_addr) * ARPTAB_BSIZ];
427 	for (n = 0; n < ARPTAB_BSIZ; n++,at++) {
428 		if (at->at_flags == 0)
429 			goto out;	 /* found an empty entry */
430 		if (at->at_flags & ATF_PERM)
431 			continue;
432 		if (at->at_timer > oldest) {
433 			oldest = at->at_timer;
434 			ato = at;
435 		}
436 	}
437 	if (ato == NULL)
438 		return (NULL);
439 	at = ato;
440 	arptfree(at);
441 out:
442 	at->at_iaddr = *addr;
443 	at->at_flags = ATF_INUSE;
444 	return (at);
445 }
446 
447 arpioctl(cmd, data)
448 	int cmd;
449 	caddr_t data;
450 {
451 	register struct arpreq *ar = (struct arpreq *)data;
452 	register struct arptab *at;
453 	register struct sockaddr_in *sin;
454 	int s;
455 
456 	if (ar->arp_pa.sa_family != AF_INET ||
457 	    ar->arp_ha.sa_family != AF_UNSPEC)
458 		return (EAFNOSUPPORT);
459 	sin = (struct sockaddr_in *)&ar->arp_pa;
460 	s = splimp();
461 	ARPTAB_LOOK(at, sin->sin_addr.s_addr);
462 	if (at == NULL) {		/* not found */
463 		if (cmd != SIOCSARP) {
464 			splx(s);
465 			return (ENXIO);
466 		}
467 		if (ifa_ifwithnet(&ar->arp_pa) == NULL) {
468 			splx(s);
469 			return (ENETUNREACH);
470 		}
471 	}
472 	switch (cmd) {
473 
474 	case SIOCSARP:		/* set entry */
475 		if (at == NULL) {
476 			at = arptnew(&sin->sin_addr);
477 			if (ar->arp_flags & ATF_PERM) {
478 			/* never make all entries in a bucket permanent */
479 				register struct arptab *tat;
480 
481 				/* try to re-allocate */
482 				tat = arptnew(&sin->sin_addr);
483 				if (tat == NULL) {
484 					arptfree(at);
485 					splx(s);
486 					return (EADDRNOTAVAIL);
487 				}
488 				arptfree(tat);
489 			}
490 		}
491 		bcopy((caddr_t)ar->arp_ha.sa_data, (caddr_t)at->at_enaddr,
492 		    sizeof(at->at_enaddr));
493 		at->at_flags = ATF_COM | ATF_INUSE |
494 			(ar->arp_flags & (ATF_PERM|ATF_PUBL));
495 		at->at_timer = 0;
496 		break;
497 
498 	case SIOCDARP:		/* delete entry */
499 		arptfree(at);
500 		break;
501 
502 	case SIOCGARP:		/* get entry */
503 		bcopy((caddr_t)at->at_enaddr, (caddr_t)ar->arp_ha.sa_data,
504 		    sizeof(at->at_enaddr));
505 		ar->arp_flags = at->at_flags;
506 		break;
507 	}
508 	splx(s);
509 	return (0);
510 }
511 
512 /*
513  * Convert Ethernet address to printable (loggable) representation.
514  */
515 char *
516 ether_sprintf(ap)
517 	register u_char *ap;
518 {
519 	register i;
520 	static char etherbuf[18];
521 	register char *cp = etherbuf;
522 	static char digits[] = "0123456789abcdef";
523 
524 	for (i = 0; i < 6; i++) {
525 		*cp++ = digits[*ap >> 4];
526 		*cp++ = digits[*ap++ & 0xf];
527 		*cp++ = ':';
528 	}
529 	*--cp = 0;
530 	return (etherbuf);
531 }
532