async.c revision 6059
1151497Sru/*
2151497Sru *	             PPP Async HDLC Module
3151497Sru *
4151497Sru *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5151497Sru *
6151497Sru *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7151497Sru *
8151497Sru * Redistribution and use in source and binary forms are permitted
9151497Sru * provided that the above copyright notice and this paragraph are
10151497Sru * duplicated in all such forms and that any documentation,
11151497Sru * advertising materials, and other materials related to such
12151497Sru * distribution and use acknowledge that the software was developed
13151497Sru * by the Internet Initiative Japan, Inc.  The name of the
14151497Sru * IIJ may not be used to endorse or promote products derived
15151497Sru * from this software without specific prior written permission.
16151497Sru * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17151497Sru * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18151497Sru * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19151497Sru *
20151497Sru * $Id:$
21151497Sru *
22151497Sru */
23151497Sru#include "fsm.h"
24151497Sru#include "hdlc.h"
25151497Sru#include "lcp.h"
26151497Sru#include "lcpproto.h"
27151497Sru#include "modem.h"
28151497Sru
29151497Sru#define HDLCSIZE	(MAX_MRU*2+6)
30151497Sru
31151497Srustruct async_state {
32151497Sru  int mode;
33151497Sru  int length;
34151497Sru  struct mbuf *hpacket;
35151497Sru  u_char hbuff[HDLCSIZE];	/* recv buffer */
36151497Sru  u_char xbuff[HDLCSIZE];	/* xmit buffer */
37151497Sru  u_long my_accmap;
38151497Sru  u_long his_accmap;
39151497Sru} AsyncState;
40151497Sru
41151497Sru#define MODE_HUNT 0x01
42151497Sru#define MODE_ESC  0x02
43151497Sru
44151497Sruvoid
45151497SruAsyncInit()
46151497Sru{
47151497Sru  struct async_state *stp = &AsyncState;
48151497Sru
49151497Sru  stp->mode = MODE_HUNT;
50151497Sru  stp->my_accmap = stp->his_accmap = 0xffffffff;
51151497Sru}
52151497Sru
53151497Sruvoid
54151497SruSetLinkParams(lcp)
55151497Srustruct lcpstate *lcp;
56151497Sru{
57151497Sru  struct async_state *stp = &AsyncState;
58151497Sru
59151497Sru  stp->my_accmap = lcp->want_accmap;
60151497Sru  stp->his_accmap = lcp->his_accmap;
61151497Sru}
62151497Sru
63151497Sru/*
64151497Sru * Encode into async HDLC byte code if necessary
65151497Sru */
66151497Srustatic void
67151497SruHdlcPutByte(cp, c, proto)
68151497Sruu_char **cp;
69151497Sruu_char c;
70151497Sruint proto;
71151497Sru{
72151497Sru  u_char *wp;
73151497Sru
74151497Sru  wp = *cp;
75151497Sru  if ((c < 0x20 && (proto == PROTO_LCP || (AsyncState.his_accmap & (1<<c))))
76151497Sru	|| (c == HDLC_ESC) || (c == HDLC_SYN)) {
77151497Sru    *wp++ = HDLC_ESC;
78151497Sru    c ^= HDLC_XOR;
79151497Sru  }
80151497Sru  if (EscMap[32] && EscMap[c >> 3] & (c&7)) {
81151497Sru    *wp++ = HDLC_ESC;
82151497Sru    c ^= HDLC_XOR;
83151497Sru  }
84151497Sru  *wp++ = c;
85151497Sru  *cp = wp;
86151497Sru}
87151497Sru
88151497Sruvoid
89151497SruAsyncOutput(pri, bp, proto)
90151497Sruint pri;
91151497Srustruct mbuf *bp;
92151497Sruint proto;
93151497Sru{
94151497Sru  struct async_state *hs = &AsyncState;
95151497Sru  u_char *cp, *sp, *ep;
96151497Sru  struct mbuf *wp;
97151497Sru  int cnt;
98151497Sru
99151497Sru  if (plength(bp) > HDLCSIZE) {
100151497Sru    pfree(bp);
101151497Sru    return;
102151497Sru  }
103151497Sru  cp = hs->xbuff;
104151497Sru  ep = cp + HDLCSIZE - 10;
105151497Sru  wp = bp;
106151497Sru  *cp ++ = HDLC_SYN;
107151497Sru  while (wp) {
108151497Sru    sp = MBUF_CTOP(wp);
109151497Sru    for (cnt = wp->cnt; cnt > 0; cnt--) {
110151497Sru      HdlcPutByte(&cp, *sp++, proto);
111151497Sru      if (cp >= ep) {
112151497Sru	pfree(bp);
113151497Sru	return;
114151497Sru      }
115151497Sru    }
116151497Sru    wp = wp->next;
117151497Sru  }
118151497Sru  *cp ++ = HDLC_SYN;
119151497Sru
120151497Sru  cnt = cp - hs->xbuff;
121151497Sru  LogDumpBuff(LOG_ASYNC, "WriteModem", hs->xbuff, cnt);
122151497Sru  WriteModem(pri, (char *)hs->xbuff, cnt);
123151497Sru  OsAddOutOctets(cnt);
124151497Sru  pfree(bp);
125151497Sru}
126151497Sru
127151497Srustruct mbuf *
128151497SruAsyncDecode(c)
129151497Sruu_char c;
130151497Sru{
131151497Sru  struct async_state *hs = &AsyncState;
132151497Sru  struct mbuf *bp;
133151497Sru
134151497Sru  if ((hs->mode & MODE_HUNT) && c != HDLC_SYN)
135151497Sru    return(NULLBUFF);
136151497Sru
137151497Sru  switch (c) {
138151497Sru  case HDLC_SYN:
139151497Sru    hs->mode &= ~MODE_HUNT;
140151497Sru    if (hs->length) {	/* packet is ready. */
141151497Sru      bp = mballoc(hs->length, MB_ASYNC);
142151497Sru      mbwrite(bp, hs->hbuff, hs->length);
143151497Sru      hs->length = 0;
144151497Sru      return(bp);
145151497Sru    }
146151497Sru    break;
147151497Sru  case HDLC_ESC:
148151497Sru    if (!(hs->mode & MODE_ESC)) {
149151497Sru      hs->mode |= MODE_ESC;
150151497Sru      break;
151151497Sru    }
152151497Sru    /* Fall into ... */
153151497Sru  default:
154151497Sru    if (hs->length >= HDLCSIZE) {
155151497Sru      /* packet is too large, discard it */
156151497Sru      logprintf("too large, diacarding.\n");
157151497Sru      hs->length = 0;
158151497Sru      hs->mode = MODE_HUNT;
159151497Sru      break;
160151497Sru    }
161151497Sru    if (hs->mode & MODE_ESC) {
162151497Sru      c ^= HDLC_XOR;
163151497Sru      hs->mode &= ~MODE_ESC;
164151497Sru    }
165151497Sru    hs->hbuff[hs->length++] = c;
166151497Sru    break;
167151497Sru  }
168151497Sru  return NULLBUFF;
169151497Sru}
170151497Sru
171151497Sruvoid
172151497SruAsyncInput(buff, cnt)
173151497Sruu_char *buff;
174151497Sruint cnt;
175151497Sru{
176151497Sru  struct mbuf *bp;
177151497Sru
178151497Sru  OsAddInOctets(cnt);
179151497Sru  while (cnt > 0) {
180151497Sru    bp = AsyncDecode(*buff++);
181151497Sru    if (bp)
182151497Sru      HdlcInput(bp);
183151497Sru    cnt--;
184151497Sru  }
185151497Sru}
186151497Sru