xref: /freebsd/usr.sbin/ppp/async.c (revision 17ee9d00bc1ae1e598c38f25826f861e4bc6c3ce)
1 /*
2  *	             PPP Async HDLC Module
3  *
4  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5  *
6  *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by the Internet Initiative Japan, Inc.  The name of the
14  * IIJ may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  *
20  * $Id:$
21  *
22  */
23 #include "fsm.h"
24 #include "hdlc.h"
25 #include "lcp.h"
26 #include "lcpproto.h"
27 #include "modem.h"
28 
29 #define HDLCSIZE	(MAX_MRU*2+6)
30 
31 struct async_state {
32   int mode;
33   int length;
34   struct mbuf *hpacket;
35   u_char hbuff[HDLCSIZE];	/* recv buffer */
36   u_char xbuff[HDLCSIZE];	/* xmit buffer */
37   u_long my_accmap;
38   u_long his_accmap;
39 } AsyncState;
40 
41 #define MODE_HUNT 0x01
42 #define MODE_ESC  0x02
43 
44 void
45 AsyncInit()
46 {
47   struct async_state *stp = &AsyncState;
48 
49   stp->mode = MODE_HUNT;
50   stp->my_accmap = stp->his_accmap = 0xffffffff;
51 }
52 
53 void
54 SetLinkParams(lcp)
55 struct lcpstate *lcp;
56 {
57   struct async_state *stp = &AsyncState;
58 
59   stp->my_accmap = lcp->want_accmap;
60   stp->his_accmap = lcp->his_accmap;
61 }
62 
63 /*
64  * Encode into async HDLC byte code if necessary
65  */
66 static void
67 HdlcPutByte(cp, c, proto)
68 u_char **cp;
69 u_char c;
70 int proto;
71 {
72   u_char *wp;
73 
74   wp = *cp;
75   if ((c < 0x20 && (proto == PROTO_LCP || (AsyncState.his_accmap & (1<<c))))
76 	|| (c == HDLC_ESC) || (c == HDLC_SYN)) {
77     *wp++ = HDLC_ESC;
78     c ^= HDLC_XOR;
79   }
80   if (EscMap[32] && EscMap[c >> 3] & (c&7)) {
81     *wp++ = HDLC_ESC;
82     c ^= HDLC_XOR;
83   }
84   *wp++ = c;
85   *cp = wp;
86 }
87 
88 void
89 AsyncOutput(pri, bp, proto)
90 int pri;
91 struct mbuf *bp;
92 int proto;
93 {
94   struct async_state *hs = &AsyncState;
95   u_char *cp, *sp, *ep;
96   struct mbuf *wp;
97   int cnt;
98 
99   if (plength(bp) > HDLCSIZE) {
100     pfree(bp);
101     return;
102   }
103   cp = hs->xbuff;
104   ep = cp + HDLCSIZE - 10;
105   wp = bp;
106   *cp ++ = HDLC_SYN;
107   while (wp) {
108     sp = MBUF_CTOP(wp);
109     for (cnt = wp->cnt; cnt > 0; cnt--) {
110       HdlcPutByte(&cp, *sp++, proto);
111       if (cp >= ep) {
112 	pfree(bp);
113 	return;
114       }
115     }
116     wp = wp->next;
117   }
118   *cp ++ = HDLC_SYN;
119 
120   cnt = cp - hs->xbuff;
121   LogDumpBuff(LOG_ASYNC, "WriteModem", hs->xbuff, cnt);
122   WriteModem(pri, (char *)hs->xbuff, cnt);
123   OsAddOutOctets(cnt);
124   pfree(bp);
125 }
126 
127 struct mbuf *
128 AsyncDecode(c)
129 u_char c;
130 {
131   struct async_state *hs = &AsyncState;
132   struct mbuf *bp;
133 
134   if ((hs->mode & MODE_HUNT) && c != HDLC_SYN)
135     return(NULLBUFF);
136 
137   switch (c) {
138   case HDLC_SYN:
139     hs->mode &= ~MODE_HUNT;
140     if (hs->length) {	/* packet is ready. */
141       bp = mballoc(hs->length, MB_ASYNC);
142       mbwrite(bp, hs->hbuff, hs->length);
143       hs->length = 0;
144       return(bp);
145     }
146     break;
147   case HDLC_ESC:
148     if (!(hs->mode & MODE_ESC)) {
149       hs->mode |= MODE_ESC;
150       break;
151     }
152     /* Fall into ... */
153   default:
154     if (hs->length >= HDLCSIZE) {
155       /* packet is too large, discard it */
156       logprintf("too large, diacarding.\n");
157       hs->length = 0;
158       hs->mode = MODE_HUNT;
159       break;
160     }
161     if (hs->mode & MODE_ESC) {
162       c ^= HDLC_XOR;
163       hs->mode &= ~MODE_ESC;
164     }
165     hs->hbuff[hs->length++] = c;
166     break;
167   }
168   return NULLBUFF;
169 }
170 
171 void
172 AsyncInput(buff, cnt)
173 u_char *buff;
174 int cnt;
175 {
176   struct mbuf *bp;
177 
178   OsAddInOctets(cnt);
179   while (cnt > 0) {
180     bp = AsyncDecode(*buff++);
181     if (bp)
182       HdlcInput(bp);
183     cnt--;
184   }
185 }
186