17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <libsec.h>
47dd7cddfSDavid du Colombier #include <ip.h>
5*9a747e4fSDavid du Colombier #include <auth.h>
67dd7cddfSDavid du Colombier #include "ppp.h"
77dd7cddfSDavid du Colombier
87dd7cddfSDavid du Colombier enum {
97dd7cddfSDavid du Colombier HistorySize= 8*1024,
107dd7cddfSDavid du Colombier Cminmatch = 3, /* sintest match possible */
117dd7cddfSDavid du Colombier Chshift = 4, /* nice compromise between space & time */
127dd7cddfSDavid du Colombier Cnhash = 1<<(Chshift*Cminmatch),
137dd7cddfSDavid du Colombier HMASK = Cnhash-1,
147dd7cddfSDavid du Colombier };
157dd7cddfSDavid du Colombier
167dd7cddfSDavid du Colombier typedef struct Carena Carena;
177dd7cddfSDavid du Colombier struct Carena
187dd7cddfSDavid du Colombier {
197dd7cddfSDavid du Colombier uchar *pos; /* current place, also amount of history filled */
207dd7cddfSDavid du Colombier uchar buf[HistorySize];
217dd7cddfSDavid du Colombier };
227dd7cddfSDavid du Colombier
237dd7cddfSDavid du Colombier typedef struct Cstate Cstate;
247dd7cddfSDavid du Colombier struct Cstate
257dd7cddfSDavid du Colombier {
267dd7cddfSDavid du Colombier QLock;
277dd7cddfSDavid du Colombier int count;
287dd7cddfSDavid du Colombier int reset; /* compressor has been reset */
297dd7cddfSDavid du Colombier int front; /* move to begining of history */
307dd7cddfSDavid du Colombier ulong sreg; /* output shift reg */
317dd7cddfSDavid du Colombier int bits; /* number of bits in sreg */
327dd7cddfSDavid du Colombier Block *b; /* output block */
337dd7cddfSDavid du Colombier
347dd7cddfSDavid du Colombier /*
357dd7cddfSDavid du Colombier * state for hashing compressor
367dd7cddfSDavid du Colombier */
377dd7cddfSDavid du Colombier Carena arenas[2];
387dd7cddfSDavid du Colombier Carena *hist;
397dd7cddfSDavid du Colombier Carena *ohist;
407dd7cddfSDavid du Colombier ulong hash[Cnhash];
417dd7cddfSDavid du Colombier int h;
427dd7cddfSDavid du Colombier ulong me;
437dd7cddfSDavid du Colombier ulong split;
447dd7cddfSDavid du Colombier
457dd7cddfSDavid du Colombier int encrypt;
467dd7cddfSDavid du Colombier uchar startkey[16];
477dd7cddfSDavid du Colombier uchar key[16];
487dd7cddfSDavid du Colombier RC4state rc4key;
497dd7cddfSDavid du Colombier };
507dd7cddfSDavid du Colombier
517dd7cddfSDavid du Colombier typedef struct Uncstate Uncstate;
527dd7cddfSDavid du Colombier struct Uncstate
537dd7cddfSDavid du Colombier {
547dd7cddfSDavid du Colombier int count; /* packet count - detects missing packets */
557dd7cddfSDavid du Colombier int resetid; /* id of reset requests */
567dd7cddfSDavid du Colombier uchar his[HistorySize];
577dd7cddfSDavid du Colombier int indx; /* current indx in history */
587dd7cddfSDavid du Colombier int size; /* current history size */
597dd7cddfSDavid du Colombier uchar startkey[16];
607dd7cddfSDavid du Colombier uchar key[16];
617dd7cddfSDavid du Colombier RC4state rc4key;
627dd7cddfSDavid du Colombier };
637dd7cddfSDavid du Colombier
647dd7cddfSDavid du Colombier /* packet flags */
657dd7cddfSDavid du Colombier enum {
667dd7cddfSDavid du Colombier Preset= (1<<15), /* reset history */
677dd7cddfSDavid du Colombier Pfront= (1<<14), /* move packet to front of history */
687dd7cddfSDavid du Colombier Pcompress= (1<<13), /* packet is compressed */
697dd7cddfSDavid du Colombier Pencrypt= (1<<12), /* packet is encrypted */
707dd7cddfSDavid du Colombier };
717dd7cddfSDavid du Colombier
727dd7cddfSDavid du Colombier enum {
737dd7cddfSDavid du Colombier Lit7, /* seven bit literal */
747dd7cddfSDavid du Colombier Lit8, /* eight bit literal */
757dd7cddfSDavid du Colombier Off6, /* six bit offset */
767dd7cddfSDavid du Colombier Off8, /* eight bit offset */
777dd7cddfSDavid du Colombier Off13, /* thirteen bit offset */
787dd7cddfSDavid du Colombier };
797dd7cddfSDavid du Colombier
807dd7cddfSDavid du Colombier /* decode first four bits */
817dd7cddfSDavid du Colombier int decode[16] = {
827dd7cddfSDavid du Colombier Lit7,
837dd7cddfSDavid du Colombier Lit7,
847dd7cddfSDavid du Colombier Lit7,
857dd7cddfSDavid du Colombier Lit7,
867dd7cddfSDavid du Colombier Lit7,
877dd7cddfSDavid du Colombier Lit7,
887dd7cddfSDavid du Colombier Lit7,
897dd7cddfSDavid du Colombier Lit7,
907dd7cddfSDavid du Colombier Lit8,
917dd7cddfSDavid du Colombier Lit8,
927dd7cddfSDavid du Colombier Lit8,
937dd7cddfSDavid du Colombier Lit8,
947dd7cddfSDavid du Colombier Off13,
957dd7cddfSDavid du Colombier Off13,
967dd7cddfSDavid du Colombier Off8,
977dd7cddfSDavid du Colombier Off6,
987dd7cddfSDavid du Colombier };
997dd7cddfSDavid du Colombier
1007dd7cddfSDavid du Colombier
1017dd7cddfSDavid du Colombier static void *compinit(PPP*);
1027dd7cddfSDavid du Colombier static Block* comp(PPP*, ushort, Block*, int*);
1037dd7cddfSDavid du Colombier static void comp2(Cstate*, uchar*, int);
1047dd7cddfSDavid du Colombier static Block *compresetreq(void*, Block*);
1057dd7cddfSDavid du Colombier static void compfini(void*);
1067dd7cddfSDavid du Colombier static void complit(Cstate*, int);
1077dd7cddfSDavid du Colombier static void compcopy(Cstate*, int, int);
1087dd7cddfSDavid du Colombier static void compout(Cstate*, ulong, int);
1097dd7cddfSDavid du Colombier static void compfront(Cstate*);
1107dd7cddfSDavid du Colombier static void hashcheck(Cstate*);
1117dd7cddfSDavid du Colombier static void compreset(Cstate*);
1127dd7cddfSDavid du Colombier static int hashit(uchar*);
1137dd7cddfSDavid du Colombier
1147dd7cddfSDavid du Colombier
1157dd7cddfSDavid du Colombier static void *uncinit(PPP*);
1167dd7cddfSDavid du Colombier static Block* uncomp(PPP*, Block*, int *protop, Block**);
1177dd7cddfSDavid du Colombier static Block *uncomp2(Uncstate *s, Block*, ushort);
1187dd7cddfSDavid du Colombier static void uncfini(void*);
1197dd7cddfSDavid du Colombier static void uncresetack(void*, Block*);
1207dd7cddfSDavid du Colombier static int ipcheck(uchar*, int);
1217dd7cddfSDavid du Colombier static void hischeck(Uncstate*);
1227dd7cddfSDavid du Colombier
1237dd7cddfSDavid du Colombier static void setkey(uchar *key, uchar *startkey);
1247dd7cddfSDavid du Colombier
1257dd7cddfSDavid du Colombier Comptype cmppc = {
1267dd7cddfSDavid du Colombier compinit,
1277dd7cddfSDavid du Colombier comp,
1287dd7cddfSDavid du Colombier compresetreq,
1297dd7cddfSDavid du Colombier compfini
1307dd7cddfSDavid du Colombier };
1317dd7cddfSDavid du Colombier
1327dd7cddfSDavid du Colombier Uncomptype uncmppc = {
1337dd7cddfSDavid du Colombier uncinit,
1347dd7cddfSDavid du Colombier uncomp,
1357dd7cddfSDavid du Colombier uncresetack,
1367dd7cddfSDavid du Colombier uncfini
1377dd7cddfSDavid du Colombier };
1387dd7cddfSDavid du Colombier
1397dd7cddfSDavid du Colombier static void *
compinit(PPP * ppp)1407dd7cddfSDavid du Colombier compinit(PPP *ppp)
1417dd7cddfSDavid du Colombier {
1427dd7cddfSDavid du Colombier Cstate *cs;
1437dd7cddfSDavid du Colombier
1447dd7cddfSDavid du Colombier cs = mallocz(sizeof(Cstate), 1);
1457dd7cddfSDavid du Colombier cs->hist = &cs->arenas[0];
1467dd7cddfSDavid du Colombier cs->ohist = &cs->arenas[1];
1477dd7cddfSDavid du Colombier compreset(cs);
1487dd7cddfSDavid du Colombier /*
1497dd7cddfSDavid du Colombier * make reset clear the hash table
1507dd7cddfSDavid du Colombier */
1517dd7cddfSDavid du Colombier cs->me = ~0;
1527dd7cddfSDavid du Colombier compreset(cs);
1537dd7cddfSDavid du Colombier
1547dd7cddfSDavid du Colombier cs->reset = 0;
1557dd7cddfSDavid du Colombier
1567dd7cddfSDavid du Colombier if(ppp->sendencrypted) {
1577dd7cddfSDavid du Colombier cs->encrypt = 1;
1587dd7cddfSDavid du Colombier memmove(cs->startkey, ppp->key, 16);
1597dd7cddfSDavid du Colombier memmove(cs->key, ppp->key, 16);
1607dd7cddfSDavid du Colombier setkey(cs->key, cs->startkey);
1617dd7cddfSDavid du Colombier setupRC4state(&cs->rc4key, cs->key, 16);
1627dd7cddfSDavid du Colombier }
1637dd7cddfSDavid du Colombier
1647dd7cddfSDavid du Colombier return cs;
1657dd7cddfSDavid du Colombier }
1667dd7cddfSDavid du Colombier
1677dd7cddfSDavid du Colombier static void
compfini(void * as)1687dd7cddfSDavid du Colombier compfini(void *as)
1697dd7cddfSDavid du Colombier {
1707dd7cddfSDavid du Colombier Cstate *cs;
1717dd7cddfSDavid du Colombier
1727dd7cddfSDavid du Colombier cs = as;
1737dd7cddfSDavid du Colombier free(cs);
1747dd7cddfSDavid du Colombier }
1757dd7cddfSDavid du Colombier
1767dd7cddfSDavid du Colombier
1777dd7cddfSDavid du Colombier static Block*
comp(PPP * ppp,ushort proto,Block * b,int * protop)1787dd7cddfSDavid du Colombier comp(PPP *ppp, ushort proto, Block *b, int *protop)
1797dd7cddfSDavid du Colombier {
1807dd7cddfSDavid du Colombier Cstate *s;
1817dd7cddfSDavid du Colombier int n, n2;
1827dd7cddfSDavid du Colombier ushort count;
1837dd7cddfSDavid du Colombier
1847dd7cddfSDavid du Colombier s = ppp->cstate;
1857dd7cddfSDavid du Colombier *protop = 0;
1867dd7cddfSDavid du Colombier
1877dd7cddfSDavid du Colombier qlock(s);
1887dd7cddfSDavid du Colombier
1897dd7cddfSDavid du Colombier /* put protocol into b */
1907dd7cddfSDavid du Colombier b->rptr -= 2;
1917dd7cddfSDavid du Colombier if(b->rptr < b->base)
1927dd7cddfSDavid du Colombier sysfatal("mppc: not enough header in block");
1937dd7cddfSDavid du Colombier b->rptr[0] = proto>>8;
1947dd7cddfSDavid du Colombier b->rptr[1] = proto;
1957dd7cddfSDavid du Colombier
1967dd7cddfSDavid du Colombier n = BLEN(b);
1977dd7cddfSDavid du Colombier s->bits = 0;
1987dd7cddfSDavid du Colombier s->b = allocb(n*9/8+20);
1997dd7cddfSDavid du Colombier s->b->wptr += 2; /* leave room for mppc header */
2007dd7cddfSDavid du Colombier
2017dd7cddfSDavid du Colombier comp2(s, b->rptr, n);
2027dd7cddfSDavid du Colombier
2037dd7cddfSDavid du Colombier /* flush sreg */
2047dd7cddfSDavid du Colombier if(s->bits)
2057dd7cddfSDavid du Colombier *s->b->wptr++ = s->sreg<<(8-s->bits);
2067dd7cddfSDavid du Colombier if(s->b->wptr > s->b->lim)
2077dd7cddfSDavid du Colombier sysfatal("mppc: comp: output block overflowed");
2087dd7cddfSDavid du Colombier
2097dd7cddfSDavid du Colombier n2 = BLEN(s->b);
2107dd7cddfSDavid du Colombier
2117dd7cddfSDavid du Colombier if(n2 > n-2 && !s->encrypt) {
2127dd7cddfSDavid du Colombier /* expened and not excrypting so send as a regular packet */
2137dd7cddfSDavid du Colombier //netlog("mppc: comp: expanded\n");
2147dd7cddfSDavid du Colombier compreset(s);
2157dd7cddfSDavid du Colombier freeb(s->b);
2167dd7cddfSDavid du Colombier b->rptr += 2;
2177dd7cddfSDavid du Colombier qunlock(s);
2187dd7cddfSDavid du Colombier *protop = proto;
2197dd7cddfSDavid du Colombier return b;
2207dd7cddfSDavid du Colombier }
2217dd7cddfSDavid du Colombier
2227dd7cddfSDavid du Colombier count = s->count++;
2237dd7cddfSDavid du Colombier s->count &= 0xfff;
2247dd7cddfSDavid du Colombier if(s->front)
2257dd7cddfSDavid du Colombier count |= Pfront;
2267dd7cddfSDavid du Colombier if(s->reset)
2277dd7cddfSDavid du Colombier count |= Preset;
2287dd7cddfSDavid du Colombier s->reset = 0;
2297dd7cddfSDavid du Colombier s->front = 0;
2307dd7cddfSDavid du Colombier
2317dd7cddfSDavid du Colombier if(n2 > n) {
2327dd7cddfSDavid du Colombier //netlog("mppc: comp: expanded\n");
2337dd7cddfSDavid du Colombier freeb(s->b);
2347dd7cddfSDavid du Colombier /* make room for count */
2357dd7cddfSDavid du Colombier compreset(s);
2367dd7cddfSDavid du Colombier b->rptr -= 2;
2377dd7cddfSDavid du Colombier } else {
2387dd7cddfSDavid du Colombier freeb(b);
2397dd7cddfSDavid du Colombier b = s->b;
2407dd7cddfSDavid du Colombier count |= Pcompress;
2417dd7cddfSDavid du Colombier }
2427dd7cddfSDavid du Colombier s->b = nil;
2437dd7cddfSDavid du Colombier
2447dd7cddfSDavid du Colombier if(s->encrypt) {
2457dd7cddfSDavid du Colombier count |= Pencrypt;
2467dd7cddfSDavid du Colombier if((count&0xff) == 0xff) {
2477dd7cddfSDavid du Colombier //netlog("mppc: comp: changing key\n");
2487dd7cddfSDavid du Colombier setkey(s->key, s->startkey);
2497dd7cddfSDavid du Colombier setupRC4state(&s->rc4key, s->key, 16);
2507dd7cddfSDavid du Colombier rc4(&s->rc4key, s->key, 16);
2517dd7cddfSDavid du Colombier setupRC4state(&s->rc4key, s->key, 16);
2527dd7cddfSDavid du Colombier } else if(count&Preset)
2537dd7cddfSDavid du Colombier setupRC4state(&s->rc4key, s->key, 16);
2547dd7cddfSDavid du Colombier rc4(&s->rc4key, b->rptr+2, BLEN(b)-2);
2557dd7cddfSDavid du Colombier //netlog("mppc: encrypt %ux\n", count);
2567dd7cddfSDavid du Colombier }
2577dd7cddfSDavid du Colombier
2587dd7cddfSDavid du Colombier b->rptr[0] = count>>8;
2597dd7cddfSDavid du Colombier b->rptr[1] = count;
2607dd7cddfSDavid du Colombier
2617dd7cddfSDavid du Colombier qunlock(s);
2627dd7cddfSDavid du Colombier
2637dd7cddfSDavid du Colombier *protop = Pcdata;
2647dd7cddfSDavid du Colombier return b;
2657dd7cddfSDavid du Colombier }
2667dd7cddfSDavid du Colombier
2677dd7cddfSDavid du Colombier static Block *
compresetreq(void * as,Block * b)2687dd7cddfSDavid du Colombier compresetreq(void *as, Block *b)
2697dd7cddfSDavid du Colombier {
2707dd7cddfSDavid du Colombier Cstate *cs;
2717dd7cddfSDavid du Colombier
2727dd7cddfSDavid du Colombier cs = as;
2737dd7cddfSDavid du Colombier netlog("mppc: comp: reset request\n");
2747dd7cddfSDavid du Colombier qlock(cs);
2757dd7cddfSDavid du Colombier compreset(cs);
2767dd7cddfSDavid du Colombier qunlock(cs);
2777dd7cddfSDavid du Colombier
2787dd7cddfSDavid du Colombier freeb(b);
2797dd7cddfSDavid du Colombier
2807dd7cddfSDavid du Colombier return nil;
2817dd7cddfSDavid du Colombier }
2827dd7cddfSDavid du Colombier
2837dd7cddfSDavid du Colombier static void
comp2(Cstate * cs,uchar * p,int n)2847dd7cddfSDavid du Colombier comp2(Cstate *cs, uchar *p, int n)
2857dd7cddfSDavid du Colombier {
2867dd7cddfSDavid du Colombier Carena *hist, *ohist;
2877dd7cddfSDavid du Colombier ulong *hash, me, split, you, last;
2887dd7cddfSDavid du Colombier uchar *s, *t, *et, *buf, *obuf, *pos, *opos;
2897dd7cddfSDavid du Colombier int i, h, m;
2907dd7cddfSDavid du Colombier
2917dd7cddfSDavid du Colombier /*
2927dd7cddfSDavid du Colombier * check for wrap
2937dd7cddfSDavid du Colombier */
2947dd7cddfSDavid du Colombier if(cs->me + n < cs->me)
2957dd7cddfSDavid du Colombier compreset(cs);
2967dd7cddfSDavid du Colombier
2977dd7cddfSDavid du Colombier if(cs->hist->pos + n > cs->hist->buf + HistorySize)
2987dd7cddfSDavid du Colombier compfront(cs);
2997dd7cddfSDavid du Colombier
3007dd7cddfSDavid du Colombier hist = cs->hist;
3017dd7cddfSDavid du Colombier ohist = cs->ohist;
3027dd7cddfSDavid du Colombier
3037dd7cddfSDavid du Colombier hash = cs->hash;
3047dd7cddfSDavid du Colombier me = cs->me;
3057dd7cddfSDavid du Colombier split = cs->split;
3067dd7cddfSDavid du Colombier
3077dd7cddfSDavid du Colombier memmove(hist->pos, p, n);
3087dd7cddfSDavid du Colombier p = hist->pos;
3097dd7cddfSDavid du Colombier hist->pos = pos = p + n;
3107dd7cddfSDavid du Colombier
3117dd7cddfSDavid du Colombier m = Cminmatch;
3127dd7cddfSDavid du Colombier if(m > n)
3137dd7cddfSDavid du Colombier m = n;
3147dd7cddfSDavid du Colombier h = cs->h;
3157dd7cddfSDavid du Colombier for(i = 0; i < m; i++) {
3167dd7cddfSDavid du Colombier h = (((h)<<Chshift) ^ p[i]) & HMASK;
3177dd7cddfSDavid du Colombier last = me + (i - (Cminmatch-1));
3187dd7cddfSDavid du Colombier if(last >= split && last != me)
3197dd7cddfSDavid du Colombier hash[h] = last;
3207dd7cddfSDavid du Colombier }
3217dd7cddfSDavid du Colombier
3227dd7cddfSDavid du Colombier buf = hist->buf - split;
3237dd7cddfSDavid du Colombier obuf = ohist->buf + HistorySize - split;
3247dd7cddfSDavid du Colombier opos = ohist->pos;
3257dd7cddfSDavid du Colombier while(p < pos) {
3267dd7cddfSDavid du Colombier you = hash[h];
3277dd7cddfSDavid du Colombier if(you < split) {
3287dd7cddfSDavid du Colombier if(me - you >= HistorySize)
3297dd7cddfSDavid du Colombier t = opos;
3307dd7cddfSDavid du Colombier else
3317dd7cddfSDavid du Colombier t = obuf + you;
3327dd7cddfSDavid du Colombier et = opos;
3337dd7cddfSDavid du Colombier } else {
3347dd7cddfSDavid du Colombier t = buf + you;
3357dd7cddfSDavid du Colombier et = pos;
3367dd7cddfSDavid du Colombier }
3377dd7cddfSDavid du Colombier m = pos - p;
3387dd7cddfSDavid du Colombier if(m < et - t)
3397dd7cddfSDavid du Colombier et = t + m;
3407dd7cddfSDavid du Colombier for(s = p; t < et; t++) {
3417dd7cddfSDavid du Colombier if(*s != *t)
3427dd7cddfSDavid du Colombier break;
3437dd7cddfSDavid du Colombier s++;
3447dd7cddfSDavid du Colombier }
3457dd7cddfSDavid du Colombier m = s - p;
3467dd7cddfSDavid du Colombier if(m < Cminmatch) {
3477dd7cddfSDavid du Colombier complit(cs, *p);
3487dd7cddfSDavid du Colombier s = p + 1;
3497dd7cddfSDavid du Colombier } else
3507dd7cddfSDavid du Colombier compcopy(cs, me - you, m);
3517dd7cddfSDavid du Colombier
3527dd7cddfSDavid du Colombier for(; p != s; p++) {
3537dd7cddfSDavid du Colombier if(p + Cminmatch <= pos) {
3547dd7cddfSDavid du Colombier hash[h] = me;
3557dd7cddfSDavid du Colombier if(p + Cminmatch < pos)
3567dd7cddfSDavid du Colombier h = (((h)<<Chshift) ^ p[Cminmatch]) & HMASK;
3577dd7cddfSDavid du Colombier }
3587dd7cddfSDavid du Colombier me++;
3597dd7cddfSDavid du Colombier }
3607dd7cddfSDavid du Colombier }
3617dd7cddfSDavid du Colombier
3627dd7cddfSDavid du Colombier cs->h = h;
3637dd7cddfSDavid du Colombier cs->me = me;
3647dd7cddfSDavid du Colombier }
3657dd7cddfSDavid du Colombier
3667dd7cddfSDavid du Colombier static void
compfront(Cstate * cs)3677dd7cddfSDavid du Colombier compfront(Cstate *cs)
3687dd7cddfSDavid du Colombier {
3697dd7cddfSDavid du Colombier Carena *th;
3707dd7cddfSDavid du Colombier
3717dd7cddfSDavid du Colombier cs->front = 1;
3727dd7cddfSDavid du Colombier
3737dd7cddfSDavid du Colombier th = cs->ohist;
3747dd7cddfSDavid du Colombier cs->ohist = cs->hist;
3757dd7cddfSDavid du Colombier cs->hist = th;
3767dd7cddfSDavid du Colombier cs->hist->pos = cs->hist->buf;
3777dd7cddfSDavid du Colombier cs->h = 0;
3787dd7cddfSDavid du Colombier cs->me = cs->split + HistorySize;
3797dd7cddfSDavid du Colombier cs->split = cs->me;
3807dd7cddfSDavid du Colombier }
3817dd7cddfSDavid du Colombier
3827dd7cddfSDavid du Colombier static void
compreset(Cstate * cs)3837dd7cddfSDavid du Colombier compreset(Cstate *cs)
3847dd7cddfSDavid du Colombier {
3857dd7cddfSDavid du Colombier ulong me;
3867dd7cddfSDavid du Colombier
3877dd7cddfSDavid du Colombier cs->reset = 1;
3887dd7cddfSDavid du Colombier
3897dd7cddfSDavid du Colombier me = cs->me;
3907dd7cddfSDavid du Colombier if(me + 2 * HistorySize < me){
3917dd7cddfSDavid du Colombier me = 0;
3927dd7cddfSDavid du Colombier memset(cs->hash, 0, sizeof(cs->hash));
3937dd7cddfSDavid du Colombier }
3947dd7cddfSDavid du Colombier cs->me = me + 2 * HistorySize;
3957dd7cddfSDavid du Colombier cs->split = cs->me;
3967dd7cddfSDavid du Colombier cs->hist->pos = cs->hist->buf;
3977dd7cddfSDavid du Colombier cs->ohist->pos = cs->ohist->buf;
3987dd7cddfSDavid du Colombier }
3997dd7cddfSDavid du Colombier
4007dd7cddfSDavid du Colombier static void
complit(Cstate * s,int c)4017dd7cddfSDavid du Colombier complit(Cstate *s, int c)
4027dd7cddfSDavid du Colombier {
4037dd7cddfSDavid du Colombier if(c&0x80)
4047dd7cddfSDavid du Colombier compout(s, 0x100|(c&0x7f), 9);
4057dd7cddfSDavid du Colombier else
4067dd7cddfSDavid du Colombier compout(s, c, 8);
4077dd7cddfSDavid du Colombier }
4087dd7cddfSDavid du Colombier
4097dd7cddfSDavid du Colombier static void
compcopy(Cstate * s,int off,int len)4107dd7cddfSDavid du Colombier compcopy(Cstate *s, int off, int len)
4117dd7cddfSDavid du Colombier {
4127dd7cddfSDavid du Colombier int i;
4137dd7cddfSDavid du Colombier ulong mask;
4147dd7cddfSDavid du Colombier
4157dd7cddfSDavid du Colombier if(off<64)
4167dd7cddfSDavid du Colombier compout(s, 0x3c0|off, 10);
4177dd7cddfSDavid du Colombier else if(off<320)
4187dd7cddfSDavid du Colombier compout(s, 0xe00|(off-64), 12);
4197dd7cddfSDavid du Colombier else
4207dd7cddfSDavid du Colombier compout(s, 0xc000|(off-320), 16);
4217dd7cddfSDavid du Colombier if(len < 3)
4227dd7cddfSDavid du Colombier sysfatal("compcopy: bad len: %d", len);
4237dd7cddfSDavid du Colombier if(len == 3)
4247dd7cddfSDavid du Colombier compout(s, 0, 1);
4257dd7cddfSDavid du Colombier else {
4267dd7cddfSDavid du Colombier for(i=3; (1<<i) <= len; i++)
4277dd7cddfSDavid du Colombier ;
4287dd7cddfSDavid du Colombier mask = (1<<(i-1))-1;
4297dd7cddfSDavid du Colombier compout(s, (((1<<(i-2))-1)<<i) | len&mask, (i-1)<<1);
4307dd7cddfSDavid du Colombier }
4317dd7cddfSDavid du Colombier }
4327dd7cddfSDavid du Colombier
4337dd7cddfSDavid du Colombier static void
compout(Cstate * s,ulong data,int bits)4347dd7cddfSDavid du Colombier compout(Cstate *s, ulong data, int bits)
4357dd7cddfSDavid du Colombier {
4367dd7cddfSDavid du Colombier ulong sreg;
4377dd7cddfSDavid du Colombier
4387dd7cddfSDavid du Colombier sreg = s->sreg;
4397dd7cddfSDavid du Colombier sreg <<= bits;
4407dd7cddfSDavid du Colombier sreg |= data;
4417dd7cddfSDavid du Colombier bits += s->bits;
4427dd7cddfSDavid du Colombier while(bits >= 8) {
4437dd7cddfSDavid du Colombier *s->b->wptr++ = sreg>>(bits-8);
4447dd7cddfSDavid du Colombier bits -= 8;
4457dd7cddfSDavid du Colombier }
4467dd7cddfSDavid du Colombier s->sreg = sreg;
4477dd7cddfSDavid du Colombier s->bits = bits;
4487dd7cddfSDavid du Colombier }
4497dd7cddfSDavid du Colombier
4507dd7cddfSDavid du Colombier void
printkey(uchar * key)4517dd7cddfSDavid du Colombier printkey(uchar *key)
4527dd7cddfSDavid du Colombier {
4537dd7cddfSDavid du Colombier char buf[200], *p;
4547dd7cddfSDavid du Colombier int i;
4557dd7cddfSDavid du Colombier
4567dd7cddfSDavid du Colombier p = buf;
4577dd7cddfSDavid du Colombier for(i=0; i<16; i++)
4587dd7cddfSDavid du Colombier p += sprint(p, "%.2ux ", key[i]);
4597dd7cddfSDavid du Colombier //netlog("key = %s\n", buf);
4607dd7cddfSDavid du Colombier }
4617dd7cddfSDavid du Colombier
4627dd7cddfSDavid du Colombier static void *
uncinit(PPP * ppp)4637dd7cddfSDavid du Colombier uncinit(PPP *ppp)
4647dd7cddfSDavid du Colombier {
4657dd7cddfSDavid du Colombier Uncstate *s;
4667dd7cddfSDavid du Colombier
4677dd7cddfSDavid du Colombier s = mallocz(sizeof(Uncstate), 1);
4687dd7cddfSDavid du Colombier
4697dd7cddfSDavid du Colombier s->count = 0xfff; /* count of non existant last packet */
4707dd7cddfSDavid du Colombier memmove(s->startkey, ppp->key, 16);
4717dd7cddfSDavid du Colombier memmove(s->key, ppp->key, 16);
4727dd7cddfSDavid du Colombier setkey(s->key, s->startkey);
4737dd7cddfSDavid du Colombier setupRC4state(&s->rc4key, s->key, 16);
4747dd7cddfSDavid du Colombier
4757dd7cddfSDavid du Colombier return s;
4767dd7cddfSDavid du Colombier }
4777dd7cddfSDavid du Colombier
4787dd7cddfSDavid du Colombier static Block*
uncomp(PPP * ppp,Block * b,int * protop,Block ** r)4797dd7cddfSDavid du Colombier uncomp(PPP *ppp, Block *b, int *protop, Block **r)
4807dd7cddfSDavid du Colombier {
4817dd7cddfSDavid du Colombier Uncstate *s;
4827dd7cddfSDavid du Colombier ushort proto;
4837dd7cddfSDavid du Colombier ushort count;
4847dd7cddfSDavid du Colombier Lcpmsg *m;
4857dd7cddfSDavid du Colombier
4867dd7cddfSDavid du Colombier *r = nil;
4877dd7cddfSDavid du Colombier *protop = 0;
4887dd7cddfSDavid du Colombier s = ppp->uncstate;
4897dd7cddfSDavid du Colombier if(BLEN(b) < 2){
4907dd7cddfSDavid du Colombier syslog(0, "ppp", ": mppc: short packet\n");
4917dd7cddfSDavid du Colombier freeb(b);
4927dd7cddfSDavid du Colombier return nil;
4937dd7cddfSDavid du Colombier }
4947dd7cddfSDavid du Colombier count = nhgets(b->rptr);
4957dd7cddfSDavid du Colombier b->rptr += 2;
4967dd7cddfSDavid du Colombier
4977dd7cddfSDavid du Colombier b = uncomp2(s, b, count);
4987dd7cddfSDavid du Colombier
4997dd7cddfSDavid du Colombier if(b == nil) {
5007dd7cddfSDavid du Colombier //netlog("ppp: mppc: reset request\n");
5017dd7cddfSDavid du Colombier /* return reset request packet */
5027dd7cddfSDavid du Colombier *r = alloclcp(Lresetreq, s->resetid++, 4, &m);
5037dd7cddfSDavid du Colombier hnputs(m->len, 4);
5047dd7cddfSDavid du Colombier *protop = 0;
5057dd7cddfSDavid du Colombier return nil;
5067dd7cddfSDavid du Colombier }
5077dd7cddfSDavid du Colombier
5087dd7cddfSDavid du Colombier if(BLEN(b) < 2){
5097dd7cddfSDavid du Colombier syslog(0, "ppp", ": mppc: short packet\n");
5107dd7cddfSDavid du Colombier freeb(b);
5117dd7cddfSDavid du Colombier *protop = 0;
5127dd7cddfSDavid du Colombier return nil;
5137dd7cddfSDavid du Colombier }
5147dd7cddfSDavid du Colombier proto = nhgets(b->rptr);
5157dd7cddfSDavid du Colombier b->rptr += 2;
5167dd7cddfSDavid du Colombier
5177dd7cddfSDavid du Colombier /*
5187dd7cddfSDavid du Colombier if(proto == 0x21)
5197dd7cddfSDavid du Colombier if(!ipcheck(b->rptr, BLEN(b)))
5207dd7cddfSDavid du Colombier hischeck(s);
5217dd7cddfSDavid du Colombier */
5227dd7cddfSDavid du Colombier
5237dd7cddfSDavid du Colombier *protop = proto;
5247dd7cddfSDavid du Colombier return b;
5257dd7cddfSDavid du Colombier }
5267dd7cddfSDavid du Colombier
5277dd7cddfSDavid du Colombier #define NEXTBYTE sreg = (sreg<<8) | *p++; n--; bits += 8
5287dd7cddfSDavid du Colombier int maxoff;
5297dd7cddfSDavid du Colombier
5307dd7cddfSDavid du Colombier static Block*
uncomp2(Uncstate * s,Block * b,ushort count)5317dd7cddfSDavid du Colombier uncomp2(Uncstate *s, Block *b, ushort count)
5327dd7cddfSDavid du Colombier {
5337dd7cddfSDavid du Colombier int ecount, n, bits, off, len, ones;
5347dd7cddfSDavid du Colombier ulong sreg;
5357dd7cddfSDavid du Colombier int t;
5367dd7cddfSDavid du Colombier uchar *p, c, *hp, *hs, *he, *hq;
5377dd7cddfSDavid du Colombier
5387dd7cddfSDavid du Colombier if(count&Preset) {
5397dd7cddfSDavid du Colombier //netlog("mppc reset\n");
5407dd7cddfSDavid du Colombier s->indx = 0;
5417dd7cddfSDavid du Colombier s->size = 0;
5427dd7cddfSDavid du Colombier setupRC4state(&s->rc4key, s->key, 16);
5437dd7cddfSDavid du Colombier } else {
5447dd7cddfSDavid du Colombier ecount = (s->count+1)&0xfff;
5457dd7cddfSDavid du Colombier if((count&0xfff) != ecount) {
5467dd7cddfSDavid du Colombier netlog("******* bad count - got %ux expected %ux\n", count&0xfff, ecount);
5477dd7cddfSDavid du Colombier freeb(b);
5487dd7cddfSDavid du Colombier return nil;
5497dd7cddfSDavid du Colombier }
5507dd7cddfSDavid du Colombier if(count&Pfront) {
5517dd7cddfSDavid du Colombier s->indx = 0;
5527dd7cddfSDavid du Colombier /* netlog("ppp: mppc: frount flag set\n"); */
5537dd7cddfSDavid du Colombier }
5547dd7cddfSDavid du Colombier }
5557dd7cddfSDavid du Colombier
5567dd7cddfSDavid du Colombier /* update key */
5577dd7cddfSDavid du Colombier n = (((count+1)>>8)&0xf) - (((s->count+1)>>8)&0xf);
5587dd7cddfSDavid du Colombier if(n < 0)
5597dd7cddfSDavid du Colombier n += 16;
5607dd7cddfSDavid du Colombier //netlog("mppc count = %ux oldcount %ux n = %d\n", count, s->count, n);
5617dd7cddfSDavid du Colombier if(n < 0 || n > 1) {
5627dd7cddfSDavid du Colombier syslog(0, "ppp", ": mppc bad count %ux, %ux", count, s->count);
5637dd7cddfSDavid du Colombier freeb(b);
5647dd7cddfSDavid du Colombier return nil;
5657dd7cddfSDavid du Colombier }
5667dd7cddfSDavid du Colombier if(n == 1) {
5677dd7cddfSDavid du Colombier setkey(s->key, s->startkey);
5687dd7cddfSDavid du Colombier setupRC4state(&s->rc4key, s->key, 16);
5697dd7cddfSDavid du Colombier rc4(&s->rc4key, s->key, 16);
5707dd7cddfSDavid du Colombier setupRC4state(&s->rc4key, s->key, 16);
5717dd7cddfSDavid du Colombier }
5727dd7cddfSDavid du Colombier
5737dd7cddfSDavid du Colombier s->count = count;
5747dd7cddfSDavid du Colombier
5757dd7cddfSDavid du Colombier n = BLEN(b);
5767dd7cddfSDavid du Colombier p = b->rptr;
5777dd7cddfSDavid du Colombier if(count & Pencrypt) {
5787dd7cddfSDavid du Colombier //netlog("mppc unencrypt count = %ux\n", count);
5797dd7cddfSDavid du Colombier rc4(&s->rc4key, p, n);
5807dd7cddfSDavid du Colombier }
5817dd7cddfSDavid du Colombier
5827dd7cddfSDavid du Colombier if(!(count & Pcompress)) {
5837dd7cddfSDavid du Colombier //netlog("uncompress blen = %d\n", BLEN(b));
5847dd7cddfSDavid du Colombier return b;
5857dd7cddfSDavid du Colombier }
5867dd7cddfSDavid du Colombier
5877dd7cddfSDavid du Colombier bits = 0;
5887dd7cddfSDavid du Colombier sreg = 0;
5897dd7cddfSDavid du Colombier hs = s->his; /* history start */
5907dd7cddfSDavid du Colombier hp = hs+s->indx; /* write pointer in history */
5917dd7cddfSDavid du Colombier he = hs+sizeof(s->his); /* hsitory end */
5927dd7cddfSDavid du Colombier for(;;) {
5937dd7cddfSDavid du Colombier if(bits<4) {
5947dd7cddfSDavid du Colombier if(n==0) goto Done;
5957dd7cddfSDavid du Colombier NEXTBYTE;
5967dd7cddfSDavid du Colombier }
5977dd7cddfSDavid du Colombier t = decode[(sreg>>(bits-4))&0xf];
5987dd7cddfSDavid du Colombier switch(t) {
5997dd7cddfSDavid du Colombier default:
6007dd7cddfSDavid du Colombier sysfatal("mppc: bad decode!");
6017dd7cddfSDavid du Colombier case Lit7:
6027dd7cddfSDavid du Colombier bits -= 1;
6037dd7cddfSDavid du Colombier if(bits<7) {
6047dd7cddfSDavid du Colombier if(n==0) goto Done;
6057dd7cddfSDavid du Colombier NEXTBYTE;
6067dd7cddfSDavid du Colombier }
6077dd7cddfSDavid du Colombier c = (sreg>>(bits-7))&0x7f;
6087dd7cddfSDavid du Colombier bits -= 7;
6097dd7cddfSDavid du Colombier if(hp >= he) goto His;
6107dd7cddfSDavid du Colombier *hp++ = c;
6117dd7cddfSDavid du Colombier /* netlog("\tlit7 %.2ux\n", c); */
6127dd7cddfSDavid du Colombier continue;
6137dd7cddfSDavid du Colombier case Lit8:
6147dd7cddfSDavid du Colombier bits -= 2;
6157dd7cddfSDavid du Colombier if(bits<7) {
6167dd7cddfSDavid du Colombier if(n==0) goto Eof;
6177dd7cddfSDavid du Colombier NEXTBYTE;
6187dd7cddfSDavid du Colombier }
6197dd7cddfSDavid du Colombier c = 0x80 | ((sreg>>(bits-7))&0x7f);
6207dd7cddfSDavid du Colombier bits -= 7;
6217dd7cddfSDavid du Colombier if(hp >= he) goto His;
6227dd7cddfSDavid du Colombier *hp++ = c;
6237dd7cddfSDavid du Colombier /* netlog("\tlit8 %.2ux\n", c); */
6247dd7cddfSDavid du Colombier continue;
6257dd7cddfSDavid du Colombier case Off6:
6267dd7cddfSDavid du Colombier bits -= 4;
6277dd7cddfSDavid du Colombier if(bits<6) {
6287dd7cddfSDavid du Colombier if(n==0) goto Eof;
6297dd7cddfSDavid du Colombier NEXTBYTE;
6307dd7cddfSDavid du Colombier }
6317dd7cddfSDavid du Colombier off = (sreg>>(bits-6))&0x3f;
6327dd7cddfSDavid du Colombier bits -= 6;
6337dd7cddfSDavid du Colombier break;
6347dd7cddfSDavid du Colombier case Off8:
6357dd7cddfSDavid du Colombier bits -= 4;
6367dd7cddfSDavid du Colombier if(bits<8) {
6377dd7cddfSDavid du Colombier if(n==0) goto Eof;
6387dd7cddfSDavid du Colombier NEXTBYTE;
6397dd7cddfSDavid du Colombier }
6407dd7cddfSDavid du Colombier off = ((sreg>>(bits-8))&0xff)+64;
6417dd7cddfSDavid du Colombier bits -= 8;
6427dd7cddfSDavid du Colombier break;
6437dd7cddfSDavid du Colombier case Off13:
6447dd7cddfSDavid du Colombier bits -= 3;
6457dd7cddfSDavid du Colombier while(bits<13) {
6467dd7cddfSDavid du Colombier if(n==0) goto Eof;
6477dd7cddfSDavid du Colombier NEXTBYTE;
6487dd7cddfSDavid du Colombier }
6497dd7cddfSDavid du Colombier off = ((sreg>>(bits-13))&0x1fff)+320;
6507dd7cddfSDavid du Colombier bits -= 13;
6517dd7cddfSDavid du Colombier /* netlog("\toff=%d bits = %d sreg = %ux t = %x\n", off, bits, sreg, t); */
6527dd7cddfSDavid du Colombier break;
6537dd7cddfSDavid du Colombier }
6547dd7cddfSDavid du Colombier for(ones=0;;ones++) {
6557dd7cddfSDavid du Colombier if(bits == 0) {
6567dd7cddfSDavid du Colombier if(n==0) goto Eof;
6577dd7cddfSDavid du Colombier NEXTBYTE;
6587dd7cddfSDavid du Colombier }
6597dd7cddfSDavid du Colombier bits--;
6607dd7cddfSDavid du Colombier if(!(sreg&(1<<bits)))
6617dd7cddfSDavid du Colombier break;
6627dd7cddfSDavid du Colombier }
6637dd7cddfSDavid du Colombier if(ones>11) {
6647dd7cddfSDavid du Colombier netlog("ppp: mppc: bad length %d\n", ones);
6657dd7cddfSDavid du Colombier freeb(b);
6667dd7cddfSDavid du Colombier return nil;
6677dd7cddfSDavid du Colombier }
6687dd7cddfSDavid du Colombier if(ones == 0) {
6697dd7cddfSDavid du Colombier len = 3;
6707dd7cddfSDavid du Colombier } else {
6717dd7cddfSDavid du Colombier ones++;
6727dd7cddfSDavid du Colombier while(bits<ones) {
6737dd7cddfSDavid du Colombier if(n==0) goto Eof;
6747dd7cddfSDavid du Colombier NEXTBYTE;
6757dd7cddfSDavid du Colombier }
6767dd7cddfSDavid du Colombier len = (1<<ones) | ((sreg>>(bits-ones))&((1<<ones)-1));
6777dd7cddfSDavid du Colombier bits -= ones;
6787dd7cddfSDavid du Colombier }
6797dd7cddfSDavid du Colombier
6807dd7cddfSDavid du Colombier hq = hp-off;
6817dd7cddfSDavid du Colombier if(hq < hs) {
6827dd7cddfSDavid du Colombier hq += sizeof(s->his);
6837dd7cddfSDavid du Colombier if(hq-hs+len > s->size)
6847dd7cddfSDavid du Colombier goto His;
6857dd7cddfSDavid du Colombier }
6867dd7cddfSDavid du Colombier if(hp+len > he) goto His;
6877dd7cddfSDavid du Colombier while(len) {
6887dd7cddfSDavid du Colombier *hp++ = *hq++;
6897dd7cddfSDavid du Colombier len--;
6907dd7cddfSDavid du Colombier }
6917dd7cddfSDavid du Colombier }
6927dd7cddfSDavid du Colombier Done:
6937dd7cddfSDavid du Colombier freeb(b);
6947dd7cddfSDavid du Colombier
6957dd7cddfSDavid du Colombier /* build up return block */
6967dd7cddfSDavid du Colombier hq = hs+s->indx;
6977dd7cddfSDavid du Colombier len = hp-hq;
6987dd7cddfSDavid du Colombier b = allocb(len);
6997dd7cddfSDavid du Colombier memmove(b->wptr, hq, len);
7007dd7cddfSDavid du Colombier b->wptr += len;
701*9a747e4fSDavid du Colombier netlog("ppp: mppc: len %d bits = %d n=%d\n", len, bits, n);
7027dd7cddfSDavid du Colombier
7037dd7cddfSDavid du Colombier s->indx += len;
7047dd7cddfSDavid du Colombier if(s->indx > s->size)
7057dd7cddfSDavid du Colombier s->size = s->indx;
7067dd7cddfSDavid du Colombier
7077dd7cddfSDavid du Colombier return b;
7087dd7cddfSDavid du Colombier Eof:
7097dd7cddfSDavid du Colombier netlog("*****unexpected end of data\n");
7107dd7cddfSDavid du Colombier freeb(b);
7117dd7cddfSDavid du Colombier return nil;
7127dd7cddfSDavid du Colombier His:
7137dd7cddfSDavid du Colombier netlog("*****bad history\n");
7147dd7cddfSDavid du Colombier freeb(b);
7157dd7cddfSDavid du Colombier return nil;
7167dd7cddfSDavid du Colombier }
7177dd7cddfSDavid du Colombier
7187dd7cddfSDavid du Colombier static void
uncresetack(void *,Block *)7197dd7cddfSDavid du Colombier uncresetack(void*, Block*)
7207dd7cddfSDavid du Colombier {
7217dd7cddfSDavid du Colombier }
7227dd7cddfSDavid du Colombier
7237dd7cddfSDavid du Colombier static void
uncfini(void * as)7247dd7cddfSDavid du Colombier uncfini(void *as)
7257dd7cddfSDavid du Colombier {
7267dd7cddfSDavid du Colombier Uncstate *s;
7277dd7cddfSDavid du Colombier
7287dd7cddfSDavid du Colombier s = as;
7297dd7cddfSDavid du Colombier free(s);
7307dd7cddfSDavid du Colombier }
7317dd7cddfSDavid du Colombier
7327dd7cddfSDavid du Colombier static void
setkey(uchar * key,uchar * startkey)7337dd7cddfSDavid du Colombier setkey(uchar *key, uchar *startkey)
7347dd7cddfSDavid du Colombier {
7357dd7cddfSDavid du Colombier uchar pad[40];
7367dd7cddfSDavid du Colombier SHAstate *s;
7377dd7cddfSDavid du Colombier uchar digest[SHA1dlen];
7387dd7cddfSDavid du Colombier
7397dd7cddfSDavid du Colombier s = sha1(startkey, 16, nil, nil);
7407dd7cddfSDavid du Colombier memset(pad, 0, 40);
7417dd7cddfSDavid du Colombier sha1(pad, 40, nil, s);
7427dd7cddfSDavid du Colombier sha1(key, 16, nil, s);
7437dd7cddfSDavid du Colombier memset(pad, 0xf2, 40);
7447dd7cddfSDavid du Colombier sha1(pad, 40, digest, s);
7457dd7cddfSDavid du Colombier memmove(key, digest, 16);
7467dd7cddfSDavid du Colombier }
7477dd7cddfSDavid du Colombier
7487dd7cddfSDavid du Colombier
7497dd7cddfSDavid du Colombier /* code to check if IP packet looks good */
7507dd7cddfSDavid du Colombier
7517dd7cddfSDavid du Colombier typedef struct Iphdr Iphdr;
7527dd7cddfSDavid du Colombier struct Iphdr
7537dd7cddfSDavid du Colombier {
7547dd7cddfSDavid du Colombier uchar vihl; /* Version and header length */
7557dd7cddfSDavid du Colombier uchar tos; /* Type of service */
7567dd7cddfSDavid du Colombier uchar length[2]; /* packet length */
7577dd7cddfSDavid du Colombier uchar id[2]; /* Identification */
7587dd7cddfSDavid du Colombier uchar frag[2]; /* Fragment information */
7597dd7cddfSDavid du Colombier uchar ttl; /* Time to live */
7607dd7cddfSDavid du Colombier uchar proto; /* Protocol */
7617dd7cddfSDavid du Colombier uchar cksum[2]; /* Header checksum */
7627dd7cddfSDavid du Colombier uchar src[4]; /* Ip source */
7637dd7cddfSDavid du Colombier uchar dst[4]; /* Ip destination */
7647dd7cddfSDavid du Colombier };
7657dd7cddfSDavid du Colombier
7667dd7cddfSDavid du Colombier enum
7677dd7cddfSDavid du Colombier {
7687dd7cddfSDavid du Colombier QMAX = 64*1024-1,
7697dd7cddfSDavid du Colombier IP_TCPPROTO = 6,
7707dd7cddfSDavid du Colombier TCP_IPLEN = 8,
7717dd7cddfSDavid du Colombier TCP_PHDRSIZE = 12,
7727dd7cddfSDavid du Colombier TCP_HDRSIZE = 20,
7737dd7cddfSDavid du Colombier TCP_PKT = TCP_IPLEN+TCP_PHDRSIZE,
7747dd7cddfSDavid du Colombier };
7757dd7cddfSDavid du Colombier
7767dd7cddfSDavid du Colombier enum
7777dd7cddfSDavid du Colombier {
7787dd7cddfSDavid du Colombier UDP_PHDRSIZE = 12,
7797dd7cddfSDavid du Colombier UDP_HDRSIZE = 20,
7807dd7cddfSDavid du Colombier UDP_IPHDR = 8,
7817dd7cddfSDavid du Colombier IP_UDPPROTO = 17,
7827dd7cddfSDavid du Colombier UDP_USEAD = 12,
7837dd7cddfSDavid du Colombier UDP_RELSIZE = 16,
7847dd7cddfSDavid du Colombier
7857dd7cddfSDavid du Colombier Udprxms = 200,
7867dd7cddfSDavid du Colombier Udptickms = 100,
7877dd7cddfSDavid du Colombier Udpmaxxmit = 10,
7887dd7cddfSDavid du Colombier };
7897dd7cddfSDavid du Colombier
7907dd7cddfSDavid du Colombier typedef struct UDPhdr UDPhdr;
7917dd7cddfSDavid du Colombier struct UDPhdr
7927dd7cddfSDavid du Colombier {
7937dd7cddfSDavid du Colombier /* ip header */
7947dd7cddfSDavid du Colombier uchar vihl; /* Version and header length */
7957dd7cddfSDavid du Colombier uchar tos; /* Type of service */
7967dd7cddfSDavid du Colombier uchar length[2]; /* packet length */
7977dd7cddfSDavid du Colombier uchar id[2]; /* Identification */
7987dd7cddfSDavid du Colombier uchar frag[2]; /* Fragment information */
7997dd7cddfSDavid du Colombier uchar Unused;
8007dd7cddfSDavid du Colombier uchar udpproto; /* Protocol */
8017dd7cddfSDavid du Colombier uchar udpplen[2]; /* Header plus data length */
8027dd7cddfSDavid du Colombier uchar udpsrc[4]; /* Ip source */
8037dd7cddfSDavid du Colombier uchar udpdst[4]; /* Ip destination */
8047dd7cddfSDavid du Colombier
8057dd7cddfSDavid du Colombier /* udp header */
8067dd7cddfSDavid du Colombier uchar udpsport[2]; /* Source port */
8077dd7cddfSDavid du Colombier uchar udpdport[2]; /* Destination port */
8087dd7cddfSDavid du Colombier uchar udplen[2]; /* data length */
8097dd7cddfSDavid du Colombier uchar udpcksum[2]; /* Checksum */
8107dd7cddfSDavid du Colombier };
8117dd7cddfSDavid du Colombier
8127dd7cddfSDavid du Colombier typedef struct TCPhdr TCPhdr;
8137dd7cddfSDavid du Colombier struct TCPhdr
8147dd7cddfSDavid du Colombier {
8157dd7cddfSDavid du Colombier uchar vihl; /* Version and header length */
8167dd7cddfSDavid du Colombier uchar tos; /* Type of service */
8177dd7cddfSDavid du Colombier uchar length[2]; /* packet length */
8187dd7cddfSDavid du Colombier uchar id[2]; /* Identification */
8197dd7cddfSDavid du Colombier uchar frag[2]; /* Fragment information */
8207dd7cddfSDavid du Colombier uchar Unused;
8217dd7cddfSDavid du Colombier uchar proto;
8227dd7cddfSDavid du Colombier uchar tcplen[2];
8237dd7cddfSDavid du Colombier uchar tcpsrc[4];
8247dd7cddfSDavid du Colombier uchar tcpdst[4];
8257dd7cddfSDavid du Colombier uchar tcpsport[2];
8267dd7cddfSDavid du Colombier uchar tcpdport[2];
8277dd7cddfSDavid du Colombier uchar tcpseq[4];
8287dd7cddfSDavid du Colombier uchar tcpack[4];
8297dd7cddfSDavid du Colombier uchar tcpflag[2];
8307dd7cddfSDavid du Colombier uchar tcpwin[2];
8317dd7cddfSDavid du Colombier uchar tcpcksum[2];
8327dd7cddfSDavid du Colombier uchar tcpurg[2];
8337dd7cddfSDavid du Colombier /* Options segment */
8347dd7cddfSDavid du Colombier uchar tcpopt[2];
8357dd7cddfSDavid du Colombier uchar tcpmss[2];
8367dd7cddfSDavid du Colombier };
8377dd7cddfSDavid du Colombier
8387dd7cddfSDavid du Colombier static void
hischeck(Uncstate * s)8397dd7cddfSDavid du Colombier hischeck(Uncstate *s)
8407dd7cddfSDavid du Colombier {
8417dd7cddfSDavid du Colombier uchar *p;
8427dd7cddfSDavid du Colombier Iphdr *iph;
8437dd7cddfSDavid du Colombier int len;
8447dd7cddfSDavid du Colombier
8457dd7cddfSDavid du Colombier p = s->his;
8467dd7cddfSDavid du Colombier
8477dd7cddfSDavid du Colombier netlog("***** history check\n");
8487dd7cddfSDavid du Colombier while(p < s->his+s->size) {
8497dd7cddfSDavid du Colombier if(p[0] != 0 || p[1] != 0x21) {
8507dd7cddfSDavid du Colombier netlog("***** unknown protocol\n");
8517dd7cddfSDavid du Colombier return;
8527dd7cddfSDavid du Colombier }
8537dd7cddfSDavid du Colombier p += 2;
85459cc4ca5SDavid du Colombier netlog("off = %ld ", p-s->his);
8557dd7cddfSDavid du Colombier iph = (Iphdr*)p;
8567dd7cddfSDavid du Colombier len = nhgets(iph->length);
8577dd7cddfSDavid du Colombier ipcheck(p, len);
8587dd7cddfSDavid du Colombier p += len;
8597dd7cddfSDavid du Colombier }
8607dd7cddfSDavid du Colombier }
8617dd7cddfSDavid du Colombier
8627dd7cddfSDavid du Colombier
8637dd7cddfSDavid du Colombier static int
ipcheck(uchar * p,int len)8647dd7cddfSDavid du Colombier ipcheck(uchar *p, int len)
8657dd7cddfSDavid du Colombier {
8667dd7cddfSDavid du Colombier Iphdr *iph;
8677dd7cddfSDavid du Colombier TCPhdr *tcph;
8687dd7cddfSDavid du Colombier ushort length;
8697dd7cddfSDavid du Colombier UDPhdr *uh;
8707dd7cddfSDavid du Colombier Block *bp;
8717dd7cddfSDavid du Colombier ushort cksum;
8727dd7cddfSDavid du Colombier int good;
8737dd7cddfSDavid du Colombier
8747dd7cddfSDavid du Colombier bp = allocb(len);
8757dd7cddfSDavid du Colombier memmove(bp->wptr, p, len);
8767dd7cddfSDavid du Colombier bp->wptr += len;
8777dd7cddfSDavid du Colombier
8787dd7cddfSDavid du Colombier good = 1;
8797dd7cddfSDavid du Colombier
8807dd7cddfSDavid du Colombier iph = (Iphdr *)(bp->rptr);
8817dd7cddfSDavid du Colombier /* netlog("ppp: mppc: ipcheck %I %I len %d proto %d\n", iph->src, iph->dst, BLEN(bp), iph->proto); */
8827dd7cddfSDavid du Colombier
8837dd7cddfSDavid du Colombier if(len != nhgets(iph->length)) {
8847dd7cddfSDavid du Colombier netlog("***** bad length! %d %d\n", len, nhgets(iph->length));
8857dd7cddfSDavid du Colombier good = 0;
8867dd7cddfSDavid du Colombier }
8877dd7cddfSDavid du Colombier
8887dd7cddfSDavid du Colombier cksum = ipcsum(&iph->vihl);
8897dd7cddfSDavid du Colombier if(cksum) {
8907dd7cddfSDavid du Colombier netlog("***** IP proto cksum!!! %I %ux\n", iph->src, cksum);
8917dd7cddfSDavid du Colombier good = 0;
8927dd7cddfSDavid du Colombier }
8937dd7cddfSDavid du Colombier
8947dd7cddfSDavid du Colombier switch(iph->proto) {
8957dd7cddfSDavid du Colombier default:
8967dd7cddfSDavid du Colombier break;
8977dd7cddfSDavid du Colombier case IP_TCPPROTO:
8987dd7cddfSDavid du Colombier
8997dd7cddfSDavid du Colombier tcph = (TCPhdr*)(bp->rptr);
9007dd7cddfSDavid du Colombier
9017dd7cddfSDavid du Colombier length = nhgets(tcph->length);
9027dd7cddfSDavid du Colombier
9037dd7cddfSDavid du Colombier tcph->Unused = 0;
9047dd7cddfSDavid du Colombier hnputs(tcph->tcplen, length-TCP_PKT);
9057dd7cddfSDavid du Colombier cksum = ptclcsum(bp, TCP_IPLEN, length-TCP_IPLEN);
9067dd7cddfSDavid du Colombier if(cksum) {
9077dd7cddfSDavid du Colombier netlog("***** bad tcp proto cksum %ux!!!\n", cksum);
9087dd7cddfSDavid du Colombier good = 0;
9097dd7cddfSDavid du Colombier }
9107dd7cddfSDavid du Colombier break;
9117dd7cddfSDavid du Colombier case IP_UDPPROTO:
9127dd7cddfSDavid du Colombier uh = (UDPhdr*)(bp->rptr);
9137dd7cddfSDavid du Colombier
9147dd7cddfSDavid du Colombier /* Put back pseudo header for checksum */
9157dd7cddfSDavid du Colombier uh->Unused = 0;
9167dd7cddfSDavid du Colombier len = nhgets(uh->udplen);
9177dd7cddfSDavid du Colombier hnputs(uh->udpplen, len);
9187dd7cddfSDavid du Colombier
9197dd7cddfSDavid du Colombier if(nhgets(uh->udpcksum)) {
9207dd7cddfSDavid du Colombier cksum = ptclcsum(bp, UDP_IPHDR, len+UDP_PHDRSIZE);
9217dd7cddfSDavid du Colombier if(cksum) {
9227dd7cddfSDavid du Colombier netlog("***** udp: proto cksum!!! %I %ux\n", uh->udpsrc, cksum);
9237dd7cddfSDavid du Colombier good = 0;
9247dd7cddfSDavid du Colombier }
9257dd7cddfSDavid du Colombier }
9267dd7cddfSDavid du Colombier break;
9277dd7cddfSDavid du Colombier }
9287dd7cddfSDavid du Colombier freeb(bp);
9297dd7cddfSDavid du Colombier return good;
9307dd7cddfSDavid du Colombier }
931