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