xref: /freebsd/usr.sbin/ppp/async.c (revision df7f5d4de4592a8948a25ce01e5bddfbb7ce39dc)
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 #include "vars.h"
29 #include "os.h"
30 
31 #define HDLCSIZE	(MAX_MRU*2+6)
32 
33 struct async_state {
34   int mode;
35   int length;
36   u_char hbuff[HDLCSIZE];	/* recv buffer */
37   u_char xbuff[HDLCSIZE];	/* xmit buffer */
38   u_long my_accmap;
39   u_long his_accmap;
40 } AsyncState;
41 
42 #define MODE_HUNT 0x01
43 #define MODE_ESC  0x02
44 
45 void
46 AsyncInit()
47 {
48   struct async_state *stp = &AsyncState;
49 
50   stp->mode = MODE_HUNT;
51   stp->length = 0;
52   stp->my_accmap = stp->his_accmap = 0xffffffff;
53 }
54 
55 void
56 SetLinkParams(lcp)
57 struct lcpstate *lcp;
58 {
59   struct async_state *stp = &AsyncState;
60 
61   stp->my_accmap = lcp->want_accmap;
62   stp->his_accmap = lcp->his_accmap;
63 }
64 
65 /*
66  * Encode into async HDLC byte code if necessary
67  */
68 static void
69 HdlcPutByte(cp, c, proto)
70 u_char **cp;
71 u_char c;
72 int proto;
73 {
74   u_char *wp;
75 
76   wp = *cp;
77   if ((c < 0x20 && (proto == PROTO_LCP || (AsyncState.his_accmap & (1<<c))))
78 	|| (c == HDLC_ESC) || (c == HDLC_SYN)) {
79     *wp++ = HDLC_ESC;
80     c ^= HDLC_XOR;
81   }
82   if (EscMap[32] && EscMap[c >> 3] &  (1 << (c&7))) {
83     *wp++ = HDLC_ESC;
84     c ^= HDLC_XOR;
85   }
86   *wp++ = c;
87   *cp = wp;
88 }
89 
90 void
91 AsyncOutput(pri, bp, proto)
92 int pri;
93 struct mbuf *bp;
94 int proto;
95 {
96   struct async_state *hs = &AsyncState;
97   u_char *cp, *sp, *ep;
98   struct mbuf *wp;
99   int cnt;
100 
101   if (plength(bp) > HDLCSIZE) {
102     pfree(bp);
103     return;
104   }
105   cp = hs->xbuff;
106   ep = cp + HDLCSIZE - 10;
107   wp = bp;
108   *cp ++ = HDLC_SYN;
109   while (wp) {
110     sp = MBUF_CTOP(wp);
111     for (cnt = wp->cnt; cnt > 0; cnt--) {
112       HdlcPutByte(&cp, *sp++, proto);
113       if (cp >= ep) {
114 	pfree(bp);
115 	return;
116       }
117     }
118     wp = wp->next;
119   }
120   *cp ++ = HDLC_SYN;
121 
122   cnt = cp - hs->xbuff;
123   LogDumpBuff(LOG_ASYNC, "WriteModem", hs->xbuff, cnt);
124   WriteModem(pri, (char *)hs->xbuff, cnt);
125   OsAddOutOctets(cnt);
126   pfree(bp);
127 }
128 
129 struct mbuf *
130 AsyncDecode(c)
131 u_char c;
132 {
133   struct async_state *hs = &AsyncState;
134   struct mbuf *bp;
135 
136   if ((hs->mode & MODE_HUNT) && c != HDLC_SYN)
137     return(NULLBUFF);
138 
139   switch (c) {
140   case HDLC_SYN:
141     hs->mode &= ~MODE_HUNT;
142     if (hs->length) {	/* packet is ready. */
143       bp = mballoc(hs->length, MB_ASYNC);
144       mbwrite(bp, hs->hbuff, hs->length);
145       hs->length = 0;
146       return(bp);
147     }
148     break;
149   case HDLC_ESC:
150     if (!(hs->mode & MODE_ESC)) {
151       hs->mode |= MODE_ESC;
152       break;
153     }
154     /* Fall into ... */
155   default:
156     if (hs->length >= HDLCSIZE) {
157       /* packet is too large, discard it */
158       logprintf("too large, diacarding.\n");
159       hs->length = 0;
160       hs->mode = MODE_HUNT;
161       break;
162     }
163     if (hs->mode & MODE_ESC) {
164       c ^= HDLC_XOR;
165       hs->mode &= ~MODE_ESC;
166     }
167     hs->hbuff[hs->length++] = c;
168     break;
169   }
170   return NULLBUFF;
171 }
172 
173 void
174 AsyncInput(buff, cnt)
175 u_char *buff;
176 int cnt;
177 {
178   struct mbuf *bp;
179 
180   OsAddInOctets(cnt);
181   if (DEV_IS_SYNC) {
182     bp = mballoc(cnt, MB_ASYNC);
183     bcopy(buff, MBUF_CTOP(bp), cnt);
184     bp->cnt = cnt;
185     HdlcInput(bp);
186   } else {
187     while (cnt > 0) {
188       bp = AsyncDecode(*buff++);
189       if (bp)
190         HdlcInput(bp);
191       cnt--;
192     }
193   }
194 }
195