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