1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org>
5 * based on work by Toshiharu OHNO <tony-o@iij.ad.jp>
6 * Internet Initiative Japan, Inc (IIJ)
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 */
31
32 #include <sys/types.h>
33
34 #include <string.h>
35 #include <termios.h>
36
37 #include "layer.h"
38 #include "mbuf.h"
39 #include "log.h"
40 #include "defs.h"
41 #include "timer.h"
42 #include "fsm.h"
43 #include "lqr.h"
44 #include "hdlc.h"
45 #include "lcp.h"
46 #include "proto.h"
47 #include "async.h"
48 #include "throughput.h"
49 #include "ccp.h"
50 #include "link.h"
51 #include "descriptor.h"
52 #include "physical.h"
53
54 #define MODE_HUNT 0x01
55 #define MODE_ESC 0x02
56
57 void
async_Init(struct async * async)58 async_Init(struct async *async)
59 {
60 async_Setup(async);
61 memset(async->cfg.EscMap, '\0', sizeof async->cfg.EscMap);
62 }
63
64 void
async_Setup(struct async * async)65 async_Setup(struct async *async)
66 {
67 async->mode = MODE_HUNT;
68 async->length = 0;
69 async->my_accmap = async->his_accmap = 0xffffffff;
70 }
71
72 void
async_SetLinkParams(struct async * async,u_int32_t mymap,u_int32_t hismap)73 async_SetLinkParams(struct async *async, u_int32_t mymap, u_int32_t hismap)
74 {
75 async->my_accmap = mymap;
76 async->his_accmap = hismap | mymap;
77 }
78
79 /*
80 * Encode into async HDLC byte code
81 */
82 static void
async_Encode(struct async * async,u_char ** cp,u_char c,int proto)83 async_Encode(struct async *async, u_char **cp, u_char c, int proto)
84 {
85 u_char *wp;
86
87 wp = *cp;
88 if ((c < 0x20 && (proto == PROTO_LCP || (async->his_accmap & (1 << c))))
89 || (c == HDLC_ESC) || (c == HDLC_SYN)) {
90 *wp++ = HDLC_ESC;
91 c ^= HDLC_XOR;
92 }
93 if (async->cfg.EscMap[32] && async->cfg.EscMap[c >> 3] & (1 << (c & 7))) {
94 *wp++ = HDLC_ESC;
95 c ^= HDLC_XOR;
96 }
97 *wp++ = c;
98 *cp = wp;
99 }
100
101 static struct mbuf *
async_LayerPush(struct bundle * b __unused,struct link * l,struct mbuf * bp,int pri __unused,u_short * proto)102 async_LayerPush(struct bundle *b __unused, struct link *l, struct mbuf *bp,
103 int pri __unused, u_short *proto)
104 {
105 struct physical *p = link2physical(l);
106 u_char *cp, *sp, *ep;
107 struct mbuf *wp;
108 size_t oldcnt;
109 size_t cnt;
110
111 if (!p || m_length(bp) > HDLCSIZE) {
112 m_freem(bp);
113 return NULL;
114 }
115
116 oldcnt = m_length(bp);
117
118 cp = p->async.xbuff;
119 ep = cp + HDLCSIZE - 10;
120 wp = bp;
121 *cp++ = HDLC_SYN;
122 while (wp) {
123 sp = MBUF_CTOP(wp);
124 for (cnt = wp->m_len; cnt > 0; cnt--) {
125 async_Encode(&p->async, &cp, *sp++, *proto);
126 if (cp >= ep) {
127 m_freem(bp);
128 return NULL;
129 }
130 }
131 wp = wp->m_next;
132 }
133 *cp++ = HDLC_SYN;
134
135 cnt = cp - p->async.xbuff;
136 m_freem(bp);
137 bp = m_get(cnt, MB_ASYNCOUT);
138 memcpy(MBUF_CTOP(bp), p->async.xbuff, cnt);
139 bp->priv = cnt - oldcnt;
140 log_DumpBp(LogASYNC, "Write", bp);
141
142 return bp;
143 }
144
145 static struct mbuf *
async_Decode(struct async * async,u_char c)146 async_Decode(struct async *async, u_char c)
147 {
148 struct mbuf *bp;
149
150 if ((async->mode & MODE_HUNT) && c != HDLC_SYN)
151 return NULL;
152
153 switch (c) {
154 case HDLC_SYN:
155 async->mode &= ~MODE_HUNT;
156 if (async->length) { /* packet is ready. */
157 bp = m_get(async->length, MB_ASYNCIN);
158 mbuf_Write(bp, async->hbuff, async->length);
159 async->length = 0;
160 return bp;
161 }
162 break;
163 case HDLC_ESC:
164 if (!(async->mode & MODE_ESC)) {
165 async->mode |= MODE_ESC;
166 break;
167 }
168 /* FALLTHROUGH */
169 default:
170 if (async->length >= HDLCSIZE) {
171 /* packet is too large, discard it */
172 log_Printf(LogWARN, "Packet too large (%d), discarding.\n",
173 async->length);
174 async->length = 0;
175 async->mode = MODE_HUNT;
176 break;
177 }
178 if (async->mode & MODE_ESC) {
179 c ^= HDLC_XOR;
180 async->mode &= ~MODE_ESC;
181 }
182 async->hbuff[async->length++] = c;
183 break;
184 }
185 return NULL;
186 }
187
188 static struct mbuf *
async_LayerPull(struct bundle * b __unused,struct link * l,struct mbuf * bp,u_short * proto __unused)189 async_LayerPull(struct bundle *b __unused, struct link *l, struct mbuf *bp,
190 u_short *proto __unused)
191 {
192 struct mbuf *nbp, **last;
193 struct physical *p = link2physical(l);
194 u_char *ch;
195 size_t cnt;
196
197 if (!p) {
198 log_Printf(LogERROR, "Can't Pull an async packet from a logical link\n");
199 return bp;
200 }
201
202 last = &nbp;
203
204 log_DumpBp(LogASYNC, "Read", bp);
205 while (bp) {
206 ch = MBUF_CTOP(bp);
207 for (cnt = bp->m_len; cnt; cnt--) {
208 *last = async_Decode(&p->async, *ch++);
209 if (*last != NULL)
210 last = &(*last)->m_nextpkt;
211 }
212 bp = m_free(bp);
213 }
214
215 return nbp;
216 }
217
218 struct layer asynclayer =
219 { LAYER_ASYNC, "async", async_LayerPush, async_LayerPull };
220