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