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