123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930 |
- #include <u.h>
- #include <libc.h>
- #include <libsec.h>
- #include <ip.h>
- #include <auth.h>
- #include "ppp.h"
- enum {
- HistorySize= 8*1024,
- Cminmatch = 3, /* sintest match possible */
- Chshift = 4, /* nice compromise between space & time */
- Cnhash = 1<<(Chshift*Cminmatch),
- HMASK = Cnhash-1,
- };
- typedef struct Carena Carena;
- struct Carena
- {
- uchar *pos; /* current place, also amount of history filled */
- uchar buf[HistorySize];
- };
- typedef struct Cstate Cstate;
- struct Cstate
- {
- QLock;
- int count;
- int reset; /* compressor has been reset */
- int front; /* move to begining of history */
- ulong sreg; /* output shift reg */
- int bits; /* number of bits in sreg */
- Block *b; /* output block */
- /*
- * state for hashing compressor
- */
- Carena arenas[2];
- Carena *hist;
- Carena *ohist;
- ulong hash[Cnhash];
- int h;
- ulong me;
- ulong split;
- int encrypt;
- uchar startkey[16];
- uchar key[16];
- RC4state rc4key;
- };
- typedef struct Uncstate Uncstate;
- struct Uncstate
- {
- int count; /* packet count - detects missing packets */
- int resetid; /* id of reset requests */
- uchar his[HistorySize];
- int indx; /* current indx in history */
- int size; /* current history size */
- uchar startkey[16];
- uchar key[16];
- RC4state rc4key;
- };
- /* packet flags */
- enum {
- Preset= (1<<15), /* reset history */
- Pfront= (1<<14), /* move packet to front of history */
- Pcompress= (1<<13), /* packet is compressed */
- Pencrypt= (1<<12), /* packet is encrypted */
- };
- enum {
- Lit7, /* seven bit literal */
- Lit8, /* eight bit literal */
- Off6, /* six bit offset */
- Off8, /* eight bit offset */
- Off13, /* thirteen bit offset */
- };
- /* decode first four bits */
- int decode[16] = {
- Lit7,
- Lit7,
- Lit7,
- Lit7,
- Lit7,
- Lit7,
- Lit7,
- Lit7,
- Lit8,
- Lit8,
- Lit8,
- Lit8,
- Off13,
- Off13,
- Off8,
- Off6,
- };
-
- static void *compinit(PPP*);
- static Block* comp(PPP*, ushort, Block*, int*);
- static void comp2(Cstate*, uchar*, int);
- static Block *compresetreq(void*, Block*);
- static void compfini(void*);
- static void complit(Cstate*, int);
- static void compcopy(Cstate*, int, int);
- static void compout(Cstate*, ulong, int);
- static void compfront(Cstate*);
- static void hashcheck(Cstate*);
- static void compreset(Cstate*);
- static int hashit(uchar*);
- static void *uncinit(PPP*);
- static Block* uncomp(PPP*, Block*, int *protop, Block**);
- static Block *uncomp2(Uncstate *s, Block*, ushort);
- static void uncfini(void*);
- static void uncresetack(void*, Block*);
- static int ipcheck(uchar*, int);
- static void hischeck(Uncstate*);
- static void setkey(uchar *key, uchar *startkey);
- Comptype cmppc = {
- compinit,
- comp,
- compresetreq,
- compfini
- };
- Uncomptype uncmppc = {
- uncinit,
- uncomp,
- uncresetack,
- uncfini
- };
- static void *
- compinit(PPP *ppp)
- {
- Cstate *cs;
- cs = mallocz(sizeof(Cstate), 1);
- cs->hist = &cs->arenas[0];
- cs->ohist = &cs->arenas[1];
- compreset(cs);
- /*
- * make reset clear the hash table
- */
- cs->me = ~0;
- compreset(cs);
- cs->reset = 0;
- if(ppp->sendencrypted) {
- cs->encrypt = 1;
- memmove(cs->startkey, ppp->key, 16);
- memmove(cs->key, ppp->key, 16);
- setkey(cs->key, cs->startkey);
- setupRC4state(&cs->rc4key, cs->key, 16);
- }
- return cs;
- }
- static void
- compfini(void *as)
- {
- Cstate *cs;
- cs = as;
- free(cs);
- }
- static Block*
- comp(PPP *ppp, ushort proto, Block *b, int *protop)
- {
- Cstate *s;
- int n, n2;
- ushort count;
- s = ppp->cstate;
- *protop = 0;
- qlock(s);
- /* put protocol into b */
- b->rptr -= 2;
- if(b->rptr < b->base)
- sysfatal("mppc: not enough header in block");
- b->rptr[0] = proto>>8;
- b->rptr[1] = proto;
- n = BLEN(b);
- s->bits = 0;
- s->b = allocb(n*9/8+20);
- s->b->wptr += 2; /* leave room for mppc header */
- comp2(s, b->rptr, n);
-
- /* flush sreg */
- if(s->bits)
- *s->b->wptr++ = s->sreg<<(8-s->bits);
- if(s->b->wptr > s->b->lim)
- sysfatal("mppc: comp: output block overflowed");
- n2 = BLEN(s->b);
- if(n2 > n-2 && !s->encrypt) {
- /* expened and not excrypting so send as a regular packet */
- //netlog("mppc: comp: expanded\n");
- compreset(s);
- freeb(s->b);
- b->rptr += 2;
- qunlock(s);
- *protop = proto;
- return b;
- }
- count = s->count++;
- s->count &= 0xfff;
- if(s->front)
- count |= Pfront;
- if(s->reset)
- count |= Preset;
- s->reset = 0;
- s->front = 0;
- if(n2 > n) {
- //netlog("mppc: comp: expanded\n");
- freeb(s->b);
- /* make room for count */
- compreset(s);
- b->rptr -= 2;
- } else {
- freeb(b);
- b = s->b;
- count |= Pcompress;
- }
- s->b = nil;
- if(s->encrypt) {
- count |= Pencrypt;
- if((count&0xff) == 0xff) {
- //netlog("mppc: comp: changing key\n");
- setkey(s->key, s->startkey);
- setupRC4state(&s->rc4key, s->key, 16);
- rc4(&s->rc4key, s->key, 16);
- setupRC4state(&s->rc4key, s->key, 16);
- } else if(count&Preset)
- setupRC4state(&s->rc4key, s->key, 16);
- rc4(&s->rc4key, b->rptr+2, BLEN(b)-2);
- //netlog("mppc: encrypt %ux\n", count);
- }
- b->rptr[0] = count>>8;
- b->rptr[1] = count;
-
- qunlock(s);
- *protop = Pcdata;
- return b;
- }
- static Block *
- compresetreq(void *as, Block *b)
- {
- Cstate *cs;
- cs = as;
- netlog("mppc: comp: reset request\n");
- qlock(cs);
- compreset(cs);
- qunlock(cs);
- freeb(b);
- return nil;
- }
- static void
- comp2(Cstate *cs, uchar *p, int n)
- {
- Carena *hist, *ohist;
- ulong *hash, me, split, you, last;
- uchar *s, *t, *et, *buf, *obuf, *pos, *opos;
- int i, h, m;
- /*
- * check for wrap
- */
- if(cs->me + n < cs->me)
- compreset(cs);
- if(cs->hist->pos + n > cs->hist->buf + HistorySize)
- compfront(cs);
- hist = cs->hist;
- ohist = cs->ohist;
- hash = cs->hash;
- me = cs->me;
- split = cs->split;
- memmove(hist->pos, p, n);
- p = hist->pos;
- hist->pos = pos = p + n;
- m = Cminmatch;
- if(m > n)
- m = n;
- h = cs->h;
- for(i = 0; i < m; i++) {
- h = (((h)<<Chshift) ^ p[i]) & HMASK;
- last = me + (i - (Cminmatch-1));
- if(last >= split && last != me)
- hash[h] = last;
- }
- buf = hist->buf - split;
- obuf = ohist->buf + HistorySize - split;
- opos = ohist->pos;
- while(p < pos) {
- you = hash[h];
- if(you < split) {
- if(me - you >= HistorySize)
- t = opos;
- else
- t = obuf + you;
- et = opos;
- } else {
- t = buf + you;
- et = pos;
- }
- m = pos - p;
- if(m < et - t)
- et = t + m;
- for(s = p; t < et; t++) {
- if(*s != *t)
- break;
- s++;
- }
- m = s - p;
- if(m < Cminmatch) {
- complit(cs, *p);
- s = p + 1;
- } else
- compcopy(cs, me - you, m);
- for(; p != s; p++) {
- if(p + Cminmatch <= pos) {
- hash[h] = me;
- if(p + Cminmatch < pos)
- h = (((h)<<Chshift) ^ p[Cminmatch]) & HMASK;
- }
- me++;
- }
- }
- cs->h = h;
- cs->me = me;
- }
- static void
- compfront(Cstate *cs)
- {
- Carena *th;
- cs->front = 1;
- th = cs->ohist;
- cs->ohist = cs->hist;
- cs->hist = th;
- cs->hist->pos = cs->hist->buf;
- cs->h = 0;
- cs->me = cs->split + HistorySize;
- cs->split = cs->me;
- }
- static void
- compreset(Cstate *cs)
- {
- ulong me;
- cs->reset = 1;
- me = cs->me;
- if(me + 2 * HistorySize < me){
- me = 0;
- memset(cs->hash, 0, sizeof(cs->hash));
- }
- cs->me = me + 2 * HistorySize;
- cs->split = cs->me;
- cs->hist->pos = cs->hist->buf;
- cs->ohist->pos = cs->ohist->buf;
- }
- static void
- complit(Cstate *s, int c)
- {
- if(c&0x80)
- compout(s, 0x100|(c&0x7f), 9);
- else
- compout(s, c, 8);
- }
- static void
- compcopy(Cstate *s, int off, int len)
- {
- int i;
- ulong mask;
- if(off<64)
- compout(s, 0x3c0|off, 10);
- else if(off<320)
- compout(s, 0xe00|(off-64), 12);
- else
- compout(s, 0xc000|(off-320), 16);
- if(len < 3)
- sysfatal("compcopy: bad len: %d", len);
- if(len == 3)
- compout(s, 0, 1);
- else {
- for(i=3; (1<<i) <= len; i++)
- ;
- mask = (1<<(i-1))-1;
- compout(s, (((1<<(i-2))-1)<<i) | len&mask, (i-1)<<1);
- }
- }
- static void
- compout(Cstate *s, ulong data, int bits)
- {
- ulong sreg;
- sreg = s->sreg;
- sreg <<= bits;
- sreg |= data;
- bits += s->bits;
- while(bits >= 8) {
- *s->b->wptr++ = sreg>>(bits-8);
- bits -= 8;
- }
- s->sreg = sreg;
- s->bits = bits;
- }
- void
- printkey(uchar *key)
- {
- char buf[200], *p;
- int i;
- p = buf;
- for(i=0; i<16; i++)
- p += sprint(p, "%.2ux ", key[i]);
- //netlog("key = %s\n", buf);
- }
- static void *
- uncinit(PPP *ppp)
- {
- Uncstate *s;
- s = mallocz(sizeof(Uncstate), 1);
- s->count = 0xfff; /* count of non existant last packet */
- memmove(s->startkey, ppp->key, 16);
- memmove(s->key, ppp->key, 16);
- setkey(s->key, s->startkey);
- setupRC4state(&s->rc4key, s->key, 16);
- return s;
- }
- static Block*
- uncomp(PPP *ppp, Block *b, int *protop, Block **r)
- {
- Uncstate *s;
- ushort proto;
- ushort count;
- Lcpmsg *m;
- *r = nil;
- *protop = 0;
- s = ppp->uncstate;
- if(BLEN(b) < 2){
- syslog(0, "ppp", ": mppc: short packet\n");
- freeb(b);
- return nil;
- }
- count = nhgets(b->rptr);
- b->rptr += 2;
- b = uncomp2(s, b, count);
- if(b == nil) {
- //netlog("ppp: mppc: reset request\n");
- /* return reset request packet */
- *r = alloclcp(Lresetreq, s->resetid++, 4, &m);
- hnputs(m->len, 4);
- *protop = 0;
- return nil;
- }
- if(BLEN(b) < 2){
- syslog(0, "ppp", ": mppc: short packet\n");
- freeb(b);
- *protop = 0;
- return nil;
- }
- proto = nhgets(b->rptr);
- b->rptr += 2;
- /*
- if(proto == 0x21)
- if(!ipcheck(b->rptr, BLEN(b)))
- hischeck(s);
- */
- *protop = proto;
- return b;
- }
- #define NEXTBYTE sreg = (sreg<<8) | *p++; n--; bits += 8
- int maxoff;
-
- static Block*
- uncomp2(Uncstate *s, Block *b, ushort count)
- {
- int ecount, n, bits, off, len, ones;
- ulong sreg;
- int t;
- uchar *p, c, *hp, *hs, *he, *hq;
- if(count&Preset) {
- //netlog("mppc reset\n");
- s->indx = 0;
- s->size = 0;
- setupRC4state(&s->rc4key, s->key, 16);
- } else {
- ecount = (s->count+1)&0xfff;
- if((count&0xfff) != ecount) {
- netlog("******* bad count - got %ux expected %ux\n", count&0xfff, ecount);
- freeb(b);
- return nil;
- }
- if(count&Pfront) {
- s->indx = 0;
- /* netlog("ppp: mppc: frount flag set\n"); */
- }
- }
- /* update key */
- n = (((count+1)>>8)&0xf) - (((s->count+1)>>8)&0xf);
- if(n < 0)
- n += 16;
- //netlog("mppc count = %ux oldcount %ux n = %d\n", count, s->count, n);
- if(n < 0 || n > 1) {
- syslog(0, "ppp", ": mppc bad count %ux, %ux", count, s->count);
- freeb(b);
- return nil;
- }
- if(n == 1) {
- setkey(s->key, s->startkey);
- setupRC4state(&s->rc4key, s->key, 16);
- rc4(&s->rc4key, s->key, 16);
- setupRC4state(&s->rc4key, s->key, 16);
- }
-
- s->count = count;
- n = BLEN(b);
- p = b->rptr;
- if(count & Pencrypt) {
- //netlog("mppc unencrypt count = %ux\n", count);
- rc4(&s->rc4key, p, n);
- }
- if(!(count & Pcompress)) {
- //netlog("uncompress blen = %d\n", BLEN(b));
- return b;
- }
- bits = 0;
- sreg = 0;
- hs = s->his; /* history start */
- hp = hs+s->indx; /* write pointer in history */
- he = hs+sizeof(s->his); /* hsitory end */
- for(;;) {
- if(bits<4) {
- if(n==0) goto Done;
- NEXTBYTE;
- }
- t = decode[(sreg>>(bits-4))&0xf];
- switch(t) {
- default:
- sysfatal("mppc: bad decode!");
- case Lit7:
- bits -= 1;
- if(bits<7) {
- if(n==0) goto Done;
- NEXTBYTE;
- }
- c = (sreg>>(bits-7))&0x7f;
- bits -= 7;
- if(hp >= he) goto His;
- *hp++ = c;
- /* netlog("\tlit7 %.2ux\n", c); */
- continue;
- case Lit8:
- bits -= 2;
- if(bits<7) {
- if(n==0) goto Eof;
- NEXTBYTE;
- }
- c = 0x80 | ((sreg>>(bits-7))&0x7f);
- bits -= 7;
- if(hp >= he) goto His;
- *hp++ = c;
- /* netlog("\tlit8 %.2ux\n", c); */
- continue;
- case Off6:
- bits -= 4;
- if(bits<6) {
- if(n==0) goto Eof;
- NEXTBYTE;
- }
- off = (sreg>>(bits-6))&0x3f;
- bits -= 6;
- break;
- case Off8:
- bits -= 4;
- if(bits<8) {
- if(n==0) goto Eof;
- NEXTBYTE;
- }
- off = ((sreg>>(bits-8))&0xff)+64;
- bits -= 8;
- break;
- case Off13:
- bits -= 3;
- while(bits<13) {
- if(n==0) goto Eof;
- NEXTBYTE;
- }
- off = ((sreg>>(bits-13))&0x1fff)+320;
- bits -= 13;
- /* netlog("\toff=%d bits = %d sreg = %ux t = %x\n", off, bits, sreg, t); */
- break;
- }
- for(ones=0;;ones++) {
- if(bits == 0) {
- if(n==0) goto Eof;
- NEXTBYTE;
- }
- bits--;
- if(!(sreg&(1<<bits)))
- break;
- }
- if(ones>11) {
- netlog("ppp: mppc: bad length %d\n", ones);
- freeb(b);
- 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 += sizeof(s->his);
- if(hq-hs+len > s->size)
- goto His;
- }
- if(hp+len > he) goto His;
- while(len) {
- *hp++ = *hq++;
- len--;
- }
- }
- Done:
- freeb(b);
- /* build up return block */
- hq = hs+s->indx;
- len = hp-hq;
- b = allocb(len);
- memmove(b->wptr, hq, len);
- b->wptr += len;
- netlog("ppp: mppc: len %d bits = %d n=%d\n", len, bits, n);
-
- s->indx += len;
- if(s->indx > s->size)
- s->size = s->indx;
-
- return b;
- Eof:
- netlog("*****unexpected end of data\n");
- freeb(b);
- return nil;
- His:
- netlog("*****bad history\n");
- freeb(b);
- return nil;
- }
- static void
- uncresetack(void*, Block*)
- {
- }
- static void
- uncfini(void *as)
- {
- Uncstate *s;
-
- s = as;
- free(s);
- }
- static void
- setkey(uchar *key, uchar *startkey)
- {
- uchar pad[40];
- SHAstate *s;
- uchar digest[SHA1dlen];
- s = sha1(startkey, 16, nil, nil);
- memset(pad, 0, 40);
- sha1(pad, 40, nil, s);
- sha1(key, 16, nil, s);
- memset(pad, 0xf2, 40);
- sha1(pad, 40, digest, s);
- memmove(key, digest, 16);
- }
- /* code to check if IP packet looks good */
- typedef struct Iphdr Iphdr;
- struct Iphdr
- {
- uchar vihl; /* Version and header length */
- uchar tos; /* Type of service */
- uchar length[2]; /* packet length */
- uchar id[2]; /* Identification */
- uchar frag[2]; /* Fragment information */
- uchar ttl; /* Time to live */
- uchar proto; /* Protocol */
- uchar cksum[2]; /* Header checksum */
- uchar src[4]; /* Ip source */
- uchar dst[4]; /* Ip destination */
- };
- enum
- {
- QMAX = 64*1024-1,
- IP_TCPPROTO = 6,
- TCP_IPLEN = 8,
- TCP_PHDRSIZE = 12,
- TCP_HDRSIZE = 20,
- TCP_PKT = TCP_IPLEN+TCP_PHDRSIZE,
- };
- enum
- {
- UDP_PHDRSIZE = 12,
- UDP_HDRSIZE = 20,
- UDP_IPHDR = 8,
- IP_UDPPROTO = 17,
- UDP_USEAD = 12,
- UDP_RELSIZE = 16,
- Udprxms = 200,
- Udptickms = 100,
- Udpmaxxmit = 10,
- };
- typedef struct UDPhdr UDPhdr;
- struct UDPhdr
- {
- /* ip header */
- uchar vihl; /* Version and header length */
- uchar tos; /* Type of service */
- uchar length[2]; /* packet length */
- uchar id[2]; /* Identification */
- uchar frag[2]; /* Fragment information */
- uchar Unused;
- uchar udpproto; /* Protocol */
- uchar udpplen[2]; /* Header plus data length */
- uchar udpsrc[4]; /* Ip source */
- uchar udpdst[4]; /* Ip destination */
- /* udp header */
- uchar udpsport[2]; /* Source port */
- uchar udpdport[2]; /* Destination port */
- uchar udplen[2]; /* data length */
- uchar udpcksum[2]; /* Checksum */
- };
- typedef struct TCPhdr TCPhdr;
- struct TCPhdr
- {
- uchar vihl; /* Version and header length */
- uchar tos; /* Type of service */
- uchar length[2]; /* packet length */
- uchar id[2]; /* Identification */
- uchar frag[2]; /* Fragment information */
- uchar Unused;
- uchar proto;
- uchar tcplen[2];
- uchar tcpsrc[4];
- uchar tcpdst[4];
- uchar tcpsport[2];
- uchar tcpdport[2];
- uchar tcpseq[4];
- uchar tcpack[4];
- uchar tcpflag[2];
- uchar tcpwin[2];
- uchar tcpcksum[2];
- uchar tcpurg[2];
- /* Options segment */
- uchar tcpopt[2];
- uchar tcpmss[2];
- };
- static void
- hischeck(Uncstate *s)
- {
- uchar *p;
- Iphdr *iph;
- int len;
- p = s->his;
- netlog("***** history check\n");
- while(p < s->his+s->size) {
- if(p[0] != 0 || p[1] != 0x21) {
- netlog("***** unknown protocol\n");
- return;
- }
- p += 2;
- netlog("off = %ld ", p-s->his);
- iph = (Iphdr*)p;
- len = nhgets(iph->length);
- ipcheck(p, len);
- p += len;
- }
- }
- static int
- ipcheck(uchar *p, int len)
- {
- Iphdr *iph;
- TCPhdr *tcph;
- ushort length;
- UDPhdr *uh;
- Block *bp;
- ushort cksum;
- int good;
- bp = allocb(len);
- memmove(bp->wptr, p, len);
- bp->wptr += len;
- good = 1;
- iph = (Iphdr *)(bp->rptr);
- /* netlog("ppp: mppc: ipcheck %I %I len %d proto %d\n", iph->src, iph->dst, BLEN(bp), iph->proto); */
- if(len != nhgets(iph->length)) {
- netlog("***** bad length! %d %d\n", len, nhgets(iph->length));
- good = 0;
- }
- cksum = ipcsum(&iph->vihl);
- if(cksum) {
- netlog("***** IP proto cksum!!! %I %ux\n", iph->src, cksum);
- good = 0;
- }
- switch(iph->proto) {
- default:
- break;
- case IP_TCPPROTO:
- tcph = (TCPhdr*)(bp->rptr);
- length = nhgets(tcph->length);
- tcph->Unused = 0;
- hnputs(tcph->tcplen, length-TCP_PKT);
- cksum = ptclcsum(bp, TCP_IPLEN, length-TCP_IPLEN);
- if(cksum) {
- netlog("***** bad tcp proto cksum %ux!!!\n", cksum);
- good = 0;
- }
- break;
- case IP_UDPPROTO:
- uh = (UDPhdr*)(bp->rptr);
- /* Put back pseudo header for checksum */
- uh->Unused = 0;
- len = nhgets(uh->udplen);
- hnputs(uh->udpplen, len);
- if(nhgets(uh->udpcksum)) {
- cksum = ptclcsum(bp, UDP_IPHDR, len+UDP_PHDRSIZE);
- if(cksum) {
- netlog("***** udp: proto cksum!!! %I %ux\n", uh->udpsrc, cksum);
- good = 0;
- }
- }
- break;
- }
- freeb(bp);
- return good;
- }
|