async.c revision 46686
1279377Simp/* 2279377Simp * PPP Async HDLC Module 3279377Simp * 4279377Simp * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5279377Simp * 6279377Simp * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7279377Simp * 8279377Simp * Redistribution and use in source and binary forms are permitted 9279377Simp * provided that the above copyright notice and this paragraph are 10279377Simp * duplicated in all such forms and that any documentation, 11279377Simp * advertising materials, and other materials related to such 12279377Simp * distribution and use acknowledge that the software was developed 13279377Simp * by the Internet Initiative Japan, Inc. The name of the 14279377Simp * IIJ may not be used to endorse or promote products derived 15279377Simp * from this software without specific prior written permission. 16279377Simp * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17279377Simp * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18279377Simp * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19279377Simp * 20279377Simp * $Id: async.c,v 1.18 1999/04/11 08:51:04 brian Exp $ 21279377Simp * 22279377Simp */ 23279377Simp#include <sys/types.h> 24279377Simp 25279377Simp#include <string.h> 26279377Simp#include <termios.h> 27279377Simp 28279377Simp#include "layer.h" 29295436Sandrew#include "mbuf.h" 30279377Simp#include "log.h" 31279377Simp#include "defs.h" 32279377Simp#include "timer.h" 33279377Simp#include "fsm.h" 34295436Sandrew#include "lqr.h" 35295436Sandrew#include "hdlc.h" 36295436Sandrew#include "lcp.h" 37295436Sandrew#include "proto.h" 38295436Sandrew#include "async.h" 39295436Sandrew#include "throughput.h" 40295436Sandrew#include "ccp.h" 41295436Sandrew#include "link.h" 42295436Sandrew#include "descriptor.h" 43295436Sandrew#include "physical.h" 44295436Sandrew 45295436Sandrew#define MODE_HUNT 0x01 46295436Sandrew#define MODE_ESC 0x02 47295436Sandrew 48295436Sandrewvoid 49295436Sandrewasync_Init(struct async *async) 50295436Sandrew{ 51295436Sandrew async->mode = MODE_HUNT; 52295436Sandrew async->length = 0; 53295436Sandrew async->my_accmap = async->his_accmap = 0xffffffff; 54295436Sandrew memset(async->cfg.EscMap, '\0', sizeof async->cfg.EscMap); 55295436Sandrew} 56295436Sandrew 57295436Sandrewvoid 58295436Sandrewasync_SetLinkParams(struct async *async, struct lcp *lcp) 59295436Sandrew{ 60295436Sandrew async->my_accmap = lcp->want_accmap; 61295436Sandrew async->his_accmap = lcp->his_accmap | lcp->want_accmap; 62295436Sandrew} 63295436Sandrew 64295436Sandrew/* 65295436Sandrew * Encode into async HDLC byte code 66295436Sandrew */ 67295436Sandrewstatic void 68295436Sandrewasync_Encode(struct async *async, u_char **cp, u_char c, int proto) 69295436Sandrew{ 70279377Simp u_char *wp; 71279377Simp 72295436Sandrew wp = *cp; 73295436Sandrew if ((c < 0x20 && (proto == PROTO_LCP || (async->his_accmap & (1 << c)))) 74295436Sandrew || (c == HDLC_ESC) || (c == HDLC_SYN)) { 75295436Sandrew *wp++ = HDLC_ESC; 76295436Sandrew c ^= HDLC_XOR; 77295436Sandrew } 78295436Sandrew if (async->cfg.EscMap[32] && async->cfg.EscMap[c >> 3] & (1 << (c & 7))) { 79279377Simp *wp++ = HDLC_ESC; 80279377Simp c ^= HDLC_XOR; 81279377Simp } 82279377Simp *wp++ = c; 83279377Simp *cp = wp; 84279377Simp} 85279377Simp 86279377Simpstatic struct mbuf * 87279377Simpasync_LayerPush(struct bundle *bundle, struct link *l, struct mbuf *bp, 88279377Simp int pri, u_short *proto) 89279377Simp{ 90279377Simp struct physical *p = link2physical(l); 91279377Simp u_char *cp, *sp, *ep; 92279377Simp struct mbuf *wp; 93279377Simp int cnt; 94279377Simp 95279377Simp if (!p || mbuf_Length(bp) > HDLCSIZE) { 96279377Simp mbuf_Free(bp); 97279377Simp return NULL; 98279377Simp } 99279377Simp 100279377Simp cp = p->async.xbuff; 101279377Simp ep = cp + HDLCSIZE - 10; 102279377Simp wp = bp; 103279377Simp *cp++ = HDLC_SYN; 104279377Simp while (wp) { 105279377Simp sp = MBUF_CTOP(wp); 106279377Simp for (cnt = wp->cnt; cnt > 0; cnt--) { 107295436Sandrew async_Encode(&p->async, &cp, *sp++, *proto); 108295436Sandrew if (cp >= ep) { 109295436Sandrew mbuf_Free(bp); 110295436Sandrew return NULL; 111295436Sandrew } 112295436Sandrew } 113295436Sandrew wp = wp->next; 114 } 115 *cp++ = HDLC_SYN; 116 117 cnt = cp - p->async.xbuff; 118 mbuf_Free(bp); 119 bp = mbuf_Alloc(cnt, MB_ASYNC); 120 memcpy(MBUF_CTOP(bp), p->async.xbuff, cnt); 121 122 log_DumpBp(LogASYNC, "WriteModem", bp); 123 return bp; 124} 125 126static struct mbuf * 127async_Decode(struct async *async, u_char c) 128{ 129 struct mbuf *bp; 130 131 if ((async->mode & MODE_HUNT) && c != HDLC_SYN) 132 return NULL; 133 134 switch (c) { 135 case HDLC_SYN: 136 async->mode &= ~MODE_HUNT; 137 if (async->length) { /* packet is ready. */ 138 bp = mbuf_Alloc(async->length, MB_ASYNC); 139 mbuf_Write(bp, async->hbuff, async->length); 140 async->length = 0; 141 return bp; 142 } 143 break; 144 case HDLC_ESC: 145 if (!(async->mode & MODE_ESC)) { 146 async->mode |= MODE_ESC; 147 break; 148 } 149 /* Fall into ... */ 150 default: 151 if (async->length >= HDLCSIZE) { 152 /* packet is too large, discard it */ 153 log_Printf(LogWARN, "Packet too large (%d), discarding.\n", 154 async->length); 155 async->length = 0; 156 async->mode = MODE_HUNT; 157 break; 158 } 159 if (async->mode & MODE_ESC) { 160 c ^= HDLC_XOR; 161 async->mode &= ~MODE_ESC; 162 } 163 async->hbuff[async->length++] = c; 164 break; 165 } 166 return NULL; 167} 168 169static struct mbuf * 170async_LayerPull(struct bundle *b, struct link *l, struct mbuf *bp, 171 u_short *proto) 172{ 173 struct mbuf *nbp, **last; 174 struct physical *p = link2physical(l); 175 u_char *ch; 176 size_t cnt; 177 178 if (!p) { 179 log_Printf(LogERROR, "Can't Pull an async packet from a logical link\n"); 180 return bp; 181 } 182 183 last = &nbp; 184 185 while (bp) { 186 ch = MBUF_CTOP(bp); 187 for (cnt = bp->cnt; cnt; cnt--) { 188 *last = async_Decode(&p->async, *ch++); 189 if (*last != NULL) 190 last = &(*last)->pnext; 191 } 192 bp = mbuf_FreeSeg(bp); 193 } 194 195 return nbp; 196} 197 198struct layer asynclayer = 199 { LAYER_ASYNC, "async", async_LayerPush, async_LayerPull }; 200