Subject: pppoe & mbuf chain
To: None <martin@netbsd.org>
From: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
List: tech-net
Date: 06/21/2002 23:54:41
----Next_Part(Fri_Jun_21_23:54:42_2002_961)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

in-kernel pppoe have an assumption that
input packets are a single mbuf.
(ie. no mbuf chain)
attached diff will fix it.

---
YAMAMOTO Takashi<yamt@mwd.biglobe.ne.jp>

----Next_Part(Fri_Jun_21_23:54:42_2002_961)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="pppoe.diff"

Index: if_pppoe.c
===================================================================
RCS file: /cvs/cvsroot/syssrc/sys/net/if_pppoe.c,v
retrieving revision 1.24
diff -u -p -r1.24 if_pppoe.c
--- if_pppoe.c	2002/04/14 12:24:28	1.24
+++ if_pppoe.c	2002/06/21 14:43:43
@@ -523,13 +523,21 @@ pppoe_disc_input(struct mbuf *m)
 
         /* avoid error messages if there is not a single pppoe instance */
         if (!LIST_EMPTY(&pppoe_softc_list)) {
+		KASSERT(m->m_flags & M_PKTHDR);
 	        eh = mtod(m, struct ether_header*);
         	m_adj(m, sizeof(struct ether_header));
+		/* should be in a single mbuf */
+		if (m->m_next != NULL) {
+			m = m_pullup(m, m->m_len);
+			if (m == NULL)
+				goto drop;
+		}
 	        p = mtod(m, u_int8_t*);
-        	KASSERT(m->m_flags & M_PKTHDR);
 	        pppoe_dispatch_disc_pkt(p, m->m_len, m->m_pkthdr.rcvif, eh);
 	}
-        m_free(m);
+
+drop:
+        m_freem(m);
 }
 
 static void
@@ -547,6 +555,10 @@ pppoe_data_input(struct mbuf *m)
                 goto drop;
         }
 
+	if (m->m_len < PPPOE_HEADERLEN) {
+		if ((m = m_pullup(m, PPPOE_HEADERLEN)) == 0)
+			goto drop;
+	}
         p = mtod(m, u_int8_t*);
 
         vertype = *p++;
@@ -601,7 +613,7 @@ pppoe_data_input(struct mbuf *m)
         return;
 
 drop:
-        m_free(m);
+        m_freem(m);
 }
 
 static int
@@ -737,8 +749,7 @@ pppoe_get_mbuf(size_t len)
 	if (len+sizeof(struct ether_header) > MHLEN) {
 		MCLGET(m, M_DONTWAIT);
 		if ((m->m_flags & M_EXT) == 0) {
-			struct mbuf *n;
-			MFREE(m, n);
+			m_free(m);
 			return 0;
 		}
 	}
@@ -1062,10 +1073,8 @@ pppoe_start(struct ifnet *ifp)
 	while ((m = sppp_dequeue(ifp)) != NULL) {
 		len = m->m_pkthdr.len;
 		M_PREPEND(m, PPPOE_HEADERLEN, M_DONTWAIT);
-		if (m == NULL) {
-			m_free(m);
+		if (m == NULL)
 			break;
-		}
 		p = mtod(m, u_int8_t*);
 		PPPOE_ADD_HEADER(p, 0, sc->sc_session, len);
 

----Next_Part(Fri_Jun_21_23:54:42_2002_961)----