async.c revision 30825
1159248Srwatson/*
2159248Srwatson *	             PPP Async HDLC Module
3159248Srwatson *
4159248Srwatson *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5159248Srwatson *
6159248Srwatson *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7159248Srwatson *
8159248Srwatson * Redistribution and use in source and binary forms are permitted
9159248Srwatson * provided that the above copyright notice and this paragraph are
10159248Srwatson * duplicated in all such forms and that any documentation,
11159248Srwatson * advertising materials, and other materials related to such
12159248Srwatson * distribution and use acknowledge that the software was developed
13159248Srwatson * by the Internet Initiative Japan, Inc.  The name of the
14159248Srwatson * IIJ may not be used to endorse or promote products derived
15159248Srwatson * from this software without specific prior written permission.
16159248Srwatson * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17159248Srwatson * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18159248Srwatson * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19159248Srwatson *
20159248Srwatson * $Id: async.c,v 1.12 1997/10/26 01:02:05 brian Exp $
21159248Srwatson *
22159248Srwatson */
23159248Srwatson#include <sys/param.h>
24159248Srwatson#include <netinet/in.h>
25159248Srwatson
26159248Srwatson#include <stdio.h>
27159248Srwatson#include <string.h>
28159248Srwatson#include <termios.h>
29159248Srwatson
30159248Srwatson#include "mbuf.h"
31159248Srwatson#include "log.h"
32159248Srwatson#include "defs.h"
33159248Srwatson#include "timer.h"
34159248Srwatson#include "fsm.h"
35159248Srwatson#include "hdlc.h"
36159248Srwatson#include "lcp.h"
37159248Srwatson#include "lcpproto.h"
38159248Srwatson#include "modem.h"
39161630Srwatson#include "loadalias.h"
40159248Srwatson#include "command.h"
41159248Srwatson#include "vars.h"
42159248Srwatson#include "os.h"
43159248Srwatson#include "async.h"
44159248Srwatson
45159248Srwatson#define HDLCSIZE	(MAX_MRU*2+6)
46161630Srwatson
47159248Srwatsonstatic struct async_state {
48159248Srwatson  int mode;
49159248Srwatson  int length;
50161630Srwatson  u_char hbuff[HDLCSIZE];	/* recv buffer */
51159248Srwatson  u_char xbuff[HDLCSIZE];	/* xmit buffer */
52159248Srwatson  u_long my_accmap;
53159248Srwatson  u_long his_accmap;
54159248Srwatson} AsyncState;
55161630Srwatson
56161630Srwatson#define MODE_HUNT 0x01
57161630Srwatson#define MODE_ESC  0x02
58161630Srwatson
59161630Srwatsonvoid
60161630SrwatsonAsyncInit()
61159248Srwatson{
62159248Srwatson  struct async_state *stp = &AsyncState;
63159248Srwatson
64159248Srwatson  stp->mode = MODE_HUNT;
65159248Srwatson  stp->length = 0;
66159248Srwatson  stp->my_accmap = stp->his_accmap = 0xffffffff;
67159248Srwatson}
68159248Srwatson
69159248Srwatsonvoid
70159248SrwatsonSetLinkParams(struct lcpstate *lcp)
71159248Srwatson{
72159248Srwatson  struct async_state *stp = &AsyncState;
73161630Srwatson
74159248Srwatson  stp->my_accmap = lcp->want_accmap;
75159248Srwatson  stp->his_accmap = lcp->his_accmap;
76159248Srwatson}
77159248Srwatson
78161630Srwatson/*
79159248Srwatson * Encode into async HDLC byte code if necessary
80159248Srwatson */
81159248Srwatsonstatic void
82HdlcPutByte(u_char **cp, u_char c, int proto)
83{
84  u_char *wp;
85
86  wp = *cp;
87  if ((c < 0x20 && (proto == PROTO_LCP || (AsyncState.his_accmap & (1 << c))))
88      || (c == HDLC_ESC) || (c == HDLC_SYN)) {
89    *wp++ = HDLC_ESC;
90    c ^= HDLC_XOR;
91  }
92  if (EscMap[32] && EscMap[c >> 3] & (1 << (c & 7))) {
93    *wp++ = HDLC_ESC;
94    c ^= HDLC_XOR;
95  }
96  *wp++ = c;
97  *cp = wp;
98}
99
100void
101AsyncOutput(int pri, struct mbuf *bp, int proto)
102{
103  struct async_state *hs = &AsyncState;
104  u_char *cp, *sp, *ep;
105  struct mbuf *wp;
106  int cnt;
107
108  if (plength(bp) > HDLCSIZE) {
109    pfree(bp);
110    return;
111  }
112  cp = hs->xbuff;
113  ep = cp + HDLCSIZE - 10;
114  wp = bp;
115  *cp++ = HDLC_SYN;
116  while (wp) {
117    sp = MBUF_CTOP(wp);
118    for (cnt = wp->cnt; cnt > 0; cnt--) {
119      HdlcPutByte(&cp, *sp++, proto);
120      if (cp >= ep) {
121	pfree(bp);
122	return;
123      }
124    }
125    wp = wp->next;
126  }
127  *cp++ = HDLC_SYN;
128
129  cnt = cp - hs->xbuff;
130  LogDumpBuff(LogASYNC, "WriteModem", hs->xbuff, cnt);
131  WriteModem(pri, (char *) hs->xbuff, cnt);
132  ModemAddOutOctets(cnt);
133  pfree(bp);
134}
135
136static struct mbuf *
137AsyncDecode(u_char c)
138{
139  struct async_state *hs = &AsyncState;
140  struct mbuf *bp;
141
142  if ((hs->mode & MODE_HUNT) && c != HDLC_SYN)
143    return (NULLBUFF);
144
145  switch (c) {
146  case HDLC_SYN:
147    hs->mode &= ~MODE_HUNT;
148    if (hs->length) {		/* packet is ready. */
149      bp = mballoc(hs->length, MB_ASYNC);
150      mbwrite(bp, hs->hbuff, hs->length);
151      hs->length = 0;
152      return (bp);
153    }
154    break;
155  case HDLC_ESC:
156    if (!(hs->mode & MODE_ESC)) {
157      hs->mode |= MODE_ESC;
158      break;
159    }
160    /* Fall into ... */
161  default:
162    if (hs->length >= HDLCSIZE) {
163      /* packet is too large, discard it */
164      LogPrintf(LogERROR, "Packet too large (%d), discarding.\n", hs->length);
165      hs->length = 0;
166      hs->mode = MODE_HUNT;
167      break;
168    }
169    if (hs->mode & MODE_ESC) {
170      c ^= HDLC_XOR;
171      hs->mode &= ~MODE_ESC;
172    }
173    hs->hbuff[hs->length++] = c;
174    break;
175  }
176  return NULLBUFF;
177}
178
179void
180AsyncInput(u_char *buff, int cnt)
181{
182  struct mbuf *bp;
183
184  ModemAddInOctets(cnt);
185  if (DEV_IS_SYNC) {
186    bp = mballoc(cnt, MB_ASYNC);
187    memcpy(MBUF_CTOP(bp), buff, cnt);
188    bp->cnt = cnt;
189    HdlcInput(bp);
190  } else {
191    while (cnt > 0) {
192      bp = AsyncDecode(*buff++);
193      if (bp)
194	HdlcInput(bp);
195      cnt--;
196    }
197  }
198}
199