async.c revision 28679
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.10 1997/06/23 23:08:23 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(struct 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(u_char ** cp, u_char c, int proto)
70{
71  u_char *wp;
72
73  wp = *cp;
74  if ((c < 0x20 && (proto == PROTO_LCP || (AsyncState.his_accmap & (1 << c))))
75      || (c == HDLC_ESC) || (c == HDLC_SYN)) {
76    *wp++ = HDLC_ESC;
77    c ^= HDLC_XOR;
78  }
79  if (EscMap[32] && EscMap[c >> 3] & (1 << (c & 7))) {
80    *wp++ = HDLC_ESC;
81    c ^= HDLC_XOR;
82  }
83  *wp++ = c;
84  *cp = wp;
85}
86
87void
88AsyncOutput(int pri, struct mbuf * bp, int proto)
89{
90  struct async_state *hs = &AsyncState;
91  u_char *cp, *sp, *ep;
92  struct mbuf *wp;
93  int cnt;
94
95  if (plength(bp) > HDLCSIZE) {
96    pfree(bp);
97    return;
98  }
99  cp = hs->xbuff;
100  ep = cp + HDLCSIZE - 10;
101  wp = bp;
102  *cp++ = HDLC_SYN;
103  while (wp) {
104    sp = MBUF_CTOP(wp);
105    for (cnt = wp->cnt; cnt > 0; cnt--) {
106      HdlcPutByte(&cp, *sp++, proto);
107      if (cp >= ep) {
108	pfree(bp);
109	return;
110      }
111    }
112    wp = wp->next;
113  }
114  *cp++ = HDLC_SYN;
115
116  cnt = cp - hs->xbuff;
117  LogDumpBuff(LogASYNC, "WriteModem", hs->xbuff, cnt);
118  WriteModem(pri, (char *) hs->xbuff, cnt);
119  OsAddOutOctets(cnt);
120  pfree(bp);
121}
122
123struct mbuf *
124AsyncDecode(u_char c)
125{
126  struct async_state *hs = &AsyncState;
127  struct mbuf *bp;
128
129  if ((hs->mode & MODE_HUNT) && c != HDLC_SYN)
130    return (NULLBUFF);
131
132  switch (c) {
133  case HDLC_SYN:
134    hs->mode &= ~MODE_HUNT;
135    if (hs->length) {		/* packet is ready. */
136      bp = mballoc(hs->length, MB_ASYNC);
137      mbwrite(bp, hs->hbuff, hs->length);
138      hs->length = 0;
139      return (bp);
140    }
141    break;
142  case HDLC_ESC:
143    if (!(hs->mode & MODE_ESC)) {
144      hs->mode |= MODE_ESC;
145      break;
146    }
147    /* Fall into ... */
148  default:
149    if (hs->length >= HDLCSIZE) {
150      /* packet is too large, discard it */
151      LogPrintf(LogERROR, "Packet too large (%d), discarding.\n", hs->length);
152      hs->length = 0;
153      hs->mode = MODE_HUNT;
154      break;
155    }
156    if (hs->mode & MODE_ESC) {
157      c ^= HDLC_XOR;
158      hs->mode &= ~MODE_ESC;
159    }
160    hs->hbuff[hs->length++] = c;
161    break;
162  }
163  return NULLBUFF;
164}
165
166void
167AsyncInput(u_char * buff, int cnt)
168{
169  struct mbuf *bp;
170
171  OsAddInOctets(cnt);
172  if (DEV_IS_SYNC) {
173    bp = mballoc(cnt, MB_ASYNC);
174    bcopy(buff, MBUF_CTOP(bp), cnt);
175    bp->cnt = cnt;
176    HdlcInput(bp);
177  } else {
178    while (cnt > 0) {
179      bp = AsyncDecode(*buff++);
180      if (bp)
181	HdlcInput(bp);
182      cnt--;
183    }
184  }
185}
186