Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 8 Dec 2010 03:19:14 +0800
From:      rozhuk.im@gmail.com
To:        <freebsd-net@freebsd.org>
Subject:   [arp] possible DoS, fixes and improvements
Message-ID:  <4cfe88b6.1cedd80a.33f5.119d@mx.google.com>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.

------=_NextPart_000_0065_01CB9686.B27BE840
Content-Type: text/plain;
	charset="windows-1251"
Content-Transfer-Encoding: quoted-printable

Hi!


1. ah->ar_hln - is depend from ar_hrd?
Yes, and for ARPHRD_ETHER is 6 (ETHER_ADDR_LEN)
For ARPHRD_IEEE1394 - sizeof(struct fw_hwaddr)
ah->ar_hln ignored in ether_output: bcopy(ar_tha(ah), edst, =
ETHER_ADDR_LEN);

check in in_arpinput:
		if (ifp->if_addrlen !=3D ah->ar_hln) {
			LLE_WUNLOCK(la);
			log(LOG_WARNING,
			    "arp from %*D: addr len: new %d, i/f %d
(ignored)",
			    ifp->if_addrlen, (u_char *) ar_sha(ah), ":",
			    ah->ar_hln, ifp->if_addrlen);
			goto reply;
		}
NO DROP!!!!
In reply we get:
		(void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
		(void)memcpy(ar_sha(ah), enaddr, ah->ar_hln);
Or=20
			(void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
			(void)memcpy(ar_sha(ah), &lle->ll_addr, ah->ar_hln);

How to use it see below.


2. ah->ar_pln - does not checked!
We can make big arp request (512 nulls after struct arphdr + 2*6 + 2*4) =
,
valid for host, set ar_plt =3D 255
And in reply will receive part of stack or core panic:
in_arpinput:
(void)memcpy(ar_spa(ah), &itaddr, ah->ar_pln);
...
m->m_len =3D sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln);
( eq arphdr_len(ah) )



3. ar_sha(ah) - does not checked for multicast!
Answers to request my be send to multicast addrs
Only broadcast and host addr are checked.
No check is ar_sha(ah) equal to Ethernet.ether_shost
As result:
arp -an
? (172.16.0.2) at 01:80:c2:00:00:01 on em0 expires in 118 seconds =
[ethernet]



4. holded packet my be sended without any locks

Current:
		if (la->la_hold !=3D NULL) {
			struct mbuf *m_hold, *m_hold_next;

			bcopy(L3_ADDR(la), &sa, sizeof(sa));
			LLE_WUNLOCK(la);
			for (m_hold =3D la->la_hold, la->la_hold =3D NULL;
			     m_hold !=3D NULL; m_hold =3D m_hold_next) {
				m_hold_next =3D m_hold->m_nextpkt;
				m_hold->m_nextpkt =3D NULL;
				(*ifp->if_output)(ifp, m_hold, &sa, NULL);
			}
		} else
			LLE_WUNLOCK(la);
		la->la_hold =3D NULL;
		la->la_numheld =3D 0;

Here we unlock la and then modify them - this is bad idea!
Patched - see in attached patch.


This sample will work only for Ethernet without locks
if_output -> call arplookup again for every packet for sa_family =3D =
AF_INET
AF_UNSPEC - just copy ether_type/arc_type/... and L2 addr from =
dst->sa_data

		struct mbuf *m_hold, *m_hold_next;
		struct sockaddr dst;

		m_hold =3D la->la_hold;
		if (m_hold !=3D NULL) {
			dst.sa_len =3D sizeof(dst);
			dst.sa_family =3D AF_UNSPEC;	/* prevent call
arpresolve, we know L2 addr dst */

			switch (ntohs(ah->ar_hrd)){
			case ARPHRD_ETHER:
				((struct
ether_header*)&dst.sa_data)->ether_type =3D ah->ar_pro;
				bcopy(ar_sha(ah), ((struct
ether_header*)&dst.sa_data)->ether_dhost, ah->ar_hln);
				break;
			//case ARPHRD_IEEE802:
			//	break;
			//case ARPHRD_ARCNET:
			//	((struct arc_header
*)&dst.sa_data)->arc_type =3D ah->ar_pro;
			//	bcopy(ar_sha(ah), ((struct arc_header
*)&dst.sa_data)->arc_dhost, ah->ar_hln);
			//	break;
			//case ARPHRD_FRELAY:
			//	break;
			//case ARPHRD_IEEE1394:
			//	break;
			default:
				bcopy(L3_ADDR(la), &dst, sizeof(dst));
			}
		}
		la->la_hold =3D NULL;
		la->la_numheld =3D 0;

		LLE_WUNLOCK(la);

		for (; m_hold !=3D NULL; m_hold =3D m_hold_next) {
			m_hold_next =3D m_hold->m_nextpkt;
			m_hold->m_nextpkt =3D NULL;
			(*ifp->if_output)(ifp, m_hold, &dst, NULL);
		}

