ppp_comp.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134
  1. /*
  2. * ppp_comp.c - STREAMS module for kernel-level compression and CCP support.
  3. *
  4. * Copyright (c) 1994 Paul Mackerras. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. *
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. *
  18. * 3. The name(s) of the authors of this software must not be used to
  19. * endorse or promote products derived from this software without
  20. * prior written permission.
  21. *
  22. * 4. Redistributions of any form whatsoever must retain the following
  23. * acknowledgment:
  24. * "This product includes software developed by Paul Mackerras
  25. * <paulus@samba.org>".
  26. *
  27. * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
  28. * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  29. * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
  30. * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  31. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  32. * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  33. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  34. *
  35. * $Id: ppp_comp.c,v 1.3 2004/01/17 05:47:55 carlsonj Exp $
  36. */
  37. /*
  38. * This file is used under SVR4, Solaris 2, SunOS 4, and Digital UNIX.
  39. */
  40. #include <sys/types.h>
  41. #include <sys/param.h>
  42. #include <sys/errno.h>
  43. #include <sys/stream.h>
  44. #ifdef SVR4
  45. #include <sys/conf.h>
  46. #include <sys/cmn_err.h>
  47. #include <sys/ddi.h>
  48. #else
  49. #include <sys/user.h>
  50. #ifdef __osf__
  51. #include <sys/cmn_err.h>
  52. #endif
  53. #endif /* SVR4 */
  54. #include <net/ppp_defs.h>
  55. #include <net/pppio.h>
  56. #include "ppp_mod.h"
  57. #ifdef __osf__
  58. #include <sys/mbuf.h>
  59. #include <sys/protosw.h>
  60. #endif
  61. #include <netinet/in.h>
  62. #include <netinet/in_systm.h>
  63. #include <netinet/ip.h>
  64. #include <net/vjcompress.h>
  65. #define PACKETPTR mblk_t *
  66. #include <net/ppp-comp.h>
  67. MOD_OPEN_DECL(ppp_comp_open);
  68. MOD_CLOSE_DECL(ppp_comp_close);
  69. static int ppp_comp_rput __P((queue_t *, mblk_t *));
  70. static int ppp_comp_rsrv __P((queue_t *));
  71. static int ppp_comp_wput __P((queue_t *, mblk_t *));
  72. static int ppp_comp_wsrv __P((queue_t *));
  73. static void ppp_comp_ccp __P((queue_t *, mblk_t *, int));
  74. static int msg_byte __P((mblk_t *, unsigned int));
  75. /* Extract byte i of message mp. */
  76. #define MSG_BYTE(mp, i) ((i) < (mp)->b_wptr - (mp)->b_rptr? (mp)->b_rptr[i]: \
  77. msg_byte((mp), (i)))
  78. /* Is this LCP packet one we have to transmit using LCP defaults? */
  79. #define LCP_USE_DFLT(mp) (1 <= (code = MSG_BYTE((mp), 4)) && code <= 7)
  80. #define PPP_COMP_ID 0xbadf
  81. static struct module_info minfo = {
  82. #ifdef PRIOQ
  83. PPP_COMP_ID, "ppp_comp", 0, INFPSZ, 16512, 16384,
  84. #else
  85. PPP_COMP_ID, "ppp_comp", 0, INFPSZ, 16384, 4096,
  86. #endif
  87. };
  88. static struct qinit r_init = {
  89. ppp_comp_rput, ppp_comp_rsrv, ppp_comp_open, ppp_comp_close,
  90. NULL, &minfo, NULL
  91. };
  92. static struct qinit w_init = {
  93. ppp_comp_wput, ppp_comp_wsrv, NULL, NULL, NULL, &minfo, NULL
  94. };
  95. #if defined(SVR4) && !defined(SOL2)
  96. int pcmpdevflag = 0;
  97. #define ppp_compinfo pcmpinfo
  98. #endif
  99. struct streamtab ppp_compinfo = {
  100. &r_init, &w_init, NULL, NULL
  101. };
  102. int ppp_comp_count; /* number of module instances in use */
  103. #ifdef __osf__
  104. static void ppp_comp_alloc __P((comp_state_t *));
  105. typedef struct memreq {
  106. unsigned char comp_opts[20];
  107. int cmd;
  108. int thread_status;
  109. char *returned_mem;
  110. } memreq_t;
  111. #endif
  112. typedef struct comp_state {
  113. int flags;
  114. int mru;
  115. int mtu;
  116. int unit;
  117. struct compressor *xcomp;
  118. void *xstate;
  119. struct compressor *rcomp;
  120. void *rstate;
  121. struct vjcompress vj_comp;
  122. int vj_last_ierrors;
  123. struct pppstat stats;
  124. #ifdef __osf__
  125. memreq_t memreq;
  126. thread_t thread;
  127. #endif
  128. } comp_state_t;
  129. #ifdef __osf__
  130. extern task_t first_task;
  131. #endif
  132. /* Bits in flags are as defined in pppio.h. */
  133. #define CCP_ERR (CCP_ERROR | CCP_FATALERROR)
  134. #define LAST_MOD 0x1000000 /* no ppp modules below us */
  135. #define DBGLOG 0x2000000 /* log debugging stuff */
  136. #define MAX_IPHDR 128 /* max TCP/IP header size */
  137. #define MAX_VJHDR 20 /* max VJ compressed header size (?) */
  138. #undef MIN /* just in case */
  139. #define MIN(a, b) ((a) < (b)? (a): (b))
  140. /*
  141. * List of compressors we know about.
  142. */
  143. #if DO_BSD_COMPRESS
  144. extern struct compressor ppp_bsd_compress;
  145. #endif
  146. #if DO_DEFLATE
  147. extern struct compressor ppp_deflate, ppp_deflate_draft;
  148. #endif
  149. struct compressor *ppp_compressors[] = {
  150. #if DO_BSD_COMPRESS
  151. &ppp_bsd_compress,
  152. #endif
  153. #if DO_DEFLATE
  154. &ppp_deflate,
  155. &ppp_deflate_draft,
  156. #endif
  157. NULL
  158. };
  159. /*
  160. * STREAMS module entry points.
  161. */
  162. MOD_OPEN(ppp_comp_open)
  163. {
  164. comp_state_t *cp;
  165. #ifdef __osf__
  166. thread_t thread;
  167. #endif
  168. if (q->q_ptr == NULL) {
  169. cp = (comp_state_t *) ALLOC_SLEEP(sizeof(comp_state_t));
  170. if (cp == NULL)
  171. OPEN_ERROR(ENOSR);
  172. bzero((caddr_t)cp, sizeof(comp_state_t));
  173. WR(q)->q_ptr = q->q_ptr = (caddr_t) cp;
  174. cp->mru = PPP_MRU;
  175. cp->mtu = PPP_MTU;
  176. cp->xstate = NULL;
  177. cp->rstate = NULL;
  178. vj_compress_init(&cp->vj_comp, -1);
  179. #ifdef __osf__
  180. if (!(thread = kernel_thread_w_arg(first_task, ppp_comp_alloc, (void *)cp)))
  181. OPEN_ERROR(ENOSR);
  182. cp->thread = thread;
  183. #endif
  184. ++ppp_comp_count;
  185. qprocson(q);
  186. }
  187. return 0;
  188. }
  189. MOD_CLOSE(ppp_comp_close)
  190. {
  191. comp_state_t *cp;
  192. qprocsoff(q);
  193. cp = (comp_state_t *) q->q_ptr;
  194. if (cp != NULL) {
  195. if (cp->xstate != NULL)
  196. (*cp->xcomp->comp_free)(cp->xstate);
  197. if (cp->rstate != NULL)
  198. (*cp->rcomp->decomp_free)(cp->rstate);
  199. #ifdef __osf__
  200. if (!cp->thread)
  201. printf("ppp_comp_close: NULL thread!\n");
  202. else
  203. thread_terminate(cp->thread);
  204. #endif
  205. FREE(cp, sizeof(comp_state_t));
  206. q->q_ptr = NULL;
  207. OTHERQ(q)->q_ptr = NULL;
  208. --ppp_comp_count;
  209. }
  210. return 0;
  211. }
  212. #ifdef __osf__
  213. /* thread for calling back to a compressor's memory allocator
  214. * Needed for Digital UNIX since it's VM can't handle requests
  215. * for large amounts of memory without blocking. The thread
  216. * provides a context in which we can call a memory allocator
  217. * that may block.
  218. */
  219. static void
  220. ppp_comp_alloc(comp_state_t *cp)
  221. {
  222. int len, cmd;
  223. unsigned char *compressor_options;
  224. thread_t thread;
  225. void *(*comp_allocator)();
  226. #if defined(MAJOR_VERSION) && (MAJOR_VERSION <= 2)
  227. /* In 2.x and earlier the argument gets passed
  228. * in the thread structure itself. Yuck.
  229. */
  230. thread = current_thread();
  231. cp = thread->reply_port;
  232. thread->reply_port = PORT_NULL;
  233. #endif
  234. for (;;) {
  235. assert_wait((vm_offset_t)&cp->memreq.thread_status, TRUE);
  236. thread_block();
  237. if (thread_should_halt(current_thread()))
  238. thread_halt_self();
  239. cmd = cp->memreq.cmd;
  240. compressor_options = &cp->memreq.comp_opts[0];
  241. len = compressor_options[1];
  242. if (cmd == PPPIO_XCOMP) {
  243. cp->memreq.returned_mem = cp->xcomp->comp_alloc(compressor_options, len);
  244. if (!cp->memreq.returned_mem) {
  245. cp->memreq.thread_status = ENOSR;
  246. } else {
  247. cp->memreq.thread_status = 0;
  248. }
  249. } else {
  250. cp->memreq.returned_mem = cp->rcomp->decomp_alloc(compressor_options, len);
  251. if (!cp->memreq.returned_mem) {
  252. cp->memreq.thread_status = ENOSR;
  253. } else {
  254. cp->memreq.thread_status = 0;
  255. }
  256. }
  257. }
  258. }
  259. #endif /* __osf__ */
  260. /* here's the deal with memory allocation under Digital UNIX.
  261. * Some other may also benefit from this...
  262. * We can't ask for huge chunks of memory in a context where
  263. * the caller can't be put to sleep (like, here.) The alloc
  264. * is likely to fail. Instead we do this: the first time we
  265. * get called, kick off a thread to do the allocation. Return
  266. * immediately to the caller with EAGAIN, as an indication that
  267. * they should send down the ioctl again. By the time the
  268. * second call comes in it's likely that the memory allocation
  269. * thread will have returned with the requested memory. We will
  270. * continue to return EAGAIN however until the thread has completed.
  271. * When it has, we return zero (and the memory) if the allocator
  272. * was successful and ENOSR otherwise.
  273. *
  274. * Callers of the RCOMP and XCOMP ioctls are encouraged (but not
  275. * required) to loop for some number of iterations with a small
  276. * delay in the loop body (for instance a 1/10-th second "sleep"
  277. * via select.)
  278. */
  279. static int
  280. ppp_comp_wput(q, mp)
  281. queue_t *q;
  282. mblk_t *mp;
  283. {
  284. struct iocblk *iop;
  285. comp_state_t *cp;
  286. int error, len, n;
  287. int flags, mask;
  288. mblk_t *np;
  289. struct compressor **comp;
  290. struct ppp_stats *psp;
  291. struct ppp_comp_stats *csp;
  292. unsigned char *opt_data;
  293. int nxslots, nrslots;
  294. cp = (comp_state_t *) q->q_ptr;
  295. if (cp == 0) {
  296. DPRINT("cp == 0 in ppp_comp_wput\n");
  297. freemsg(mp);
  298. return 0;
  299. }
  300. switch (mp->b_datap->db_type) {
  301. case M_DATA:
  302. putq(q, mp);
  303. break;
  304. case M_IOCTL:
  305. iop = (struct iocblk *) mp->b_rptr;
  306. error = EINVAL;
  307. switch (iop->ioc_cmd) {
  308. case PPPIO_CFLAGS:
  309. /* set/get CCP state */
  310. if (iop->ioc_count != 2 * sizeof(int))
  311. break;
  312. if (mp->b_cont == 0) {
  313. DPRINT1("ppp_comp_wput/%d: PPPIO_CFLAGS b_cont = 0!\n", cp->unit);
  314. break;
  315. }
  316. flags = ((int *) mp->b_cont->b_rptr)[0];
  317. mask = ((int *) mp->b_cont->b_rptr)[1];
  318. cp->flags = (cp->flags & ~mask) | (flags & mask);
  319. if ((mask & CCP_ISOPEN) && (flags & CCP_ISOPEN) == 0) {
  320. if (cp->xstate != NULL) {
  321. (*cp->xcomp->comp_free)(cp->xstate);
  322. cp->xstate = NULL;
  323. }
  324. if (cp->rstate != NULL) {
  325. (*cp->rcomp->decomp_free)(cp->rstate);
  326. cp->rstate = NULL;
  327. }
  328. cp->flags &= ~CCP_ISUP;
  329. }
  330. error = 0;
  331. iop->ioc_count = sizeof(int);
  332. ((int *) mp->b_cont->b_rptr)[0] = cp->flags;
  333. mp->b_cont->b_wptr = mp->b_cont->b_rptr + sizeof(int);
  334. break;
  335. case PPPIO_VJINIT:
  336. /*
  337. * Initialize VJ compressor/decompressor
  338. */
  339. if (iop->ioc_count != 2)
  340. break;
  341. if (mp->b_cont == 0) {
  342. DPRINT1("ppp_comp_wput/%d: PPPIO_VJINIT b_cont = 0!\n", cp->unit);
  343. break;
  344. }
  345. nxslots = mp->b_cont->b_rptr[0] + 1;
  346. nrslots = mp->b_cont->b_rptr[1] + 1;
  347. if (nxslots > MAX_STATES || nrslots > MAX_STATES)
  348. break;
  349. vj_compress_init(&cp->vj_comp, nxslots);
  350. cp->vj_last_ierrors = cp->stats.ppp_ierrors;
  351. error = 0;
  352. iop->ioc_count = 0;
  353. break;
  354. case PPPIO_XCOMP:
  355. case PPPIO_RCOMP:
  356. if (iop->ioc_count <= 0)
  357. break;
  358. if (mp->b_cont == 0) {
  359. DPRINT1("ppp_comp_wput/%d: PPPIO_[XR]COMP b_cont = 0!\n", cp->unit);
  360. break;
  361. }
  362. opt_data = mp->b_cont->b_rptr;
  363. len = mp->b_cont->b_wptr - opt_data;
  364. if (len > iop->ioc_count)
  365. len = iop->ioc_count;
  366. if (opt_data[1] < 2 || opt_data[1] > len)
  367. break;
  368. for (comp = ppp_compressors; *comp != NULL; ++comp)
  369. if ((*comp)->compress_proto == opt_data[0]) {
  370. /* here's the handler! */
  371. error = 0;
  372. #ifndef __osf__
  373. if (iop->ioc_cmd == PPPIO_XCOMP) {
  374. /* A previous call may have fetched memory for a compressor
  375. * that's now being retired or reset. Free it using it's
  376. * mechanism for freeing stuff.
  377. */
  378. if (cp->xstate != NULL) {
  379. (*cp->xcomp->comp_free)(cp->xstate);
  380. cp->xstate = NULL;
  381. }
  382. cp->xcomp = *comp;
  383. cp->xstate = (*comp)->comp_alloc(opt_data, len);
  384. if (cp->xstate == NULL)
  385. error = ENOSR;
  386. } else {
  387. if (cp->rstate != NULL) {
  388. (*cp->rcomp->decomp_free)(cp->rstate);
  389. cp->rstate = NULL;
  390. }
  391. cp->rcomp = *comp;
  392. cp->rstate = (*comp)->decomp_alloc(opt_data, len);
  393. if (cp->rstate == NULL)
  394. error = ENOSR;
  395. }
  396. #else
  397. if ((error = cp->memreq.thread_status) != EAGAIN)
  398. if (iop->ioc_cmd == PPPIO_XCOMP) {
  399. if (cp->xstate) {
  400. (*cp->xcomp->comp_free)(cp->xstate);
  401. cp->xstate = 0;
  402. }
  403. /* sanity check for compressor options
  404. */
  405. if (sizeof (cp->memreq.comp_opts) < len) {
  406. printf("can't handle options for compressor %d (%d)\n", opt_data[0],
  407. opt_data[1]);
  408. cp->memreq.thread_status = ENOSR;
  409. cp->memreq.returned_mem = 0;
  410. }
  411. /* fill in request for the thread and kick it off
  412. */
  413. if (cp->memreq.thread_status == 0 && !cp->memreq.returned_mem) {
  414. bcopy(opt_data, cp->memreq.comp_opts, len);
  415. cp->memreq.cmd = PPPIO_XCOMP;
  416. cp->xcomp = *comp;
  417. error = cp->memreq.thread_status = EAGAIN;
  418. thread_wakeup((vm_offset_t)&cp->memreq.thread_status);
  419. } else {
  420. cp->xstate = cp->memreq.returned_mem;
  421. cp->memreq.returned_mem = 0;
  422. cp->memreq.thread_status = 0;
  423. }
  424. } else {
  425. if (cp->rstate) {
  426. (*cp->rcomp->decomp_free)(cp->rstate);
  427. cp->rstate = NULL;
  428. }
  429. if (sizeof (cp->memreq.comp_opts) < len) {
  430. printf("can't handle options for compressor %d (%d)\n", opt_data[0],
  431. opt_data[1]);
  432. cp->memreq.thread_status = ENOSR;
  433. cp->memreq.returned_mem = 0;
  434. }
  435. if (cp->memreq.thread_status == 0 && !cp->memreq.returned_mem) {
  436. bcopy(opt_data, cp->memreq.comp_opts, len);
  437. cp->memreq.cmd = PPPIO_RCOMP;
  438. cp->rcomp = *comp;
  439. error = cp->memreq.thread_status = EAGAIN;
  440. thread_wakeup((vm_offset_t)&cp->memreq.thread_status);
  441. } else {
  442. cp->rstate = cp->memreq.returned_mem;
  443. cp->memreq.returned_mem = 0;
  444. cp->memreq.thread_status = 0;
  445. }
  446. }
  447. #endif
  448. break;
  449. }
  450. iop->ioc_count = 0;
  451. break;
  452. case PPPIO_GETSTAT:
  453. if ((cp->flags & LAST_MOD) == 0) {
  454. error = -1; /* let the ppp_ahdl module handle it */
  455. break;
  456. }
  457. np = allocb(sizeof(struct ppp_stats), BPRI_HI);
  458. if (np == 0) {
  459. error = ENOSR;
  460. break;
  461. }
  462. if (mp->b_cont != 0)
  463. freemsg(mp->b_cont);
  464. mp->b_cont = np;
  465. psp = (struct ppp_stats *) np->b_wptr;
  466. np->b_wptr += sizeof(struct ppp_stats);
  467. iop->ioc_count = sizeof(struct ppp_stats);
  468. psp->p = cp->stats;
  469. psp->vj = cp->vj_comp.stats;
  470. error = 0;
  471. break;
  472. case PPPIO_GETCSTAT:
  473. np = allocb(sizeof(struct ppp_comp_stats), BPRI_HI);
  474. if (np == 0) {
  475. error = ENOSR;
  476. break;
  477. }
  478. if (mp->b_cont != 0)
  479. freemsg(mp->b_cont);
  480. mp->b_cont = np;
  481. csp = (struct ppp_comp_stats *) np->b_wptr;
  482. np->b_wptr += sizeof(struct ppp_comp_stats);
  483. iop->ioc_count = sizeof(struct ppp_comp_stats);
  484. bzero((caddr_t)csp, sizeof(struct ppp_comp_stats));
  485. if (cp->xstate != 0)
  486. (*cp->xcomp->comp_stat)(cp->xstate, &csp->c);
  487. if (cp->rstate != 0)
  488. (*cp->rcomp->decomp_stat)(cp->rstate, &csp->d);
  489. error = 0;
  490. break;
  491. case PPPIO_DEBUG:
  492. if (iop->ioc_count != sizeof(int))
  493. break;
  494. if (mp->b_cont == 0) {
  495. DPRINT1("ppp_comp_wput/%d: PPPIO_DEBUG b_cont = 0!\n", cp->unit);
  496. break;
  497. }
  498. n = *(int *)mp->b_cont->b_rptr;
  499. if (n == PPPDBG_LOG + PPPDBG_COMP) {
  500. DPRINT1("ppp_comp%d: debug log enabled\n", cp->unit);
  501. cp->flags |= DBGLOG;
  502. error = 0;
  503. iop->ioc_count = 0;
  504. } else {
  505. error = -1;
  506. }
  507. break;
  508. case PPPIO_LASTMOD:
  509. cp->flags |= LAST_MOD;
  510. error = 0;
  511. break;
  512. default:
  513. error = -1;
  514. break;
  515. }
  516. if (error < 0)
  517. putnext(q, mp);
  518. else if (error == 0) {
  519. mp->b_datap->db_type = M_IOCACK;
  520. qreply(q, mp);
  521. } else {
  522. mp->b_datap->db_type = M_IOCNAK;
  523. iop->ioc_error = error;
  524. iop->ioc_count = 0;
  525. qreply(q, mp);
  526. }
  527. break;
  528. case M_CTL:
  529. switch (*mp->b_rptr) {
  530. case PPPCTL_MTU:
  531. cp->mtu = ((unsigned short *)mp->b_rptr)[1];
  532. break;
  533. case PPPCTL_MRU:
  534. cp->mru = ((unsigned short *)mp->b_rptr)[1];
  535. break;
  536. case PPPCTL_UNIT:
  537. cp->unit = mp->b_rptr[1];
  538. break;
  539. }
  540. putnext(q, mp);
  541. break;
  542. default:
  543. putnext(q, mp);
  544. }
  545. return 0;
  546. }
  547. static int
  548. ppp_comp_wsrv(q)
  549. queue_t *q;
  550. {
  551. mblk_t *mp, *cmp = NULL;
  552. comp_state_t *cp;
  553. int len, proto, type, hlen, code;
  554. struct ip *ip;
  555. unsigned char *vjhdr, *dp;
  556. cp = (comp_state_t *) q->q_ptr;
  557. if (cp == 0) {
  558. DPRINT("cp == 0 in ppp_comp_wsrv\n");
  559. return 0;
  560. }
  561. while ((mp = getq(q)) != 0) {
  562. /* assert(mp->b_datap->db_type == M_DATA) */
  563. #ifdef PRIOQ
  564. if (!bcanputnext(q,mp->b_band))
  565. #else
  566. if (!canputnext(q))
  567. #endif /* PRIOQ */
  568. {
  569. putbq(q, mp);
  570. break;
  571. }
  572. /*
  573. * First check the packet length and work out what the protocol is.
  574. */
  575. len = msgdsize(mp);
  576. if (len < PPP_HDRLEN) {
  577. DPRINT1("ppp_comp_wsrv: bogus short packet (%d)\n", len);
  578. freemsg(mp);
  579. cp->stats.ppp_oerrors++;
  580. putctl1(RD(q)->q_next, M_CTL, PPPCTL_OERROR);
  581. continue;
  582. }
  583. proto = (MSG_BYTE(mp, 2) << 8) + MSG_BYTE(mp, 3);
  584. /*
  585. * Make sure we've got enough data in the first mblk
  586. * and that we are its only user.
  587. */
  588. if (proto == PPP_CCP)
  589. hlen = len;
  590. else if (proto == PPP_IP)
  591. hlen = PPP_HDRLEN + MAX_IPHDR;
  592. else
  593. hlen = PPP_HDRLEN;
  594. if (hlen > len)
  595. hlen = len;
  596. if (mp->b_wptr < mp->b_rptr + hlen || mp->b_datap->db_ref > 1) {
  597. PULLUP(mp, hlen);
  598. if (mp == 0) {
  599. DPRINT1("ppp_comp_wsrv: pullup failed (%d)\n", hlen);
  600. cp->stats.ppp_oerrors++;
  601. putctl1(RD(q)->q_next, M_CTL, PPPCTL_OERROR);
  602. continue;
  603. }
  604. }
  605. /*
  606. * Do VJ compression if requested.
  607. */
  608. if (proto == PPP_IP && (cp->flags & COMP_VJC)) {
  609. ip = (struct ip *) (mp->b_rptr + PPP_HDRLEN);
  610. if (ip->ip_p == IPPROTO_TCP) {
  611. type = vj_compress_tcp(ip, len - PPP_HDRLEN, &cp->vj_comp,
  612. (cp->flags & COMP_VJCCID), &vjhdr);
  613. switch (type) {
  614. case TYPE_UNCOMPRESSED_TCP:
  615. mp->b_rptr[3] = proto = PPP_VJC_UNCOMP;
  616. break;
  617. case TYPE_COMPRESSED_TCP:
  618. dp = vjhdr - PPP_HDRLEN;
  619. dp[1] = mp->b_rptr[1]; /* copy control field */
  620. dp[0] = mp->b_rptr[0]; /* copy address field */
  621. dp[2] = 0; /* set protocol field */
  622. dp[3] = proto = PPP_VJC_COMP;
  623. mp->b_rptr = dp;
  624. break;
  625. }
  626. }
  627. }
  628. /*
  629. * Do packet compression if enabled.
  630. */
  631. if (proto == PPP_CCP)
  632. ppp_comp_ccp(q, mp, 0);
  633. else if (proto != PPP_LCP && (cp->flags & CCP_COMP_RUN)
  634. && cp->xstate != NULL) {
  635. len = msgdsize(mp);
  636. (*cp->xcomp->compress)(cp->xstate, &cmp, mp, len,
  637. (cp->flags & CCP_ISUP? cp->mtu + PPP_HDRLEN: 0));
  638. if (cmp != NULL) {
  639. #ifdef PRIOQ
  640. cmp->b_band=mp->b_band;
  641. #endif /* PRIOQ */
  642. freemsg(mp);
  643. mp = cmp;
  644. }
  645. }
  646. /*
  647. * Do address/control and protocol compression if enabled.
  648. */
  649. if ((cp->flags & COMP_AC)
  650. && !(proto == PPP_LCP && LCP_USE_DFLT(mp))) {
  651. mp->b_rptr += 2; /* drop the address & ctrl fields */
  652. if (proto < 0x100 && (cp->flags & COMP_PROT))
  653. ++mp->b_rptr; /* drop the high protocol byte */
  654. } else if (proto < 0x100 && (cp->flags & COMP_PROT)) {
  655. /* shuffle up the address & ctrl fields */
  656. mp->b_rptr[2] = mp->b_rptr[1];
  657. mp->b_rptr[1] = mp->b_rptr[0];
  658. ++mp->b_rptr;
  659. }
  660. cp->stats.ppp_opackets++;
  661. cp->stats.ppp_obytes += msgdsize(mp);
  662. putnext(q, mp);
  663. }
  664. return 0;
  665. }
  666. static int
  667. ppp_comp_rput(q, mp)
  668. queue_t *q;
  669. mblk_t *mp;
  670. {
  671. comp_state_t *cp;
  672. struct iocblk *iop;
  673. struct ppp_stats *psp;
  674. cp = (comp_state_t *) q->q_ptr;
  675. if (cp == 0) {
  676. DPRINT("cp == 0 in ppp_comp_rput\n");
  677. freemsg(mp);
  678. return 0;
  679. }
  680. switch (mp->b_datap->db_type) {
  681. case M_DATA:
  682. putq(q, mp);
  683. break;
  684. case M_IOCACK:
  685. iop = (struct iocblk *) mp->b_rptr;
  686. switch (iop->ioc_cmd) {
  687. case PPPIO_GETSTAT:
  688. /*
  689. * Catch this on the way back from the ppp_ahdl module
  690. * so we can fill in the VJ stats.
  691. */
  692. if (mp->b_cont == 0 || iop->ioc_count != sizeof(struct ppp_stats))
  693. break;
  694. psp = (struct ppp_stats *) mp->b_cont->b_rptr;
  695. psp->vj = cp->vj_comp.stats;
  696. break;
  697. }
  698. putnext(q, mp);
  699. break;
  700. case M_CTL:
  701. switch (mp->b_rptr[0]) {
  702. case PPPCTL_IERROR:
  703. ++cp->stats.ppp_ierrors;
  704. break;
  705. case PPPCTL_OERROR:
  706. ++cp->stats.ppp_oerrors;
  707. break;
  708. }
  709. putnext(q, mp);
  710. break;
  711. default:
  712. putnext(q, mp);
  713. }
  714. return 0;
  715. }
  716. static int
  717. ppp_comp_rsrv(q)
  718. queue_t *q;
  719. {
  720. int proto, rv, i;
  721. mblk_t *mp, *dmp = NULL, *np;
  722. uchar_t *dp, *iphdr;
  723. comp_state_t *cp;
  724. int len, hlen, vjlen;
  725. u_int iphlen;
  726. cp = (comp_state_t *) q->q_ptr;
  727. if (cp == 0) {
  728. DPRINT("cp == 0 in ppp_comp_rsrv\n");
  729. return 0;
  730. }
  731. while ((mp = getq(q)) != 0) {
  732. /* assert(mp->b_datap->db_type == M_DATA) */
  733. if (!canputnext(q)) {
  734. putbq(q, mp);
  735. break;
  736. }
  737. len = msgdsize(mp);
  738. cp->stats.ppp_ibytes += len;
  739. cp->stats.ppp_ipackets++;
  740. /*
  741. * First work out the protocol and where the PPP header ends.
  742. */
  743. i = 0;
  744. proto = MSG_BYTE(mp, 0);
  745. if (proto == PPP_ALLSTATIONS) {
  746. i = 2;
  747. proto = MSG_BYTE(mp, 2);
  748. }
  749. if ((proto & 1) == 0) {
  750. ++i;
  751. proto = (proto << 8) + MSG_BYTE(mp, i);
  752. }
  753. hlen = i + 1;
  754. /*
  755. * Now reconstruct a complete, contiguous PPP header at the
  756. * start of the packet.
  757. */
  758. if (hlen < ((cp->flags & DECOMP_AC)? 0: 2)
  759. + ((cp->flags & DECOMP_PROT)? 1: 2)) {
  760. /* count these? */
  761. goto bad;
  762. }
  763. if (mp->b_rptr + hlen > mp->b_wptr) {
  764. adjmsg(mp, hlen); /* XXX check this call */
  765. hlen = 0;
  766. }
  767. if (hlen != PPP_HDRLEN) {
  768. /*
  769. * We need to put some bytes on the front of the packet
  770. * to make a full-length PPP header.
  771. * If we can put them in *mp, we do, otherwise we
  772. * tack another mblk on the front.
  773. * XXX we really shouldn't need to carry around
  774. * the address and control at this stage.
  775. */
  776. dp = mp->b_rptr + hlen - PPP_HDRLEN;
  777. if (dp < mp->b_datap->db_base || mp->b_datap->db_ref > 1) {
  778. np = allocb(PPP_HDRLEN, BPRI_MED);
  779. if (np == 0)
  780. goto bad;
  781. np->b_cont = mp;
  782. mp->b_rptr += hlen;
  783. mp = np;
  784. dp = mp->b_wptr;
  785. mp->b_wptr += PPP_HDRLEN;
  786. } else
  787. mp->b_rptr = dp;
  788. dp[0] = PPP_ALLSTATIONS;
  789. dp[1] = PPP_UI;
  790. dp[2] = proto >> 8;
  791. dp[3] = proto;
  792. }
  793. /*
  794. * Now see if we have a compressed packet to decompress,
  795. * or a CCP packet to take notice of.
  796. */
  797. proto = PPP_PROTOCOL(mp->b_rptr);
  798. if (proto == PPP_CCP) {
  799. len = msgdsize(mp);
  800. if (mp->b_wptr < mp->b_rptr + len) {
  801. PULLUP(mp, len);
  802. if (mp == 0)
  803. goto bad;
  804. }
  805. ppp_comp_ccp(q, mp, 1);
  806. } else if (proto == PPP_COMP) {
  807. if ((cp->flags & CCP_ISUP)
  808. && (cp->flags & CCP_DECOMP_RUN) && cp->rstate
  809. && (cp->flags & CCP_ERR) == 0) {
  810. rv = (*cp->rcomp->decompress)(cp->rstate, mp, &dmp);
  811. switch (rv) {
  812. case DECOMP_OK:
  813. freemsg(mp);
  814. mp = dmp;
  815. if (mp == NULL) {
  816. /* no error, but no packet returned either. */
  817. continue;
  818. }
  819. break;
  820. case DECOMP_ERROR:
  821. cp->flags |= CCP_ERROR;
  822. ++cp->stats.ppp_ierrors;
  823. putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
  824. break;
  825. case DECOMP_FATALERROR:
  826. cp->flags |= CCP_FATALERROR;
  827. ++cp->stats.ppp_ierrors;
  828. putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
  829. break;
  830. }
  831. }
  832. } else if (cp->rstate && (cp->flags & CCP_DECOMP_RUN)) {
  833. (*cp->rcomp->incomp)(cp->rstate, mp);
  834. }
  835. /*
  836. * Now do VJ decompression.
  837. */
  838. proto = PPP_PROTOCOL(mp->b_rptr);
  839. if (proto == PPP_VJC_COMP || proto == PPP_VJC_UNCOMP) {
  840. len = msgdsize(mp) - PPP_HDRLEN;
  841. if ((cp->flags & DECOMP_VJC) == 0 || len <= 0)
  842. goto bad;
  843. /*
  844. * Advance past the ppp header.
  845. * Here we assume that the whole PPP header is in the first mblk.
  846. */
  847. np = mp;
  848. dp = np->b_rptr + PPP_HDRLEN;
  849. if (dp >= mp->b_wptr) {
  850. np = np->b_cont;
  851. dp = np->b_rptr;
  852. }
  853. /*
  854. * Make sure we have sufficient contiguous data at this point.
  855. */
  856. hlen = (proto == PPP_VJC_COMP)? MAX_VJHDR: MAX_IPHDR;
  857. if (hlen > len)
  858. hlen = len;
  859. if (np->b_wptr < dp + hlen || np->b_datap->db_ref > 1) {
  860. PULLUP(mp, hlen + PPP_HDRLEN);
  861. if (mp == 0)
  862. goto bad;
  863. np = mp;
  864. dp = np->b_rptr + PPP_HDRLEN;
  865. }
  866. if (proto == PPP_VJC_COMP) {
  867. /*
  868. * Decompress VJ-compressed packet.
  869. * First reset compressor if an input error has occurred.
  870. */
  871. if (cp->stats.ppp_ierrors != cp->vj_last_ierrors) {
  872. if (cp->flags & DBGLOG)
  873. DPRINT1("ppp%d: resetting VJ\n", cp->unit);
  874. vj_uncompress_err(&cp->vj_comp);
  875. cp->vj_last_ierrors = cp->stats.ppp_ierrors;
  876. }
  877. vjlen = vj_uncompress_tcp(dp, np->b_wptr - dp, len,
  878. &cp->vj_comp, &iphdr, &iphlen);
  879. if (vjlen < 0) {
  880. if (cp->flags & DBGLOG)
  881. DPRINT2("ppp%d: vj_uncomp_tcp failed, pkt len %d\n",
  882. cp->unit, len);
  883. ++cp->vj_last_ierrors; /* so we don't reset next time */
  884. goto bad;
  885. }
  886. /* drop ppp and vj headers off */
  887. if (mp != np) {
  888. freeb(mp);
  889. mp = np;
  890. }
  891. mp->b_rptr = dp + vjlen;
  892. /* allocate a new mblk for the ppp and ip headers */
  893. if ((np = allocb(iphlen + PPP_HDRLEN + 4, BPRI_MED)) == 0)
  894. goto bad;
  895. dp = np->b_rptr; /* prepend mblk with TCP/IP hdr */
  896. dp[0] = PPP_ALLSTATIONS; /* reconstruct PPP header */
  897. dp[1] = PPP_UI;
  898. dp[2] = PPP_IP >> 8;
  899. dp[3] = PPP_IP;
  900. bcopy((caddr_t)iphdr, (caddr_t)dp + PPP_HDRLEN, iphlen);
  901. np->b_wptr = dp + iphlen + PPP_HDRLEN;
  902. np->b_cont = mp;
  903. /* XXX there seems to be a bug which causes panics in strread
  904. if we make an mbuf with only the IP header in it :-( */
  905. if (mp->b_wptr - mp->b_rptr > 4) {
  906. bcopy((caddr_t)mp->b_rptr, (caddr_t)np->b_wptr, 4);
  907. mp->b_rptr += 4;
  908. np->b_wptr += 4;
  909. } else {
  910. bcopy((caddr_t)mp->b_rptr, (caddr_t)np->b_wptr,
  911. mp->b_wptr - mp->b_rptr);
  912. np->b_wptr += mp->b_wptr - mp->b_rptr;
  913. np->b_cont = mp->b_cont;
  914. freeb(mp);
  915. }
  916. mp = np;
  917. } else {
  918. /*
  919. * "Decompress" a VJ-uncompressed packet.
  920. */
  921. cp->vj_last_ierrors = cp->stats.ppp_ierrors;
  922. if (!vj_uncompress_uncomp(dp, hlen, &cp->vj_comp)) {
  923. if (cp->flags & DBGLOG)
  924. DPRINT2("ppp%d: vj_uncomp_uncomp failed, pkt len %d\n",
  925. cp->unit, len);
  926. ++cp->vj_last_ierrors; /* don't need to reset next time */
  927. goto bad;
  928. }
  929. mp->b_rptr[3] = PPP_IP; /* fix up the PPP protocol field */
  930. }
  931. }
  932. putnext(q, mp);
  933. continue;
  934. bad:
  935. if (mp != 0)
  936. freemsg(mp);
  937. cp->stats.ppp_ierrors++;
  938. putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
  939. }
  940. return 0;
  941. }
  942. /*
  943. * Handle a CCP packet being sent or received.
  944. * Here all the data in the packet is in a single mbuf.
  945. */
  946. static void
  947. ppp_comp_ccp(q, mp, rcvd)
  948. queue_t *q;
  949. mblk_t *mp;
  950. int rcvd;
  951. {
  952. int len, clen;
  953. comp_state_t *cp;
  954. unsigned char *dp;
  955. len = msgdsize(mp);
  956. if (len < PPP_HDRLEN + CCP_HDRLEN)
  957. return;
  958. cp = (comp_state_t *) q->q_ptr;
  959. dp = mp->b_rptr + PPP_HDRLEN;
  960. len -= PPP_HDRLEN;
  961. clen = CCP_LENGTH(dp);
  962. if (clen > len)
  963. return;
  964. switch (CCP_CODE(dp)) {
  965. case CCP_CONFREQ:
  966. case CCP_TERMREQ:
  967. case CCP_TERMACK:
  968. cp->flags &= ~CCP_ISUP;
  969. break;
  970. case CCP_CONFACK:
  971. if ((cp->flags & (CCP_ISOPEN | CCP_ISUP)) == CCP_ISOPEN
  972. && clen >= CCP_HDRLEN + CCP_OPT_MINLEN
  973. && clen >= CCP_HDRLEN + CCP_OPT_LENGTH(dp + CCP_HDRLEN)) {
  974. if (!rcvd) {
  975. if (cp->xstate != NULL
  976. && (*cp->xcomp->comp_init)
  977. (cp->xstate, dp + CCP_HDRLEN, clen - CCP_HDRLEN,
  978. cp->unit, 0, ((cp->flags & DBGLOG) != 0)))
  979. cp->flags |= CCP_COMP_RUN;
  980. } else {
  981. if (cp->rstate != NULL
  982. && (*cp->rcomp->decomp_init)
  983. (cp->rstate, dp + CCP_HDRLEN, clen - CCP_HDRLEN,
  984. cp->unit, 0, cp->mru, ((cp->flags & DBGLOG) != 0)))
  985. cp->flags = (cp->flags & ~CCP_ERR) | CCP_DECOMP_RUN;
  986. }
  987. }
  988. break;
  989. case CCP_RESETACK:
  990. if (cp->flags & CCP_ISUP) {
  991. if (!rcvd) {
  992. if (cp->xstate && (cp->flags & CCP_COMP_RUN))
  993. (*cp->xcomp->comp_reset)(cp->xstate);
  994. } else {
  995. if (cp->rstate && (cp->flags & CCP_DECOMP_RUN)) {
  996. (*cp->rcomp->decomp_reset)(cp->rstate);
  997. cp->flags &= ~CCP_ERROR;
  998. }
  999. }
  1000. }
  1001. break;
  1002. }
  1003. }
  1004. #if 0
  1005. dump_msg(mp)
  1006. mblk_t *mp;
  1007. {
  1008. dblk_t *db;
  1009. while (mp != 0) {
  1010. db = mp->b_datap;
  1011. DPRINT2("mp=%x cont=%x ", mp, mp->b_cont);
  1012. DPRINT3("rptr=%x wptr=%x datap=%x\n", mp->b_rptr, mp->b_wptr, db);
  1013. DPRINT2(" base=%x lim=%x", db->db_base, db->db_lim);
  1014. DPRINT2(" ref=%d type=%d\n", db->db_ref, db->db_type);
  1015. mp = mp->b_cont;
  1016. }
  1017. }
  1018. #endif
  1019. static int
  1020. msg_byte(mp, i)
  1021. mblk_t *mp;
  1022. unsigned int i;
  1023. {
  1024. while (mp != 0 && i >= mp->b_wptr - mp->b_rptr)
  1025. mp = mp->b_cont;
  1026. if (mp == 0)
  1027. return -1;
  1028. return mp->b_rptr[i];
  1029. }