fix svn patch breakage in glib
[openwrt.git] / obsolete-buildroot / sources / openwrt / kernel / patches / 150-mppe-mppc-0.98.patch
1 diff -ruN linux-2.4.21.orig/drivers/net/Config.in linux-2.4.21/drivers/net/Config.in
2 --- linux-2.4.21.orig/drivers/net/Config.in     2003-06-13 16:51:34.000000000 +0200
3 +++ linux-2.4.21/drivers/net/Config.in  2003-07-08 07:27:10.000000000 +0200
4 @@ -301,6 +301,7 @@
5     dep_tristate '  PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP
6     dep_tristate '  PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP
7     dep_tristate '  PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP $CONFIG_PPP
8 +   dep_tristate '  Microsoft PPP compression/encryption (MPPC/MPPE)' CONFIG_PPP_MPPE $CONFIG_PPP
9     if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
10        dep_tristate '  PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP
11     fi
12 diff -ruN linux-2.4.21.orig/drivers/net/Makefile linux-2.4.21/drivers/net/Makefile
13 --- linux-2.4.21.orig/drivers/net/Makefile      2003-06-13 16:51:34.000000000 +0200
14 +++ linux-2.4.21/drivers/net/Makefile   2003-07-14 23:53:15.000000000 +0200
15 @@ -18,8 +18,9 @@
16  export-objs     :=     8390.o arlan.o aironet4500_core.o aironet4500_card.o \
17                         ppp_async.o ppp_generic.o slhc.o pppox.o auto_irq.o \
18                         net_init.o mii.o
19 -list-multi     :=      rcpci.o
20 +list-multi     :=      rcpci.o ppp_mppe_mppc.o
21  rcpci-objs     :=      rcpci45.o rclanmtl.o
22 +ppp_mppe_c-objs        :=      ppp_mppe_mppc_comp.o ppp_mppe_crypto.o
23  
24  ifeq ($(CONFIG_TULIP),y)
25    obj-y += tulip/tulip.o
26 @@ -149,6 +150,15 @@
27  obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o
28  obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o
29  obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o
30 +
31 +ifeq ($(CONFIG_PPP_MPPE),y)
32 +  obj-y += $(ppp_mppe_c-objs)
33 +else
34 +  ifeq ($(CONFIG_PPP_MPPE),m)
35 +    obj-m += ppp_mppe_mppc.o
36 +  endif
37 +endif
38 +
39  obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
40  
41  obj-$(CONFIG_SLIP) += slip.o
42 @@ -258,3 +268,5 @@
43  rcpci.o: $(rcpci-objs)
44         $(LD) -r -o $@ $(rcpci-objs)
45  
46 +ppp_mppe_mppc.o: $(ppp_mppe_c-objs)
47 +       $(LD) -r -o $@ $(ppp_mppe_c-objs)
48 diff -ruN linux-2.4.21.orig/drivers/net/ppp_generic.c linux-2.4.21/drivers/net/ppp_generic.c
49 --- linux-2.4.21.orig/drivers/net/ppp_generic.c 2003-06-13 16:51:35.000000000 +0200
50 +++ linux-2.4.21/drivers/net/ppp_generic.c      2003-07-12 04:39:03.000000000 +0200
51 @@ -19,7 +19,7 @@
52   * PPP driver, written by Michael Callahan and Al Longyear, and
53   * subsequently hacked by Paul Mackerras.
54   *
55 - * ==FILEVERSION 20020217==
56 + * ==FILEVERSION 20030706==
57   */
58  
59  #include <linux/config.h>
60 @@ -102,6 +102,7 @@
61         spinlock_t      rlock;          /* lock for receive side 58 */
62         spinlock_t      wlock;          /* lock for transmit side 5c */
63         int             mru;            /* max receive unit 60 */
64 +       int             mru_alloc;      /* MAX(1500,MRU) for dev_alloc_skb() */
65         unsigned int    flags;          /* control bits 64 */
66         unsigned int    xstate;         /* transmit state bits 68 */
67         unsigned int    rstate;         /* receive state bits 6c */
68 @@ -129,6 +130,7 @@
69         struct sock_fprog pass_filter;  /* filter for packets to pass */
70         struct sock_fprog active_filter;/* filter for pkts to reset idle */
71  #endif /* CONFIG_PPP_FILTER */
72 +       int             xpad;           /* ECP or CCP (MPPE) transmit padding */
73  };
74  
75  /*
76 @@ -552,7 +554,9 @@
77         case PPPIOCSMRU:
78                 if (get_user(val, (int *) arg))
79                         break;
80 -               ppp->mru = val;
81 +               ppp->mru_alloc = ppp->mru = val;
82 +               if (ppp->mru_alloc < PPP_MRU)
83 +                   ppp->mru_alloc = PPP_MRU;   /* increase for broken peers */
84                 err = 0;
85                 break;
86  
87 @@ -1023,14 +1027,35 @@
88         case PPP_CCP:
89                 /* peek at outbound CCP frames */
90                 ppp_ccp_peek(ppp, skb, 0);
91 +               /*
92 +                * When LZS or MPPE/MPPC is negotiated we don't send
93 +                * CCP_RESETACK after receiving CCP_RESETREQ; in fact pppd
94 +                * sends such a packet but we silently discard it here
95 +                */
96 +               if (CCP_CODE(skb->data+2) == CCP_RESETACK
97 +                   && (ppp->xcomp->compress_proto == CI_MPPE
98 +                       || ppp->xcomp->compress_proto == CI_LZS)) {
99 +                   --ppp->stats.tx_packets;
100 +                   ppp->stats.tx_bytes -= skb->len - 2;
101 +                   kfree_skb(skb);
102 +                   return;
103 +               }
104                 break;
105         }
106  
107         /* try to do packet compression */
108         if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state != 0
109             && proto != PPP_LCP && proto != PPP_CCP) {
110 -               new_skb = alloc_skb(ppp->dev->mtu + ppp->dev->hard_header_len,
111 -                                   GFP_ATOMIC);
112 +               int comp_ovhd = 0;
113 +               /* because of possible data expansion when MPPC or LZS
114 +                  is used, allocate compressor's buffer about 12.5% bigger
115 +                  than MTU */
116 +               if (ppp->xcomp->compress_proto == CI_MPPE)
117 +                   comp_ovhd = (((ppp->dev->mtu * 9) / 8) + 1);
118 +               else if (ppp->xcomp->compress_proto == CI_LZS)
119 +                   comp_ovhd = (((ppp->dev->mtu * 9) / 8) + 1) + LZS_OVHD;
120 +               new_skb = alloc_skb(ppp->dev->mtu + ppp->dev->hard_header_len
121 +                                   + ppp->xpad + comp_ovhd, GFP_ATOMIC);
122                 if (new_skb == 0) {
123                         printk(KERN_ERR "PPP: no memory (comp pkt)\n");
124                         goto drop;
125 @@ -1042,15 +1067,28 @@
126                 /* compressor still expects A/C bytes in hdr */
127                 len = ppp->xcomp->compress(ppp->xc_state, skb->data - 2,
128                                            new_skb->data, skb->len + 2,
129 -                                          ppp->dev->mtu + PPP_HDRLEN);
130 +                                          ppp->dev->mtu + ppp->xpad
131 +                                          + PPP_HDRLEN);
132                 if (len > 0 && (ppp->flags & SC_CCP_UP)) {
133                         kfree_skb(skb);
134                         skb = new_skb;
135                         skb_put(skb, len);
136                         skb_pull(skb, 2);       /* pull off A/C bytes */
137 -               } else {
138 +               } else if (len == 0) {
139                         /* didn't compress, or CCP not up yet */
140                         kfree_skb(new_skb);
141 +               } else {
142 +                       /*
143 +                        * (len < 0)
144 +                        * MPPE requires that we do not send unencrypted
145 +                        * frames.  The compressor will return -1 if we
146 +                        * should drop the frame.  We cannot simply test
147 +                        * the compress_proto because MPPE and MPPC share
148 +                        * the same number.
149 +                        */
150 +                       printk(KERN_ERR "ppp: compressor dropped pkt\n");
151 +                       kfree_skb(new_skb);
152 +                       goto drop;
153                 }
154         }
155  
156 @@ -1538,14 +1576,15 @@
157         int len;
158  
159         if (proto == PPP_COMP) {
160 -               ns = dev_alloc_skb(ppp->mru + PPP_HDRLEN);
161 +               ns = dev_alloc_skb(ppp->mru_alloc + PPP_HDRLEN);
162                 if (ns == 0) {
163                         printk(KERN_ERR "ppp_decompress_frame: no memory\n");
164                         goto err;
165                 }
166                 /* the decompressor still expects the A/C bytes in the hdr */
167                 len = ppp->rcomp->decompress(ppp->rc_state, skb->data - 2,
168 -                               skb->len + 2, ns->data, ppp->mru + PPP_HDRLEN);
169 +                               skb->len + 2, ns->data,
170 +                               ppp->mru_alloc + PPP_HDRLEN);
171                 if (len < 0) {
172                         /* Pass the compressed frame to pppd as an
173                            error indication. */
174 @@ -1571,7 +1610,12 @@
175         return skb;
176  
177   err:
178 -       ppp->rstate |= SC_DC_ERROR;
179 +       if (ppp->rcomp->compress_proto != CI_MPPE
180 +           && ppp->rcomp->compress_proto != CI_LZS) {
181 +           /* If decompression protocol isn't MPPE/MPPC or LZS, we set
182 +            SC_DC_ERROR flag and wait for CCP_RESETACK */
183 +           ppp->rstate |= SC_DC_ERROR;
184 +       }
185         ppp_receive_error(ppp);
186         return skb;
187  }
188 @@ -1980,6 +2024,20 @@
189                                 ocomp->comp_free(ostate);
190                         err = 0;
191                 }
192 +               if (ccp_option[0] == CI_MPPE)
193 +                       /*
194 +                        * pppd (userland) has reduced the MTU by MPPE_PAD,
195 +                        * to accomodate "compressor" growth.  We must
196 +                        * increase the space allocated for compressor
197 +                        * output in ppp_send_frame() accordingly.  Note
198 +                        * that from a purist's view, it may be more correct
199 +                        * to require multilink and fragment large packets,
200 +                        * but that seems inefficient compared to this
201 +                        * little trick.
202 +                        */
203 +                       ppp->xpad = MPPE_PAD;
204 +               else
205 +                       ppp->xpad = 0;
206  
207         } else {
208                 state = cp->decomp_alloc(ccp_option, data.length);
209 @@ -2251,6 +2309,7 @@
210         /* Initialize the new ppp unit */
211         ppp->file.index = unit;
212         ppp->mru = PPP_MRU;
213 +       ppp->mru_alloc = PPP_MRU;
214         init_ppp_file(&ppp->file, INTERFACE);
215         ppp->file.hdrlen = PPP_HDRLEN - 2;      /* don't count proto bytes */
216         for (i = 0; i < NUM_NP; ++i)
217 diff -ruN linux-2.4.21.orig/drivers/net/ppp_mppe_crypto.c linux-2.4.21/drivers/net/ppp_mppe_crypto.c
218 --- linux-2.4.21.orig/drivers/net/ppp_mppe_crypto.c     1970-01-01 01:00:00.000000000 +0100
219 +++ linux-2.4.21/drivers/net/ppp_mppe_crypto.c  2003-07-08 19:07:18.000000000 +0200
220 @@ -0,0 +1,257 @@
221 +/*
222 + * ppp_mppe_crypto.c - cryptografic funtions for MPPE
223 + *
224 + *  This code is Public Domain. Please see comments below.
225 + *
226 + *  I have just put SHA1 and ARCFOUR implementations into one file
227 + *  in order to not pollute kernel namespace. 
228 + *
229 + *  Jan Dubiec <jdx@slackware.pl>, 2003-07-08
230 + */
231 +
232 +/*
233 + * ftp://ftp.funet.fi/pub/crypt/hash/sha/sha1.c
234 + * 
235 + * SHA-1 in C
236 + * By Steve Reid <steve@edmweb.com>
237 + * 100% Public Domain
238 + * 
239 + * Test Vectors (from FIPS PUB 180-1)
240 + * "abc"
241 + * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
242 + * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
243 + * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
244 + * A million repetitions of "a"
245 + * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
246 + */
247 +
248 +/* #define SHA1HANDSOFF * Copies data before messing with it. */
249 +
250 +#if defined(__linux__)
251 +#include <asm/byteorder.h>
252 +#include <linux/string.h>
253 +#elif defined(__solaris__)
254 +#include <sys/isa_defs.h>
255 +#include <sys/ddi.h>
256 +#include <sys/sunddi.h>
257 +#define memcpy(d, s, c) bcopy(s, d, c)
258 +#define memset(d, b, c) bzero(d, c)
259 +#endif
260 +
261 +#include "ppp_mppe_crypto.h"
262 +
263 +static void SHA1_Transform(unsigned long[5], const unsigned char[64]);
264 +
265 +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
266 +
267 +/* blk0() and blk() perform the initial expand. */
268 +/* I got the idea of expanding during the round function from SSLeay */
269 +#if defined(__LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN)
270 +#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
271 +    |(rol(block->l[i],8)&0x00FF00FF))
272 +#elif defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN)
273 +#define blk0(i) block->l[i]
274 +#else
275 +#error Endianness not defined
276 +#endif
277 +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
278 +    ^block->l[(i+2)&15]^block->l[i&15],1))
279 +
280 +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
281 +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
282 +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
283 +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
284 +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
285 +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
286 +
287 +/* Hash a single 512-bit block. This is the core of the algorithm. */
288 +static void
289 +SHA1_Transform(unsigned long state[5], const unsigned char buffer[64])
290 +{
291 +    unsigned long a, b, c, d, e;
292 +    typedef union {
293 +       unsigned char c[64];
294 +       unsigned long l[16];
295 +    } CHAR64LONG16;
296 +    CHAR64LONG16 *block;
297 +
298 +#ifdef SHA1HANDSOFF
299 +    static unsigned char workspace[64];
300 +    block = (CHAR64LONG16 *) workspace;
301 +    memcpy(block, buffer, 64);
302 +#else
303 +    block = (CHAR64LONG16 *) buffer;
304 +#endif
305 +    /* Copy context->state[] to working vars */
306 +    a = state[0];
307 +    b = state[1];
308 +    c = state[2];
309 +    d = state[3];
310 +    e = state[4];
311 +    /* 4 rounds of 20 operations each. Loop unrolled. */
312 +    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
313 +    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
314 +    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
315 +    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
316 +    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
317 +    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
318 +    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
319 +    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
320 +    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
321 +    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
322 +    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
323 +    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
324 +    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
325 +    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
326 +    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
327 +    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
328 +    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
329 +    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
330 +    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
331 +    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
332 +    /* Add the working vars back into context.state[] */
333 +    state[0] += a;
334 +    state[1] += b;
335 +    state[2] += c;
336 +    state[3] += d;
337 +    state[4] += e;
338 +    /* Wipe variables */
339 +    a = b = c = d = e = 0;
340 +}
341 +
342 +/* SHA1Init - Initialize new context */
343 +void
344 +SHA1_Init(SHA1_CTX *context)
345 +{
346 +    /* SHA1 initialization constants */
347 +    context->state[0] = 0x67452301;
348 +    context->state[1] = 0xEFCDAB89;
349 +    context->state[2] = 0x98BADCFE;
350 +    context->state[3] = 0x10325476;
351 +    context->state[4] = 0xC3D2E1F0;
352 +    context->count[0] = context->count[1] = 0;
353 +}
354 +
355 +/* Run your data through this. */
356 +void
357 +SHA1_Update(SHA1_CTX *context, const unsigned char *data, unsigned int len)
358 +{
359 +    unsigned int i, j;
360 +
361 +    j = (context->count[0] >> 3) & 63;
362 +    if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
363 +    context->count[1] += (len >> 29);
364 +    if ((j + len) > 63) {
365 +       memcpy(&context->buffer[j], data, (i = 64-j));
366 +       SHA1_Transform(context->state, context->buffer);
367 +       for ( ; i + 63 < len; i += 64) {
368 +           SHA1_Transform(context->state, &data[i]);
369 +       }
370 +       j = 0;
371 +    }
372 +    else
373 +       i = 0;
374 +
375 +    memcpy(&context->buffer[j], &data[i], len - i);
376 +}
377 +
378 +/* Add padding and return the message digest. */
379 +void
380 +SHA1_Final(unsigned char digest[20], SHA1_CTX *context)
381 +{
382 +    unsigned long i, j;
383 +    unsigned char finalcount[8];
384 +
385 +    for (i = 0; i < 8; i++) {
386 +        finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
387 +         >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
388 +    }
389 +    SHA1_Update(context, (unsigned char *) "\200", 1);
390 +    while ((context->count[0] & 504) != 448) {
391 +       SHA1_Update(context, (unsigned char *) "\0", 1);
392 +    }
393 +    SHA1_Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
394 +    for (i = 0; i < 20; i++) {
395 +       digest[i] = (unsigned char)
396 +                    ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
397 +    }
398 +    /* Wipe variables */
399 +    i = j = 0;
400 +    memset(context->buffer, 0, 64);
401 +    memset(context->state, 0, 20);
402 +    memset(context->count, 0, 8);
403 +    memset(&finalcount, 0, 8);
404 +#ifdef SHA1HANDSOFF  /* make SHA1Transform overwrite it's own static vars */
405 +    SHA1Transform(context->state, context->buffer);
406 +#endif
407 +}
408 +
409 +/*
410 + * arcfour.c
411 + * by Frank Cusack <frank@google.com>
412 + * 100% public domain
413 + *
414 + * Implemented from the description in _Applied Cryptography_, 2nd ed.
415 + *
416 + * ** Distribution ** of this software is unlimited and unrestricted.
417 + *
418 + * ** Use ** of this software is almost certainly legal; however, refer
419 + * to <http://theory.lcs.mit.edu/~rivest/faq.html>.
420 + */
421 +
422 +#define swap(a, b)             \
423 +{                              \
424 +    unsigned char t = b;       \
425 +    b = a;                     \
426 +    a = t;                     \
427 +}
428 +
429 +/*
430 + * Initialize arcfour from a key.
431 + */
432 +void
433 +arcfour_setkey(arcfour_context *context, const unsigned char *key,
434 +              unsigned keylen)
435 +{
436 +    unsigned i, j;
437 +    unsigned char K[256];
438 +
439 +    context->i = context->j = 0;
440 +
441 +    for (i = 0; i < 256; i++) {
442 +       context->S[i] = i;
443 +       K[i] = key[i % keylen];
444 +    }
445 +
446 +    j = 0;
447 +    for (i = 0; i < 256; i++) {
448 +       j = (j + context->S[i] + K[i]) % 256;
449 +       swap(context->S[i], context->S[j]);
450 +    }
451 +
452 +    memset(K, 0, sizeof(K));
453 +}
454 +
455 +/*
456 + * plaintext -> ciphertext (or vice versa)
457 + */
458 +void
459 +arcfour_encrypt(arcfour_context *context, const unsigned char *in, unsigned len,
460 +               unsigned char *out)
461 +{
462 +    unsigned i = context->i;
463 +    unsigned j = context->j;
464 +    unsigned char *S = context->S;
465 +    unsigned char K;
466 +
467 +    while (len--) {
468 +       i = (i + 1) % 256;
469 +       j = (j + S[i]) % 256;
470 +       swap(S[i], S[j]);
471 +       K = S[(S[i] + S[j]) % 256];
472 +       *out++ = *in++ ^ K;
473 +    }
474 +
475 +    context->i = i;
476 +    context->j = j;
477 +}
478 diff -ruN linux-2.4.21.orig/drivers/net/ppp_mppe_crypto.h linux-2.4.21/drivers/net/ppp_mppe_crypto.h
479 --- linux-2.4.21.orig/drivers/net/ppp_mppe_crypto.h     1970-01-01 01:00:00.000000000 +0100
480 +++ linux-2.4.21/drivers/net/ppp_mppe_crypto.h  2003-07-08 19:07:25.000000000 +0200
481 @@ -0,0 +1,40 @@
482 +/*
483 + * ppp_mppe_crypto.h - cryptografic funtion prototypes for MPPE
484 + *
485 + *  This code is Public Domain. Please see comments below.
486 + *
487 + *  I have just put SHA1 and ARCFOUR declarations into one file
488 + *  in order to not pollute kernel namespace. 
489 + *
490 + *  Jan Dubiec <jdx@slackware.pl>, 2003-07-08
491 + */
492 +
493 +#ifndef _PPP_MPPE_CRYPTO_
494 +#define _PPP_MPPE_CRYPTO_
495 +
496 +/* SHA1 definitions and prototypes */
497 +typedef struct {
498 +    unsigned long state[5];
499 +    unsigned long count[2];
500 +    unsigned char buffer[64];
501 +} SHA1_CTX;
502 +
503 +#define SHA1_SIGNATURE_SIZE 20
504 +
505 +extern void SHA1_Init(SHA1_CTX *);
506 +extern void SHA1_Update(SHA1_CTX *, const unsigned char *, unsigned int);
507 +extern void SHA1_Final(unsigned char[SHA1_SIGNATURE_SIZE], SHA1_CTX *);
508 +
509 +/* ARCFOUR (aka RC4) definitions and prototypes */
510 +typedef struct {
511 +    unsigned i;
512 +    unsigned j;
513 +    unsigned char S[256];
514 +} arcfour_context;
515 +
516 +extern void arcfour_setkey(arcfour_context *, const unsigned char *, unsigned);
517 +extern void arcfour_encrypt(arcfour_context *, const unsigned char *, unsigned,
518 +                           unsigned char *);
519 +#define arcfour_decrypt arcfour_encrypt
520 +
521 +#endif /* _PPP_MPPE_CRYPTO_ */
522 diff -ruN linux-2.4.21.orig/drivers/net/ppp_mppe_mppc_comp.c linux-2.4.21/drivers/net/ppp_mppe_mppc_comp.c
523 --- linux-2.4.21.orig/drivers/net/ppp_mppe_mppc_comp.c  1970-01-01 01:00:00.000000000 +0100
524 +++ linux-2.4.21/drivers/net/ppp_mppe_mppc_comp.c       2003-08-07 22:36:59.000000000 +0200
525 @@ -0,0 +1,1144 @@
526 +/*
527 + * ppp_mppe_mppc_comp.c - MPPC/MPPE "compressor/decompressor" module.
528 + *
529 + * Copyright (c) 1994 Árpád Magosányi <mag@bunuel.tii.matav.hu>
530 + * Copyright (c) 1999 Tim Hockin, Cobalt Networks Inc. <thockin@cobaltnet.com>
531 + * Copyright (c) 2002, 2003 Jan Dubiec <jdx@slackware.pl>
532 + * 
533 + * Permission to use, copy, modify, and distribute this software and its
534 + * documentation is hereby granted, provided that the above copyright
535 + * notice appears in all copies. This software is provided without any
536 + * warranty, express or implied.
537 + *
538 + * The code is based on MPPE kernel module written by Árpád Magosányi and
539 + * Tim Hockin which can be found on http://planetmirror.com/pub/mppe/.
540 + * I have added MPPC and 56 bit session keys support in MPPE.
541 + *
542 + * WARNING! Although this is open source code, its usage in some countries
543 + * (in particular in the USA) may violate Stac Inc. patent for MPPC.
544 + *
545 + * Compile command:
546 + * gcc -O2 -Wall -I/usr/src/linux/include -D__KERNEL__ -DMODULE -c ppp_mppe_mppc_comp.c
547 + *
548 + *  ==FILEVERSION 20030807==
549 + *
550 + */
551 +
552 +#include <linux/module.h>
553 +#include <linux/slab.h>
554 +#include <linux/vmalloc.h>
555 +#include <linux/init.h>
556 +
557 +#include <linux/ppp_defs.h>
558 +#include <linux/ppp-comp.h>
559 +
560 +#include "ppp_mppe_crypto.h"
561 +
562 +/*
563 + * State for a mppc/mppe "(de)compressor".
564 + */
565 +struct ppp_mppe_state {
566 +    arcfour_context arcfour_context;
567 +    u8         master_key[MPPE_MAX_KEY_LEN];
568 +    u8         session_key[MPPE_MAX_KEY_LEN];
569 +    u8         mppc;           /* do we use compression (MPPC)? */
570 +    u8         mppe;           /* do we use encryption (MPPE)? */
571 +    u8         keylen;         /* key length in bytes */
572 +    u8         bitkeylen;      /* key length in bits */
573 +    u16                ccount;         /* coherency counter */
574 +    u16                bits;           /* MPPC/MPPE control bits */
575 +    u8         stateless;      /* do we use stateless mode? */
576 +    u8         nextflushed;    /* set A bit in the next outgoing packet;
577 +                                  used only by compressor*/
578 +    u8         flushexpected;  /* drop packets until A bit is received;
579 +                                  used only by decompressor*/
580 +    u8         *hist;          /* MPPC history */
581 +    u16                *hash;          /* Hash table; used only by compressor */
582 +    u16                histptr;        /* history "cursor" */
583 +    int                unit;
584 +    int                debug;
585 +    int                mru;
586 +    struct compstat stats;
587 +};
588 +
589 +#define MPPE_OVHD              2       /* MPPE overhead */
590 +#define MPPE_HIST_LEN          8192    /* MPPC history size */
591 +#define MPPE_MAX_CCOUNT                0x0FFF  /* max. coherency counter value */
592 +
593 +#define MPPE_BIT_FLUSHED       0x80    /* bit A */
594 +#define MPPE_BIT_RESET         0x40    /* bit B */
595 +#define MPPE_BIT_COMP          0x20    /* bit C */
596 +#define MPPE_BIT_ENCRYPTED     0x10    /* bit D */
597 +
598 +#define MPPE_SALT0             0xD1    /* values used in MPPE key derivation */
599 +#define MPPE_SALT1             0x26    /* according to RFC3079 */
600 +#define MPPE_SALT2             0x9E
601 +
602 +#define MPPE_CCOUNT(x)         ((((x)[4] & 0x0f) << 8) + (x)[5])
603 +#define MPPE_BITS(x)           ((x)[4] & 0xf0)
604 +#define MPPE_CTRLHI(x)         ((((x)->ccount & 0xf00)>>8)|((x)->bits))
605 +#define MPPE_CTRLLO(x)         ((x)->ccount & 0xff)
606 +
607 +/*
608 + * Key Derivation, from RFC 3078, RFC 3079.
609 + * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079.
610 + */
611 +static void
612 +GetNewKeyFromSHA(unsigned char *MasterKey, unsigned char *SessionKey,
613 +                unsigned long SessionKeyLength, unsigned char *InterimKey)
614 +{
615 +    /*Pads used in key derivation */
616 +    static unsigned char  SHAPad1[40] =
617 +    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618 +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619 +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620 +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
621 +
622 +    static unsigned char  SHAPad2[40] =
623 +    { 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
624 +      0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
625 +      0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
626 +      0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2 };
627 +
628 +    SHA1_CTX Context;
629 +    unsigned char Digest[SHA1_SIGNATURE_SIZE];
630 +
631 +    SHA1_Init(&Context);
632 +    SHA1_Update(&Context, MasterKey, SessionKeyLength);
633 +    SHA1_Update(&Context, SHAPad1, sizeof(SHAPad1));
634 +    SHA1_Update(&Context, SessionKey, SessionKeyLength);
635 +    SHA1_Update(&Context, SHAPad2, sizeof(SHAPad2));
636 +    SHA1_Final(Digest,&Context);
637 +    memcpy(InterimKey, Digest, SessionKeyLength);
638 +}
639 +
640 +static void
641 +mppe_change_key(struct ppp_mppe_state *state, int initialize)
642 +{
643 +    unsigned char InterimKey[MPPE_MAX_KEY_LEN];
644 +
645 +    GetNewKeyFromSHA(state->master_key, state->session_key,
646 +                    state->keylen, InterimKey);
647 +    if (initialize) {
648 +       memcpy(state->session_key, InterimKey, state->keylen);
649 +    } else {
650 +       arcfour_setkey(&state->arcfour_context, InterimKey, state->keylen);
651 +       arcfour_encrypt(&state->arcfour_context, InterimKey, state->keylen,
652 +                       state->session_key);
653 +    }
654 +    if (state->keylen == 8) {
655 +       if (state->bitkeylen == 40) {
656 +           state->session_key[0] = MPPE_SALT0;
657 +           state->session_key[1] = MPPE_SALT1;
658 +           state->session_key[2] = MPPE_SALT2;
659 +       } else {
660 +           state->session_key[0] = MPPE_SALT0;
661 +       }
662 +    }
663 +    arcfour_setkey(&state->arcfour_context, state->session_key, state->keylen);
664 +}
665 +
666 +/* increase 12-bit coherency counter */
667 +static inline void
668 +mppe_increase_ccount(struct ppp_mppe_state *state)
669 +{
670 +    state->ccount = (state->ccount + 1) & MPPE_MAX_CCOUNT;
671 +    if (state->mppe) {
672 +       if (state->stateless) {
673 +           mppe_change_key(state, 0);
674 +           state->nextflushed = 1;
675 +       } else {
676 +           if ((state->ccount & 0xff) == 0xff) {
677 +               mppe_change_key(state, 0);
678 +               state->nextflushed = 1;
679 +           }
680 +       }
681 +    }
682 +}
683 +
684 +/* allocate space for a MPPE/MPPC (de)compressor.  */
685 +/*   comp != 0 -> init compressor */
686 +/*   comp = 0 -> init decompressor */
687 +static void *
688 +mppe_alloc(unsigned char *options, int opt_len, int comp)
689 +{
690 +    struct ppp_mppe_state *state;
691 +    u8* fname;
692 +
693 +    fname = comp ? "mppe_comp_alloc" : "mppe_decomp_alloc";
694 +
695 +    /*  
696 +       Hack warning - additionally to the standard MPPC/MPPE configuration
697 +       options, pppd passes to the (de)copressor 8 or 16 byte session key.
698 +       Therefore options[1] contains MPPC/MPPE configuration option length
699 +       (CILEN_MPPE = 6), but the real options length, depending on the key
700 +       length, is 6+8 or 6+16.
701 +    */
702 +    if (opt_len < CILEN_MPPE) {
703 +       printk(KERN_WARNING "%s: wrong options length: %u\n", fname, opt_len);
704 +       return NULL;
705 +    }
706 +
707 +    if (options[0] != CI_MPPE || options[1] != CILEN_MPPE ||
708 +       (options[2] & ~MPPE_STATELESS) != 0 ||
709 +       options[3] != 0 || options[4] != 0 ||
710 +       (options[5] & ~(MPPE_128BIT|MPPE_56BIT|MPPE_40BIT|MPPE_MPPC)) != 0 ||
711 +       (options[5] & (MPPE_128BIT|MPPE_56BIT|MPPE_40BIT|MPPE_MPPC)) == 0) {
712 +       printk(KERN_WARNING "%s: options rejected: o[0]=%02x, o[1]=%02x, "
713 +              "o[2]=%02x, o[3]=%02x, o[4]=%02x, o[5]=%02x\n", fname, options[0],
714 +              options[1], options[2], options[3], options[4], options[5]);
715 +       return NULL;
716 +    }
717 +
718 +    state = (struct ppp_mppe_state *)kmalloc(sizeof(*state), GFP_KERNEL);
719 +    if (state == NULL) {
720 +       printk(KERN_ERR "%s: cannot allocate space for %scompressor\n", fname,
721 +              comp ? "" : "de");
722 +       return NULL;
723 +    }
724 +    memset(state, 0, sizeof(struct ppp_mppe_state));
725 +
726 +    state->mppc = options[5] & MPPE_MPPC;      /* Do we use MPPC? */
727 +    state->mppe = options[5] & (MPPE_128BIT | MPPE_56BIT |
728 +       MPPE_40BIT);                            /* Do we use MPPE? */
729 +
730 +    if (state->mppc) {
731 +       /* allocate MPPC history */
732 +       state->hist = (u8*)vmalloc(2*MPPE_HIST_LEN*sizeof(u8));
733 +       if (state->hist == NULL) {
734 +           kfree(state);
735 +           printk(KERN_ERR "%s: cannot allocate space for MPPC history\n",
736 +                  fname);
737 +           return NULL;
738 +       }
739 +
740 +       /* allocate hashtable for MPPC compressor */
741 +       if (comp) {
742 +           state->hash = (u16*)vmalloc(MPPE_HIST_LEN*sizeof(u16));
743 +           if (state->hash == NULL) {
744 +               vfree(state->hist);
745 +               kfree(state);
746 +               printk(KERN_ERR "%s: cannot allocate space for MPPC history\n",
747 +                      fname);
748 +               return NULL;
749 +           }
750 +       }
751 +    }
752 +
753 +    MOD_INC_USE_COUNT;
754 +
755 +    if (state->mppe) { /* specific for MPPE */
756 +       memcpy(state->master_key, options+CILEN_MPPE, MPPE_MAX_KEY_LEN);
757 +       memcpy(state->session_key, state->master_key, MPPE_MAX_KEY_LEN);
758 +       /* initial key generation is done in mppe_init() */
759 +    }
760 +
761 +    return (void *) state;
762 +}
763 +
764 +static void *
765 +mppe_comp_alloc(unsigned char *options, int opt_len)
766 +{
767 +    return mppe_alloc(options, opt_len, 1);
768 +}
769 +
770 +static void *
771 +mppe_decomp_alloc(unsigned char *options, int opt_len)
772 +{
773 +    return mppe_alloc(options, opt_len, 0);
774 +}
775 +
776 +/* cleanup the (de)compressor */
777 +static void
778 +mppe_comp_free(void *arg)
779 +{
780 +    struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
781 +
782 +    if (state != NULL) {
783 +       if (state->hist != NULL)
784 +           vfree(state->hist);
785 +       if (state->hash != NULL)
786 +           vfree(state->hash);
787 +       kfree(state);
788 +    }
789 +    MOD_DEC_USE_COUNT;
790 +}
791 +
792 +/* init MPPC/MPPE (de)compresor */
793 +/*   comp != 0 -> init compressor */
794 +/*   comp = 0 -> init decompressor */
795 +static int
796 +mppe_init(void *arg, unsigned char *options, int opt_len, int unit,
797 +         int hdrlen, int mru, int debug, int comp)
798 +{
799 +    struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
800 +    u8* fname;
801 +
802 +    fname = comp ? "mppe_comp_init" : "mppe_decomp_init";
803 +
804 +    if (opt_len < CILEN_MPPE) {
805 +       if (debug)
806 +           printk(KERN_WARNING "%s: wrong options length: %u\n",
807 +                  fname, opt_len);
808 +       return 0;
809 +    }
810 +
811 +    if (options[0] != CI_MPPE || options[1] != CILEN_MPPE ||
812 +       (options[2] & ~MPPE_STATELESS) != 0 ||
813 +       options[3] != 0 || options[4] != 0 ||
814 +       (options[5] & ~(MPPE_56BIT|MPPE_128BIT|MPPE_40BIT|MPPE_MPPC)) != 0 ||
815 +       (options[5] & (MPPE_56BIT|MPPE_128BIT|MPPE_40BIT|MPPE_MPPC)) == 0) {
816 +       if (debug)
817 +           printk(KERN_WARNING "%s: options rejected: o[0]=%02x, o[1]=%02x, "
818 +                  "o[2]=%02x, o[3]=%02x, o[4]=%02x, o[5]=%02x\n", fname,
819 +                  options[0], options[1], options[2], options[3], options[4],
820 +                  options[5]);
821 +       return 0;
822 +    }
823 +
824 +    if ((options[5] & ~MPPE_MPPC) != MPPE_128BIT &&
825 +       (options[5] & ~MPPE_MPPC) != MPPE_56BIT &&
826 +       (options[5] & ~MPPE_MPPC) != MPPE_40BIT &&
827 +       (options[5] & MPPE_MPPC) != MPPE_MPPC) {
828 +       if (debug)
829 +           printk(KERN_WARNING "%s: don't know what to do: o[5]=%02x\n",
830 +                  fname, options[5]);
831 +       return 0;
832 +    }
833 +
834 +    state->mppc = options[5] & MPPE_MPPC;      /* Do we use MPPC? */
835 +    state->mppe = options[5] & (MPPE_128BIT | MPPE_56BIT |
836 +       MPPE_40BIT);                            /* Do we use MPPE? */
837 +    state->stateless = options[2] & MPPE_STATELESS; /* Do we use stateless mode? */
838 +
839 +    switch (state->mppe) {
840 +    case MPPE_40BIT:     /* 40 bit key */
841 +       state->keylen = 8;
842 +       state->bitkeylen = 40;
843 +       break;
844 +    case MPPE_56BIT:     /* 56 bit key */
845 +       state->keylen = 8;
846 +       state->bitkeylen = 56;
847 +       break;
848 +    case MPPE_128BIT:     /* 128 bit key */
849 +       state->keylen = 16;
850 +       state->bitkeylen = 128;
851 +       break;
852 +    default:
853 +       state->keylen = 0;
854 +       state->bitkeylen = 0;
855 +    }
856 +
857 +    state->ccount = MPPE_MAX_CCOUNT;
858 +    state->bits = 0;
859 +    state->unit  = unit;
860 +    state->debug = debug;
861 +    state->histptr = MPPE_HIST_LEN;
862 +    if (state->mppc) { /* reset history if MPPC was negotiated */
863 +       memset(state->hist, 0, 2*MPPE_HIST_LEN*sizeof(u8));
864 +    }
865 +
866 +    if (state->mppe) { /* generate initial session keys */
867 +       mppe_change_key(state, 1);
868 +    }
869 +
870 +    if (comp) { /* specific for compressor */
871 +       state->nextflushed = 1;
872 +    } else { /* specific for decompressor */
873 +       state->mru = mru;
874 +       state->flushexpected = 1;
875 +    }
876 +
877 +    return 1;
878 +}
879 +
880 +static int
881 +mppe_comp_init(void *arg, unsigned char *options, int opt_len, int unit,
882 +              int hdrlen, int debug)
883 +{
884 +    return mppe_init(arg, options, opt_len, unit, hdrlen, 0, debug, 1);
885 +}
886 +
887 +
888 +static int
889 +mppe_decomp_init(void *arg, unsigned char *options, int opt_len, int unit,
890 +                int hdrlen, int mru, int debug)
891 +{
892 +    return mppe_init(arg, options, opt_len, unit, hdrlen, mru, debug, 0);
893 +}
894 +
895 +static void
896 +mppe_comp_reset(void *arg)
897 +{
898 +    struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg;
899 +
900 +    if (state->debug)
901 +       printk(KERN_DEBUG "%s%d: resetting MPPC/MPPE compressor\n",
902 +              __FUNCTION__, state->unit);
903 +
904 +    state->nextflushed = 1;
905 +    if (state->mppe)
906 +       arcfour_setkey(&state->arcfour_context, state->session_key,
907 +                      state->keylen);
908 +}
909 +
910 +static void
911 +mppe_decomp_reset(void *arg)
912 +{
913 +    /* When MPPC/MPPE is in use, we shouldn't receive any CCP Reset-Ack.
914 +       But when we receive such a packet, we just ignore it. */
915 +    return;
916 +}
917 +
918 +static void
919 +mppe_stats(void *arg, struct compstat *stats)
920 +{
921 +    struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg;
922 +
923 +    *stats = state->stats;
924 +}
925 +
926 +/***************************/
927 +/**** Compression stuff ****/
928 +/***************************/
929 +/* inserts 1 to max. 8 bits into the output buffer */
930 +static inline void putbits8(u8 *buf, u32 val, const u32 n, u32 *i, u32 *l)
931 +{
932 +    buf += *i;
933 +    if (*l >= n) {
934 +       *l = (*l) - n;
935 +       val <<= *l;
936 +       *buf = *buf | (val & 0xff);
937 +       if (*l == 0) {
938 +           *l = 8;
939 +           (*i)++;
940 +           *(++buf) = 0;
941 +       }
942 +    } else {
943 +       (*i)++;
944 +       *l = 8 - n + (*l);
945 +       val <<= *l;
946 +       *buf = *buf | ((val >> 8) & 0xff);
947 +       *(++buf) = val & 0xff;
948 +    }
949 +}
950 +
951 +/* inserts 9 to max. 16 bits into the output buffer */
952 +static inline void putbits16(u8 *buf, u32 val, const u32 n, u32 *i, u32 *l)
953 +{
954 +    buf += *i;
955 +    if (*l >= n - 8) {
956 +       (*i)++;
957 +       *l = 8 - n + (*l);
958 +       val <<= *l;
959 +       *buf = *buf | ((val >> 8) & 0xff);
960 +       *(++buf) = val & 0xff;
961 +       if (*l == 0) {
962 +           *l = 8;
963 +           (*i)++;
964 +           *(++buf) = 0;
965 +       }
966 +    } else {
967 +       (*i)++; (*i)++;
968 +       *l = 16 - n + (*l);
969 +       val <<= *l;
970 +       *buf = *buf | ((val >> 16) & 0xff);
971 +       *(++buf) = (val >> 8) & 0xff;
972 +       *(++buf) = val & 0xff;
973 +    }
974 +}
975 +
976 +/* inserts 17 to max. 24 bits into the output buffer */
977 +static inline void putbits24(u8 *buf, u32 val, const u32 n, u32 *i, u32 *l)
978 +{
979 +    buf += *i;
980 +    if (*l >= n - 16) {
981 +       (*i)++; (*i)++;
982 +       *l = 16 - n + (*l);
983 +       val <<= *l;
984 +       *buf = *buf | ((val >> 16) & 0xff);
985 +       *(++buf) = (val >> 8) & 0xff;
986 +       *(++buf) = val & 0xff;
987 +       if (*l == 0) {
988 +           *l = 8;
989 +           (*i)++;
990 +           *(++buf) = 0;
991 +       }
992 +    } else {
993 +       (*i)++; (*i)++; (*i)++;
994 +       *l = 24 - n + (*l);
995 +       val <<= *l;
996 +       *buf = *buf | ((val >> 24) & 0xff);
997 +       *(++buf) = (val >> 16) & 0xff;
998 +       *(++buf) = (val >> 8) & 0xff;
999 +       *(++buf) = val & 0xff;
1000 +    }
1001 +}
1002 +
1003 +static int
1004 +mppc_compress(struct ppp_mppe_state *state, unsigned char *ibuf,
1005 +             unsigned char *obuf, int isize, int osize)
1006 +{
1007 +    u32 olen, off, len, idx, i, l;
1008 +    u8 *hist, *sbuf, *p, *q, *r, *s;
1009 +
1010 +    /*  
1011 +       At this point, to avoid possible buffer overflow caused by packet
1012 +       expansion during/after compression,  we should make sure that
1013 +       osize >= (((isize*9)/8)+1)+2, but we don't do that because in
1014 +       ppp_generic.c we just allocate bigger obuf.
1015 +
1016 +       Maximum MPPC packet expansion is 12.5%. This is the worst case when
1017 +       all octets in the input buffer are >= 0x80 and we cannot find any
1018 +       repeated tokens. Additionally we have to reserve 2 bytes for MPPE/MPPC
1019 +       status bits and coherency counter.
1020 +    */
1021 +
1022 +    hist = state->hist + MPPE_HIST_LEN;
1023 +    /* check if there is enough room at the end of the history */
1024 +    if (state->histptr + isize >= 2*MPPE_HIST_LEN) {
1025 +       state->bits |= MPPE_BIT_RESET;
1026 +       state->histptr = MPPE_HIST_LEN;
1027 +       memcpy(state->hist, hist, MPPE_HIST_LEN);
1028 +    }
1029 +    /* add packet to the history; isize must be <= MPPE_HIST_LEN */
1030 +    sbuf = state->hist + state->histptr;
1031 +    memcpy(sbuf, ibuf, isize);
1032 +    state->histptr += isize;
1033 +
1034 +    /* compress data */
1035 +    r = sbuf + isize;
1036 +    *obuf = olen = i = 0;
1037 +    l = 8;
1038 +    while (i < isize - 2) {
1039 +       s = q = sbuf + i;
1040 +       idx = ((40542*((((s[0]<<4)^s[1])<<4)^s[2]))>>4) & 0x1FFF;
1041 +       p = hist + state->hash[idx];
1042 +       state->hash[idx] = (u16) (s - hist);
1043 +       off = s - p;
1044 +       if (off > 8191 || off < 1 || *p++ != *s++ || *p++ != *s++ || *p++ != *s++)
1045 +           goto literal;
1046 +       if (r - q >= 64) {
1047 +           *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
1048 +           *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
1049 +           *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
1050 +           *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
1051 +           *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
1052 +           *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
1053 +           *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
1054 +           *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
1055 +           *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
1056 +           *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
1057 +           *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
1058 +           *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
1059 +           *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
1060 +           *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
1061 +           *p++ != *s++ || *p++ != *s++ || *p++ != *s++ || *p++ != *s++ ||
1062 +           *p++ != *s++;
1063 +           if (s - q == 64) {
1064 +               p--; s--;
1065 +               while((*p++ == *s++) && (s < r));
1066 +           }
1067 +       } else {
1068 +           while((*p++ == *s++) && (s < r));
1069 +       }
1070 +       len = s - q - 1;
1071 +       i += len;
1072 +
1073 +       /* at least 3 character match found; code data */
1074 +       /* encode offset */
1075 +       if (off < 64) {                 /* 10-bit offset; 0 <= offset < 64 */
1076 +           putbits16(obuf, 0x3c0|off, 10, &olen, &l);
1077 +       } else if (off < 320) {         /* 12-bit offset; 64 <= offset < 320 */
1078 +           putbits16(obuf, 0xe00|(off-64), 12, &olen, &l);
1079 +       } else if (off < 8192) {        /* 16-bit offset; 320 <= offset < 8192 */
1080 +           putbits16(obuf, 0xc000|(off-320), 16, &olen, &l);
1081 +       } else {
1082 +           /* This shouldn't happen; we return 0 what means "packet expands",
1083 +           and we send packet uncompressed. */
1084 +           if (state->debug)
1085 +               printk(KERN_DEBUG "%s%d: wrong offset value: %d\n",
1086 +                      __FUNCTION__, state->unit, off);
1087 +           return 0;
1088 +       }
1089 +       /* encode length of match */
1090 +       if (len < 4) {                  /* length = 3 */
1091 +           putbits8(obuf, 0, 1, &olen, &l);
1092 +       } else if (len < 8) {           /* 4 <= length < 8 */
1093 +           putbits8(obuf, 0x08|(len&0x03), 4, &olen, &l);
1094 +       } else if (len < 16) {          /* 8 <= length < 16 */
1095 +           putbits8(obuf, 0x30|(len&0x07), 6, &olen, &l);
1096 +       } else if (len < 32) {          /* 16 <= length < 32 */
1097 +           putbits8(obuf, 0xe0|(len&0x0f), 8, &olen, &l);
1098 +       } else if (len < 64) {          /* 32 <= length < 64 */
1099 +           putbits16(obuf, 0x3c0|(len&0x1f), 10, &olen, &l);
1100 +       } else if (len < 128) {         /* 64 <= length < 128 */
1101 +           putbits16(obuf, 0xf80|(len&0x3f), 12, &olen, &l);
1102 +       } else if (len < 256) {         /* 128 <= length < 256 */
1103 +           putbits16(obuf, 0x3f00|(len&0x7f), 14, &olen, &l);
1104 +       } else if (len < 512) {         /* 256 <= length < 512 */
1105 +           putbits16(obuf, 0xfe00|(len&0xff), 16, &olen, &l);
1106 +       } else if (len < 1024) {        /* 512 <= length < 1024 */
1107 +           putbits24(obuf, 0x3fc00|(len&0x1ff), 18, &olen, &l);
1108 +       } else if (len < 2048) {        /* 1024 <= length < 2048 */
1109 +           putbits24(obuf, 0xff800|(len&0x3ff), 20, &olen, &l);
1110 +       } else if (len < 4096) {        /* 2048 <= length < 4096 */
1111 +           putbits24(obuf, 0x3ff000|(len&0x7ff), 22, &olen, &l);
1112 +       } else if (len < 8192) {        /* 4096 <= length < 8192 */
1113 +           putbits24(obuf, 0xffe000|(len&0xfff), 24, &olen, &l);
1114 +       } else {
1115 +           /* This shouldn't happen; we return 0 what means "packet expands",
1116 +           and send packet uncompressed. */
1117 +           if (state->debug)
1118 +               printk(KERN_DEBUG "%s%d: wrong length of match value: %d\n",
1119 +                      __FUNCTION__, state->unit, len);
1120 +           return 0;
1121 +       }
1122 +       continue;
1123 +
1124 +    literal:
1125 +       /* no match found; encode literal byte */
1126 +       if (ibuf[i] < 0x80) {           /* literal byte < 0x80 */
1127 +           putbits8(obuf, (u32) ibuf[i++], 8, &olen, &l);
1128 +       } else {                        /* literal byte >= 0x80 */
1129 +           putbits16(obuf, (u32) (0x100|(ibuf[i++]&0x7f)), 9, &olen, &l);
1130 +       }
1131 +    }
1132 +
1133 +    /* Add remaining octets to the output */
1134 +    while(isize - i > 0) {
1135 +       if (ibuf[i] < 0x80) {   /* literal byte < 0x80 */
1136 +           putbits8(obuf, (u32) ibuf[i++], 8, &olen, &l);
1137 +       } else {                /* literal byte >= 0x80 */
1138 +           putbits16(obuf, (u32) (0x100|(ibuf[i++]&0x7f)), 9, &olen, &l);
1139 +       }
1140 +    }
1141 +    /* Reset unused bits of the last output octet */
1142 +    if ((l != 0) && (l != 8)) {
1143 +       putbits8(obuf, 0, l, &olen, &l);
1144 +    }
1145 +
1146 +    return (int) olen;
1147 +}
1148 +
1149 +int
1150 +mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf,
1151 +             int isize, int osize)
1152 +{
1153 +    struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
1154 +    int proto, olen, complen;
1155 +    unsigned char *wptr;
1156 +
1157 +    /* Check that the protocol is in the range we handle. */
1158 +    proto = PPP_PROTOCOL(ibuf);
1159 +    if (proto < 0x0021 || proto > 0x00fa)
1160 +       return 0;
1161 +
1162 +    wptr = obuf;
1163 +    /* Copy over the PPP header */
1164 +    wptr[0] = PPP_ADDRESS(ibuf);
1165 +    wptr[1] = PPP_CONTROL(ibuf);
1166 +    wptr[2] = PPP_COMP >> 8;
1167 +    wptr[3] = PPP_COMP;
1168 +    wptr += PPP_HDRLEN + MPPE_OVHD; /* Leave two octets for MPPE/MPPC bits */
1169 +
1170 +    mppe_increase_ccount(state);
1171 +
1172 +    if (state->nextflushed) {
1173 +       if (!state->stateless) {
1174 +           state->nextflushed = 0;
1175 +       }
1176 +       state->bits |= MPPE_BIT_FLUSHED;
1177 +       if (state->mppc) { /* reset history */
1178 +           state->bits |= MPPE_BIT_RESET;
1179 +           state->histptr = MPPE_HIST_LEN;
1180 +           memset(state->hist + MPPE_HIST_LEN, 0, MPPE_HIST_LEN*sizeof(u8));
1181 +       }
1182 +    }
1183 +
1184 +    if (state->mppc && !state->mppe) { /* Do only compression */
1185 +       complen = mppc_compress(state, ibuf+2, wptr, isize-2,
1186 +                               osize-PPP_HDRLEN-MPPE_OVHD);
1187 +       if ((complen > isize) || (complen == 0)) {
1188 +           /* packet expands */
1189 +           state->nextflushed = 1;
1190 +           memcpy(wptr, ibuf+2, isize-2);
1191 +           olen = isize + (PPP_HDRLEN / 2) + MPPE_OVHD;
1192 +           (state->stats).inc_bytes += olen;
1193 +           (state->stats).inc_packets++;
1194 +       } else {
1195 +           state->bits |= MPPE_BIT_COMP;
1196 +           olen = complen + PPP_HDRLEN + MPPE_OVHD;
1197 +           (state->stats).comp_bytes += olen;
1198 +           (state->stats).comp_packets++;
1199 +       }
1200 +    } else {
1201 +       if (!state->mppc && state->mppe) { /* Do only encryption */
1202 +           /* read from ibuf, write to wptr, adjust for PPP_HDRLEN */
1203 +           arcfour_encrypt(&state->arcfour_context, ibuf+2, isize-2, wptr);
1204 +           state->bits |= MPPE_BIT_ENCRYPTED;
1205 +           olen = isize + (PPP_HDRLEN / 2) + MPPE_OVHD;
1206 +           (state->stats).inc_bytes += olen;
1207 +           (state->stats).inc_packets++;
1208 +       } else { /* Do compression and then encryption - RFC3078 */
1209 +           complen = mppc_compress(state, ibuf+2, wptr, isize-2,
1210 +                                   osize-PPP_HDRLEN-MPPE_OVHD);
1211 +           if ((complen > isize) || (complen == 0)) {
1212 +               /* packet expands */
1213 +               memcpy(wptr, ibuf+2, isize-2);
1214 +               state->nextflushed = 1;
1215 +               arcfour_encrypt(&state->arcfour_context, ibuf+2, isize-2, wptr);
1216 +               olen = isize + (PPP_HDRLEN / 2) + MPPE_OVHD;
1217 +               (state->stats).inc_bytes += olen;
1218 +               (state->stats).inc_packets++;
1219 +           } else {
1220 +               state->bits |= MPPE_BIT_COMP;
1221 +               /* Hack warning !!! RC4 implementation which we use does
1222 +                  encryption "in place" - it means that input and output
1223 +                  buffers can be *the same* memory area. Therefore we don't
1224 +                  need to use a temporary buffer. But be careful - other
1225 +                  implementations don't have to be so nice.
1226 +                  I used to use ibuf as temporary buffer here, but it led
1227 +                  packet sniffers into error. Thanks to Wilfried Weissmann
1228 +                  for pointing that. */
1229 +               arcfour_encrypt(&state->arcfour_context, wptr, complen, wptr);
1230 +               olen = complen + PPP_HDRLEN + MPPE_OVHD;
1231 +               (state->stats).comp_bytes += olen;
1232 +               (state->stats).comp_packets++;
1233 +           }
1234 +           state->bits |= MPPE_BIT_ENCRYPTED;
1235 +       }
1236 +    }
1237 +
1238 +    /* write status bits and coherency counter into the output buffer */
1239 +    wptr = obuf + PPP_HDRLEN;
1240 +    wptr[0] = MPPE_CTRLHI(state);
1241 +    wptr[1] = MPPE_CTRLLO(state);
1242 +
1243 +    state->bits = 0;
1244 +
1245 +    (state->stats).unc_bytes += isize;
1246 +    (state->stats).unc_packets++;
1247 +
1248 +    return olen;
1249 +}
1250 +
1251 +/***************************/
1252 +/*** Decompression stuff ***/
1253 +/***************************/
1254 +static inline u32 getbits(const u8 *buf, const u32 n, u32 *i, u32 *l)
1255 +{
1256 +    static u32 m[] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
1257 +    u32 res, ol;
1258 +
1259 +    ol = *l;
1260 +    if (*l >= n) {
1261 +       *l = (*l) - n;
1262 +       res = (buf[*i] & m[ol]) >> (*l);
1263 +       if (*l == 0) {
1264 +           *l = 8;
1265 +           (*i)++;
1266 +       }
1267 +    } else {
1268 +       *l = 8 - n + (*l);
1269 +       res = (buf[(*i)++] & m[ol]) << 8;
1270 +       res = (res | buf[*i]) >> (*l);
1271 +    }
1272 +
1273 +    return res;
1274 +}
1275 +
1276 +static inline u32 getbyte(const u8 *buf, const u32 i, const u32 l)
1277 +{
1278 +    if (l == 8) {
1279 +       return buf[i];
1280 +    } else {
1281 +       return (((buf[i] << 8) | buf[i+1]) >> l) & 0xff;
1282 +    }
1283 +}
1284 +
1285 +static inline void lamecopy(u8 *dst, u8 *src, u32 len)
1286 +{
1287 +    while (len--)
1288 +       *dst++ = *src++;
1289 +}
1290 +
1291 +static int
1292 +mppc_decompress(struct ppp_mppe_state *state, unsigned char *ibuf,
1293 +               unsigned char *obuf, int isize, int osize)
1294 +{
1295 +    u32 olen, off, len, bits, val, sig, i, l;
1296 +    u8 *history, *s;
1297 +
1298 +    history = state->hist + state->histptr;
1299 +    olen = len = i = 0;
1300 +    l = 8;
1301 +    bits = isize * 8;
1302 +    while (bits >= 8) {
1303 +       val = getbyte(ibuf, i++, l);
1304 +       if (val < 0x80) {               /* literal byte < 0x80 */
1305 +           if (state->histptr < 2*MPPE_HIST_LEN) {
1306 +               /* copy uncompressed byte to the history */
1307 +               (state->hist)[(state->histptr)++] = (u8) val;
1308 +           } else {
1309 +               /* buffer overflow; drop packet */
1310 +               if (state->debug)
1311 +                   printk(KERN_ERR "%s%d: trying to write outside history "
1312 +                          "buffer\n", __FUNCTION__, state->unit);
1313 +               return DECOMP_ERROR;
1314 +           }
1315 +           olen++;
1316 +           bits -= 8;
1317 +           continue;
1318 +       }
1319 +
1320 +       sig = val & 0xc0;
1321 +       if (sig == 0x80) {              /* literal byte >= 0x80 */
1322 +           if (state->histptr < 2*MPPE_HIST_LEN) {
1323 +               /* copy uncompressed byte to the history */
1324 +               (state->hist)[(state->histptr)++] = 
1325 +                   (u8) (0x80|((val&0x3f)<<1)|getbits(ibuf, 1 , &i ,&l));
1326 +           } else {
1327 +               /* buffer overflow; drop packet */
1328 +               if (state->debug)
1329 +                   printk(KERN_ERR "%s%d: trying to write outside history "
1330 +                          "buffer\n", __FUNCTION__, state->unit);
1331 +               return DECOMP_ERROR;
1332 +           }
1333 +           olen++;
1334 +           bits -= 9;
1335 +           continue;
1336 +       }
1337 +
1338 +       /* Not a literal byte so it must be an (offset,length) pair */
1339 +       /* decode offset */
1340 +       sig = val & 0xf0;
1341 +       if (sig == 0xf0) {              /* 10-bit offset; 0 <= offset < 64 */
1342 +           off = (((val&0x0f)<<2)|getbits(ibuf, 2 , &i ,&l));
1343 +           bits -= 10;
1344 +       } else {
1345 +           if (sig == 0xe0) {          /* 12-bit offset; 64 <= offset < 320 */
1346 +               off = ((((val&0x0f)<<4)|getbits(ibuf, 4 , &i ,&l))+64);
1347 +               bits -= 12;
1348 +           } else {
1349 +               if ((sig&0xe0) == 0xc0) {/* 16-bit offset; 320 <= offset < 8192 */
1350 +                   off = ((((val&0x1f)<<8)|getbyte(ibuf, i++, l))+320);
1351 +                   bits -= 16;
1352 +                   if (off > MPPE_HIST_LEN - 1) {
1353 +                       if (state->debug)
1354 +                           printk(KERN_DEBUG "%s%d: too big offset value: %d\n",
1355 +                                  __FUNCTION__, state->unit, off);
1356 +                       return DECOMP_ERROR;
1357 +                   }
1358 +               } else {                /* this shouldn't happen */
1359 +                   if (state->debug)
1360 +                       printk(KERN_DEBUG "%s%d: cannot decode offset value\n",
1361 +                              __FUNCTION__, state->unit);
1362 +                   return DECOMP_ERROR;
1363 +               }
1364 +           }
1365 +       }
1366 +       /* decode length of match */
1367 +       val = getbyte(ibuf, i, l);
1368 +       if ((val & 0x80) == 0x00) {                     /* len = 3 */
1369 +           len = 3;
1370 +           bits--;
1371 +           getbits(ibuf, 1 , &i ,&l);
1372 +       } else if ((val & 0xc0) == 0x80) {              /* 4 <= len < 8 */
1373 +           len = 0x04 | ((val>>4) & 0x03);
1374 +           bits -= 4;
1375 +           getbits(ibuf, 4 , &i ,&l);
1376 +       } else if ((val & 0xe0) == 0xc0) {              /* 8 <= len < 16 */
1377 +           len = 0x08 | ((val>>2) & 0x07);
1378 +           bits -= 6;
1379 +           getbits(ibuf, 6 , &i ,&l);
1380 +       } else if ((val & 0xf0) == 0xe0) {              /* 16 <= len < 32 */
1381 +           len = 0x10 | (val & 0x0f);
1382 +           bits -= 8;
1383 +           i++;
1384 +       } else {
1385 +           bits -= 8;
1386 +           val = (val << 8) | getbyte(ibuf, ++i, l);
1387 +           if ((val & 0xf800) == 0xf000) {             /* 32 <= len < 64 */
1388 +               len = 0x0020 | ((val >> 6) & 0x001f);
1389 +               bits -= 2;
1390 +               getbits(ibuf, 2 , &i ,&l);
1391 +           } else if ((val & 0xfc00) == 0xf800) {      /* 64 <= len < 128 */
1392 +               len = 0x0040 | ((val >> 4) & 0x003f);
1393 +               bits -= 4;
1394 +               getbits(ibuf, 4 , &i ,&l);
1395 +           } else if ((val & 0xfe00) == 0xfc00) {      /* 128 <= len < 256 */
1396 +               len = 0x0080 | ((val >> 2) & 0x007f);
1397 +               bits -= 6;
1398 +               getbits(ibuf, 6 , &i ,&l);
1399 +           } else if ((val & 0xff00) == 0xfe00) {      /* 256 <= len < 512 */
1400 +               len = 0x0100 | (val & 0x00ff);
1401 +               bits -= 8;
1402 +               i++;
1403 +           } else {
1404 +               bits -= 8;
1405 +               val = (val << 8) | getbyte(ibuf, ++i, l);
1406 +               if ((val & 0xff8000) == 0xff0000) {     /* 512 <= len < 1024 */
1407 +                   len = 0x000200 | ((val >> 6) & 0x0001ff);
1408 +                   bits -= 2;
1409 +                   getbits(ibuf, 2 , &i ,&l);
1410 +               } else if ((val & 0xffc000) == 0xff8000) {/* 1024 <= len < 2048 */
1411 +                   len = 0x000400 | ((val >> 4) & 0x0003ff);
1412 +                   bits -= 4;
1413 +                   getbits(ibuf, 4 , &i ,&l);
1414 +               } else if ((val & 0xffe000) == 0xffc000) {/* 2048 <= len < 4096 */
1415 +                   len = 0x000800 | ((val >> 2) & 0x0007ff);
1416 +                   bits -= 6;
1417 +                   getbits(ibuf, 6 , &i ,&l);
1418 +               } else if ((val & 0xfff000) == 0xffe000) {/* 4096 <= len < 8192 */
1419 +                   len = 0x001000 | (val & 0x000fff);
1420 +                   bits -= 8;
1421 +                   i++;
1422 +               } else {                                /* this shouldn't happen */
1423 +                   if (state->debug)
1424 +                       printk(KERN_DEBUG "%s%d: wrong length code: 0x%X\n",
1425 +                              __FUNCTION__, state->unit, val);
1426 +                   return DECOMP_ERROR;
1427 +               }
1428 +           }
1429 +       }
1430 +       s = state->hist + state->histptr;
1431 +       state->histptr += len;
1432 +       olen += len;
1433 +       if (state->histptr < 2*MPPE_HIST_LEN) {
1434 +           /* copy uncompressed bytes to the history */
1435 +
1436 +           /* In some cases len may be greater than off. It means that memory
1437 +            * areas pointed by s and s-off overlap. I used to use memmove()
1438 +            * here, because I thought that it acts as libc's version. But
1439 +            * I was wrong. I got strange errors sometimes. Wilfried suggested
1440 +            * using of byte by byte copying here and strange errors disappeared.
1441 +            */
1442 +           lamecopy(s, s-off, len);
1443 +       } else {
1444 +           /* buffer overflow; drop packet */
1445 +           if (state->debug)
1446 +               printk(KERN_ERR "%s%d: trying to write outside history "
1447 +                      "buffer\n", __FUNCTION__, state->unit);
1448 +           return DECOMP_ERROR;
1449 +       }
1450 +    }
1451 +
1452 +    if (olen <= osize) {
1453 +       /* copy uncompressed packet to the output buffer */
1454 +       memcpy(obuf, history, olen);
1455 +    } else {
1456 +       /* buffer overflow; drop packet */
1457 +       if (state->debug)
1458 +           printk(KERN_ERR "%s%d: too big uncompressed packet: %d\n",
1459 +                  __FUNCTION__, state->unit, olen+(PPP_HDRLEN/2));
1460 +       return DECOMP_ERROR;
1461 +    }
1462 +
1463 +    return (int) olen;
1464 +}
1465 +
1466 +int
1467 +mppe_decompress(void *arg, unsigned char *ibuf, int isize,
1468 +               unsigned char *obuf, int osize)
1469 +{
1470 +    struct ppp_mppe_state *state = (struct ppp_mppe_state *)arg;
1471 +    int seq, bits, uncomplen;
1472 +
1473 +    if (isize <= PPP_HDRLEN + MPPE_OVHD) {
1474 +       if (state->debug) {
1475 +           printk(KERN_DEBUG "%s%d: short packet (len=%d)\n",  __FUNCTION__,
1476 +                  state->unit, isize);
1477 +       }
1478 +       return DECOMP_ERROR;
1479 +    }
1480 +
1481 +    /* Get coherency counter and control bits from input buffer */
1482 +    seq = MPPE_CCOUNT(ibuf);
1483 +    bits = MPPE_BITS(ibuf);
1484 +
1485 +    if (state->stateless) {
1486 +       /* RFC 3078, sec 8.1. */
1487 +       mppe_increase_ccount(state);
1488 +       if ((seq != state->ccount) && state->debug)
1489 +           printk(KERN_DEBUG "%s%d: bad sequence number: %d, expected: %d\n",
1490 +                  __FUNCTION__, state->unit, seq, state->ccount);
1491 +       while (seq != state->ccount)
1492 +           mppe_increase_ccount(state);
1493 +    } else {
1494 +       /* RFC 3078, sec 8.2. */
1495 +       if (state->flushexpected) { /* discard state */
1496 +           if ((bits & MPPE_BIT_FLUSHED)) { /* we received expected FLUSH bit */
1497 +               while (seq != state->ccount)
1498 +                   mppe_increase_ccount(state);
1499 +               state->flushexpected = 0;
1500 +           } else /* drop packet*/
1501 +               return DECOMP_ERROR;
1502 +       } else { /* normal state */
1503 +           mppe_increase_ccount(state);
1504 +           if (seq != state->ccount) {
1505 +               /* Packet loss detected, enter the discard state. */
1506 +               if (state->debug)
1507 +                   printk(KERN_DEBUG "%s%d: bad sequence number: %d, expected: %d\n",
1508 +                          __FUNCTION__, state->unit, seq, state->ccount);
1509 +               state->flushexpected = 1;
1510 +               return DECOMP_ERROR;
1511 +           }
1512 +       }
1513 +       if (state->mppe && (bits & MPPE_BIT_FLUSHED)) {
1514 +           arcfour_setkey(&state->arcfour_context, state->session_key,
1515 +                          state->keylen);
1516 +       }
1517 +    }
1518 +
1519 +    if (state->mppc && (bits & (MPPE_BIT_FLUSHED | MPPE_BIT_RESET))) {
1520 +       state->histptr = MPPE_HIST_LEN;
1521 +       if ((bits & MPPE_BIT_FLUSHED)) {
1522 +           memset(state->hist + MPPE_HIST_LEN, 0, MPPE_HIST_LEN*sizeof(u8));
1523 +       } else
1524 +           if ((bits & MPPE_BIT_RESET)) {
1525 +               memcpy(state->hist, state->hist+MPPE_HIST_LEN, MPPE_HIST_LEN);
1526 +           }
1527 +    }
1528 +
1529 +    /* Fill in the first part of the PPP header. The protocol field
1530 +       comes from the decompressed data. */
1531 +    obuf[0] = PPP_ADDRESS(ibuf);
1532 +    obuf[1] = PPP_CONTROL(ibuf);
1533 +    obuf += PPP_HDRLEN / 2;
1534 +
1535 +    if (state->mppe) { /* process encrypted packet */
1536 +       if ((bits & MPPE_BIT_ENCRYPTED)) {
1537 +           /* OK, packet encrypted, so decrypt it */
1538 +           if (state->mppc && (bits & MPPE_BIT_COMP)) {
1539 +               /* Hack warning !!! RC4 implementation which we use does
1540 +                  decryption "in place" - it means that input and output
1541 +                  buffers can be *the same* memory area. Therefore we don't
1542 +                  need to use a temporary buffer. But be careful - other
1543 +                  implementations don't have to be so nice. */
1544 +               arcfour_decrypt(&state->arcfour_context, ibuf+PPP_HDRLEN+MPPE_OVHD,
1545 +                               isize-PPP_HDRLEN-MPPE_OVHD, ibuf+PPP_HDRLEN+MPPE_OVHD);
1546 +               uncomplen = mppc_decompress(state, ibuf+PPP_HDRLEN+MPPE_OVHD,
1547 +                                           obuf, isize-PPP_HDRLEN-MPPE_OVHD,
1548 +                                           osize-(PPP_HDRLEN/2));
1549 +               if (uncomplen == DECOMP_ERROR) {
1550 +                   state->flushexpected = 1;
1551 +                   return DECOMP_ERROR;
1552 +               }
1553 +               uncomplen += PPP_HDRLEN / 2;
1554 +               (state->stats).comp_bytes += isize;
1555 +               (state->stats).comp_packets++;
1556 +           } else {
1557 +               arcfour_decrypt(&state->arcfour_context, ibuf+PPP_HDRLEN+MPPE_OVHD,
1558 +                               isize-PPP_HDRLEN-MPPE_OVHD, obuf);
1559 +               uncomplen = isize - (PPP_HDRLEN / 2) - MPPE_OVHD;
1560 +               (state->stats).inc_bytes += isize;
1561 +               (state->stats).inc_packets++;
1562 +           }
1563 +       } else { /* this shouldn't happen */
1564 +           if (state->debug)
1565 +               printk(KERN_ERR "%s%d: encryption negotiated but not an "
1566 +                      "encrypted packet received\n", __FUNCTION__, state->unit);
1567 +           mppe_change_key(state, 0);
1568 +           state->flushexpected = 1;
1569 +           return DECOMP_ERROR;
1570 +       }
1571 +    } else {
1572 +       if (state->mppc) { /* no MPPE, only MPPC */
1573 +           if ((bits & MPPE_BIT_COMP)) {
1574 +               uncomplen = mppc_decompress(state, ibuf+PPP_HDRLEN+MPPE_OVHD,
1575 +                                           obuf, isize-PPP_HDRLEN-MPPE_OVHD,
1576 +                                           osize-(PPP_HDRLEN/2));
1577 +               if (uncomplen == DECOMP_ERROR) {
1578 +                   state->flushexpected = 1;
1579 +                   return DECOMP_ERROR;
1580 +               }
1581 +               uncomplen += PPP_HDRLEN / 2;
1582 +               (state->stats).comp_bytes += isize;
1583 +               (state->stats).comp_packets++;
1584 +           } else {
1585 +               memcpy(obuf, ibuf+PPP_HDRLEN+MPPE_OVHD,
1586 +                      isize-PPP_HDRLEN-MPPE_OVHD);
1587 +               uncomplen = isize - (PPP_HDRLEN / 2) - MPPE_OVHD;
1588 +               (state->stats).inc_bytes += isize;
1589 +               (state->stats).inc_packets++;
1590 +           }
1591 +       } else { /* this shouldn't happen */
1592 +           if (state->debug)
1593 +               printk(KERN_ERR "%s%d: error - no MPPC nor MPPE negotiated\n",
1594 +                      __FUNCTION__, state->unit);
1595 +           state->flushexpected = 1;
1596 +           return DECOMP_ERROR;
1597 +       }
1598 +    }
1599 +
1600 +    (state->stats).unc_bytes += uncomplen;
1601 +    (state->stats).unc_packets++;
1602 +
1603 +    return uncomplen;
1604 +}
1605 +
1606 +
1607 +/************************************************************
1608 + * Module interface table
1609 + ************************************************************/
1610 +
1611 +/* These are in ppp_generic.c */
1612 +extern int  ppp_register_compressor   (struct compressor *cp);
1613 +extern void ppp_unregister_compressor (struct compressor *cp);
1614 +
1615 +/*
1616 + * Functions exported to ppp_generic.c.
1617 + */
1618 +struct compressor ppp_mppe = {
1619 +    CI_MPPE,           /* compress_proto */
1620 +    mppe_comp_alloc,   /* comp_alloc */
1621 +    mppe_comp_free,    /* comp_free */
1622 +    mppe_comp_init,    /* comp_init */
1623 +    mppe_comp_reset,   /* comp_reset */
1624 +    mppe_compress,     /* compress */
1625 +    mppe_stats,                /* comp_stat */
1626 +    mppe_decomp_alloc, /* decomp_alloc */
1627 +    mppe_comp_free,    /* decomp_free */
1628 +    mppe_decomp_init,  /* decomp_init */
1629 +    mppe_decomp_reset, /* decomp_reset */
1630 +    mppe_decompress,   /* decompress */
1631 +    NULL,              /* incomp */
1632 +    mppe_stats,                /* decomp_stat */
1633 +};
1634 +
1635 +/*
1636 +  In case of MPPC/MPPE there is no need to process incompressible data
1637 +  because such a data is sent in MPPC/MPPE frame. Therefore the (*incomp)
1638 +  callback function isn't needed.
1639 +*/
1640 +
1641 +/************************************************************
1642 + * Module support routines
1643 + ************************************************************/
1644 +
1645 +int __init mppe_module_init(void)
1646 +{
1647 +    int answer = ppp_register_compressor(&ppp_mppe);
1648 +    if (answer == 0) {
1649 +       printk(KERN_INFO "MPPE/MPPC encryption/compression module registered\n");
1650 +    }
1651 +    return answer;
1652 +}
1653 +
1654 +void __exit mppe_module_cleanup(void)
1655 +{
1656 +    if (MOD_IN_USE) {
1657 +       printk (KERN_INFO "MPPE/MPPC module busy, removing delayed\n");
1658 +    } else {
1659 +       ppp_unregister_compressor (&ppp_mppe);
1660 +       printk(KERN_INFO "MPPE/MPPC encryption/compression module unregistered\n");
1661 +    }
1662 +}
1663 +
1664 +module_init(mppe_module_init);
1665 +module_exit(mppe_module_cleanup);
1666 +
1667 +MODULE_AUTHOR("Jan Dubiec <jdx@slackware.pl>");
1668 +MODULE_DESCRIPTION("MPPE/MPPC encryption/compression module for Linux");
1669 +MODULE_LICENSE("Dual BSD/GPL");
1670 diff -ruN linux-2.4.21.orig/include/linux/ppp-comp.h linux-2.4.21/include/linux/ppp-comp.h
1671 --- linux-2.4.21.orig/include/linux/ppp-comp.h  1999-08-06 19:44:11.000000000 +0200
1672 +++ linux-2.4.21/include/linux/ppp-comp.h       2003-07-15 01:45:22.000000000 +0200
1673 @@ -1,34 +1,42 @@
1674  /*
1675   * ppp-comp.h - Definitions for doing PPP packet compression.
1676   *
1677 - * Copyright (c) 1994 The Australian National University.
1678 - * All rights reserved.
1679 + * Copyright (c) 1984 Paul Mackerras. All rights reserved.
1680   *
1681 - * Permission to use, copy, modify, and distribute this software and its
1682 - * documentation is hereby granted, provided that the above copyright
1683 - * notice appears in all copies.  This software is provided without any
1684 - * warranty, express or implied. The Australian National University
1685 - * makes no representations about the suitability of this software for
1686 - * any purpose.
1687 - *
1688 - * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
1689 - * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
1690 - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
1691 - * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
1692 - * OF SUCH DAMAGE.
1693 - *
1694 - * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
1695 - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
1696 - * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
1697 - * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
1698 - * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
1699 - * OR MODIFICATIONS.
1700 + * Redistribution and use in source and binary forms, with or without
1701 + * modification, are permitted provided that the following conditions
1702 + * are met:
1703   *
1704 - * $Id: ppp-comp.h,v 1.6 1997/11/27 06:04:44 paulus Exp $
1705 + * 1. Redistributions of source code must retain the above copyright
1706 + *    notice, this list of conditions and the following disclaimer.
1707 + *
1708 + * 2. Redistributions in binary form must reproduce the above copyright
1709 + *    notice, this list of conditions and the following disclaimer in
1710 + *    the documentation and/or other materials provided with the
1711 + *    distribution.
1712 + *
1713 + * 3. The name(s) of the authors of this software must not be used to
1714 + *    endorse or promote products derived from this software without
1715 + *    prior written permission.
1716 + *
1717 + * 4. Redistributions of any form whatsoever must retain the following
1718 + *    acknowledgment:
1719 + *    "This product includes software developed by Paul Mackerras
1720 + *     <paulus@samba.org>".
1721 + *
1722 + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
1723 + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1724 + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
1725 + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1726 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
1727 + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
1728 + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1729 + *
1730 + * $Id: ppp-comp.h,v 1.10 2002/12/06 09:49:15 paulus Exp $
1731   */
1732  
1733  /*
1734 - *  ==FILEVERSION 980319==
1735 + *  ==FILEVERSION 20020715==
1736   *
1737   *  NOTE TO MAINTAINERS:
1738   *     If you modify this file at all, please set the above date.
1739 @@ -78,7 +86,7 @@
1740  
1741         /* Compress a packet */
1742         int     (*compress) (void *state, unsigned char *rptr,
1743 -                             unsigned char *obuf, int isize, int osize);
1744 +                            unsigned char *obuf, int isize, int osize);
1745  
1746         /* Return compression statistics */
1747         void    (*comp_stat) (void *state, struct compstat *stats);
1748 @@ -99,7 +107,7 @@
1749  
1750         /* Decompress a packet. */
1751         int     (*decompress) (void *state, unsigned char *ibuf, int isize,
1752 -                               unsigned char *obuf, int osize);
1753 +                              unsigned char *obuf, int osize);
1754  
1755         /* Update state for an incompressible packet received */
1756         void    (*incomp) (void *state, unsigned char *ibuf, int icnt);
1757 @@ -187,6 +195,127 @@
1758  #define DEFLATE_CHK_SEQUENCE   0
1759  
1760  /*
1761 + * Definitions for MPPE.
1762 + */
1763 +
1764 +#define CI_MPPE                        18      /* config option for MPPE */
1765 +#define CILEN_MPPE             6       /* length of config option */
1766 +
1767 +#define MPPE_PAD               4       /* MPPE growth per frame */
1768 +#define MPPE_MAX_KEY_LEN       16      /* largest key length (128-bit) */
1769 +
1770 +/* option bits for ccp_options.mppe */
1771 +#define MPPE_OPT_40            0x01    /* 40 bit */
1772 +#define MPPE_OPT_128           0x02    /* 128 bit */
1773 +#define MPPE_OPT_STATEFUL      0x04    /* stateful mode */
1774 +/* unsupported opts */
1775 +#define MPPE_OPT_56            0x08    /* 56 bit */
1776 +#define MPPE_OPT_MPPC          0x10    /* MPPC compression */
1777 +#define MPPE_OPT_D             0x20    /* Unknown */
1778 +#define MPPE_OPT_UNSUPPORTED (MPPE_OPT_56|MPPE_OPT_MPPC|MPPE_OPT_D)
1779 +#define MPPE_OPT_UNKNOWN       0x40    /* Bits !defined in RFC 3078 were set */
1780 +
1781 +/*
1782 + * This is not nice ... the alternative is a bitfield struct though.
1783 + * And unfortunately, we cannot share the same bits for the option
1784 + * names above since C and H are the same bit.  We could do a u_int32
1785 + * but then we have to do a htonl() all the time and/or we still need
1786 + * to know which octet is which.
1787 + */
1788 +#define MPPE_C_BIT             0x01    /* MPPC */
1789 +#define MPPE_D_BIT             0x10    /* Obsolete, usage unknown */
1790 +#define MPPE_L_BIT             0x20    /* 40-bit */
1791 +#define MPPE_S_BIT             0x40    /* 128-bit */
1792 +#define MPPE_M_BIT             0x80    /* 56-bit, not supported */
1793 +#define MPPE_H_BIT             0x01    /* Stateless (in a different byte) */
1794 +
1795 +/* Does not include H bit; used for least significant octet only. */
1796 +#define MPPE_ALL_BITS (MPPE_D_BIT|MPPE_L_BIT|MPPE_S_BIT|MPPE_M_BIT|MPPE_H_BIT)
1797 +
1798 +/* Build a CI from mppe opts (see RFC 3078) */
1799 +#define MPPE_OPTS_TO_CI(opts, ci)              \
1800 +    do {                                       \
1801 +       u_char *ptr = ci; /* u_char[4] */       \
1802 +                                               \
1803 +       /* H bit */                             \
1804 +       if (opts & MPPE_OPT_STATEFUL)           \
1805 +           *ptr++ = 0x0;                       \
1806 +       else                                    \
1807 +           *ptr++ = MPPE_H_BIT;                \
1808 +       *ptr++ = 0;                             \
1809 +       *ptr++ = 0;                             \
1810 +                                               \
1811 +       /* S,L bits */                          \
1812 +       *ptr = 0;                               \
1813 +       if (opts & MPPE_OPT_128)                \
1814 +           *ptr |= MPPE_S_BIT;                 \
1815 +       if (opts & MPPE_OPT_40)                 \
1816 +           *ptr |= MPPE_L_BIT;                 \
1817 +       /* M,D,C bits not supported */          \
1818 +    } while (/* CONSTCOND */ 0)
1819 +
1820 +/* The reverse of the above */
1821 +#define MPPE_CI_TO_OPTS(ci, opts)              \
1822 +    do {                                       \
1823 +       u_char *ptr = ci; /* u_char[4] */       \
1824 +                                               \
1825 +       opts = 0;                               \
1826 +                                               \
1827 +       /* H bit */                             \
1828 +       if (!(ptr[0] & MPPE_H_BIT))             \
1829 +           opts |= MPPE_OPT_STATEFUL;          \
1830 +                                               \
1831 +       /* S,L bits */                          \
1832 +       if (ptr[3] & MPPE_S_BIT)                \
1833 +           opts |= MPPE_OPT_128;               \
1834 +       if (ptr[3] & MPPE_L_BIT)                \
1835 +           opts |= MPPE_OPT_40;                \
1836 +                                               \
1837 +       /* M,D,C bits */                        \
1838 +       if (ptr[3] & MPPE_M_BIT)                \
1839 +           opts |= MPPE_OPT_56;                \
1840 +       if (ptr[3] & MPPE_D_BIT)                \
1841 +           opts |= MPPE_OPT_D;                 \
1842 +       if (ptr[3] & MPPE_C_BIT)                \
1843 +           opts |= MPPE_OPT_MPPC;              \
1844 +                                               \
1845 +       /* Other bits */                        \
1846 +       if (ptr[0] & ~MPPE_H_BIT)               \
1847 +           opts |= MPPE_OPT_UNKNOWN;           \
1848 +       if (ptr[1] || ptr[2])                   \
1849 +           opts |= MPPE_OPT_UNKNOWN;           \
1850 +       if (ptr[3] & ~MPPE_ALL_BITS)            \
1851 +           opts |= MPPE_OPT_UNKNOWN;           \
1852 +    } while (/* CONSTCOND */ 0)
1853 +
1854 +/* MPPE/MPPC definitions by J.D.*/
1855 +#define MPPE_STATELESS          MPPE_H_BIT     /* configuration bit H */
1856 +#define MPPE_40BIT              MPPE_L_BIT     /* configuration bit L */
1857 +#define MPPE_56BIT              MPPE_M_BIT     /* configuration bit M */
1858 +#define MPPE_128BIT             MPPE_S_BIT     /* configuration bit S */
1859 +#define MPPE_MPPC               MPPE_C_BIT     /* configuration bit C */
1860 +
1861 +/*
1862 + * Definitions for Stac LZS.
1863 + */
1864 +
1865 +#define CI_LZS                 17      /* config option for Stac LZS */
1866 +#define CILEN_LZS              5       /* length of config option */
1867 +
1868 +#define LZS_OVHD               4       /* max. LZS overhead */
1869 +#define LZS_HIST_LEN           2048    /* LZS history size */
1870 +#define LZS_MAX_CCOUNT         0x0FFF  /* max. coherency counter value */
1871 +
1872 +#define LZS_MODE_NONE          0
1873 +#define LZS_MODE_LCB           1
1874 +#define LZS_MODE_CRC           2
1875 +#define LZS_MODE_SEQ           3
1876 +#define LZS_MODE_EXT           4
1877 +
1878 +#define LZS_EXT_BIT_FLUSHED    0x80    /* bit A */
1879 +#define LZS_EXT_BIT_COMP       0x20    /* bit C */
1880 +
1881 +/*
1882   * Definitions for other, as yet unsupported, compression methods.
1883   */
1884