Module Name:    src
Committed By:   kefren
Date:           Mon Jul  5 09:54:26 UTC 2010

Modified Files:
        src/sys/netmpls: mpls_ttl.c

Log Message:
do some rudimentary checks on ip4 header before passing packet to
mpls_icmp_error


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/netmpls/mpls_ttl.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/netmpls/mpls_ttl.c
diff -u src/sys/netmpls/mpls_ttl.c:1.2 src/sys/netmpls/mpls_ttl.c:1.3
--- src/sys/netmpls/mpls_ttl.c:1.2	Fri Jul  2 12:25:54 2010
+++ src/sys/netmpls/mpls_ttl.c	Mon Jul  5 09:54:26 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: mpls_ttl.c,v 1.2 2010/07/02 12:25:54 kefren Exp $ */
+/*	$NetBSD: mpls_ttl.c,v 1.3 2010/07/05 09:54:26 kefren Exp $ */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -97,7 +97,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mpls_ttl.c,v 1.2 2010/07/02 12:25:54 kefren Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mpls_ttl.c,v 1.3 2010/07/05 09:54:26 kefren Exp $");
 
 #include "opt_inet.h"
 #include "opt_mpls.h"
@@ -160,10 +160,12 @@
 	union mpls_shim ms;
 } __packed;
 
-static void mpls_icmp_error(struct mbuf*, int, int, n_long, int, union mpls_shim *);
+static void mpls_icmp_error(struct mbuf *, int, int, n_long, int,
+	union mpls_shim *);
+static bool ip4_check(struct mbuf *);
 
 /*
- * http://www.ietf.org/proceedings/01aug/I-D/draft-ietf-mpls-icmp-02.txt
+ * Reference: http://tools.ietf.org/html/rfc4950
  * This should be in sync with icmp_error() in sys/netinet/ip_icmp.c
  */
 
@@ -326,6 +328,45 @@
 
 }
 
+static bool
+ip4_check(struct mbuf *m)
+{
+	struct ip *iph;
+	int hlen, len;
+
+	if (m->m_len < sizeof(struct ip) &&
+	    (m = m_pullup(m, sizeof(struct ip))) == NULL)
+		return false;
+
+	iph = mtod(m, struct ip *);
+
+	if (iph->ip_v != IPVERSION)
+		goto freeit;
+	hlen = iph->ip_hl << 2;
+	if (hlen < sizeof(struct ip))
+		goto freeit;
+	if (hlen > m->m_len) {
+		if ((m = m_pullup(m, hlen)) == NULL)
+			return false;
+		iph = mtod(m, struct ip *);
+	}
+	if (IN_MULTICAST(iph->ip_src.s_addr) ||
+	    (ntohl(iph->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
+	    (ntohl(iph->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
+	    in_cksum(m, hlen) != 0)
+		goto freeit;
+
+	len = ntohs(iph->ip_len);
+	if (len < hlen || m->m_pkthdr.len < len)
+		goto freeit;
+
+	return true;
+freeit:
+	m_freem(m);
+	return false;
+
+}
+
 #endif	/* INET */
 
 struct mbuf *
@@ -368,9 +409,10 @@
 			bossh.s_addr = ntohl(mtod(m, union mpls_shim *)->s_addr);
 			m_adj(m, sizeof(union mpls_shim));
 		}
-
-		mpls_icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS,
-		    0, 0, &top_shim);
+		
+		if (ip4_check(m) == true)
+			mpls_icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS,
+			    0, 0, &top_shim);
 #else
 		m_freem(m);
 #endif

Reply via email to