Do I need include this improvement in next patch?


Will attached patch included in mainstream code?



PS: patch contain fixes and some code cleanup and improvements.
Only basics tests done, not tested in production.


PPS: tests for 1 and 2
Part of code to generate arp packet

	struct arphdr *ah;
	u_char buff[2048];
	u_int32_t src, dst;

	bzero(buff, sizeof(buff));
	ah =3D (struct arphdr *)buff;

	src =3D INET_ADDR(172,16,0,2);
	dst =3D INET_ADDR(172,16,0,254);// - target!

	ah->ar_hrd =3D htons(ARPHRD_ETHER);
	ah->ar_pro =3D htons(ETHERTYPE_IP);
	ah->ar_op =3D htons(ARPOP_REQUEST);
	ah->ar_hln =3D 255;//ETHER_ADDR_LEN;
	ah->ar_pln =3D 255;//INET_ADDR_LEN;
	ETHER_ADDR_COPY(ar_sha(ah), ether_shost);
	INET_ADDR_COPY(ar_spa(ah), &src);
	INET_ADDR_COPY(ar_tpa(ah), &dst);

send_ether(bpf, ether_dhost, ether_shost, ETHERTYPE_ARP, (u_char*)ah, =
1200);

returned answer is 1042 bytes size, no core panic
tested on my home freebsd box (i386, 8.2 @ E5300), with custom kernel


