async.c revision 8857
1/*
2 *	             PPP Async HDLC Module
3 *
4 *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5 *
6 *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the Internet Initiative Japan, Inc.  The name of the
14 * IIJ may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * $Id: async.c,v 1.3 1995/04/16 12:06:39 amurai Exp $
21 *
22 */
23#include "fsm.h"
24#include "hdlc.h"
25#include "lcp.h"
26#include "lcpproto.h"
27#include "modem.h"
28#include "vars.h"
29
30#define HDLCSIZE	(MAX_MRU*2+6)
31
32struct async_state {
33  int mode;
34  int length;
35  u_char hbuff[HDLCSIZE];	/* recv buffer */
36  u_char xbuff[HDLCSIZE];	/* xmit buffer */
37  u_long my_accmap;
38  u_long his_accmap;
39} AsyncState;
40
41#define MODE_HUNT 0x01
42#define MODE_ESC  0x02
43
44void
45AsyncInit()
46{
47  struct async_state *stp = &AsyncState;
48
49  stp->mode = MODE_HUNT;
50  stp->length = 0;
51  stp->my_accmap = stp->his_accmap = 0xffffffff;
52}
53
54void
55SetLinkParams(lcp)
56struct lcpstate *lcp;
57{
58  struct async_state *stp = &AsyncState;
59
60  stp->my_accmap = lcp->want_accmap;
61  stp->his_accmap = lcp->his_accmap;
62}
63
64/*
65 * Encode into async HDLC byte code if necessary
66 */
67static void
68HdlcPutByte(cp, c, proto)
69u_char **cp;
70u_char c;
71int proto;
72{
73  u_char *wp;
74
75  wp = *cp;
76  if ((c < 0x20 && (proto == PROTO_LCP || (AsyncState.his_accmap & (1<<c))))
77	|| (c == HDLC_ESC) || (c == HDLC_SYN)) {
78    *wp++ = HDLC_ESC;
79    c ^= HDLC_XOR;
80  }
81  if (EscMap[32] && EscMap[c >> 3] &  (1 << (c&7))) {
82    *wp++ = HDLC_ESC;
83    c ^= HDLC_XOR;
84  }
85  *wp++ = c;
86  *cp = wp;
87}
88
89void
90AsyncOutput(pri, bp, proto)
91int pri;
92struct mbuf *bp;
93int proto;
94{
95  struct async_state *hs = &AsyncState;
96  u_char *cp, *sp, *ep;
97  struct mbuf *wp;
98  int cnt;
99
100  if (plength(bp) > HDLCSIZE) {
101    pfree(bp);
102    return;
103  }
104  cp = hs->xbuff;
105  ep = cp + HDLCSIZE - 10;
106  wp = bp;
107  *cp ++ = HDLC_SYN;
108  while (wp) {
109    sp = MBUF_CTOP(wp);
110    for (cnt = wp->cnt; cnt > 0; cnt--) {
111      HdlcPutByte(&cp, *sp++, proto);
112      if (cp >= ep) {
113	pfree(bp);
114	return;
115      }
116    }
117    wp = wp->next;
118  }
119  *cp ++ = HDLC_SYN;
120
121  cnt = cp - hs->xbuff;
122  LogDumpBuff(LOG_ASYNC, "WriteModem", hs->xbuff, cnt);
123  WriteModem(pri, (char *)hs->xbuff, cnt);
124  OsAddOutOctets(cnt);
125  pfree(bp);
126}
127
128struct mbuf *
129AsyncDecode(c)
130u_char c;
131{
132  struct async_state *hs = &AsyncState;
133  struct mbuf *bp;
134
135  if ((hs->mode & MODE_HUNT) && c != HDLC_SYN)
136    return(NULLBUFF);
137
138  switch (c) {
139  case HDLC_SYN:
140    hs->mode &= ~MODE_HUNT;
141    if (hs->length) {	/* packet is ready. */
142      bp = mballoc(hs->length, MB_ASYNC);
143      mbwrite(bp, hs->hbuff, hs->length);
144      hs->length = 0;
145      return(bp);
146    }
147    break;
148  case HDLC_ESC:
149    if (!(hs->mode & MODE_ESC)) {
150      hs->mode |= MODE_ESC;
151      break;
152    }
153    /* Fall into ... */
154  default:
155    if (hs->length >= HDLCSIZE) {
156      /* packet is too large, discard it */
157      logprintf("too large, diacarding.\n");
158      hs->length = 0;
159      hs->mode = MODE_HUNT;
160      break;
161    }
162    if (hs->mode & MODE_ESC) {
163      c ^= HDLC_XOR;
164      hs->mode &= ~MODE_ESC;
165    }
166    hs->hbuff[hs->length++] = c;
167    break;
168  }
169  return NULLBUFF;
170}
171
172void
173AsyncInput(buff, cnt)
174u_char *buff;
175int cnt;
176{
177  struct mbuf *bp;
178
179  OsAddInOctets(cnt);
180  if (DEV_IS_SYNC) {
181    bp = mballoc(cnt, MB_ASYNC);
182    bcopy(buff, MBUF_CTOP(bp), cnt);
183    bp->cnt = cnt;
184    HdlcInput(bp);
185  } else {
186    while (cnt > 0) {
187      bp = AsyncDecode(*buff++);
188      if (bp)
189        HdlcInput(bp);
190      cnt--;
191    }
192  }
193}
194