diff options
author | cube <cube> | 2005-01-02 02:52:56 +0000 |
---|---|---|
committer | cube <cube> | 2005-01-02 02:52:56 +0000 |
commit | cc8c867afeb9a6f351e7f8a7f51c31c252897054 (patch) | |
tree | 815e41bbd9ed4abc2a706cce70c35766582f7507 /net/mppe-lkm | |
parent | 2eef026e19e24ee098f068674d97bc267e804d89 (diff) | |
download | pkgsrc-cc8c867afeb9a6f351e7f8a7f51c31c252897054.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/DESCR | 4 | ||||
-rw-r--r-- | net/mppe-lkm/Makefile | 27 | ||||
-rw-r--r-- | net/mppe-lkm/PLIST | 2 | ||||
-rw-r--r-- | net/mppe-lkm/distinfo | 5 | ||||
-rw-r--r-- | net/mppe-lkm/files/Makefile | 8 | ||||
-rw-r--r-- | net/mppe-lkm/files/lkm_mppe.c | 114 | ||||
-rw-r--r-- | net/mppe-lkm/patches/patch-aa | 650 |
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"); |