2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1982, 1986, 1988, 1993
27 * The Regents of the University of California. All rights reserved.
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. All advertising materials mentioning features or use of this software
38 * must display the following acknowledgement:
39 * This product includes software developed by the University of
40 * California, Berkeley and its contributors.
41 * 4. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * @(#)if_ether.c 8.1 (Berkeley) 6/10/93
58 * $FreeBSD: src/sys/netinet/if_ether.c,v 1.64.2.11 2001/07/25 17:27:56 jlemon Exp $
62 * Ethernet address resolution protocol.
64 * add "inuse/lock" bit (or ref. count) along with valid bit
67 #include <sys/param.h>
68 #include <sys/kernel.h>
69 #include <sys/queue.h>
70 #include <sys/sysctl.h>
71 #include <sys/systm.h>
73 #include <sys/malloc.h>
74 #include <sys/socket.h>
75 #include <sys/syslog.h>
78 #include <net/if_dl.h>
79 #include <net/if_types.h>
80 #include <net/route.h>
81 #include <net/netisr.h>
82 #include <net/if_llc.h>
84 #include <net/ethernet.h>
85 #include <net/bridge.h>
88 #include <netinet/in.h>
89 #include <netinet/in_var.h>
90 #include <netinet/if_ether.h>
92 #include <net/iso88025.h>
94 #define SIN(s) ((struct sockaddr_in *)s)
95 #define SDL(s) ((struct sockaddr_dl *)s)
97 SYSCTL_DECL(_net_link_ether
);
98 SYSCTL_NODE(_net_link_ether
, PF_INET
, inet
, CTLFLAG_RW
, 0, "");
101 static int arpt_prune
= (5*60*1); /* walk list every 5 minutes */
102 static int arpt_keep
= (20*60); /* once resolved, good for 20 more minutes */
103 static int arpt_down
= 20; /* once declared down, don't send for 20 sec */
105 /* Apple Hardware SUM16 checksuming */
106 int apple_hwcksum_tx
= 1;
107 int apple_hwcksum_rx
= 1;
109 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, prune_intvl
, CTLFLAG_RW
,
111 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, max_age
, CTLFLAG_RW
,
113 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, host_down_time
, CTLFLAG_RW
,
115 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, apple_hwcksum_tx
, CTLFLAG_RW
,
116 &apple_hwcksum_tx
, 0, "");
117 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, apple_hwcksum_rx
, CTLFLAG_RW
,
118 &apple_hwcksum_rx
, 0, "");
120 #define rt_expire rt_rmx.rmx_expire
123 LIST_ENTRY(llinfo_arp
) la_le
;
124 struct rtentry
*la_rt
;
125 struct mbuf
*la_hold
; /* last packet until resolved/timeout */
126 long la_asked
; /* last time we QUERIED for this addr */
127 #define la_timer la_rt->rt_rmx.rmx_expire /* deletion time in seconds */
130 static LIST_HEAD(, llinfo_arp
) llinfo_arp
;
132 struct ifqueue arpintrq
= {0, 0, 0, 50};
133 static int arp_inuse
, arp_allocated
;
135 static int arp_maxtries
= 5;
136 static int useloopback
= 1; /* use loopback interface for local traffic */
137 static int arp_proxyall
= 0;
138 static int arp_init_called
= 0;
140 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, maxtries
, CTLFLAG_RW
,
141 &arp_maxtries
, 0, "");
142 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, useloopback
, CTLFLAG_RW
,
143 &useloopback
, 0, "");
144 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, proxyall
, CTLFLAG_RW
,
145 &arp_proxyall
, 0, "");
147 void arp_rtrequest
__P((int, struct rtentry
*, struct sockaddr
*));
148 static void arprequest
__P((struct arpcom
*,
149 struct in_addr
*, struct in_addr
*, u_char
*));
150 void arpintr
__P((void));
151 static void arptfree
__P((struct llinfo_arp
*));
152 static void arptimer
__P((void *));
153 static u_char etherbroadcastaddr
[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
154 static struct llinfo_arp
155 *arplookup
__P((u_long
, int, int));
157 static void in_arpinput
__P((struct mbuf
*));
161 * Timeout routine. Age arp_tab entries periodically.
165 arptimer(ignored_arg
)
169 boolean_t funnel_state
= thread_funnel_set(network_flock
, TRUE
);
172 register struct llinfo_arp
*la
= llinfo_arp
.lh_first
;
173 struct llinfo_arp
*ola
;
175 timeout(arptimer
, (caddr_t
)0, arpt_prune
* hz
);
176 while ((ola
= la
) != 0) {
177 register struct rtentry
*rt
= la
->la_rt
;
178 la
= la
->la_le
.le_next
;
179 if (rt
->rt_expire
&& rt
->rt_expire
<= time_second
)
180 arptfree(ola
); /* timer has expired, clear */
184 (void) thread_funnel_set(network_flock
, FALSE
);
189 * Parallel to llc_rtrequest.
192 arp_rtrequest(req
, rt
, sa
)
194 register struct rtentry
*rt
;
197 register struct sockaddr
*gate
= rt
->rt_gateway
;
198 register struct llinfo_arp
*la
= (struct llinfo_arp
*)rt
->rt_llinfo
;
199 static struct sockaddr_dl null_sdl
= {sizeof(null_sdl
), AF_LINK
};
200 static int arpinit_done
;
204 LIST_INIT(&llinfo_arp
);
205 timeout(arptimer
, (caddr_t
)0, hz
);
207 register_netisr(NETISR_ARP
, arpintr
);
210 if (rt
->rt_flags
& RTF_GATEWAY
)
216 * XXX: If this is a manually added route to interface
217 * such as older version of routed or gated might provide,
218 * restore cloning bit.
220 if ((rt
->rt_flags
& RTF_HOST
) == 0 &&
221 SIN(rt_mask(rt
))->sin_addr
.s_addr
!= 0xffffffff)
222 rt
->rt_flags
|= RTF_CLONING
;
223 if (rt
->rt_flags
& RTF_CLONING
) {
225 * Case 1: This route should come from a route to iface.
227 rt_setgate(rt
, rt_key(rt
),
228 (struct sockaddr
*)&null_sdl
);
229 gate
= rt
->rt_gateway
;
230 SDL(gate
)->sdl_type
= rt
->rt_ifp
->if_type
;
231 SDL(gate
)->sdl_index
= rt
->rt_ifp
->if_index
;
232 rt
->rt_expire
= time_second
;
235 /* Announce a new entry if requested. */
236 if (rt
->rt_flags
& RTF_ANNOUNCE
)
237 arprequest((struct arpcom
*)rt
->rt_ifp
,
238 &SIN(rt_key(rt
))->sin_addr
,
239 &SIN(rt_key(rt
))->sin_addr
,
240 (u_char
*)LLADDR(SDL(gate
)));
243 if (gate
->sa_family
!= AF_LINK
||
244 gate
->sa_len
< sizeof(null_sdl
)) {
245 log(LOG_DEBUG
, "arp_rtrequest: bad gateway value\n");
248 SDL(gate
)->sdl_type
= rt
->rt_ifp
->if_type
;
249 SDL(gate
)->sdl_index
= rt
->rt_ifp
->if_index
;
251 break; /* This happens on a route change */
253 * Case 2: This route may come from cloning, or a manual route
254 * add with a LL address.
256 R_Malloc(la
, struct llinfo_arp
*, sizeof(*la
));
257 rt
->rt_llinfo
= (caddr_t
)la
;
259 log(LOG_DEBUG
, "arp_rtrequest: malloc failed\n");
262 arp_inuse
++, arp_allocated
++;
263 Bzero(la
, sizeof(*la
));
265 rt
->rt_flags
|= RTF_LLINFO
;
266 LIST_INSERT_HEAD(&llinfo_arp
, la
, la_le
);
270 * This keeps the multicast addresses from showing up
271 * in `arp -a' listings as unresolved. It's not actually
272 * functional. Then the same for broadcast.
274 if (IN_MULTICAST(ntohl(SIN(rt_key(rt
))->sin_addr
.s_addr
))) {
275 ETHER_MAP_IP_MULTICAST(&SIN(rt_key(rt
))->sin_addr
,
277 SDL(gate
)->sdl_alen
= 6;
280 if (in_broadcast(SIN(rt_key(rt
))->sin_addr
, rt
->rt_ifp
)) {
281 memcpy(LLADDR(SDL(gate
)), etherbroadcastaddr
, 6);
282 SDL(gate
)->sdl_alen
= 6;
283 rt
->rt_expire
= time_second
;
287 if (SIN(rt_key(rt
))->sin_addr
.s_addr
==
288 (IA_SIN(rt
->rt_ifa
))->sin_addr
.s_addr
) {
290 * This test used to be
291 * if (loif.if_flags & IFF_UP)
292 * It allowed local traffic to be forced
293 * through the hardware by configuring the loopback down.
294 * However, it causes problems during network configuration
295 * for boards that can't receive packets they send.
296 * It is now necessary to clear "useloopback" and remove
297 * the route to force traffic out to the hardware.
300 Bcopy(((struct arpcom
*)rt
->rt_ifp
)->ac_enaddr
,
301 LLADDR(SDL(gate
)), SDL(gate
)->sdl_alen
= 6);
312 LIST_REMOVE(la
, la_le
);
314 rt
->rt_flags
&= ~RTF_LLINFO
;
316 m_freem(la
->la_hold
);
322 * Broadcast an ARP packet, asking who has addr on interface ac.
327 struct in_addr
*addr
;
329 struct ifnet
*ifp
= (struct ifnet
*)ac
;
330 struct ifaddr
*ifa
= TAILQ_FIRST(&ifp
->if_addrhead
);
333 if (ifa
->ifa_addr
->sa_family
== AF_INET
) {
334 arprequest(ac
, &SIN(ifa
->ifa_addr
)->sin_addr
, addr
, ac
->ac_enaddr
);
337 ifa
= TAILQ_NEXT(ifa
, ifa_link
);
343 * Broadcast an ARP request. Caller specifies:
344 * - arp header source ip address
345 * - arp header target ip address
346 * - arp header source ethernet address
349 arprequest(ac
, sip
, tip
, enaddr
)
350 register struct arpcom
*ac
;
351 register struct in_addr
*sip
, *tip
;
352 register u_char
*enaddr
;
354 register struct mbuf
*m
;
355 register struct ether_header
*eh
;
356 register struct ether_arp
*ea
;
358 static u_char llcx
[] = { 0x82, 0x40, LLC_SNAP_LSAP
, LLC_SNAP_LSAP
,
359 LLC_UI
, 0x00, 0x00, 0x00, 0x08, 0x06 };
361 if ((m
= m_gethdr(M_DONTWAIT
, MT_DATA
)) == NULL
)
363 m
->m_pkthdr
.rcvif
= (struct ifnet
*)0;
364 switch (ac
->ac_if
.if_type
) {
366 m
->m_len
= sizeof(*ea
) + sizeof(llcx
);
367 m
->m_pkthdr
.len
= sizeof(*ea
) + sizeof(llcx
);
368 MH_ALIGN(m
, sizeof(*ea
) + sizeof(llcx
));
369 (void)memcpy(mtod(m
, caddr_t
), llcx
, sizeof(llcx
));
370 (void)memcpy(sa
.sa_data
, etherbroadcastaddr
, 6);
371 (void)memcpy(sa
.sa_data
+ 6, enaddr
, 6);
372 sa
.sa_data
[6] |= TR_RII
;
373 sa
.sa_data
[12] = TR_AC
;
374 sa
.sa_data
[13] = TR_LLC_FRAME
;
375 ea
= (struct ether_arp
*)(mtod(m
, char *) + sizeof(llcx
));
376 bzero((caddr_t
)ea
, sizeof (*ea
));
377 ea
->arp_hrd
= htons(ARPHRD_IEEE802
);
382 * This may not be correct for types not explicitly
383 * listed, but this is our best guess
386 m
->m_len
= sizeof(*ea
);
387 m
->m_pkthdr
.len
= sizeof(*ea
);
388 MH_ALIGN(m
, sizeof(*ea
));
389 ea
= mtod(m
, struct ether_arp
*);
390 eh
= (struct ether_header
*)sa
.sa_data
;
391 bzero((caddr_t
)ea
, sizeof (*ea
));
392 /* if_output will not swap */
393 eh
->ether_type
= htons(ETHERTYPE_ARP
);
394 (void)memcpy(eh
->ether_dhost
, etherbroadcastaddr
,
395 sizeof(eh
->ether_dhost
));
396 ea
->arp_hrd
= htons(ARPHRD_ETHER
);
399 ea
->arp_pro
= htons(ETHERTYPE_IP
);
400 ea
->arp_hln
= sizeof(ea
->arp_sha
); /* hardware address length */
401 ea
->arp_pln
= sizeof(ea
->arp_spa
); /* protocol address length */
402 ea
->arp_op
= htons(ARPOP_REQUEST
);
403 (void)memcpy(ea
->arp_sha
, enaddr
, sizeof(ea
->arp_sha
));
404 (void)memcpy(ea
->arp_spa
, sip
, sizeof(ea
->arp_spa
));
405 (void)memcpy(ea
->arp_tpa
, tip
, sizeof(ea
->arp_tpa
));
406 sa
.sa_family
= AF_UNSPEC
;
407 sa
.sa_len
= sizeof(sa
);
408 dlil_output(((struct ifnet
*)ac
)->if_data
.default_proto
, m
, 0, &sa
, 0);
412 * Resolve an IP address into an ethernet address. If success,
413 * desten is filled in. If there is no entry in arptab,
414 * set one up and broadcast a request for the IP address.
415 * Hold onto this mbuf and resend it once the address
416 * is finally resolved. A return value of 1 indicates
417 * that desten has been filled in and the packet should be sent
418 * normally; a 0 return indicates that the packet has been
419 * taken over here, either now or for later transmission.
422 arpresolve(ac
, rt
, m
, dst
, desten
, rt0
)
423 register struct arpcom
*ac
;
424 register struct rtentry
*rt
;
426 register struct sockaddr
*dst
;
427 register u_char
*desten
;
430 struct llinfo_arp
*la
= 0;
431 struct sockaddr_dl
*sdl
;
433 if (m
->m_flags
& M_BCAST
) { /* broadcast */
434 (void)memcpy(desten
, etherbroadcastaddr
, sizeof(etherbroadcastaddr
));
437 if (m
->m_flags
& M_MCAST
) { /* multicast */
438 ETHER_MAP_IP_MULTICAST(&SIN(dst
)->sin_addr
, desten
);
442 la
= (struct llinfo_arp
*)rt
->rt_llinfo
;
444 la
= arplookup(SIN(dst
)->sin_addr
.s_addr
, 1, 0);
448 if (la
== 0 || rt
== 0) {
449 log(LOG_DEBUG
, "arpresolve: can't allocate llinfo for %s%s%s\n",
450 inet_ntoa(SIN(dst
)->sin_addr
), la
? "la" : "",
455 sdl
= SDL(rt
->rt_gateway
);
457 * Check the address family and length is valid, the address
458 * is resolved; otherwise, try to resolve.
460 if ((rt
->rt_expire
== 0 || rt
->rt_expire
> time_second
) &&
461 sdl
->sdl_family
== AF_LINK
&& sdl
->sdl_alen
!= 0) {
462 bcopy(LLADDR(sdl
), desten
, sdl
->sdl_alen
);
466 * If ARP is disabled on this interface, stop.
468 * Probably should not allocate empty llinfo struct if we are
469 * not going to be sending out an arp request.
471 if (ac
->ac_if
.if_flags
& IFF_NOARP
)
474 * There is an arptab entry, but no ethernet address
475 * response yet. Replace the held mbuf with this
479 m_freem(la
->la_hold
);
482 rt
->rt_flags
&= ~RTF_REJECT
;
483 if (la
->la_asked
== 0 || rt
->rt_expire
!= time_second
) {
484 rt
->rt_expire
= time_second
;
485 if (la
->la_asked
++ < arp_maxtries
)
487 &SIN(rt
->rt_ifa
->ifa_addr
)->sin_addr
,
488 &SIN(dst
)->sin_addr
, ac
->ac_enaddr
);
490 rt
->rt_flags
|= RTF_REJECT
;
491 rt
->rt_expire
+= arpt_down
;
501 * Common length and type checks are done here,
502 * then the protocol-specific routine is called.
507 register struct mbuf
*m
;
508 register struct arphdr
*ar
;
511 while (arpintrq
.ifq_head
) {
513 IF_DEQUEUE(&arpintrq
, m
);
515 if (m
== 0 || (m
->m_flags
& M_PKTHDR
) == 0)
518 if (m
->m_len
< sizeof(struct arphdr
) &&
519 ((m
= m_pullup(m
, sizeof(struct arphdr
))) == NULL
)) {
520 log(LOG_ERR
, "arp: runt packet -- m_pullup failed\n");
523 ar
= mtod(m
, struct arphdr
*);
525 if (ntohs(ar
->ar_hrd
) != ARPHRD_ETHER
526 && ntohs(ar
->ar_hrd
) != ARPHRD_IEEE802
) {
528 "arp: unknown hardware address format (0x%2D)\n",
529 (unsigned char *)&ar
->ar_hrd
, "");
534 if (m
->m_pkthdr
.len
< sizeof(struct arphdr
) + 2 * ar
->ar_hln
536 log(LOG_ERR
, "arp: runt packet\n");
541 switch (ntohs(ar
->ar_pro
)) {
554 * ARP for Internet protocols on 10 Mb/s Ethernet.
555 * Algorithm is that given in RFC 826.
556 * In addition, a sanity check is performed on the sender
557 * protocol address, to catch impersonators.
558 * We no longer handle negotiations for use of trailer protocol:
559 * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent
560 * along with IP replies if we wanted trailers sent to us,
561 * and also sent them in response to IP replies.
562 * This allowed either end to announce the desire to receive
564 * We no longer reply to requests for ETHERTYPE_TRAIL protocol either,
565 * but formerly didn't normally send requests.
567 static int log_arp_wrong_iface
= 0;
569 SYSCTL_INT(_net_link_ether_inet
, OID_AUTO
, log_arp_wrong_iface
, CTLFLAG_RW
,
570 &log_arp_wrong_iface
, 0,
571 "log arp packets arriving on the wrong interface");
577 register struct ether_arp
*ea
;
578 register struct arpcom
*ac
= (struct arpcom
*)m
->m_pkthdr
.rcvif
;
579 struct ether_header
*eh
;
580 struct iso88025_header
*th
= (struct iso88025_header
*)0;
581 register struct llinfo_arp
*la
= 0;
582 register struct rtentry
*rt
;
583 struct in_ifaddr
*ia
, *maybe_ia
= 0;
584 struct sockaddr_dl
*sdl
;
586 struct in_addr isaddr
, itaddr
, myaddr
;
588 unsigned char buf
[18];
589 unsigned char buf2
[18];
591 if (m
->m_len
< sizeof(struct ether_arp
) &&
592 (m
= m_pullup(m
, sizeof(struct ether_arp
))) == NULL
) {
593 log(LOG_ERR
, "in_arp: runt packet -- m_pullup failed\n");
597 ea
= mtod(m
, struct ether_arp
*);
598 op
= ntohs(ea
->arp_op
);
599 (void)memcpy(&isaddr
, ea
->arp_spa
, sizeof (isaddr
));
600 (void)memcpy(&itaddr
, ea
->arp_tpa
, sizeof (itaddr
));
603 /* Don't respond to requests for 0.0.0.0 */
604 if (itaddr
.s_addr
== 0 && op
== ARPOP_REQUEST
) {
610 for (ia
= in_ifaddrhead
.tqh_first
; ia
; ia
= ia
->ia_link
.tqe_next
) {
612 * For a bridge, we want to check the address irrespective
613 * of the receive interface. (This will change slightly
614 * when we have clusters of interfaces).
617 #define BRIDGE_TEST (do_bridge)
619 #define BRIDGE_TEST (0) /* cc will optimise the test away */
621 if ((BRIDGE_TEST
) || (ia
->ia_ifp
== &ac
->ac_if
)) {
623 if ((itaddr
.s_addr
== ia
->ia_addr
.sin_addr
.s_addr
) ||
624 (isaddr
.s_addr
== ia
->ia_addr
.sin_addr
.s_addr
)) {
633 myaddr
= ia
? ia
->ia_addr
.sin_addr
: maybe_ia
->ia_addr
.sin_addr
;
634 if (!bcmp((caddr_t
)ea
->arp_sha
, (caddr_t
)ac
->ac_enaddr
,
635 sizeof (ea
->arp_sha
))) {
636 m_freem(m
); /* it's from me, ignore it. */
639 if (!bcmp((caddr_t
)ea
->arp_sha
, (caddr_t
)etherbroadcastaddr
,
640 sizeof (ea
->arp_sha
))) {
642 "arp: ether address is broadcast for IP address %s!\n",
647 if (isaddr
.s_addr
== myaddr
.s_addr
) {
648 struct kev_msg ev_msg
;
649 struct kev_in_collision
*in_collision
;
650 u_char storage
[sizeof(struct kev_in_collision
) + 6];
651 in_collision
= (struct kev_in_collision
*)storage
;
654 "duplicate IP address %s sent from ethernet address %s\n",
655 inet_ntoa(isaddr
), ether_sprintf(buf
, ea
->arp_sha
));
657 /* Send a kernel event so anyone can learn of the conflict */
658 in_collision
->link_data
.if_family
= ac
->ac_if
.if_family
;
659 in_collision
->link_data
.if_unit
= ac
->ac_if
.if_unit
;
660 strncpy(&in_collision
->link_data
.if_name
[0], ac
->ac_if
.if_name
, IFNAMSIZ
);
661 in_collision
->ia_ipaddr
= isaddr
;
662 in_collision
->hw_len
= ETHER_ADDR_LEN
;
663 bcopy((caddr_t
)ea
->arp_sha
, (caddr_t
)in_collision
->hw_addr
, sizeof(ea
->arp_sha
));
664 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
665 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
666 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
667 ev_msg
.event_code
= KEV_INET_ARPCOLLISION
;
668 ev_msg
.dv
[0].data_ptr
= in_collision
;
669 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_collision
) + 6;
670 ev_msg
.dv
[1].data_length
= 0;
671 kev_post_msg(&ev_msg
);
676 la
= arplookup(isaddr
.s_addr
, itaddr
.s_addr
== myaddr
.s_addr
, 0);
677 if (la
&& (rt
= la
->la_rt
) && (sdl
= SDL(rt
->rt_gateway
))) {
678 /* the following is not an error when doing bridging */
679 if (!BRIDGE_TEST
&& rt
->rt_ifp
!= &ac
->ac_if
) {
680 if (log_arp_wrong_iface
)
681 log(LOG_ERR
, "arp: %s is on %s%d but got reply from %s on %s%d\n",
683 rt
->rt_ifp
->if_name
, rt
->rt_ifp
->if_unit
,
684 ether_sprintf(buf
, ea
->arp_sha
),
685 ac
->ac_if
.if_name
, ac
->ac_if
.if_unit
);
689 bcmp((caddr_t
)ea
->arp_sha
, LLADDR(sdl
), sdl
->sdl_alen
)) {
691 log(LOG_INFO
, "arp: %s moved from %s to %s on %s%d\n",
693 ether_sprintf(buf
, (u_char
*)LLADDR(sdl
)),
694 ether_sprintf(buf2
, ea
->arp_sha
),
695 ac
->ac_if
.if_name
, ac
->ac_if
.if_unit
);
698 "arp: %s attempts to modify permanent entry for %s on %s%d",
699 ether_sprintf(buf
, ea
->arp_sha
), inet_ntoa(isaddr
),
700 ac
->ac_if
.if_name
, ac
->ac_if
.if_unit
);
704 (void)memcpy(LLADDR(sdl
), ea
->arp_sha
, sizeof(ea
->arp_sha
));
705 sdl
->sdl_alen
= sizeof(ea
->arp_sha
);
708 sdl
->sdl_rcf
= (u_short
)0;
710 * If we receive an arp from a token-ring station over
711 * a token-ring nic then try to save the source
714 if (ac
->ac_if
.if_type
== IFT_ISO88025
) {
715 th
= (struct iso88025_header
*)m
->m_pkthdr
.header
;
716 rif_len
= TR_RCF_RIFLEN(th
->rcf
);
717 if ((th
->iso88025_shost
[0] & TR_RII
) &&
719 sdl
->sdl_rcf
= th
->rcf
;
720 sdl
->sdl_rcf
^= htons(TR_RCF_DIR
);
721 memcpy(sdl
->sdl_route
, th
->rd
, rif_len
- 2);
722 sdl
->sdl_rcf
&= ~htons(TR_RCF_BCST_MASK
);
724 * Set up source routing information for
727 m
->m_data
-= rif_len
;
729 m
->m_pkthdr
.len
+= rif_len
;
731 th
->iso88025_shost
[0] &= ~TR_RII
;
735 m
->m_pkthdr
.len
+= 8;
736 th
->rcf
= sdl
->sdl_rcf
;
740 rt
->rt_expire
= time_second
+ arpt_keep
;
741 rt
->rt_flags
&= ~RTF_REJECT
;
744 dlil_output(((struct ifnet
*)ac
)->if_data
.default_proto
, la
->la_hold
, rt
,
750 if (op
!= ARPOP_REQUEST
) {
754 if (itaddr
.s_addr
== myaddr
.s_addr
) {
755 /* I am the target */
756 (void)memcpy(ea
->arp_tha
, ea
->arp_sha
, sizeof(ea
->arp_sha
));
757 (void)memcpy(ea
->arp_sha
, ac
->ac_enaddr
, sizeof(ea
->arp_sha
));
759 la
= arplookup(itaddr
.s_addr
, 0, SIN_PROXY
);
761 struct sockaddr_in sin
;
768 bzero(&sin
, sizeof sin
);
769 sin
.sin_family
= AF_INET
;
770 sin
.sin_len
= sizeof sin
;
771 sin
.sin_addr
= itaddr
;
773 rt
= rtalloc1((struct sockaddr
*)&sin
, 0, 0UL);
779 * Don't send proxies for nodes on the same interface
780 * as this one came out of, or we'll get into a fight
781 * over who claims what Ether address.
783 if (rt
->rt_ifp
== &ac
->ac_if
) {
788 (void)memcpy(ea
->arp_tha
, ea
->arp_sha
, sizeof(ea
->arp_sha
));
789 (void)memcpy(ea
->arp_sha
, ac
->ac_enaddr
, sizeof(ea
->arp_sha
));
792 printf("arp: proxying for %s\n",
797 (void)memcpy(ea
->arp_tha
, ea
->arp_sha
, sizeof(ea
->arp_sha
));
798 sdl
= SDL(rt
->rt_gateway
);
799 (void)memcpy(ea
->arp_sha
, LLADDR(sdl
), sizeof(ea
->arp_sha
));
803 (void)memcpy(ea
->arp_tpa
, ea
->arp_spa
, sizeof(ea
->arp_spa
));
804 (void)memcpy(ea
->arp_spa
, &itaddr
, sizeof(ea
->arp_spa
));
805 ea
->arp_op
= htons(ARPOP_REPLY
);
806 ea
->arp_pro
= htons(ETHERTYPE_IP
); /* let's be sure! */
807 switch (ac
->ac_if
.if_type
) {
809 /* Re-arrange the source/dest address */
810 memcpy(th
->iso88025_dhost
, th
->iso88025_shost
,
811 sizeof(th
->iso88025_dhost
));
812 memcpy(th
->iso88025_shost
, ac
->ac_enaddr
,
813 sizeof(th
->iso88025_shost
));
814 /* Set the source routing bit if neccesary */
815 if (th
->iso88025_dhost
[0] & TR_RII
) {
816 th
->iso88025_dhost
[0] &= ~TR_RII
;
817 if (TR_RCF_RIFLEN(th
->rcf
) > 2)
818 th
->iso88025_shost
[0] |= TR_RII
;
820 /* Copy the addresses, ac and fc into sa_data */
821 memcpy(sa
.sa_data
, th
->iso88025_dhost
,
822 sizeof(th
->iso88025_dhost
) * 2);
823 sa
.sa_data
[(sizeof(th
->iso88025_dhost
) * 2)] = TR_AC
;
824 sa
.sa_data
[(sizeof(th
->iso88025_dhost
) * 2) + 1] = TR_LLC_FRAME
;
829 * May not be correct for types not explictly
830 * listed, but it is our best guess.
833 eh
= (struct ether_header
*)sa
.sa_data
;
835 if (IN_LINKLOCAL(ntohl(*((u_int32_t
*)ea
->arp_spa
))))
836 (void)memcpy(eh
->ether_dhost
, etherbroadcastaddr
, sizeof(eh
->ether_dhost
));
839 (void)memcpy(eh
->ether_dhost
, ea
->arp_tha
, sizeof(eh
->ether_dhost
));
840 eh
->ether_type
= htons(ETHERTYPE_ARP
);
843 sa
.sa_family
= AF_UNSPEC
;
844 sa
.sa_len
= sizeof(sa
);
845 dlil_output(((struct ifnet
*)ac
)->if_data
.default_proto
, m
, 0, &sa
, 0);
855 register struct llinfo_arp
*la
;
857 register struct rtentry
*rt
= la
->la_rt
;
858 register struct sockaddr_dl
*sdl
;
861 if (rt
->rt_refcnt
> 0 && (sdl
= SDL(rt
->rt_gateway
)) &&
862 sdl
->sdl_family
== AF_LINK
) {
865 rt
->rt_flags
&= ~RTF_REJECT
;
868 rtrequest(RTM_DELETE
, rt_key(rt
), (struct sockaddr
*)0, rt_mask(rt
),
869 0, (struct rtentry
**)0);
872 * Lookup or enter a new address in arptab.
874 static struct llinfo_arp
*
875 arplookup(addr
, create
, proxy
)
879 register struct rtentry
*rt
;
880 static struct sockaddr_inarp sin
= {sizeof(sin
), AF_INET
};
883 sin
.sin_addr
.s_addr
= addr
;
884 sin
.sin_other
= proxy
? SIN_PROXY
: 0;
885 rt
= rtalloc1((struct sockaddr
*)&sin
, create
, 0UL);
890 if (rt
->rt_flags
& RTF_GATEWAY
) {
891 why
= "host is not on local network";
893 /* If there are no references to this route, purge it */
894 if (rt
->rt_refcnt
<= 0 && (rt
->rt_flags
& RTF_WASCLONED
) != 0) {
895 rtrequest(RTM_DELETE
,
896 (struct sockaddr
*)rt_key(rt
),
897 rt
->rt_gateway
, rt_mask(rt
),
901 else if ((rt
->rt_flags
& RTF_LLINFO
) == 0)
902 why
= "could not allocate llinfo";
903 else if (rt
->rt_gateway
->sa_family
!= AF_LINK
)
904 why
= "gateway route is not ours";
907 log(LOG_DEBUG
, "arplookup %s failed: %s\n",
908 inet_ntoa(sin
.sin_addr
), why
);
913 return ((struct llinfo_arp
*)rt
->rt_llinfo
);
921 if (ntohl(IA_SIN(ifa
)->sin_addr
.s_addr
) != INADDR_ANY
)
922 arprequest(ac
, &IA_SIN(ifa
)->sin_addr
,
923 &IA_SIN(ifa
)->sin_addr
, ac
->ac_enaddr
);
924 ifa
->ifa_rtrequest
= arp_rtrequest
;
925 ifa
->ifa_flags
|= RTF_CLONING
;