ppp_tty.c revision 1.5 1 1.5 paulus /* $NetBSD: ppp_tty.c,v 1.5 1996/03/15 02:28:10 paulus Exp $ */
2 1.1 paulus
3 1.1 paulus /*
4 1.1 paulus * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous
5 1.1 paulus * tty devices.
6 1.1 paulus *
7 1.1 paulus * Copyright (c) 1989 Carnegie Mellon University.
8 1.1 paulus * All rights reserved.
9 1.1 paulus *
10 1.1 paulus * Redistribution and use in source and binary forms are permitted
11 1.1 paulus * provided that the above copyright notice and this paragraph are
12 1.1 paulus * duplicated in all such forms and that any documentation,
13 1.1 paulus * advertising materials, and other materials related to such
14 1.1 paulus * distribution and use acknowledge that the software was developed
15 1.1 paulus * by Carnegie Mellon University. The name of the
16 1.1 paulus * University may not be used to endorse or promote products derived
17 1.1 paulus * from this software without specific prior written permission.
18 1.1 paulus * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19 1.1 paulus * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20 1.1 paulus * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 1.1 paulus *
22 1.1 paulus * Drew D. Perkins
23 1.1 paulus * Carnegie Mellon University
24 1.1 paulus * 4910 Forbes Ave.
25 1.1 paulus * Pittsburgh, PA 15213
26 1.1 paulus * (412) 268-8576
27 1.1 paulus * ddp (at) andrew.cmu.edu
28 1.1 paulus *
29 1.1 paulus * Based on:
30 1.1 paulus * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
31 1.1 paulus *
32 1.1 paulus * Copyright (c) 1987 Regents of the University of California.
33 1.1 paulus * All rights reserved.
34 1.1 paulus *
35 1.1 paulus * Redistribution and use in source and binary forms are permitted
36 1.1 paulus * provided that the above copyright notice and this paragraph are
37 1.1 paulus * duplicated in all such forms and that any documentation,
38 1.1 paulus * advertising materials, and other materials related to such
39 1.1 paulus * distribution and use acknowledge that the software was developed
40 1.1 paulus * by the University of California, Berkeley. The name of the
41 1.1 paulus * University may not be used to endorse or promote products derived
42 1.1 paulus * from this software without specific prior written permission.
43 1.1 paulus * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
44 1.1 paulus * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
45 1.1 paulus * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
46 1.1 paulus *
47 1.1 paulus * Serial Line interface
48 1.1 paulus *
49 1.1 paulus * Rick Adams
50 1.1 paulus * Center for Seismic Studies
51 1.1 paulus * 1300 N 17th Street, Suite 1450
52 1.1 paulus * Arlington, Virginia 22209
53 1.1 paulus * (703)276-7900
54 1.1 paulus * rick (at) seismo.ARPA
55 1.1 paulus * seismo!rick
56 1.1 paulus *
57 1.1 paulus * Pounded on heavily by Chris Torek (chris (at) mimsy.umd.edu, umcp-cs!chris).
58 1.1 paulus * Converted to 4.3BSD Beta by Chris Torek.
59 1.1 paulus * Other changes made at Berkeley, based in part on code by Kirk Smith.
60 1.1 paulus *
61 1.1 paulus * Converted to 4.3BSD+ 386BSD by Brad Parker (brad (at) cayman.com)
62 1.1 paulus * Added VJ tcp header compression; more unified ioctls
63 1.1 paulus *
64 1.1 paulus * Extensively modified by Paul Mackerras (paulus (at) cs.anu.edu.au).
65 1.1 paulus * Cleaned up a lot of the mbuf-related code to fix bugs that
66 1.1 paulus * caused system crashes and packet corruption. Changed pppstart
67 1.1 paulus * so that it doesn't just give up with a collision if the whole
68 1.1 paulus * packet doesn't fit in the output ring buffer.
69 1.1 paulus *
70 1.1 paulus * Added priority queueing for interactive IP packets, following
71 1.1 paulus * the model of if_sl.c, plus hooks for bpf.
72 1.1 paulus * Paul Mackerras (paulus (at) cs.anu.edu.au).
73 1.1 paulus */
74 1.1 paulus
75 1.1 paulus /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
76 1.1 paulus /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
77 1.1 paulus
78 1.1 paulus #include "ppp.h"
79 1.1 paulus #if NPPP > 0
80 1.1 paulus
81 1.1 paulus #define VJC
82 1.1 paulus #define PPP_COMPRESS
83 1.1 paulus
84 1.1 paulus #include <sys/param.h>
85 1.1 paulus #include <sys/proc.h>
86 1.1 paulus #include <sys/mbuf.h>
87 1.1 paulus #include <sys/dkstat.h>
88 1.1 paulus #include <sys/socket.h>
89 1.1 paulus #include <sys/ioctl.h>
90 1.1 paulus #include <sys/file.h>
91 1.1 paulus #include <sys/tty.h>
92 1.1 paulus #include <sys/kernel.h>
93 1.1 paulus #include <sys/conf.h>
94 1.1 paulus #include <sys/vnode.h>
95 1.4 christos #include <sys/systm.h>
96 1.1 paulus
97 1.1 paulus #include <net/if.h>
98 1.1 paulus #include <net/if_types.h>
99 1.1 paulus
100 1.1 paulus #ifdef VJC
101 1.1 paulus #include <netinet/in.h>
102 1.1 paulus #include <netinet/in_systm.h>
103 1.1 paulus #include <netinet/ip.h>
104 1.1 paulus #include <net/slcompress.h>
105 1.1 paulus #endif
106 1.1 paulus
107 1.5 paulus #include <net/bpf.h>
108 1.1 paulus #include <net/ppp_defs.h>
109 1.1 paulus #include <net/if_ppp.h>
110 1.1 paulus #include <net/if_pppvar.h>
111 1.1 paulus
112 1.1 paulus int pppopen __P((dev_t dev, struct tty *tp));
113 1.1 paulus int pppclose __P((struct tty *tp, int flag));
114 1.1 paulus int pppread __P((struct tty *tp, struct uio *uio, int flag));
115 1.1 paulus int pppwrite __P((struct tty *tp, struct uio *uio, int flag));
116 1.1 paulus int ppptioctl __P((struct tty *tp, u_long cmd, caddr_t data, int flag,
117 1.1 paulus struct proc *));
118 1.1 paulus int pppinput __P((int c, struct tty *tp));
119 1.1 paulus int pppstart __P((struct tty *tp));
120 1.1 paulus
121 1.1 paulus static u_int16_t pppfcs __P((u_int16_t fcs, u_char *cp, int len));
122 1.1 paulus static void pppasyncstart __P((struct ppp_softc *));
123 1.1 paulus static void pppasyncctlp __P((struct ppp_softc *));
124 1.1 paulus static void pppasyncrelinq __P((struct ppp_softc *));
125 1.1 paulus static void ppp_timeout __P((void *));
126 1.1 paulus static void pppgetm __P((struct ppp_softc *sc));
127 1.1 paulus static void pppdumpb __P((u_char *b, int l));
128 1.1 paulus static void ppplogchar __P((struct ppp_softc *, int));
129 1.1 paulus
130 1.1 paulus /*
131 1.1 paulus * Some useful mbuf macros not in mbuf.h.
132 1.1 paulus */
133 1.1 paulus #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
134 1.1 paulus
135 1.1 paulus #define M_DATASTART(m) \
136 1.1 paulus (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
137 1.1 paulus (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
138 1.1 paulus
139 1.1 paulus #define M_DATASIZE(m) \
140 1.1 paulus (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
141 1.1 paulus (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
142 1.1 paulus
143 1.1 paulus /*
144 1.1 paulus * Does c need to be escaped?
145 1.1 paulus */
146 1.1 paulus #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
147 1.1 paulus
148 1.1 paulus /*
149 1.1 paulus * Procedures for using an async tty interface for PPP.
150 1.1 paulus */
151 1.1 paulus
152 1.1 paulus /* This is a NetBSD-1.0 or later kernel. */
153 1.1 paulus #define CCOUNT(q) ((q)->c_cc)
154 1.1 paulus
155 1.1 paulus #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
156 1.1 paulus
157 1.1 paulus /*
158 1.1 paulus * Line specific open routine for async tty devices.
159 1.1 paulus * Attach the given tty to the first available ppp unit.
160 1.1 paulus * Called from device open routine or ttioctl.
161 1.1 paulus */
162 1.1 paulus /* ARGSUSED */
163 1.1 paulus int
164 1.1 paulus pppopen(dev, tp)
165 1.1 paulus dev_t dev;
166 1.1 paulus register struct tty *tp;
167 1.1 paulus {
168 1.1 paulus struct proc *p = curproc; /* XXX */
169 1.1 paulus register struct ppp_softc *sc;
170 1.4 christos int error, s;
171 1.1 paulus
172 1.4 christos if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
173 1.1 paulus return (error);
174 1.1 paulus
175 1.1 paulus s = spltty();
176 1.1 paulus
177 1.1 paulus if (tp->t_line == PPPDISC) {
178 1.1 paulus sc = (struct ppp_softc *) tp->t_sc;
179 1.1 paulus if (sc != NULL && sc->sc_devp == (void *) tp) {
180 1.1 paulus splx(s);
181 1.1 paulus return (0);
182 1.1 paulus }
183 1.1 paulus }
184 1.1 paulus
185 1.1 paulus if ((sc = pppalloc(p->p_pid)) == NULL) {
186 1.1 paulus splx(s);
187 1.1 paulus return ENXIO;
188 1.1 paulus }
189 1.1 paulus
190 1.1 paulus if (sc->sc_relinq)
191 1.1 paulus (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */
192 1.1 paulus
193 1.1 paulus sc->sc_ilen = 0;
194 1.1 paulus sc->sc_m = NULL;
195 1.1 paulus bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
196 1.1 paulus sc->sc_asyncmap[0] = 0xffffffff;
197 1.1 paulus sc->sc_asyncmap[3] = 0x60000000;
198 1.1 paulus sc->sc_rasyncmap = 0;
199 1.1 paulus sc->sc_devp = (void *) tp;
200 1.1 paulus sc->sc_start = pppasyncstart;
201 1.1 paulus sc->sc_ctlp = pppasyncctlp;
202 1.1 paulus sc->sc_relinq = pppasyncrelinq;
203 1.1 paulus sc->sc_outm = NULL;
204 1.1 paulus pppgetm(sc);
205 1.1 paulus sc->sc_if.if_flags |= IFF_RUNNING;
206 1.3 mycroft sc->sc_if.if_baudrate = tp->t_ospeed;
207 1.1 paulus
208 1.1 paulus tp->t_sc = (caddr_t) sc;
209 1.1 paulus ttyflush(tp, FREAD | FWRITE);
210 1.1 paulus
211 1.1 paulus splx(s);
212 1.1 paulus return (0);
213 1.1 paulus }
214 1.1 paulus
215 1.1 paulus /*
216 1.1 paulus * Line specific close routine, called from device close routine
217 1.1 paulus * and from ttioctl.
218 1.1 paulus * Detach the tty from the ppp unit.
219 1.1 paulus * Mimics part of ttyclose().
220 1.1 paulus */
221 1.1 paulus int
222 1.1 paulus pppclose(tp, flag)
223 1.1 paulus struct tty *tp;
224 1.1 paulus int flag;
225 1.1 paulus {
226 1.1 paulus register struct ppp_softc *sc;
227 1.1 paulus int s;
228 1.1 paulus
229 1.1 paulus s = spltty();
230 1.5 paulus ttyflush(tp, FREAD|FWRITE);
231 1.1 paulus tp->t_line = 0;
232 1.1 paulus sc = (struct ppp_softc *) tp->t_sc;
233 1.1 paulus if (sc != NULL) {
234 1.1 paulus tp->t_sc = NULL;
235 1.1 paulus if (tp == (struct tty *) sc->sc_devp) {
236 1.1 paulus pppasyncrelinq(sc);
237 1.1 paulus pppdealloc(sc);
238 1.1 paulus }
239 1.1 paulus }
240 1.1 paulus splx(s);
241 1.1 paulus return 0;
242 1.1 paulus }
243 1.1 paulus
244 1.1 paulus /*
245 1.1 paulus * Relinquish the interface unit to another device.
246 1.1 paulus */
247 1.1 paulus static void
248 1.1 paulus pppasyncrelinq(sc)
249 1.1 paulus struct ppp_softc *sc;
250 1.1 paulus {
251 1.1 paulus int s;
252 1.1 paulus
253 1.1 paulus s = spltty();
254 1.1 paulus if (sc->sc_outm) {
255 1.1 paulus m_freem(sc->sc_outm);
256 1.1 paulus sc->sc_outm = NULL;
257 1.1 paulus }
258 1.1 paulus if (sc->sc_m) {
259 1.1 paulus m_freem(sc->sc_m);
260 1.1 paulus sc->sc_m = NULL;
261 1.1 paulus }
262 1.1 paulus if (sc->sc_flags & SC_TIMEOUT) {
263 1.1 paulus untimeout(ppp_timeout, (void *) sc);
264 1.1 paulus sc->sc_flags &= ~SC_TIMEOUT;
265 1.1 paulus }
266 1.1 paulus splx(s);
267 1.1 paulus }
268 1.1 paulus
269 1.1 paulus /*
270 1.1 paulus * Line specific (tty) read routine.
271 1.1 paulus */
272 1.1 paulus int
273 1.1 paulus pppread(tp, uio, flag)
274 1.1 paulus register struct tty *tp;
275 1.1 paulus struct uio *uio;
276 1.1 paulus int flag;
277 1.1 paulus {
278 1.1 paulus register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
279 1.1 paulus struct mbuf *m, *m0;
280 1.1 paulus register int s;
281 1.1 paulus int error = 0;
282 1.1 paulus
283 1.1 paulus if (sc == NULL)
284 1.1 paulus return 0;
285 1.1 paulus /*
286 1.1 paulus * Loop waiting for input, checking that nothing disasterous
287 1.1 paulus * happens in the meantime.
288 1.1 paulus */
289 1.1 paulus s = spltty();
290 1.1 paulus for (;;) {
291 1.1 paulus if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
292 1.1 paulus splx(s);
293 1.1 paulus return 0;
294 1.1 paulus }
295 1.1 paulus if (sc->sc_inq.ifq_head != NULL)
296 1.1 paulus break;
297 1.1 paulus if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0
298 1.1 paulus && (tp->t_state & TS_ISOPEN)) {
299 1.1 paulus splx(s);
300 1.1 paulus return 0; /* end of file */
301 1.1 paulus }
302 1.1 paulus if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
303 1.1 paulus splx(s);
304 1.1 paulus return (EWOULDBLOCK);
305 1.1 paulus }
306 1.1 paulus error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI|PCATCH, ttyin, 0);
307 1.1 paulus if (error) {
308 1.1 paulus splx(s);
309 1.1 paulus return error;
310 1.1 paulus }
311 1.1 paulus }
312 1.1 paulus
313 1.1 paulus /* Pull place-holder byte out of canonical queue */
314 1.1 paulus getc(&tp->t_canq);
315 1.1 paulus
316 1.1 paulus /* Get the packet from the input queue */
317 1.1 paulus IF_DEQUEUE(&sc->sc_inq, m0);
318 1.1 paulus splx(s);
319 1.1 paulus
320 1.1 paulus for (m = m0; m && uio->uio_resid; m = m->m_next)
321 1.4 christos if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
322 1.1 paulus break;
323 1.1 paulus m_freem(m0);
324 1.1 paulus return (error);
325 1.1 paulus }
326 1.1 paulus
327 1.1 paulus /*
328 1.1 paulus * Line specific (tty) write routine.
329 1.1 paulus */
330 1.1 paulus int
331 1.1 paulus pppwrite(tp, uio, flag)
332 1.1 paulus register struct tty *tp;
333 1.1 paulus struct uio *uio;
334 1.1 paulus int flag;
335 1.1 paulus {
336 1.1 paulus register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
337 1.1 paulus struct mbuf *m, *m0, **mp;
338 1.1 paulus struct sockaddr dst;
339 1.1 paulus int len, error;
340 1.1 paulus
341 1.1 paulus if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
342 1.1 paulus return 0; /* wrote 0 bytes */
343 1.1 paulus if (tp->t_line != PPPDISC)
344 1.1 paulus return (EINVAL);
345 1.1 paulus if (sc == NULL || tp != (struct tty *) sc->sc_devp)
346 1.1 paulus return EIO;
347 1.1 paulus if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
348 1.1 paulus uio->uio_resid < PPP_HDRLEN)
349 1.1 paulus return (EMSGSIZE);
350 1.1 paulus for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
351 1.1 paulus MGET(m, M_WAIT, MT_DATA);
352 1.1 paulus if ((*mp = m) == NULL) {
353 1.1 paulus m_freem(m0);
354 1.1 paulus return (ENOBUFS);
355 1.1 paulus }
356 1.1 paulus m->m_len = 0;
357 1.1 paulus if (uio->uio_resid >= MCLBYTES / 2)
358 1.1 paulus MCLGET(m, M_DONTWAIT);
359 1.1 paulus len = M_TRAILINGSPACE(m);
360 1.1 paulus if (len > uio->uio_resid)
361 1.1 paulus len = uio->uio_resid;
362 1.4 christos if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
363 1.1 paulus m_freem(m0);
364 1.1 paulus return (error);
365 1.1 paulus }
366 1.1 paulus m->m_len = len;
367 1.1 paulus }
368 1.1 paulus dst.sa_family = AF_UNSPEC;
369 1.1 paulus bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
370 1.1 paulus m0->m_data += PPP_HDRLEN;
371 1.1 paulus m0->m_len -= PPP_HDRLEN;
372 1.1 paulus return (pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0));
373 1.1 paulus }
374 1.1 paulus
375 1.1 paulus /*
376 1.1 paulus * Line specific (tty) ioctl routine.
377 1.1 paulus * This discipline requires that tty device drivers call
378 1.1 paulus * the line specific l_ioctl routine from their ioctl routines.
379 1.1 paulus */
380 1.1 paulus /* ARGSUSED */
381 1.1 paulus int
382 1.1 paulus ppptioctl(tp, cmd, data, flag, p)
383 1.1 paulus struct tty *tp;
384 1.1 paulus u_long cmd;
385 1.1 paulus caddr_t data;
386 1.1 paulus int flag;
387 1.1 paulus struct proc *p;
388 1.1 paulus {
389 1.1 paulus struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
390 1.1 paulus int error, s;
391 1.1 paulus
392 1.1 paulus if (sc == NULL || tp != (struct tty *) sc->sc_devp)
393 1.1 paulus return -1;
394 1.1 paulus
395 1.1 paulus error = 0;
396 1.1 paulus switch (cmd) {
397 1.1 paulus case PPPIOCSASYNCMAP:
398 1.4 christos if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
399 1.1 paulus break;
400 1.1 paulus sc->sc_asyncmap[0] = *(u_int *)data;
401 1.1 paulus break;
402 1.1 paulus
403 1.1 paulus case PPPIOCGASYNCMAP:
404 1.1 paulus *(u_int *)data = sc->sc_asyncmap[0];
405 1.1 paulus break;
406 1.1 paulus
407 1.1 paulus case PPPIOCSRASYNCMAP:
408 1.4 christos if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
409 1.1 paulus break;
410 1.1 paulus sc->sc_rasyncmap = *(u_int *)data;
411 1.1 paulus break;
412 1.1 paulus
413 1.1 paulus case PPPIOCGRASYNCMAP:
414 1.1 paulus *(u_int *)data = sc->sc_rasyncmap;
415 1.1 paulus break;
416 1.1 paulus
417 1.1 paulus case PPPIOCSXASYNCMAP:
418 1.4 christos if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
419 1.1 paulus break;
420 1.1 paulus s = spltty();
421 1.1 paulus bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
422 1.1 paulus sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
423 1.1 paulus sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
424 1.1 paulus sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
425 1.1 paulus splx(s);
426 1.1 paulus break;
427 1.1 paulus
428 1.1 paulus case PPPIOCGXASYNCMAP:
429 1.1 paulus bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
430 1.1 paulus break;
431 1.1 paulus
432 1.1 paulus default:
433 1.1 paulus error = pppioctl(sc, cmd, data, flag, p);
434 1.1 paulus if (error == 0 && cmd == PPPIOCSMRU)
435 1.1 paulus pppgetm(sc);
436 1.1 paulus }
437 1.1 paulus
438 1.1 paulus return error;
439 1.1 paulus }
440 1.1 paulus
441 1.1 paulus /*
442 1.1 paulus * FCS lookup table as calculated by genfcstab.
443 1.1 paulus */
444 1.1 paulus static u_int16_t fcstab[256] = {
445 1.1 paulus 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
446 1.1 paulus 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
447 1.1 paulus 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
448 1.1 paulus 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
449 1.1 paulus 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
450 1.1 paulus 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
451 1.1 paulus 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
452 1.1 paulus 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
453 1.1 paulus 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
454 1.1 paulus 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
455 1.1 paulus 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
456 1.1 paulus 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
457 1.1 paulus 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
458 1.1 paulus 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
459 1.1 paulus 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
460 1.1 paulus 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
461 1.1 paulus 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
462 1.1 paulus 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
463 1.1 paulus 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
464 1.1 paulus 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
465 1.1 paulus 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
466 1.1 paulus 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
467 1.1 paulus 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
468 1.1 paulus 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
469 1.1 paulus 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
470 1.1 paulus 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
471 1.1 paulus 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
472 1.1 paulus 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
473 1.1 paulus 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
474 1.1 paulus 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
475 1.1 paulus 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
476 1.1 paulus 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
477 1.1 paulus };
478 1.1 paulus
479 1.1 paulus /*
480 1.1 paulus * Calculate a new FCS given the current FCS and the new data.
481 1.1 paulus */
482 1.1 paulus static u_int16_t
483 1.1 paulus pppfcs(fcs, cp, len)
484 1.1 paulus register u_int16_t fcs;
485 1.1 paulus register u_char *cp;
486 1.1 paulus register int len;
487 1.1 paulus {
488 1.1 paulus while (len--)
489 1.1 paulus fcs = PPP_FCS(fcs, *cp++);
490 1.1 paulus return (fcs);
491 1.1 paulus }
492 1.1 paulus
493 1.1 paulus /*
494 1.1 paulus * This gets called from pppoutput when a new packet is
495 1.1 paulus * put on a queue, at splsoftnet.
496 1.1 paulus */
497 1.1 paulus static void
498 1.1 paulus pppasyncstart(sc)
499 1.1 paulus register struct ppp_softc *sc;
500 1.1 paulus {
501 1.1 paulus register struct tty *tp = (struct tty *) sc->sc_devp;
502 1.1 paulus int s;
503 1.1 paulus
504 1.1 paulus s = spltty();
505 1.1 paulus pppstart(tp);
506 1.1 paulus splx(s);
507 1.1 paulus }
508 1.1 paulus
509 1.1 paulus /*
510 1.1 paulus * This gets called when a received packet is placed on
511 1.1 paulus * the inq, at splsoftnet.
512 1.1 paulus */
513 1.1 paulus static void
514 1.1 paulus pppasyncctlp(sc)
515 1.1 paulus struct ppp_softc *sc;
516 1.1 paulus {
517 1.1 paulus struct tty *tp;
518 1.1 paulus int s;
519 1.1 paulus
520 1.1 paulus /* Put a placeholder byte in canq for ttselect()/ttnread(). */
521 1.1 paulus s = spltty();
522 1.1 paulus tp = (struct tty *) sc->sc_devp;
523 1.1 paulus putc(0, &tp->t_canq);
524 1.1 paulus ttwakeup(tp);
525 1.1 paulus splx(s);
526 1.1 paulus }
527 1.1 paulus
528 1.1 paulus /*
529 1.1 paulus * Start output on async tty interface. Get another datagram
530 1.1 paulus * to send from the interface queue and start sending it.
531 1.1 paulus * Called at spltty or higher.
532 1.1 paulus */
533 1.1 paulus int
534 1.1 paulus pppstart(tp)
535 1.1 paulus register struct tty *tp;
536 1.1 paulus {
537 1.1 paulus register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
538 1.1 paulus register struct mbuf *m;
539 1.1 paulus register int len;
540 1.1 paulus register u_char *start, *stop, *cp;
541 1.4 christos int n, ndone, done, idle;
542 1.1 paulus struct mbuf *m2;
543 1.1 paulus
544 1.4 christos if (((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
545 1.1 paulus || sc == NULL || tp != (struct tty *) sc->sc_devp) {
546 1.1 paulus if (tp->t_oproc != NULL)
547 1.1 paulus (*tp->t_oproc)(tp);
548 1.1 paulus return 0;
549 1.1 paulus }
550 1.1 paulus
551 1.1 paulus idle = 0;
552 1.1 paulus while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
553 1.1 paulus /*
554 1.1 paulus * See if we have an existing packet partly sent.
555 1.1 paulus * If not, get a new packet and start sending it.
556 1.1 paulus */
557 1.1 paulus m = sc->sc_outm;
558 1.1 paulus if (m == NULL) {
559 1.1 paulus /*
560 1.1 paulus * Get another packet to be sent.
561 1.1 paulus */
562 1.1 paulus m = ppp_dequeue(sc);
563 1.1 paulus if (m == NULL) {
564 1.1 paulus idle = 1;
565 1.1 paulus break;
566 1.1 paulus }
567 1.1 paulus
568 1.1 paulus /*
569 1.1 paulus * The extra PPP_FLAG will start up a new packet, and thus
570 1.1 paulus * will flush any accumulated garbage. We do this whenever
571 1.1 paulus * the line may have been idle for some time.
572 1.1 paulus */
573 1.1 paulus if (CCOUNT(&tp->t_outq) == 0) {
574 1.5 paulus ++sc->sc_stats.ppp_obytes;
575 1.1 paulus (void) putc(PPP_FLAG, &tp->t_outq);
576 1.1 paulus }
577 1.1 paulus
578 1.1 paulus /* Calculate the FCS for the first mbuf's worth. */
579 1.1 paulus sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
580 1.3 mycroft sc->sc_if.if_lastchange = time;
581 1.1 paulus }
582 1.1 paulus
583 1.1 paulus for (;;) {
584 1.1 paulus start = mtod(m, u_char *);
585 1.1 paulus len = m->m_len;
586 1.1 paulus stop = start + len;
587 1.1 paulus while (len > 0) {
588 1.1 paulus /*
589 1.1 paulus * Find out how many bytes in the string we can
590 1.1 paulus * handle without doing something special.
591 1.1 paulus */
592 1.1 paulus for (cp = start; cp < stop; cp++)
593 1.1 paulus if (ESCAPE_P(*cp))
594 1.1 paulus break;
595 1.1 paulus n = cp - start;
596 1.1 paulus if (n) {
597 1.1 paulus /* NetBSD (0.9 or later), 4.3-Reno or similar. */
598 1.1 paulus ndone = n - b_to_q(start, n, &tp->t_outq);
599 1.1 paulus len -= ndone;
600 1.1 paulus start += ndone;
601 1.5 paulus sc->sc_stats.ppp_obytes += ndone;
602 1.1 paulus
603 1.1 paulus if (ndone < n)
604 1.1 paulus break; /* packet doesn't fit */
605 1.1 paulus }
606 1.1 paulus /*
607 1.1 paulus * If there are characters left in the mbuf,
608 1.1 paulus * the first one must be special..
609 1.1 paulus * Put it out in a different form.
610 1.1 paulus */
611 1.1 paulus if (len) {
612 1.1 paulus if (putc(PPP_ESCAPE, &tp->t_outq))
613 1.1 paulus break;
614 1.1 paulus if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
615 1.1 paulus (void) unputc(&tp->t_outq);
616 1.1 paulus break;
617 1.1 paulus }
618 1.5 paulus sc->sc_stats.ppp_obytes += 2;
619 1.1 paulus start++;
620 1.1 paulus len--;
621 1.1 paulus }
622 1.1 paulus }
623 1.1 paulus
624 1.1 paulus /*
625 1.1 paulus * If we didn't empty this mbuf, remember where we're up to.
626 1.1 paulus * If we emptied the last mbuf, try to add the FCS and closing
627 1.1 paulus * flag, and if we can't, leave sc_outm pointing to m, but with
628 1.1 paulus * m->m_len == 0, to remind us to output the FCS and flag later.
629 1.1 paulus */
630 1.1 paulus done = len == 0;
631 1.1 paulus if (done && m->m_next == NULL) {
632 1.1 paulus u_char *p, *q;
633 1.1 paulus int c;
634 1.1 paulus u_char endseq[8];
635 1.1 paulus
636 1.1 paulus /*
637 1.1 paulus * We may have to escape the bytes in the FCS.
638 1.1 paulus */
639 1.1 paulus p = endseq;
640 1.1 paulus c = ~sc->sc_outfcs & 0xFF;
641 1.1 paulus if (ESCAPE_P(c)) {
642 1.1 paulus *p++ = PPP_ESCAPE;
643 1.1 paulus *p++ = c ^ PPP_TRANS;
644 1.1 paulus } else
645 1.1 paulus *p++ = c;
646 1.1 paulus c = (~sc->sc_outfcs >> 8) & 0xFF;
647 1.1 paulus if (ESCAPE_P(c)) {
648 1.1 paulus *p++ = PPP_ESCAPE;
649 1.1 paulus *p++ = c ^ PPP_TRANS;
650 1.1 paulus } else
651 1.1 paulus *p++ = c;
652 1.1 paulus *p++ = PPP_FLAG;
653 1.1 paulus
654 1.1 paulus /*
655 1.1 paulus * Try to output the FCS and flag. If the bytes
656 1.1 paulus * don't all fit, back out.
657 1.1 paulus */
658 1.1 paulus for (q = endseq; q < p; ++q)
659 1.1 paulus if (putc(*q, &tp->t_outq)) {
660 1.1 paulus done = 0;
661 1.1 paulus for (; q > endseq; --q)
662 1.1 paulus unputc(&tp->t_outq);
663 1.1 paulus break;
664 1.1 paulus }
665 1.5 paulus sc->sc_stats.ppp_obytes += q - endseq;
666 1.1 paulus }
667 1.1 paulus
668 1.1 paulus if (!done) {
669 1.1 paulus /* remember where we got to */
670 1.1 paulus m->m_data = start;
671 1.1 paulus m->m_len = len;
672 1.1 paulus break;
673 1.1 paulus }
674 1.1 paulus
675 1.1 paulus /* Finished with this mbuf; free it and move on. */
676 1.1 paulus MFREE(m, m2);
677 1.1 paulus m = m2;
678 1.1 paulus if (m == NULL) {
679 1.1 paulus /* Finished a packet */
680 1.1 paulus break;
681 1.1 paulus }
682 1.1 paulus sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
683 1.1 paulus }
684 1.1 paulus
685 1.1 paulus /*
686 1.1 paulus * Here we have either finished a packet (m == NULL)
687 1.1 paulus * or filled up the output queue (m != NULL).
688 1.1 paulus */
689 1.1 paulus sc->sc_outm = m;
690 1.1 paulus if (m)
691 1.1 paulus break;
692 1.1 paulus }
693 1.1 paulus
694 1.1 paulus /*
695 1.1 paulus * If there is stuff in the output queue, send it now.
696 1.1 paulus * We are being called in lieu of ttstart and must do what it would.
697 1.1 paulus */
698 1.1 paulus if (tp->t_oproc != NULL)
699 1.1 paulus (*tp->t_oproc)(tp);
700 1.1 paulus
701 1.1 paulus /*
702 1.1 paulus * This timeout is needed for operation on a pseudo-tty,
703 1.1 paulus * because the pty code doesn't call pppstart after it has
704 1.1 paulus * drained the t_outq.
705 1.1 paulus */
706 1.1 paulus if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
707 1.1 paulus timeout(ppp_timeout, (void *) sc, 1);
708 1.1 paulus sc->sc_flags |= SC_TIMEOUT;
709 1.1 paulus }
710 1.1 paulus
711 1.1 paulus return 0;
712 1.1 paulus }
713 1.1 paulus
714 1.1 paulus /*
715 1.1 paulus * Timeout routine - try to start some more output.
716 1.1 paulus */
717 1.1 paulus static void
718 1.1 paulus ppp_timeout(x)
719 1.1 paulus void *x;
720 1.1 paulus {
721 1.1 paulus struct ppp_softc *sc = (struct ppp_softc *) x;
722 1.1 paulus struct tty *tp = (struct tty *) sc->sc_devp;
723 1.1 paulus int s;
724 1.1 paulus
725 1.1 paulus s = spltty();
726 1.1 paulus sc->sc_flags &= ~SC_TIMEOUT;
727 1.1 paulus pppstart(tp);
728 1.1 paulus splx(s);
729 1.1 paulus }
730 1.1 paulus
731 1.1 paulus /*
732 1.1 paulus * Allocate enough mbuf to handle current MRU.
733 1.1 paulus */
734 1.1 paulus static void
735 1.1 paulus pppgetm(sc)
736 1.1 paulus register struct ppp_softc *sc;
737 1.1 paulus {
738 1.1 paulus struct mbuf *m, **mp;
739 1.1 paulus int len;
740 1.1 paulus int s;
741 1.1 paulus
742 1.1 paulus s = spltty();
743 1.1 paulus mp = &sc->sc_m;
744 1.1 paulus for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
745 1.1 paulus if ((m = *mp) == NULL) {
746 1.1 paulus MGETHDR(m, M_DONTWAIT, MT_DATA);
747 1.1 paulus if (m == NULL)
748 1.1 paulus break;
749 1.1 paulus *mp = m;
750 1.1 paulus MCLGET(m, M_DONTWAIT);
751 1.1 paulus }
752 1.1 paulus len -= M_DATASIZE(m);
753 1.1 paulus mp = &m->m_next;
754 1.1 paulus }
755 1.1 paulus splx(s);
756 1.1 paulus }
757 1.1 paulus
758 1.1 paulus /*
759 1.1 paulus * tty interface receiver interrupt.
760 1.1 paulus */
761 1.1 paulus static unsigned paritytab[8] = {
762 1.1 paulus 0x96696996, 0x69969669, 0x69969669, 0x96696996,
763 1.1 paulus 0x69969669, 0x96696996, 0x96696996, 0x69969669
764 1.1 paulus };
765 1.1 paulus
766 1.1 paulus int
767 1.1 paulus pppinput(c, tp)
768 1.1 paulus int c;
769 1.1 paulus register struct tty *tp;
770 1.1 paulus {
771 1.1 paulus register struct ppp_softc *sc;
772 1.1 paulus struct mbuf *m;
773 1.1 paulus int ilen, s;
774 1.1 paulus
775 1.1 paulus sc = (struct ppp_softc *) tp->t_sc;
776 1.1 paulus if (sc == NULL || tp != (struct tty *) sc->sc_devp)
777 1.1 paulus return 0;
778 1.1 paulus
779 1.1 paulus s = spltty(); /* should be unnecessary */
780 1.1 paulus ++tk_nin;
781 1.5 paulus ++sc->sc_stats.ppp_ibytes;
782 1.1 paulus
783 1.1 paulus if (c & TTY_FE) {
784 1.1 paulus /* framing error or overrun on this char - abort packet */
785 1.1 paulus if (sc->sc_flags & SC_DEBUG)
786 1.1 paulus printf("ppp%d: bad char %x\n", sc->sc_if.if_unit, c);
787 1.1 paulus goto flush;
788 1.1 paulus }
789 1.1 paulus
790 1.1 paulus c &= 0xff;
791 1.1 paulus
792 1.5 paulus /*
793 1.5 paulus * Handle software flow control of output.
794 1.5 paulus */
795 1.5 paulus if (tp->t_iflag & IXON) {
796 1.5 paulus if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
797 1.5 paulus if ((tp->t_state & TS_TTSTOP) == 0) {
798 1.5 paulus tp->t_state |= TS_TTSTOP;
799 1.5 paulus (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
800 1.5 paulus }
801 1.5 paulus return 0;
802 1.5 paulus }
803 1.5 paulus if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
804 1.5 paulus tp->t_state &= ~TS_TTSTOP;
805 1.5 paulus if (tp->t_oproc != NULL)
806 1.5 paulus (*tp->t_oproc)(tp);
807 1.5 paulus return 0;
808 1.5 paulus }
809 1.5 paulus }
810 1.5 paulus
811 1.1 paulus if (c & 0x80)
812 1.1 paulus sc->sc_flags |= SC_RCV_B7_1;
813 1.1 paulus else
814 1.1 paulus sc->sc_flags |= SC_RCV_B7_0;
815 1.1 paulus if (paritytab[c >> 5] & (1 << (c & 0x1F)))
816 1.1 paulus sc->sc_flags |= SC_RCV_ODDP;
817 1.1 paulus else
818 1.1 paulus sc->sc_flags |= SC_RCV_EVNP;
819 1.1 paulus
820 1.1 paulus if (sc->sc_flags & SC_LOG_RAWIN)
821 1.1 paulus ppplogchar(sc, c);
822 1.1 paulus
823 1.1 paulus if (c == PPP_FLAG) {
824 1.1 paulus ilen = sc->sc_ilen;
825 1.1 paulus sc->sc_ilen = 0;
826 1.1 paulus
827 1.1 paulus if (sc->sc_rawin_count > 0)
828 1.1 paulus ppplogchar(sc, -1);
829 1.1 paulus
830 1.1 paulus /*
831 1.1 paulus * If SC_ESCAPED is set, then we've seen the packet
832 1.1 paulus * abort sequence "}~".
833 1.1 paulus */
834 1.1 paulus if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
835 1.4 christos || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
836 1.1 paulus sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
837 1.1 paulus if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
838 1.1 paulus if (sc->sc_flags & SC_DEBUG)
839 1.1 paulus printf("ppp%d: bad fcs %x\n", sc->sc_if.if_unit,
840 1.1 paulus sc->sc_fcs);
841 1.1 paulus sc->sc_if.if_ierrors++;
842 1.5 paulus sc->sc_stats.ppp_ierrors++;
843 1.1 paulus } else
844 1.1 paulus sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
845 1.1 paulus splx(s);
846 1.1 paulus return 0;
847 1.1 paulus }
848 1.1 paulus
849 1.1 paulus if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
850 1.1 paulus if (ilen) {
851 1.1 paulus if (sc->sc_flags & SC_DEBUG)
852 1.1 paulus printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
853 1.1 paulus sc->sc_if.if_ierrors++;
854 1.5 paulus sc->sc_stats.ppp_ierrors++;
855 1.1 paulus sc->sc_flags |= SC_PKTLOST;
856 1.1 paulus }
857 1.1 paulus splx(s);
858 1.1 paulus return 0;
859 1.1 paulus }
860 1.1 paulus
861 1.1 paulus /*
862 1.1 paulus * Remove FCS trailer. Somewhat painful...
863 1.1 paulus */
864 1.1 paulus ilen -= 2;
865 1.1 paulus if (--sc->sc_mc->m_len == 0) {
866 1.1 paulus for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
867 1.1 paulus ;
868 1.1 paulus sc->sc_mc = m;
869 1.1 paulus }
870 1.1 paulus sc->sc_mc->m_len--;
871 1.1 paulus
872 1.1 paulus /* excise this mbuf chain */
873 1.1 paulus m = sc->sc_m;
874 1.1 paulus sc->sc_m = sc->sc_mc->m_next;
875 1.1 paulus sc->sc_mc->m_next = NULL;
876 1.1 paulus
877 1.1 paulus ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
878 1.1 paulus sc->sc_flags &= ~SC_PKTLOST;
879 1.1 paulus
880 1.1 paulus pppgetm(sc);
881 1.1 paulus splx(s);
882 1.1 paulus return 0;
883 1.1 paulus }
884 1.1 paulus
885 1.1 paulus if (sc->sc_flags & SC_FLUSH) {
886 1.1 paulus if (sc->sc_flags & SC_LOG_FLUSH)
887 1.1 paulus ppplogchar(sc, c);
888 1.1 paulus splx(s);
889 1.1 paulus return 0;
890 1.1 paulus }
891 1.1 paulus
892 1.1 paulus if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) {
893 1.1 paulus splx(s);
894 1.1 paulus return 0;
895 1.1 paulus }
896 1.1 paulus
897 1.1 paulus if (sc->sc_flags & SC_ESCAPED) {
898 1.1 paulus sc->sc_flags &= ~SC_ESCAPED;
899 1.1 paulus c ^= PPP_TRANS;
900 1.1 paulus } else if (c == PPP_ESCAPE) {
901 1.1 paulus sc->sc_flags |= SC_ESCAPED;
902 1.1 paulus splx(s);
903 1.1 paulus return 0;
904 1.1 paulus }
905 1.1 paulus
906 1.1 paulus /*
907 1.1 paulus * Initialize buffer on first octet received.
908 1.1 paulus * First octet could be address or protocol (when compressing
909 1.1 paulus * address/control).
910 1.1 paulus * Second octet is control.
911 1.1 paulus * Third octet is first or second (when compressing protocol)
912 1.1 paulus * octet of protocol.
913 1.1 paulus * Fourth octet is second octet of protocol.
914 1.1 paulus */
915 1.1 paulus if (sc->sc_ilen == 0) {
916 1.1 paulus /* reset the first input mbuf */
917 1.1 paulus if (sc->sc_m == NULL) {
918 1.1 paulus pppgetm(sc);
919 1.1 paulus if (sc->sc_m == NULL) {
920 1.1 paulus if (sc->sc_flags & SC_DEBUG)
921 1.1 paulus printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
922 1.1 paulus goto flush;
923 1.1 paulus }
924 1.1 paulus }
925 1.1 paulus m = sc->sc_m;
926 1.1 paulus m->m_len = 0;
927 1.1 paulus m->m_data = M_DATASTART(sc->sc_m);
928 1.1 paulus sc->sc_mc = m;
929 1.1 paulus sc->sc_mp = mtod(m, char *);
930 1.1 paulus sc->sc_fcs = PPP_INITFCS;
931 1.1 paulus if (c != PPP_ALLSTATIONS) {
932 1.1 paulus if (sc->sc_flags & SC_REJ_COMP_AC) {
933 1.1 paulus if (sc->sc_flags & SC_DEBUG)
934 1.1 paulus printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
935 1.1 paulus sc->sc_if.if_unit, c);
936 1.1 paulus goto flush;
937 1.1 paulus }
938 1.1 paulus *sc->sc_mp++ = PPP_ALLSTATIONS;
939 1.1 paulus *sc->sc_mp++ = PPP_UI;
940 1.1 paulus sc->sc_ilen += 2;
941 1.1 paulus m->m_len += 2;
942 1.1 paulus }
943 1.1 paulus }
944 1.1 paulus if (sc->sc_ilen == 1 && c != PPP_UI) {
945 1.1 paulus if (sc->sc_flags & SC_DEBUG)
946 1.1 paulus printf("ppp%d: missing UI (0x3), got 0x%x\n",
947 1.1 paulus sc->sc_if.if_unit, c);
948 1.1 paulus goto flush;
949 1.1 paulus }
950 1.1 paulus if (sc->sc_ilen == 2 && (c & 1) == 1) {
951 1.1 paulus /* a compressed protocol */
952 1.1 paulus *sc->sc_mp++ = 0;
953 1.1 paulus sc->sc_ilen++;
954 1.1 paulus sc->sc_mc->m_len++;
955 1.1 paulus }
956 1.1 paulus if (sc->sc_ilen == 3 && (c & 1) == 0) {
957 1.1 paulus if (sc->sc_flags & SC_DEBUG)
958 1.1 paulus printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
959 1.1 paulus (sc->sc_mp[-1] << 8) + c);
960 1.1 paulus goto flush;
961 1.1 paulus }
962 1.1 paulus
963 1.1 paulus /* packet beyond configured mru? */
964 1.1 paulus if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
965 1.1 paulus if (sc->sc_flags & SC_DEBUG)
966 1.1 paulus printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
967 1.1 paulus goto flush;
968 1.1 paulus }
969 1.1 paulus
970 1.1 paulus /* is this mbuf full? */
971 1.1 paulus m = sc->sc_mc;
972 1.1 paulus if (M_TRAILINGSPACE(m) <= 0) {
973 1.1 paulus if (m->m_next == NULL) {
974 1.1 paulus pppgetm(sc);
975 1.1 paulus if (m->m_next == NULL) {
976 1.1 paulus if (sc->sc_flags & SC_DEBUG)
977 1.1 paulus printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
978 1.1 paulus goto flush;
979 1.1 paulus }
980 1.1 paulus }
981 1.1 paulus sc->sc_mc = m = m->m_next;
982 1.1 paulus m->m_len = 0;
983 1.1 paulus m->m_data = M_DATASTART(m);
984 1.1 paulus sc->sc_mp = mtod(m, char *);
985 1.1 paulus }
986 1.1 paulus
987 1.1 paulus ++m->m_len;
988 1.1 paulus *sc->sc_mp++ = c;
989 1.1 paulus sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
990 1.1 paulus splx(s);
991 1.1 paulus return 0;
992 1.1 paulus
993 1.1 paulus flush:
994 1.1 paulus if (!(sc->sc_flags & SC_FLUSH)) {
995 1.1 paulus sc->sc_if.if_ierrors++;
996 1.5 paulus sc->sc_stats.ppp_ierrors++;
997 1.1 paulus sc->sc_flags |= SC_FLUSH;
998 1.1 paulus if (sc->sc_flags & SC_LOG_FLUSH)
999 1.1 paulus ppplogchar(sc, c);
1000 1.1 paulus }
1001 1.1 paulus splx(s);
1002 1.1 paulus return 0;
1003 1.1 paulus }
1004 1.1 paulus
1005 1.1 paulus #define MAX_DUMP_BYTES 128
1006 1.1 paulus
1007 1.1 paulus static void
1008 1.1 paulus ppplogchar(sc, c)
1009 1.1 paulus struct ppp_softc *sc;
1010 1.1 paulus int c;
1011 1.1 paulus {
1012 1.1 paulus if (c >= 0)
1013 1.1 paulus sc->sc_rawin[sc->sc_rawin_count++] = c;
1014 1.1 paulus if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1015 1.4 christos || (c < 0 && sc->sc_rawin_count > 0)) {
1016 1.1 paulus printf("ppp%d input: ", sc->sc_if.if_unit);
1017 1.1 paulus pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
1018 1.1 paulus sc->sc_rawin_count = 0;
1019 1.1 paulus }
1020 1.1 paulus }
1021 1.1 paulus
1022 1.1 paulus static void
1023 1.1 paulus pppdumpb(b, l)
1024 1.1 paulus u_char *b;
1025 1.1 paulus int l;
1026 1.1 paulus {
1027 1.1 paulus char buf[3*MAX_DUMP_BYTES+4];
1028 1.1 paulus char *bp = buf;
1029 1.1 paulus static char digits[] = "0123456789abcdef";
1030 1.1 paulus
1031 1.1 paulus while (l--) {
1032 1.1 paulus if (bp >= buf + sizeof(buf) - 3) {
1033 1.1 paulus *bp++ = '>';
1034 1.1 paulus break;
1035 1.1 paulus }
1036 1.1 paulus *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
1037 1.1 paulus *bp++ = digits[*b++ & 0xf];
1038 1.1 paulus *bp++ = ' ';
1039 1.1 paulus }
1040 1.1 paulus
1041 1.1 paulus *bp = 0;
1042 1.1 paulus printf("%s\n", buf);
1043 1.1 paulus }
1044 1.1 paulus
1045 1.1 paulus #endif /* NPPP > 0 */
1046