Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 14 Sep 2015 10:28:48 +0000 (UTC)
From:      "Alexander V. Chernikov" <melifaro@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r287779 - head/sys/netinet
Message-ID:  <201509141028.t8EASmUe096159@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: melifaro
Date: Mon Sep 14 10:28:47 2015
New Revision: 287779
URL: https://svnweb.freebsd.org/changeset/base/287779

Log:
  * Improve error checking for arp messages.
  * Clean stale headers from if_ether.c.
  
  Reported by:	rozhuk.im at gmail.com
  Reviewed by:	ae
  MFC after:	2 weeks

Modified:
  head/sys/netinet/if_ether.c

Modified: head/sys/netinet/if_ether.c
==============================================================================
--- head/sys/netinet/if_ether.c	Mon Sep 14 09:56:01 2015	(r287778)
+++ head/sys/netinet/if_ether.c	Mon Sep 14 10:28:47 2015	(r287779)
@@ -58,7 +58,6 @@ __FBSDID("$FreeBSD$");
 #include <net/if_dl.h>
 #include <net/if_types.h>
 #include <net/netisr.h>
-#include <net/if_llc.h>
 #include <net/ethernet.h>
 #include <net/route.h>
 #include <net/vnet.h>
@@ -71,9 +70,6 @@ __FBSDID("$FreeBSD$");
 #include <netinet/ip_carp.h>
 #endif
 
-#include <net/if_arc.h>
-#include <net/iso88025.h>
-
 #include <security/mac/mac_framework.h>
 
 #define SIN(s) ((const struct sockaddr_in *)(s))
@@ -529,6 +525,8 @@ static void
 arpintr(struct mbuf *m)
 {
 	struct arphdr *ar;
+	char *layer;
+	int hlen;
 
 	if (m->m_len < sizeof(struct arphdr) &&
 	    ((m = m_pullup(m, sizeof(struct arphdr))) == NULL)) {
@@ -537,26 +535,56 @@ arpintr(struct mbuf *m)
 	}
 	ar = mtod(m, struct arphdr *);
 
-	if (ntohs(ar->ar_hrd) != ARPHRD_ETHER &&
-	    ntohs(ar->ar_hrd) != ARPHRD_IEEE802 &&
-	    ntohs(ar->ar_hrd) != ARPHRD_ARCNET &&
-	    ntohs(ar->ar_hrd) != ARPHRD_IEEE1394 &&
-	    ntohs(ar->ar_hrd) != ARPHRD_INFINIBAND) {
-		log(LOG_NOTICE, "arp: unknown hardware address format (0x%2D)"
-		    " (from %*D to %*D)\n", (unsigned char *)&ar->ar_hrd, "",
-		    ETHER_ADDR_LEN, (u_char *)ar_sha(ar), ":",
-		    ETHER_ADDR_LEN, (u_char *)ar_tha(ar), ":");
+	/* Check if length is sufficient */
+	if ((m = m_pullup(m, arphdr_len(ar))) == NULL) {
+		log(LOG_NOTICE, "arp: short header received\n");
+		return;
+	}
+	ar = mtod(m, struct arphdr *);
+
+	hlen = 0;
+	layer = "";
+	switch (ntohs(ar->ar_hrd)) {
+	case ARPHRD_ETHER:
+		hlen = ETHER_ADDR_LEN; /* RFC 826 */
+		layer = "ethernet";
+		break;
+	case ARPHRD_IEEE802:
+		hlen = 6; /* RFC 1390, FDDI_ADDR_LEN */
+		layer = "fddi";
+		break;
+	case ARPHRD_ARCNET:
+		hlen = 1; /* RFC 1201, ARC_ADDR_LEN */
+		layer = "arcnet";
+		break;
+	case ARPHRD_INFINIBAND:
+		hlen = 20;	/* RFC 4391, INFINIBAND_ALEN */ 
+		layer = "infiniband";
+		break;
+	case ARPHRD_IEEE1394:
+		hlen = 0; /* SHALL be 16 */ /* RFC 2734 */
+		layer = "firewire";
+
+		/*
+		 * Restrict too long harware addresses.
+		 * Currently we are capable of handling 20-byte
+		 * addresses ( sizeof(lle->ll_addr) )
+		 */
+		if (ar->ar_hln >= 20)
+			hlen = 16;
+		break;
+	default:
+		log(LOG_NOTICE, "arp: unknown hardware address format (0x%2d)\n",
+		    htons(ar->ar_hrd));
 		m_freem(m);
 		return;
 	}
 
-	if (m->m_len < arphdr_len(ar)) {
-		if ((m = m_pullup(m, arphdr_len(ar))) == NULL) {
-			log(LOG_NOTICE, "arp: runt packet\n");
-			m_freem(m);
-			return;
-		}
-		ar = mtod(m, struct arphdr *);
+	if (hlen != 0 && hlen != ar->ar_hln) {
+		log(LOG_NOTICE, "arp: bad %s header length: %d\n", layer,
+		    ar->ar_hln);
+		m_freem(m);
+		return;
 	}
 
 	ARPSTAT_INC(received);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201509141028.t8EASmUe096159>