async.c revision 37019
1102166Stjr/*
2102166Stjr *	             PPP Async HDLC Module
3102166Stjr *
4102166Stjr *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5102166Stjr *
6102166Stjr *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7102166Stjr *
8102166Stjr * Redistribution and use in source and binary forms are permitted
9102166Stjr * provided that the above copyright notice and this paragraph are
10102166Stjr * duplicated in all such forms and that any documentation,
11102166Stjr * advertising materials, and other materials related to such
12102166Stjr * distribution and use acknowledge that the software was developed
13102166Stjr * by the Internet Initiative Japan, Inc.  The name of the
14102166Stjr * IIJ may not be used to endorse or promote products derived
15102166Stjr * from this software without specific prior written permission.
16102166Stjr * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17102166Stjr * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18102166Stjr * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19102166Stjr *
20102166Stjr * $Id: async.c,v 1.16 1998/05/21 21:43:55 brian Exp $
21102166Stjr *
22102166Stjr */
23102166Stjr#include <sys/types.h>
24102166Stjr
25102166Stjr#include <string.h>
26107706Sru#include <termios.h>
27107706Sru
28102166Stjr#include "mbuf.h"
29102166Stjr#include "log.h"
30102166Stjr#include "defs.h"
31102166Stjr#include "timer.h"
32102166Stjr#include "fsm.h"
33102166Stjr#include "lqr.h"
34102166Stjr#include "hdlc.h"
35102166Stjr#include "lcp.h"
36102166Stjr#include "lcpproto.h"
37102166Stjr#include "async.h"
38102166Stjr#include "throughput.h"
39102166Stjr#include "ccp.h"
40102166Stjr#include "link.h"
41102166Stjr#include "descriptor.h"
42102166Stjr#include "physical.h"
43102166Stjr
44102166Stjr#define MODE_HUNT 0x01
45102166Stjr#define MODE_ESC  0x02
46102166Stjr
47102166Stjrvoid
48102166Stjrasync_Init(struct async *async)
49102166Stjr{
50102166Stjr  async->mode = MODE_HUNT;
51102166Stjr  async->length = 0;
52102166Stjr  async->my_accmap = async->his_accmap = 0xffffffff;
53107706Sru  memset(async->cfg.EscMap, '\0', sizeof async->cfg.EscMap);
54102166Stjr}
55102166Stjr
56102166Stjrvoid
57102166Stjrasync_SetLinkParams(struct async *async, struct lcp *lcp)
58102166Stjr{
59102166Stjr  async->my_accmap = lcp->want_accmap;
60102166Stjr  async->his_accmap = lcp->his_accmap;
61102166Stjr}
62102166Stjr
63/*
64 * Encode into async HDLC byte code if necessary
65 */
66static void
67HdlcPutByte(struct async *async, u_char **cp, u_char c, int proto)
68{
69  u_char *wp;
70
71  wp = *cp;
72  if ((c < 0x20 && (proto == PROTO_LCP || (async->his_accmap & (1 << c))))
73      || (c == HDLC_ESC) || (c == HDLC_SYN)) {
74    *wp++ = HDLC_ESC;
75    c ^= HDLC_XOR;
76  }
77  if (async->cfg.EscMap[32] && async->cfg.EscMap[c >> 3] & (1 << (c & 7))) {
78    *wp++ = HDLC_ESC;
79    c ^= HDLC_XOR;
80  }
81  *wp++ = c;
82  *cp = wp;
83}
84
85void
86async_Output(int pri, struct mbuf *bp, int proto, struct physical *physical)
87{
88  u_char *cp, *sp, *ep;
89  struct mbuf *wp;
90  int cnt;
91
92  if (mbuf_Length(bp) > HDLCSIZE) {
93    mbuf_Free(bp);
94    return;
95  }
96  cp = physical->async.xbuff;
97  ep = cp + HDLCSIZE - 10;
98  wp = bp;
99  *cp++ = HDLC_SYN;
100  while (wp) {
101    sp = MBUF_CTOP(wp);
102    for (cnt = wp->cnt; cnt > 0; cnt--) {
103      HdlcPutByte(&physical->async, &cp, *sp++, proto);
104      if (cp >= ep) {
105	mbuf_Free(bp);
106	return;
107      }
108    }
109    wp = wp->next;
110  }
111  *cp++ = HDLC_SYN;
112
113  cnt = cp - physical->async.xbuff;
114  log_DumpBuff(LogASYNC, "WriteModem", physical->async.xbuff, cnt);
115  link_Write(&physical->link, pri, (char *)physical->async.xbuff, cnt);
116  link_AddOutOctets(&physical->link, cnt);
117  mbuf_Free(bp);
118}
119
120static struct mbuf *
121async_Decode(struct async *async, u_char c)
122{
123  struct mbuf *bp;
124
125  if ((async->mode & MODE_HUNT) && c != HDLC_SYN)
126    return NULL;
127
128  switch (c) {
129  case HDLC_SYN:
130    async->mode &= ~MODE_HUNT;
131    if (async->length) {		/* packet is ready. */
132      bp = mbuf_Alloc(async->length, MB_ASYNC);
133      mbuf_Write(bp, async->hbuff, async->length);
134      async->length = 0;
135      return bp;
136    }
137    break;
138  case HDLC_ESC:
139    if (!(async->mode & MODE_ESC)) {
140      async->mode |= MODE_ESC;
141      break;
142    }
143    /* Fall into ... */
144  default:
145    if (async->length >= HDLCSIZE) {
146      /* packet is too large, discard it */
147      log_Printf(LogWARN, "Packet too large (%d), discarding.\n",
148                 async->length);
149      async->length = 0;
150      async->mode = MODE_HUNT;
151      break;
152    }
153    if (async->mode & MODE_ESC) {
154      c ^= HDLC_XOR;
155      async->mode &= ~MODE_ESC;
156    }
157    async->hbuff[async->length++] = c;
158    break;
159  }
160  return NULL;
161}
162
163void
164async_Input(struct bundle *bundle, u_char *buff, int cnt,
165            struct physical *physical)
166{
167  struct mbuf *bp;
168
169  link_AddInOctets(&physical->link, cnt);
170
171  if (physical_IsSync(physical)) {
172    bp = mbuf_Alloc(cnt, MB_ASYNC);
173    memcpy(MBUF_CTOP(bp), buff, cnt);
174    bp->cnt = cnt;
175    hdlc_Input(bundle, bp, physical);
176  } else {
177    while (cnt > 0) {
178      bp = async_Decode(&physical->async, *buff++);
179      if (bp)
180	hdlc_Input(bundle, bp, physical);
181      cnt--;
182    }
183  }
184}
185