Home | History | Annotate | Download | only in src
      1 /*-
      2  * Copyright (c) 1996 - 2001 Brian Somers <brian (at) Awfulhak.org>
      3  *          based on work by Toshiharu OHNO <tony-o (at) iij.ad.jp>
      4  *                           Internet Initiative Japan, Inc (IIJ)
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  *
     28  */
     29 
     30 #include <sys/cdefs.h>
     31 __FBSDID("$FreeBSD: src/usr.sbin/ppp/async.c,v 1.29.26.1 2010/12/21 17:10:29 kensmith Exp $");
     32 
     33 #include <sys/types.h>
     34 
     35 #include <string.h>
     36 #include <termios.h>
     37 
     38 #include "layer.h"
     39 #include "mbuf.h"
     40 #include "log.h"
     41 #include "defs.h"
     42 #include "timer.h"
     43 #include "fsm.h"
     44 #include "lqr.h"
     45 #include "hdlc.h"
     46 #include "lcp.h"
     47 #include "proto.h"
     48 #include "async.h"
     49 #include "throughput.h"
     50 #include "ccp.h"
     51 #include "link.h"
     52 #include "descriptor.h"
     53 #include "physical.h"
     54 
     55 #define MODE_HUNT 0x01
     56 #define MODE_ESC  0x02
     57 
     58 void
     59 async_Init(struct async *async)
     60 {
     61   async_Setup(async);
     62   memset(async->cfg.EscMap, '\0', sizeof async->cfg.EscMap);
     63 }
     64 
     65 void
     66 async_Setup(struct async *async)
     67 {
     68   async->mode = MODE_HUNT;
     69   async->length = 0;
     70   async->my_accmap = async->his_accmap = 0xffffffff;
     71 }
     72 
     73 void
     74 async_SetLinkParams(struct async *async, u_int32_t mymap, u_int32_t hismap)
     75 {
     76   async->my_accmap = mymap;
     77   async->his_accmap = hismap | mymap;
     78 }
     79 
     80 /*
     81  * Encode into async HDLC byte code
     82  */
     83 static void
     84 async_Encode(struct async *async, u_char **cp, u_char c, int proto)
     85 {
     86   u_char *wp;
     87 
     88   wp = *cp;
     89   if ((c < 0x20 && (proto == PROTO_LCP || (async->his_accmap & (1 << c))))
     90       || (c == HDLC_ESC) || (c == HDLC_SYN)) {
     91     *wp++ = HDLC_ESC;
     92     c ^= HDLC_XOR;
     93   }
     94   if (async->cfg.EscMap[32] && async->cfg.EscMap[c >> 3] & (1 << (c & 7))) {
     95     *wp++ = HDLC_ESC;
     96     c ^= HDLC_XOR;
     97   }
     98   *wp++ = c;
     99   *cp = wp;
    100 }
    101 
    102 static struct mbuf *
    103 async_LayerPush(struct bundle *b __unused, struct link *l, struct mbuf *bp,
    104                 int pri __unused, u_short *proto)
    105 {
    106   struct physical *p = link2physical(l);
    107   u_char *cp, *sp, *ep;
    108   struct mbuf *wp;
    109   size_t oldcnt;
    110   size_t cnt;
    111 
    112   if (!p || m_length(bp) > HDLCSIZE) {
    113     m_freem(bp);
    114     return NULL;
    115   }
    116 
    117   oldcnt = m_length(bp);
    118 
    119   cp = p->async.xbuff;
    120   ep = cp + HDLCSIZE - 10;
    121   wp = bp;
    122   *cp++ = HDLC_SYN;
    123   while (wp) {
    124     sp = MBUF_CTOP(wp);
    125     for (cnt = wp->m_len; cnt > 0; cnt--) {
    126       async_Encode(&p->async, &cp, *sp++, *proto);
    127       if (cp >= ep) {
    128 	m_freem(bp);
    129 	return NULL;
    130       }
    131     }
    132     wp = wp->m_next;
    133   }
    134   *cp++ = HDLC_SYN;
    135 
    136   cnt = cp - p->async.xbuff;
    137   m_freem(bp);
    138   bp = m_get(cnt, MB_ASYNCOUT);
    139   memcpy(MBUF_CTOP(bp), p->async.xbuff, cnt);
    140   bp->priv = cnt - oldcnt;
    141   log_DumpBp(LogASYNC, "Write", bp);
    142 
    143   return bp;
    144 }
    145 
    146 static struct mbuf *
    147 async_Decode(struct async *async, u_char c)
    148 {
    149   struct mbuf *bp;
    150 
    151   if ((async->mode & MODE_HUNT) && c != HDLC_SYN)
    152     return NULL;
    153 
    154   switch (c) {
    155   case HDLC_SYN:
    156     async->mode &= ~MODE_HUNT;
    157     if (async->length) {		/* packet is ready. */
    158       bp = m_get(async->length, MB_ASYNCIN);
    159       mbuf_Write(bp, async->hbuff, async->length);
    160       async->length = 0;
    161       return bp;
    162     }
    163     break;
    164   case HDLC_ESC:
    165     if (!(async->mode & MODE_ESC)) {
    166       async->mode |= MODE_ESC;
    167       break;
    168     }
    169     /* FALLTHROUGH */
    170   default:
    171     if (async->length >= HDLCSIZE) {
    172       /* packet is too large, discard it */
    173       log_Printf(LogWARN, "Packet too large (%d), discarding.\n",
    174                  async->length);
    175       async->length = 0;
    176       async->mode = MODE_HUNT;
    177       break;
    178     }
    179     if (async->mode & MODE_ESC) {
    180       c ^= HDLC_XOR;
    181       async->mode &= ~MODE_ESC;
    182     }
    183     async->hbuff[async->length++] = c;
    184     break;
    185   }
    186   return NULL;
    187 }
    188 
    189 static struct mbuf *
    190 async_LayerPull(struct bundle *b __unused, struct link *l, struct mbuf *bp,
    191                 u_short *proto __unused)
    192 {
    193   struct mbuf *nbp, **last;
    194   struct physical *p = link2physical(l);
    195   u_char *ch;
    196   size_t cnt;
    197 
    198   if (!p) {
    199     log_Printf(LogERROR, "Can't Pull an async packet from a logical link\n");
    200     return bp;
    201   }
    202 
    203   last = &nbp;
    204 
    205   log_DumpBp(LogASYNC, "Read", bp);
    206   while (bp) {
    207     ch = MBUF_CTOP(bp);
    208     for (cnt = bp->m_len; cnt; cnt--) {
    209       *last = async_Decode(&p->async, *ch++);
    210       if (*last != NULL)
    211         last = &(*last)->m_nextpkt;
    212     }
    213     bp = m_free(bp);
    214   }
    215 
    216   return nbp;
    217 }
    218 
    219 struct layer asynclayer =
    220   { LAYER_ASYNC, "async", async_LayerPush, async_LayerPull };
    221