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