async.c revision 22997
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$
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#include "os.h"
30
31#define HDLCSIZE	(MAX_MRU*2+6)
32
33struct async_state {
34  int mode;
35  int length;
36  u_char hbuff[HDLCSIZE];	/* recv buffer */
37  u_char xbuff[HDLCSIZE];	/* xmit buffer */
38  u_long my_accmap;
39  u_long his_accmap;
40} AsyncState;
41
42#define MODE_HUNT 0x01
43#define MODE_ESC  0x02
44
45void
46AsyncInit()
47{
48  struct async_state *stp = &AsyncState;
49
50  stp->mode = MODE_HUNT;
51  stp->length = 0;
52  stp->my_accmap = stp->his_accmap = 0xffffffff;
53}
54
55void
56SetLinkParams(lcp)
57struct lcpstate *lcp;
58{
59  struct async_state *stp = &AsyncState;
60
61  stp->my_accmap = lcp->want_accmap;
62  stp->his_accmap = lcp->his_accmap;
63}
64
65/*
66 * Encode into async HDLC byte code if necessary
67 */
68static void
69HdlcPutByte(cp, c, proto)
70u_char **cp;
71u_char c;
72int proto;
73{
74  u_char *wp;
75
76  wp = *cp;
77  if ((c < 0x20 && (proto == PROTO_LCP || (AsyncState.his_accmap & (1<<c))))
78	|| (c == HDLC_ESC) || (c == HDLC_SYN)) {
79    *wp++ = HDLC_ESC;
80    c ^= HDLC_XOR;
81  }
82  if (EscMap[32] && EscMap[c >> 3] &  (1 << (c&7))) {
83    *wp++ = HDLC_ESC;
84    c ^= HDLC_XOR;
85  }
86  *wp++ = c;
87  *cp = wp;
88}
89
90void
91AsyncOutput(pri, bp, proto)
92int pri;
93struct mbuf *bp;
94int proto;
95{
96  struct async_state *hs = &AsyncState;
97  u_char *cp, *sp, *ep;
98  struct mbuf *wp;
99  int cnt;
100
101  if (plength(bp) > HDLCSIZE) {
102    pfree(bp);
103    return;
104  }
105  cp = hs->xbuff;
106  ep = cp + HDLCSIZE - 10;
107  wp = bp;
108  *cp ++ = HDLC_SYN;
109  while (wp) {
110    sp = MBUF_CTOP(wp);
111    for (cnt = wp->cnt; cnt > 0; cnt--) {
112      HdlcPutByte(&cp, *sp++, proto);
113      if (cp >= ep) {
114	pfree(bp);
115	return;
116      }
117    }
118    wp = wp->next;
119  }
120  *cp ++ = HDLC_SYN;
121
122  cnt = cp - hs->xbuff;
123  LogDumpBuff(LOG_ASYNC, "WriteModem", hs->xbuff, cnt);
124  WriteModem(pri, (char *)hs->xbuff, cnt);
125  OsAddOutOctets(cnt);
126  pfree(bp);
127}
128
129struct mbuf *
130AsyncDecode(c)
131u_char c;
132{
133  struct async_state *hs = &AsyncState;
134  struct mbuf *bp;
135
136  if ((hs->mode & MODE_HUNT) && c != HDLC_SYN)
137    return(NULLBUFF);
138
139  switch (c) {
140  case HDLC_SYN:
141    hs->mode &= ~MODE_HUNT;
142    if (hs->length) {	/* packet is ready. */
143      bp = mballoc(hs->length, MB_ASYNC);
144      mbwrite(bp, hs->hbuff, hs->length);
145      hs->length = 0;
146      return(bp);
147    }
148    break;
149  case HDLC_ESC:
150    if (!(hs->mode & MODE_ESC)) {
151      hs->mode |= MODE_ESC;
152      break;
153    }
154    /* Fall into ... */
155  default:
156    if (hs->length >= HDLCSIZE) {
157      /* packet is too large, discard it */
158      logprintf("too large, diacarding.\n");
159      hs->length = 0;
160      hs->mode = MODE_HUNT;
161      break;
162    }
163    if (hs->mode & MODE_ESC) {
164      c ^= HDLC_XOR;
165      hs->mode &= ~MODE_ESC;
166    }
167    hs->hbuff[hs->length++] = c;
168    break;
169  }
170  return NULLBUFF;
171}
172
173void
174AsyncInput(buff, cnt)
175u_char *buff;
176int cnt;
177{
178  struct mbuf *bp;
179
180  OsAddInOctets(cnt);
181  if (DEV_IS_SYNC) {
182    bp = mballoc(cnt, MB_ASYNC);
183    bcopy(buff, MBUF_CTOP(bp), cnt);
184    bp->cnt = cnt;
185    HdlcInput(bp);
186  } else {
187    while (cnt > 0) {
188      bp = AsyncDecode(*buff++);
189      if (bp)
190        HdlcInput(bp);
191      cnt--;
192    }
193  }
194}
195