async.c revision 32663
1272343Sngie/*
2272343Sngie *	             PPP Async HDLC Module
3272343Sngie *
4272343Sngie *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5272343Sngie *
6272343Sngie *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7272343Sngie *
8272343Sngie * Redistribution and use in source and binary forms are permitted
9272343Sngie * provided that the above copyright notice and this paragraph are
10272343Sngie * duplicated in all such forms and that any documentation,
11272343Sngie * advertising materials, and other materials related to such
12272343Sngie * distribution and use acknowledge that the software was developed
13272343Sngie * by the Internet Initiative Japan, Inc.  The name of the
14272343Sngie * IIJ may not be used to endorse or promote products derived
15272343Sngie * from this software without specific prior written permission.
16272343Sngie * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17272343Sngie * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18272343Sngie * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19272343Sngie *
20272343Sngie * $Id: async.c,v 1.14 1997/11/22 03:37:23 brian Exp $
21272343Sngie *
22272343Sngie */
23272343Sngie#include <sys/param.h>
24272343Sngie#include <netinet/in.h>
25272343Sngie
26272343Sngie#include <stdio.h>
27272343Sngie#include <string.h>
28272343Sngie#include <termios.h>
29272343Sngie
30272343Sngie#include "command.h"
31272343Sngie#include "mbuf.h"
32272343Sngie#include "log.h"
33272343Sngie#include "defs.h"
34272343Sngie#include "timer.h"
35272343Sngie#include "fsm.h"
36272343Sngie#include "hdlc.h"
37272343Sngie#include "lcp.h"
38272343Sngie#include "lcpproto.h"
39272343Sngie#include "modem.h"
40272343Sngie#include "loadalias.h"
41272343Sngie#include "vars.h"
42272343Sngie#include "async.h"
43272343Sngie
44272343Sngie#define HDLCSIZE	(MAX_MRU*2+6)
45272343Sngie
46272343Sngiestatic struct async_state {
47272343Sngie  int mode;
48272343Sngie  int length;
49272343Sngie  u_char hbuff[HDLCSIZE];	/* recv buffer */
50272343Sngie  u_char xbuff[HDLCSIZE];	/* xmit buffer */
51272343Sngie  u_long my_accmap;
52272343Sngie  u_long his_accmap;
53272343Sngie} AsyncState;
54272343Sngie
55272343Sngie#define MODE_HUNT 0x01
56272343Sngie#define MODE_ESC  0x02
57272343Sngie
58272343Sngievoid
59272343SngieAsyncInit()
60272343Sngie{
61272343Sngie  struct async_state *stp = &AsyncState;
62272343Sngie
63272343Sngie  stp->mode = MODE_HUNT;
64272343Sngie  stp->length = 0;
65272343Sngie  stp->my_accmap = stp->his_accmap = 0xffffffff;
66272343Sngie}
67272343Sngie
68272343Sngievoid
69272343SngieSetLinkParams(struct lcpstate *lcp)
70272343Sngie{
71272343Sngie  struct async_state *stp = &AsyncState;
72272343Sngie
73272343Sngie  stp->my_accmap = lcp->want_accmap;
74272343Sngie  stp->his_accmap = lcp->his_accmap;
75272343Sngie}
76272343Sngie
77272343Sngie/*
78272343Sngie * Encode into async HDLC byte code if necessary
79272343Sngie */
80272343Sngiestatic void
81272343SngieHdlcPutByte(u_char **cp, u_char c, int proto)
82272343Sngie{
83272343Sngie  u_char *wp;
84272343Sngie
85272343Sngie  wp = *cp;
86272343Sngie  if ((c < 0x20 && (proto == PROTO_LCP || (AsyncState.his_accmap & (1 << c))))
87272343Sngie      || (c == HDLC_ESC) || (c == HDLC_SYN)) {
88272343Sngie    *wp++ = HDLC_ESC;
89272343Sngie    c ^= HDLC_XOR;
90272343Sngie  }
91272343Sngie  if (EscMap[32] && EscMap[c >> 3] & (1 << (c & 7))) {
92272343Sngie    *wp++ = HDLC_ESC;
93272343Sngie    c ^= HDLC_XOR;
94272343Sngie  }
95272343Sngie  *wp++ = c;
96272343Sngie  *cp = wp;
97272343Sngie}
98272343Sngie
99272343Sngievoid
100272343SngieAsyncOutput(int pri, struct mbuf *bp, int proto)
101272343Sngie{
102272343Sngie  struct async_state *hs = &AsyncState;
103272343Sngie  u_char *cp, *sp, *ep;
104272343Sngie  struct mbuf *wp;
105272343Sngie  int cnt;
106272343Sngie
107272343Sngie  if (plength(bp) > HDLCSIZE) {
108272343Sngie    pfree(bp);
109272343Sngie    return;
110272343Sngie  }
111272343Sngie  cp = hs->xbuff;
112272343Sngie  ep = cp + HDLCSIZE - 10;
113272343Sngie  wp = bp;
114272343Sngie  *cp++ = HDLC_SYN;
115272343Sngie  while (wp) {
116272343Sngie    sp = MBUF_CTOP(wp);
117272343Sngie    for (cnt = wp->cnt; cnt > 0; cnt--) {
118272343Sngie      HdlcPutByte(&cp, *sp++, proto);
119272343Sngie      if (cp >= ep) {
120272343Sngie	pfree(bp);
121272343Sngie	return;
122272343Sngie      }
123272343Sngie    }
124272343Sngie    wp = wp->next;
125272343Sngie  }
126272343Sngie  *cp++ = HDLC_SYN;
127272343Sngie
128272343Sngie  cnt = cp - hs->xbuff;
129272343Sngie  LogDumpBuff(LogASYNC, "WriteModem", hs->xbuff, cnt);
130272343Sngie  WriteModem(pri, (char *) hs->xbuff, cnt);
131272343Sngie  ModemAddOutOctets(cnt);
132272343Sngie  pfree(bp);
133272343Sngie}
134272343Sngie
135272343Sngiestatic struct mbuf *
136272343SngieAsyncDecode(u_char c)
137272343Sngie{
138272343Sngie  struct async_state *hs = &AsyncState;
139272343Sngie  struct mbuf *bp;
140272343Sngie
141272343Sngie  if ((hs->mode & MODE_HUNT) && c != HDLC_SYN)
142272343Sngie    return NULL;
143272343Sngie
144272343Sngie  switch (c) {
145272343Sngie  case HDLC_SYN:
146272343Sngie    hs->mode &= ~MODE_HUNT;
147272343Sngie    if (hs->length) {		/* packet is ready. */
148272343Sngie      bp = mballoc(hs->length, MB_ASYNC);
149272343Sngie      mbwrite(bp, hs->hbuff, hs->length);
150272343Sngie      hs->length = 0;
151272343Sngie      return bp;
152272343Sngie    }
153272343Sngie    break;
154272343Sngie  case HDLC_ESC:
155272343Sngie    if (!(hs->mode & MODE_ESC)) {
156272343Sngie      hs->mode |= MODE_ESC;
157272343Sngie      break;
158272343Sngie    }
159272343Sngie    /* Fall into ... */
160272343Sngie  default:
161272343Sngie    if (hs->length >= HDLCSIZE) {
162272343Sngie      /* packet is too large, discard it */
163272343Sngie      LogPrintf(LogERROR, "Packet too large (%d), discarding.\n", hs->length);
164272343Sngie      hs->length = 0;
165272343Sngie      hs->mode = MODE_HUNT;
166272343Sngie      break;
167272343Sngie    }
168272343Sngie    if (hs->mode & MODE_ESC) {
169272343Sngie      c ^= HDLC_XOR;
170272343Sngie      hs->mode &= ~MODE_ESC;
171272343Sngie    }
172272343Sngie    hs->hbuff[hs->length++] = c;
173272343Sngie    break;
174272343Sngie  }
175272343Sngie  return NULL;
176272343Sngie}
177272343Sngie
178272343Sngievoid
179272343SngieAsyncInput(u_char *buff, int cnt)
180272343Sngie{
181272343Sngie  struct mbuf *bp;
182272343Sngie
183272343Sngie  ModemAddInOctets(cnt);
184272343Sngie  if (DEV_IS_SYNC) {
185272343Sngie    bp = mballoc(cnt, MB_ASYNC);
186272343Sngie    memcpy(MBUF_CTOP(bp), buff, cnt);
187272343Sngie    bp->cnt = cnt;
188272343Sngie    HdlcInput(bp);
189272343Sngie  } else {
190272343Sngie    while (cnt > 0) {
191272343Sngie      bp = AsyncDecode(*buff++);
192272343Sngie      if (bp)
193272343Sngie	HdlcInput(bp);
194272343Sngie      cnt--;
195272343Sngie    }
196272343Sngie  }
197272343Sngie}
198272343Sngie