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