Merge from vendor branch NCURSES:
[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.12 2005/02/11 22:25:57 joerg 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 #include <net/if.h>
97 #include <net/ifq_var.h>
98
99 #ifdef PPP_FILTER
100 #include <net/bpf.h>
101 #endif
102 #include <net/ppp/if_ppp.h>
103 #include <net/ppp/if_pppvar.h>
104
105 static int      pppopen (dev_t dev, struct tty *tp);
106 static int      pppclose (struct tty *tp, int flag);
107 static int      pppread (struct tty *tp, struct uio *uio, int flag);
108 static int      pppwrite (struct tty *tp, struct uio *uio, int flag);
109 static int      ppptioctl (struct tty *tp, u_long cmd, caddr_t data,
110                         int flag, struct thread *);
111 static int      pppinput (int c, struct tty *tp);
112 static int      pppstart (struct tty *tp);
113
114 static u_short  pppfcs (u_short fcs, u_char *cp, int len);
115 static void     pppasyncstart (struct ppp_softc *);
116 static void     pppasyncctlp (struct ppp_softc *);
117 static void     pppasyncrelinq (struct ppp_softc *);
118 static void     pppasyncsetmtu (struct ppp_softc *);
119 static void     ppp_timeout (void *);
120 static void     pppgetm (struct ppp_softc *sc);
121 static void     ppplogchar (struct ppp_softc *, int);
122
123 /* XXX called from if_ppp.c - layering violation */
124 void            pppasyncattach (void *);
125
126 /*
127  * Some useful mbuf macros not in mbuf.h.
128  */
129 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
130
131 #define M_DATASTART(m)  \
132         (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
133             (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
134
135 #define M_DATASIZE(m)   \
136         (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
137             (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
138
139 /*
140  * Does c need to be escaped?
141  */
142 #define ESCAPE_P(c)     (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
143
144 /*
145  * Procedures for using an async tty interface for PPP.
146  */
147
148 /* This is a FreeBSD-2.X kernel. */
149 #define CCOUNT(q)       ((q)->c_cc)
150 #define PPP_LOWAT       100     /* Process more output when < LOWAT on queue */
151 #define PPP_HIWAT       400     /* Don't start a new packet if HIWAT on que */
152
153 /*
154  * Define the PPP line discipline.
155  */
156
157 static struct linesw pppdisc = {
158         pppopen,        pppclose,       pppread,        pppwrite,
159         ppptioctl,      pppinput,       pppstart,       ttymodem,
160         PPP_FLAG
161 };
162
163 void
164 pppasyncattach(dummy)
165     void *dummy;
166 {
167 #ifdef __i386__
168     int s;
169
170     s = splhigh();
171
172     /*
173      * Make sure that the soft net "engine" cannot run while spltty code is
174      * active.  The if_ppp.c code can walk down into b_to_q etc, and it is
175      * bad if the tty system was in the middle of another b_to_q...
176      */
177     tty_imask |= softnet_imask; /* spltty() block spl[soft]net() */
178     net_imask |= softtty_imask; /* splimp() block splsofttty() */
179     net_imask |= tty_imask;     /* splimp() block spltty() */
180     update_intr_masks();
181
182     splx(s);
183     if ( bootverbose )
184         printf("new masks: bio %x, tty %x, net %x\n",
185                 bio_imask, tty_imask, net_imask);
186 #endif
187
188     /* register line discipline */
189     linesw[PPPDISC] = pppdisc;
190 }
191
192 /*
193  * Line specific open routine for async tty devices.
194  * Attach the given tty to the first available ppp unit.
195  * Called from device open routine or ttioctl() at >= splsofttty()
196  */
197 /* ARGSUSED */
198 static int
199 pppopen(dev_t dev, struct tty *tp)
200 {
201     struct thread *td = curthread;      /* XXX */
202     struct ppp_softc *sc;
203     int error, s;
204
205     if ((error = suser(td)) != 0)
206         return (error);
207
208     s = spltty();
209
210     if (tp->t_line == PPPDISC) {
211         sc = (struct ppp_softc *) tp->t_sc;
212         if (sc != NULL && sc->sc_devp == (void *) tp) {
213             splx(s);
214             return (0);
215         }
216     }
217
218     if ((sc = pppalloc(td)) == NULL) {
219         splx(s);
220         return ENXIO;
221     }
222
223     if (sc->sc_relinq)
224         (*sc->sc_relinq)(sc);   /* get previous owner to relinquish the unit */
225
226     sc->sc_ilen = 0;
227     sc->sc_m = NULL;
228     bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
229     sc->sc_asyncmap[0] = 0xffffffff;
230     sc->sc_asyncmap[3] = 0x60000000;
231     sc->sc_rasyncmap = 0;
232     sc->sc_devp = (void *) tp;
233     sc->sc_start = pppasyncstart;
234     sc->sc_ctlp = pppasyncctlp;
235     sc->sc_relinq = pppasyncrelinq;
236     sc->sc_setmtu = pppasyncsetmtu;
237     sc->sc_outm = NULL;
238     pppgetm(sc);
239     sc->sc_if.if_flags |= IFF_RUNNING;
240     getmicrotime(&sc->sc_if.if_lastchange);
241     sc->sc_if.if_baudrate = tp->t_ospeed;
242
243     tp->t_sc = (caddr_t) sc;
244     ttyflush(tp, FREAD | FWRITE);
245
246     /*
247      * Pre-allocate cblocks to the "just right" amount.  The 1 byte t_canq
248      * allocation helps avoid the need for select and/or FIONREAD.
249      * We also pass 1 byte tokens through t_canq...
250      */
251     clist_alloc_cblocks(&tp->t_canq, 1, 1);
252     clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
253                         sc->sc_if.if_mtu + PPP_HIWAT);
254     clist_alloc_cblocks(&tp->t_rawq, 0, 0);
255
256     splx(s);
257
258     return (0);
259 }
260
261 /*
262  * Line specific close routine, called from device close routine
263  * and from ttioctl at >= splsofttty().
264  * Detach the tty from the ppp unit.
265  * Mimics part of ttyclose().
266  */
267 static int
268 pppclose(tp, flag)
269     struct tty *tp;
270     int flag;
271 {
272     struct ppp_softc *sc;
273     int s;
274
275     s = spltty();
276     ttyflush(tp, FREAD | FWRITE);
277     clist_free_cblocks(&tp->t_canq);
278     clist_free_cblocks(&tp->t_outq);
279     tp->t_line = 0;
280     sc = (struct ppp_softc *) tp->t_sc;
281     if (sc != NULL) {
282         tp->t_sc = NULL;
283         if (tp == (struct tty *) sc->sc_devp) {
284             pppasyncrelinq(sc);
285             pppdealloc(sc);
286         }
287     }
288     splx(s);
289     return 0;
290 }
291
292 /*
293  * Relinquish the interface unit to another device.
294  */
295 static void
296 pppasyncrelinq(sc)
297     struct ppp_softc *sc;
298 {
299     int s;
300
301     s = spltty();
302     if (sc->sc_outm) {
303         m_freem(sc->sc_outm);
304         sc->sc_outm = NULL;
305     }
306     if (sc->sc_m) {
307         m_freem(sc->sc_m);
308         sc->sc_m = NULL;
309     }
310     if (sc->sc_flags & SC_TIMEOUT) {
311         callout_stop(&sc->sc_timeout);
312         sc->sc_flags &= ~SC_TIMEOUT;
313     }
314     splx(s);
315 }
316
317 /*
318  * This gets called from the upper layer to notify a mtu change
319  */
320 static void
321 pppasyncsetmtu(sc)
322 struct ppp_softc *sc;
323 {
324     struct tty *tp = (struct tty *) sc->sc_devp;
325     int s;
326
327     s = spltty();
328     if (tp != NULL)
329         clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
330                              sc->sc_if.if_mtu + PPP_HIWAT);
331     splx(s);
332 }
333
334 /*
335  * Line specific (tty) read routine.
336  * called at zero spl from the device driver in the response to user-level
337  * reads on the tty file descriptor (ie: pppd).
338  */
339 static int
340 pppread(tp, uio, flag)
341     struct tty *tp;
342     struct uio *uio;
343     int flag;
344 {
345     struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
346     struct mbuf *m, *m0;
347     int s;
348     int error = 0;
349
350     if (sc == NULL)
351         return 0;
352     /*
353      * Loop waiting for input, checking that nothing disasterous
354      * happens in the meantime.
355      */
356     s = spltty();
357     for (;;) {
358         if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
359             splx(s);
360             return 0;
361         }
362         if (sc->sc_inq.ifq_head != NULL)
363             break;
364         if ((tp->t_state & TS_CONNECTED) == 0) {
365             splx(s);
366             return 0;           /* end of file */
367         }
368         if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
369             splx(s);
370             return (EWOULDBLOCK);
371         }
372         error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), PCATCH, "pppin", 0);
373         if (error) {
374             splx(s);
375             return error;
376         }
377     }
378
379     /* Pull place-holder byte out of canonical queue */
380     getc(&tp->t_canq);
381
382     /* Get the packet from the input queue */
383     IF_DEQUEUE(&sc->sc_inq, m0);
384     splx(s);
385
386     for (m = m0; m && uio->uio_resid; m = m->m_next)
387         if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
388             break;
389     m_freem(m0);
390     return (error);
391 }
392
393 /*
394  * Line specific (tty) write routine.
395  * called at zero spl from the device driver in the response to user-level
396  * writes on the tty file descriptor (ie: pppd).
397  */
398 static int
399 pppwrite(tp, uio, flag)
400     struct tty *tp;
401     struct uio *uio;
402     int flag;
403 {
404     struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
405     struct mbuf *m, *m0, **mp;
406     struct sockaddr dst;
407     int len, error, s;
408
409     if ((tp->t_state & TS_CONNECTED) == 0)
410         return 0;               /* wrote 0 bytes */
411     if (tp->t_line != PPPDISC)
412         return (EINVAL);
413     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
414         return EIO;
415     if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
416         uio->uio_resid < PPP_HDRLEN)
417         return (EMSGSIZE);
418
419     s = spltty();
420     for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
421         MGET(m, MB_WAIT, MT_DATA);
422         if ((*mp = m) == NULL) {
423             m_freem(m0);
424             splx(s);
425             return (ENOBUFS);
426         }
427         m->m_len = 0;
428         if (uio->uio_resid >= MCLBYTES / 2)
429             MCLGET(m, MB_DONTWAIT);
430         len = M_TRAILINGSPACE(m);
431         if (len > uio->uio_resid)
432             len = uio->uio_resid;
433         if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
434             m_freem(m0);
435             splx(s);
436             return (error);
437         }
438         m->m_len = len;
439     }
440     dst.sa_family = AF_UNSPEC;
441     bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
442     m0->m_data += PPP_HDRLEN;
443     m0->m_len -= PPP_HDRLEN;
444
445     /* call the upper layer to "transmit" it... */
446     error = pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0);
447     splx(s);
448     return (error);
449 }
450
451 /*
452  * Line specific (tty) ioctl routine.
453  * This discipline requires that tty device drivers call
454  * the line specific l_ioctl routine from their ioctl routines.
455  */
456 /* ARGSUSED */
457 static int
458 ppptioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct thread *td)
459 {
460     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
461     int error, s;
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(td)) != 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(td)) != 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(td)) != 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, td);
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     struct ppp_softc *sc;
568 {
569     struct tty *tp = (struct tty *) sc->sc_devp;
570     struct mbuf *m;
571     int len;
572     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         callout_reset(&sc->sc_timeout, 1, ppp_timeout, sc);
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     struct tty *tp;
774 {
775     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 ALTQ is enabled, don't invoke NETISR_PPP.
786      * pppintr() could loop without doing anything useful
787      * under rate-limiting.
788      */
789     if (ifq_is_enabled(&sc->sc_if.if_snd))
790         return 0;
791
792     /*
793      * If the transmit queue has drained and the tty has not hung up
794      * or been disconnected from the ppp unit, then tell if_ppp.c that
795      * we need more output.
796      */
797     if (CCOUNT(&tp->t_outq) < PPP_LOWAT
798         && !((tp->t_state & TS_CONNECTED) == 0)
799         && sc != NULL && tp == (struct tty *) sc->sc_devp) {
800         ppp_restart(sc);
801     }
802
803     return 0;
804 }
805
806 /*
807  * Timeout routine - try to start some more output.
808  */
809 static void
810 ppp_timeout(x)
811     void *x;
812 {
813     struct ppp_softc *sc = (struct ppp_softc *) x;
814     struct tty *tp = (struct tty *) sc->sc_devp;
815     int s;
816
817     s = spltty();
818     sc->sc_flags &= ~SC_TIMEOUT;
819     pppstart(tp);
820     splx(s);
821 }
822
823 /*
824  * Allocate enough mbuf to handle current MRU.
825  */
826 static void
827 pppgetm(sc)
828     struct ppp_softc *sc;
829 {
830     struct mbuf *m, **mp;
831     int len;
832
833     mp = &sc->sc_m;
834     for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
835         if ((m = *mp) == NULL) {
836             MGETHDR(m, MB_DONTWAIT, MT_DATA);
837             if (m == NULL)
838                 break;
839             *mp = m;
840             MCLGET(m, MB_DONTWAIT);
841         }
842         len -= M_DATASIZE(m);
843         mp = &m->m_next;
844     }
845 }
846
847 /*
848  * tty interface receiver interrupt.
849  */
850 static unsigned paritytab[8] = {
851     0x96696996, 0x69969669, 0x69969669, 0x96696996,
852     0x69969669, 0x96696996, 0x96696996, 0x69969669
853 };
854
855 /*
856  * Called when character is available from device driver.
857  * Only guaranteed to be at splsofttty() or spltty()
858  * This is safe to be called while the upper half's netisr is preempted.
859  */
860 static int
861 pppinput(c, tp)
862     int c;
863     struct tty *tp;
864 {
865     struct ppp_softc *sc;
866     struct mbuf *m;
867     int ilen, s;
868
869     sc = (struct ppp_softc *) tp->t_sc;
870     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
871         return 0;
872
873     ++tk_nin;
874     ++sc->sc_stats.ppp_ibytes;
875
876     if ((tp->t_state & TS_CONNECTED) == 0) {
877         if (sc->sc_flags & SC_DEBUG)
878             printf("%s: no carrier\n", sc->sc_if.if_xname);
879         goto flush;
880     }
881
882     if (c & TTY_ERRORMASK) {
883         /* framing error or overrun on this char - abort packet */
884         if (sc->sc_flags & SC_DEBUG)
885             printf("%s: line error %x\n", sc->sc_if.if_xname,
886                                                 c & TTY_ERRORMASK);
887         goto flush;
888     }
889
890     c &= TTY_CHARMASK;
891
892     /*
893      * Handle software flow control of output.
894      */
895     if (tp->t_iflag & IXON) {
896         if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
897             if ((tp->t_state & TS_TTSTOP) == 0) {
898                 tp->t_state |= TS_TTSTOP;
899                 tp->t_stop(tp, 0);
900             }
901             return 0;
902         }
903         if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
904             tp->t_state &= ~TS_TTSTOP;
905             if (tp->t_oproc != NULL)
906                 (*tp->t_oproc)(tp);
907             return 0;
908         }
909     }
910
911     s = spltty();
912     if (c & 0x80)
913         sc->sc_flags |= SC_RCV_B7_1;
914     else
915         sc->sc_flags |= SC_RCV_B7_0;
916     if (paritytab[c >> 5] & (1 << (c & 0x1F)))
917         sc->sc_flags |= SC_RCV_ODDP;
918     else
919         sc->sc_flags |= SC_RCV_EVNP;
920     splx(s);
921
922     if (sc->sc_flags & SC_LOG_RAWIN)
923         ppplogchar(sc, c);
924
925     if (c == PPP_FLAG) {
926         ilen = sc->sc_ilen;
927         sc->sc_ilen = 0;
928
929         if (sc->sc_rawin_count > 0) 
930             ppplogchar(sc, -1);
931
932         /*
933          * If SC_ESCAPED is set, then we've seen the packet
934          * abort sequence "}~".
935          */
936         if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
937             || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
938             s = spltty();
939             sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
940             if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
941                 if (sc->sc_flags & SC_DEBUG)
942                     printf("%s: bad fcs %x, pkt len %d\n",
943                            sc->sc_if.if_xname, sc->sc_fcs, ilen);
944                 sc->sc_if.if_ierrors++;
945                 sc->sc_stats.ppp_ierrors++;
946             } else
947                 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
948             splx(s);
949             return 0;
950         }
951
952         if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
953             if (ilen) {
954                 if (sc->sc_flags & SC_DEBUG)
955                     printf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen);
956                 s = spltty();
957                 sc->sc_if.if_ierrors++;
958                 sc->sc_stats.ppp_ierrors++;
959                 sc->sc_flags |= SC_PKTLOST;
960                 splx(s);
961             }
962             return 0;
963         }
964
965         /*
966          * Remove FCS trailer.  Somewhat painful...
967          */
968         ilen -= 2;
969         if (--sc->sc_mc->m_len == 0) {
970             for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
971                 ;
972             sc->sc_mc = m;
973         }
974         sc->sc_mc->m_len--;
975
976         /* excise this mbuf chain */
977         m = sc->sc_m;
978         sc->sc_m = sc->sc_mc->m_next;
979         sc->sc_mc->m_next = NULL;
980
981         ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
982         if (sc->sc_flags & SC_PKTLOST) {
983             s = spltty();
984             sc->sc_flags &= ~SC_PKTLOST;
985             splx(s);
986         }
987
988         pppgetm(sc);
989         return 0;
990     }
991
992     if (sc->sc_flags & SC_FLUSH) {
993         if (sc->sc_flags & SC_LOG_FLUSH)
994             ppplogchar(sc, c);
995         return 0;
996     }
997
998     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
999         return 0;
1000
1001     s = spltty();
1002     if (sc->sc_flags & SC_ESCAPED) {
1003         sc->sc_flags &= ~SC_ESCAPED;
1004         c ^= PPP_TRANS;
1005     } else if (c == PPP_ESCAPE) {
1006         sc->sc_flags |= SC_ESCAPED;
1007         splx(s);
1008         return 0;
1009     }
1010     splx(s);
1011
1012     /*
1013      * Initialize buffer on first octet received.
1014      * First octet could be address or protocol (when compressing
1015      * address/control).
1016      * Second octet is control.
1017      * Third octet is first or second (when compressing protocol)
1018      * octet of protocol.
1019      * Fourth octet is second octet of protocol.
1020      */
1021     if (sc->sc_ilen == 0) {
1022         /* reset the first input mbuf */
1023         if (sc->sc_m == NULL) {
1024             pppgetm(sc);
1025             if (sc->sc_m == NULL) {
1026                 if (sc->sc_flags & SC_DEBUG)
1027                     printf("%s: no input mbufs!\n", sc->sc_if.if_xname);
1028                 goto flush;
1029             }
1030         }
1031         m = sc->sc_m;
1032         m->m_len = 0;
1033         m->m_data = M_DATASTART(sc->sc_m);
1034         sc->sc_mc = m;
1035         sc->sc_mp = mtod(m, char *);
1036         sc->sc_fcs = PPP_INITFCS;
1037         if (c != PPP_ALLSTATIONS) {
1038             if (sc->sc_flags & SC_REJ_COMP_AC) {
1039                 if (sc->sc_flags & SC_DEBUG)
1040                     printf("%s: garbage received: 0x%x (need 0xFF)\n",
1041                            sc->sc_if.if_xname, c);
1042                 goto flush;
1043             }
1044             *sc->sc_mp++ = PPP_ALLSTATIONS;
1045             *sc->sc_mp++ = PPP_UI;
1046             sc->sc_ilen += 2;
1047             m->m_len += 2;
1048         }
1049     }
1050     if (sc->sc_ilen == 1 && c != PPP_UI) {
1051         if (sc->sc_flags & SC_DEBUG)
1052             printf("%s: missing UI (0x3), got 0x%x\n",
1053                    sc->sc_if.if_xname, c);
1054         goto flush;
1055     }
1056     if (sc->sc_ilen == 2 && (c & 1) == 1) {
1057         /* a compressed protocol */
1058         *sc->sc_mp++ = 0;
1059         sc->sc_ilen++;
1060         sc->sc_mc->m_len++;
1061     }
1062     if (sc->sc_ilen == 3 && (c & 1) == 0) {
1063         if (sc->sc_flags & SC_DEBUG)
1064             printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
1065                    (sc->sc_mp[-1] << 8) + c);
1066         goto flush;
1067     }
1068
1069     /* packet beyond configured mru? */
1070     if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1071         if (sc->sc_flags & SC_DEBUG)
1072             printf("%s: packet too big\n", sc->sc_if.if_xname);
1073         goto flush;
1074     }
1075
1076     /* is this mbuf full? */
1077     m = sc->sc_mc;
1078     if (M_TRAILINGSPACE(m) <= 0) {
1079         if (m->m_next == NULL) {
1080             pppgetm(sc);
1081             if (m->m_next == NULL) {
1082                 if (sc->sc_flags & SC_DEBUG)
1083                     printf("%s: too few input mbufs!\n", sc->sc_if.if_xname);
1084                 goto flush;
1085             }
1086         }
1087         sc->sc_mc = m = m->m_next;
1088         m->m_len = 0;
1089         m->m_data = M_DATASTART(m);
1090         sc->sc_mp = mtod(m, char *);
1091     }
1092
1093     ++m->m_len;
1094     *sc->sc_mp++ = c;
1095     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1096     return 0;
1097
1098  flush:
1099     if (!(sc->sc_flags & SC_FLUSH)) {
1100         s = spltty();
1101         sc->sc_if.if_ierrors++;
1102         sc->sc_stats.ppp_ierrors++;
1103         sc->sc_flags |= SC_FLUSH;
1104         splx(s);
1105         if (sc->sc_flags & SC_LOG_FLUSH)
1106             ppplogchar(sc, c);
1107     }
1108     return 0;
1109 }
1110
1111 #define MAX_DUMP_BYTES  128
1112
1113 static void
1114 ppplogchar(sc, c)
1115     struct ppp_softc *sc;
1116     int c;
1117 {
1118     if (c >= 0)
1119         sc->sc_rawin[sc->sc_rawin_count++] = c;
1120     if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1121         || (c < 0 && sc->sc_rawin_count > 0)) {
1122         printf("%s input: %*D", sc->sc_if.if_xname,
1123                 sc->sc_rawin_count, sc->sc_rawin, " ");
1124         sc->sc_rawin_count = 0;
1125     }
1126 }