123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- #include <u.h>
- #include <libc.h>
- #include <ip.h>
- #include <auth.h>
- #include "ppp.h"
- #include "thwack.h"
- typedef struct Cstate Cstate;
- struct Cstate
- {
- ulong seq;
- Thwack th;
- ulong stats[ThwStats];
- };
- typedef struct Uncstate Uncstate;
- struct Uncstate
- {
- QLock ackl; /* lock for acks sent back to compressor */
- int doack; /* send an ack? */
- int badpacks; /* bad packets seen in a row */
- ulong ackseq; /* packets to ack */
- int ackmask;
- int active; /* 0 => waiting for resetack */
- int resetid; /* id of most recent reset */
- Unthwack ut;
- };
- enum
- {
- ThwAcked = 1UL << 23,
- ThwCompMask = 3UL << 21,
- ThwCompressed = 0UL << 21,
- ThwUncomp = 1UL << 21,
- ThwUncompAdd = 2UL << 21, /* uncompressed, but add to decompression buffer */
- ThwSeqMask = 0x0fffff,
- ThwSmallPack = 96,
- };
- static void *compinit(PPP*);
- static Block* comp(PPP*, ushort, Block*, int*);
- static Block *compresetreq(void*, Block*);
- static void compcompack(void*, Block*);
- static void compfini(void*);
- static void *uncinit(PPP*);
- static Block* uncomp(PPP*, Block*, int *protop, Block**);
- static void uncfini(void*);
- static void uncresetack(void*, Block*);
- Comptype cthwack = {
- compinit,
- comp,
- compresetreq,
- compfini
- };
- Uncomptype uncthwack = {
- uncinit,
- uncomp,
- uncresetack,
- uncfini
- };
- static void *
- compinit(PPP *)
- {
- Cstate *cs;
- cs = mallocz(sizeof(Cstate), 1);
- thwackinit(&cs->th);
- return cs;
- }
- static void
- compfini(void *as)
- {
- Cstate *cs;
- cs = as;
- thwackcleanup(&cs->th);
- free(cs);
- }
- static Block *
- compresetreq(void *as, Block *b)
- {
- Cstate *cs;
- Lcpmsg *m;
- int id;
- cs = as;
- m = (Lcpmsg*)b->rptr;
- id = m->id;
- thwackinit(&cs->th);
- freeb(b);
- netlog("thwack resetreq id=%d \n", id);
- b = alloclcp(Lresetack, id, 4, &m);
- hnputs(m->len, 4);
- return b;
- }
- static Block*
- comp(PPP *ppp, ushort proto, Block *b, int *protop)
- {
- Uncstate *uncs;
- Cstate *cs;
- Block *bb;
- ulong seq, acked;
- int n, nn, mustadd;
- cs = ppp->cstate;
- *protop = 0;
- /* put ack and protocol into b */
- n = BLEN(b);
- if(b->rptr - (2+4) < b->base)
- sysfatal("thwack: not enough header in block");
- acked = 0;
- if(ppp->unctype == &uncthwack){
- uncs = ppp->uncstate;
- qlock(&uncs->ackl);
- if(uncs->doack){
- uncs->doack = 0;
- b->rptr -= 4;
- b->rptr[0] = uncs->ackseq >> 16;
- b->rptr[1] = uncs->ackseq >> 8;
- b->rptr[2] = uncs->ackseq;
- b->rptr[3] = uncs->ackmask;
- acked = ThwAcked;
- }
- qunlock(&uncs->ackl);
- }
- if(proto > 0xff){
- b->rptr -= 2;
- b->rptr[0] = proto >> 8;
- b->rptr[1] = proto;
- }else{
- b->rptr--;
- b->rptr[0] = proto;
- }
- bb = allocb(BLEN(b) + 3);
- seq = cs->seq;
- if(n <= 3){
- mustadd = 0;
- nn = -1;
- }else{
- mustadd = n < ThwSmallPack;
- nn = thwack(&cs->th, mustadd, bb->wptr + 3, n - 3, b, seq, cs->stats);
- }
- if(nn < 0 && !mustadd){
- if(!acked || BLEN(b) + 1 > ppp->mtu){
- freeb(bb);
- if(acked)
- b->rptr += 4;
- if(proto > 0xff)
- b->rptr += 2;
- else
- b->rptr++;
- *protop = proto;
- return b;
- }
- bb->wptr[0] = (ThwUncomp | ThwAcked) >> 16;
- memmove(bb->wptr + 1, b->rptr, BLEN(b));
- bb->wptr += BLEN(b) + 1;
- freeb(b);
- }else{
- cs->seq = (seq + 1) & ThwSeqMask;
- if(nn < 0){
- nn = BLEN(b);
- memmove(bb->wptr + 3, b->rptr, nn);
- seq |= ThwUncompAdd;
- }else
- seq |= ThwCompressed;
- seq |= acked;
- bb->wptr[0] = seq>>16;
- bb->wptr[1] = seq>>8;
- bb->wptr[2] = seq;
- bb->wptr += nn + 3;
- }
- *protop = Pcdata;
- return bb;
- }
- static void *
- uncinit(PPP *)
- {
- Uncstate *s;
- s = mallocz(sizeof(Uncstate), 1);
- s->active = 1;
- unthwackinit(&s->ut);
- return s;
- }
- static void
- uncfini(void *as)
- {
- free(as);
- }
- static void
- uncresetack(void *as, Block *b)
- {
- Uncstate *s;
- Lcpmsg *m;
- s = as;
- m = (Lcpmsg*)b->rptr;
- /*
- * rfc 1962 says we must reset every message
- * we don't since we may have acked some messages
- * which the compressor will use in the future.
- */
- netlog("unthwack resetack id=%d resetid=%d active=%d\n", m->id, s->resetid, s->active);
- if(m->id == (uchar)s->resetid && !s->active){
- s->active = 1;
- unthwackinit(&s->ut);
- }
- }
- static Block*
- uncomp(PPP *ppp, Block *bb, int *protop, Block **reply)
- {
- Lcpmsg *m;
- Cstate *cs;
- Uncstate *uncs;
- Block *b, *r;
- ulong seq, mseq;
- ushort proto;
- uchar mask;
- int n;
- *reply = nil;
- *protop = 0;
- uncs = ppp->uncstate;
- if(BLEN(bb) < 4){
- syslog(0, "ppp", ": thwack: short packet\n");
- freeb(bb);
- return nil;
- }
- if(!uncs->active){
- netlog("unthwack: inactive, killing packet\n");
- freeb(bb);
- r = alloclcp(Lresetreq, uncs->resetid, 4, &m);
- hnputs(m->len, 4);
- *reply = r;
- return nil;
- }
- seq = bb->rptr[0] << 16;
- if((seq & ThwCompMask) == ThwUncomp){
- bb->rptr++;
- b = bb;
- }else{
- seq |= (bb->rptr[1]<<8) | bb->rptr[2];
- bb->rptr += 3;
- if((seq & ThwCompMask) == ThwCompressed){
- b = allocb(ThwMaxBlock);
- n = unthwack(&uncs->ut, b->wptr, ThwMaxBlock, bb->rptr, BLEN(bb), seq & ThwSeqMask);
- freeb(bb);
- if(n < 2){
- syslog(0, "ppp", ": unthwack: short or corrupted packet %d seq=%ld\n", n, seq);
- netlog("unthwack: short or corrupted packet n=%d seq=%ld: %s\n", n, seq, uncs->ut.err);
- freeb(b);
- r = alloclcp(Lresetreq, ++uncs->resetid, 4, &m);
- hnputs(m->len, 4);
- *reply = r;
- uncs->active = 0;
- return nil;
- }
- b->wptr += n;
- }else{
- unthwackadd(&uncs->ut, bb->rptr, BLEN(bb), seq & ThwSeqMask);
- b = bb;
- }
- /*
- * update ack state
- */
- mseq = unthwackstate(&uncs->ut, &mask);
- qlock(&uncs->ackl);
- uncs->ackseq = mseq;
- uncs->ackmask = mask;
- uncs->doack = 1;
- qunlock(&uncs->ackl);
- }
- /*
- * grab the compressed protocol field
- */
- proto = *b->rptr++;
- if((proto & 1) == 0)
- proto = (proto << 8) | *b->rptr++;
- *protop = proto;
- /*
- * decode the ack, and forward to compressor
- */
- if(seq & ThwAcked){
- if(ppp->ctype == &cthwack){
- cs = ppp->cstate;
- mseq = (b->rptr[0]<<16) | (b->rptr[1]<<8) | b->rptr[2];
- mask = b->rptr[3];
- thwackack(&cs->th, mseq, mask);
- }
- b->rptr += 4;
- }
- return b;
- }
|