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