Module Name:    src
Committed By:   is
Date:           Fri Apr 10 17:28:37 UTC 2020

Modified Files:
        src/sys/net [is-mlppp]: if_spppsubr.c if_spppvar.h

Log Message:
first part of defragmentation code. No dropping/sequence error statistics
yet, and no MRRU negotiation so not active.


To generate a diff of this commit:
cvs rdiff -u -r1.187.2.3 -r1.187.2.4 src/sys/net/if_spppsubr.c
cvs rdiff -u -r1.22.12.2 -r1.22.12.3 src/sys/net/if_spppvar.h

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

Modified files:

Index: src/sys/net/if_spppsubr.c
diff -u src/sys/net/if_spppsubr.c:1.187.2.3 src/sys/net/if_spppsubr.c:1.187.2.4
--- src/sys/net/if_spppsubr.c:1.187.2.3	Tue Apr  7 19:26:44 2020
+++ src/sys/net/if_spppsubr.c	Fri Apr 10 17:28:37 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_spppsubr.c,v 1.187.2.3 2020/04/07 19:26:44 is Exp $	 */
+/*	$NetBSD: if_spppsubr.c,v 1.187.2.4 2020/04/10 17:28:37 is Exp $	 */
 
 /*
  * Synchronous PPP/Cisco link level subroutines.
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.187.2.3 2020/04/07 19:26:44 is Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.187.2.4 2020/04/10 17:28:37 is Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -336,6 +336,9 @@ static void sppp_lcp_scr(struct sppp *sp
 static void sppp_lcp_check_and_close(struct sppp *sp);
 static int sppp_ncp_check(struct sppp *sp);
 
+static struct mbuf *sppp_ml_defrag(struct sppp *sp, struct mbuf *m,
+				    u_int16_t *protocolp);
+
 static void sppp_ipcp_init(struct sppp *sp);
 static void sppp_ipcp_up(struct sppp *sp);
 static void sppp_ipcp_down(struct sppp *sp);
@@ -517,6 +520,123 @@ sppp_change_phase(struct sppp *sp, int p
 	}
 }
 
+
+/*
+ * Defragment an MP packet. 
+ *
+ * Returns NULL or an assembled packet or the original,
+ * and adjusts the passed protocol to the inner one.
+ *
+ * Called with and returns a packet without PPP header, 
+ * but with MP fragment header.
+ *
+ * Called and returns with lock held.
+ */
+static struct mbuf *
+sppp_ml_defrag(struct sppp *sp, struct mbuf *m, u_int16_t *protocolp)
+{
+	u_int8_t *p;
+	u_int8_t flags;
+	u_int32_t seqid;
+	u_int16_t protocol;
+	u_int16_t *m_protop;
+	int newflen;
+
+	if (*protocolp != PPP_MP)
+		return m; 	/* not ours */
+
+	if (sp->lcp.mrru == 0)
+		return m; 	/*
+				 * ours, but we're not ready.
+				 * sppp_input will arrange for rejection.
+				 */
+
+	if (m->m_len < 4) {
+		m = m_pullup(m, 4);
+		if (m == NULL) {
+			if_statadd2(ifp, if_ierrors, 1, if_iqdrops, 1);
+			return NULL;
+		}
+	}
+	p = mtod(m, u_int8_t *);
+	flags = *p; 
+	seqid = (p[1]<<16) + (p[2]<<8) + p[3];
+
+	m_adj(m, 4);
+
+	/* We're manipulating the defragmentation state below: */
+	SPPP_UPGRADE(sp);
+
+	if (flags & 0x80) {
+		/* Beginning fragment. */
+		sp->lcp.ml_seq_expected=seqid+1;	/* next expected */
+		
+		/* TODO: if prefix, count dropped? */
+
+		m_freem(sp->lcp.ml_prefix);
+		sp->lcp.ml_prefix = m;
+
+	} else if (seqid == sp->lcp.ml_seq_expected) {
+		sp->lcp.ml_seq_expected=seqid+1;	/* next expected */
+		if (sp->lcp.ml_prefix == 0) {
+			/* didn't see B frame.	*/
+		 	/* TODO: count as dropped. */
+			m_freem(m);
+			return NULL;
+		}
+		/*
+		 * m_cat might free the first mbuf (with pkthdr)
+		 * in 2nd chain; therefore:
+		 */
+		newflen = m->m_pkthdr.len;
+		m_cat(sp->lcp.ml_prefix, m);
+		lcp.ml_prefix->m_pkthdr.len += newflen;
+
+	} else {
+		/*
+		 * sequence error. 
+		 *
+		 * For now, only drop this fragment, and don't touch state-
+		 * might be from the long past or future, and we could still
+		 * finish our current prefix.
+		 *
+		 * TODO: count as dropped.
+		 */
+		 m_freem(sp->lcp.ml_prefix);
+		 return NULL;
+	}
+	/* Successfully got the Beginning or appended a non-B packet.*/
+	if (flags & 0x40) {
+		/* B/next was E packet. Unwrap gift and deliver. */
+		m = sp->lcp.ml_prefix;
+		sp->lcp.ml_prefix = NULL;
+
+		if (m->m_len < 2) {
+			m = m_pullup(m,2)
+			if (m == NULL) {
+			 	* TODO: count as dropped.
+				return NULL;
+			}
+		}
+		/* RFC 1990 2.: don't assume no protocol field compression */
+		p = mtod(m, u_int8_t);
+		protocol = *p;
+		
+		if (protocol & 1) {
+			m_adj(m, 1);
+		} else {
+			protocol = (protocol << 8) + p[1];
+			m_adj(m, 2);
+		}
+		*protocolp = protocol;
+
+		return m;
+	}
+
+	return NULL;
+}
+
+
 /*
  * Exported functions, comprising our interface to the lower layer.
  */
