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.10 1997/06/23 23:08:23 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 34 struct 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 46 void 47 AsyncInit() 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 56 void 57 SetLinkParams(struct lcpstate * lcp) 58 { 59 struct async_state *stp = &AsyncState; 60 61 stp->my_accmap = lcp->want_accmap; 62 stp->his_accmap = lcp->his_accmap; 63 } 64 65 /* 66 * Encode into async HDLC byte code if necessary 67 */ 68 static void 69 HdlcPutByte(u_char ** cp, u_char c, int proto) 70 { 71 u_char *wp; 72 73 wp = *cp; 74 if ((c < 0x20 && (proto == PROTO_LCP || (AsyncState.his_accmap & (1 << c)))) 75 || (c == HDLC_ESC) || (c == HDLC_SYN)) { 76 *wp++ = HDLC_ESC; 77 c ^= HDLC_XOR; 78 } 79 if (EscMap[32] && EscMap[c >> 3] & (1 << (c & 7))) { 80 *wp++ = HDLC_ESC; 81 c ^= HDLC_XOR; 82 } 83 *wp++ = c; 84 *cp = wp; 85 } 86 87 void 88 AsyncOutput(int pri, struct mbuf * bp, int proto) 89 { 90 struct async_state *hs = &AsyncState; 91 u_char *cp, *sp, *ep; 92 struct mbuf *wp; 93 int cnt; 94 95 if (plength(bp) > HDLCSIZE) { 96 pfree(bp); 97 return; 98 } 99 cp = hs->xbuff; 100 ep = cp + HDLCSIZE - 10; 101 wp = bp; 102 *cp++ = HDLC_SYN; 103 while (wp) { 104 sp = MBUF_CTOP(wp); 105 for (cnt = wp->cnt; cnt > 0; cnt--) { 106 HdlcPutByte(&cp, *sp++, proto); 107 if (cp >= ep) { 108 pfree(bp); 109 return; 110 } 111 } 112 wp = wp->next; 113 } 114 *cp++ = HDLC_SYN; 115 116 cnt = cp - hs->xbuff; 117 LogDumpBuff(LogASYNC, "WriteModem", hs->xbuff, cnt); 118 WriteModem(pri, (char *) hs->xbuff, cnt); 119 OsAddOutOctets(cnt); 120 pfree(bp); 121 } 122 123 struct mbuf * 124 AsyncDecode(u_char c) 125 { 126 struct async_state *hs = &AsyncState; 127 struct mbuf *bp; 128 129 if ((hs->mode & MODE_HUNT) && c != HDLC_SYN) 130 return (NULLBUFF); 131 132 switch (c) { 133 case HDLC_SYN: 134 hs->mode &= ~MODE_HUNT; 135 if (hs->length) { /* packet is ready. */ 136 bp = mballoc(hs->length, MB_ASYNC); 137 mbwrite(bp, hs->hbuff, hs->length); 138 hs->length = 0; 139 return (bp); 140 } 141 break; 142 case HDLC_ESC: 143 if (!(hs->mode & MODE_ESC)) { 144 hs->mode |= MODE_ESC; 145 break; 146 } 147 /* Fall into ... */ 148 default: 149 if (hs->length >= HDLCSIZE) { 150 /* packet is too large, discard it */ 151 LogPrintf(LogERROR, "Packet too large (%d), discarding.\n", hs->length); 152 hs->length = 0; 153 hs->mode = MODE_HUNT; 154 break; 155 } 156 if (hs->mode & MODE_ESC) { 157 c ^= HDLC_XOR; 158 hs->mode &= ~MODE_ESC; 159 } 160 hs->hbuff[hs->length++] = c; 161 break; 162 } 163 return NULLBUFF; 164 } 165 166 void 167 AsyncInput(u_char * buff, int cnt) 168 { 169 struct mbuf *bp; 170 171 OsAddInOctets(cnt); 172 if (DEV_IS_SYNC) { 173 bp = mballoc(cnt, MB_ASYNC); 174 bcopy(buff, MBUF_CTOP(bp), cnt); 175 bp->cnt = cnt; 176 HdlcInput(bp); 177 } else { 178 while (cnt > 0) { 179 bp = AsyncDecode(*buff++); 180 if (bp) 181 HdlcInput(bp); 182 cnt--; 183 } 184 } 185 } 186