/* * lifted from /sys/src/cmd/ip/ppp/mppc.c (RFC 2118) * plus the RDP 5.0 64K history (3.1.8.4.2 RDP 5.0) */#include <u.h>#include <libc.h>#include "dat.h"#include "fns.h" #define DBG if(0)//#define DBG enum{ MaxHistorySize= 64*1024, Preset= 0x80, /* reset history */ Pfront= 0x40, /* move packet to front of history */ Pcompress= 0x20, /* packet is compressed */ Pbulk64= 0x01, /* RPD5 bulk compression (64K history) */}; enum{ Bits4= 0xf, Bits5= 0x1f, Bits6= 0x3f, Bits7= 0x7f, Bits8= 0xff, Bits11= 0x7ff, Bits13= 0x1fff, Bits16= 0xffff,}; enum{ Lit7, /* seven bit literal */ Lit8, /* eight bit literal */ Off6, /* six bit offset */ Off8, /* eight bit offset */ Off11, /* eleven bit offset (64K history) */ Off13, /* thirteen bit offset (8K history) */ Off16, /* sixteen bit offset (64K history) */}; /* decode first four bits (8K history) */static int decode8[16]={ Lit7, Lit7, Lit7, Lit7, Lit7, Lit7, Lit7, Lit7, Lit8, Lit8, Lit8, Lit8, Off13, Off13, Off8, Off6,}; /* decode first five bits (64K history) */static int decode64[32]={ Lit7, Lit7, Lit7, Lit7, Lit7, Lit7, Lit7, Lit7, Lit7, Lit7, Lit7, Lit7, Lit7, Lit7, Lit7, Lit7, Lit8, Lit8, Lit8, Lit8, Lit8, Lit8, Lit8, Lit8, Off16, Off16, Off16, Off16, Off11, Off11, Off8, Off6,}; typedef struct Uncstate Uncstate;struct Uncstate{ uchar his[MaxHistorySize]; int indx; /* current indx in history */ int size; /* current history size */}; static Uncstate uncstate; #define NEXTBYTE sreg = (sreg<<8) | *p++; n--; bits += 8uchar*uncomp(uchar* buf, int nbytes, int flags, int* psize){ int n, bits, off, len, ones, t; int *decode, lookbits, lookmask, maxhis, maxones; ulong sreg; uchar *p, c, *hp, *hs, *he, *hq; Uncstate *s; s = &uncstate; p = buf; n = nbytes; if(flags&Pbulk64){ maxhis = 64*1024; maxones = 14; decode = decode64; lookbits = 5; lookmask = Bits5; }else{ maxhis = 8*1024; maxones = 11; decode = decode8; lookbits = 4; lookmask = Bits4; } if(flags&Preset){ s->indx = 0; s->size = 0; memset(s->his, maxhis, 0); } if(flags&Pfront){ s->indx = 0;DBG fprint(2, "mppc: front flag set\n"); } if(!(flags&Pcompress)){ *psize = n; return buf; } bits = 0; sreg = 0; hs = s->his; /* history start */ hp = hs+s->indx; /* write pointer in history */ he = hs+maxhis; /* history end */ for(;;){ if(bits<lookbits){ if(n==0) goto Done; NEXTBYTE; } t = decode[(sreg>>(bits-lookbits))&lookmask]; switch(t){ default: sysfatal("mppc: bad decode %d!", t); case Lit7: bits -= 1; if(bits<7){ if(n==0) goto Done; NEXTBYTE; } c = (sreg>>(bits-7))&Bits7; bits -= 7; if(hp >= he) goto His; *hp++ = c; continue; case Lit8: bits -= 2; if(bits<7) { if(n==0) goto Eof; NEXTBYTE; } c = 0x80 | ((sreg>>(bits-7))&Bits7); bits -= 7; if(hp >= he) goto His; *hp++ = c; continue; case Off6: bits -= lookbits; if(bits<6){ if(n==0) goto Eof; NEXTBYTE; } off = (sreg>>(bits-6))&Bits6; bits -= 6; break; case Off8: bits -= lookbits; if(bits<8){ if(n==0) goto Eof; NEXTBYTE; } off = ((sreg>>(bits-8))&Bits8)+64; bits -= 8; break; case Off13: /* (8K history) */ bits -= 3; while(bits<13){ if(n==0) goto Eof; NEXTBYTE; } off = ((sreg>>(bits-13))&Bits13)+320; bits -= 13; break; case Off11: /* (64K history) */ bits -= 4; while(bits<11){ if(n==0) goto Eof; NEXTBYTE; } off = ((sreg>>(bits-11))&Bits11)+320; bits -= 11; break; case Off16: /* (64K history) */ bits -= 3; while(bits<16){ if(n==0) goto Eof; NEXTBYTE; } off = ((sreg>>(bits-16))&Bits16)+2368; bits -= 16; break; } for(ones=0;;ones++) { if(bits == 0) { if(n==0) goto Eof; NEXTBYTE; } bits--; if(!(sreg&(1<<bits))) break; } if(ones>maxones){ werrstr("bad length %d\n", ones); return nil; } if(ones == 0) { len = 3; } else { ones++; while(bits<ones) { if(n==0) goto Eof; NEXTBYTE; } len = (1<<ones) | ((sreg>>(bits-ones))&((1<<ones)-1)); bits -= ones; } hq = hp-off; if(hq < hs) { hq += maxhis; if(hq-hs+len > s->size){// goto His;fprint(2, "mppc: reference past valid history\n"); } } if(hp+len > he) goto His; while(len) { *hp++ = *hq++; len--; } } Done: hq = hs+s->indx; len = hp-hq;DBG fprint(2, "mppc: len %d bits = %d n=%d\n", len, bits, n); s->indx += len; if(s->indx > s->size) s->size = s->indx; *psize = len; return hq; Eof: werrstr("unexpected end of data"); return nil;His: werrstr("bad history reference"); return nil;}
/*
* lifted from /sys/src/cmd/ip/ppp/mppc.c (RFC 2118)
* plus the RDP 5.0 64K history (3.1.8.4.2 RDP 5.0)
*/
#include <u.h>
#include <libc.h>
#include "dat.h"
#include "fns.h"
#define DBG if(0)
//#define DBG
enum
{
MaxHistorySize= 64*1024,
Preset= 0x80, /* reset history */
Pfront= 0x40, /* move packet to front of history */
Pcompress= 0x20, /* packet is compressed */
Pbulk64= 0x01, /* RPD5 bulk compression (64K history) */
};
enum
{
Bits4= 0xf,
Bits5= 0x1f,
Bits6= 0x3f,
Bits7= 0x7f,
Bits8= 0xff,
Bits11= 0x7ff,
Bits13= 0x1fff,
Bits16= 0xffff,
};
enum
{
Lit7, /* seven bit literal */
Lit8, /* eight bit literal */
Off6, /* six bit offset */
Off8, /* eight bit offset */
Off11, /* eleven bit offset (64K history) */
Off13, /* thirteen bit offset (8K history) */
Off16, /* sixteen bit offset (64K history) */
};
/* decode first four bits (8K history) */
static int decode8[16]=
{
Lit7, Lit7, Lit7, Lit7,
Lit7, Lit7, Lit7, Lit7,
Lit8, Lit8, Lit8, Lit8,
Off13, Off13, Off8, Off6,
};
/* decode first five bits (64K history) */
static int decode64[32]=
{
Lit7, Lit7, Lit7, Lit7,
Lit7, Lit7, Lit7, Lit7,
Lit7, Lit7, Lit7, Lit7,
Lit7, Lit7, Lit7, Lit7,
Lit8, Lit8, Lit8, Lit8,
Lit8, Lit8, Lit8, Lit8,
Off16, Off16, Off16, Off16,
Off11, Off11, Off8, Off6,
};
typedef struct Uncstate Uncstate;
struct Uncstate
{
uchar his[MaxHistorySize];
int indx; /* current indx in history */
int size; /* current history size */
};
static Uncstate uncstate;
#define NEXTBYTE sreg = (sreg<<8) | *p++; n--; bits += 8
uchar*
uncomp(uchar* buf, int nbytes, int flags, int* psize)
{
int n, bits, off, len, ones, t;
int *decode, lookbits, lookmask, maxhis, maxones;
ulong sreg;
uchar *p, c, *hp, *hs, *he, *hq;
Uncstate *s;
s = &uncstate;
p = buf;
n = nbytes;
if(flags&Pbulk64){
maxhis = 64*1024;
maxones = 14;
decode = decode64;
lookbits = 5;
lookmask = Bits5;
}else{
maxhis = 8*1024;
maxones = 11;
decode = decode8;
lookbits = 4;
lookmask = Bits4;
}
if(flags&Preset){
s->indx = 0;
s->size = 0;
memset(s->his, maxhis, 0);
}
if(flags&Pfront){
s->indx = 0;
DBG fprint(2, "mppc: front flag set\n");
}
if(!(flags&Pcompress)){
*psize = n;
return buf;
}
bits = 0;
sreg = 0;
hs = s->his; /* history start */
hp = hs+s->indx; /* write pointer in history */
he = hs+maxhis; /* history end */
for(;;){
if(bits<lookbits){
if(n==0) goto Done;
NEXTBYTE;
}
t = decode[(sreg>>(bits-lookbits))&lookmask];
switch(t){
default:
sysfatal("mppc: bad decode %d!", t);
case Lit7:
bits -= 1;
if(bits<7){
if(n==0) goto Done;
NEXTBYTE;
}
c = (sreg>>(bits-7))&Bits7;
bits -= 7;
if(hp >= he) goto His;
*hp++ = c;
continue;
case Lit8:
bits -= 2;
if(bits<7) {
if(n==0) goto Eof;
NEXTBYTE;
}
c = 0x80 | ((sreg>>(bits-7))&Bits7);
bits -= 7;
if(hp >= he) goto His;
*hp++ = c;
continue;
case Off6:
bits -= lookbits;
if(bits<6){
if(n==0) goto Eof;
NEXTBYTE;
}
off = (sreg>>(bits-6))&Bits6;
bits -= 6;
break;
case Off8:
bits -= lookbits;
if(bits<8){
if(n==0) goto Eof;
NEXTBYTE;
}
off = ((sreg>>(bits-8))&Bits8)+64;
bits -= 8;
break;
case Off13: /* (8K history) */
bits -= 3;
while(bits<13){
if(n==0) goto Eof;
NEXTBYTE;
}
off = ((sreg>>(bits-13))&Bits13)+320;
bits -= 13;
break;
case Off11: /* (64K history) */
bits -= 4;
while(bits<11){
if(n==0) goto Eof;
NEXTBYTE;
}
off = ((sreg>>(bits-11))&Bits11)+320;
bits -= 11;
break;
case Off16: /* (64K history) */
bits -= 3;
while(bits<16){
if(n==0) goto Eof;
NEXTBYTE;
}
off = ((sreg>>(bits-16))&Bits16)+2368;
bits -= 16;
break;
}
for(ones=0;;ones++) {
if(bits == 0) {
if(n==0) goto Eof;
NEXTBYTE;
}
bits--;
if(!(sreg&(1<<bits)))
break;
}
if(ones>maxones){
werrstr("bad length %d\n", ones);
return nil;
}
if(ones == 0) {
len = 3;
} else {
ones++;
while(bits<ones) {
if(n==0) goto Eof;
NEXTBYTE;
}
len = (1<<ones) | ((sreg>>(bits-ones))&((1<<ones)-1));
bits -= ones;
}
hq = hp-off;
if(hq < hs) {
hq += maxhis;
if(hq-hs+len > s->size){
// goto His;
fprint(2, "mppc: reference past valid history\n");
}
}
if(hp+len > he)
goto His;
while(len) {
*hp++ = *hq++;
len--;
}
}
Done:
hq = hs+s->indx;
len = hp-hq;
DBG fprint(2, "mppc: len %d bits = %d n=%d\n", len, bits, n);
s->indx += len;
if(s->indx > s->size)
s->size = s->indx;
*psize = len;
return hq;
Eof:
werrstr("unexpected end of data");
return nil;
His:
werrstr("bad history reference");
return nil;
}