$NetBSD: patch-aa,v 1.3 2005/04/29 11:41:29 cube Exp $

--- ppp_mppe_compress.c.orig	2004-05-31 07:31:51.000000000 +0200
+++ ppp_mppe_compress.c
@@ -5,6 +5,8 @@
  * By Frank Cusack <frank@google.com>.
  * Copyright (c) 2002,2003,2004 Google, Inc.
  * All rights reserved.
+ * Copyright (c) 1999 Darrin B. Jewell <dbj@NetBSD.org>
+ * Copyright (c) 2004, 2005 Quentin Garnier <cube@NetBSD.org>
  *
  * Permission to use, copy, modify, and distribute this software and its
  * documentation is hereby granted, provided that the above copyright
@@ -18,19 +20,35 @@
  *                    deprecated in 2.6
  */
 
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/version.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/string.h>
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+
+#define PACKETPTR	struct mbuf *
+
+#include <net/ppp_defs.h>
+#include <net/ppp-comp.h>
+
+#include <sys/sha1.h>
+#include <crypto/arc4/arc4.h>
+
+#if __NetBSD_Version__ < 299001600
+/* MPPE definitions were included into the kernel source */
+#include "ppp-comp-local.h"
+#endif
 
-#include <linux/ppp_defs.h>
-#include <linux/ppp-comp.h>
+int mppe_in_use;
+#define MOD_INC_USE_COUNT	mppe_in_use++
+#define MOD_DEC_USE_COUNT	mppe_in_use--
 
-#include "arcfour.h"
-#include "sha1.h"
+#ifdef MPPE_DEBUG
+#define DPRINTF(x)	aprint_normal x
+#else
+#define DPRINTF(x)
+#endif
 
 /*
  * State for an MPPE (de)compressor.
@@ -38,8 +56,8 @@
 typedef struct ppp_mppe_state {
     unsigned char	master_key[MPPE_MAX_KEY_LEN];
     unsigned char	session_key[MPPE_MAX_KEY_LEN];
-    arcfour_context	arcfour_context; /* encryption state */
-    unsigned		keylen;		/* key length in bytes             */
+    void		*arcfour_context; /* encryption state */
+    unsigned 		keylen;		/* key length in bytes             */
 					/* NB: 128-bit == 16, 40-bit == 8! */
 					/* If we want to support 56-bit,   */
 					/* the unit has to change to bits  */
