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