654 lines
20 KiB
Plaintext
654 lines
20 KiB
Plaintext
$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");
|