@@ -84,12 +102,12 @@ static int	mppe_comp_init __P((void *sta
 static int	mppe_decomp_init __P((void *state, unsigned char *options,
 				      int optlen, int unit,
 				      int hdrlen, int mru, int debug));
-static int	mppe_compress __P((void *state, unsigned char *ibuf,
-				   unsigned char *obuf,
+static int	mppe_compress __P((void *state, struct mbuf **opkt,
+				   struct mbuf *ipkt,
 				   int isize, int osize));
-static void	mppe_incomp __P((void *state, unsigned char *ibuf, int icnt));
-static int	mppe_decompress __P((void *state, unsigned char *ibuf,
-				     int isize, unsigned char *obuf,int osize));
+static void	mppe_incomp __P((void *state, struct mbuf *mp));
+static int	mppe_decompress __P((void *state, struct mbuf *ipkt,
+				     struct mbuf **opkt));
 static void	mppe_comp_reset __P((void *state));
 static void	mppe_decomp_reset __P((void *state));
 static void	mppe_comp_stats __P((void *state, struct compstat *stats));
@@ -104,7 +122,7 @@ GetNewKeyFromSHA(unsigned char *MasterKe
 		 unsigned SessionKeyLength, unsigned char *InterimKey)
 {
     SHA1_CTX Context;
-    unsigned char Digest[SHA1_SIGNATURE_SIZE];
+    unsigned char Digest[20];
 
     unsigned char SHApad1[40] =
     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -119,12 +137,12 @@ GetNewKeyFromSHA(unsigned char *MasterKe
 
     /* assert(SessionKeyLength <= SHA1_SIGNATURE_SIZE); */
 
-    SHA1_Init(&Context);
-    SHA1_Update(&Context, MasterKey, SessionKeyLength);
-    SHA1_Update(&Context, SHApad1, sizeof(SHApad1));
-    SHA1_Update(&Context, SessionKey, SessionKeyLength);
-    SHA1_Update(&Context, SHApad2, sizeof(SHApad2));
-    SHA1_Final(Digest, &Context);
+    SHA1Init(&Context);
+    SHA1Update(&Context, MasterKey, SessionKeyLength);
+    SHA1Update(&Context, SHApad1, sizeof(SHApad1));
+    SHA1Update(&Context, SessionKey, SessionKeyLength);
+    SHA1Update(&Context, SHApad2, sizeof(SHApad2));
+    SHA1Final(Digest, &Context);
 
     memcpy(InterimKey, Digest, SessionKeyLength);
 }
@@ -141,9 +159,9 @@ mppe_rekey(ppp_mppe_state *state, int in
     GetNewKeyFromSHA(state->master_key, state->session_key,
 		     state->keylen, InterimKey);
     if (!initial_key) {
-	arcfour_setkey(&state->arcfour_context, InterimKey, state->keylen);
-	arcfour_encrypt(&state->arcfour_context, InterimKey, state->keylen,
-			state->session_key);
+	arc4_setkey(state->arcfour_context, InterimKey, state->keylen);
+	arc4_encrypt(state->arcfour_context, state->session_key, InterimKey,
+			state->keylen);
     } else {
 	memcpy(state->session_key, InterimKey, state->keylen);
     }
@@ -153,7 +171,7 @@ mppe_rekey(ppp_mppe_state *state, int in
 	state->session_key[1] = 0x26;
 	state->session_key[2] = 0x9e;
     }
-    arcfour_setkey(&state->arcfour_context, state->session_key, state->keylen);
+    arc4_setkey(state->arcfour_context, state->session_key, state->keylen);
 }
 
 
@@ -170,15 +188,12 @@ mppe_alloc(unsigned char *options, int o
 	|| options[1] != CILEN_MPPE)
 	return NULL;
 
-    state = (ppp_mppe_state *) kmalloc(sizeof(*state), GFP_KERNEL);
+    state = (ppp_mppe_state *) malloc(sizeof(*state), M_DEVBUF, M_NOWAIT);
     if (state == NULL)
 	return NULL;
+    state->arcfour_context = NULL;
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
-    try_module_get(THIS_MODULE);
-#else
     MOD_INC_USE_COUNT;
-#endif
     memset(state, 0, sizeof(*state));
 
     /* Save keys. */
@@ -201,12 +216,10 @@ mppe_free(void *arg)
     ppp_mppe_state *state = (ppp_mppe_state *) arg;
 
     if (state) {
-	kfree(state);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
-	module_put(THIS_MODULE);
-#else
+	if (state->arcfour_context)
+	    free(state->arcfour_context, M_DEVBUF);
+	free(state, M_DEVBUF);
 	MOD_DEC_USE_COUNT;
-#endif
     }
 }
 
@@ -232,12 +245,16 @@ mppe_init(void *arg, unsigned char *opti
     else if (mppe_opts & MPPE_OPT_40)
 	state->keylen = 8;
     else {
-	printk(KERN_WARNING "%s[%d]: unknown key length\n", debugstr, unit);
+	aprint_error("%s[%d]: unknown key length\n", debugstr, unit);
 	return 0;
     }
     if (mppe_opts & MPPE_OPT_STATEFUL)
 	state->stateful = 1;
 
+    state->arcfour_context = malloc(arc4_ctxlen(), M_DEVBUF, M_NOWAIT);
+    if (state->arcfour_context == NULL)
+	return 0;
+
     /* Generate the initial session key. */
     mppe_rekey(state, 1);
 
@@ -246,7 +263,7 @@ mppe_init(void *arg, unsigned char *opti
 	char mkey[sizeof(state->master_key) * 2 + 1];
 	char skey[sizeof(state->session_key) * 2 + 1];
 
-	printk(KERN_DEBUG "%s[%d]: initialized with %d-bit %s mode\n", debugstr,
+	aprint_normal("%s[%d]: initialized with %d-bit %s mode\n", debugstr,
 	       unit, (state->keylen == 16)? 128: 40,
 	       (state->stateful)? "stateful": "stateless");
 
@@ -254,7 +271,7 @@ mppe_init(void *arg, unsigned char *opti
 	    sprintf(mkey + i * 2, "%.2x", state->master_key[i]);
 	for (i = 0; i < sizeof(state->session_key); i++)
 	    sprintf(skey + i * 2, "%.2x", state->session_key[i]);
-	printk(KERN_DEBUG "%s[%d]: keys: master: %s initial session: %s\n",
+	aprint_normal("%s[%d]: keys: master: %s initial session: %s\n",
 	       debugstr, unit, mkey, skey);
     }
 
@@ -311,30 +328,75 @@ mppe_comp_reset(void *arg)
  * MPPE_OVHD + 2 bytes larger than the input.
  */
 int
-mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf,
+mppe_compress(void *arg, struct mbuf **mret, struct mbuf *mp,
 	      int isize, int osize)
 {
     ppp_mppe_state *state = (ppp_mppe_state *) arg;
     int proto;
+    unsigned char *ibuf, *obuf;
 
+    *mret = NULL;
+    ibuf = mtod(mp, unsigned char *);
     /*
      * Check that the protocol is in the range we handle.
      */
     proto = PPP_PROTOCOL(ibuf);
-    if (proto < 0x0021 || proto > 0x00fa)
+    if (proto < 0x0021 || proto > 0x00fa) {
+	DPRINTF(("unhandled proto %d\n", proto));
 	return 0;
+    }
 
     /* Make sure we have enough room to generate an encrypted packet. */
-    if (osize < isize + MPPE_OVHD + 2) {
+    /* XXX */
+    if (osize + MPPE_OVHD < isize + MPPE_OVHD) {
 	/* Drop the packet if we should encrypt it, but can't. */
-	printk(KERN_DEBUG "mppe_compress[%d]: osize too small! "
+	aprint_normal("mppe_compress[%d]: osize too small! "
 	       "(have: %d need: %d)\n", state->unit,
-	       osize, osize + MPPE_OVHD + 2);
-	return -1;
+	       osize, isize + MPPE_OVHD + 2);
+	/* XXX */
+	return 0;
     }
 
     osize = isize + MPPE_OVHD + 2;
 
+    /* Allocate an mbuf chain to hold the encrypted packet */
+    {
+      struct mbuf *mfirst = NULL;
+      struct mbuf *mprev;
+      struct mbuf *m = NULL;
+      int bleft = isize+MPPE_OVHD+2;
+      do {
+	mprev = m;
+	MGET(m,M_DONTWAIT, MT_DATA);
+	if (m == NULL) {
+	  m_freem(mfirst);
+	  /* XXX: what should we do here?  If we return NULL, the data
+	   * will go out unencrypted. We can't use M_WAITOK, since this
+	   * will be called from splsoftnet()
+	   */
+	  panic("ppp%d/mppe: unable to allocate mbuf to encrypt packet",
+		state->unit);
+	}
+	m->m_len = 0;
+	if (mfirst == NULL) {
+	  mfirst = m;
+	  M_COPY_PKTHDR(m,mp);
+	  if (bleft > MHLEN) {
+	    MCLGET(m, M_DONTWAIT);
+	  }
+	} else {
+	  mprev->m_next = m;
+	  if (bleft > MLEN) {
+	    MCLGET(m, M_DONTWAIT);
+	  }
+	}
+	bleft -= M_TRAILINGSPACE(m);
+      } while (bleft > 0);
+      *mret = mfirst;
+    }
+
+    obuf = mtod(*mret, unsigned char *);
+
     /*
      * Copy over the PPP header and set control bits.
      */
@@ -346,7 +408,7 @@ mppe_compress(void *arg, unsigned char *
 
     state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
     if (state->debug >= 7)
-	printk(KERN_DEBUG "mppe_compress[%d]: ccount %d\n", state->unit,
+	aprint_verbose("mppe_compress[%d]: ccount %d\n", state->unit,
 	       state->ccount);
     obuf[0] = state->ccount >> 8;
     obuf[1] = state->ccount & 0xff;
@@ -356,19 +418,62 @@ mppe_compress(void *arg, unsigned char *
 	(state->bits & MPPE_BIT_FLUSHED)) {	/* CCP Reset-Request  */
 	/* We must rekey */
 	if (state->debug && state->stateful)
-	    printk(KERN_DEBUG "mppe_compress[%d]: rekeying\n", state->unit);
+	    aprint_verbose("mppe_compress[%d]: rekeying\n", state->unit);
 	mppe_rekey(state, 0);
 	state->bits |= MPPE_BIT_FLUSHED;
     }
     obuf[0] |= state->bits;
     state->bits &= ~MPPE_BIT_FLUSHED;	/* reset for next xmit */
 
-    obuf  += MPPE_OVHD;
     ibuf  += 2;	/* skip to proto field */
     isize -= 2;
+    (*mret)->m_len += PPP_HDRLEN + MPPE_OVHD;
 
-    /* Encrypt packet */
-    arcfour_encrypt(&state->arcfour_context, ibuf, isize, obuf);
+    /* March down input and output mbuf chains, encoding with RC4 */
+    {
+      struct mbuf *mi = mp;	/* mbuf in */
+      struct mbuf *mo = *mret;	/* mbuf out */
+      int maxi, maxo;
+      maxi = mi->m_len-2;
+      maxo = M_TRAILINGSPACE(mo);
+      while (mi) {
+	if (maxi < maxo) {
+	  arc4_encrypt(state->arcfour_context,
+	      mtod(mo,unsigned char *)+mo->m_len,
+	      mtod(mi,unsigned char *)+mi->m_len-maxi,
+	      maxi);
+	  mo->m_len += maxi;
+	  maxo -= maxi;
+	  mi = mi->m_next;
+	  if (mi) {
+	    maxi = mi->m_len;
+	  }
+	} else if (maxi > maxo) {
+	  arc4_encrypt(state->arcfour_context,
+	      mtod(mo,unsigned char *)+mo->m_len,
+	      mtod(mi,unsigned char *)+mi->m_len-maxi,
+	      maxo);
+	  mo->m_len += maxo;
+	  maxi -= maxo;
+	  mo = mo->m_next;
+	  if (mo) {
+	    maxo = M_TRAILINGSPACE(mo);
+	  }
+	} else {
+	  arc4_encrypt(state->arcfour_context,
+	      mtod(mo,unsigned char *)+mo->m_len,
+	      mtod(mi,unsigned char *)+mi->m_len-maxi,
+	      maxi);
+	  mo->m_len += maxi;
+	  mi = mi->m_next;
+	  mo = mo->m_next;
+	  if (mi) {
+	    maxi = mi->m_len;
+	    maxo = M_TRAILINGSPACE(mo);
+	  }
+	}
+      }
+    }
 
     state->stats.unc_bytes += isize;
     state->stats.unc_packets++;
@@ -413,56 +518,50 @@ mppe_decomp_reset(void *arg)
  * Decompress (decrypt) an MPPE packet.
  */
 int
-mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf,
-		int osize)
+mppe_decompress(void *arg, struct mbuf *mp, struct mbuf **mret)
 {
     ppp_mppe_state *state = (ppp_mppe_state *) arg;
     unsigned ccount;
-    int flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED;
-    int sanity = 0;
+    int flushed;
+    int sanity = 0, isize;
+    unsigned char *ibuf, *obuf;
 
-    if (isize <= PPP_HDRLEN + MPPE_OVHD) {
-	if (state->debug)
-	    printk(KERN_DEBUG "mppe_decompress[%d]: short pkt (%d)\n",
-		   state->unit, isize);
+    if (!mp) {
+	DPRINTF(("ppp%d/mppe: null input packet\n",state->unit));
 	return DECOMP_ERROR;
     }
 
-    /*
-     * Make sure we have enough room to decrypt the packet.
-     * Note that for our test we only subtract 1 byte whereas in
-     * mppe_compress() we added 2 bytes (+MPPE_OVHD);
-     * this is to account for possible PFC.
-     */
-    if (osize < isize - MPPE_OVHD - 1) {
-	printk(KERN_DEBUG "mppe_decompress[%d]: osize too small! "
-	       "(have: %d need: %d)\n", state->unit,
-	       osize, isize - MPPE_OVHD - 1);
+    if (mp->m_len <= PPP_HDRLEN + MPPE_OVHD) {
+	if (state->debug)
+	    aprint_error("mppe_decompress[%d]: short pkt (%d)\n",
+		   state->unit, mp->m_len);
 	return DECOMP_ERROR;
     }
-    osize = isize - MPPE_OVHD - 2;	/* assume no PFC */
+
+    ibuf = mtod(mp,unsigned char *);
+    flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED;
 
     ccount = MPPE_CCOUNT(ibuf);
     if (state->debug >= 7)
-	printk(KERN_DEBUG "mppe_decompress[%d]: ccount %d\n", state->unit,
+	aprint_error("mppe_decompress[%d]: ccount %d\n", state->unit,
 	       ccount);
 
     /* sanity checks -- terminate with extreme prejudice */
     if (!(MPPE_BITS(ibuf) & MPPE_BIT_ENCRYPTED)) {
-	printk(KERN_DEBUG "mppe_decompress[%d]: ENCRYPTED bit not set!\n",
-	       state->unit);
+	DPRINTF(("mppe_decompress[%d]: ENCRYPTED bit not set!\n",
+	       state->unit));
 	state->sanity_errors += 100;
 	sanity = 1;
     }
     if (!state->stateful && !flushed) {
-	printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set in "
-	       "stateless mode!\n", state->unit);
+	DPRINTF(("mppe_decompress[%d]: FLUSHED bit not set in "
+	       "stateless mode!\n", state->unit));
 	state->sanity_errors += 100;
 	sanity = 1;
     }
     if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) {
-	printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set on "
-	       "flag packet!\n", state->unit);
+	DPRINTF(("mppe_decompress[%d]: FLUSHED bit not set on "
+	       "flag packet!\n", state->unit));
 	state->sanity_errors += 100;
 	sanity = 1;
     }
@@ -531,6 +630,46 @@ mppe_decompress(void *arg, unsigned char
 	    mppe_rekey(state, 0);
     }
 
+    /* Allocate an mbuf chain to hold the decrypted packet */
+    {
+	struct mbuf *mfirst = 0;
+	struct mbuf *mprev;
+	struct mbuf *m = 0;
+	int bleft;
+	isize = 0;
+	for (m=mp; m; m= m->m_next) isize += m->m_len;
+	bleft = isize-MPPE_OVHD;
+	do {
+	    mprev = m;
+	    MGET(m,M_DONTWAIT, MT_DATA);
+	    if (m == NULL) {
+		m_freem(mfirst);
+#ifdef DEBUG
+		aprint_error("ppp%d/mppe: unable to allocate mbuf to decrypt packet\n",
+		    state->unit);
+#endif
+		return DECOMP_ERROR;
+	    }
+	    m->m_len = 0;
+	    if (mfirst == NULL) {
+		mfirst=m;
+		M_COPY_PKTHDR(m,mp);
+		if (bleft > MHLEN) {
+		    MCLGET(m, M_DONTWAIT);
+		}
+	    } else {
+		mprev->m_next = m;
+		if (bleft > MLEN) {
+		    MCLGET(m, M_DONTWAIT);
+		}
+	    }
+	    bleft -= M_TRAILINGSPACE(m);
+	} while (bleft > 0);
+	*mret = mfirst;
+    }
+
+    obuf = mtod(*mret, unsigned char *);
+
     /*
      * Fill in the first part of the PPP header.  The protocol field
      * comes from the decrypted data.
@@ -538,15 +677,17 @@ mppe_decompress(void *arg, unsigned char
     obuf[0] = PPP_ADDRESS(ibuf);	/* +1 */
     obuf[1] = PPP_CONTROL(ibuf);	/* +1 */
     obuf  += 2;
+    (*mret)->m_len += 2;
     ibuf  += PPP_HDRLEN + MPPE_OVHD;
     isize -= PPP_HDRLEN + MPPE_OVHD;	/* -6 */
 					/* net osize: isize-4 */
 
+#ifdef notyet
     /*
      * Decrypt the first byte in order to check if it is
      * a compressed or uncompressed protocol field.
      */
-    arcfour_decrypt(&state->arcfour_context, ibuf, 1, obuf);
+    arc4_decrypt(state->arcfour_context, obuf, ibuf, 1);
 
     /*
      * Do PFC decompression.
@@ -557,13 +698,56 @@ mppe_decompress(void *arg, unsigned char
 	obuf[1] = obuf[0];
 	obuf[0] = 0;
 	obuf++;
-	osize++;
     }
+#endif
 
     /* And finally, decrypt the rest of the packet. */
-    arcfour_decrypt(&state->arcfour_context, ibuf + 1, isize - 1, obuf + 1);
-
-    state->stats.unc_bytes += osize;
+	/* March down input and output mbuf chains, decoding with RC4 */
+	{
+	    struct mbuf *mi = mp;	/* mbuf in */
+	    struct mbuf *mo = *mret;	/* mbuf out */
+	    int maxi, maxo;
+	    maxi = mi->m_len-6;	/* adjust for PPP_HDRLEN and MPPE_OVERHEAD */
+	    maxo = M_TRAILINGSPACE(mo);
+	    while (mi) {
+		if (maxi < maxo) {
+		    arc4_encrypt(state->arcfour_context,
+			mtod(mo,unsigned char *)+mo->m_len,
+			mtod(mi,unsigned char *)+mi->m_len-maxi,
+			maxi);
+		    mo->m_len += maxi;
+		    maxo -= maxi;
+		    mi = mi->m_next;
+		    if (mi) {
+			maxi = mi->m_len;
+		    }
+		} else if (maxi > maxo) {
+		    arc4_encrypt(state->arcfour_context,
+			mtod(mo,unsigned char *)+mo->m_len,
+			mtod(mi,unsigned char *)+mi->m_len-maxi,
+			maxo);
+		    mo->m_len += maxo;
+		    maxi -= maxo;
+		    mo = mo->m_next;
+		    if (mo) {
+			maxo = M_TRAILINGSPACE(mo);
+		    }
+		} else {
+		    arc4_encrypt(state->arcfour_context,
+			mtod(mo,unsigned char *)+mo->m_len,
+			mtod(mi,unsigned char *)+mi->m_len-maxi,
+			maxi);
+		    mo->m_len += maxi;
+		    mi = mi->m_next;
+		    mo = mo->m_next;
+		    if (mi) {
+			maxi = mi->m_len;
+			maxo = M_TRAILINGSPACE(mo);
+		    }
+		}
+	    }
+	}
+    state->stats.unc_bytes += (*mret)->m_len;
     state->stats.unc_packets++;
     state->stats.comp_bytes += isize;
     state->stats.comp_packets++;
@@ -571,7 +755,7 @@ mppe_decompress(void *arg, unsigned char
     /* good packet credit */
     state->sanity_errors >>= 1;
 
-    return osize;
+    return DECOMP_OK;
 }
 
 /*
@@ -581,29 +765,23 @@ mppe_decompress(void *arg, unsigned char
  * packet.  (How to do this?)
  */
 static void
-mppe_incomp(void *arg, unsigned char *ibuf, int icnt)
+mppe_incomp(void *arg, struct mbuf *mp)
 {
     ppp_mppe_state *state = (ppp_mppe_state *) arg;
+    struct mbuf *m;
 
-    if (state->debug &&
-	(PPP_PROTOCOL(ibuf) >= 0x0021 && PPP_PROTOCOL(ibuf) <= 0x00fa))
-	printk(KERN_DEBUG "mppe_incomp[%d]: incompressible (unencrypted) data! "
-	       "(proto %04x)\n", state->unit, PPP_PROTOCOL(ibuf));
-
-    state->stats.inc_bytes += icnt;
-    state->stats.inc_packets++;
-    state->stats.unc_bytes += icnt;
-    state->stats.unc_packets++;
+    for (m=mp;m;m = m->m_next) {
+      (state->stats).inc_bytes += m->m_len;
+      (state->stats).unc_bytes += m->m_len;
+    }
+    (state->stats).inc_packets++;
+    (state->stats).unc_packets++;
 }
 
 /*************************************************************
  * Module interface table
  *************************************************************/
 
-/* These are in ppp.c (2.2.x) or ppp_generic.c (2.4.x) */
-extern int  ppp_register_compressor   (struct compressor *cp);
-extern void ppp_unregister_compressor (struct compressor *cp);
-
 /*
  * Procedures exported to if_ppp.c.
  */
@@ -623,34 +801,3 @@ struct compressor ppp_mppe = {
     mppe_incomp,	/* incomp */
     mppe_comp_stats,	/* decomp_stat */
 };
-
-/* 2.2 compatibility defines */
-#ifndef __init
-#define __init
-#endif
-#ifndef __exit
-#define __exit
-#endif
-#ifndef MODULE_LICENSE
-#define MODULE_LICENSE(license)
-#endif
-
-int __init
-ppp_mppe_init(void)
-{  
-    int answer = ppp_register_compressor(&ppp_mppe);
-
-    if (answer == 0)
-	printk(KERN_INFO "PPP MPPE Compression module registered\n");
-    return answer;
-}
-
-void __exit
-ppp_mppe_cleanup(void)
-{
-    ppp_unregister_compressor(&ppp_mppe);
-}
-
-module_init(ppp_mppe_init);
-module_exit(ppp_mppe_cleanup);
-MODULE_LICENSE("BSD without advertisement clause");
