178189Sbrian/*- 278189Sbrian * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 378189Sbrian * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 478189Sbrian * Internet Initiative Japan, Inc (IIJ) 578189Sbrian * All rights reserved. 66059Samurai * 778189Sbrian * Redistribution and use in source and binary forms, with or without 878189Sbrian * modification, are permitted provided that the following conditions 978189Sbrian * are met: 1078189Sbrian * 1. Redistributions of source code must retain the above copyright 1178189Sbrian * notice, this list of conditions and the following disclaimer. 1278189Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1378189Sbrian * notice, this list of conditions and the following disclaimer in the 1478189Sbrian * documentation and/or other materials provided with the distribution. 156059Samurai * 1678189Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1778189Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1878189Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1978189Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2078189Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2178189Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2278189Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2378189Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2478189Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2578189Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2678189Sbrian * SUCH DAMAGE. 276059Samurai * 286059Samurai */ 2978189Sbrian 30102413Scharnier#include <sys/cdefs.h> 31102413Scharnier__FBSDID("$FreeBSD$"); 32102413Scharnier 3336285Sbrian#include <sys/types.h> 3430715Sbrian 3530715Sbrian#include <string.h> 3630715Sbrian#include <termios.h> 3730715Sbrian 3846686Sbrian#include "layer.h" 3930715Sbrian#include "mbuf.h" 4030715Sbrian#include "log.h" 4130715Sbrian#include "defs.h" 4230715Sbrian#include "timer.h" 436059Samurai#include "fsm.h" 4436285Sbrian#include "lqr.h" 456059Samurai#include "hdlc.h" 466059Samurai#include "lcp.h" 4746686Sbrian#include "proto.h" 4830715Sbrian#include "async.h" 4936285Sbrian#include "throughput.h" 5036285Sbrian#include "ccp.h" 5136285Sbrian#include "link.h" 5236285Sbrian#include "descriptor.h" 5336285Sbrian#include "physical.h" 546059Samurai 556059Samurai#define MODE_HUNT 0x01 566059Samurai#define MODE_ESC 0x02 576059Samurai 586059Samuraivoid 5936285Sbrianasync_Init(struct async *async) 606059Samurai{ 6191623Sbrian async_Setup(async); 6291623Sbrian memset(async->cfg.EscMap, '\0', sizeof async->cfg.EscMap); 6391623Sbrian} 6491623Sbrian 6591623Sbrianvoid 6691623Sbrianasync_Setup(struct async *async) 6791623Sbrian{ 6836285Sbrian async->mode = MODE_HUNT; 6936285Sbrian async->length = 0; 7036285Sbrian async->my_accmap = async->his_accmap = 0xffffffff; 716059Samurai} 726059Samurai 736059Samuraivoid 7493418Sbrianasync_SetLinkParams(struct async *async, u_int32_t mymap, u_int32_t hismap) 756059Samurai{ 7693418Sbrian async->my_accmap = mymap; 7793418Sbrian async->his_accmap = hismap | mymap; 786059Samurai} 796059Samurai 806059Samurai/* 8146686Sbrian * Encode into async HDLC byte code 826059Samurai */ 836059Samuraistatic void 8446686Sbrianasync_Encode(struct async *async, u_char **cp, u_char c, int proto) 856059Samurai{ 866059Samurai u_char *wp; 876059Samurai 886059Samurai wp = *cp; 8936285Sbrian if ((c < 0x20 && (proto == PROTO_LCP || (async->his_accmap & (1 << c)))) 9028679Sbrian || (c == HDLC_ESC) || (c == HDLC_SYN)) { 916059Samurai *wp++ = HDLC_ESC; 926059Samurai c ^= HDLC_XOR; 936059Samurai } 9436285Sbrian if (async->cfg.EscMap[32] && async->cfg.EscMap[c >> 3] & (1 << (c & 7))) { 956059Samurai *wp++ = HDLC_ESC; 966059Samurai c ^= HDLC_XOR; 976059Samurai } 986059Samurai *wp++ = c; 996059Samurai *cp = wp; 1006059Samurai} 1016059Samurai 10246686Sbrianstatic struct mbuf * 103134789Sbrianasync_LayerPush(struct bundle *b __unused, struct link *l, struct mbuf *bp, 104134789Sbrian int pri __unused, u_short *proto) 1056059Samurai{ 10646686Sbrian struct physical *p = link2physical(l); 1076059Samurai u_char *cp, *sp, *ep; 1086059Samurai struct mbuf *wp; 109131327Sbrian size_t oldcnt; 110134789Sbrian size_t cnt; 1116059Samurai 11254912Sbrian if (!p || m_length(bp) > HDLCSIZE) { 11354912Sbrian m_freem(bp); 11446686Sbrian return NULL; 1156059Samurai } 11646686Sbrian 117131327Sbrian oldcnt = m_length(bp); 118131327Sbrian 11946686Sbrian cp = p->async.xbuff; 1206059Samurai ep = cp + HDLCSIZE - 10; 1216059Samurai wp = bp; 12228679Sbrian *cp++ = HDLC_SYN; 1236059Samurai while (wp) { 1246059Samurai sp = MBUF_CTOP(wp); 12554912Sbrian for (cnt = wp->m_len; cnt > 0; cnt--) { 12646686Sbrian async_Encode(&p->async, &cp, *sp++, *proto); 1276059Samurai if (cp >= ep) { 12854912Sbrian m_freem(bp); 12946686Sbrian return NULL; 1306059Samurai } 1316059Samurai } 13254912Sbrian wp = wp->m_next; 1336059Samurai } 13428679Sbrian *cp++ = HDLC_SYN; 1356059Samurai 13646686Sbrian cnt = cp - p->async.xbuff; 13754912Sbrian m_freem(bp); 13854912Sbrian bp = m_get(cnt, MB_ASYNCOUT); 13946686Sbrian memcpy(MBUF_CTOP(bp), p->async.xbuff, cnt); 140131327Sbrian bp->priv = cnt - oldcnt; 14147061Sbrian log_DumpBp(LogASYNC, "Write", bp); 14246686Sbrian 14346686Sbrian return bp; 1446059Samurai} 1456059Samurai 14630715Sbrianstatic struct mbuf * 14736285Sbrianasync_Decode(struct async *async, u_char c) 1486059Samurai{ 1496059Samurai struct mbuf *bp; 1506059Samurai 15136285Sbrian if ((async->mode & MODE_HUNT) && c != HDLC_SYN) 15232663Sbrian return NULL; 1536059Samurai 1546059Samurai switch (c) { 1556059Samurai case HDLC_SYN: 15636285Sbrian async->mode &= ~MODE_HUNT; 15736285Sbrian if (async->length) { /* packet is ready. */ 15854912Sbrian bp = m_get(async->length, MB_ASYNCIN); 15936285Sbrian mbuf_Write(bp, async->hbuff, async->length); 16036285Sbrian async->length = 0; 16132663Sbrian return bp; 1626059Samurai } 1636059Samurai break; 1646059Samurai case HDLC_ESC: 16536285Sbrian if (!(async->mode & MODE_ESC)) { 16636285Sbrian async->mode |= MODE_ESC; 1676059Samurai break; 1686059Samurai } 169102413Scharnier /* FALLTHROUGH */ 1706059Samurai default: 17136285Sbrian if (async->length >= HDLCSIZE) { 1726059Samurai /* packet is too large, discard it */ 17337019Sbrian log_Printf(LogWARN, "Packet too large (%d), discarding.\n", 17437019Sbrian async->length); 17536285Sbrian async->length = 0; 17636285Sbrian async->mode = MODE_HUNT; 1776059Samurai break; 1786059Samurai } 17936285Sbrian if (async->mode & MODE_ESC) { 1806059Samurai c ^= HDLC_XOR; 18136285Sbrian async->mode &= ~MODE_ESC; 1826059Samurai } 18336285Sbrian async->hbuff[async->length++] = c; 1846059Samurai break; 1856059Samurai } 18632663Sbrian return NULL; 1876059Samurai} 1886059Samurai 18946686Sbrianstatic struct mbuf * 190134789Sbrianasync_LayerPull(struct bundle *b __unused, struct link *l, struct mbuf *bp, 191134789Sbrian u_short *proto __unused) 1926059Samurai{ 19346686Sbrian struct mbuf *nbp, **last; 19446686Sbrian struct physical *p = link2physical(l); 19546686Sbrian u_char *ch; 19646686Sbrian size_t cnt; 1976059Samurai 19846686Sbrian if (!p) { 19946686Sbrian log_Printf(LogERROR, "Can't Pull an async packet from a logical link\n"); 20046686Sbrian return bp; 20146686Sbrian } 20236285Sbrian 20346686Sbrian last = &nbp; 20446686Sbrian 20547061Sbrian log_DumpBp(LogASYNC, "Read", bp); 20646686Sbrian while (bp) { 20746686Sbrian ch = MBUF_CTOP(bp); 20854912Sbrian for (cnt = bp->m_len; cnt; cnt--) { 20946686Sbrian *last = async_Decode(&p->async, *ch++); 21046686Sbrian if (*last != NULL) 21154912Sbrian last = &(*last)->m_nextpkt; 2126735Samurai } 21354912Sbrian bp = m_free(bp); 2146059Samurai } 21546686Sbrian 21646686Sbrian return nbp; 2176059Samurai} 21846686Sbrian 21946686Sbrianstruct layer asynclayer = 22046686Sbrian { LAYER_ASYNC, "async", async_LayerPush, async_LayerPull }; 221