async.c revision 32663
1139825Simp/*
21541Srgrimes *	             PPP Async HDLC Module
31541Srgrimes *
41541Srgrimes *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
51541Srgrimes *
61541Srgrimes *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
71541Srgrimes *
81541Srgrimes * Redistribution and use in source and binary forms are permitted
91541Srgrimes * provided that the above copyright notice and this paragraph are
101541Srgrimes * duplicated in all such forms and that any documentation,
111541Srgrimes * advertising materials, and other materials related to such
121541Srgrimes * distribution and use acknowledge that the software was developed
131541Srgrimes * by the Internet Initiative Japan, Inc.  The name of the
141541Srgrimes * IIJ may not be used to endorse or promote products derived
151541Srgrimes * from this software without specific prior written permission.
161541Srgrimes * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
171541Srgrimes * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
181541Srgrimes * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
191541Srgrimes *
201541Srgrimes * $Id: async.c,v 1.14 1997/11/22 03:37:23 brian Exp $
211541Srgrimes *
221541Srgrimes */
231541Srgrimes#include <sys/param.h>
241541Srgrimes#include <netinet/in.h>
251541Srgrimes
261541Srgrimes#include <stdio.h>
271541Srgrimes#include <string.h>
281541Srgrimes#include <termios.h>
291541Srgrimes
3050477Speter#include "command.h"
311541Srgrimes#include "mbuf.h"
321541Srgrimes#include "log.h"
331541Srgrimes#include "defs.h"
341541Srgrimes#include "timer.h"
351541Srgrimes#include "fsm.h"
36103731Swollman#include "hdlc.h"
3734319Sdufault#include "lcp.h"
38103731Swollman#include "lcpproto.h"
39103731Swollman#include "modem.h"
40103731Swollman#include "loadalias.h"
41103731Swollman#include "vars.h"
42103731Swollman#include "async.h"
43103731Swollman
44103731Swollman#define HDLCSIZE	(MAX_MRU*2+6)
45103731Swollman
46103731Swollmanstatic struct async_state {
47103731Swollman  int mode;
48103731Swollman  int length;
49103731Swollman  u_char hbuff[HDLCSIZE];	/* recv buffer */
50103731Swollman  u_char xbuff[HDLCSIZE];	/* xmit buffer */
51103731Swollman  u_long my_accmap;
52103731Swollman  u_long his_accmap;
53103731Swollman} AsyncState;
54103731Swollman
55103731Swollman#define MODE_HUNT 0x01
56103731Swollman#define MODE_ESC  0x02
57103731Swollman
58106055Swollmanvoid
59103731SwollmanAsyncInit()
60103731Swollman{
61103731Swollman  struct async_state *stp = &AsyncState;
62103731Swollman
63103731Swollman  stp->mode = MODE_HUNT;
64153006Sdavidxu  stp->length = 0;
65151659Swollman  stp->my_accmap = stp->his_accmap = 0xffffffff;
66103731Swollman}
67103731Swollman
68103731Swollmanvoid
69103731SwollmanSetLinkParams(struct lcpstate *lcp)
70151578Sdavidxu{
71103731Swollman  struct async_state *stp = &AsyncState;
72103731Swollman
73103731Swollman  stp->my_accmap = lcp->want_accmap;
74103731Swollman  stp->his_accmap = lcp->his_accmap;
75153004Sdavidxu}
76151872Sdavidxu
77103731Swollman/*
78103731Swollman * Encode into async HDLC byte code if necessary
791541Srgrimes */
80103731Swollmanstatic void
81103731SwollmanHdlcPutByte(u_char **cp, u_char c, int proto)
82103731Swollman{
83103731Swollman  u_char *wp;
84103731Swollman
851541Srgrimes  wp = *cp;
8620640Sbde  if ((c < 0x20 && (proto == PROTO_LCP || (AsyncState.his_accmap & (1 << c))))
8720640Sbde      || (c == HDLC_ESC) || (c == HDLC_SYN)) {
8820640Sbde    *wp++ = HDLC_ESC;
89103731Swollman    c ^= HDLC_XOR;
90103731Swollman  }
911541Srgrimes  if (EscMap[32] && EscMap[c >> 3] & (1 << (c & 7))) {
9220640Sbde    *wp++ = HDLC_ESC;
93103731Swollman    c ^= HDLC_XOR;
9420640Sbde  }
951541Srgrimes  *wp++ = c;
96105045Smike  *cp = wp;
97105045Smike}
98105045Smike
991541Srgrimesvoid
1001541SrgrimesAsyncOutput(int pri, struct mbuf *bp, int proto)
1011541Srgrimes{
1021541Srgrimes  struct async_state *hs = &AsyncState;
1031541Srgrimes  u_char *cp, *sp, *ep;
1041541Srgrimes  struct mbuf *wp;
1051541Srgrimes  int cnt;
106105789Sphk
1071541Srgrimes  if (plength(bp) > HDLCSIZE) {
1081541Srgrimes    pfree(bp);
1091541Srgrimes    return;
110168397Spjd  }
111168397Spjd  cp = hs->xbuff;
112105789Sphk  ep = cp + HDLCSIZE - 10;
1131541Srgrimes  wp = bp;
1141541Srgrimes  *cp++ = HDLC_SYN;
1151541Srgrimes  while (wp) {
1161541Srgrimes    sp = MBUF_CTOP(wp);
1171541Srgrimes    for (cnt = wp->cnt; cnt > 0; cnt--) {
1181541Srgrimes      HdlcPutByte(&cp, *sp++, proto);
1191541Srgrimes      if (cp >= ep) {
1201541Srgrimes	pfree(bp);
1211541Srgrimes	return;
1221541Srgrimes      }
1231541Srgrimes    }
1241541Srgrimes    wp = wp->next;
1251541Srgrimes  }
1261541Srgrimes  *cp++ = HDLC_SYN;
1271541Srgrimes
1281541Srgrimes  cnt = cp - hs->xbuff;
1291541Srgrimes  LogDumpBuff(LogASYNC, "WriteModem", hs->xbuff, cnt);
1301541Srgrimes  WriteModem(pri, (char *) hs->xbuff, cnt);
1311541Srgrimes  ModemAddOutOctets(cnt);
132103731Swollman  pfree(bp);
133103768Sbde}
134103768Sbde
135103768Sbdestatic struct mbuf *
136103731SwollmanAsyncDecode(u_char c)
13734030Sdufault{
138103731Swollman  struct async_state *hs = &AsyncState;
139103731Swollman  struct mbuf *bp;
140103731Swollman
141103731Swollman  if ((hs->mode & MODE_HUNT) && c != HDLC_SYN)
142103731Swollman    return NULL;
143103731Swollman
144103731Swollman  switch (c) {
145106055Swollman  case HDLC_SYN:
146103731Swollman    hs->mode &= ~MODE_HUNT;
14734030Sdufault    if (hs->length) {		/* packet is ready. */
148103731Swollman      bp = mballoc(hs->length, MB_ASYNC);
149105572Srwatson      mbwrite(bp, hs->hbuff, hs->length);
150105572Srwatson      hs->length = 0;
151105572Srwatson      return bp;
152105572Srwatson    }
153105572Srwatson    break;
154103731Swollman  case HDLC_ESC:
155101071Srwatson    if (!(hs->mode & MODE_ESC)) {
156168397Spjd      hs->mode |= MODE_ESC;
157168397Spjd      break;
158168397Spjd    }
159103731Swollman    /* Fall into ... */
16014222Speter  default:
16114222Speter    if (hs->length >= HDLCSIZE) {
16214222Speter      /* packet is too large, discard it */
16365557Sjasone      LogPrintf(LogERROR, "Packet too large (%d), discarding.\n", hs->length);
16414222Speter      hs->length = 0;
165103768Sbde      hs->mode = MODE_HUNT;
166103768Sbde      break;
167103768Sbde    }
168103768Sbde    if (hs->mode & MODE_ESC) {
169103768Sbde      c ^= HDLC_XOR;
170103768Sbde      hs->mode &= ~MODE_ESC;
171103768Sbde    }
172103768Sbde    hs->hbuff[hs->length++] = c;
173103768Sbde    break;
174103768Sbde  }
175103731Swollman  return NULL;
176103731Swollman}
177103768Sbde
178103731Swollmanvoid
179103768SbdeAsyncInput(u_char *buff, int cnt)
180103768Sbde{
181103768Sbde  struct mbuf *bp;
18226671Sdyson
183103731Swollman  ModemAddInOctets(cnt);
18414222Speter  if (DEV_IS_SYNC) {
1851541Srgrimes    bp = mballoc(cnt, MB_ASYNC);
186    memcpy(MBUF_CTOP(bp), buff, cnt);
187    bp->cnt = cnt;
188    HdlcInput(bp);
189  } else {
190    while (cnt > 0) {
191      bp = AsyncDecode(*buff++);
192      if (bp)
193	HdlcInput(bp);
194      cnt--;
195    }
196  }
197}
198