ppp_ahdlc.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  1. /*
  2. * ppp_ahdlc.c - STREAMS module for doing PPP asynchronous HDLC.
  3. *
  4. * Re-written by Adi Masputra <adi.masputra@sun.com>, based on
  5. * the original ppp_ahdlc.c
  6. *
  7. * Copyright (c) 2000 by Sun Microsystems, Inc.
  8. * All rights reserved.
  9. *
  10. * Permission to use, copy, modify, and distribute this software and its
  11. * documentation is hereby granted, provided that the above copyright
  12. * notice appears in all copies.
  13. *
  14. * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
  15. * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  16. * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  17. * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  18. * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  19. * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
  20. *
  21. * Copyright (c) 1994 Paul Mackerras. All rights reserved.
  22. *
  23. * Redistribution and use in source and binary forms, with or without
  24. * modification, are permitted provided that the following conditions
  25. * are met:
  26. *
  27. * 1. Redistributions of source code must retain the above copyright
  28. * notice, this list of conditions and the following disclaimer.
  29. *
  30. * 2. Redistributions in binary form must reproduce the above copyright
  31. * notice, this list of conditions and the following disclaimer in
  32. * the documentation and/or other materials provided with the
  33. * distribution.
  34. *
  35. * 3. The name(s) of the authors of this software must not be used to
  36. * endorse or promote products derived from this software without
  37. * prior written permission.
  38. *
  39. * 4. Redistributions of any form whatsoever must retain the following
  40. * acknowledgment:
  41. * "This product includes software developed by Paul Mackerras
  42. * <paulus@samba.org>".
  43. *
  44. * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
  45. * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  46. * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
  47. * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  48. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  49. * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  50. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  51. *
  52. * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  53. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  54. * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
  55. * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
  56. * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  57. * OR MODIFICATIONS.
  58. *
  59. * $Id: ppp_ahdlc.c,v 1.18 2002/12/06 09:49:15 paulus Exp $
  60. */
  61. /*
  62. * This file is used under Solaris 2, SVR4, SunOS 4, and Digital UNIX.
  63. */
  64. #include <sys/types.h>
  65. #include <sys/param.h>
  66. #include <sys/stream.h>
  67. #include <sys/errno.h>
  68. #ifdef SVR4
  69. #include <sys/conf.h>
  70. #include <sys/kmem.h>
  71. #include <sys/cmn_err.h>
  72. #include <sys/ddi.h>
  73. #else
  74. #include <sys/user.h>
  75. #ifdef __osf__
  76. #include <sys/cmn_err.h>
  77. #endif
  78. #endif /* SVR4 */
  79. #include <net/ppp_defs.h>
  80. #include <net/pppio.h>
  81. #include "ppp_mod.h"
  82. /*
  83. * Right now, mutex is only enabled for Solaris 2.x
  84. */
  85. #if defined(SOL2)
  86. #define USE_MUTEX
  87. #endif /* SOL2 */
  88. /*
  89. * intpointer_t and uintpointer_t are signed and unsigned integer types
  90. * large enough to hold any data pointer; that is, data pointers can be
  91. * assigned into or from these integer types without losing precision.
  92. * On recent Solaris releases, these types are defined in sys/int_types.h,
  93. * but not on SunOS 4.x or the earlier Solaris versions.
  94. */
  95. #if defined(_LP64) || defined(_I32LPx)
  96. typedef long intpointer_t;
  97. typedef unsigned long uintpointer_t;
  98. #else
  99. typedef int intpointer_t;
  100. typedef unsigned int uintpointer_t;
  101. #endif
  102. MOD_OPEN_DECL(ahdlc_open);
  103. MOD_CLOSE_DECL(ahdlc_close);
  104. static int ahdlc_wput __P((queue_t *, mblk_t *));
  105. static int ahdlc_rput __P((queue_t *, mblk_t *));
  106. static void ahdlc_encode __P((queue_t *, mblk_t *));
  107. static void ahdlc_decode __P((queue_t *, mblk_t *));
  108. static int msg_byte __P((mblk_t *, unsigned int));
  109. #if defined(SOL2)
  110. /*
  111. * Don't send HDLC start flag is last transmit is within 1.5 seconds -
  112. * FLAG_TIME is defined is microseconds
  113. */
  114. #define FLAG_TIME 1500
  115. #define ABS(x) (x >= 0 ? x : (-x))
  116. #endif /* SOL2 */
  117. /*
  118. * Extract byte i of message mp
  119. */
  120. #define MSG_BYTE(mp, i) ((i) < (mp)->b_wptr - (mp)->b_rptr? (mp)->b_rptr[i]: \
  121. msg_byte((mp), (i)))
  122. /*
  123. * Is this LCP packet one we have to transmit using LCP defaults?
  124. */
  125. #define LCP_USE_DFLT(mp) (1 <= (code = MSG_BYTE((mp), 4)) && code <= 7)
  126. /*
  127. * Standard STREAMS declarations
  128. */
  129. static struct module_info minfo = {
  130. 0x7d23, "ppp_ahdl", 0, INFPSZ, 32768, 512
  131. };
  132. static struct qinit rinit = {
  133. ahdlc_rput, NULL, ahdlc_open, ahdlc_close, NULL, &minfo, NULL
  134. };
  135. static struct qinit winit = {
  136. ahdlc_wput, NULL, NULL, NULL, NULL, &minfo, NULL
  137. };
  138. #if defined(SVR4) && !defined(SOL2)
  139. int phdldevflag = 0;
  140. #define ppp_ahdlcinfo phdlinfo
  141. #endif /* defined(SVR4) && !defined(SOL2) */
  142. struct streamtab ppp_ahdlcinfo = {
  143. &rinit, /* ptr to st_rdinit */
  144. &winit, /* ptr to st_wrinit */
  145. NULL, /* ptr to st_muxrinit */
  146. NULL, /* ptr to st_muxwinit */
  147. #if defined(SUNOS4)
  148. NULL /* ptr to ptr to st_modlist */
  149. #endif /* SUNOS4 */
  150. };
  151. #if defined(SUNOS4)
  152. int ppp_ahdlc_count = 0; /* open counter */
  153. #endif /* SUNOS4 */
  154. /*
  155. * Per-stream state structure
  156. */
  157. typedef struct ahdlc_state {
  158. #if defined(USE_MUTEX)
  159. kmutex_t lock; /* lock for this structure */
  160. #endif /* USE_MUTEX */
  161. int flags; /* link flags */
  162. mblk_t *rx_buf; /* ptr to receive buffer */
  163. int rx_buf_size; /* receive buffer size */
  164. ushort_t infcs; /* calculated rx HDLC FCS */
  165. u_int32_t xaccm[8]; /* 256-bit xmit ACCM */
  166. u_int32_t raccm; /* 32-bit rcv ACCM */
  167. int mtu; /* interface MTU */
  168. int mru; /* link MRU */
  169. int unit; /* current PPP unit number */
  170. struct pppstat stats; /* statistic structure */
  171. #if defined(SOL2)
  172. clock_t flag_time; /* time in usec between flags */
  173. clock_t lbolt; /* last updated lbolt */
  174. #endif /* SOL2 */
  175. } ahdlc_state_t;
  176. /*
  177. * Values for flags
  178. */
  179. #define ESCAPED 0x100 /* last saw escape char on input */
  180. #define IFLUSH 0x200 /* flushing input due to error */
  181. /*
  182. * RCV_B7_1, etc., defined in net/pppio.h, are stored in flags also.
  183. */
  184. #define RCV_FLAGS (RCV_B7_1|RCV_B7_0|RCV_ODDP|RCV_EVNP)
  185. /*
  186. * FCS lookup table as calculated by genfcstab.
  187. */
  188. static u_short fcstab[256] = {
  189. 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
  190. 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
  191. 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
  192. 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
  193. 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
  194. 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
  195. 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
  196. 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
  197. 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
  198. 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
  199. 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
  200. 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
  201. 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
  202. 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
  203. 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
  204. 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
  205. 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
  206. 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
  207. 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
  208. 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
  209. 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
  210. 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
  211. 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
  212. 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
  213. 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
  214. 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
  215. 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
  216. 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
  217. 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
  218. 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
  219. 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
  220. 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
  221. };
  222. static u_int32_t paritytab[8] =
  223. {
  224. 0x96696996, 0x69969669, 0x69969669, 0x96696996,
  225. 0x69969669, 0x96696996, 0x96696996, 0x69969669
  226. };
  227. /*
  228. * STREAMS module open (entry) point
  229. */
  230. MOD_OPEN(ahdlc_open)
  231. {
  232. ahdlc_state_t *state;
  233. /*
  234. * Return if it's already opened
  235. */
  236. if (q->q_ptr) {
  237. return 0;
  238. }
  239. /*
  240. * This can only be opened as a module
  241. */
  242. if (sflag != MODOPEN) {
  243. return 0;
  244. }
  245. state = (ahdlc_state_t *) ALLOC_NOSLEEP(sizeof(ahdlc_state_t));
  246. if (state == 0)
  247. OPEN_ERROR(ENOSR);
  248. bzero((caddr_t) state, sizeof(ahdlc_state_t));
  249. q->q_ptr = (caddr_t) state;
  250. WR(q)->q_ptr = (caddr_t) state;
  251. #if defined(USE_MUTEX)
  252. mutex_init(&state->lock, NULL, MUTEX_DEFAULT, NULL);
  253. mutex_enter(&state->lock);
  254. #endif /* USE_MUTEX */
  255. state->xaccm[0] = ~0; /* escape 0x00 through 0x1f */
  256. state->xaccm[3] = 0x60000000; /* escape 0x7d and 0x7e */
  257. state->mru = PPP_MRU; /* default of 1500 bytes */
  258. #if defined(SOL2)
  259. state->flag_time = drv_usectohz(FLAG_TIME);
  260. #endif /* SOL2 */
  261. #if defined(USE_MUTEX)
  262. mutex_exit(&state->lock);
  263. #endif /* USE_MUTEX */
  264. #if defined(SUNOS4)
  265. ppp_ahdlc_count++;
  266. #endif /* SUNOS4 */
  267. qprocson(q);
  268. return 0;
  269. }
  270. /*
  271. * STREAMS module close (exit) point
  272. */
  273. MOD_CLOSE(ahdlc_close)
  274. {
  275. ahdlc_state_t *state;
  276. qprocsoff(q);
  277. state = (ahdlc_state_t *) q->q_ptr;
  278. if (state == 0) {
  279. DPRINT("state == 0 in ahdlc_close\n");
  280. return 0;
  281. }
  282. #if defined(USE_MUTEX)
  283. mutex_enter(&state->lock);
  284. #endif /* USE_MUTEX */
  285. if (state->rx_buf != 0) {
  286. freemsg(state->rx_buf);
  287. state->rx_buf = 0;
  288. }
  289. #if defined(USE_MUTEX)
  290. mutex_exit(&state->lock);
  291. mutex_destroy(&state->lock);
  292. #endif /* USE_MUTEX */
  293. FREE(q->q_ptr, sizeof(ahdlc_state_t));
  294. q->q_ptr = NULL;
  295. OTHERQ(q)->q_ptr = NULL;
  296. #if defined(SUNOS4)
  297. if (ppp_ahdlc_count)
  298. ppp_ahdlc_count--;
  299. #endif /* SUNOS4 */
  300. return 0;
  301. }
  302. /*
  303. * Write side put routine
  304. */
  305. static int
  306. ahdlc_wput(q, mp)
  307. queue_t *q;
  308. mblk_t *mp;
  309. {
  310. ahdlc_state_t *state;
  311. struct iocblk *iop;
  312. int error;
  313. mblk_t *np;
  314. struct ppp_stats *psp;
  315. state = (ahdlc_state_t *) q->q_ptr;
  316. if (state == 0) {
  317. DPRINT("state == 0 in ahdlc_wput\n");
  318. freemsg(mp);
  319. return 0;
  320. }
  321. switch (mp->b_datap->db_type) {
  322. case M_DATA:
  323. /*
  324. * A data packet - do character-stuffing and FCS, and
  325. * send it onwards.
  326. */
  327. ahdlc_encode(q, mp);
  328. freemsg(mp);
  329. break;
  330. case M_IOCTL:
  331. iop = (struct iocblk *) mp->b_rptr;
  332. error = EINVAL;
  333. switch (iop->ioc_cmd) {
  334. case PPPIO_XACCM:
  335. if ((iop->ioc_count < sizeof(u_int32_t)) ||
  336. (iop->ioc_count > sizeof(ext_accm))) {
  337. break;
  338. }
  339. if (mp->b_cont == 0) {
  340. DPRINT1("ahdlc_wput/%d: PPPIO_XACCM b_cont = 0!\n", state->unit);
  341. break;
  342. }
  343. #if defined(USE_MUTEX)
  344. mutex_enter(&state->lock);
  345. #endif /* USE_MUTEX */
  346. bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)state->xaccm,
  347. iop->ioc_count);
  348. state->xaccm[2] &= ~0x40000000; /* don't escape 0x5e */
  349. state->xaccm[3] |= 0x60000000; /* do escape 0x7d, 0x7e */
  350. #if defined(USE_MUTEX)
  351. mutex_exit(&state->lock);
  352. #endif /* USE_MUTEX */
  353. iop->ioc_count = 0;
  354. error = 0;
  355. break;
  356. case PPPIO_RACCM:
  357. if (iop->ioc_count != sizeof(u_int32_t))
  358. break;
  359. if (mp->b_cont == 0) {
  360. DPRINT1("ahdlc_wput/%d: PPPIO_RACCM b_cont = 0!\n", state->unit);
  361. break;
  362. }
  363. #if defined(USE_MUTEX)
  364. mutex_enter(&state->lock);
  365. #endif /* USE_MUTEX */
  366. bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)&state->raccm,
  367. sizeof(u_int32_t));
  368. #if defined(USE_MUTEX)
  369. mutex_exit(&state->lock);
  370. #endif /* USE_MUTEX */
  371. iop->ioc_count = 0;
  372. error = 0;
  373. break;
  374. case PPPIO_GCLEAN:
  375. np = allocb(sizeof(int), BPRI_HI);
  376. if (np == 0) {
  377. error = ENOSR;
  378. break;
  379. }
  380. if (mp->b_cont != 0)
  381. freemsg(mp->b_cont);
  382. mp->b_cont = np;
  383. #if defined(USE_MUTEX)
  384. mutex_enter(&state->lock);
  385. #endif /* USE_MUTEX */
  386. *(int *)np->b_wptr = state->flags & RCV_FLAGS;
  387. #if defined(USE_MUTEX)
  388. mutex_exit(&state->lock);
  389. #endif /* USE_MUTEX */
  390. np->b_wptr += sizeof(int);
  391. iop->ioc_count = sizeof(int);
  392. error = 0;
  393. break;
  394. case PPPIO_GETSTAT:
  395. np = allocb(sizeof(struct ppp_stats), BPRI_HI);
  396. if (np == 0) {
  397. error = ENOSR;
  398. break;
  399. }
  400. if (mp->b_cont != 0)
  401. freemsg(mp->b_cont);
  402. mp->b_cont = np;
  403. psp = (struct ppp_stats *) np->b_wptr;
  404. np->b_wptr += sizeof(struct ppp_stats);
  405. bzero((caddr_t)psp, sizeof(struct ppp_stats));
  406. psp->p = state->stats;
  407. iop->ioc_count = sizeof(struct ppp_stats);
  408. error = 0;
  409. break;
  410. case PPPIO_LASTMOD:
  411. /* we knew this anyway */
  412. error = 0;
  413. break;
  414. default:
  415. error = -1;
  416. break;
  417. }
  418. if (error < 0)
  419. putnext(q, mp);
  420. else if (error == 0) {
  421. mp->b_datap->db_type = M_IOCACK;
  422. qreply(q, mp);
  423. } else {
  424. mp->b_datap->db_type = M_IOCNAK;
  425. iop->ioc_count = 0;
  426. iop->ioc_error = error;
  427. qreply(q, mp);
  428. }
  429. break;
  430. case M_CTL:
  431. switch (*mp->b_rptr) {
  432. case PPPCTL_MTU:
  433. #if defined(USE_MUTEX)
  434. mutex_enter(&state->lock);
  435. #endif /* USE_MUTEX */
  436. state->mtu = ((unsigned short *)mp->b_rptr)[1];
  437. #if defined(USE_MUTEX)
  438. mutex_exit(&state->lock);
  439. #endif /* USE_MUTEX */
  440. freemsg(mp);
  441. break;
  442. case PPPCTL_MRU:
  443. #if defined(USE_MUTEX)
  444. mutex_enter(&state->lock);
  445. #endif /* USE_MUTEX */
  446. state->mru = ((unsigned short *)mp->b_rptr)[1];
  447. #if defined(USE_MUTEX)
  448. mutex_exit(&state->lock);
  449. #endif /* USE_MUTEX */
  450. freemsg(mp);
  451. break;
  452. case PPPCTL_UNIT:
  453. #if defined(USE_MUTEX)
  454. mutex_enter(&state->lock);
  455. #endif /* USE_MUTEX */
  456. state->unit = mp->b_rptr[1];
  457. #if defined(USE_MUTEX)
  458. mutex_exit(&state->lock);
  459. #endif /* USE_MUTEX */
  460. break;
  461. default:
  462. putnext(q, mp);
  463. }
  464. break;
  465. default:
  466. putnext(q, mp);
  467. }
  468. return 0;
  469. }
  470. /*
  471. * Read side put routine
  472. */
  473. static int
  474. ahdlc_rput(q, mp)
  475. queue_t *q;
  476. mblk_t *mp;
  477. {
  478. ahdlc_state_t *state;
  479. state = (ahdlc_state_t *) q->q_ptr;
  480. if (state == 0) {
  481. DPRINT("state == 0 in ahdlc_rput\n");
  482. freemsg(mp);
  483. return 0;
  484. }
  485. switch (mp->b_datap->db_type) {
  486. case M_DATA:
  487. ahdlc_decode(q, mp);
  488. break;
  489. case M_HANGUP:
  490. #if defined(USE_MUTEX)
  491. mutex_enter(&state->lock);
  492. #endif /* USE_MUTEX */
  493. if (state->rx_buf != 0) {
  494. /* XXX would like to send this up for debugging */
  495. freemsg(state->rx_buf);
  496. state->rx_buf = 0;
  497. }
  498. state->flags = IFLUSH;
  499. #if defined(USE_MUTEX)
  500. mutex_exit(&state->lock);
  501. #endif /* USE_MUTEX */
  502. putnext(q, mp);
  503. break;
  504. default:
  505. putnext(q, mp);
  506. }
  507. return 0;
  508. }
  509. /*
  510. * Extract bit c from map m, to determine if c needs to be escaped
  511. */
  512. #define IN_TX_MAP(c, m) ((m)[(c) >> 5] & (1 << ((c) & 0x1f)))
  513. static void
  514. ahdlc_encode(q, mp)
  515. queue_t *q;
  516. mblk_t *mp;
  517. {
  518. ahdlc_state_t *state;
  519. u_int32_t *xaccm, loc_xaccm[8];
  520. ushort_t fcs;
  521. size_t outmp_len;
  522. mblk_t *outmp, *tmp;
  523. uchar_t *dp, fcs_val;
  524. int is_lcp, code;
  525. #if defined(SOL2)
  526. clock_t lbolt;
  527. #endif /* SOL2 */
  528. if (msgdsize(mp) < 4) {
  529. return;
  530. }
  531. state = (ahdlc_state_t *)q->q_ptr;
  532. #if defined(USE_MUTEX)
  533. mutex_enter(&state->lock);
  534. #endif /* USE_MUTEX */
  535. /*
  536. * Allocate an output buffer large enough to handle a case where all
  537. * characters need to be escaped
  538. */
  539. outmp_len = (msgdsize(mp) << 1) + /* input block x 2 */
  540. (sizeof(fcs) << 2) + /* HDLC FCS x 4 */
  541. (sizeof(uchar_t) << 1); /* HDLC flags x 2 */
  542. outmp = allocb(outmp_len, BPRI_MED);
  543. if (outmp == NULL) {
  544. state->stats.ppp_oerrors++;
  545. #if defined(USE_MUTEX)
  546. mutex_exit(&state->lock);
  547. #endif /* USE_MUTEX */
  548. putctl1(RD(q)->q_next, M_CTL, PPPCTL_OERROR);
  549. return;
  550. }
  551. #if defined(SOL2)
  552. /*
  553. * Check if our last transmit happenned within flag_time, using
  554. * the system's LBOLT value in clock ticks
  555. */
  556. if (drv_getparm(LBOLT, &lbolt) != -1) {
  557. if (ABS((clock_t)lbolt - state->lbolt) > state->flag_time) {
  558. *outmp->b_wptr++ = PPP_FLAG;
  559. }
  560. state->lbolt = lbolt;
  561. } else {
  562. *outmp->b_wptr++ = PPP_FLAG;
  563. }
  564. #else
  565. /*
  566. * If the driver below still has a message to process, skip the
  567. * HDLC flag, otherwise, put one in the beginning
  568. */
  569. if (qsize(q->q_next) == 0) {
  570. *outmp->b_wptr++ = PPP_FLAG;
  571. }
  572. #endif
  573. /*
  574. * All control characters must be escaped for LCP packets with code
  575. * values between 1 (Conf-Req) and 7 (Code-Rej).
  576. */
  577. is_lcp = ((MSG_BYTE(mp, 0) == PPP_ALLSTATIONS) &&
  578. (MSG_BYTE(mp, 1) == PPP_UI) &&
  579. (MSG_BYTE(mp, 2) == (PPP_LCP >> 8)) &&
  580. (MSG_BYTE(mp, 3) == (PPP_LCP & 0xff)) &&
  581. LCP_USE_DFLT(mp));
  582. xaccm = state->xaccm;
  583. if (is_lcp) {
  584. bcopy((caddr_t)state->xaccm, (caddr_t)loc_xaccm, sizeof(loc_xaccm));
  585. loc_xaccm[0] = ~0; /* force escape on 0x00 through 0x1f */
  586. xaccm = loc_xaccm;
  587. }
  588. fcs = PPP_INITFCS; /* Initial FCS is 0xffff */
  589. /*
  590. * Process this block and the rest (if any) attached to the this one
  591. */
  592. for (tmp = mp; tmp; tmp = tmp->b_cont) {
  593. if (tmp->b_datap->db_type == M_DATA) {
  594. for (dp = tmp->b_rptr; dp < tmp->b_wptr; dp++) {
  595. fcs = PPP_FCS(fcs, *dp);
  596. if (IN_TX_MAP(*dp, xaccm)) {
  597. *outmp->b_wptr++ = PPP_ESCAPE;
  598. *outmp->b_wptr++ = *dp ^ PPP_TRANS;
  599. } else {
  600. *outmp->b_wptr++ = *dp;
  601. }
  602. }
  603. } else {
  604. continue; /* skip if db_type is something other than M_DATA */
  605. }
  606. }
  607. /*
  608. * Append the HDLC FCS, making sure that escaping is done on any
  609. * necessary bytes
  610. */
  611. fcs_val = (fcs ^ 0xffff) & 0xff;
  612. if (IN_TX_MAP(fcs_val, xaccm)) {
  613. *outmp->b_wptr++ = PPP_ESCAPE;
  614. *outmp->b_wptr++ = fcs_val ^ PPP_TRANS;
  615. } else {
  616. *outmp->b_wptr++ = fcs_val;
  617. }
  618. fcs_val = ((fcs ^ 0xffff) >> 8) & 0xff;
  619. if (IN_TX_MAP(fcs_val, xaccm)) {
  620. *outmp->b_wptr++ = PPP_ESCAPE;
  621. *outmp->b_wptr++ = fcs_val ^ PPP_TRANS;
  622. } else {
  623. *outmp->b_wptr++ = fcs_val;
  624. }
  625. /*
  626. * And finally, append the HDLC flag, and send it away
  627. */
  628. *outmp->b_wptr++ = PPP_FLAG;
  629. state->stats.ppp_obytes += msgdsize(outmp);
  630. state->stats.ppp_opackets++;
  631. #if defined(USE_MUTEX)
  632. mutex_exit(&state->lock);
  633. #endif /* USE_MUTEX */
  634. putnext(q, outmp);
  635. return;
  636. }
  637. /*
  638. * Checks the 32-bit receive ACCM to see if the byte needs un-escaping
  639. */
  640. #define IN_RX_MAP(c, m) ((((unsigned int) (uchar_t) (c)) < 0x20) && \
  641. (m) & (1 << (c)))
  642. /*
  643. * Process received characters.
  644. */
  645. static void
  646. ahdlc_decode(q, mp)
  647. queue_t *q;
  648. mblk_t *mp;
  649. {
  650. ahdlc_state_t *state;
  651. mblk_t *om;
  652. uchar_t *dp;
  653. state = (ahdlc_state_t *) q->q_ptr;
  654. #if defined(USE_MUTEX)
  655. mutex_enter(&state->lock);
  656. #endif /* USE_MUTEX */
  657. state->stats.ppp_ibytes += msgdsize(mp);
  658. for (; mp != 0; om = mp->b_cont, freeb(mp), mp = om)
  659. for (dp = mp->b_rptr; dp < mp->b_wptr; dp++) {
  660. /*
  661. * This should detect the lack of 8-bit communication channel
  662. * which is necessary for PPP to work. In addition, it also
  663. * checks on the parity.
  664. */
  665. if (*dp & 0x80)
  666. state->flags |= RCV_B7_1;
  667. else
  668. state->flags |= RCV_B7_0;
  669. if (paritytab[*dp >> 5] & (1 << (*dp & 0x1f)))
  670. state->flags |= RCV_ODDP;
  671. else
  672. state->flags |= RCV_EVNP;
  673. /*
  674. * So we have a HDLC flag ...
  675. */
  676. if (*dp == PPP_FLAG) {
  677. /*
  678. * If we think that it marks the beginning of the frame,
  679. * then continue to process the next octects
  680. */
  681. if ((state->flags & IFLUSH) ||
  682. (state->rx_buf == 0) ||
  683. (msgdsize(state->rx_buf) == 0)) {
  684. state->flags &= ~IFLUSH;
  685. continue;
  686. }
  687. /*
  688. * We get here because the above condition isn't true,
  689. * in which case the HDLC flag was there to mark the end
  690. * of the frame (or so we think)
  691. */
  692. om = state->rx_buf;
  693. if (state->infcs == PPP_GOODFCS) {
  694. state->stats.ppp_ipackets++;
  695. adjmsg(om, -PPP_FCSLEN);
  696. putnext(q, om);
  697. } else {
  698. DPRINT2("ppp%d: bad fcs (len=%d)\n",
  699. state->unit, msgdsize(state->rx_buf));
  700. freemsg(state->rx_buf);
  701. state->flags &= ~(IFLUSH | ESCAPED);
  702. state->stats.ppp_ierrors++;
  703. putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
  704. }
  705. state->rx_buf = 0;
  706. continue;
  707. }
  708. if (state->flags & IFLUSH) {
  709. continue;
  710. }
  711. /*
  712. * Allocate a receive buffer, large enough to store a frame (after
  713. * un-escaping) of at least 1500 octets. If MRU is negotiated to
  714. * be more than the default, then allocate that much. In addition,
  715. * we add an extra 32-bytes for a fudge factor
  716. */
  717. if (state->rx_buf == 0) {
  718. state->rx_buf_size = (state->mru < PPP_MRU ? PPP_MRU : state->mru);
  719. state->rx_buf_size += (sizeof(u_int32_t) << 3);
  720. state->rx_buf = allocb(state->rx_buf_size, BPRI_MED);
  721. /*
  722. * If allocation fails, try again on the next frame
  723. */
  724. if (state->rx_buf == 0) {
  725. state->flags |= IFLUSH;
  726. continue;
  727. }
  728. state->flags &= ~(IFLUSH | ESCAPED);
  729. state->infcs = PPP_INITFCS;
  730. }
  731. if (*dp == PPP_ESCAPE) {
  732. state->flags |= ESCAPED;
  733. continue;
  734. }
  735. /*
  736. * Make sure we un-escape the necessary characters, as well as the
  737. * ones in our receive async control character map
  738. */
  739. if (state->flags & ESCAPED) {
  740. *dp ^= PPP_TRANS;
  741. state->flags &= ~ESCAPED;
  742. } else if (IN_RX_MAP(*dp, state->raccm))
  743. continue;
  744. /*
  745. * Unless the peer lied to us about the negotiated MRU, we should
  746. * never get a frame which is too long. If it happens, toss it away
  747. * and grab the next incoming one
  748. */
  749. if (msgdsize(state->rx_buf) < state->rx_buf_size) {
  750. state->infcs = PPP_FCS(state->infcs, *dp);
  751. *state->rx_buf->b_wptr++ = *dp;
  752. } else {
  753. DPRINT2("ppp%d: frame too long (%d)\n",
  754. state->unit, msgdsize(state->rx_buf));
  755. freemsg(state->rx_buf);
  756. state->rx_buf = 0;
  757. state->flags |= IFLUSH;
  758. }
  759. }
  760. #if defined(USE_MUTEX)
  761. mutex_exit(&state->lock);
  762. #endif /* USE_MUTEX */
  763. }
  764. static int
  765. msg_byte(mp, i)
  766. mblk_t *mp;
  767. unsigned int i;
  768. {
  769. while (mp != 0 && i >= mp->b_wptr - mp->b_rptr)
  770. mp = mp->b_cont;
  771. if (mp == 0)
  772. return -1;
  773. return mp->b_rptr[i];
  774. }