0x0030 x 0000 0000 0018 0000 0000 0000 00ff ffff x ................
0x0040 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0050 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0060 x 0000 0000 0000 0000 0000 0000 0000 6a2f x ..............j/
0x0070 x c5a0 522f c580 552f c500 412f c500 0008 x ..R/..U/..A/....
0x0080 x f100 0000 f101 b000 0000 000a f100 0000 x ................
0x0090 x 0000 0000 0000 0000 0086 801f a086 80d3 x ................
0x00A0 x 1007 0010 0002 0000 0000 0801 1100 0000 x ................
0x00B0 x 0006 0000 0000 0000 0002 0000 0022 c8cc x ............."..
0x00C0 x cecf 0000 0000 0000 0000 0000 0000 0000 x ................
0x00D0 x 0000 0000 0000 0000 0000 0000 0080 00d0 x ................
0x00E0 x 0100 0000 0000 0000 0000 0000 0000 0000 x ................
0x00F0 x 0000 0000 0004 8005 00a0 1c1c 0000 0000 x ................
0x0100 x 0000 2000 0003 00ac 1000 feac 1000 0210 x ................
0x0110 x 0200 00ac 1000 0200 0000 0000 0000 00a0 x ................
0x0120 x 3520 c570 3820 c5a0 3520 c5a0 3520 c502 x 5..p8...5...5...
0x0130 x e249 fb00 0000 0000 8121 c900 58c2 c07c x .I.......!..X..|
0x0140 x 7cdb c4ea 6856 c000 8121 c9c0 066c c001 x |...hV...!...l..
0x0150 x 0000 0002 0000 0060 7cdb c4a0 3520 c5a0 x .......`|...5...
0x0160 x 3520 c5c4 0000 007f ffff ff80 0000 00cc x 5...............
0x0170 x 59c2 c001 0000 0007 0000 00c0 c31e c500 x Y...............
0x0180 x 5e1c c5a0 3520 c5ac 7cdb c49e 0d49 c000 x ^...5...|....I..
0x0190 x 58c2 c0ec e64b c000 0000 0009 0100 0047 x X....K.........G
0x01A0 x d152 e8a0 3520 c500 0000 0000 5e1c c530 x .R..5.......^..0
0x01B0 x d11e c5a0 3520 c5dc 7cdb c43e 2649 c0a0 x ....5...|..>&I..
0x01C0 x 1a20 c500 5e1c c57d c565 c02d 0500 0070 x ....^..}.e.-...p
0x01D0 x 5e1c c56c 5e1c c5a0 1a20 c530 d11e c5a0 x ^..l^......0....
0x01E0 x 3520 c500 0000 0014 7ddb c4fd e948 c030 x 5.......}....H.0
0x01F0 x d11e c528 7ddb c400 0000 0000 0000 0000 x ...(}...........
0x0200 x 0000 0000 0000 001d 0ff2 4b4a 0000 0000 x ..........KJ....
0x0210 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0220 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0230 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0240 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0250 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0260 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0270 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0280 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0290 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x02A0 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x02B0 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x02C0 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x02D0 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x02E0 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x02F0 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0300 x 0000 0000 00ac 1000 0200 0000 0000 0000 x ................
0x0310 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0320 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0330 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0340 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0350 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0360 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0370 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0380 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0390 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x03A0 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x03B0 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x03C0 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x03D0 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x03E0 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x03F0 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0400 x 0000 0000                               x ....




ah->ar_hln =3D ETHER_ADDR_LEN; // =3D 6
ah->ar_pln =3D 255;//INET_ADDR_LEN;

0x0000 x 0001 0800 06ff 0002 001b 214f f5b3 ac10 x ..........!O....
0x0010 x 00fe ac10 0002 1002 0000 ac10 0002 0000 x ................
0x0020 x 0000 0000 0000 a035 20c5 0000 0000 a035 x .......5.......5
0x0030 x 20c5 a035 20c5 02e2 49fb 0000 0000 00c4 x ...5....I.......
0x0040 x 26c9 0058 c2c0 7c7c dbc4 ea68 56c0 00c4 x &..X..||...hV...
0x0050 x 26c9 c006 6cc0 0100 0000 0200 0000 607c x &...l.........`|
0x0060 x dbc4 a035 20c5 a035 20c5 c400 0000 7fff x ...5...5........
0x0070 x ffff 8000 0000 cc59 c2c0 0100 0000 0700 x .......Y........
0x0080 x 0000 c0c3 1ec5 005e 1cc5 a035 20c5 ac7c x .......^...5...|
0x0090 x dbc4 9e0d 49c0 0058 c2c0 ece6 4bc0 0000 x ....I..X....K...
0x00A0 x 0000 0901 0000 dedc 6b6f a035 20c5 0000 x ........ko.5....
0x00B0 x 0000 005e 1cc5 30d1 1ec5 a035 20c5 dc7c x ...^..0....5...|
0x00C0 x dbc4 3e26 49c0 a01a 20c5 005e 1cc5 7dc5 x ..>&I......^..}.
0x00D0 x 65c0 2d05 0000 705e 1cc5 6c5e 1cc5 a01a x e.-...p^..l^....
0x00E0 x 20c5 30d1 1ec5 a035 20c5 0000 0000 147d x ..0....5.......}
0x00F0 x dbc4 fde9 48c0 30d1 1ec5 287d dbc4 0000 x ....H.0...(}....
0x0100 x 0000 0000 0000 0000 0000 0000 0000 1d0f x ................
0x0110 x f24b 4aac 1000 0200 0000 0000 0000 0000 x .KJ.............
0x0120 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0130 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0140 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0150 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0160 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0170 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0180 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0190 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x01A0 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x01B0 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x01C0 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x01D0 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x01E0 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x01F0 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0200 x 0000 0000 0000 0000 0000 0000 0000 0000 x ................
0x0210 x 0000                                    x ..


=A0
--
Rozhuk Ivan
=A0=20



------=_NextPart_000_0065_01CB9686.B27BE840
Content-Type: application/octet-stream;
	name="if_ether.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="if_ether.patch"

--- /usr/src/sys/netinet/if_ether.orig	2010-12-02 16:52:06.000000000 =
+0800=0A=
+++ /usr/src/sys/netinet/if_ether.c	2010-12-08 02:49:07.000000000 +0800=0A=
@@ -57,6 +57,9 @@=0A=
 #include <net/netisr.h>=0A=
 #include <net/if_llc.h>=0A=
 #include <net/ethernet.h>=0A=
