mppc.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <libsec.h>
  4. #include <ip.h>
  5. #include <auth.h>
  6. #include "ppp.h"
  7. enum {
  8. HistorySize= 8*1024,
  9. Cminmatch = 3, /* sintest match possible */
  10. Chshift = 4, /* nice compromise between space & time */
  11. Cnhash = 1<<(Chshift*Cminmatch),
  12. HMASK = Cnhash-1,
  13. };
  14. typedef struct Carena Carena;
  15. struct Carena
  16. {
  17. uchar *pos; /* current place, also amount of history filled */
  18. uchar buf[HistorySize];
  19. };
  20. typedef struct Cstate Cstate;
  21. struct Cstate
  22. {
  23. QLock;
  24. int count;
  25. int reset; /* compressor has been reset */
  26. int front; /* move to begining of history */
  27. ulong sreg; /* output shift reg */
  28. int bits; /* number of bits in sreg */
  29. Block *b; /* output block */
  30. /*
  31. * state for hashing compressor
  32. */
  33. Carena arenas[2];
  34. Carena *hist;
  35. Carena *ohist;
  36. ulong hash[Cnhash];
  37. int h;
  38. ulong me;
  39. ulong split;
  40. int encrypt;
  41. uchar startkey[16];
  42. uchar key[16];
  43. RC4state rc4key;
  44. };
  45. typedef struct Uncstate Uncstate;
  46. struct Uncstate
  47. {
  48. int count; /* packet count - detects missing packets */
  49. int resetid; /* id of reset requests */
  50. uchar his[HistorySize];
  51. int indx; /* current indx in history */
  52. int size; /* current history size */
  53. uchar startkey[16];
  54. uchar key[16];
  55. RC4state rc4key;
  56. };
  57. /* packet flags */
  58. enum {
  59. Preset= (1<<15), /* reset history */
  60. Pfront= (1<<14), /* move packet to front of history */
  61. Pcompress= (1<<13), /* packet is compressed */
  62. Pencrypt= (1<<12), /* packet is encrypted */
  63. };
  64. enum {
  65. Lit7, /* seven bit literal */
  66. Lit8, /* eight bit literal */
  67. Off6, /* six bit offset */
  68. Off8, /* eight bit offset */
  69. Off13, /* thirteen bit offset */
  70. };
  71. /* decode first four bits */
  72. int decode[16] = {
  73. Lit7,
  74. Lit7,
  75. Lit7,
  76. Lit7,
  77. Lit7,
  78. Lit7,
  79. Lit7,
  80. Lit7,
  81. Lit8,
  82. Lit8,
  83. Lit8,
  84. Lit8,
  85. Off13,
  86. Off13,
  87. Off8,
  88. Off6,
  89. };
  90. static void *compinit(PPP*);
  91. static Block* comp(PPP*, ushort, Block*, int*);
  92. static void comp2(Cstate*, uchar*, int);
  93. static Block *compresetreq(void*, Block*);
  94. static void compfini(void*);
  95. static void complit(Cstate*, int);
  96. static void compcopy(Cstate*, int, int);
  97. static void compout(Cstate*, ulong, int);
  98. static void compfront(Cstate*);
  99. static void hashcheck(Cstate*);
  100. static void compreset(Cstate*);
  101. static int hashit(uchar*);
  102. static void *uncinit(PPP*);
  103. static Block* uncomp(PPP*, Block*, int *protop, Block**);
  104. static Block *uncomp2(Uncstate *s, Block*, ushort);
  105. static void uncfini(void*);
  106. static void uncresetack(void*, Block*);
  107. static int ipcheck(uchar*, int);
  108. static void hischeck(Uncstate*);
  109. static void setkey(uchar *key, uchar *startkey);
  110. Comptype cmppc = {
  111. compinit,
  112. comp,
  113. compresetreq,
  114. compfini
  115. };
  116. Uncomptype uncmppc = {
  117. uncinit,
  118. uncomp,
  119. uncresetack,
  120. uncfini
  121. };
  122. static void *
  123. compinit(PPP *ppp)
  124. {
  125. Cstate *cs;
  126. cs = mallocz(sizeof(Cstate), 1);
  127. cs->hist = &cs->arenas[0];
  128. cs->ohist = &cs->arenas[1];
  129. compreset(cs);
  130. /*
  131. * make reset clear the hash table
  132. */
  133. cs->me = ~0;
  134. compreset(cs);
  135. cs->reset = 0;
  136. if(ppp->sendencrypted) {
  137. cs->encrypt = 1;
  138. memmove(cs->startkey, ppp->key, 16);
  139. memmove(cs->key, ppp->key, 16);
  140. setkey(cs->key, cs->startkey);
  141. setupRC4state(&cs->rc4key, cs->key, 16);
  142. }
  143. return cs;
  144. }
  145. static void
  146. compfini(void *as)
  147. {
  148. Cstate *cs;
  149. cs = as;
  150. free(cs);
  151. }
  152. static Block*
  153. comp(PPP *ppp, ushort proto, Block *b, int *protop)
  154. {
  155. Cstate *s;
  156. int n, n2;
  157. ushort count;
  158. s = ppp->cstate;
  159. *protop = 0;
  160. qlock(s);
  161. /* put protocol into b */
  162. b->rptr -= 2;
  163. if(b->rptr < b->base)
  164. sysfatal("mppc: not enough header in block");
  165. b->rptr[0] = proto>>8;
  166. b->rptr[1] = proto;
  167. n = BLEN(b);
  168. s->bits = 0;
  169. s->b = allocb(n*9/8+20);
  170. s->b->wptr += 2; /* leave room for mppc header */
  171. comp2(s, b->rptr, n);
  172. /* flush sreg */
  173. if(s->bits)
  174. *s->b->wptr++ = s->sreg<<(8-s->bits);
  175. if(s->b->wptr > s->b->lim)
  176. sysfatal("mppc: comp: output block overflowed");
  177. n2 = BLEN(s->b);
  178. if(n2 > n-2 && !s->encrypt) {
  179. /* expened and not excrypting so send as a regular packet */
  180. //netlog("mppc: comp: expanded\n");
  181. compreset(s);
  182. freeb(s->b);
  183. b->rptr += 2;
  184. qunlock(s);
  185. *protop = proto;
  186. return b;
  187. }
  188. count = s->count++;
  189. s->count &= 0xfff;
  190. if(s->front)
  191. count |= Pfront;
  192. if(s->reset)
  193. count |= Preset;
  194. s->reset = 0;
  195. s->front = 0;
  196. if(n2 > n) {
  197. //netlog("mppc: comp: expanded\n");
  198. freeb(s->b);
  199. /* make room for count */
  200. compreset(s);
  201. b->rptr -= 2;
  202. } else {
  203. freeb(b);
  204. b = s->b;
  205. count |= Pcompress;
  206. }
  207. s->b = nil;
  208. if(s->encrypt) {
  209. count |= Pencrypt;
  210. if((count&0xff) == 0xff) {
  211. //netlog("mppc: comp: changing key\n");
  212. setkey(s->key, s->startkey);
  213. setupRC4state(&s->rc4key, s->key, 16);
  214. rc4(&s->rc4key, s->key, 16);
  215. setupRC4state(&s->rc4key, s->key, 16);
  216. } else if(count&Preset)
  217. setupRC4state(&s->rc4key, s->key, 16);
  218. rc4(&s->rc4key, b->rptr+2, BLEN(b)-2);
  219. //netlog("mppc: encrypt %ux\n", count);
  220. }
  221. b->rptr[0] = count>>8;
  222. b->rptr[1] = count;
  223. qunlock(s);
  224. *protop = Pcdata;
  225. return b;
  226. }
  227. static Block *
  228. compresetreq(void *as, Block *b)
  229. {
  230. Cstate *cs;
  231. cs = as;
  232. netlog("mppc: comp: reset request\n");
  233. qlock(cs);
  234. compreset(cs);
  235. qunlock(cs);
  236. freeb(b);
  237. return nil;
  238. }
  239. static void
  240. comp2(Cstate *cs, uchar *p, int n)
  241. {
  242. Carena *hist, *ohist;
  243. ulong *hash, me, split, you, last;
  244. uchar *s, *t, *et, *buf, *obuf, *pos, *opos;
  245. int i, h, m;
  246. /*
  247. * check for wrap
  248. */
  249. if(cs->me + n < cs->me)
  250. compreset(cs);
  251. if(cs->hist->pos + n > cs->hist->buf + HistorySize)
  252. compfront(cs);
  253. hist = cs->hist;
  254. ohist = cs->ohist;
  255. hash = cs->hash;
  256. me = cs->me;
  257. split = cs->split;
  258. memmove(hist->pos, p, n);
  259. p = hist->pos;
  260. hist->pos = pos = p + n;
  261. m = Cminmatch;
  262. if(m > n)
  263. m = n;
  264. h = cs->h;
  265. for(i = 0; i < m; i++) {
  266. h = (((h)<<Chshift) ^ p[i]) & HMASK;
  267. last = me + (i - (Cminmatch-1));
  268. if(last >= split && last != me)
  269. hash[h] = last;
  270. }
  271. buf = hist->buf - split;
  272. obuf = ohist->buf + HistorySize - split;
  273. opos = ohist->pos;
  274. while(p < pos) {
  275. you = hash[h];
  276. if(you < split) {
  277. if(me - you >= HistorySize)
  278. t = opos;
  279. else
  280. t = obuf + you;
  281. et = opos;
  282. } else {
  283. t = buf + you;
  284. et = pos;
  285. }
  286. m = pos - p;
  287. if(m < et - t)
  288. et = t + m;
  289. for(s = p; t < et; t++) {
  290. if(*s != *t)
  291. break;
  292. s++;
  293. }
  294. m = s - p;
  295. if(m < Cminmatch) {
  296. complit(cs, *p);
  297. s = p + 1;
  298. } else
  299. compcopy(cs, me - you, m);
  300. for(; p != s; p++) {
  301. if(p + Cminmatch <= pos) {
  302. hash[h] = me;
  303. if(p + Cminmatch < pos)
  304. h = (((h)<<Chshift) ^ p[Cminmatch]) & HMASK;
  305. }
  306. me++;
  307. }
  308. }
  309. cs->h = h;
  310. cs->me = me;
  311. }
  312. static void
  313. compfront(Cstate *cs)
  314. {
  315. Carena *th;
  316. cs->front = 1;
  317. th = cs->ohist;
  318. cs->ohist = cs->hist;
  319. cs->hist = th;
  320. cs->hist->pos = cs->hist->buf;
  321. cs->h = 0;
  322. cs->me = cs->split + HistorySize;
  323. cs->split = cs->me;
  324. }
  325. static void
  326. compreset(Cstate *cs)
  327. {
  328. ulong me;
  329. cs->reset = 1;
  330. me = cs->me;
  331. if(me + 2 * HistorySize < me){
  332. me = 0;
  333. memset(cs->hash, 0, sizeof(cs->hash));
  334. }
  335. cs->me = me + 2 * HistorySize;
  336. cs->split = cs->me;
  337. cs->hist->pos = cs->hist->buf;
  338. cs->ohist->pos = cs->ohist->buf;
  339. }
  340. static void
  341. complit(Cstate *s, int c)
  342. {
  343. if(c&0x80)
  344. compout(s, 0x100|(c&0x7f), 9);
  345. else
  346. compout(s, c, 8);
  347. }
  348. static void
  349. compcopy(Cstate *s, int off, int len)
  350. {
  351. int i;
  352. ulong mask;
  353. if(off<64)
  354. compout(s, 0x3c0|off, 10);
  355. else if(off<320)
  356. compout(s, 0xe00|(off-64), 12);
  357. else
  358. compout(s, 0xc000|(off-320), 16);
  359. if(len < 3)
  360. sysfatal("compcopy: bad len: %d", len);
  361. if(len == 3)
  362. compout(s, 0, 1);
  363. else {
  364. for(i=3; (1<<i) <= len; i++)
  365. ;
  366. mask = (1<<(i-1))-1;
  367. compout(s, (((1<<(i-2))-1)<<i) | len&mask, (i-1)<<1);
  368. }
  369. }
  370. static void
  371. compout(Cstate *s, ulong data, int bits)
  372. {
  373. ulong sreg;
  374. sreg = s->sreg;
  375. sreg <<= bits;
  376. sreg |= data;
  377. bits += s->bits;
  378. while(bits >= 8) {
  379. *s->b->wptr++ = sreg>>(bits-8);
  380. bits -= 8;
  381. }
  382. s->sreg = sreg;
  383. s->bits = bits;
  384. }
  385. void
  386. printkey(uchar *key)
  387. {
  388. char buf[200], *p;
  389. int i;
  390. p = buf;
  391. for(i=0; i<16; i++)
  392. p += sprint(p, "%.2ux ", key[i]);
  393. //netlog("key = %s\n", buf);
  394. }
  395. static void *
  396. uncinit(PPP *ppp)
  397. {
  398. Uncstate *s;
  399. s = mallocz(sizeof(Uncstate), 1);
  400. s->count = 0xfff; /* count of non existant last packet */
  401. memmove(s->startkey, ppp->key, 16);
  402. memmove(s->key, ppp->key, 16);
  403. setkey(s->key, s->startkey);
  404. setupRC4state(&s->rc4key, s->key, 16);
  405. return s;
  406. }
  407. static Block*
  408. uncomp(PPP *ppp, Block *b, int *protop, Block **r)
  409. {
  410. Uncstate *s;
  411. ushort proto;
  412. ushort count;
  413. Lcpmsg *m;
  414. *r = nil;
  415. *protop = 0;
  416. s = ppp->uncstate;
  417. if(BLEN(b) < 2){
  418. syslog(0, "ppp", ": mppc: short packet\n");
  419. freeb(b);
  420. return nil;
  421. }
  422. count = nhgets(b->rptr);
  423. b->rptr += 2;
  424. b = uncomp2(s, b, count);
  425. if(b == nil) {
  426. //netlog("ppp: mppc: reset request\n");
  427. /* return reset request packet */
  428. *r = alloclcp(Lresetreq, s->resetid++, 4, &m);
  429. hnputs(m->len, 4);
  430. *protop = 0;
  431. return nil;
  432. }
  433. if(BLEN(b) < 2){
  434. syslog(0, "ppp", ": mppc: short packet\n");
  435. freeb(b);
  436. *protop = 0;
  437. return nil;
  438. }
  439. proto = nhgets(b->rptr);
  440. b->rptr += 2;
  441. /*
  442. if(proto == 0x21)
  443. if(!ipcheck(b->rptr, BLEN(b)))
  444. hischeck(s);
  445. */
  446. *protop = proto;
  447. return b;
  448. }
  449. #define NEXTBYTE sreg = (sreg<<8) | *p++; n--; bits += 8
  450. int maxoff;
  451. static Block*
  452. uncomp2(Uncstate *s, Block *b, ushort count)
  453. {
  454. int ecount, n, bits, off, len, ones;
  455. ulong sreg;
  456. int t;
  457. uchar *p, c, *hp, *hs, *he, *hq;
  458. if(count&Preset) {
  459. //netlog("mppc reset\n");
  460. s->indx = 0;
  461. s->size = 0;
  462. setupRC4state(&s->rc4key, s->key, 16);
  463. } else {
  464. ecount = (s->count+1)&0xfff;
  465. if((count&0xfff) != ecount) {
  466. netlog("******* bad count - got %ux expected %ux\n", count&0xfff, ecount);
  467. freeb(b);
  468. return nil;
  469. }
  470. if(count&Pfront) {
  471. s->indx = 0;
  472. /* netlog("ppp: mppc: frount flag set\n"); */
  473. }
  474. }
  475. /* update key */
  476. n = (((count+1)>>8)&0xf) - (((s->count+1)>>8)&0xf);
  477. if(n < 0)
  478. n += 16;
  479. //netlog("mppc count = %ux oldcount %ux n = %d\n", count, s->count, n);
  480. if(n < 0 || n > 1) {
  481. syslog(0, "ppp", ": mppc bad count %ux, %ux", count, s->count);
  482. freeb(b);
  483. return nil;
  484. }
  485. if(n == 1) {
  486. setkey(s->key, s->startkey);
  487. setupRC4state(&s->rc4key, s->key, 16);
  488. rc4(&s->rc4key, s->key, 16);
  489. setupRC4state(&s->rc4key, s->key, 16);
  490. }
  491. s->count = count;
  492. n = BLEN(b);
  493. p = b->rptr;
  494. if(count & Pencrypt) {
  495. //netlog("mppc unencrypt count = %ux\n", count);
  496. rc4(&s->rc4key, p, n);
  497. }
  498. if(!(count & Pcompress)) {
  499. //netlog("uncompress blen = %d\n", BLEN(b));
  500. return b;
  501. }
  502. bits = 0;
  503. sreg = 0;
  504. hs = s->his; /* history start */
  505. hp = hs+s->indx; /* write pointer in history */
  506. he = hs+sizeof(s->his); /* hsitory end */
  507. for(;;) {
  508. if(bits<4) {
  509. if(n==0) goto Done;
  510. NEXTBYTE;
  511. }
  512. t = decode[(sreg>>(bits-4))&0xf];
  513. switch(t) {
  514. default:
  515. sysfatal("mppc: bad decode!");
  516. case Lit7:
  517. bits -= 1;
  518. if(bits<7) {
  519. if(n==0) goto Done;
  520. NEXTBYTE;
  521. }
  522. c = (sreg>>(bits-7))&0x7f;
  523. bits -= 7;
  524. if(hp >= he) goto His;
  525. *hp++ = c;
  526. /* netlog("\tlit7 %.2ux\n", c); */
  527. continue;
  528. case Lit8:
  529. bits -= 2;
  530. if(bits<7) {
  531. if(n==0) goto Eof;
  532. NEXTBYTE;
  533. }
  534. c = 0x80 | ((sreg>>(bits-7))&0x7f);
  535. bits -= 7;
  536. if(hp >= he) goto His;
  537. *hp++ = c;
  538. /* netlog("\tlit8 %.2ux\n", c); */
  539. continue;
  540. case Off6:
  541. bits -= 4;
  542. if(bits<6) {
  543. if(n==0) goto Eof;
  544. NEXTBYTE;
  545. }
  546. off = (sreg>>(bits-6))&0x3f;
  547. bits -= 6;
  548. break;
  549. case Off8:
  550. bits -= 4;
  551. if(bits<8) {
  552. if(n==0) goto Eof;
  553. NEXTBYTE;
  554. }
  555. off = ((sreg>>(bits-8))&0xff)+64;
  556. bits -= 8;
  557. break;
  558. case Off13:
  559. bits -= 3;
  560. while(bits<13) {
  561. if(n==0) goto Eof;
  562. NEXTBYTE;
  563. }
  564. off = ((sreg>>(bits-13))&0x1fff)+320;
  565. bits -= 13;
  566. /* netlog("\toff=%d bits = %d sreg = %ux t = %x\n", off, bits, sreg, t); */
  567. break;
  568. }
  569. for(ones=0;;ones++) {
  570. if(bits == 0) {
  571. if(n==0) goto Eof;
  572. NEXTBYTE;
  573. }
  574. bits--;
  575. if(!(sreg&(1<<bits)))
  576. break;
  577. }
  578. if(ones>11) {
  579. netlog("ppp: mppc: bad length %d\n", ones);
  580. freeb(b);
  581. return nil;
  582. }
  583. if(ones == 0) {
  584. len = 3;
  585. } else {
  586. ones++;
  587. while(bits<ones) {
  588. if(n==0) goto Eof;
  589. NEXTBYTE;
  590. }
  591. len = (1<<ones) | ((sreg>>(bits-ones))&((1<<ones)-1));
  592. bits -= ones;
  593. }
  594. hq = hp-off;
  595. if(hq < hs) {
  596. hq += sizeof(s->his);
  597. if(hq-hs+len > s->size)
  598. goto His;
  599. }
  600. if(hp+len > he) goto His;
  601. while(len) {
  602. *hp++ = *hq++;
  603. len--;
  604. }
  605. }
  606. Done:
  607. freeb(b);
  608. /* build up return block */
  609. hq = hs+s->indx;
  610. len = hp-hq;
  611. b = allocb(len);
  612. memmove(b->wptr, hq, len);
  613. b->wptr += len;
  614. netlog("ppp: mppc: len %d bits = %d n=%d\n", len, bits, n);
  615. s->indx += len;
  616. if(s->indx > s->size)
  617. s->size = s->indx;
  618. return b;
  619. Eof:
  620. netlog("*****unexpected end of data\n");
  621. freeb(b);
  622. return nil;
  623. His:
  624. netlog("*****bad history\n");
  625. freeb(b);
  626. return nil;
  627. }
  628. static void
  629. uncresetack(void*, Block*)
  630. {
  631. }
  632. static void
  633. uncfini(void *as)
  634. {
  635. Uncstate *s;
  636. s = as;
  637. free(s);
  638. }
  639. static void
  640. setkey(uchar *key, uchar *startkey)
  641. {
  642. uchar pad[40];
  643. SHAstate *s;
  644. uchar digest[SHA1dlen];
  645. s = sha1(startkey, 16, nil, nil);
  646. memset(pad, 0, 40);
  647. sha1(pad, 40, nil, s);
  648. sha1(key, 16, nil, s);
  649. memset(pad, 0xf2, 40);
  650. sha1(pad, 40, digest, s);
  651. memmove(key, digest, 16);
  652. }
  653. /* code to check if IP packet looks good */
  654. typedef struct Iphdr Iphdr;
  655. struct Iphdr
  656. {
  657. uchar vihl; /* Version and header length */
  658. uchar tos; /* Type of service */
  659. uchar length[2]; /* packet length */
  660. uchar id[2]; /* Identification */
  661. uchar frag[2]; /* Fragment information */
  662. uchar ttl; /* Time to live */
  663. uchar proto; /* Protocol */
  664. uchar cksum[2]; /* Header checksum */
  665. uchar src[4]; /* Ip source */
  666. uchar dst[4]; /* Ip destination */
  667. };
  668. enum
  669. {
  670. QMAX = 64*1024-1,
  671. IP_TCPPROTO = 6,
  672. TCP_IPLEN = 8,
  673. TCP_PHDRSIZE = 12,
  674. TCP_HDRSIZE = 20,
  675. TCP_PKT = TCP_IPLEN+TCP_PHDRSIZE,
  676. };
  677. enum
  678. {
  679. UDP_PHDRSIZE = 12,
  680. UDP_HDRSIZE = 20,
  681. UDP_IPHDR = 8,
  682. IP_UDPPROTO = 17,
  683. UDP_USEAD = 12,
  684. UDP_RELSIZE = 16,
  685. Udprxms = 200,
  686. Udptickms = 100,
  687. Udpmaxxmit = 10,
  688. };
  689. typedef struct UDPhdr UDPhdr;
  690. struct UDPhdr
  691. {
  692. /* ip header */
  693. uchar vihl; /* Version and header length */
  694. uchar tos; /* Type of service */
  695. uchar length[2]; /* packet length */
  696. uchar id[2]; /* Identification */
  697. uchar frag[2]; /* Fragment information */
  698. uchar Unused;
  699. uchar udpproto; /* Protocol */
  700. uchar udpplen[2]; /* Header plus data length */
  701. uchar udpsrc[4]; /* Ip source */
  702. uchar udpdst[4]; /* Ip destination */
  703. /* udp header */
  704. uchar udpsport[2]; /* Source port */
  705. uchar udpdport[2]; /* Destination port */
  706. uchar udplen[2]; /* data length */
  707. uchar udpcksum[2]; /* Checksum */
  708. };
  709. typedef struct TCPhdr TCPhdr;
  710. struct TCPhdr
  711. {
  712. uchar vihl; /* Version and header length */
  713. uchar tos; /* Type of service */
  714. uchar length[2]; /* packet length */
  715. uchar id[2]; /* Identification */
  716. uchar frag[2]; /* Fragment information */
  717. uchar Unused;
  718. uchar proto;
  719. uchar tcplen[2];
  720. uchar tcpsrc[4];
  721. uchar tcpdst[4];
  722. uchar tcpsport[2];
  723. uchar tcpdport[2];
  724. uchar tcpseq[4];
  725. uchar tcpack[4];
  726. uchar tcpflag[2];
  727. uchar tcpwin[2];
  728. uchar tcpcksum[2];
  729. uchar tcpurg[2];
  730. /* Options segment */
  731. uchar tcpopt[2];
  732. uchar tcpmss[2];
  733. };
  734. static void
  735. hischeck(Uncstate *s)
  736. {
  737. uchar *p;
  738. Iphdr *iph;
  739. int len;
  740. p = s->his;
  741. netlog("***** history check\n");
  742. while(p < s->his+s->size) {
  743. if(p[0] != 0 || p[1] != 0x21) {
  744. netlog("***** unknown protocol\n");
  745. return;
  746. }
  747. p += 2;
  748. netlog("off = %ld ", p-s->his);
  749. iph = (Iphdr*)p;
  750. len = nhgets(iph->length);
  751. ipcheck(p, len);
  752. p += len;
  753. }
  754. }
  755. static int
  756. ipcheck(uchar *p, int len)
  757. {
  758. Iphdr *iph;
  759. TCPhdr *tcph;
  760. ushort length;
  761. UDPhdr *uh;
  762. Block *bp;
  763. ushort cksum;
  764. int good;
  765. bp = allocb(len);
  766. memmove(bp->wptr, p, len);
  767. bp->wptr += len;
  768. good = 1;
  769. iph = (Iphdr *)(bp->rptr);
  770. /* netlog("ppp: mppc: ipcheck %I %I len %d proto %d\n", iph->src, iph->dst, BLEN(bp), iph->proto); */
  771. if(len != nhgets(iph->length)) {
  772. netlog("***** bad length! %d %d\n", len, nhgets(iph->length));
  773. good = 0;
  774. }
  775. cksum = ipcsum(&iph->vihl);
  776. if(cksum) {
  777. netlog("***** IP proto cksum!!! %I %ux\n", iph->src, cksum);
  778. good = 0;
  779. }
  780. switch(iph->proto) {
  781. default:
  782. break;
  783. case IP_TCPPROTO:
  784. tcph = (TCPhdr*)(bp->rptr);
  785. length = nhgets(tcph->length);
  786. tcph->Unused = 0;
  787. hnputs(tcph->tcplen, length-TCP_PKT);
  788. cksum = ptclcsum(bp, TCP_IPLEN, length-TCP_IPLEN);
  789. if(cksum) {
  790. netlog("***** bad tcp proto cksum %ux!!!\n", cksum);
  791. good = 0;
  792. }
  793. break;
  794. case IP_UDPPROTO:
  795. uh = (UDPhdr*)(bp->rptr);
  796. /* Put back pseudo header for checksum */
  797. uh->Unused = 0;
  798. len = nhgets(uh->udplen);
  799. hnputs(uh->udpplen, len);
  800. if(nhgets(uh->udpcksum)) {
  801. cksum = ptclcsum(bp, UDP_IPHDR, len+UDP_PHDRSIZE);
  802. if(cksum) {
  803. netlog("***** udp: proto cksum!!! %I %ux\n", uh->udpsrc, cksum);
  804. good = 0;
  805. }
  806. }
  807. break;
  808. }
  809. freeb(bp);
  810. return good;
  811. }