summaryrefslogtreecommitdiffstats
path: root/sys/netinet/if_ether.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2000-03-11 00:24:29 +0000
committerrwatson <rwatson@FreeBSD.org>2000-03-11 00:24:29 +0000
commit2bf7fb4443657c73135a45e4c526e1315a86d1db (patch)
tree43f1ca67a00b8dfcf13357b1ba0452403c08b5ff /sys/netinet/if_ether.c
parent024aa99ddd71845ee5ffdde94fa0e7dd00f30bbd (diff)
downloadFreeBSD-src-2bf7fb4443657c73135a45e4c526e1315a86d1db.zip
FreeBSD-src-2bf7fb4443657c73135a45e4c526e1315a86d1db.tar.gz
The function arpintr() incorrectly checks m->m_len to detect incomplete
ARP packets. This can incorrectly reject complete frames since the frame could be stored in more than one mbuf. The following patches fix the length comparisson, and add several diagnostic log messages to the interrupt handler for out-of-the-norm ARP packets. This should make ARP problems easier to detect, diagnose and fix. Submitted by: C. Stephen Gunn <csg@waterspout.com> Approved by: jkh Reviewed by: rwatson
Diffstat (limited to 'sys/netinet/if_ether.c')
-rw-r--r--sys/netinet/if_ether.c49
1 files changed, 36 insertions, 13 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index c87b72d..00bfb84 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -430,9 +430,9 @@ arpresolve(ac, rt, m, dst, desten, rt0)
static void
arpintr()
{
- register struct mbuf *m;
+ register struct mbuf *m, *m0;
register struct arphdr *ar;
- int s;
+ int s, ml;
while (arpintrq.ifq_head) {
s = splimp();
@@ -440,21 +440,44 @@ arpintr()
splx(s);
if (m == 0 || (m->m_flags & M_PKTHDR) == 0)
panic("arpintr");
- if (m->m_len >= sizeof(struct arphdr) &&
- (ar = mtod(m, struct arphdr *)) &&
- (ntohs(ar->ar_hrd) == ARPHRD_ETHER ||
- ntohs(ar->ar_hrd) == ARPHRD_IEEE802) &&
- m->m_len >=
- sizeof(struct arphdr) + 2 * ar->ar_hln + 2 * ar->ar_pln)
+
+ if (m->m_len < sizeof(struct arphdr) &&
+ (m = m_pullup(m, sizeof(struct arphdr)) == NULL)) {
+ log(LOG_ERR, "arp: runt packet -- m_pullup failed.");
+ continue;
+ }
+ ar = mtod(m, struct arphdr *);
+
+ if (ntohs(ar->ar_hrd) != ARPHRD_ETHER
+ && ntohs(ar->ar_hrd) != ARPHRD_IEEE802) {
+ log(LOG_ERR,
+ "arp: unknown hardware address format (%2D)",
+ (unsigned char *)&ar->ar_hrd, "");
+ m_freem(m);
+ continue;
+ }
- switch (ntohs(ar->ar_pro)) {
+ m0 = m;
+ ml = 0;
+ while (m0 != NULL) {
+ ml += m0->m_len; /* wanna implement m_size?? */
+ m0 = m0->m_next;
+ }
+ if (ml < sizeof(struct arphdr) + 2 * ar->ar_hln
+ + 2 * ar->ar_pln) {
+ log(LOG_ERR, "arp: runt packet.");
+ m_freem(m);
+ continue;
+ }
+
+ switch (ntohs(ar->ar_pro)) {
#ifdef INET
- case ETHERTYPE_IP:
- in_arpinput(m);
- continue;
+ case ETHERTYPE_IP:
+ in_arpinput(m);
+ continue;
#endif
- }
+ }
m_freem(m);
}
}
OpenPOWER on IntegriCloud