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