1af57ed9fSAtsushi Murai /* 2af57ed9fSAtsushi Murai * PPP Async HDLC Module 3af57ed9fSAtsushi Murai * 4af57ed9fSAtsushi Murai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5af57ed9fSAtsushi Murai * 6af57ed9fSAtsushi Murai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7af57ed9fSAtsushi Murai * 8af57ed9fSAtsushi Murai * Redistribution and use in source and binary forms are permitted 9af57ed9fSAtsushi Murai * provided that the above copyright notice and this paragraph are 10af57ed9fSAtsushi Murai * duplicated in all such forms and that any documentation, 11af57ed9fSAtsushi Murai * advertising materials, and other materials related to such 12af57ed9fSAtsushi Murai * distribution and use acknowledge that the software was developed 13af57ed9fSAtsushi Murai * by the Internet Initiative Japan, Inc. The name of the 14af57ed9fSAtsushi Murai * IIJ may not be used to endorse or promote products derived 15af57ed9fSAtsushi Murai * from this software without specific prior written permission. 16af57ed9fSAtsushi Murai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17af57ed9fSAtsushi Murai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18af57ed9fSAtsushi Murai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19af57ed9fSAtsushi Murai * 2097d92980SPeter Wemm * $FreeBSD$ 21af57ed9fSAtsushi Murai * 22af57ed9fSAtsushi Murai */ 232764b86aSBrian Somers #include <sys/types.h> 2475240ed1SBrian Somers 2575240ed1SBrian Somers #include <string.h> 2675240ed1SBrian Somers #include <termios.h> 2775240ed1SBrian Somers 285d9e6103SBrian Somers #include "layer.h" 2975240ed1SBrian Somers #include "mbuf.h" 3075240ed1SBrian Somers #include "log.h" 3175240ed1SBrian Somers #include "defs.h" 3275240ed1SBrian Somers #include "timer.h" 33af57ed9fSAtsushi Murai #include "fsm.h" 34879ed6faSBrian Somers #include "lqr.h" 35af57ed9fSAtsushi Murai #include "hdlc.h" 36af57ed9fSAtsushi Murai #include "lcp.h" 375d9e6103SBrian Somers #include "proto.h" 3875240ed1SBrian Somers #include "async.h" 398c07a7b2SBrian Somers #include "throughput.h" 403b0f8d2eSBrian Somers #include "ccp.h" 418c07a7b2SBrian Somers #include "link.h" 4242d4d396SBrian Somers #include "descriptor.h" 4363b73463SBrian Somers #include "physical.h" 44af57ed9fSAtsushi Murai 45af57ed9fSAtsushi Murai #define MODE_HUNT 0x01 46af57ed9fSAtsushi Murai #define MODE_ESC 0x02 47af57ed9fSAtsushi Murai 48af57ed9fSAtsushi Murai void 496140ba11SBrian Somers async_Init(struct async *async) 50af57ed9fSAtsushi Murai { 516140ba11SBrian Somers async->mode = MODE_HUNT; 526140ba11SBrian Somers async->length = 0; 536140ba11SBrian Somers async->my_accmap = async->his_accmap = 0xffffffff; 549dee069dSBrian Somers memset(async->cfg.EscMap, '\0', sizeof async->cfg.EscMap); 55af57ed9fSAtsushi Murai } 56af57ed9fSAtsushi Murai 57af57ed9fSAtsushi Murai void 58aad81d1eSBrian Somers async_SetLinkParams(struct async *async, struct lcp *lcp) 59af57ed9fSAtsushi Murai { 606140ba11SBrian Somers async->my_accmap = lcp->want_accmap; 614ae29eb7SBrian Somers async->his_accmap = lcp->his_accmap | lcp->want_accmap; 62af57ed9fSAtsushi Murai } 63af57ed9fSAtsushi Murai 64af57ed9fSAtsushi Murai /* 655d9e6103SBrian Somers * Encode into async HDLC byte code 66af57ed9fSAtsushi Murai */ 67af57ed9fSAtsushi Murai static void 685d9e6103SBrian Somers async_Encode(struct async *async, u_char **cp, u_char c, int proto) 69af57ed9fSAtsushi Murai { 70af57ed9fSAtsushi Murai u_char *wp; 71af57ed9fSAtsushi Murai 72af57ed9fSAtsushi Murai wp = *cp; 736140ba11SBrian Somers if ((c < 0x20 && (proto == PROTO_LCP || (async->his_accmap & (1 << c)))) 74af57ed9fSAtsushi Murai || (c == HDLC_ESC) || (c == HDLC_SYN)) { 75af57ed9fSAtsushi Murai *wp++ = HDLC_ESC; 76af57ed9fSAtsushi Murai c ^= HDLC_XOR; 77af57ed9fSAtsushi Murai } 789991562dSBrian Somers if (async->cfg.EscMap[32] && async->cfg.EscMap[c >> 3] & (1 << (c & 7))) { 79af57ed9fSAtsushi Murai *wp++ = HDLC_ESC; 80af57ed9fSAtsushi Murai c ^= HDLC_XOR; 81af57ed9fSAtsushi Murai } 82af57ed9fSAtsushi Murai *wp++ = c; 83af57ed9fSAtsushi Murai *cp = wp; 84af57ed9fSAtsushi Murai } 85af57ed9fSAtsushi Murai 865d9e6103SBrian Somers static struct mbuf * 875d9e6103SBrian Somers async_LayerPush(struct bundle *bundle, struct link *l, struct mbuf *bp, 885d9e6103SBrian Somers int pri, u_short *proto) 89af57ed9fSAtsushi Murai { 905d9e6103SBrian Somers struct physical *p = link2physical(l); 91af57ed9fSAtsushi Murai u_char *cp, *sp, *ep; 92af57ed9fSAtsushi Murai struct mbuf *wp; 93af57ed9fSAtsushi Murai int cnt; 94af57ed9fSAtsushi Murai 9526af0ae9SBrian Somers if (!p || m_length(bp) > HDLCSIZE) { 9626af0ae9SBrian Somers m_freem(bp); 975d9e6103SBrian Somers return NULL; 98af57ed9fSAtsushi Murai } 995d9e6103SBrian Somers 1005d9e6103SBrian Somers cp = p->async.xbuff; 101af57ed9fSAtsushi Murai ep = cp + HDLCSIZE - 10; 102af57ed9fSAtsushi Murai wp = bp; 103af57ed9fSAtsushi Murai *cp++ = HDLC_SYN; 104af57ed9fSAtsushi Murai while (wp) { 105af57ed9fSAtsushi Murai sp = MBUF_CTOP(wp); 10626af0ae9SBrian Somers for (cnt = wp->m_len; cnt > 0; cnt--) { 1075d9e6103SBrian Somers async_Encode(&p->async, &cp, *sp++, *proto); 108af57ed9fSAtsushi Murai if (cp >= ep) { 10926af0ae9SBrian Somers m_freem(bp); 1105d9e6103SBrian Somers return NULL; 111af57ed9fSAtsushi Murai } 112af57ed9fSAtsushi Murai } 11326af0ae9SBrian Somers wp = wp->m_next; 114af57ed9fSAtsushi Murai } 115af57ed9fSAtsushi Murai *cp++ = HDLC_SYN; 116af57ed9fSAtsushi Murai 1175d9e6103SBrian Somers cnt = cp - p->async.xbuff; 11826af0ae9SBrian Somers m_freem(bp); 11926af0ae9SBrian Somers bp = m_get(cnt, MB_ASYNCOUT); 1205d9e6103SBrian Somers memcpy(MBUF_CTOP(bp), p->async.xbuff, cnt); 1216815097bSBrian Somers log_DumpBp(LogASYNC, "Write", bp); 1225d9e6103SBrian Somers 1235d9e6103SBrian Somers return bp; 124af57ed9fSAtsushi Murai } 125af57ed9fSAtsushi Murai 12675240ed1SBrian Somers static struct mbuf * 1276140ba11SBrian Somers async_Decode(struct async *async, u_char c) 128af57ed9fSAtsushi Murai { 129af57ed9fSAtsushi Murai struct mbuf *bp; 130af57ed9fSAtsushi Murai 1316140ba11SBrian Somers if ((async->mode & MODE_HUNT) && c != HDLC_SYN) 132aa8e0519SBrian Somers return NULL; 133af57ed9fSAtsushi Murai 134af57ed9fSAtsushi Murai switch (c) { 135af57ed9fSAtsushi Murai case HDLC_SYN: 1366140ba11SBrian Somers async->mode &= ~MODE_HUNT; 1376140ba11SBrian Somers if (async->length) { /* packet is ready. */ 13826af0ae9SBrian Somers bp = m_get(async->length, MB_ASYNCIN); 139dd7e2610SBrian Somers mbuf_Write(bp, async->hbuff, async->length); 1406140ba11SBrian Somers async->length = 0; 141aa8e0519SBrian Somers return bp; 142af57ed9fSAtsushi Murai } 143af57ed9fSAtsushi Murai break; 144af57ed9fSAtsushi Murai case HDLC_ESC: 1456140ba11SBrian Somers if (!(async->mode & MODE_ESC)) { 1466140ba11SBrian Somers async->mode |= MODE_ESC; 147af57ed9fSAtsushi Murai break; 148af57ed9fSAtsushi Murai } 149af57ed9fSAtsushi Murai /* Fall into ... */ 150af57ed9fSAtsushi Murai default: 1516140ba11SBrian Somers if (async->length >= HDLCSIZE) { 152af57ed9fSAtsushi Murai /* packet is too large, discard it */ 153a33b2ef7SBrian Somers log_Printf(LogWARN, "Packet too large (%d), discarding.\n", 154a33b2ef7SBrian Somers async->length); 1556140ba11SBrian Somers async->length = 0; 1566140ba11SBrian Somers async->mode = MODE_HUNT; 157af57ed9fSAtsushi Murai break; 158af57ed9fSAtsushi Murai } 1596140ba11SBrian Somers if (async->mode & MODE_ESC) { 160af57ed9fSAtsushi Murai c ^= HDLC_XOR; 1616140ba11SBrian Somers async->mode &= ~MODE_ESC; 162af57ed9fSAtsushi Murai } 1636140ba11SBrian Somers async->hbuff[async->length++] = c; 164af57ed9fSAtsushi Murai break; 165af57ed9fSAtsushi Murai } 166aa8e0519SBrian Somers return NULL; 167af57ed9fSAtsushi Murai } 168af57ed9fSAtsushi Murai 1695d9e6103SBrian Somers static struct mbuf * 1705d9e6103SBrian Somers async_LayerPull(struct bundle *b, struct link *l, struct mbuf *bp, 1715d9e6103SBrian Somers u_short *proto) 172af57ed9fSAtsushi Murai { 1735d9e6103SBrian Somers struct mbuf *nbp, **last; 1745d9e6103SBrian Somers struct physical *p = link2physical(l); 1755d9e6103SBrian Somers u_char *ch; 1765d9e6103SBrian Somers size_t cnt; 177af57ed9fSAtsushi Murai 1785d9e6103SBrian Somers if (!p) { 1795d9e6103SBrian Somers log_Printf(LogERROR, "Can't Pull an async packet from a logical link\n"); 1805d9e6103SBrian Somers return bp; 1815d9e6103SBrian Somers } 1828c07a7b2SBrian Somers 1835d9e6103SBrian Somers last = &nbp; 1845d9e6103SBrian Somers 1856815097bSBrian Somers log_DumpBp(LogASYNC, "Read", bp); 1865d9e6103SBrian Somers while (bp) { 1875d9e6103SBrian Somers ch = MBUF_CTOP(bp); 18826af0ae9SBrian Somers for (cnt = bp->m_len; cnt; cnt--) { 1895d9e6103SBrian Somers *last = async_Decode(&p->async, *ch++); 1905d9e6103SBrian Somers if (*last != NULL) 19126af0ae9SBrian Somers last = &(*last)->m_nextpkt; 192af57ed9fSAtsushi Murai } 19326af0ae9SBrian Somers bp = m_free(bp); 194af57ed9fSAtsushi Murai } 1955d9e6103SBrian Somers 1965d9e6103SBrian Somers return nbp; 19753c9f6c0SAtsushi Murai } 1985d9e6103SBrian Somers 1995d9e6103SBrian Somers struct layer asynclayer = 2005d9e6103SBrian Somers { LAYER_ASYNC, "async", async_LayerPush, async_LayerPull }; 201