async.c revision 45586
1/*
2 *	             PPP Async HDLC Module
3 *
4 *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5 *
6 *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the Internet Initiative Japan, Inc.  The name of the
14 * IIJ may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * $Id: async.c,v 1.17 1998/06/16 19:40:34 brian Exp $
21 *
22 */
23#include <sys/types.h>
24
25#include <string.h>
26#include <termios.h>
27
28#include "mbuf.h"
29#include "log.h"
30#include "defs.h"
31#include "timer.h"
32#include "fsm.h"
33#include "lqr.h"
34#include "hdlc.h"
35#include "lcp.h"
36#include "lcpproto.h"
37#include "async.h"
38#include "throughput.h"
39#include "ccp.h"
40#include "link.h"
41#include "descriptor.h"
42#include "physical.h"
43
44#define MODE_HUNT 0x01
45#define MODE_ESC  0x02
46
47void
48async_Init(struct async *async)
49{
50  async->mode = MODE_HUNT;
51  async->length = 0;
52  async->my_accmap = async->his_accmap = 0xffffffff;
53  memset(async->cfg.EscMap, '\0', sizeof async->cfg.EscMap);
54}
55
56void
57async_SetLinkParams(struct async *async, struct lcp *lcp)
58{
59  async->my_accmap = lcp->want_accmap;
60  async->his_accmap = lcp->his_accmap | lcp->want_accmap;
61}
62
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