async.c revision 50479
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 * $FreeBSD: head/usr.sbin/ppp/async.c 50479 1999-08-28 01:35:59Z peter $ 21 * 22 */ 23#include <sys/types.h> 24 25#include <string.h> 26#include <termios.h> 27 28#include "layer.h" 29#include "mbuf.h" 30#include "log.h" 31#include "defs.h" 32#include "timer.h" 33#include "fsm.h" 34#include "lqr.h" 35#include "hdlc.h" 36#include "lcp.h" 37#include "proto.h" 38#include "async.h" 39#include "throughput.h" 40#include "ccp.h" 41#include "link.h" 42#include "descriptor.h" 43#include "physical.h" 44 45#define MODE_HUNT 0x01 46#define MODE_ESC 0x02 47 48void 49async_Init(struct async *async) 50{ 51 async->mode = MODE_HUNT; 52 async->length = 0; 53 async->my_accmap = async->his_accmap = 0xffffffff; 54 memset(async->cfg.EscMap, '\0', sizeof async->cfg.EscMap); 55} 56 57void 58async_SetLinkParams(struct async *async, struct lcp *lcp) 59{ 60 async->my_accmap = lcp->want_accmap; 61 async->his_accmap = lcp->his_accmap | lcp->want_accmap; 62} 63 64/* 65 * Encode into async HDLC byte code 66 */ 67static void 68async_Encode(struct async *async, u_char **cp, u_char c, int proto) 69{ 70 u_char *wp; 71 72 wp = *cp; 73 if ((c < 0x20 && (proto == PROTO_LCP || (async->his_accmap & (1 << c)))) 74 || (c == HDLC_ESC) || (c == HDLC_SYN)) { 75 *wp++ = HDLC_ESC; 76 c ^= HDLC_XOR; 77 } 78 if (async->cfg.EscMap[32] && async->cfg.EscMap[c >> 3] & (1 << (c & 7))) { 79 *wp++ = HDLC_ESC; 80 c ^= HDLC_XOR; 81 } 82 *wp++ = c; 83 *cp = wp; 84} 85 86static struct mbuf * 87async_LayerPush(struct bundle *bundle, struct link *l, struct mbuf *bp, 88 int pri, u_short *proto) 89{ 90 struct physical *p = link2physical(l); 91 u_char *cp, *sp, *ep; 92 struct mbuf *wp; 93 int cnt; 94 95 if (!p || mbuf_Length(bp) > HDLCSIZE) { 96 mbuf_Free(bp); 97 return NULL; 98 } 99 100 cp = p->async.xbuff; 101 ep = cp + HDLCSIZE - 10; 102 wp = bp; 103 *cp++ = HDLC_SYN; 104 while (wp) { 105 sp = MBUF_CTOP(wp); 106 for (cnt = wp->cnt; cnt > 0; cnt--) { 107 async_Encode(&p->async, &cp, *sp++, *proto); 108 if (cp >= ep) { 109 mbuf_Free(bp); 110 return NULL; 111 } 112 } 113 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_ASYNCOUT); 120 memcpy(MBUF_CTOP(bp), p->async.xbuff, cnt); 121 log_DumpBp(LogASYNC, "Write", bp); 122 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_ASYNCIN); 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 log_DumpBp(LogASYNC, "Read", bp); 186 while (bp) { 187 ch = MBUF_CTOP(bp); 188 for (cnt = bp->cnt; cnt; cnt--) { 189 *last = async_Decode(&p->async, *ch++); 190 if (*last != NULL) 191 last = &(*last)->pnext; 192 } 193 bp = mbuf_FreeSeg(bp); 194 } 195 196 return nbp; 197} 198 199struct layer asynclayer = 200 { LAYER_ASYNC, "async", async_LayerPush, async_LayerPull }; 201