+#include <net/iso88025.h>=0A=
+#include <net/if_arc.h>=0A=
+#include <net/firewire.h>=0A=
 #include <net/route.h>=0A=
 #include <net/vnet.h>=0A=
 =0A=
@@ -246,7 +249,7 @@=0A=
 	m->m_pkthdr.len =3D m->m_len;=0A=
 	MH_ALIGN(m, m->m_len);=0A=
 	ah =3D mtod(m, struct arphdr *);=0A=
-	bzero((caddr_t)ah, m->m_len);=0A=
+	bzero(ah, m->m_len);=0A=
 #ifdef MAC=0A=
 	mac_netinet_arp_send(ifp, m);=0A=
 #endif=0A=
@@ -254,9 +257,9 @@=0A=
 	ah->ar_hln =3D ifp->if_addrlen;		/* hardware address length */=0A=
 	ah->ar_pln =3D sizeof(struct in_addr);	/* protocol address length */=0A=
 	ah->ar_op =3D htons(ARPOP_REQUEST);=0A=
-	bcopy((caddr_t)enaddr, (caddr_t)ar_sha(ah), ah->ar_hln);=0A=
-	bcopy((caddr_t)sip, (caddr_t)ar_spa(ah), ah->ar_pln);=0A=
-	bcopy((caddr_t)tip, (caddr_t)ar_tpa(ah), ah->ar_pln);=0A=
+	bcopy(enaddr, ar_sha(ah), ah->ar_hln);=0A=
+	bcopy(sip, ar_spa(ah), ah->ar_pln);=0A=
+	bcopy(tip, ar_tpa(ah), ah->ar_pln);=0A=
 	sa.sa_family =3D AF_ARP;=0A=
 	sa.sa_len =3D 2;=0A=
 	m->m_flags |=3D M_BCAST;=0A=
