proc->thread stage 2: MAJOR revamping of system calls, ucred, jail API,
[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.3 2003/06/23 17:55:45 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,
107                         int flag, struct thread *));
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_t dev, struct tty *tp)
197 {
198     struct proc *p = curproc;           /* XXX */
199     struct ppp_softc *sc;
200     int error, s;
201
202     if ((error = suser_xxx(p->p_ucred, 0)) != 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(p->p_pid)) == 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     register 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         untimeout(ppp_timeout, (void *) sc, sc->sc_ch);
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 register struct ppp_softc *sc;
320 {
321     register 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     register struct tty *tp;
339     struct uio *uio;
340     int flag;
341 {
342     register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
343     struct mbuf *m, *m0;
344     register 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), TTIPRI | 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     register struct tty *tp;
398     struct uio *uio;
399     int flag;
400 {
401     register 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, M_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, M_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     struct proc *p = td->td_proc;
459     int error, s;
460
461     KKASSERT(p != NULL);
462
463     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
464         return (ENOIOCTL);
465
466     error = 0;
467     switch (cmd) {
468     case PPPIOCSASYNCMAP:
469         if ((error = suser_xxx(p->p_ucred, 0)) != 0)
470             break;
471         sc->sc_asyncmap[0] = *(u_int *)data;
472         break;
473
474     case PPPIOCGASYNCMAP:
475         *(u_int *)data = sc->sc_asyncmap[0];
476         break;
477
478     case PPPIOCSRASYNCMAP:
479         if ((error = suser_xxx(p->p_ucred, 0)) != 0)
480             break;
481         sc->sc_rasyncmap = *(u_int *)data;
482         break;
483
484     case PPPIOCGRASYNCMAP:
485         *(u_int *)data = sc->sc_rasyncmap;
486         break;
487
488     case PPPIOCSXASYNCMAP:
489         if ((error = suser_xxx(p->p_ucred, 0)) != 0)
490             break;
491         s = spltty();
492         bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
493         sc->sc_asyncmap[1] = 0;             /* mustn't escape 0x20 - 0x3f */
494         sc->sc_asyncmap[2] &= ~0x40000000;  /* mustn't escape 0x5e */
495         sc->sc_asyncmap[3] |= 0x60000000;   /* must escape 0x7d, 0x7e */
496         splx(s);
497         break;
498
499     case PPPIOCGXASYNCMAP:
500         bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
501         break;
502
503     default:
504         error = pppioctl(sc, cmd, data, flag, p);
505         if (error == 0 && cmd == PPPIOCSMRU)
506             pppgetm(sc);
507     }
508
509     return error;
510 }
511
512 /*
513  * FCS lookup table as calculated by genfcstab.
514  */
515 static u_short fcstab[256] = {
516         0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
517         0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
518         0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
519         0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
520         0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
521         0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
522         0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
523         0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
524         0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
525         0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
526         0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
527         0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
528         0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
529         0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
530         0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
531         0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
532         0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
533         0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
534         0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
535         0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
536         0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
537         0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
538         0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
539         0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
540         0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
541         0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
542         0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
543         0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
544         0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
545         0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
546         0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
547         0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
548 };
549
550 /*
551  * Calculate a new FCS given the current FCS and the new data.
552  */
553 static u_short
554 pppfcs(u_short fcs, u_char *cp, int len)
555 {
556     while (len--)
557         fcs = PPP_FCS(fcs, *cp++);
558     return (fcs);
559 }
560
561 /*
562  * This gets called at splsoftnet from if_ppp.c at various times
563  * when there is data ready to be sent.
564  */
565 static void
566 pppasyncstart(sc)
567     register struct ppp_softc *sc;
568 {
569     register struct tty *tp = (struct tty *) sc->sc_devp;
570     register struct mbuf *m;
571     register int len;
572     register u_char *start, *stop, *cp;
573     int n, ndone, done, idle;
574     int s;
575
576     idle = 0;
577     /* XXX assumes atomic access to *tp although we're not at spltty(). */
578     while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
579         /*
580          * See if we have an existing packet partly sent.
581          * If not, get a new packet and start sending it.
582          */
583         m = sc->sc_outm;
584         if (m == NULL) {
585             /*
586              * Get another packet to be sent.
587              */
588             m = ppp_dequeue(sc);
589             if (m == NULL) {
590                 idle = 1;
591                 break;
592             }
593
594             /*
595              * The extra PPP_FLAG will start up a new packet, and thus
596              * will flush any accumulated garbage.  We do this whenever
597              * the line may have been idle for some time.
598              */
599             /* XXX as above. */
600             if (CCOUNT(&tp->t_outq) == 0) {
601                 ++sc->sc_stats.ppp_obytes;
602                 (void) putc(PPP_FLAG, &tp->t_outq);
603             }
604
605             /* Calculate the FCS for the first mbuf's worth. */
606             sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
607             getmicrotime(&sc->sc_if.if_lastchange);
608         }
609
610         for (;;) {
611             start = mtod(m, u_char *);
612             len = m->m_len;
613             stop = start + len;
614             while (len > 0) {
615                 /*
616                  * Find out how many bytes in the string we can
617                  * handle without doing something special.
618                  */
619                 for (cp = start; cp < stop; cp++)
620                     if (ESCAPE_P(*cp))
621                         break;
622                 n = cp - start;
623                 if (n) {
624                     /* NetBSD (0.9 or later), 4.3-Reno or similar. */
625                     ndone = n - b_to_q(start, n, &tp->t_outq);
626                     len -= ndone;
627                     start += ndone;
628                     sc->sc_stats.ppp_obytes += ndone;
629
630                     if (ndone < n)
631                         break;  /* packet doesn't fit */
632                 }
633                 /*
634                  * If there are characters left in the mbuf,
635                  * the first one must be special.
636                  * Put it out in a different form.
637                  */
638                 if (len) {
639                     s = spltty();
640                     if (putc(PPP_ESCAPE, &tp->t_outq)) {
641                         splx(s);
642                         break;
643                     }
644                     if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
645                         (void) unputc(&tp->t_outq);
646                         splx(s);
647                         break;
648                     }
649                     splx(s);
650                     sc->sc_stats.ppp_obytes += 2;
651                     start++;
652                     len--;
653                 }
654             }
655
656             /*
657              * If we didn't empty this mbuf, remember where we're up to.
658              * If we emptied the last mbuf, try to add the FCS and closing
659              * flag, and if we can't, leave sc_outm pointing to m, but with
660              * m->m_len == 0, to remind us to output the FCS and flag later.
661              */
662             done = len == 0;
663             if (done && m->m_next == NULL) {
664                 u_char *p, *q;
665                 int c;
666                 u_char endseq[8];
667
668                 /*
669                  * We may have to escape the bytes in the FCS.
670                  */
671                 p = endseq;
672                 c = ~sc->sc_outfcs & 0xFF;
673                 if (ESCAPE_P(c)) {
674                     *p++ = PPP_ESCAPE;
675                     *p++ = c ^ PPP_TRANS;
676                 } else
677                     *p++ = c;
678                 c = (~sc->sc_outfcs >> 8) & 0xFF;
679                 if (ESCAPE_P(c)) {
680                     *p++ = PPP_ESCAPE;
681                     *p++ = c ^ PPP_TRANS;
682                 } else
683                     *p++ = c;
684                 *p++ = PPP_FLAG;
685
686                 /*
687                  * Try to output the FCS and flag.  If the bytes
688                  * don't all fit, back out.
689                  */
690                 s = spltty();
691                 for (q = endseq; q < p; ++q)
692                     if (putc(*q, &tp->t_outq)) {
693                         done = 0;
694                         for (; q > endseq; --q)
695                             unputc(&tp->t_outq);
696                         break;
697                     }
698                 splx(s);
699                 if (done)
700                     sc->sc_stats.ppp_obytes += q - endseq;
701             }
702
703             if (!done) {
704                 /* remember where we got to */
705                 m->m_data = start;
706                 m->m_len = len;
707                 break;
708             }
709
710             /* Finished with this mbuf; free it and move on. */
711             m = m_free(m);
712             if (m == NULL) {
713                 /* Finished a packet */
714                 break;
715             }
716             sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
717         }
718
719         /*
720          * If m == NULL, we have finished a packet.
721          * If m != NULL, we've either done as much work this time
722          * as we need to, or else we've filled up the output queue.
723          */
724         sc->sc_outm = m;
725         if (m)
726             break;
727     }
728
729     /* Call pppstart to start output again if necessary. */
730     s = spltty();
731     pppstart(tp);
732
733     /*
734      * This timeout is needed for operation on a pseudo-tty,
735      * because the pty code doesn't call pppstart after it has
736      * drained the t_outq.
737      */
738     if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
739         sc->sc_ch = timeout(ppp_timeout, (void *) sc, 1);
740         sc->sc_flags |= SC_TIMEOUT;
741     }
742
743     splx(s);
744 }
745
746 /*
747  * This gets called when a received packet is placed on
748  * the inq, at splsoftnet. The pppd daemon is to be woken up to do a read().
749  */
750 static void
751 pppasyncctlp(sc)
752     struct ppp_softc *sc;
753 {
754     struct tty *tp;
755     int s;
756
757     /* Put a placeholder byte in canq for ttselect()/ttnread(). */
758     s = spltty();
759     tp = (struct tty *) sc->sc_devp;
760     putc(0, &tp->t_canq);
761     ttwakeup(tp);
762     splx(s);
763 }
764
765 /*
766  * Start output on async tty interface.  If the transmit queue
767  * has drained sufficiently, arrange for pppasyncstart to be
768  * called later at splsoftnet.
769  * Called at spltty or higher.
770  */
771 int
772 pppstart(tp)
773     register struct tty *tp;
774 {
775     register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
776
777     /*
778      * Call output process whether or not there is any output.
779      * We are being called in lieu of ttstart and must do what it would.
780      */
781     if (tp->t_oproc != NULL)
782         (*tp->t_oproc)(tp);
783
784     /*
785      * If the transmit queue has drained and the tty has not hung up
786      * or been disconnected from the ppp unit, then tell if_ppp.c that
787      * we need more output.
788      */
789     if (CCOUNT(&tp->t_outq) < PPP_LOWAT
790         && !((tp->t_state & TS_CONNECTED) == 0)
791         && sc != NULL && tp == (struct tty *) sc->sc_devp) {
792         ppp_restart(sc);
793     }
794
795     return 0;
796 }
797
798 /*
799  * Timeout routine - try to start some more output.
800  */
801 static void
802 ppp_timeout(x)
803     void *x;
804 {
805     struct ppp_softc *sc = (struct ppp_softc *) x;
806     struct tty *tp = (struct tty *) sc->sc_devp;
807     int s;
808
809     s = spltty();
810     sc->sc_flags &= ~SC_TIMEOUT;
811     pppstart(tp);
812     splx(s);
813 }
814
815 /*
816  * Allocate enough mbuf to handle current MRU.
817  */
818 static void
819 pppgetm(sc)
820     register struct ppp_softc *sc;
821 {
822     struct mbuf *m, **mp;
823     int len;
824
825     mp = &sc->sc_m;
826     for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
827         if ((m = *mp) == NULL) {
828             MGETHDR(m, M_DONTWAIT, MT_DATA);
829             if (m == NULL)
830                 break;
831             *mp = m;
832             MCLGET(m, M_DONTWAIT);
833         }
834         len -= M_DATASIZE(m);
835         mp = &m->m_next;
836     }
837 }
838
839 /*
840  * tty interface receiver interrupt.
841  */
842 static unsigned paritytab[8] = {
843     0x96696996, 0x69969669, 0x69969669, 0x96696996,
844     0x69969669, 0x96696996, 0x96696996, 0x69969669
845 };
846
847 /*
848  * Called when character is available from device driver.
849  * Only guaranteed to be at splsofttty() or spltty()
850  * This is safe to be called while the upper half's netisr is preempted.
851  */
852 static int
853 pppinput(c, tp)
854     int c;
855     register struct tty *tp;
856 {
857     register struct ppp_softc *sc;
858     struct mbuf *m;
859     int ilen, s;
860
861     sc = (struct ppp_softc *) tp->t_sc;
862     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
863         return 0;
864
865     ++tk_nin;
866     ++sc->sc_stats.ppp_ibytes;
867
868     if ((tp->t_state & TS_CONNECTED) == 0) {
869         if (sc->sc_flags & SC_DEBUG)
870             printf("ppp%d: no carrier\n", sc->sc_if.if_unit);
871         goto flush;
872     }
873
874     if (c & TTY_ERRORMASK) {
875         /* framing error or overrun on this char - abort packet */
876         if (sc->sc_flags & SC_DEBUG)
877             printf("ppp%d: line error %x\n", sc->sc_if.if_unit,
878                                                 c & TTY_ERRORMASK);
879         goto flush;
880     }
881
882     c &= TTY_CHARMASK;
883
884     /*
885      * Handle software flow control of output.
886      */
887     if (tp->t_iflag & IXON) {
888         if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
889             if ((tp->t_state & TS_TTSTOP) == 0) {
890                 tp->t_state |= TS_TTSTOP;
891                 tp->t_stop(tp, 0);
892             }
893             return 0;
894         }
895         if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
896             tp->t_state &= ~TS_TTSTOP;
897             if (tp->t_oproc != NULL)
898                 (*tp->t_oproc)(tp);
899             return 0;
900         }
901     }
902
903     s = spltty();
904     if (c & 0x80)
905         sc->sc_flags |= SC_RCV_B7_1;
906     else
907         sc->sc_flags |= SC_RCV_B7_0;
908     if (paritytab[c >> 5] & (1 << (c & 0x1F)))
909         sc->sc_flags |= SC_RCV_ODDP;
910     else
911         sc->sc_flags |= SC_RCV_EVNP;
912     splx(s);
913
914     if (sc->sc_flags & SC_LOG_RAWIN)
915         ppplogchar(sc, c);
916
917     if (c == PPP_FLAG) {
918         ilen = sc->sc_ilen;
919         sc->sc_ilen = 0;
920
921         if (sc->sc_rawin_count > 0) 
922             ppplogchar(sc, -1);
923
924         /*
925          * If SC_ESCAPED is set, then we've seen the packet
926          * abort sequence "}~".
927          */
928         if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
929             || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
930             s = spltty();
931             sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
932             if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
933                 if (sc->sc_flags & SC_DEBUG)
934                     printf("ppp%d: bad fcs %x, pkt len %d\n",
935                            sc->sc_if.if_unit, sc->sc_fcs, ilen);
936                 sc->sc_if.if_ierrors++;
937                 sc->sc_stats.ppp_ierrors++;
938             } else
939                 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
940             splx(s);
941             return 0;
942         }
943
944         if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
945             if (ilen) {
946                 if (sc->sc_flags & SC_DEBUG)
947                     printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
948                 s = spltty();
949                 sc->sc_if.if_ierrors++;
950                 sc->sc_stats.ppp_ierrors++;
951                 sc->sc_flags |= SC_PKTLOST;
952                 splx(s);
953             }
954             return 0;
955         }
956
957         /*
958          * Remove FCS trailer.  Somewhat painful...
959          */
960         ilen -= 2;
961         if (--sc->sc_mc->m_len == 0) {
962             for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
963                 ;
964             sc->sc_mc = m;
965         }
966         sc->sc_mc->m_len--;
967
968         /* excise this mbuf chain */
969         m = sc->sc_m;
970         sc->sc_m = sc->sc_mc->m_next;
971         sc->sc_mc->m_next = NULL;
972
973         ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
974         if (sc->sc_flags & SC_PKTLOST) {
975             s = spltty();
976             sc->sc_flags &= ~SC_PKTLOST;
977             splx(s);
978         }
979
980         pppgetm(sc);
981         return 0;
982     }
983
984     if (sc->sc_flags & SC_FLUSH) {
985         if (sc->sc_flags & SC_LOG_FLUSH)
986             ppplogchar(sc, c);
987         return 0;
988     }
989
990     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
991         return 0;
992
993     s = spltty();
994     if (sc->sc_flags & SC_ESCAPED) {
995         sc->sc_flags &= ~SC_ESCAPED;
996         c ^= PPP_TRANS;
997     } else if (c == PPP_ESCAPE) {
998         sc->sc_flags |= SC_ESCAPED;
999         splx(s);
1000         return 0;
1001     }
1002     splx(s);
1003
1004     /*
1005      * Initialize buffer on first octet received.
1006      * First octet could be address or protocol (when compressing
1007      * address/control).
1008      * Second octet is control.
1009      * Third octet is first or second (when compressing protocol)
1010      * octet of protocol.
1011      * Fourth octet is second octet of protocol.
1012      */
1013     if (sc->sc_ilen == 0) {
1014         /* reset the first input mbuf */
1015         if (sc->sc_m == NULL) {
1016             pppgetm(sc);
1017             if (sc->sc_m == NULL) {
1018                 if (sc->sc_flags & SC_DEBUG)
1019                     printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
1020                 goto flush;
1021             }
1022         }
1023         m = sc->sc_m;
1024         m->m_len = 0;
1025         m->m_data = M_DATASTART(sc->sc_m);
1026         sc->sc_mc = m;
1027         sc->sc_mp = mtod(m, char *);
1028         sc->sc_fcs = PPP_INITFCS;
1029         if (c != PPP_ALLSTATIONS) {
1030             if (sc->sc_flags & SC_REJ_COMP_AC) {
1031                 if (sc->sc_flags & SC_DEBUG)
1032                     printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
1033                            sc->sc_if.if_unit, c);
1034                 goto flush;
1035             }
1036             *sc->sc_mp++ = PPP_ALLSTATIONS;
1037             *sc->sc_mp++ = PPP_UI;
1038             sc->sc_ilen += 2;
1039             m->m_len += 2;
1040         }
1041     }
1042     if (sc->sc_ilen == 1 && c != PPP_UI) {
1043         if (sc->sc_flags & SC_DEBUG)
1044             printf("ppp%d: missing UI (0x3), got 0x%x\n",
1045                    sc->sc_if.if_unit, c);
1046         goto flush;
1047     }
1048     if (sc->sc_ilen == 2 && (c & 1) == 1) {
1049         /* a compressed protocol */
1050         *sc->sc_mp++ = 0;
1051         sc->sc_ilen++;
1052         sc->sc_mc->m_len++;
1053     }
1054     if (sc->sc_ilen == 3 && (c & 1) == 0) {
1055         if (sc->sc_flags & SC_DEBUG)
1056             printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
1057                    (sc->sc_mp[-1] << 8) + c);
1058         goto flush;
1059     }
1060
1061     /* packet beyond configured mru? */
1062     if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1063         if (sc->sc_flags & SC_DEBUG)
1064             printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
1065         goto flush;
1066     }
1067
1068     /* is this mbuf full? */
1069     m = sc->sc_mc;
1070     if (M_TRAILINGSPACE(m) <= 0) {
1071         if (m->m_next == NULL) {
1072             pppgetm(sc);
1073             if (m->m_next == NULL) {
1074                 if (sc->sc_flags & SC_DEBUG)
1075                     printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
1076                 goto flush;
1077             }
1078         }
1079         sc->sc_mc = m = m->m_next;
1080         m->m_len = 0;
1081         m->m_data = M_DATASTART(m);
1082         sc->sc_mp = mtod(m, char *);
1083     }
1084
1085     ++m->m_len;
1086     *sc->sc_mp++ = c;
1087     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1088     return 0;
1089
1090  flush:
1091     if (!(sc->sc_flags & SC_FLUSH)) {
1092         s = spltty();
1093         sc->sc_if.if_ierrors++;
1094         sc->sc_stats.ppp_ierrors++;
1095         sc->sc_flags |= SC_FLUSH;
1096         splx(s);
1097         if (sc->sc_flags & SC_LOG_FLUSH)
1098             ppplogchar(sc, c);
1099     }
1100     return 0;
1101 }
1102
1103 #define MAX_DUMP_BYTES  128
1104
1105 static void
1106 ppplogchar(sc, c)
1107     struct ppp_softc *sc;
1108     int c;
1109 {
1110     if (c >= 0)
1111         sc->sc_rawin[sc->sc_rawin_count++] = c;
1112     if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1113         || (c < 0 && sc->sc_rawin_count > 0)) {
1114         printf("ppp%d input: %*D", sc->sc_if.if_unit,
1115                 sc->sc_rawin_count, sc->sc_rawin, " ");
1116         sc->sc_rawin_count = 0;
1117     }
1118 }