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