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