xref: /freebsd/usr.sbin/ppp/async.c (revision 26af0ae96638b0453bcc87cae6031eb0b3988171)
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