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.13 1997/10/29 01:19:38 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 "command.h" 31 #include "mbuf.h" 32 #include "log.h" 33 #include "defs.h" 34 #include "timer.h" 35 #include "fsm.h" 36 #include "hdlc.h" 37 #include "lcp.h" 38 #include "lcpproto.h" 39 #include "modem.h" 40 #include "loadalias.h" 41 #include "vars.h" 42 #include "os.h" 43 #include "async.h" 44 45 #define HDLCSIZE (MAX_MRU*2+6) 46 47 static 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 59 void 60 AsyncInit() 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 69 void 70 SetLinkParams(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 */ 81 static void 82 HdlcPutByte(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 100 void 101 AsyncOutput(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 ModemAddOutOctets(cnt); 133 pfree(bp); 134 } 135 136 static struct mbuf * 137 AsyncDecode(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 179 void 180 AsyncInput(u_char *buff, int cnt) 181 { 182 struct mbuf *bp; 183 184 ModemAddInOctets(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