summaryrefslogtreecommitdiff
path: root/net/mppe-lkm
diff options
context:
space:
mode:
authorcube <cube@pkgsrc.org>2005-01-02 02:52:56 +0000
committercube <cube@pkgsrc.org>2005-01-02 02:52:56 +0000
commit9737cd7203adecebc17d0dd65b85bf7a1c84c8c8 (patch)
tree815e41bbd9ed4abc2a706cce70c35766582f7507 /net/mppe-lkm
parent3e861581566373837c074b8c9af2ffddc6215e9c (diff)
downloadpkgsrc-9737cd7203adecebc17d0dd65b85bf7a1c84c8c8.tar.gz
Initial import of mppe-lkm, version 0.0.4, into the NetBSD Packages
Collection. To get encryption over a PPTP connection, you need the kernel to support the MPPE algorithm. It is used as a PPP compression module, and the mppe-lkm package provides a LKM (Loadable Kernel Module) that will install the functionality into your NetBSD kernel.
Diffstat (limited to 'net/mppe-lkm')
-rw-r--r--net/mppe-lkm/DESCR4
-rw-r--r--net/mppe-lkm/Makefile27
-rw-r--r--net/mppe-lkm/PLIST2
-rw-r--r--net/mppe-lkm/distinfo5
-rw-r--r--net/mppe-lkm/files/Makefile8
-rw-r--r--net/mppe-lkm/files/lkm_mppe.c114
-rw-r--r--net/mppe-lkm/patches/patch-aa650
7 files changed, 810 insertions, 0 deletions
diff --git a/net/mppe-lkm/DESCR b/net/mppe-lkm/DESCR
new file mode 100644
index 00000000000..37e6ff49724
--- /dev/null
+++ b/net/mppe-lkm/DESCR
@@ -0,0 +1,4 @@
+To get encryption over a PPTP connection, you need the kernel to support the
+MPPE algorithm. It is used as a PPP compression module, and the mppe-lkm
+package provides a LKM (Loadable Kernel Module) that will install the
+functionality into your NetBSD kernel.
diff --git a/net/mppe-lkm/Makefile b/net/mppe-lkm/Makefile
new file mode 100644
index 00000000000..6b9aef92b7f
--- /dev/null
+++ b/net/mppe-lkm/Makefile
@@ -0,0 +1,27 @@
+# $NetBSD: Makefile,v 1.1.1.1 2005/01/02 02:52:56 cube Exp $
+
+DISTNAME= kernel_ppp_mppe-0.0.4-src
+PKGNAME= mppe-lkm-0.0.4
+CATEGORIES= net
+MASTER_SITES= ${MASTER_SITE_SOURCEFORGE:=poptop/}
+EXTRACT_SUFX= .tgz
+
+MAINTAINER= cube@NetBSD.org
+COMMENT= NetBSD kernel module for MPPE compression with PPP
+
+NO_CONFIGURE= yes
+
+ONLY_FOR_PLATFORM= NetBSD-*-*
+MAKE_ENV+= KMODDIR=${PREFIX}/lkm
+WRKSRC= ${WRKDIR}/mppe-lkm
+KPM_SRC= ${WRKDIR}/${DISTNAME:C/-src$//}
+
+INSTALLATION_DIRS= lkm
+
+post-extract:
+ @${CP} -Rp ${FILESDIR} ${WRKSRC}
+ @${CHMOD} -R u+w ${KPM_SRC}
+ @${CP} -p ${KPM_SRC}/ppp-comp-local.h ${KPM_SRC}/ppp_mppe_compress.c \
+ ${WRKSRC}
+
+.include "../../mk/bsd.pkg.mk"
diff --git a/net/mppe-lkm/PLIST b/net/mppe-lkm/PLIST
new file mode 100644
index 00000000000..74f87808467
--- /dev/null
+++ b/net/mppe-lkm/PLIST
@@ -0,0 +1,2 @@
+@comment $NetBSD: PLIST,v 1.1.1.1 2005/01/02 02:52:56 cube Exp $
+lkm/mppe.o
diff --git a/net/mppe-lkm/distinfo b/net/mppe-lkm/distinfo
new file mode 100644
index 00000000000..9e31e5c8cad
--- /dev/null
+++ b/net/mppe-lkm/distinfo
@@ -0,0 +1,5 @@
+$NetBSD: distinfo,v 1.1.1.1 2005/01/02 02:52:56 cube Exp $
+
+SHA1 (kernel_ppp_mppe-0.0.4-src.tgz) = 37dc2487c760a78eb02585690bd6a1708d8dbaa2
+Size (kernel_ppp_mppe-0.0.4-src.tgz) = 54194 bytes
+SHA1 (patch-aa) = 56209bf008dbff6983d27c26b011d8a7d839973d
diff --git a/net/mppe-lkm/files/Makefile b/net/mppe-lkm/files/Makefile
new file mode 100644
index 00000000000..9a368e32fe1
--- /dev/null
+++ b/net/mppe-lkm/files/Makefile
@@ -0,0 +1,8 @@
+KMOD= mppe
+SRCS= ppp_mppe_compress.c lkm_mppe.c
+MKMAN= no
+
+# We set LDFLAGS becuase bsd.pkg.mk will put cc specific flags in it.
+LDFLAGS=
+
+.include <bsd.kmod.mk>
diff --git a/net/mppe-lkm/files/lkm_mppe.c b/net/mppe-lkm/files/lkm_mppe.c
new file mode 100644
index 00000000000..234c075b144
--- /dev/null
+++ b/net/mppe-lkm/files/lkm_mppe.c
@@ -0,0 +1,114 @@
+/* NetBSD */
+/*
+ * Copyright (c) 1999 Darrin B. Jewell
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Darrin B. Jewell
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/exec.h>
+#include <sys/lkm.h>
+
+#include <sys/tty.h>
+#include <sys/ttycom.h>
+
+MOD_MISC("mppe");
+
+extern struct compressor ppp_mppe;
+extern struct compressor *ppp_compressors[];
+extern int mppe_in_use;
+
+int mppe_lkmentry __P((struct lkm_table *, int, int));
+int mppe_lkm_load __P((struct lkm_table *, int));
+
+int
+mppe_lkm_load(lkmtp, cmd)
+ struct lkm_table *lkmtp;
+ int cmd;
+{
+ int i;
+ for(i=0;i<7;i++) {
+ if (ppp_compressors[i] == NULL) {
+ ppp_compressors[i] = &ppp_mppe;
+ ppp_compressors[i+1] = NULL;
+ break;
+ }
+ }
+ if (i==7) {
+ printf("MPPE: no free compressor slots\n");
+ return ENODEV;
+ }
+
+ printf("MPPE: loaded into ppp at slot %d\n",i);
+
+ return 0;
+}
+
+int
+mppe_lkm_unload(lkmtp, cmd)
+ struct lkm_table *lkmtp;
+ int cmd;
+{
+ int i;
+ if (mppe_in_use) {
+ printf("MPPE: cannot unload lkm while in use (count=%d)\n",
+ mppe_in_use);
+ return EBUSY;
+ }
+ for(i=0;ppp_compressors[i];i++) {
+ if (ppp_compressors[i] == &ppp_mppe) break;
+ }
+ if (ppp_compressors[i] == NULL) {
+ printf("MPPE: cannot find mppe in ppp compressor slots\n");
+ return ENODEV;
+ }
+ printf("MPPE: unloaded from ppp at slot %d\n",i);
+ do {
+ ppp_compressors[i] = ppp_compressors[i+1];
+ } while(ppp_compressors[i++]);
+
+ return 0;
+}
+
+int
+mppe_lkm_stat(lkmtp, cmd)
+ struct lkm_table *lkmtp;
+ int cmd;
+{
+ printf("MPPE: use count %d\n",mppe_in_use);
+ return 0;
+}
+
+int
+mppe_lkmentry(lkmtp, cmd, ver)
+ struct lkm_table *lkmtp;
+ int cmd, ver;
+{
+ DISPATCH(lkmtp, cmd, ver, mppe_lkm_load,mppe_lkm_unload,mppe_lkm_stat);
+}
diff --git a/net/mppe-lkm/patches/patch-aa b/net/mppe-lkm/patches/patch-aa
new file mode 100644
index 00000000000..daa5e0fda85
--- /dev/null
+++ b/net/mppe-lkm/patches/patch-aa
@@ -0,0 +1,650 @@
+$NetBSD: patch-aa,v 1.1.1.1 2005/01/02 02:52:57 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,32 @@
+ * 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>
+
+-#include <linux/ppp_defs.h>
+-#include <linux/ppp-comp.h>
++#define PACKETPTR struct mbuf *
+
+-#include "arcfour.h"
+-#include "sha1.h"
++#include <net/ppp_defs.h>
++#include <net/ppp-comp.h>
++
++#include <sys/sha1.h>
++#include <crypto/arc4/arc4.h>
++
++#include "ppp-comp-local.h"
++
++int mppe_in_use;
++#define MOD_INC_USE_COUNT mppe_in_use++
++#define MOD_DEC_USE_COUNT mppe_in_use--
++
++#ifdef MPPE_DEBUG
++#define DPRINTF(x) aprint_normal x
++#else
++#define DPRINTF(x)
++#endif
+
+ /*
+ * State for an MPPE (de)compressor.
+@@ -38,8 +53,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 +99,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 +119,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 +134,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 +156,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 +168,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 +185,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 +213,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 +242,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 +260,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 +268,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 +325,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;
++ 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 +405,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 +415,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 +515,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, isize);
+ 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 +627,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 +674,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 +695,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 +752,7 @@ mppe_decompress(void *arg, unsigned char
+ /* good packet credit */
+ state->sanity_errors >>= 1;
+
+- return osize;
++ return DECOMP_OK;
+ }
+
+ /*
+@@ -581,29 +762,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 +798,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");