xref: /freebsd/usr.sbin/ppp/async.c (revision 75240ed1789e0754da5b1024dcb80dcfc5dae0c3)
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  *
2075240ed1SBrian Somers  * $Id: async.c,v 1.11 1997/08/25 00:29:05 brian Exp $
21af57ed9fSAtsushi Murai  *
22af57ed9fSAtsushi Murai  */
2375240ed1SBrian Somers #include <sys/param.h>
2475240ed1SBrian Somers #include <netinet/in.h>
2575240ed1SBrian Somers 
2675240ed1SBrian Somers #include <stdio.h>
2775240ed1SBrian Somers #include <string.h>
2875240ed1SBrian Somers #include <termios.h>
2975240ed1SBrian Somers 
3075240ed1SBrian Somers #include "mbuf.h"
3175240ed1SBrian Somers #include "log.h"
3275240ed1SBrian Somers #include "defs.h"
3375240ed1SBrian Somers #include "timer.h"
34af57ed9fSAtsushi Murai #include "fsm.h"
35af57ed9fSAtsushi Murai #include "hdlc.h"
36af57ed9fSAtsushi Murai #include "lcp.h"
37af57ed9fSAtsushi Murai #include "lcpproto.h"
38af57ed9fSAtsushi Murai #include "modem.h"
396ed9fb2fSBrian Somers #include "loadalias.h"
4075240ed1SBrian Somers #include "command.h"
4153c9f6c0SAtsushi Murai #include "vars.h"
42ed6a16c1SPoul-Henning Kamp #include "os.h"
4375240ed1SBrian Somers #include "async.h"
44af57ed9fSAtsushi Murai 
45af57ed9fSAtsushi Murai #define HDLCSIZE	(MAX_MRU*2+6)
46af57ed9fSAtsushi Murai 
4775240ed1SBrian Somers static struct async_state {
48af57ed9fSAtsushi Murai   int mode;
49af57ed9fSAtsushi Murai   int length;
50af57ed9fSAtsushi Murai   u_char hbuff[HDLCSIZE];	/* recv buffer */
51af57ed9fSAtsushi Murai   u_char xbuff[HDLCSIZE];	/* xmit buffer */
52af57ed9fSAtsushi Murai   u_long my_accmap;
53af57ed9fSAtsushi Murai   u_long his_accmap;
54af57ed9fSAtsushi Murai } AsyncState;
55af57ed9fSAtsushi Murai 
56af57ed9fSAtsushi Murai #define MODE_HUNT 0x01
57af57ed9fSAtsushi Murai #define MODE_ESC  0x02
58af57ed9fSAtsushi Murai 
59af57ed9fSAtsushi Murai void
60af57ed9fSAtsushi Murai AsyncInit()
61af57ed9fSAtsushi Murai {
62af57ed9fSAtsushi Murai   struct async_state *stp = &AsyncState;
63af57ed9fSAtsushi Murai 
64af57ed9fSAtsushi Murai   stp->mode = MODE_HUNT;
6553c9f6c0SAtsushi Murai   stp->length = 0;
66af57ed9fSAtsushi Murai   stp->my_accmap = stp->his_accmap = 0xffffffff;
67af57ed9fSAtsushi Murai }
68af57ed9fSAtsushi Murai 
69af57ed9fSAtsushi Murai void
70944f7098SBrian Somers SetLinkParams(struct lcpstate *lcp)
71af57ed9fSAtsushi Murai {
72af57ed9fSAtsushi Murai   struct async_state *stp = &AsyncState;
73af57ed9fSAtsushi Murai 
74af57ed9fSAtsushi Murai   stp->my_accmap = lcp->want_accmap;
75af57ed9fSAtsushi Murai   stp->his_accmap = lcp->his_accmap;
76af57ed9fSAtsushi Murai }
77af57ed9fSAtsushi Murai 
78af57ed9fSAtsushi Murai /*
79af57ed9fSAtsushi Murai  * Encode into async HDLC byte code if necessary
80af57ed9fSAtsushi Murai  */
81af57ed9fSAtsushi Murai static void
82944f7098SBrian Somers HdlcPutByte(u_char **cp, u_char c, int proto)
83af57ed9fSAtsushi Murai {
84af57ed9fSAtsushi Murai   u_char *wp;
85af57ed9fSAtsushi Murai 
86af57ed9fSAtsushi Murai   wp = *cp;
87af57ed9fSAtsushi Murai   if ((c < 0x20 && (proto == PROTO_LCP || (AsyncState.his_accmap & (1 << c))))
88af57ed9fSAtsushi Murai       || (c == HDLC_ESC) || (c == HDLC_SYN)) {
89af57ed9fSAtsushi Murai     *wp++ = HDLC_ESC;
90af57ed9fSAtsushi Murai     c ^= HDLC_XOR;
91af57ed9fSAtsushi Murai   }
9210b74897SAtsushi Murai   if (EscMap[32] && EscMap[c >> 3] & (1 << (c & 7))) {
93af57ed9fSAtsushi Murai     *wp++ = HDLC_ESC;
94af57ed9fSAtsushi Murai     c ^= HDLC_XOR;
95af57ed9fSAtsushi Murai   }
96af57ed9fSAtsushi Murai   *wp++ = c;
97af57ed9fSAtsushi Murai   *cp = wp;
98af57ed9fSAtsushi Murai }
99af57ed9fSAtsushi Murai 
100af57ed9fSAtsushi Murai void
101944f7098SBrian Somers AsyncOutput(int pri, struct mbuf *bp, int proto)
102af57ed9fSAtsushi Murai {
103af57ed9fSAtsushi Murai   struct async_state *hs = &AsyncState;
104af57ed9fSAtsushi Murai   u_char *cp, *sp, *ep;
105af57ed9fSAtsushi Murai   struct mbuf *wp;
106af57ed9fSAtsushi Murai   int cnt;
107af57ed9fSAtsushi Murai 
108af57ed9fSAtsushi Murai   if (plength(bp) > HDLCSIZE) {
109af57ed9fSAtsushi Murai     pfree(bp);
110af57ed9fSAtsushi Murai     return;
111af57ed9fSAtsushi Murai   }
112af57ed9fSAtsushi Murai   cp = hs->xbuff;
113af57ed9fSAtsushi Murai   ep = cp + HDLCSIZE - 10;
114af57ed9fSAtsushi Murai   wp = bp;
115af57ed9fSAtsushi Murai   *cp++ = HDLC_SYN;
116af57ed9fSAtsushi Murai   while (wp) {
117af57ed9fSAtsushi Murai     sp = MBUF_CTOP(wp);
118af57ed9fSAtsushi Murai     for (cnt = wp->cnt; cnt > 0; cnt--) {
119af57ed9fSAtsushi Murai       HdlcPutByte(&cp, *sp++, proto);
120af57ed9fSAtsushi Murai       if (cp >= ep) {
121af57ed9fSAtsushi Murai 	pfree(bp);
122af57ed9fSAtsushi Murai 	return;
123af57ed9fSAtsushi Murai       }
124af57ed9fSAtsushi Murai     }
125af57ed9fSAtsushi Murai     wp = wp->next;
126af57ed9fSAtsushi Murai   }
127af57ed9fSAtsushi Murai   *cp++ = HDLC_SYN;
128af57ed9fSAtsushi Murai 
129af57ed9fSAtsushi Murai   cnt = cp - hs->xbuff;
130927145beSBrian Somers   LogDumpBuff(LogASYNC, "WriteModem", hs->xbuff, cnt);
131af57ed9fSAtsushi Murai   WriteModem(pri, (char *) hs->xbuff, cnt);
132af57ed9fSAtsushi Murai   OsAddOutOctets(cnt);
133af57ed9fSAtsushi Murai   pfree(bp);
134af57ed9fSAtsushi Murai }
135af57ed9fSAtsushi Murai 
13675240ed1SBrian Somers static struct mbuf *
137944f7098SBrian Somers AsyncDecode(u_char c)
138af57ed9fSAtsushi Murai {
139af57ed9fSAtsushi Murai   struct async_state *hs = &AsyncState;
140af57ed9fSAtsushi Murai   struct mbuf *bp;
141af57ed9fSAtsushi Murai 
142af57ed9fSAtsushi Murai   if ((hs->mode & MODE_HUNT) && c != HDLC_SYN)
143af57ed9fSAtsushi Murai     return (NULLBUFF);
144af57ed9fSAtsushi Murai 
145af57ed9fSAtsushi Murai   switch (c) {
146af57ed9fSAtsushi Murai   case HDLC_SYN:
147af57ed9fSAtsushi Murai     hs->mode &= ~MODE_HUNT;
148af57ed9fSAtsushi Murai     if (hs->length) {		/* packet is ready. */
149af57ed9fSAtsushi Murai       bp = mballoc(hs->length, MB_ASYNC);
150af57ed9fSAtsushi Murai       mbwrite(bp, hs->hbuff, hs->length);
151af57ed9fSAtsushi Murai       hs->length = 0;
152af57ed9fSAtsushi Murai       return (bp);
153af57ed9fSAtsushi Murai     }
154af57ed9fSAtsushi Murai     break;
155af57ed9fSAtsushi Murai   case HDLC_ESC:
156af57ed9fSAtsushi Murai     if (!(hs->mode & MODE_ESC)) {
157af57ed9fSAtsushi Murai       hs->mode |= MODE_ESC;
158af57ed9fSAtsushi Murai       break;
159af57ed9fSAtsushi Murai     }
160af57ed9fSAtsushi Murai     /* Fall into ... */
161af57ed9fSAtsushi Murai   default:
162af57ed9fSAtsushi Murai     if (hs->length >= HDLCSIZE) {
163af57ed9fSAtsushi Murai       /* packet is too large, discard it */
164c3a83f67SBrian Somers       LogPrintf(LogERROR, "Packet too large (%d), discarding.\n", hs->length);
165af57ed9fSAtsushi Murai       hs->length = 0;
166af57ed9fSAtsushi Murai       hs->mode = MODE_HUNT;
167af57ed9fSAtsushi Murai       break;
168af57ed9fSAtsushi Murai     }
169af57ed9fSAtsushi Murai     if (hs->mode & MODE_ESC) {
170af57ed9fSAtsushi Murai       c ^= HDLC_XOR;
171af57ed9fSAtsushi Murai       hs->mode &= ~MODE_ESC;
172af57ed9fSAtsushi Murai     }
173af57ed9fSAtsushi Murai     hs->hbuff[hs->length++] = c;
174af57ed9fSAtsushi Murai     break;
175af57ed9fSAtsushi Murai   }
176af57ed9fSAtsushi Murai   return NULLBUFF;
177af57ed9fSAtsushi Murai }
178af57ed9fSAtsushi Murai 
179af57ed9fSAtsushi Murai void
180944f7098SBrian Somers AsyncInput(u_char *buff, int cnt)
181af57ed9fSAtsushi Murai {
182af57ed9fSAtsushi Murai   struct mbuf *bp;
183af57ed9fSAtsushi Murai 
184af57ed9fSAtsushi Murai   OsAddInOctets(cnt);
18553c9f6c0SAtsushi Murai   if (DEV_IS_SYNC) {
18653c9f6c0SAtsushi Murai     bp = mballoc(cnt, MB_ASYNC);
18775240ed1SBrian Somers     memcpy(MBUF_CTOP(bp), buff, cnt);
18853c9f6c0SAtsushi Murai     bp->cnt = cnt;
18953c9f6c0SAtsushi Murai     HdlcInput(bp);
19053c9f6c0SAtsushi Murai   } else {
191af57ed9fSAtsushi Murai     while (cnt > 0) {
192af57ed9fSAtsushi Murai       bp = AsyncDecode(*buff++);
193af57ed9fSAtsushi Murai       if (bp)
194af57ed9fSAtsushi Murai 	HdlcInput(bp);
195af57ed9fSAtsushi Murai       cnt--;
196af57ed9fSAtsushi Murai     }
197af57ed9fSAtsushi Murai   }
19853c9f6c0SAtsushi Murai }
199