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