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