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