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