xref: /netbsd-src/sys/netinet/if_arp.c (revision 7c7c171d130af9949261bc7dce2150a03c3d239c)
1 /*	$NetBSD: if_arp.c,v 1.45 1998/02/15 18:24:23 tls Exp $	*/
2 
3 /*-
4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Public Access Networks Corporation ("Panix").  It was developed under
9  * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the NetBSD
22  *	Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 /*
41  * Copyright (c) 1982, 1986, 1988, 1993
42  *	The Regents of the University of California.  All rights reserved.
43  *
44  * Redistribution and use in source and binary forms, with or without
45  * modification, are permitted provided that the following conditions
46  * are met:
47  * 1. Redistributions of source code must retain the above copyright
48  *    notice, this list of conditions and the following disclaimer.
49  * 2. Redistributions in binary form must reproduce the above copyright
50  *    notice, this list of conditions and the following disclaimer in the
51  *    documentation and/or other materials provided with the distribution.
52  * 3. All advertising materials mentioning features or use of this software
53  *    must display the following acknowledgement:
54  *	This product includes software developed by the University of
55  *	California, Berkeley and its contributors.
56  * 4. Neither the name of the University nor the names of its contributors
57  *    may be used to endorse or promote products derived from this software
58  *    without specific prior written permission.
59  *
60  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
61  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
62  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
63  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
64  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
66  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
67  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
69  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70  * SUCH DAMAGE.
71  *
72  *	@(#)if_ether.c	8.2 (Berkeley) 9/26/94
73  */
74 
75 /*
76  * Ethernet address resolution protocol.
77  * TODO:
78  *	add "inuse/lock" bit (or ref. count) along with valid bit
79  */
80 
81 #ifdef INET
82 
83 #include <sys/param.h>
84 #include <sys/systm.h>
85 #include <sys/malloc.h>
86 #include <sys/mbuf.h>
87 #include <sys/socket.h>
88 #include <sys/time.h>
89 #include <sys/kernel.h>
90 #include <sys/errno.h>
91 #include <sys/ioctl.h>
92 #include <sys/syslog.h>
93 #include <sys/proc.h>
94 
95 #include <net/ethertypes.h>
96 #include <net/if.h>
97 #include <net/if_dl.h>
98 #include <net/route.h>
99 
100 #include <netinet/in.h>
101 #include <netinet/in_systm.h>
102 #include <netinet/in_var.h>
103 #include <netinet/ip.h>
104 #include <netinet/if_inarp.h>
105 
106 #include "loop.h"
107 
108 #define SIN(s) ((struct sockaddr_in *)s)
109 #define SDL(s) ((struct sockaddr_dl *)s)
110 #define SRP(s) ((struct sockaddr_inarp *)s)
111 
112 /*
113  * ARP trailer negotiation.  Trailer protocol is not IP specific,
114  * but ARP request/response use IP addresses.
115  */
116 #define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL
117 
118 /* timer values */
119 int	arpt_prune = (5*60*1);	/* walk list every 5 minutes */
120 int	arpt_keep = (20*60);	/* once resolved, good for 20 more minutes */
121 int	arpt_down = 20;		/* once declared down, don't send for 20 secs */
122 #define	rt_expire rt_rmx.rmx_expire
123 
124 static	void arprequest __P((struct ifnet *,
125 	    struct in_addr *, struct in_addr *, u_int8_t *));
126 static	void arptfree __P((struct llinfo_arp *));
127 static	void arptimer __P((void *));
128 static	struct llinfo_arp *arplookup __P((struct in_addr *, int, int));
129 static	void in_arpinput __P((struct mbuf *));
130 
131 extern	struct ifnet loif[NLOOP];
132 LIST_HEAD(, llinfo_arp) llinfo_arp;
133 struct	ifqueue arpintrq = {0, 0, 0, 50};
134 int	arp_inuse, arp_allocated, arp_intimer;
135 int	arp_maxtries = 5;
136 int	useloopback = 1;	/* use loopback interface for local traffic */
137 int	arpinit_done = 0;
138 
139 /* revarp state */
140 static struct	in_addr myip, srv_ip;
141 static int	myip_initialized = 0;
142 static int	revarp_in_progress = 0;
143 static struct	ifnet *myip_ifp = NULL;
144 
145 #ifdef DDB
146 static void db_print_sa __P((struct sockaddr *));
147 static void db_print_ifa __P((struct ifaddr *));
148 static void db_print_llinfo __P((caddr_t));
149 static int db_show_radix_node __P((struct radix_node *, void *));
150 #endif
151 
152 /*
153  * this should be elsewhere.
154  */
155 
156 static char *
157 lla_snprintf __P((u_int8_t *, int));
158 
159 static char *
160 lla_snprintf(adrp, len)
161 	u_int8_t *adrp;
162 	int len;
163 {
164 	static char buf[16*3];
165 	static const char hexdigits[] = {
166 	    '0','1','2','3','4','5','6','7',
167 	    '8','9','a','b','c','d','e','f'
168 	};
169 
170 	int i;
171 	char *p;
172 
173 	p = buf;
174 
175 	*p++ = hexdigits[(*adrp)>>4];
176 	*p++ = hexdigits[(*adrp++)&0xf];
177 
178 	for (i=1; i<len && i<16; i++) {
179 		*p++ = ':';
180 		*p++ = hexdigits[(*adrp)>>4];
181 		*p++ = hexdigits[(*adrp++)&0xf];
182 	}
183 
184 	*p = 0;
185 	return buf;
186 }
187 
188 /*
189  * Timeout routine.  Age arp_tab entries periodically.
190  */
191 /* ARGSUSED */
192 static void
193 arptimer(arg)
194 	void *arg;
195 {
196 	int s;
197 	register struct llinfo_arp *la, *nla;
198 
199 	s = splsoftnet();
200 	timeout(arptimer, NULL, arpt_prune * hz);
201 	for (la = llinfo_arp.lh_first; la != 0; la = nla) {
202 		register struct rtentry *rt = la->la_rt;
203 
204 		nla = la->la_list.le_next;
205 		if (rt->rt_expire && rt->rt_expire <= time.tv_sec)
206 			arptfree(la); /* timer has expired; clear */
207 	}
208 	splx(s);
209 }
210 
211 /*
212  * Parallel to llc_rtrequest.
213  */
214 void
215 arp_rtrequest(req, rt, sa)
216 	int req;
217 	register struct rtentry *rt;
218 	struct sockaddr *sa;
219 {
220 	register struct sockaddr *gate = rt->rt_gateway;
221 	register struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
222 	static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
223 
224 	if (!arpinit_done) {
225 		arpinit_done = 1;
226 		/*
227 		 * We generate expiration times from time.tv_sec
228 		 * so avoid accidently creating permanent routes.
229 		 */
230 		if (time.tv_sec == 0) {
231 			time.tv_sec++;
232 		}
233 		timeout(arptimer, (caddr_t)0, hz);
234 	}
235 	if (rt->rt_flags & RTF_GATEWAY)
236 		return;
237 	switch (req) {
238 
239 	case RTM_ADD:
240 		/*
241 		 * XXX: If this is a manually added route to interface
242 		 * such as older version of routed or gated might provide,
243 		 * restore cloning bit.
244 		 */
245 		if ((rt->rt_flags & RTF_HOST) == 0 &&
246 		    SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
247 			rt->rt_flags |= RTF_CLONING;
248 		if (rt->rt_flags & RTF_CLONING) {
249 			/*
250 			 * Case 1: This route should come from a route to iface.
251 			 */
252 			rt_setgate(rt, rt_key(rt),
253 					(struct sockaddr *)&null_sdl);
254 			gate = rt->rt_gateway;
255 			SDL(gate)->sdl_type = rt->rt_ifp->if_type;
256 			SDL(gate)->sdl_index = rt->rt_ifp->if_index;
257 			/*
258 			 * Give this route an expiration time, even though
259 			 * it's a "permanent" route, so that routes cloned
260 			 * from it do not need their expiration time set.
261 			 */
262 			rt->rt_expire = time.tv_sec;
263 			break;
264 		}
265 		/* Announce a new entry if requested. */
266 		if (rt->rt_flags & RTF_ANNOUNCE)
267 			arprequest(rt->rt_ifp,
268 			    &SIN(rt_key(rt))->sin_addr,
269 			    &SIN(rt_key(rt))->sin_addr,
270 			    (u_char *)LLADDR(SDL(gate)));
271 		/*FALLTHROUGH*/
272 	case RTM_RESOLVE:
273 		if (gate->sa_family != AF_LINK ||
274 		    gate->sa_len < sizeof(null_sdl)) {
275 			log(LOG_DEBUG, "arp_rtrequest: bad gateway value\n");
276 			break;
277 		}
278 		SDL(gate)->sdl_type = rt->rt_ifp->if_type;
279 		SDL(gate)->sdl_index = rt->rt_ifp->if_index;
280 		if (la != 0)
281 			break; /* This happens on a route change */
282 		/*
283 		 * Case 2:  This route may come from cloning, or a manual route
284 		 * add with a LL address.
285 		 */
286 		R_Malloc(la, struct llinfo_arp *, sizeof(*la));
287 		rt->rt_llinfo = (caddr_t)la;
288 		if (la == 0) {
289 			log(LOG_DEBUG, "arp_rtrequest: malloc failed\n");
290 			break;
291 		}
292 		arp_inuse++, arp_allocated++;
293 		Bzero(la, sizeof(*la));
294 		la->la_rt = rt;
295 		rt->rt_flags |= RTF_LLINFO;
296 		LIST_INSERT_HEAD(&llinfo_arp, la, la_list);
297 		if (in_hosteq(SIN(rt_key(rt))->sin_addr,
298 		    (IA_SIN(rt->rt_ifa))->sin_addr)) {
299 			/*
300 			 * This test used to be
301 			 *	if (loif.if_flags & IFF_UP)
302 			 * It allowed local traffic to be forced through
303 			 * the hardware by configuring the loopback down.
304 			 * However, it causes problems during network
305 			 * configuration for boards that can't receive
306 			 * packets they send.  It is now necessary to clear
307 			 * "useloopback" and remove the route to force
308 			 * traffic out to the hardware.
309 			 */
310 			rt->rt_expire = 0;
311 			Bcopy(LLADDR(rt->rt_ifp->if_sadl),
312 			    LLADDR(SDL(gate)),
313 			    SDL(gate)->sdl_alen =
314 			    rt->rt_ifp->if_data.ifi_addrlen);
315 			if (useloopback)
316 				rt->rt_ifp = &loif[0];
317 		}
318 		break;
319 
320 	case RTM_DELETE:
321 		if (la == 0)
322 			break;
323 		arp_inuse--;
324 		LIST_REMOVE(la, la_list);
325 		rt->rt_llinfo = 0;
326 		rt->rt_flags &= ~RTF_LLINFO;
327 		if (la->la_hold)
328 			m_freem(la->la_hold);
329 		Free((caddr_t)la);
330 	}
331 }
332 
333 /*
334  * Broadcast an ARP request. Caller specifies:
335  *	- arp header source ip address
336  *	- arp header target ip address
337  *	- arp header source ethernet address
338  */
339 static void
340 arprequest(ifp, sip, tip, enaddr)
341 	register struct ifnet *ifp;
342 	register struct in_addr *sip, *tip;
343 	register u_int8_t *enaddr;
344 {
345 	register struct mbuf *m;
346 	struct arphdr *ah;
347 	struct sockaddr sa;
348 
349 	if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
350 		return;
351 	m->m_len = sizeof(*ah) + 2*sizeof(struct in_addr) +
352 	    2*ifp->if_data.ifi_addrlen;
353 	m->m_pkthdr.len = m->m_len;
354 	MH_ALIGN(m, m->m_len);
355 	ah = mtod(m, struct arphdr *);
356 	bzero((caddr_t)ah, m->m_len);
357 	ah->ar_pro = htons(ETHERTYPE_IP);
358 	ah->ar_hln = ifp->if_data.ifi_addrlen;	/* hardware address length */
359 	ah->ar_pln = sizeof(struct in_addr);	/* protocol address length */
360 	ah->ar_op = htons(ARPOP_REQUEST);
361 	bcopy((caddr_t)enaddr, (caddr_t)ar_sha(ah), ah->ar_hln);
362 	bcopy((caddr_t)sip, (caddr_t)ar_spa(ah), ah->ar_pln);
363 	bcopy((caddr_t)tip, (caddr_t)ar_tpa(ah), ah->ar_pln);
364 	sa.sa_family = AF_ARP;
365 	sa.sa_len = 2;
366 	m->m_flags |= M_BCAST;
367 	(*ifp->if_output)(ifp, m, &sa, (struct rtentry *)0);
368 }
369 
370 /*
371  * Resolve an IP address into an ethernet address.  If success,
372  * desten is filled in.  If there is no entry in arptab,
373  * set one up and broadcast a request for the IP address.
374  * Hold onto this mbuf and resend it once the address
375  * is finally resolved.  A return value of 1 indicates
376  * that desten has been filled in and the packet should be sent
377  * normally; a 0 return indicates that the packet has been
378  * taken over here, either now or for later transmission.
379  */
380 int
381 arpresolve(ifp, rt, m, dst, desten)
382 	register struct ifnet *ifp;
383 	register struct rtentry *rt;
384 	struct mbuf *m;
385 	register struct sockaddr *dst;
386 	register u_char *desten;
387 {
388 	register struct llinfo_arp *la;
389 	struct sockaddr_dl *sdl;
390 
391 	if (rt)
392 		la = (struct llinfo_arp *)rt->rt_llinfo;
393 	else {
394 		if ((la = arplookup(&SIN(dst)->sin_addr, 1, 0)) != NULL)
395 			rt = la->la_rt;
396 	}
397 	if (la == 0 || rt == 0) {
398 		log(LOG_DEBUG, "arpresolve: can't allocate llinfo\n");
399 		m_freem(m);
400 		return (0);
401 	}
402 	sdl = SDL(rt->rt_gateway);
403 	/*
404 	 * Check the address family and length is valid, the address
405 	 * is resolved; otherwise, try to resolve.
406 	 */
407 	if ((rt->rt_expire == 0 || rt->rt_expire > time.tv_sec) &&
408 	    sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {
409 		bcopy(LLADDR(sdl), desten,
410 		    min(sdl->sdl_alen, ifp->if_data.ifi_addrlen));
411 		return 1;
412 	}
413 	/*
414 	 * There is an arptab entry, but no ethernet address
415 	 * response yet.  Replace the held mbuf with this
416 	 * latest one.
417 	 */
418 	if (la->la_hold)
419 		m_freem(la->la_hold);
420 	la->la_hold = m;
421 	/*
422 	 * Re-send the ARP request when appropriate.
423 	 */
424 #ifdef	DIAGNOSTIC
425 	if (rt->rt_expire == 0) {
426 		/* This should never happen. (Should it? -gwr) */
427 		printf("arpresolve: unresolved and rt_expire == 0\n");
428 		/* Set expiration time to now (expired). */
429 		rt->rt_expire = time.tv_sec;
430 	}
431 #endif
432 	if (rt->rt_expire) {
433 		rt->rt_flags &= ~RTF_REJECT;
434 		if (la->la_asked == 0 || rt->rt_expire != time.tv_sec) {
435 			rt->rt_expire = time.tv_sec;
436 			if (la->la_asked++ < arp_maxtries)
437 				arprequest(ifp,
438 				    &SIN(rt->rt_ifa->ifa_addr)->sin_addr,
439 				    &SIN(dst)->sin_addr,
440 				    LLADDR(ifp->if_sadl));
441 			else {
442 				rt->rt_flags |= RTF_REJECT;
443 				rt->rt_expire += arpt_down;
444 				la->la_asked = 0;
445 			}
446 		}
447 	}
448 	return (0);
449 }
450 
451 /*
452  * Common length and type checks are done here,
453  * then the protocol-specific routine is called.
454  */
455 void
456 arpintr()
457 {
458 	register struct mbuf *m;
459 	register struct arphdr *ar;
460 	int s;
461 
462 	while (arpintrq.ifq_head) {
463 		s = splimp();
464 		IF_DEQUEUE(&arpintrq, m);
465 		splx(s);
466 		if (m == 0 || (m->m_flags & M_PKTHDR) == 0)
467 			panic("arpintr");
468 
469 		if (m->m_len >= sizeof(struct arphdr) &&
470 		    (ar = mtod(m, struct arphdr *)) &&
471 		    /* XXX ntohs(ar->ar_hrd) == ARPHRD_ETHER && */
472 		    m->m_len >=
473 		      sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln))
474 			switch (ntohs(ar->ar_pro)) {
475 
476 			case ETHERTYPE_IP:
477 			case ETHERTYPE_IPTRAILERS:
478 				in_arpinput(m);
479 				continue;
480 			}
481 		m_freem(m);
482 	}
483 }
484 
485 /*
486  * ARP for Internet protocols on 10 Mb/s Ethernet.
487  * Algorithm is that given in RFC 826.
488  * In addition, a sanity check is performed on the sender
489  * protocol address, to catch impersonators.
490  * We no longer handle negotiations for use of trailer protocol:
491  * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent
492  * along with IP replies if we wanted trailers sent to us,
493  * and also sent them in response to IP replies.
494  * This allowed either end to announce the desire to receive
495  * trailer packets.
496  * We no longer reply to requests for ETHERTYPE_TRAIL protocol either,
497  * but formerly didn't normally send requests.
498  */
499 static void
500 in_arpinput(m)
501 	struct mbuf *m;
502 {
503 	struct arphdr *ah;
504 	register struct ifnet *ifp = m->m_pkthdr.rcvif;
505 	register struct llinfo_arp *la = 0;
506 	register struct rtentry *rt;
507 	struct in_ifaddr *ia;
508 	struct sockaddr_dl *sdl;
509 	struct sockaddr sa;
510 	struct in_addr isaddr, itaddr, myaddr;
511 	int op;
512 
513 	ah = mtod(m, struct arphdr *);
514 	op = ntohs(ah->ar_op);
515 	bcopy((caddr_t)ar_spa(ah), (caddr_t)&isaddr, sizeof (isaddr));
516 	bcopy((caddr_t)ar_tpa(ah), (caddr_t)&itaddr, sizeof (itaddr));
517 
518 	/*
519 	 * If the target IP address is zero, ignore the packet.
520 	 * This prevents the code below from tring to answer
521 	 * when we are using IP address zero (booting).
522 	 */
523 	if (in_nullhost(itaddr))
524 		goto out;
525 
526 	/*
527 	 * If the source IP address is zero, this is most likely a
528 	 * confused host trying to use IP address zero. (Windoze?)
529 	 * XXX: Should we bother trying to reply to these?
530 	 */
531 	if (in_nullhost(isaddr))
532 		goto out;
533 
534 	/*
535 	 * Search for a matching interface address
536 	 * or any address on the interface to use
537 	 * as a dummy address in the rest of this function
538 	 */
539 	INADDR_TO_IA(itaddr, ia);
540 	if (ia == NULL) {
541 		INADDR_TO_IA(isaddr, ia);
542 			if (ia == NULL) {
543 				IFP_TO_IA(ifp, ia);
544 				if (ia == NULL) goto out;
545 			}
546 	}
547 	myaddr = ia->ia_addr.sin_addr;
548 
549 	if (!bcmp((caddr_t)ar_sha(ah), LLADDR(ifp->if_sadl),
550 	    ifp->if_data.ifi_addrlen))
551 		goto out;	/* it's from me, ignore it. */
552 
553 	if (!bcmp((caddr_t)ar_sha(ah), (caddr_t)ifp->if_broadcastaddr,
554 	    ifp->if_data.ifi_addrlen)) {
555 		log(LOG_ERR,
556 		    "%s: arp: link address is broadcast for IP address %x!\n",
557 		    ifp->if_xname, ntohl(isaddr.s_addr));
558 		goto out;
559 	}
560 
561 	if (in_hosteq(isaddr, myaddr)) {
562 		log(LOG_ERR,
563 		   "duplicate IP address %08x sent from link address %s\n",
564 		   ntohl(isaddr.s_addr), lla_snprintf(ar_sha(ah), ah->ar_hln));
565 		itaddr = myaddr;
566 		goto reply;
567 	}
568 	la = arplookup(&isaddr, in_hosteq(itaddr, myaddr), 0);
569 	if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) {
570 		if (sdl->sdl_alen &&
571 		    bcmp((caddr_t)ar_sha(ah), LLADDR(sdl), sdl->sdl_alen))
572 			log(LOG_INFO, "arp info overwritten for %08x by %s\n",
573 			    ntohl(isaddr.s_addr),
574 			    lla_snprintf(ar_sha(ah), ah->ar_hln));
575 		/*
576 		 * sanity check for the address length.
577 		 * XXX this does not work for protocols with variable address
578 		 * length. -is
579 		 */
580 		if (sdl->sdl_alen &&
581 		    sdl->sdl_alen != ah->ar_hln) {
582 			log(LOG_WARNING,
583 			    "arp from %08x: new addr len %d, was %d",
584 			    ntohl(isaddr.s_addr), ah->ar_hln, sdl->sdl_alen);
585 		}
586 		if (ifp->if_data.ifi_addrlen != ah->ar_hln) {
587 			log(LOG_WARNING,
588 			    "arp from %08x: addr len: new %d, i/f %d (ignored)",
589 			    ntohl(isaddr.s_addr), ah->ar_hln,
590 			    ifp->if_data.ifi_addrlen);
591 			goto reply;
592 		}
593 		bcopy((caddr_t)ar_sha(ah), LLADDR(sdl),
594 		    sdl->sdl_alen = ah->ar_hln);
595 		if (rt->rt_expire)
596 			rt->rt_expire = time.tv_sec + arpt_keep;
597 		rt->rt_flags &= ~RTF_REJECT;
598 		la->la_asked = 0;
599 		if (la->la_hold) {
600 			(*ifp->if_output)(ifp, la->la_hold,
601 				rt_key(rt), rt);
602 			la->la_hold = 0;
603 		}
604 	}
605 reply:
606 	if (op != ARPOP_REQUEST) {
607 	out:
608 		m_freem(m);
609 		return;
610 	}
611 	if (in_hosteq(itaddr, myaddr)) {
612 		/* I am the target */
613 		bcopy((caddr_t)ar_sha(ah), (caddr_t)ar_tha(ah), ah->ar_hln);
614 		bcopy(LLADDR(ifp->if_sadl), (caddr_t)ar_sha(ah), ah->ar_hln);
615 	} else {
616 		la = arplookup(&itaddr, 0, SIN_PROXY);
617 		if (la == 0)
618 			goto out;
619 		rt = la->la_rt;
620 		bcopy((caddr_t)ar_sha(ah), (caddr_t)ar_tha(ah), ah->ar_hln);
621 		sdl = SDL(rt->rt_gateway);
622 		bcopy(LLADDR(sdl), (caddr_t)ar_sha(ah), ah->ar_hln);
623 	}
624 
625 	bcopy((caddr_t)ar_spa(ah), (caddr_t)ar_tpa(ah), ah->ar_pln);
626 	bcopy((caddr_t)&itaddr, (caddr_t)ar_spa(ah), ah->ar_pln);
627 	ah->ar_op = htons(ARPOP_REPLY);
628 	ah->ar_pro = htons(ETHERTYPE_IP); /* let's be sure! */
629 	m->m_flags &= ~(M_BCAST|M_MCAST); /* never reply by broadcast */
630 	sa.sa_family = AF_ARP;
631 	sa.sa_len = 2;
632 	(*ifp->if_output)(ifp, m, &sa, (struct rtentry *)0);
633 	return;
634 }
635 
636 /*
637  * Free an arp entry.
638  */
639 static void
640 arptfree(la)
641 	register struct llinfo_arp *la;
642 {
643 	register struct rtentry *rt = la->la_rt;
644 	register struct sockaddr_dl *sdl;
645 
646 	if (rt == 0)
647 		panic("arptfree");
648 	if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) &&
649 	    sdl->sdl_family == AF_LINK) {
650 		sdl->sdl_alen = 0;
651 		la->la_asked = 0;
652 		rt->rt_flags &= ~RTF_REJECT;
653 		return;
654 	}
655 	rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, rt_mask(rt),
656 	    0, (struct rtentry **)0);
657 }
658 
659 /*
660  * Lookup or enter a new address in arptab.
661  */
662 static struct llinfo_arp *
663 arplookup(addr, create, proxy)
664 	struct in_addr *addr;
665 	int create, proxy;
666 {
667 	register struct rtentry *rt;
668 	static struct sockaddr_inarp sin;
669 
670 	sin.sin_len = sizeof(sin);
671 	sin.sin_family = AF_INET;
672 	sin.sin_addr = *addr;
673 	sin.sin_other = proxy ? SIN_PROXY : 0;
674 	rt = rtalloc1(sintosa(&sin), create);
675 	if (rt == 0)
676 		return (0);
677 	rt->rt_refcnt--;
678 	if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 ||
679 	    rt->rt_gateway->sa_family != AF_LINK) {
680 		if (create)
681 			log(LOG_DEBUG, "arplookup: unable to enter address for %x\n",
682 			    ntohl(addr->s_addr));
683 		return (0);
684 	}
685 	return ((struct llinfo_arp *)rt->rt_llinfo);
686 }
687 
688 int
689 arpioctl(cmd, data)
690 	u_long cmd;
691 	caddr_t data;
692 {
693 
694 	return (EOPNOTSUPP);
695 }
696 
697 void
698 arp_ifinit(ifp, ifa)
699 	struct ifnet *ifp;
700 	struct ifaddr *ifa;
701 {
702 	struct in_addr *ip;
703 
704 	/*
705 	 * Warn the user if another station has this IP address,
706 	 * but only if the interface IP address is not zero.
707 	 */
708 	ip = &IA_SIN(ifa)->sin_addr;
709 	if (!in_nullhost(*ip))
710 		arprequest(ifp, ip, ip, LLADDR(ifp->if_sadl));
711 
712 	ifa->ifa_rtrequest = arp_rtrequest;
713 	ifa->ifa_flags |= RTF_CLONING;
714 }
715 
716 /*
717  * Called from 10 Mb/s Ethernet interrupt handlers
718  * when ether packet type ETHERTYPE_REVARP
719  * is received.  Common length and type checks are done here,
720  * then the protocol-specific routine is called.
721  */
722 void
723 revarpinput(m)
724 	struct mbuf *m;
725 {
726 	struct arphdr *ar;
727 
728 	if (m->m_len < sizeof(struct arphdr))
729 		goto out;
730 	ar = mtod(m, struct arphdr *);
731 #if 0 /* XXX I don't think we need this... and it will prevent other LL */
732 	if (ntohs(ar->ar_hrd) != ARPHRD_ETHER)
733 		goto out;
734 #endif
735 	if (m->m_len < sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln))
736 		goto out;
737 	switch (ntohs(ar->ar_pro)) {
738 
739 	case ETHERTYPE_IP:
740 	case ETHERTYPE_IPTRAILERS:
741 		in_revarpinput(m);
742 		return;
743 
744 	default:
745 		break;
746 	}
747 out:
748 	m_freem(m);
749 }
750 
751 /*
752  * RARP for Internet protocols on 10 Mb/s Ethernet.
753  * Algorithm is that given in RFC 903.
754  * We are only using for bootstrap purposes to get an ip address for one of
755  * our interfaces.  Thus we support no user-interface.
756  *
757  * Since the contents of the RARP reply are specific to the interface that
758  * sent the request, this code must ensure that they are properly associated.
759  *
760  * Note: also supports ARP via RARP packets, per the RFC.
761  */
762 void
763 in_revarpinput(m)
764 	struct mbuf *m;
765 {
766 	struct ifnet *ifp;
767 	struct arphdr *ah;
768 	int op;
769 
770 	ah = mtod(m, struct arphdr *);
771 	op = ntohs(ah->ar_op);
772 	switch (op) {
773 	case ARPOP_REQUEST:
774 	case ARPOP_REPLY:	/* per RFC */
775 		in_arpinput(m);
776 		return;
777 	case ARPOP_REVREPLY:
778 		break;
779 	case ARPOP_REVREQUEST:	/* handled by rarpd(8) */
780 	default:
781 		goto out;
782 	}
783 	if (!revarp_in_progress)
784 		goto out;
785 	ifp = m->m_pkthdr.rcvif;
786 	if (ifp != myip_ifp) /* !same interface */
787 		goto out;
788 	if (myip_initialized)
789 		goto wake;
790 	if (bcmp(ar_tha(ah), LLADDR(ifp->if_sadl), ifp->if_sadl->sdl_alen))
791 		goto out;
792 	bcopy((caddr_t)ar_spa(ah), (caddr_t)&srv_ip, sizeof(srv_ip));
793 	bcopy((caddr_t)ar_tpa(ah), (caddr_t)&myip, sizeof(myip));
794 	myip_initialized = 1;
795 wake:	/* Do wakeup every time in case it was missed. */
796 	wakeup((caddr_t)&myip);
797 
798 out:
799 	m_freem(m);
800 }
801 
802 /*
803  * Send a RARP request for the ip address of the specified interface.
804  * The request should be RFC 903-compliant.
805  */
806 void
807 revarprequest(ifp)
808 	struct ifnet *ifp;
809 {
810 	struct sockaddr sa;
811 	struct mbuf *m;
812 	struct arphdr *ah;
813 
814 	if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
815 		return;
816 	m->m_len = sizeof(*ah) + 2*sizeof(struct in_addr) +
817 	    2*ifp->if_data.ifi_addrlen;
818 	m->m_pkthdr.len = m->m_len;
819 	MH_ALIGN(m, m->m_len);
820 	ah = mtod(m, struct arphdr *);
821 	bzero((caddr_t)ah, m->m_len);
822 	ah->ar_pro = htons(ETHERTYPE_IP);
823 	ah->ar_hln = ifp->if_data.ifi_addrlen;	/* hardware address length */
824 	ah->ar_pln = sizeof(struct in_addr);	/* protocol address length */
825 	ah->ar_op = htons(ARPOP_REVREQUEST);
826 
827 	bcopy(LLADDR(ifp->if_sadl), (caddr_t)ar_sha(ah), ah->ar_hln);
828 	bcopy(LLADDR(ifp->if_sadl), (caddr_t)ar_tha(ah), ah->ar_hln);
829 
830 	sa.sa_family = AF_ARP;
831 	sa.sa_len = 2;
832 	m->m_flags |= M_BCAST;
833 	(*ifp->if_output)(ifp, m, &sa, (struct rtentry *)0);
834 
835 }
836 
837 /*
838  * RARP for the ip address of the specified interface, but also
839  * save the ip address of the server that sent the answer.
840  * Timeout if no response is received.
841  */
842 int
843 revarpwhoarewe(ifp, serv_in, clnt_in)
844 	struct ifnet *ifp;
845 	struct in_addr *serv_in;
846 	struct in_addr *clnt_in;
847 {
848 	int result, count = 20;
849 
850 	if (!myip_initialized) {
851 		myip_ifp = ifp;
852 		revarp_in_progress = 1;
853 		while (count--) {
854 			revarprequest(ifp);
855 			result = tsleep((caddr_t)&myip, PSOCK, "revarp", hz/2);
856 			if (result != EWOULDBLOCK)
857 				break;
858 		}
859 		revarp_in_progress = 0;
860 	}
861 	if (!myip_initialized)
862 		return ENETUNREACH;
863 
864 	bcopy((caddr_t)&srv_ip, serv_in, sizeof(*serv_in));
865 	bcopy((caddr_t)&myip, clnt_in, sizeof(*clnt_in));
866 	return 0;
867 }
868 
869 /* For compatibility: only saves interface address. */
870 int
871 revarpwhoami(in, ifp)
872 	struct in_addr *in;
873 	struct ifnet *ifp;
874 {
875 	struct in_addr server;
876 	return (revarpwhoarewe(ifp, &server, in));
877 }
878 
879 
880 #ifdef DDB
881 
882 #include <machine/db_machdep.h>
883 #include <ddb/db_interface.h>
884 #include <ddb/db_output.h>
885 static void
886 db_print_sa(sa)
887 	struct sockaddr *sa;
888 {
889 	int len;
890 	u_char *p;
891 
892 	if (sa == 0) {
893 		db_printf("[NULL]");
894 		return;
895 	}
896 
897 	p = (u_char*)sa;
898 	len = sa->sa_len;
899 	db_printf("[");
900 	while (len > 0) {
901 		db_printf("%d", *p);
902 		p++; len--;
903 		if (len) db_printf(",");
904 	}
905 	db_printf("]\n");
906 }
907 static void
908 db_print_ifa(ifa)
909 	struct ifaddr *ifa;
910 {
911 	if (ifa == 0)
912 		return;
913 	db_printf("  ifa_addr=");
914 	db_print_sa(ifa->ifa_addr);
915 	db_printf("  ifa_dsta=");
916 	db_print_sa(ifa->ifa_dstaddr);
917 	db_printf("  ifa_mask=");
918 	db_print_sa(ifa->ifa_netmask);
919 	db_printf("  flags=0x%x,refcnt=%d,metric=%d\n",
920 			  ifa->ifa_flags,
921 			  ifa->ifa_refcnt,
922 			  ifa->ifa_metric);
923 }
924 static void
925 db_print_llinfo(li)
926 	caddr_t li;
927 {
928 	struct llinfo_arp *la;
929 
930 	if (li == 0)
931 		return;
932 	la = (struct llinfo_arp *)li;
933 	db_printf("  la_rt=%p la_hold=%p, la_asked=0x%lx\n",
934 			  la->la_rt, la->la_hold, la->la_asked);
935 }
936 /*
937  * Function to pass to rn_walktree().
938  * Return non-zero error to abort walk.
939  */
940 static int
941 db_show_radix_node(rn, w)
942 	struct radix_node *rn;
943 	void *w;
944 {
945 	struct rtentry *rt = (struct rtentry *)rn;
946 
947 	db_printf("rtentry=%p", rt);
948 
949 	db_printf(" flags=0x%x refcnt=%d use=%ld expire=%ld\n",
950 			  rt->rt_flags, rt->rt_refcnt,
951 			  rt->rt_use, rt->rt_expire);
952 
953 	db_printf(" key="); db_print_sa(rt_key(rt));
954 	db_printf(" mask="); db_print_sa(rt_mask(rt));
955 	db_printf(" gw="); db_print_sa(rt->rt_gateway);
956 
957 	db_printf(" ifp=%p ", rt->rt_ifp);
958 	if (rt->rt_ifp)
959 		db_printf("(%s)", rt->rt_ifp->if_xname);
960 	else
961 		db_printf("(NULL)");
962 
963 	db_printf(" ifa=%p\n", rt->rt_ifa);
964 	db_print_ifa(rt->rt_ifa);
965 
966 	db_printf(" genmask="); db_print_sa(rt->rt_genmask);
967 
968 	db_printf(" gwroute=%p llinfo=%p\n",
969 			  rt->rt_gwroute, rt->rt_llinfo);
970 	db_print_llinfo(rt->rt_llinfo);
971 
972 	return (0);
973 }
974 /*
975  * Function to print all the route trees.
976  * Use this from ddb:  "call db_show_arptab"
977  */
978 int
979 db_show_arptab()
980 {
981 	struct radix_node_head *rnh;
982 	rnh = rt_tables[AF_INET];
983 	db_printf("Route tree for AF_INET\n");
984 	if (rnh == NULL) {
985 		db_printf(" (not initialized)\n");
986 		return (0);
987 	}
988 	rn_walktree(rnh, db_show_radix_node, NULL);
989 	return (0);
990 }
991 #endif
992 #endif /* INET */
993