Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 8 Jun 2008 18:14:23 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 143124 for review
Message-ID:  <200806081814.m58IEN1S068010@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=143124

Change 143124 by sam@sam_ebb on 2008/06/08 18:14:11

	handle max_linkhdr large enough to force overflow of an
	inline mbuf when forming the tcpip hdr

Affected files ...

.. //depot/projects/vap/sys/netinet/tcp_output.c#9 edit
.. //depot/projects/vap/sys/netinet/tcp_subr.c#10 edit
.. //depot/projects/vap/sys/netinet/tcp_syncache.c#10 edit
.. //depot/projects/vap/sys/netinet/tcp_timewait.c#4 edit
.. //depot/projects/vap/sys/sys/mbuf.h#14 edit

Differences ...

==== //depot/projects/vap/sys/netinet/tcp_output.c#9 (text+ko) ====

@@ -735,14 +735,10 @@
 		}
 	}
 
-/*#ifdef DIAGNOSTIC*/
-#ifdef INET6
+#ifdef DIAGNOSTIC
 	if (max_linkhdr + hdrlen > MCLBYTES)
-#else
-	if (max_linkhdr + hdrlen > MHLEN)
+		panic("tcphdr too big");
 #endif
-		panic("tcphdr too big");
-/*#endif*/
 
 	/*
 	 * Grab a header mbuf, attaching a copy of data to
@@ -751,7 +747,7 @@
 	 */
 	if (len) {
 		struct mbuf *mb;
-		u_int moff;
+		u_int moff, trailingspace;
 
 		if ((tp->t_flags & TF_FORCEDATA) && len == 1)
 			tcpstat.tcps_sndprobe++;
@@ -775,23 +771,18 @@
 		m->m_len += hdrlen;
 		m->m_data -= hdrlen;
 #else
-		MGETHDR(m, M_DONTWAIT, MT_DATA);
+		if (hdrlen + max_linkhdr <= MHLEN) {
+			m = m_gethdr(M_DONTWAIT, MT_DATA);
+			trailingspace = MHLEN - (hdrlen + max_linkhdr);
+		} else {
+			m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+			trailingspace = MCLBYTES - (hdrlen + max_linkhdr);
+		}
 		if (m == NULL) {
 			SOCKBUF_UNLOCK(&so->so_snd);
 			error = ENOBUFS;
 			goto out;
 		}
-#ifdef INET6
-		if (MHLEN < hdrlen + max_linkhdr) {
-			MCLGET(m, M_DONTWAIT);
-			if ((m->m_flags & M_EXT) == 0) {
-				SOCKBUF_UNLOCK(&so->so_snd);
-				m_freem(m);
-				error = ENOBUFS;
-				goto out;
-			}
-		}
-#endif
 		m->m_data += max_linkhdr;
 		m->m_len = hdrlen;
 
@@ -801,7 +792,7 @@
 		 */
 		mb = sbsndptr(&so->so_snd, off, len, &moff);
 
-		if (len <= MHLEN - hdrlen - max_linkhdr) {
+		if (len <= trailingspace) {
 			m_copydata(mb, moff, (int)len,
 			    mtod(m, caddr_t) + hdrlen);
 			m->m_len += len;
@@ -834,7 +825,7 @@
 			tcpstat.tcps_sndurg++;
 		else
 			tcpstat.tcps_sndwinup++;
-
+#if 0
 		MGETHDR(m, M_DONTWAIT, MT_DATA);
 		if (m == NULL) {
 			error = ENOBUFS;
@@ -848,6 +839,21 @@
 #endif
 		m->m_data += max_linkhdr;
 		m->m_len = hdrlen;
+#else
+		if (hdrlen + max_linkhdr <= MHLEN)
+			m = m_gethdr(M_DONTWAIT, MT_DATA);
+		else
+			m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+		if (m == NULL) {
+			error = ENOBUFS;
+			goto out;
+		}
+		if (hdrlen + max_linkhdr <= MHLEN)
+			MH_ALIGN(m, hdrlen);
+		else
+			MCL_ALIGN(m, hdrlen);
+		m->m_len = hdrlen;
+#endif
 	}
 	SOCKBUF_UNLOCK_ASSERT(&so->so_snd);
 	m->m_pkthdr.rcvif = (struct ifnet *)0;

==== //depot/projects/vap/sys/netinet/tcp_subr.c#10 (text+ko) ====

@@ -291,7 +291,7 @@
 #endif /* INET6 */
 	if (max_protohdr < TCP_MINPROTOHDR)
 		max_protohdr = TCP_MINPROTOHDR;
-	if (max_linkhdr + TCP_MINPROTOHDR > MHLEN)
+	if (max_linkhdr + TCP_MINPROTOHDR > MCLBYTES)
 		panic("tcp_init");
 #undef TCP_MINPROTOHDR
 	/*
@@ -412,7 +412,7 @@
 tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m,
     tcp_seq ack, tcp_seq seq, int flags)
 {
-	int tlen;
+	int hdrlen, tlen;
 	int win = 0;
 	struct ip *ip;
 	struct tcphdr *nth;
@@ -446,11 +446,28 @@
 		}
 	}
 	if (m == NULL) {
+#if 0
 		m = m_gethdr(M_DONTWAIT, MT_DATA);
 		if (m == NULL)
 			return;
 		tlen = 0;
 		m->m_data += max_linkhdr;
+#else
+#ifdef INET6
+		if (isipv6)
+			hdrlen = sizeof (struct ip6_hdr) +
+			    sizeof (struct tcphdr);
+		else
+#endif
+			hdrlen = sizeof (struct tcpiphdr);
+		if (hdrlen + max_linkhdr <= MHLEN)
+			m = m_gethdr(M_DONTWAIT, MT_DATA);
+		else
+			m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+		if (m == NULL)
+			return;
+		m->m_data += max_linkhdr;
+#endif
 #ifdef INET6
 		if (isipv6) {
 			bcopy((caddr_t)ip6, mtod(m, caddr_t),

==== //depot/projects/vap/sys/netinet/tcp_syncache.c#10 (text+ko) ====

@@ -1285,12 +1285,19 @@
 	if (sc->sc_peer_mss)
 		mssopt = max( min(sc->sc_peer_mss, mssopt), tcp_minmss);
 
+#if 0
 	/* XXX: Assume that the entire packet will fit in a header mbuf. */
 	KASSERT(max_linkhdr + tlen + TCP_MAXOLEN <= MHLEN,
 	    ("syncache: mbuf too small"));
 
 	/* Create the IP+TCP header from scratch. */
 	m = m_gethdr(M_DONTWAIT, MT_DATA);
+#else
+	if (max_linkhdr + tlen + TCP_MAXOLEN <= MHLEN)
+		m = m_gethdr(M_DONTWAIT, MT_DATA);
+	else
+		m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+#endif
 	if (m == NULL)
 		return (ENOBUFS);
 #ifdef MAC

==== //depot/projects/vap/sys/netinet/tcp_timewait.c#4 (text+ko) ====

@@ -534,7 +534,20 @@
 
 	INP_WLOCK_ASSERT(inp);
 
+#ifdef INET6
+	if (isipv6)
+		hdrlen = sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
+	else
+#endif
+		hdrlen = sizeof(struct tcpiphdr);
+#if 0
 	m = m_gethdr(M_DONTWAIT, MT_DATA);
+#else
+	if (max_linkhdr + hdrlen + TCP_MAXOLEN <= MHLEN)
+		m = m_gethdr(M_DONTWAIT, MT_DATA);
+	else
+		m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+#endif
 	if (m == NULL)
 		return (ENOBUFS);
 	m->m_data += max_linkhdr;
@@ -545,14 +558,12 @@
 
 #ifdef INET6
 	if (isipv6) {
-		hdrlen = sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
 		ip6 = mtod(m, struct ip6_hdr *);
 		th = (struct tcphdr *)(ip6 + 1);
 		tcpip_fillheaders(inp, ip6, th);
 	} else
 #endif
 	{
-		hdrlen = sizeof(struct tcpiphdr);
 		ip = mtod(m, struct ip *);
 		th = (struct tcphdr *)(ip + 1);
 		tcpip_fillheaders(inp, ip, th);
@@ -572,9 +583,9 @@
 
 	m->m_len = hdrlen + optlen;
 	m->m_pkthdr.len = m->m_len;
-
+#if 0
 	KASSERT(max_linkhdr + m->m_len <= MHLEN, ("tcptw: mbuf too small"));
-
+#endif
 	th->th_seq = htonl(tw->snd_nxt);
 	th->th_ack = htonl(tw->rcv_nxt);
 	th->th_off = (sizeof(struct tcphdr) + optlen) >> 2;

==== //depot/projects/vap/sys/sys/mbuf.h#14 (text+ko) ====

@@ -677,6 +677,17 @@
 } while (0)
 
 /*
+ * As above, for mbufs allocated with m_getcl.
+ */
+#define	MCL_ALIGN(m, len) do {						\
+	KASSERT((m)->m_flags & M_PKTHDR && ((m)->m_flags & M_EXT),	\
+		("%s: MCL_ALIGN not PKTHDR cluster", __func__));	\
+	KASSERT((m)->m_data == (m)->m_ext.ext_buf,			\
+		("%s: MCL_ALIGN not a virgin mbuf", __func__));		\
+	(m)->m_data += (MCLBYTES - (len)) & ~(sizeof(long) - 1);	\
+} while (0)
+
+/*
  * Compute the amount of space available before the current start of data in
  * an mbuf.
  *



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