@@ -627,6 +747,12 @@ sppp_input(struct ifnet *ifp, struct mbu
 		protocol = ntohs(h->protocol);
 	}
 
+	m = sppp_ml_defrag(sp, m, &protocol);
+	if (m == 0) {
+		SPPP_UNLOCK(sp);
+		return;
+	}
+
 	switch (protocol) {
 	default:
 		if (sp->state[IDX_LCP] == STATE_OPENED) {
@@ -2222,6 +2348,11 @@ sppp_lcp_up(struct sppp *sp)
 	/* Initialize activity timestamp: opening a connection is an activity */
 	sp->pp_last_receive = sp->pp_last_activity = time_uptime;
 
+	/* Initialize mlppp state */
+	sp->lcp.mrru = sp->lcp.their_mrru = 0;
+	sp->lcp.ml_prefix = NULL;
+	sp->lcp.ml_seq_expected = 0;
+
 	/*
 	 * If this interface is passive or dial-on-demand, and we are
 	 * still in Initial state, it means we've got an incoming

Index: src/sys/net/if_spppvar.h
diff -u src/sys/net/if_spppvar.h:1.22.12.2 src/sys/net/if_spppvar.h:1.22.12.3
--- src/sys/net/if_spppvar.h:1.22.12.2	Tue Apr  7 18:47:43 2020
+++ src/sys/net/if_spppvar.h	Fri Apr 10 17:28:37 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_spppvar.h,v 1.22.12.2 2020/04/07 18:47:43 is Exp $	*/
+/*	$NetBSD: if_spppvar.h,v 1.22.12.3 2020/04/10 17:28:37 is Exp $	*/
 
 #ifndef _NET_IF_SPPPVAR_H_
 #define _NET_IF_SPPPVAR_H_
@@ -48,6 +48,8 @@ struct slcp {
 	/* multilink variables */
 	u_long	mrru;		/* our   max received reconstructed unit */
 	u_long	their_mrru;	/* their max received reconstructed unit */
+	u_long	ml_seq_xpctd;	/* next seqid we expect to receive */
+	struct mbuf *ml_prefix;	/* reassembled packet so far */
 };
 
 #define IDX_IPCP 1		/* idx into state table */

Reply via email to