async.c revision 26857
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.9 1997/06/09 03:27:12 brian Exp $ 21 * 22 */ 23#include "fsm.h" 24#include "hdlc.h" 25#include "lcp.h" 26#include "lcpproto.h" 27#include "modem.h" 28#include "loadalias.h" 29#include "vars.h" 30#include "os.h" 31 32#define HDLCSIZE (MAX_MRU*2+6) 33 34struct async_state { 35 int mode; 36 int length; 37 u_char hbuff[HDLCSIZE]; /* recv buffer */ 38 u_char xbuff[HDLCSIZE]; /* xmit buffer */ 39 u_long my_accmap; 40 u_long his_accmap; 41} AsyncState; 42 43#define MODE_HUNT 0x01 44#define MODE_ESC 0x02 45 46void 47AsyncInit() 48{ 49 struct async_state *stp = &AsyncState; 50 51 stp->mode = MODE_HUNT; 52 stp->length = 0; 53 stp->my_accmap = stp->his_accmap = 0xffffffff; 54} 55 56void 57SetLinkParams(lcp) 58struct lcpstate *lcp; 59{ 60 struct async_state *stp = &AsyncState; 61 62 stp->my_accmap = lcp->want_accmap; 63 stp->his_accmap = lcp->his_accmap; 64} 65 66/* 67 * Encode into async HDLC byte code if necessary 68 */ 69static void 70HdlcPutByte(cp, c, proto) 71u_char **cp; 72u_char c; 73int proto; 74{ 75 u_char *wp; 76 77 wp = *cp; 78 if ((c < 0x20 && (proto == PROTO_LCP || (AsyncState.his_accmap & (1<<c)))) 79 || (c == HDLC_ESC) || (c == HDLC_SYN)) { 80 *wp++ = HDLC_ESC; 81 c ^= HDLC_XOR; 82 } 83 if (EscMap[32] && EscMap[c >> 3] & (1 << (c&7))) { 84 *wp++ = HDLC_ESC; 85 c ^= HDLC_XOR; 86 } 87 *wp++ = c; 88 *cp = wp; 89} 90 91void 92AsyncOutput(pri, bp, proto) 93int pri; 94struct mbuf *bp; 95int proto; 96{ 97 struct async_state *hs = &AsyncState; 98 u_char *cp, *sp, *ep; 99 struct mbuf *wp; 100 int cnt; 101 102 if (plength(bp) > HDLCSIZE) { 103 pfree(bp); 104 return; 105 } 106 cp = hs->xbuff; 107 ep = cp + HDLCSIZE - 10; 108 wp = bp; 109 *cp ++ = HDLC_SYN; 110 while (wp) { 111 sp = MBUF_CTOP(wp); 112 for (cnt = wp->cnt; cnt > 0; cnt--) { 113 HdlcPutByte(&cp, *sp++, proto); 114 if (cp >= ep) { 115 pfree(bp); 116 return; 117 } 118 } 119 wp = wp->next; 120 } 121 *cp ++ = HDLC_SYN; 122 123 cnt = cp - hs->xbuff; 124 LogDumpBuff(LogASYNC, "WriteModem", hs->xbuff, cnt); 125 WriteModem(pri, (char *)hs->xbuff, cnt); 126 OsAddOutOctets(cnt); 127 pfree(bp); 128} 129 130struct mbuf * 131AsyncDecode(c) 132u_char c; 133{ 134 struct async_state *hs = &AsyncState; 135 struct mbuf *bp; 136 137 if ((hs->mode & MODE_HUNT) && c != HDLC_SYN) 138 return(NULLBUFF); 139 140 switch (c) { 141 case HDLC_SYN: 142 hs->mode &= ~MODE_HUNT; 143 if (hs->length) { /* packet is ready. */ 144 bp = mballoc(hs->length, MB_ASYNC); 145 mbwrite(bp, hs->hbuff, hs->length); 146 hs->length = 0; 147 return(bp); 148 } 149 break; 150 case HDLC_ESC: 151 if (!(hs->mode & MODE_ESC)) { 152 hs->mode |= MODE_ESC; 153 break; 154 } 155 /* Fall into ... */ 156 default: 157 if (hs->length >= HDLCSIZE) { 158 /* packet is too large, discard it */ 159 LogPrintf(LogERROR, "Packet too large (%d), discarding.\n", hs->length); 160 hs->length = 0; 161 hs->mode = MODE_HUNT; 162 break; 163 } 164 if (hs->mode & MODE_ESC) { 165 c ^= HDLC_XOR; 166 hs->mode &= ~MODE_ESC; 167 } 168 hs->hbuff[hs->length++] = c; 169 break; 170 } 171 return NULLBUFF; 172} 173 174void 175AsyncInput(buff, cnt) 176u_char *buff; 177int cnt; 178{ 179 struct mbuf *bp; 180 181 OsAddInOctets(cnt); 182 if (DEV_IS_SYNC) { 183 bp = mballoc(cnt, MB_ASYNC); 184 bcopy(buff, MBUF_CTOP(bp), cnt); 185 bp->cnt = cnt; 186 HdlcInput(bp); 187 } else { 188 while (cnt > 0) { 189 bp = AsyncDecode(*buff++); 190 if (bp) 191 HdlcInput(bp); 192 cnt--; 193 } 194 } 195} 196