async.c revision 30715
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.11 1997/08/25 00:29:05 brian Exp $ 21 * 22 */ 23#include <sys/param.h> 24#include <netinet/in.h> 25 26#include <stdio.h> 27#include <string.h> 28#include <termios.h> 29 30#include "mbuf.h" 31#include "log.h" 32#include "defs.h" 33#include "timer.h" 34#include "fsm.h" 35#include "hdlc.h" 36#include "lcp.h" 37#include "lcpproto.h" 38#include "modem.h" 39#include "loadalias.h" 40#include "command.h" 41#include "vars.h" 42#include "os.h" 43#include "async.h" 44 45#define HDLCSIZE (MAX_MRU*2+6) 46 47static struct async_state { 48 int mode; 49 int length; 50 u_char hbuff[HDLCSIZE]; /* recv buffer */ 51 u_char xbuff[HDLCSIZE]; /* xmit buffer */ 52 u_long my_accmap; 53 u_long his_accmap; 54} AsyncState; 55 56#define MODE_HUNT 0x01 57#define MODE_ESC 0x02 58 59void 60AsyncInit() 61{ 62 struct async_state *stp = &AsyncState; 63 64 stp->mode = MODE_HUNT; 65 stp->length = 0; 66 stp->my_accmap = stp->his_accmap = 0xffffffff; 67} 68 69void 70SetLinkParams(struct lcpstate *lcp) 71{ 72 struct async_state *stp = &AsyncState; 73 74 stp->my_accmap = lcp->want_accmap; 75 stp->his_accmap = lcp->his_accmap; 76} 77 78/* 79 * Encode into async HDLC byte code if necessary 80 */ 81static 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 OsAddOutOctets(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 OsAddInOctets(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