mppc.c 17 KB

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