@@ -292,8 +295,7 @@=0A=
 	if (m !=3D NULL) {=0A=
 		if (m->m_flags & M_BCAST) {=0A=
 			/* broadcast */=0A=
-			(void)memcpy(desten,=0A=
-			    ifp->if_broadcastaddr, ifp->if_addrlen);=0A=
+			bcopy(ifp->if_broadcastaddr, desten, ifp->if_addrlen);=0A=
 			return (0);=0A=
 		}=0A=
 		if (m->m_flags & M_MCAST && ifp->if_type !=3D IFT_ARCNET) {=0A=
@@ -429,42 +431,68 @@=0A=
 static void=0A=
 arpintr(struct mbuf *m)=0A=
 {=0A=
-	struct arphdr *ar;=0A=
+	struct arphdr *ah;=0A=
 =0A=
 	if (m->m_len < sizeof(struct arphdr) &&=0A=
 	    ((m =3D m_pullup(m, sizeof(struct arphdr))) =3D=3D NULL)) {=0A=
 		log(LOG_ERR, "arp: runt packet -- m_pullup failed\n");=0A=
 		return;=0A=
 	}=0A=
-	ar =3D mtod(m, struct arphdr *);=0A=
+	ah =3D mtod(m, struct arphdr *);=0A=
 =0A=
-	if (ntohs(ar->ar_hrd) !=3D ARPHRD_ETHER &&=0A=
-	    ntohs(ar->ar_hrd) !=3D ARPHRD_IEEE802 &&=0A=
-	    ntohs(ar->ar_hrd) !=3D ARPHRD_ARCNET &&=0A=
-	    ntohs(ar->ar_hrd) !=3D ARPHRD_IEEE1394) {=0A=
-		log(LOG_ERR, "arp: unknown hardware address format (0x%2D)\n",=0A=
-		    (unsigned char *)&ar->ar_hrd, "");=0A=
-		m_freem(m);=0A=
-		return;=0A=
+	/* check hw addr len and hw addr */=0A=
+	switch (ntohs(ah->ar_hrd)){=0A=
+	case ARPHRD_ETHER:=0A=
+		if (ah->ar_hln !=3D ETHER_ADDR_LEN) {=0A=
+			log(LOG_ERR, "arp: invalid length of hardware address\n");=0A=
+			goto drop;=0A=
+		}=0A=
+		/* is from [multi/broad]cast? - sender cant be [multi/broad]cast! */=0A=
+		if (ETHER_IS_MULTICAST(ar_sha(ah)) !=3D 0) {=0A=
+			log(LOG_ERR, "arp: link address is multicast\n");=0A=
+			goto drop;=0A=
+		}=0A=
+		break;=0A=
+	case ARPHRD_IEEE802:=0A=
+		if (ah->ar_hln !=3D ISO88025_ADDR_LEN)=0A=
+			goto drop;=0A=
+		break;=0A=
+	case ARPHRD_ARCNET:=0A=
+		if (ah->ar_hln !=3D ARC_ADDR_LEN)=0A=
+			goto drop;=0A=
+		break;=0A=
+	case ARPHRD_FRELAY:=0A=
+		if (ah->ar_hln !=3D 2)=0A=
+			goto drop;=0A=
+		break;=0A=
+	case ARPHRD_IEEE1394:=0A=
+		if (ah->ar_hln !=3D sizeof(struct fw_hwaddr)) /* XXX 8? */=0A=
+			goto drop;=0A=
+		break;=0A=
+	default:=0A=
+		log(LOG_ERR, "arp: unknown hardware address format\n");=0A=
+		goto drop;=0A=
 	}=0A=
 =0A=
-	if (m->m_len < arphdr_len(ar)) {=0A=
-		if ((m =3D m_pullup(m, arphdr_len(ar))) =3D=3D NULL) {=0A=
+	if (m->m_len < arphdr_len(ah)) {=0A=
+		if ((m =3D m_pullup(m, arphdr_len(ah))) =3D=3D NULL) {=0A=
 			log(LOG_ERR, "arp: runt packet\n");=0A=
-			m_freem(m);=0A=
 			return;=0A=
 		}=0A=
-		ar =3D mtod(m, struct arphdr *);=0A=
+		ah =3D mtod(m, struct arphdr *);=0A=
 	}=0A=
 =0A=
 	ARPSTAT_INC(received);=0A=
-	switch (ntohs(ar->ar_pro)) {=0A=
+	switch (ntohs(ah->ar_pro)) {=0A=
 #ifdef INET=0A=
 	case ETHERTYPE_IP:=0A=
 		in_arpinput(m);=0A=
 		return;=0A=
 #endif=0A=
 	}=0A=
+=0A=
+	log(LOG_ERR, "arp: unknown format of protocol address\n");=0A=
+drop:=0A=
 	m_freem(m);=0A=
 }=0A=
 =0A=
@@ -507,11 +535,10 @@=0A=
 	struct rtentry *rt;=0A=
 	struct ifaddr *ifa;=0A=
 	struct in_ifaddr *ia;=0A=
-	struct sockaddr sa;=0A=
+	struct sockaddr dst;=0A=
 	struct in_addr isaddr, itaddr, myaddr;=0A=
 	u_int8_t *enaddr =3D NULL;=0A=
 	int op, flags;=0A=
-	int req_len;=0A=
 	int bridged =3D 0, is_bridge =3D 0;=0A=
 	int carp_match =3D 0;=0A=
 	struct sockaddr_in sin;=0A=
@@ -519,25 +546,25 @@=0A=
 	sin.sin_family =3D AF_INET;=0A=
 	sin.sin_addr.s_addr =3D 0;=0A=
 =0A=
-	if (ifp->if_bridge)=0A=
-		bridged =3D 1;=0A=
-	if (ifp->if_type =3D=3D IFT_BRIDGE)=0A=
-		is_bridge =3D 1;=0A=
 =0A=
-	req_len =3D arphdr_len2(ifp->if_addrlen, sizeof(struct in_addr));=0A=
-	if (m->m_len < req_len && (m =3D m_pullup(m, req_len)) =3D=3D NULL) {=0A=
-		log(LOG_ERR, "in_arp: runt packet -- m_pullup failed\n");=0A=
-		return;=0A=
+	ah =3D mtod(m, struct arphdr *);=0A=
+	if (ah->ar_pln !=3D sizeof(struct in_addr)) {=0A=
+		log(LOG_ERR, "arp: invalid length of protocol address\n");=0A=
+		goto drop;=0A=
 	}=0A=
 =0A=
-	ah =3D mtod(m, struct arphdr *);=0A=
 	op =3D ntohs(ah->ar_op);=0A=
-	(void)memcpy(&isaddr, ar_spa(ah), sizeof (isaddr));=0A=
-	(void)memcpy(&itaddr, ar_tpa(ah), sizeof (itaddr));=0A=
+	bcopy(ar_spa(ah), &isaddr, sizeof (isaddr));=0A=
+	bcopy(ar_tpa(ah), &itaddr, sizeof (itaddr));=0A=
 =0A=
 	if (op =3D=3D ARPOP_REPLY)=0A=
 		ARPSTAT_INC(rxreplies);=0A=
 =0A=
+	if (ifp->if_bridge)=0A=
+		bridged =3D 1;=0A=
+	if (ifp->if_type =3D=3D IFT_BRIDGE)=0A=
+		is_bridge =3D 1;=0A=
+=0A=
 	/*=0A=
 	 * For a bridge, we want to check the address irrespective=0A=
 	 * of the receive interface. (This will change slightly=0A=
@@ -626,6 +653,15 @@=0A=
 		enaddr =3D (u_int8_t *)IF_LLADDR(ifp);=0A=
 	myaddr =3D ia->ia_addr.sin_addr;=0A=
 	ifa_free(&ia->ia_ifa);=0A=
+=0A=
+	/* XXX length of hardware address (ar_hln) already checked in arpintr =
*/=0A=
+	if (ifp->if_addrlen !=3D ah->ar_hln) {=0A=
+		log(LOG_WARNING,=0A=
+		    "arp from %*D: addr len: new %d, i/f %d (ignored)",=0A=
+		    ifp->if_addrlen, (u_char *) ar_sha(ah), ":",=0A=
+		    ah->ar_hln, ifp->if_addrlen);=0A=
+		goto drop;=0A=
+	}=0A=
 	if (!bcmp(ar_sha(ah), enaddr, ifp->if_addrlen))=0A=
 		goto drop;	/* it's from me, ignore it. */=0A=
 	if (!bcmp(ar_sha(ah), ifp->if_broadcastaddr, ifp->if_addrlen)) {=0A=
@@ -695,16 +731,8 @@=0A=
 				    ifp->if_xname);=0A=
 			}=0A=
 		}=0A=
-		    =0A=
-		if (ifp->if_addrlen !=3D ah->ar_hln) {=0A=
-			LLE_WUNLOCK(la);=0A=
-			log(LOG_WARNING,=0A=
-			    "arp from %*D: addr len: new %d, i/f %d (ignored)",=0A=
-			    ifp->if_addrlen, (u_char *) ar_sha(ah), ":",=0A=
-			    ah->ar_hln, ifp->if_addrlen);=0A=
-			goto reply;=0A=
-		}=0A=
-		(void)memcpy(&la->ll_addr, ar_sha(ah), ifp->if_addrlen);=0A=
+=0A=
+		bcopy(ar_sha(ah), &la->ll_addr, ifp->if_addrlen);=0A=
 		la->la_flags |=3D LLE_VALID;=0A=
 =0A=
 		EVENTHANDLER_INVOKE(arp_update_event, la);=0A=
@@ -728,31 +756,31 @@=0A=
 		 * NB: The lock MUST be released before the call to the=0A=
 		 * output routine.=0A=
 		 */=0A=
-		if (la->la_hold !=3D NULL) {=0A=
-			struct mbuf *m_hold, *m_hold_next;=0A=
+		struct mbuf *m_hold, *m_hold_next;=0A=
 =0A=
-			memcpy(&sa, L3_ADDR(la), sizeof(sa));=0A=
-			LLE_WUNLOCK(la);=0A=
-			for (m_hold =3D la->la_hold, la->la_hold =3D NULL;=0A=
-			     m_hold !=3D NULL; m_hold =3D m_hold_next) {=0A=
-				m_hold_next =3D m_hold->m_nextpkt;=0A=
-				m_hold->m_nextpkt =3D NULL;=0A=
-				(*ifp->if_output)(ifp, m_hold, &sa, NULL);=0A=
-			}=0A=
-		} else=0A=
-			LLE_WUNLOCK(la);=0A=
+		m_hold =3D la->la_hold;=0A=
+		if (m_hold !=3D NULL)=0A=
+			bcopy(L3_ADDR(la), &dst, sizeof(dst));=0A=
 		la->la_hold =3D NULL;=0A=
 		la->la_numheld =3D 0;=0A=
-	} /* end of FIB loop */=0A=
+		LLE_WUNLOCK(la);=0A=
+=0A=
+		/* send packets to output */=0A=
+		for (; m_hold !=3D NULL; m_hold =3D m_hold_next) {=0A=
+			m_hold_next =3D m_hold->m_nextpkt;=0A=
+			m_hold->m_nextpkt =3D NULL;=0A=
+			(*ifp->if_output)(ifp, m_hold, &dst, NULL);=0A=
+		}=0A=
+	}=0A=
 reply:=0A=
 	if (op !=3D ARPOP_REQUEST)=0A=
 		goto drop;=0A=
 	ARPSTAT_INC(rxrequests);=0A=
 =0A=
+	bcopy(ar_sha(ah), ar_tha(ah), ah->ar_hln);=0A=
 	if (itaddr.s_addr =3D=3D myaddr.s_addr) {=0A=
 		/* Shortcut.. the receiving interface is the target. */=0A=
-		(void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);=0A=
-		(void)memcpy(ar_sha(ah), enaddr, ah->ar_hln);=0A=
+		bcopy(enaddr, ar_sha(ah), ah->ar_hln);=0A=
 	} else {=0A=
 		struct llentry *lle =3D NULL;=0A=
 =0A=
@@ -762,8 +790,7 @@=0A=
 		IF_AFDATA_UNLOCK(ifp);=0A=
 =0A=
 		if ((lle !=3D NULL) && (lle->la_flags & LLE_PUB)) {=0A=
-			(void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);=0A=
-			(void)memcpy(ar_sha(ah), &lle->ll_addr, ah->ar_hln);=0A=
+			bcopy(&lle->ll_addr, ar_sha(ah), ah->ar_hln);=0A=
 			LLE_RUNLOCK(lle);=0A=
 		} else {=0A=
 =0A=
@@ -790,9 +817,6 @@=0A=
 			}=0A=
 			RTFREE_LOCKED(rt);=0A=
 =0A=
-			(void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);=0A=
-			(void)memcpy(ar_sha(ah), enaddr, ah->ar_hln);=0A=
-=0A=
 			/*=0A=
 			 * Also check that the node which sent the ARP packet=0A=
 			 * is on the the interface we expect it to be on. This=0A=
@@ -815,6 +839,8 @@=0A=
 			}=0A=
 			RTFREE_LOCKED(rt);=0A=
 =0A=
+			bcopy(enaddr, ar_sha(ah), ah->ar_hln);=0A=
+=0A=
 #ifdef DEBUG_PROXY=0A=
 			printf("arp: proxying for %s\n",=0A=
 			       inet_ntoa(itaddr));=0A=
@@ -835,15 +861,15 @@=0A=
 		/* default behaviour; never reply by broadcast. */=0A=
 		m->m_flags &=3D ~(M_BCAST|M_MCAST);=0A=
 	}=0A=
-	(void)memcpy(ar_tpa(ah), ar_spa(ah), ah->ar_pln);=0A=
-	(void)memcpy(ar_spa(ah), &itaddr, ah->ar_pln);=0A=
+	bcopy(ar_spa(ah), ar_tpa(ah), ah->ar_pln);=0A=
+	bcopy(&itaddr, ar_spa(ah), ah->ar_pln);=0A=
 	ah->ar_op =3D htons(ARPOP_REPLY);=0A=
 	ah->ar_pro =3D htons(ETHERTYPE_IP); /* let's be sure! */=0A=
-	m->m_len =3D sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln);   =0A=
+	m->m_len =3D arphdr_len(ah);   =0A=
 	m->m_pkthdr.len =3D m->m_len;   =0A=
-	sa.sa_family =3D AF_ARP;=0A=
-	sa.sa_len =3D 2;=0A=
-	(*ifp->if_output)(ifp, m, &sa, NULL);=0A=
+	dst.sa_family =3D AF_ARP;=0A=
+	dst.sa_len =3D 2;=0A=
+	(*ifp->if_output)(ifp, m, &dst, NULL);=0A=
 	ARPSTAT_INC(txreplies);=0A=
 	return;=0A=
 =0A=

------=_NextPart_000_0065_01CB9686.B27BE840--




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4cfe88b6.1cedd80a.33f5.119d>