thw.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  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 <ip.h>
  12. #include <auth.h>
  13. #include "ppp.h"
  14. #include "thwack.h"
  15. typedef struct Cstate Cstate;
  16. struct Cstate
  17. {
  18. uint32_t seq;
  19. Thwack th;
  20. uint32_t stats[ThwStats];
  21. };
  22. typedef struct Uncstate Uncstate;
  23. struct Uncstate
  24. {
  25. QLock ackl; /* lock for acks sent back to compressor */
  26. int doack; /* send an ack? */
  27. int badpacks; /* bad packets seen in a row */
  28. uint32_t ackseq; /* packets to ack */
  29. int ackmask;
  30. int active; /* 0 => waiting for resetack */
  31. int resetid; /* id of most recent reset */
  32. Unthwack ut;
  33. };
  34. enum
  35. {
  36. ThwAcked = 1UL << 23,
  37. ThwCompMask = 3UL << 21,
  38. ThwCompressed = 0UL << 21,
  39. ThwUncomp = 1UL << 21,
  40. ThwUncompAdd = 2UL << 21, /* uncompressed, but add to decompression buffer */
  41. ThwSeqMask = 0x0fffff,
  42. ThwSmallPack = 96,
  43. };
  44. static void *compinit(PPP*);
  45. static Block* comp(PPP*, uint16_t, Block*, int*);
  46. static Block *compresetreq(void*, Block*);
  47. static void compcompack(void*, Block*);
  48. static void compfini(void*);
  49. static void *uncinit(PPP*);
  50. static Block* uncomp(PPP*, Block*, int *protop, Block**);
  51. static void uncfini(void*);
  52. static void uncresetack(void*, Block*);
  53. Comptype cthwack = {
  54. compinit,
  55. comp,
  56. compresetreq,
  57. compfini
  58. };
  59. Uncomptype uncthwack = {
  60. uncinit,
  61. uncomp,
  62. uncresetack,
  63. uncfini
  64. };
  65. static void *
  66. compinit(PPP *p)
  67. {
  68. Cstate *cs;
  69. cs = mallocz(sizeof(Cstate), 1);
  70. thwackinit(&cs->th);
  71. return cs;
  72. }
  73. static void
  74. compfini(void *as)
  75. {
  76. Cstate *cs;
  77. cs = as;
  78. thwackcleanup(&cs->th);
  79. free(cs);
  80. }
  81. static Block *
  82. compresetreq(void *as, Block *b)
  83. {
  84. Cstate *cs;
  85. Lcpmsg *m;
  86. int id;
  87. cs = as;
  88. m = (Lcpmsg*)b->rptr;
  89. id = m->id;
  90. thwackinit(&cs->th);
  91. freeb(b);
  92. netlog("thwack resetreq id=%d \n", id);
  93. b = alloclcp(Lresetack, id, 4, &m);
  94. hnputs(m->len, 4);
  95. return b;
  96. }
  97. static Block*
  98. comp(PPP *ppp, uint16_t proto, Block *b, int *protop)
  99. {
  100. Uncstate *uncs;
  101. Cstate *cs;
  102. Block *bb;
  103. uint32_t seq, acked;
  104. int n, nn, mustadd;
  105. cs = ppp->cstate;
  106. *protop = 0;
  107. /* put ack and protocol into b */
  108. n = BLEN(b);
  109. if(b->rptr - (2+4) < b->base)
  110. sysfatal("thwack: not enough header in block");
  111. acked = 0;
  112. if(ppp->unctype == &uncthwack){
  113. uncs = ppp->uncstate;
  114. qlock(&uncs->ackl);
  115. if(uncs->doack){
  116. uncs->doack = 0;
  117. b->rptr -= 4;
  118. b->rptr[0] = uncs->ackseq >> 16;
  119. b->rptr[1] = uncs->ackseq >> 8;
  120. b->rptr[2] = uncs->ackseq;
  121. b->rptr[3] = uncs->ackmask;
  122. acked = ThwAcked;
  123. }
  124. qunlock(&uncs->ackl);
  125. }
  126. if(proto > 0xff){
  127. b->rptr -= 2;
  128. b->rptr[0] = proto >> 8;
  129. b->rptr[1] = proto;
  130. }else{
  131. b->rptr--;
  132. b->rptr[0] = proto;
  133. }
  134. bb = allocb(BLEN(b) + 3);
  135. seq = cs->seq;
  136. if(n <= 3){
  137. mustadd = 0;
  138. nn = -1;
  139. }else{
  140. mustadd = n < ThwSmallPack;
  141. nn = thwack(&cs->th, mustadd, bb->wptr + 3, n - 3, b, seq, cs->stats);
  142. }
  143. if(nn < 0 && !mustadd){
  144. if(!acked || BLEN(b) + 1 > ppp->mtu){
  145. freeb(bb);
  146. if(acked)
  147. b->rptr += 4;
  148. if(proto > 0xff)
  149. b->rptr += 2;
  150. else
  151. b->rptr++;
  152. *protop = proto;
  153. return b;
  154. }
  155. bb->wptr[0] = (ThwUncomp | ThwAcked) >> 16;
  156. memmove(bb->wptr + 1, b->rptr, BLEN(b));
  157. bb->wptr += BLEN(b) + 1;
  158. freeb(b);
  159. }else{
  160. cs->seq = (seq + 1) & ThwSeqMask;
  161. if(nn < 0){
  162. nn = BLEN(b);
  163. memmove(bb->wptr + 3, b->rptr, nn);
  164. seq |= ThwUncompAdd;
  165. }else
  166. seq |= ThwCompressed;
  167. seq |= acked;
  168. bb->wptr[0] = seq>>16;
  169. bb->wptr[1] = seq>>8;
  170. bb->wptr[2] = seq;
  171. bb->wptr += nn + 3;
  172. }
  173. *protop = Pcdata;
  174. return bb;
  175. }
  176. static void *
  177. uncinit(PPP *p)
  178. {
  179. Uncstate *s;
  180. s = mallocz(sizeof(Uncstate), 1);
  181. s->active = 1;
  182. unthwackinit(&s->ut);
  183. return s;
  184. }
  185. static void
  186. uncfini(void *as)
  187. {
  188. free(as);
  189. }
  190. static void
  191. uncresetack(void *as, Block *b)
  192. {
  193. Uncstate *s;
  194. Lcpmsg *m;
  195. s = as;
  196. m = (Lcpmsg*)b->rptr;
  197. /*
  198. * rfc 1962 says we must reset every message
  199. * we don't since we may have acked some messages
  200. * which the compressor will use in the future.
  201. */
  202. netlog("unthwack resetack id=%d resetid=%d active=%d\n", m->id, s->resetid, s->active);
  203. if(m->id == (uint8_t)s->resetid && !s->active){
  204. s->active = 1;
  205. unthwackinit(&s->ut);
  206. }
  207. }
  208. static Block*
  209. uncomp(PPP *ppp, Block *bb, int *protop, Block **reply)
  210. {
  211. Lcpmsg *m;
  212. Cstate *cs;
  213. Uncstate *uncs;
  214. Block *b, *r;
  215. uint32_t seq, mseq;
  216. uint16_t proto;
  217. uint8_t mask;
  218. int n;
  219. *reply = nil;
  220. *protop = 0;
  221. uncs = ppp->uncstate;
  222. if(BLEN(bb) < 4){
  223. syslog(0, "ppp", ": thwack: short packet\n");
  224. freeb(bb);
  225. return nil;
  226. }
  227. if(!uncs->active){
  228. netlog("unthwack: inactive, killing packet\n");
  229. freeb(bb);
  230. r = alloclcp(Lresetreq, uncs->resetid, 4, &m);
  231. hnputs(m->len, 4);
  232. *reply = r;
  233. return nil;
  234. }
  235. seq = bb->rptr[0] << 16;
  236. if((seq & ThwCompMask) == ThwUncomp){
  237. bb->rptr++;
  238. b = bb;
  239. }else{
  240. seq |= (bb->rptr[1]<<8) | bb->rptr[2];
  241. bb->rptr += 3;
  242. if((seq & ThwCompMask) == ThwCompressed){
  243. b = allocb(ThwMaxBlock);
  244. n = unthwack(&uncs->ut, b->wptr, ThwMaxBlock, bb->rptr, BLEN(bb), seq & ThwSeqMask);
  245. freeb(bb);
  246. if(n < 2){
  247. syslog(0, "ppp", ": unthwack: short or corrupted packet %d seq=%ld\n", n, seq);
  248. netlog("unthwack: short or corrupted packet n=%d seq=%ld: %s\n", n, seq, uncs->ut.err);
  249. freeb(b);
  250. r = alloclcp(Lresetreq, ++uncs->resetid, 4, &m);
  251. hnputs(m->len, 4);
  252. *reply = r;
  253. uncs->active = 0;
  254. return nil;
  255. }
  256. b->wptr += n;
  257. }else{
  258. unthwackadd(&uncs->ut, bb->rptr, BLEN(bb), seq & ThwSeqMask);
  259. b = bb;
  260. }
  261. /*
  262. * update ack state
  263. */
  264. mseq = unthwackstate(&uncs->ut, &mask);
  265. qlock(&uncs->ackl);
  266. uncs->ackseq = mseq;
  267. uncs->ackmask = mask;
  268. uncs->doack = 1;
  269. qunlock(&uncs->ackl);
  270. }
  271. /*
  272. * grab the compressed protocol field
  273. */
  274. proto = *b->rptr++;
  275. if((proto & 1) == 0)
  276. proto = (proto << 8) | *b->rptr++;
  277. *protop = proto;
  278. /*
  279. * decode the ack, and forward to compressor
  280. */
  281. if(seq & ThwAcked){
  282. if(ppp->ctype == &cthwack){
  283. cs = ppp->cstate;
  284. mseq = (b->rptr[0]<<16) | (b->rptr[1]<<8) | b->rptr[2];
  285. mask = b->rptr[3];
  286. thwackack(&cs->th, mseq, mask);
  287. }
  288. b->rptr += 4;
  289. }
  290. return b;
  291. }