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
55 * $FreeBSD: src/sys/netinet/if_ether.c,v 1.64.2.11 2001/07/25 17:27:56 jlemon Exp $
59 * Ethernet address resolution protocol.
61 * add "inuse/lock" bit (or ref. count) along with valid bit
64 #include <sys/param.h>
65 #include <sys/kernel.h>
66 #include <sys/queue.h>
67 #include <sys/sysctl.h>
68 #include <sys/systm.h>
70 #include <sys/malloc.h>
71 #include <sys/socket.h>
72 #include <sys/syslog.h>
75 #include <net/if_dl.h>
76 #include <net/if_types.h>
77 #include <net/route.h>
78 #include <net/netisr.h>
79 #include <net/if_llc.h>
81 #include <net/ethernet.h>
82 #include <net/bridge.h>
85 #include <netinet/in.h>
86 #include <netinet/in_var.h>
87 #include <netinet/if_ether.h>
89 #include <net/iso88025.h>
91 #define SIN(s) ((struct sockaddr_in *)s)
92 #define SDL(s) ((struct sockaddr_dl *)s)
94 SYSCTL_DECL(_net_link_ether
);
95 SYSCTL_NODE(_net_link_ether
, PF_INET
, inet
, CTLFLAG_RW
, 0, "");
98 static int arpt_prune
= (5*60*1); /* walk list every 5 minutes */
99 static int arpt_keep
= (20*60); /* once resolved, good for 20 more minutes */
100 static int arpt_down
= 20; /* once declared down, don't send for 20 sec */
102 /* Apple Hardware SUM16 checksuming */
103 int apple_hwcksum_tx
= 1;
104 int apple_hwcksum_rx
= 1;
106 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, prune_intvl
, CTLFLAG_RW
,
108 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, max_age
, CTLFLAG_RW
,
110 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, host_down_time
, CTLFLAG_RW
,
112 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, apple_hwcksum_tx
, CTLFLAG_RW
,
113 &apple_hwcksum_tx
, 0, "");
114 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, apple_hwcksum_rx
, CTLFLAG_RW
,
115 &apple_hwcksum_rx
, 0, "");
117 #define rt_expire rt_rmx.rmx_expire
120 LIST_ENTRY(llinfo_arp
) la_le
;
121 struct rtentry
*la_rt
;
122 struct mbuf
*la_hold
; /* last packet until resolved/timeout */
123 long la_asked
; /* last time we QUERIED for this addr */
124 #define la_timer la_rt->rt_rmx.rmx_expire /* deletion time in seconds */
127 static LIST_HEAD(, llinfo_arp
) llinfo_arp
;
129 struct ifqueue arpintrq
= {0, 0, 0, 50};
130 static int arp_inuse
, arp_allocated
;
132 static int arp_maxtries
= 5;
133 static int useloopback
= 1; /* use loopback interface for local traffic */
134 static int arp_proxyall
= 0;
135 static int arp_init_called
= 0;
137 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, maxtries
, CTLFLAG_RW
,
138 &arp_maxtries
, 0, "");
139 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, useloopback
, CTLFLAG_RW
,
140 &useloopback
, 0, "");
141 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, proxyall
, CTLFLAG_RW
,
142 &arp_proxyall
, 0, "");
144 void arp_rtrequest
__P((int, struct rtentry
*, struct sockaddr
*));
145 static void arprequest
__P((struct arpcom
*,
146 struct in_addr
*, struct in_addr
*, u_char
*));
147 void arpintr
__P((void));
148 static void arptfree
__P((struct llinfo_arp
*));
149 static void arptimer
__P((void *));
150 static u_char etherbroadcastaddr
[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
151 static struct llinfo_arp
152 *arplookup
__P((u_long
, int, int));
154 static void in_arpinput
__P((struct mbuf
*));
158 * Timeout routine. Age arp_tab entries periodically.
162 arptimer(ignored_arg
)
166 boolean_t funnel_state
= thread_funnel_set(network_flock
, TRUE
);
169 register struct llinfo_arp
*la
= llinfo_arp
.lh_first
;
170 struct llinfo_arp
*ola
;
172 timeout(arptimer
, (caddr_t
)0, arpt_prune
* hz
);
173 while ((ola
= la
) != 0) {
174 register struct rtentry
*rt
= la
->la_rt
;
175 la
= la
->la_le
.le_next
;
176 if (rt
->rt_expire
&& rt
->rt_expire
<= time_second
)
177 arptfree(ola
); /* timer has expired, clear */
181 (void) thread_funnel_set(network_flock
, FALSE
);
186 * Parallel to llc_rtrequest.
189 arp_rtrequest(req
, rt
, sa
)
191 register struct rtentry
*rt
;
194 register struct sockaddr
*gate
= rt
->rt_gateway
;
195 register struct llinfo_arp
*la
= (struct llinfo_arp
*)rt
->rt_llinfo
;
196 static struct sockaddr_dl null_sdl
= {sizeof(null_sdl
), AF_LINK
};
197 static int arpinit_done
;
201 LIST_INIT(&llinfo_arp
);
202 timeout(arptimer
, (caddr_t
)0, hz
);
204 register_netisr(NETISR_ARP
, arpintr
);
207 if (rt
->rt_flags
& RTF_GATEWAY
)
213 * XXX: If this is a manually added route to interface
214 * such as older version of routed or gated might provide,
215 * restore cloning bit.
217 if ((rt
->rt_flags
& RTF_HOST
) == 0 &&
218 SIN(rt_mask(rt
))->sin_addr
.s_addr
!= 0xffffffff)
219 rt
->rt_flags
|= RTF_CLONING
;
220 if (rt
->rt_flags
& RTF_CLONING
) {
222 * Case 1: This route should come from a route to iface.
224 rt_setgate(rt
, rt_key(rt
),
225 (struct sockaddr
*)&null_sdl
);
226 gate
= rt
->rt_gateway
;
227 SDL(gate
)->sdl_type
= rt
->rt_ifp
->if_type
;
228 SDL(gate
)->sdl_index
= rt
->rt_ifp
->if_index
;
229 rt
->rt_expire
= time_second
;
232 /* Announce a new entry if requested. */
233 if (rt
->rt_flags
& RTF_ANNOUNCE
)
234 arprequest((struct arpcom
*)rt
->rt_ifp
,
235 &SIN(rt_key(rt
))->sin_addr
,
236 &SIN(rt_key(rt
))->sin_addr
,
237 (u_char
*)LLADDR(SDL(gate
)));
240 if (gate
->sa_family
!= AF_LINK
||
241 gate
->sa_len
< sizeof(null_sdl
)) {
242 log(LOG_DEBUG
, "arp_rtrequest: bad gateway value\n");
245 SDL(gate
)->sdl_type
= rt
->rt_ifp
->if_type
;
246 SDL(gate
)->sdl_index
= rt
->rt_ifp
->if_index
;
248 break; /* This happens on a route change */
250 * Case 2: This route may come from cloning, or a manual route
251 * add with a LL address.
253 R_Malloc(la
, struct llinfo_arp
*, sizeof(*la
));
254 rt
->rt_llinfo
= (caddr_t
)la
;
256 log(LOG_DEBUG
, "arp_rtrequest: malloc failed\n");
259 arp_inuse
++, arp_allocated
++;
260 Bzero(la
, sizeof(*la
));
262 rt
->rt_flags
|= RTF_LLINFO
;
263 LIST_INSERT_HEAD(&llinfo_arp
, la
, la_le
);
267 * This keeps the multicast addresses from showing up
268 * in `arp -a' listings as unresolved. It's not actually
269 * functional. Then the same for broadcast.
271 if (IN_MULTICAST(ntohl(SIN(rt_key(rt
))->sin_addr
.s_addr
))) {
272 ETHER_MAP_IP_MULTICAST(&SIN(rt_key(rt
))->sin_addr
,
274 SDL(gate
)->sdl_alen
= 6;
277 if (in_broadcast(SIN(rt_key(rt
))->sin_addr
, rt
->rt_ifp
)) {
278 memcpy(LLADDR(SDL(gate
)), etherbroadcastaddr
, 6);
279 SDL(gate
)->sdl_alen
= 6;
280 rt
->rt_expire
= time_second
;
284 if (SIN(rt_key(rt
))->sin_addr
.s_addr
==
285 (IA_SIN(rt
->rt_ifa
))->sin_addr
.s_addr
) {
287 * This test used to be
288 * if (loif.if_flags & IFF_UP)
289 * It allowed local traffic to be forced
290 * through the hardware by configuring the loopback down.
291 * However, it causes problems during network configuration
292 * for boards that can't receive packets they send.
293 * It is now necessary to clear "useloopback" and remove
294 * the route to force traffic out to the hardware.
297 Bcopy(((struct arpcom
*)rt
->rt_ifp
)->ac_enaddr
,
298 LLADDR(SDL(gate
)), SDL(gate
)->sdl_alen
= 6);
309 LIST_REMOVE(la
, la_le
);
311 rt
->rt_flags
&= ~RTF_LLINFO
;
313 m_freem(la
->la_hold
);
319 * Broadcast an ARP packet, asking who has addr on interface ac.
324 struct in_addr
*addr
;
326 struct ifnet
*ifp
= (struct ifnet
*)ac
;
327 struct ifaddr
*ifa
= TAILQ_FIRST(&ifp
->if_addrhead
);
330 if (ifa
->ifa_addr
->sa_family
== AF_INET
) {
331 arprequest(ac
, &SIN(ifa
->ifa_addr
)->sin_addr
, addr
, ac
->ac_enaddr
);
334 ifa
= TAILQ_NEXT(ifa
, ifa_link
);
340 * Broadcast an ARP request. Caller specifies:
341 * - arp header source ip address
342 * - arp header target ip address
343 * - arp header source ethernet address
346 arprequest(ac
, sip
, tip
, enaddr
)
347 register struct arpcom
*ac
;
348 register struct in_addr
*sip
, *tip
;
349 register u_char
*enaddr
;
351 register struct mbuf
*m
;
352 register struct ether_header
*eh
;
353 register struct ether_arp
*ea
;
355 static u_char llcx
[] = { 0x82, 0x40, LLC_SNAP_LSAP
, LLC_SNAP_LSAP
,
356 LLC_UI
, 0x00, 0x00, 0x00, 0x08, 0x06 };
358 if ((m
= m_gethdr(M_DONTWAIT
, MT_DATA
)) == NULL
)
360 m
->m_pkthdr
.rcvif
= (struct ifnet
*)0;
361 switch (ac
->ac_if
.if_type
) {
363 m
->m_len
= sizeof(*ea
) + sizeof(llcx
);
364 m
->m_pkthdr
.len
= sizeof(*ea
) + sizeof(llcx
);
365 MH_ALIGN(m
, sizeof(*ea
) + sizeof(llcx
));
366 (void)memcpy(mtod(m
, caddr_t
), llcx
, sizeof(llcx
));
367 (void)memcpy(sa
.sa_data
, etherbroadcastaddr
, 6);
368 (void)memcpy(sa
.sa_data
+ 6, enaddr
, 6);
369 sa
.sa_data
[6] |= TR_RII
;
370 sa
.sa_data
[12] = TR_AC
;
371 sa
.sa_data
[13] = TR_LLC_FRAME
;
372 ea
= (struct ether_arp
*)(mtod(m
, char *) + sizeof(llcx
));
373 bzero((caddr_t
)ea
, sizeof (*ea
));
374 ea
->arp_hrd
= htons(ARPHRD_IEEE802
);
379 * This may not be correct for types not explicitly
380 * listed, but this is our best guess
383 m
->m_len
= sizeof(*ea
);
384 m
->m_pkthdr
.len
= sizeof(*ea
);
385 MH_ALIGN(m
, sizeof(*ea
));
386 ea
= mtod(m
, struct ether_arp
*);
387 eh
= (struct ether_header
*)sa
.sa_data
;
388 bzero((caddr_t
)ea
, sizeof (*ea
));
389 /* if_output will not swap */
390 eh
->ether_type
= htons(ETHERTYPE_ARP
);
391 (void)memcpy(eh
->ether_dhost
, etherbroadcastaddr
,
392 sizeof(eh
->ether_dhost
));
393 ea
->arp_hrd
= htons(ARPHRD_ETHER
);
396 ea
->arp_pro
= htons(ETHERTYPE_IP
);
397 ea
->arp_hln
= sizeof(ea
->arp_sha
); /* hardware address length */
398 ea
->arp_pln
= sizeof(ea
->arp_spa
); /* protocol address length */
399 ea
->arp_op
= htons(ARPOP_REQUEST
);
400 (void)memcpy(ea
->arp_sha
, enaddr
, sizeof(ea
->arp_sha
));
401 (void)memcpy(ea
->arp_spa
, sip
, sizeof(ea
->arp_spa
));
402 (void)memcpy(ea
->arp_tpa
, tip
, sizeof(ea
->arp_tpa
));
403 sa
.sa_family
= AF_UNSPEC
;
404 sa
.sa_len
= sizeof(sa
);
405 dlil_output(((struct ifnet
*)ac
)->if_data
.default_proto
, m
, 0, &sa
, 0);
409 * Resolve an IP address into an ethernet address. If success,
410 * desten is filled in. If there is no entry in arptab,
411 * set one up and broadcast a request for the IP address.
412 * Hold onto this mbuf and resend it once the address
413 * is finally resolved. A return value of 1 indicates
414 * that desten has been filled in and the packet should be sent
415 * normally; a 0 return indicates that the packet has been
416 * taken over here, either now or for later transmission.
419 arpresolve(ac
, rt
, m
, dst
, desten
, rt0
)
420 register struct arpcom
*ac
;
421 register struct rtentry
*rt
;
423 register struct sockaddr
*dst
;
424 register u_char
*desten
;
427 struct llinfo_arp
*la
= 0;
428 struct sockaddr_dl
*sdl
;
430 if (m
->m_flags
& M_BCAST
) { /* broadcast */
431 (void)memcpy(desten
, etherbroadcastaddr
, sizeof(etherbroadcastaddr
));
434 if (m
->m_flags
& M_MCAST
) { /* multicast */
435 ETHER_MAP_IP_MULTICAST(&SIN(dst
)->sin_addr
, desten
);
439 la
= (struct llinfo_arp
*)rt
->rt_llinfo
;
441 la
= arplookup(SIN(dst
)->sin_addr
.s_addr
, 1, 0);
445 if (la
== 0 || rt
== 0) {
446 log(LOG_DEBUG
, "arpresolve: can't allocate llinfo for %s%s%s\n",
447 inet_ntoa(SIN(dst
)->sin_addr
), la
? "la" : "",
452 sdl
= SDL(rt
->rt_gateway
);
454 * Check the address family and length is valid, the address
455 * is resolved; otherwise, try to resolve.
457 if ((rt
->rt_expire
== 0 || rt
->rt_expire
> time_second
) &&
458 sdl
->sdl_family
== AF_LINK
&& sdl
->sdl_alen
!= 0) {
459 bcopy(LLADDR(sdl
), desten
, sdl
->sdl_alen
);
463 * If ARP is disabled on this interface, stop.
465 * Probably should not allocate empty llinfo struct if we are
466 * not going to be sending out an arp request.
468 if (ac
->ac_if
.if_flags
& IFF_NOARP
)
471 * There is an arptab entry, but no ethernet address
472 * response yet. Replace the held mbuf with this
476 m_freem(la
->la_hold
);
479 rt
->rt_flags
&= ~RTF_REJECT
;
480 if (la
->la_asked
== 0 || rt
->rt_expire
!= time_second
) {
481 rt
->rt_expire
= time_second
;
482 if (la
->la_asked
++ < arp_maxtries
)
484 &SIN(rt
->rt_ifa
->ifa_addr
)->sin_addr
,
485 &SIN(dst
)->sin_addr
, ac
->ac_enaddr
);
487 rt
->rt_flags
|= RTF_REJECT
;
488 rt
->rt_expire
+= arpt_down
;
498 * Common length and type checks are done here,
499 * then the protocol-specific routine is called.
504 register struct mbuf
*m
;
505 register struct arphdr
*ar
;
508 while (arpintrq
.ifq_head
) {
510 IF_DEQUEUE(&arpintrq
, m
);
512 if (m
== 0 || (m
->m_flags
& M_PKTHDR
) == 0)
515 if (m
->m_len
< sizeof(struct arphdr
) &&
516 ((m
= m_pullup(m
, sizeof(struct arphdr
))) == NULL
)) {
517 log(LOG_ERR
, "arp: runt packet -- m_pullup failed\n");
520 ar
= mtod(m
, struct arphdr
*);
522 if (ntohs(ar
->ar_hrd
) != ARPHRD_ETHER
523 && ntohs(ar
->ar_hrd
) != ARPHRD_IEEE802
) {
525 "arp: unknown hardware address format (0x%2D)\n",
526 (unsigned char *)&ar
->ar_hrd
, "");
531 if (m
->m_pkthdr
.len
< sizeof(struct arphdr
) + 2 * ar
->ar_hln
533 log(LOG_ERR
, "arp: runt packet\n");
538 switch (ntohs(ar
->ar_pro
)) {
551 * ARP for Internet protocols on 10 Mb/s Ethernet.
552 * Algorithm is that given in RFC 826.
553 * In addition, a sanity check is performed on the sender
554 * protocol address, to catch impersonators.
555 * We no longer handle negotiations for use of trailer protocol:
556 * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent
557 * along with IP replies if we wanted trailers sent to us,
558 * and also sent them in response to IP replies.
559 * This allowed either end to announce the desire to receive
561 * We no longer reply to requests for ETHERTYPE_TRAIL protocol either,
562 * but formerly didn't normally send requests.
564 static int log_arp_wrong_iface
= 0;
566 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, log_arp_wrong_iface
, CTLFLAG_RW
,
567 &log_arp_wrong_iface
, 0,
568 "log arp packets arriving on the wrong interface");
574 register struct ether_arp
*ea
;
575 register struct arpcom
*ac
= (struct arpcom
*)m
->m_pkthdr
.rcvif
;
576 struct ether_header
*eh
;
577 struct iso88025_header
*th
= (struct iso88025_header
*)0;
578 register struct llinfo_arp
*la
= 0;
579 register struct rtentry
*rt
;
580 struct in_ifaddr
*ia
, *maybe_ia
= 0;
581 struct sockaddr_dl
*sdl
;
583 struct in_addr isaddr
, itaddr
, myaddr
;
585 unsigned char buf
[18];
586 unsigned char buf2
[18];
588 if (m
->m_len
< sizeof(struct ether_arp
) &&
589 (m
= m_pullup(m
, sizeof(struct ether_arp
))) == NULL
) {
590 log(LOG_ERR
, "in_arp: runt packet -- m_pullup failed\n");
594 ea
= mtod(m
, struct ether_arp
*);
595 op
= ntohs(ea
->arp_op
);
596 (void)memcpy(&isaddr
, ea
->arp_spa
, sizeof (isaddr
));
597 (void)memcpy(&itaddr
, ea
->arp_tpa
, sizeof (itaddr
));
600 /* Don't respond to requests for 0.0.0.0 */
601 if (itaddr
.s_addr
== 0 && op
== ARPOP_REQUEST
) {
607 for (ia
= in_ifaddrhead
.tqh_first
; ia
; ia
= ia
->ia_link
.tqe_next
) {
609 * For a bridge, we want to check the address irrespective
610 * of the receive interface. (This will change slightly
611 * when we have clusters of interfaces).
614 #define BRIDGE_TEST (do_bridge)
616 #define BRIDGE_TEST (0) /* cc will optimise the test away */
618 if ((BRIDGE_TEST
) || (ia
->ia_ifp
== &ac
->ac_if
)) {
620 if ((itaddr
.s_addr
== ia
->ia_addr
.sin_addr
.s_addr
) ||
621 (isaddr
.s_addr
== ia
->ia_addr
.sin_addr
.s_addr
)) {
630 myaddr
= ia
? ia
->ia_addr
.sin_addr
: maybe_ia
->ia_addr
.sin_addr
;
631 if (!bcmp((caddr_t
)ea
->arp_sha
, (caddr_t
)ac
->ac_enaddr
,
632 sizeof (ea
->arp_sha
))) {
633 m_freem(m
); /* it's from me, ignore it. */
636 if (!bcmp((caddr_t
)ea
->arp_sha
, (caddr_t
)etherbroadcastaddr
,
637 sizeof (ea
->arp_sha
))) {
639 "arp: ether address is broadcast for IP address %s!\n",
644 if (isaddr
.s_addr
== myaddr
.s_addr
) {
646 "duplicate IP address %s sent from ethernet address %s\n",
647 inet_ntoa(isaddr
), ether_sprintf(buf
, ea
->arp_sha
));
651 la
= arplookup(isaddr
.s_addr
, itaddr
.s_addr
== myaddr
.s_addr
, 0);
652 if (la
&& (rt
= la
->la_rt
) && (sdl
= SDL(rt
->rt_gateway
))) {
653 /* the following is not an error when doing bridging */
654 if (!BRIDGE_TEST
&& rt
->rt_ifp
!= &ac
->ac_if
) {
655 if (log_arp_wrong_iface
)
656 log(LOG_ERR
, "arp: %s is on %s%d but got reply from %s on %s%d\n",
658 rt
->rt_ifp
->if_name
, rt
->rt_ifp
->if_unit
,
659 ether_sprintf(buf
, ea
->arp_sha
),
660 ac
->ac_if
.if_name
, ac
->ac_if
.if_unit
);
664 bcmp((caddr_t
)ea
->arp_sha
, LLADDR(sdl
), sdl
->sdl_alen
)) {
666 log(LOG_INFO
, "arp: %s moved from %s to %s on %s%d\n",
668 ether_sprintf(buf
, (u_char
*)LLADDR(sdl
)),
669 ether_sprintf(buf2
, ea
->arp_sha
),
670 ac
->ac_if
.if_name
, ac
->ac_if
.if_unit
);
673 "arp: %s attempts to modify permanent entry for %s on %s%d",
674 ether_sprintf(buf
, ea
->arp_sha
), inet_ntoa(isaddr
),
675 ac
->ac_if
.if_name
, ac
->ac_if
.if_unit
);
679 (void)memcpy(LLADDR(sdl
), ea
->arp_sha
, sizeof(ea
->arp_sha
));
680 sdl
->sdl_alen
= sizeof(ea
->arp_sha
);
683 sdl
->sdl_rcf
= (u_short
)0;
685 * If we receive an arp from a token-ring station over
686 * a token-ring nic then try to save the source
689 if (ac
->ac_if
.if_type
== IFT_ISO88025
) {
690 th
= (struct iso88025_header
*)m
->m_pkthdr
.header
;
691 rif_len
= TR_RCF_RIFLEN(th
->rcf
);
692 if ((th
->iso88025_shost
[0] & TR_RII
) &&
694 sdl
->sdl_rcf
= th
->rcf
;
695 sdl
->sdl_rcf
^= htons(TR_RCF_DIR
);
696 memcpy(sdl
->sdl_route
, th
->rd
, rif_len
- 2);
697 sdl
->sdl_rcf
&= ~htons(TR_RCF_BCST_MASK
);
699 * Set up source routing information for
702 m
->m_data
-= rif_len
;
704 m
->m_pkthdr
.len
+= rif_len
;
706 th
->iso88025_shost
[0] &= ~TR_RII
;
710 m
->m_pkthdr
.len
+= 8;
711 th
->rcf
= sdl
->sdl_rcf
;
715 rt
->rt_expire
= time_second
+ arpt_keep
;
716 rt
->rt_flags
&= ~RTF_REJECT
;
719 dlil_output(((struct ifnet
*)ac
)->if_data
.default_proto
, la
->la_hold
, rt
,
725 if (op
!= ARPOP_REQUEST
) {
729 if (itaddr
.s_addr
== myaddr
.s_addr
) {
730 /* I am the target */
731 (void)memcpy(ea
->arp_tha
, ea
->arp_sha
, sizeof(ea
->arp_sha
));
732 (void)memcpy(ea
->arp_sha
, ac
->ac_enaddr
, sizeof(ea
->arp_sha
));
734 la
= arplookup(itaddr
.s_addr
, 0, SIN_PROXY
);
736 struct sockaddr_in sin
;
743 bzero(&sin
, sizeof sin
);
744 sin
.sin_family
= AF_INET
;
745 sin
.sin_len
= sizeof sin
;
746 sin
.sin_addr
= itaddr
;
748 rt
= rtalloc1((struct sockaddr
*)&sin
, 0, 0UL);
754 * Don't send proxies for nodes on the same interface
755 * as this one came out of, or we'll get into a fight
756 * over who claims what Ether address.
758 if (rt
->rt_ifp
== &ac
->ac_if
) {
763 (void)memcpy(ea
->arp_tha
, ea
->arp_sha
, sizeof(ea
->arp_sha
));
764 (void)memcpy(ea
->arp_sha
, ac
->ac_enaddr
, sizeof(ea
->arp_sha
));
767 printf("arp: proxying for %s\n",
772 (void)memcpy(ea
->arp_tha
, ea
->arp_sha
, sizeof(ea
->arp_sha
));
773 sdl
= SDL(rt
->rt_gateway
);
774 (void)memcpy(ea
->arp_sha
, LLADDR(sdl
), sizeof(ea
->arp_sha
));
778 (void)memcpy(ea
->arp_tpa
, ea
->arp_spa
, sizeof(ea
->arp_spa
));
779 (void)memcpy(ea
->arp_spa
, &itaddr
, sizeof(ea
->arp_spa
));
780 ea
->arp_op
= htons(ARPOP_REPLY
);
781 ea
->arp_pro
= htons(ETHERTYPE_IP
); /* let's be sure! */
782 switch (ac
->ac_if
.if_type
) {
784 /* Re-arrange the source/dest address */
785 memcpy(th
->iso88025_dhost
, th
->iso88025_shost
,
786 sizeof(th
->iso88025_dhost
));
787 memcpy(th
->iso88025_shost
, ac
->ac_enaddr
,
788 sizeof(th
->iso88025_shost
));
789 /* Set the source routing bit if neccesary */
790 if (th
->iso88025_dhost
[0] & TR_RII
) {
791 th
->iso88025_dhost
[0] &= ~TR_RII
;
792 if (TR_RCF_RIFLEN(th
->rcf
) > 2)
793 th
->iso88025_shost
[0] |= TR_RII
;
795 /* Copy the addresses, ac and fc into sa_data */
796 memcpy(sa
.sa_data
, th
->iso88025_dhost
,
797 sizeof(th
->iso88025_dhost
) * 2);
798 sa
.sa_data
[(sizeof(th
->iso88025_dhost
) * 2)] = TR_AC
;
799 sa
.sa_data
[(sizeof(th
->iso88025_dhost
) * 2) + 1] = TR_LLC_FRAME
;
804 * May not be correct for types not explictly
805 * listed, but it is our best guess.
808 eh
= (struct ether_header
*)sa
.sa_data
;
810 if (IN_LINKLOCAL(ntohl(*((u_int32_t
*)ea
->arp_spa
))))
811 (void)memcpy(eh
->ether_dhost
, etherbroadcastaddr
, sizeof(eh
->ether_dhost
));
814 (void)memcpy(eh
->ether_dhost
, ea
->arp_tha
, sizeof(eh
->ether_dhost
));
815 eh
->ether_type
= htons(ETHERTYPE_ARP
);
818 sa
.sa_family
= AF_UNSPEC
;
819 sa
.sa_len
= sizeof(sa
);
820 dlil_output(((struct ifnet
*)ac
)->if_data
.default_proto
, m
, 0, &sa
, 0);
830 register struct llinfo_arp
*la
;
832 register struct rtentry
*rt
= la
->la_rt
;
833 register struct sockaddr_dl
*sdl
;
836 if (rt
->rt_refcnt
> 0 && (sdl
= SDL(rt
->rt_gateway
)) &&
837 sdl
->sdl_family
== AF_LINK
) {
840 rt
->rt_flags
&= ~RTF_REJECT
;
843 rtrequest(RTM_DELETE
, rt_key(rt
), (struct sockaddr
*)0, rt_mask(rt
),
844 0, (struct rtentry
**)0);
847 * Lookup or enter a new address in arptab.
849 static struct llinfo_arp
*
850 arplookup(addr
, create
, proxy
)
854 register struct rtentry
*rt
;
855 static struct sockaddr_inarp sin
= {sizeof(sin
), AF_INET
};
858 sin
.sin_addr
.s_addr
= addr
;
859 sin
.sin_other
= proxy
? SIN_PROXY
: 0;
860 rt
= rtalloc1((struct sockaddr
*)&sin
, create
, 0UL);
865 if (rt
->rt_flags
& RTF_GATEWAY
)
866 why
= "host is not on local network";
867 else if ((rt
->rt_flags
& RTF_LLINFO
) == 0)
868 why
= "could not allocate llinfo";
869 else if (rt
->rt_gateway
->sa_family
!= AF_LINK
)
870 why
= "gateway route is not ours";
873 log(LOG_DEBUG
, "arplookup %s failed: %s\n",
874 inet_ntoa(sin
.sin_addr
), why
);
879 return ((struct llinfo_arp
*)rt
->rt_llinfo
);
887 if (ntohl(IA_SIN(ifa
)->sin_addr
.s_addr
) != INADDR_ANY
)
888 arprequest(ac
, &IA_SIN(ifa
)->sin_addr
,
889 &IA_SIN(ifa
)->sin_addr
, ac
->ac_enaddr
);
890 ifa
->ifa_rtrequest
= arp_rtrequest
;
891 ifa
->ifa_flags
|= RTF_CLONING
;