2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1982, 1986, 1988, 1993
24 * The Regents of the University of California. All rights reserved.
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
29 * 1. Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 * 3. All advertising materials mentioning features or use of this software
35 * must display the following acknowledgement:
36 * This product includes software developed by the University of
37 * California, Berkeley and its contributors.
38 * 4. Neither the name of the University nor the names of its contributors
39 * may be used to endorse or promote products derived from this software
40 * without specific prior written permission.
42 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * @(#)if_ether.c 8.1 (Berkeley) 6/10/93
58 * Ethernet address resolution protocol.
60 * add "inuse/lock" bit (or ref. count) along with valid bit
68 #include <sys/param.h>
69 #include <sys/kernel.h>
71 #include <sys/sysctl.h>
73 #include <sys/systm.h>
75 #include <sys/malloc.h>
76 #include <sys/socket.h>
77 #include <sys/syslog.h>
80 #include <net/if_dl.h>
81 #include <net/route.h>
82 #include <net/netisr.h>
84 #include <netinet/in.h>
85 #include <netinet/in_var.h>
86 #include <netinet/if_ether.h>
88 #define SIN(s) ((struct sockaddr_in *)s)
89 #define SDL(s) ((struct sockaddr_dl *)s)
91 SYSCTL_DECL(_net_link_ether
);
92 SYSCTL_NODE(_net_link_ether
, PF_INET
, inet
, CTLFLAG_RW
, 0, "");
95 static int arpt_prune
= (5*60*1); /* walk list every 5 minutes */
96 static int arpt_keep
= (20*60); /* once resolved, good for 20 more minutes */
97 static int arpt_down
= 20; /* once declared down, don't send for 20 sec */
99 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, prune_intvl
, CTLFLAG_RW
,
101 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, max_age
, CTLFLAG_RW
,
103 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, host_down_time
, CTLFLAG_RW
,
106 #define rt_expire rt_rmx.rmx_expire
109 LIST_ENTRY(llinfo_arp
) la_le
;
110 struct rtentry
*la_rt
;
111 struct mbuf
*la_hold
; /* last packet until resolved/timeout */
112 long la_asked
; /* last time we QUERIED for this addr */
113 #define la_timer la_rt->rt_rmx.rmx_expire /* deletion time in seconds */
116 static LIST_HEAD(, llinfo_arp
) llinfo_arp
;
118 struct ifqueue arpintrq
= {0, 0, 0, 50};
119 static int arp_inuse
, arp_allocated
;
121 static int arp_maxtries
= 5;
122 static int useloopback
= 1; /* use loopback interface for local traffic */
123 static int arp_proxyall
= 0;
124 static int arp_init_called
= 0;
126 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, maxtries
, CTLFLAG_RW
,
127 &arp_maxtries
, 0, "");
128 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, useloopback
, CTLFLAG_RW
,
129 &useloopback
, 0, "");
130 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, proxyall
, CTLFLAG_RW
,
131 &arp_proxyall
, 0, "");
133 void arp_rtrequest
__P((int, struct rtentry
*, struct sockaddr
*));
134 static void arprequest
__P((struct arpcom
*,
135 struct in_addr
*, struct in_addr
*, u_char
*));
136 void arpintr
__P((void));
137 static void arptfree
__P((struct llinfo_arp
*));
138 static void arptimer
__P((void *));
139 static u_char etherbroadcastaddr
[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
140 static struct llinfo_arp
141 *arplookup
__P((u_long
, int, int));
143 static void in_arpinput
__P((struct mbuf
*));
147 * Timeout routine. Age arp_tab entries periodically.
151 arptimer(ignored_arg
)
155 register struct llinfo_arp
*la
;
156 struct llinfo_arp
*ola
;
157 boolean_t funnel_state
;
160 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
162 la
= llinfo_arp
.lh_first
;
164 timeout(arptimer
, (caddr_t
)0, arpt_prune
* hz
);
165 while ((ola
= la
) != 0) {
166 register struct rtentry
*rt
= la
->la_rt
;
167 la
= la
->la_le
.le_next
;
168 if (rt
->rt_expire
&& rt
->rt_expire
<= time_second
)
169 arptfree(ola
); /* timer has expired, clear */
172 (void) thread_funnel_set(network_flock
, FALSE
);
177 * Parallel to llc_rtrequest.
180 arp_rtrequest(req
, rt
, sa
)
182 register struct rtentry
*rt
;
185 register struct sockaddr
*gate
= rt
->rt_gateway
;
186 register struct llinfo_arp
*la
= (struct llinfo_arp
*)rt
->rt_llinfo
;
187 static struct sockaddr_dl null_sdl
= {sizeof(null_sdl
), AF_LINK
};
188 static int arpinit_done
;
192 LIST_INIT(&llinfo_arp
);
193 timeout(arptimer
, (caddr_t
)0, hz
);
195 if (rt
->rt_flags
& RTF_GATEWAY
)
201 * XXX: If this is a manually added route to interface
202 * such as older version of routed or gated might provide,
203 * restore cloning bit.
205 if ((rt
->rt_flags
& RTF_HOST
) == 0 &&
206 SIN(rt_mask(rt
))->sin_addr
.s_addr
!= 0xffffffff)
207 rt
->rt_flags
|= RTF_CLONING
;
208 if (rt
->rt_flags
& RTF_CLONING
) {
210 * Case 1: This route should come from a route to iface.
212 rt_setgate(rt
, rt_key(rt
),
213 (struct sockaddr
*)&null_sdl
);
214 gate
= rt
->rt_gateway
;
215 SDL(gate
)->sdl_type
= rt
->rt_ifp
->if_type
;
216 SDL(gate
)->sdl_index
= rt
->rt_ifp
->if_index
;
217 rt
->rt_expire
= time_second
;
220 /* Announce a new entry if requested. */
221 if (rt
->rt_flags
& RTF_ANNOUNCE
)
222 arprequest((struct arpcom
*)rt
->rt_ifp
,
223 &SIN(rt_key(rt
))->sin_addr
,
224 &SIN(rt_key(rt
))->sin_addr
,
225 (u_char
*)LLADDR(SDL(gate
)));
228 if (gate
->sa_family
!= AF_LINK
||
229 gate
->sa_len
< sizeof(null_sdl
)) {
230 log(LOG_DEBUG
, "arp_rtrequest: bad gateway value\n");
233 SDL(gate
)->sdl_type
= rt
->rt_ifp
->if_type
;
234 SDL(gate
)->sdl_index
= rt
->rt_ifp
->if_index
;
236 break; /* This happens on a route change */
238 * Case 2: This route may come from cloning, or a manual route
239 * add with a LL address.
241 R_Malloc(la
, struct llinfo_arp
*, sizeof(*la
));
242 rt
->rt_llinfo
= (caddr_t
)la
;
244 log(LOG_DEBUG
, "arp_rtrequest: malloc failed\n");
247 arp_inuse
++, arp_allocated
++;
248 Bzero(la
, sizeof(*la
));
250 rt
->rt_flags
|= RTF_LLINFO
;
251 LIST_INSERT_HEAD(&llinfo_arp
, la
, la_le
);
255 * This keeps the multicast addresses from showing up
256 * in `arp -a' listings as unresolved. It's not actually
257 * functional. Then the same for broadcast.
259 if (IN_MULTICAST(ntohl(SIN(rt_key(rt
))->sin_addr
.s_addr
))) {
260 ETHER_MAP_IP_MULTICAST(&SIN(rt_key(rt
))->sin_addr
,
262 SDL(gate
)->sdl_alen
= 6;
265 if (in_broadcast(SIN(rt_key(rt
))->sin_addr
, rt
->rt_ifp
)) {
266 memcpy(LLADDR(SDL(gate
)), etherbroadcastaddr
, 6);
267 SDL(gate
)->sdl_alen
= 6;
272 if (SIN(rt_key(rt
))->sin_addr
.s_addr
==
273 (IA_SIN(rt
->rt_ifa
))->sin_addr
.s_addr
) {
275 * This test used to be
276 * if (loif.if_flags & IFF_UP)
277 * It allowed local traffic to be forced
278 * through the hardware by configuring the loopback down.
279 * However, it causes problems during network configuration
280 * for boards that can't receive packets they send.
281 * It is now necessary to clear "useloopback" and remove
282 * the route to force traffic out to the hardware.
285 Bcopy(((struct arpcom
*)rt
->rt_ifp
)->ac_enaddr
,
286 LLADDR(SDL(gate
)), SDL(gate
)->sdl_alen
= 6);
297 LIST_REMOVE(la
, la_le
);
299 rt
->rt_flags
&= ~RTF_LLINFO
;
301 m_freem(la
->la_hold
);
310 * Broadcast an ARP packet, asking who has addr on interface ac.
314 register struct arpcom
*ac
;
315 register struct in_addr
*addr
;
316 { struct ifnet
*ifp
= (struct ifnet
*)ac
;
317 struct ifaddr
*ifa
= TAILQ_FIRST(&ifp
->if_addrhead
);
320 { if (ifa
->ifa_addr
->sa_family
== AF_INET
)
321 { arprequest(ac
, &SIN(ifa
->ifa_addr
)->sin_addr
, addr
, ac
->ac_enaddr
);
324 ifa
= TAILQ_NEXT(ifa
, ifa_link
);
332 * Broadcast an ARP request. Caller specifies:
333 * - arp header source ip address
334 * - arp header target ip address
335 * - arp header source ethernet address
338 arprequest(ac
, sip
, tip
, enaddr
)
339 register struct arpcom
*ac
;
340 register struct in_addr
*sip
, *tip
;
341 register u_char
*enaddr
;
343 register struct mbuf
*m
;
344 register struct ether_header
*eh
;
345 register struct ether_arp
*ea
;
348 if ((m
= m_gethdr(M_DONTWAIT
, MT_DATA
)) == NULL
)
350 m
->m_len
= sizeof(*ea
);
351 m
->m_pkthdr
.len
= sizeof(*ea
);
352 m
->m_pkthdr
.rcvif
= (struct ifnet
*)0;
353 MH_ALIGN(m
, sizeof(*ea
));
354 ea
= mtod(m
, struct ether_arp
*);
355 eh
= (struct ether_header
*)sa
.sa_data
;
356 bzero((caddr_t
)ea
, sizeof (*ea
));
357 (void)memcpy(eh
->ether_dhost
, etherbroadcastaddr
, sizeof(eh
->ether_dhost
));
358 eh
->ether_type
= htons(ETHERTYPE_ARP
); /* if_output will not swap */
359 ea
->arp_hrd
= htons(ARPHRD_ETHER
);
360 ea
->arp_pro
= htons(ETHERTYPE_IP
);
361 ea
->arp_hln
= sizeof(ea
->arp_sha
); /* hardware address length */
362 ea
->arp_pln
= sizeof(ea
->arp_spa
); /* protocol address length */
363 ea
->arp_op
= htons(ARPOP_REQUEST
);
364 (void)memcpy(ea
->arp_sha
, enaddr
, sizeof(ea
->arp_sha
));
365 (void)memcpy(ea
->arp_spa
, sip
, sizeof(ea
->arp_spa
));
366 (void)memcpy(ea
->arp_tpa
, tip
, sizeof(ea
->arp_tpa
));
367 sa
.sa_family
= AF_UNSPEC
;
368 sa
.sa_len
= sizeof(sa
);
369 dlil_output((u_long
) ac
, m
, 0, &sa
, 0);
373 * Resolve an IP address into an ethernet address. If success,
374 * desten is filled in. If there is no entry in arptab,
375 * set one up and broadcast a request for the IP address.
376 * Hold onto this mbuf and resend it once the address
377 * is finally resolved. A return value of 1 indicates
378 * that desten has been filled in and the packet should be sent
379 * normally; a 0 return indicates that the packet has been
380 * taken over here, either now or for later transmission.
383 arpresolve(ac
, rt
, m
, dst
, desten
, rt0
)
384 register struct arpcom
*ac
;
385 register struct rtentry
*rt
;
387 register struct sockaddr
*dst
;
388 register u_char
*desten
;
391 register struct llinfo_arp
*la
= 0;
392 struct sockaddr_dl
*sdl
;
394 if (m
->m_flags
& M_BCAST
) { /* broadcast */
395 (void)memcpy(desten
, etherbroadcastaddr
, sizeof(etherbroadcastaddr
));
398 if (m
->m_flags
& M_MCAST
) { /* multicast */
399 ETHER_MAP_IP_MULTICAST(&SIN(dst
)->sin_addr
, desten
);
403 la
= (struct llinfo_arp
*)rt
->rt_llinfo
;
405 la
= arplookup(SIN(dst
)->sin_addr
.s_addr
, 1, 0);
409 if (la
== 0 || rt
== 0) {
410 log(LOG_DEBUG
, "arpresolve: can't allocate llinfo for %s%s%s\n",
411 inet_ntoa(SIN(dst
)->sin_addr
), la
? "la" : "",
416 sdl
= SDL(rt
->rt_gateway
);
418 * Check the address family and length is valid, the address
419 * is resolved; otherwise, try to resolve.
421 if ((rt
->rt_expire
== 0 || rt
->rt_expire
> time_second
) &&
422 sdl
->sdl_family
== AF_LINK
&& sdl
->sdl_alen
!= 0) {
423 bcopy(LLADDR(sdl
), desten
, sdl
->sdl_alen
);
427 * There is an arptab entry, but no ethernet address
428 * response yet. Replace the held mbuf with this
432 m_freem(la
->la_hold
);
435 rt
->rt_flags
&= ~RTF_REJECT
;
436 if (la
->la_asked
== 0 || rt
->rt_expire
!= time_second
) {
437 rt
->rt_expire
= time_second
;
438 if (la
->la_asked
++ < arp_maxtries
)
440 &SIN(rt
->rt_ifa
->ifa_addr
)->sin_addr
,
441 &SIN(dst
)->sin_addr
, ac
->ac_enaddr
);
443 rt
->rt_flags
|= RTF_REJECT
;
444 rt
->rt_expire
+= arpt_down
;
454 * Common length and type checks are done here,
455 * then the protocol-specific routine is called.
460 register struct mbuf
*m
;
461 register struct arphdr
*ar
;
464 while (arpintrq
.ifq_head
) {
466 IF_DEQUEUE(&arpintrq
, m
);
468 if (m
== 0 || (m
->m_flags
& M_PKTHDR
) == 0)
470 if (m
->m_len
>= sizeof(struct arphdr
) &&
471 (ar
= mtod(m
, struct arphdr
*)) &&
472 ntohs(ar
->ar_hrd
) == ARPHRD_ETHER
&&
474 sizeof(struct arphdr
) + 2 * ar
->ar_hln
+ 2 * ar
->ar_pln
)
476 switch (ntohs(ar
->ar_pro
)) {
488 NETISR_SET(NETISR_ARP
, arpintr
);
493 * ARP for Internet protocols on 10 Mb/s Ethernet.
494 * Algorithm is that given in RFC 826.
495 * In addition, a sanity check is performed on the sender
496 * protocol address, to catch impersonators.
497 * We no longer handle negotiations for use of trailer protocol:
498 * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent
499 * along with IP replies if we wanted trailers sent to us,
500 * and also sent them in response to IP replies.
501 * This allowed either end to announce the desire to receive
503 * We no longer reply to requests for ETHERTYPE_TRAIL protocol either,
504 * but formerly didn't normally send requests.
510 register struct ether_arp
*ea
;
511 register struct arpcom
*ac
= (struct arpcom
*)m
->m_pkthdr
.rcvif
;
512 struct ether_header
*eh
;
513 register struct llinfo_arp
*la
= 0;
514 register struct rtentry
*rt
;
515 struct in_ifaddr
*ia
, *maybe_ia
= 0;
516 struct sockaddr_dl
*sdl
;
518 struct in_addr isaddr
, itaddr
, myaddr
;
520 unsigned char buf
[18];
522 ea
= mtod(m
, struct ether_arp
*);
523 op
= ntohs(ea
->arp_op
);
524 (void)memcpy(&isaddr
, ea
->arp_spa
, sizeof (isaddr
));
525 (void)memcpy(&itaddr
, ea
->arp_tpa
, sizeof (itaddr
));
526 for (ia
= in_ifaddrhead
.tqh_first
; ia
; ia
= ia
->ia_link
.tqe_next
)
529 * For a bridge, we want to check the address irrespective
530 * of the receive interface. (This will change slightly
531 * when we have clusters of interfaces).
535 if (ia
->ia_ifp
== &ac
->ac_if
) {
538 if ((itaddr
.s_addr
== ia
->ia_addr
.sin_addr
.s_addr
) ||
539 (isaddr
.s_addr
== ia
->ia_addr
.sin_addr
.s_addr
))
546 myaddr
= ia
? ia
->ia_addr
.sin_addr
: maybe_ia
->ia_addr
.sin_addr
;
550 * In order to support BlueBox networking, we need to allow
551 * "self-addressed" stamped envelopes
553 if (!bcmp((caddr_t
)ea
->arp_sha
, (caddr_t
)ac
->ac_enaddr
,
554 sizeof (ea
->arp_sha
))) {
555 m_freem(m
); /* it's from me, ignore it. */
559 if (!bcmp((caddr_t
)ea
->arp_sha
, (caddr_t
)etherbroadcastaddr
,
560 sizeof (ea
->arp_sha
))) {
562 "arp: ether address is broadcast for IP address %s!\n",
567 if (isaddr
.s_addr
== myaddr
.s_addr
) {
569 "duplicate IP address %s sent from ethernet address %s\n",
570 inet_ntoa(isaddr
), ether_sprintf(buf
, ea
->arp_sha
));
574 la
= arplookup(isaddr
.s_addr
, itaddr
.s_addr
== myaddr
.s_addr
, 0);
575 if (la
&& (rt
= la
->la_rt
) && (sdl
= SDL(rt
->rt_gateway
))) {
576 #ifndef BRIDGE /* the following is not an error when doing bridging */
577 if (rt
->rt_ifp
!= &ac
->ac_if
) {
578 log(LOG_ERR
, "arp: %s is on %s%d but got reply from %6D on %s%d\n",
580 rt
->rt_ifp
->if_name
, rt
->rt_ifp
->if_unit
,
582 ac
->ac_if
.if_name
, ac
->ac_if
.if_unit
);
587 bcmp((caddr_t
)ea
->arp_sha
, LLADDR(sdl
), sdl
->sdl_alen
))
589 log(LOG_INFO
, "arp: %s moved from %6D to %6D on %s%d\n",
590 inet_ntoa(isaddr
), (u_char
*)LLADDR(sdl
), ":",
592 ac
->ac_if
.if_name
, ac
->ac_if
.if_unit
);
595 "arp: %6D attempts to modify permanent entry for %s on %s%d",
596 ea
->arp_sha
, ":", inet_ntoa(isaddr
),
597 ac
->ac_if
.if_name
, ac
->ac_if
.if_unit
);
600 (void)memcpy(LLADDR(sdl
), ea
->arp_sha
, sizeof(ea
->arp_sha
));
601 sdl
->sdl_alen
= sizeof(ea
->arp_sha
);
603 rt
->rt_expire
= time_second
+ arpt_keep
;
604 rt
->rt_flags
&= ~RTF_REJECT
;
607 dlil_output((u_long
) ac
, la
->la_hold
, rt
,
613 if (op
!= ARPOP_REQUEST
) {
617 if (itaddr
.s_addr
== myaddr
.s_addr
) {
618 /* I am the target */
619 (void)memcpy(ea
->arp_tha
, ea
->arp_sha
, sizeof(ea
->arp_sha
));
620 (void)memcpy(ea
->arp_sha
, ac
->ac_enaddr
, sizeof(ea
->arp_sha
));
622 la
= arplookup(itaddr
.s_addr
, 0, SIN_PROXY
);
624 struct sockaddr_in sin
;
631 bzero(&sin
, sizeof sin
);
632 sin
.sin_family
= AF_INET
;
633 sin
.sin_len
= sizeof sin
;
634 sin
.sin_addr
= itaddr
;
636 rt
= rtalloc1((struct sockaddr
*)&sin
, 0, 0UL);
642 * Don't send proxies for nodes on the same interface
643 * as this one came out of, or we'll get into a fight
644 * over who claims what Ether address.
646 if (rt
->rt_ifp
== &ac
->ac_if
) {
651 (void)memcpy(ea
->arp_tha
, ea
->arp_sha
, sizeof(ea
->arp_sha
));
652 (void)memcpy(ea
->arp_sha
, ac
->ac_enaddr
, sizeof(ea
->arp_sha
));
655 printf("arp: proxying for %s\n",
660 (void)memcpy(ea
->arp_tha
, ea
->arp_sha
, sizeof(ea
->arp_sha
));
661 sdl
= SDL(rt
->rt_gateway
);
662 (void)memcpy(ea
->arp_sha
, LLADDR(sdl
), sizeof(ea
->arp_sha
));
666 (void)memcpy(ea
->arp_tpa
, ea
->arp_spa
, sizeof(ea
->arp_spa
));
667 (void)memcpy(ea
->arp_spa
, &itaddr
, sizeof(ea
->arp_spa
));
668 ea
->arp_op
= htons(ARPOP_REPLY
);
669 ea
->arp_pro
= htons(ETHERTYPE_IP
); /* let's be sure! */
670 eh
= (struct ether_header
*)sa
.sa_data
;
671 (void)memcpy(eh
->ether_dhost
, ea
->arp_tha
, sizeof(eh
->ether_dhost
));
672 eh
->ether_type
= htons(ETHERTYPE_ARP
);
673 sa
.sa_family
= AF_UNSPEC
;
674 sa
.sa_len
= sizeof(sa
);
675 dlil_output((u_long
) ac
, m
, 0, &sa
, 0);
685 register struct llinfo_arp
*la
;
687 register struct rtentry
*rt
= la
->la_rt
;
688 register struct sockaddr_dl
*sdl
;
691 if (rt
->rt_refcnt
> 0 && (sdl
= SDL(rt
->rt_gateway
)) &&
692 sdl
->sdl_family
== AF_LINK
) {
695 rt
->rt_flags
&= ~RTF_REJECT
;
698 rtrequest(RTM_DELETE
, rt_key(rt
), (struct sockaddr
*)0, rt_mask(rt
),
699 0, (struct rtentry
**)0);
702 * Lookup or enter a new address in arptab.
704 static struct llinfo_arp
*
705 arplookup(addr
, create
, proxy
)
709 register struct rtentry
*rt
;
710 static struct sockaddr_inarp sin
= {sizeof(sin
), AF_INET
};
713 sin
.sin_addr
.s_addr
= addr
;
714 sin
.sin_other
= proxy
? SIN_PROXY
: 0;
715 rt
= rtalloc1((struct sockaddr
*)&sin
, create
, 0UL);
720 if (rt
->rt_flags
& RTF_GATEWAY
)
721 why
= "host is not on local network";
722 else if ((rt
->rt_flags
& RTF_LLINFO
) == 0)
723 why
= "could not allocate llinfo";
724 else if (rt
->rt_gateway
->sa_family
!= AF_LINK
)
725 why
= "gateway route is not ours";
728 log(LOG_DEBUG
, "arplookup %s failed: %s\n",
729 inet_ntoa(sin
.sin_addr
), why
);
734 return ((struct llinfo_arp
*)rt
->rt_llinfo
);
742 if (ntohl(IA_SIN(ifa
)->sin_addr
.s_addr
) != INADDR_ANY
)
743 arprequest(ac
, &IA_SIN(ifa
)->sin_addr
,
744 &IA_SIN(ifa
)->sin_addr
, ac
->ac_enaddr
);
745 ifa
->ifa_rtrequest
= arp_rtrequest
;
746 ifa
->ifa_flags
|= RTF_CLONING
;