xref: /netbsd-src/sys/net/ppp_tty.c (revision 5e4c038a45edbc7d63b7c2daa76e29f88b64a4e3)
1 /*	$NetBSD: ppp_tty.c,v 1.30 2002/03/17 19:41:11 atatat Exp $	*/
2 /*	Id: ppp_tty.c,v 1.3 1996/07/01 01:04:11 paulus Exp 	*/
3 
4 /*
5  * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous
6  * 	       tty devices.
7  *
8  * Copyright (c) 1989 Carnegie Mellon University.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms are permitted
12  * provided that the above copyright notice and this paragraph are
13  * duplicated in all such forms and that any documentation,
14  * advertising materials, and other materials related to such
15  * distribution and use acknowledge that the software was developed
16  * by Carnegie Mellon University.  The name of the
17  * University may not be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
21  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22  *
23  * Drew D. Perkins
24  * Carnegie Mellon University
25  * 4910 Forbes Ave.
26  * Pittsburgh, PA 15213
27  * (412) 268-8576
28  * ddp@andrew.cmu.edu
29  *
30  * Based on:
31  *	@(#)if_sl.c	7.6.1.2 (Berkeley) 2/15/89
32  *
33  * Copyright (c) 1987 Regents of the University of California.
34  * All rights reserved.
35  *
36  * Redistribution and use in source and binary forms are permitted
37  * provided that the above copyright notice and this paragraph are
38  * duplicated in all such forms and that any documentation,
39  * advertising materials, and other materials related to such
40  * distribution and use acknowledge that the software was developed
41  * by the University of California, Berkeley.  The name of the
42  * University may not be used to endorse or promote products derived
43  * from this software without specific prior written permission.
44  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
45  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
46  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
47  *
48  * Serial Line interface
49  *
50  * Rick Adams
51  * Center for Seismic Studies
52  * 1300 N 17th Street, Suite 1450
53  * Arlington, Virginia 22209
54  * (703)276-7900
55  * rick@seismo.ARPA
56  * seismo!rick
57  *
58  * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
59  * Converted to 4.3BSD Beta by Chris Torek.
60  * Other changes made at Berkeley, based in part on code by Kirk Smith.
61  *
62  * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
63  * Added VJ tcp header compression; more unified ioctls
64  *
65  * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
66  * Cleaned up a lot of the mbuf-related code to fix bugs that
67  * caused system crashes and packet corruption.  Changed pppstart
68  * so that it doesn't just give up with a "collision" if the whole
69  * packet doesn't fit in the output ring buffer.
70  *
71  * Added priority queueing for interactive IP packets, following
72  * the model of if_sl.c, plus hooks for bpf.
73  * Paul Mackerras (paulus@cs.anu.edu.au).
74  */
75 
76 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
77 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
78 
79 #include <sys/cdefs.h>
80 __KERNEL_RCSID(0, "$NetBSD: ppp_tty.c,v 1.30 2002/03/17 19:41:11 atatat Exp $");
81 
82 #include "ppp.h"
83 
84 #include "opt_ppp.h"
85 #define VJC
86 #define PPP_COMPRESS
87 
88 #include <sys/param.h>
89 #include <sys/proc.h>
90 #include <sys/mbuf.h>
91 #include <sys/dkstat.h>
92 #include <sys/socket.h>
93 #include <sys/ioctl.h>
94 #include <sys/file.h>
95 #include <sys/tty.h>
96 #include <sys/kernel.h>
97 #include <sys/conf.h>
98 #include <sys/vnode.h>
99 #include <sys/systm.h>
100 
101 #include <net/if.h>
102 #include <net/if_types.h>
103 
104 #ifdef VJC
105 #include <netinet/in.h>
106 #include <netinet/in_systm.h>
107 #include <netinet/ip.h>
108 #include <net/slcompress.h>
109 #endif
110 
111 #include "bpfilter.h"
112 #if NBPFILTER > 0 || defined(PPP_FILTER)
113 #include <net/bpf.h>
114 #endif
115 #include <net/ppp_defs.h>
116 #include <net/if_ppp.h>
117 #include <net/if_pppvar.h>
118 
119 int	pppopen __P((dev_t dev, struct tty *tp));
120 int	pppclose __P((struct tty *tp, int flag));
121 int	pppread __P((struct tty *tp, struct uio *uio, int flag));
122 int	pppwrite __P((struct tty *tp, struct uio *uio, int flag));
123 int	ppptioctl __P((struct tty *tp, u_long cmd, caddr_t data, int flag,
124 		       struct proc *));
125 int	pppinput __P((int c, struct tty *tp));
126 int	pppstart __P((struct tty *tp));
127 
128 static void	ppprcvframe __P((struct ppp_softc *sc, struct mbuf *m));
129 static u_int16_t pppfcs __P((u_int16_t fcs, u_char *cp, int len));
130 static void	pppsyncstart __P((struct ppp_softc *sc));
131 static void	pppasyncstart __P((struct ppp_softc *));
132 static void	pppasyncctlp __P((struct ppp_softc *));
133 static void	pppasyncrelinq __P((struct ppp_softc *));
134 static void	ppp_timeout __P((void *));
135 static void	pppgetm __P((struct ppp_softc *sc));
136 static void	pppdumpb __P((u_char *b, int l));
137 static void	ppplogchar __P((struct ppp_softc *, int));
138 static void	pppdumpframe __P((struct ppp_softc *sc, struct mbuf* m,
139     int xmit));
140 
141 /*
142  * Some useful mbuf macros not in mbuf.h.
143  */
144 #define M_IS_CLUSTER(m)	((m)->m_flags & M_EXT)
145 
146 #define M_DATASTART(m)	\
147 	(M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
148 	    (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
149 
150 #define M_DATASIZE(m)	\
151 	(M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
152 	    (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
153 
154 /*
155  * Does c need to be escaped?
156  */
157 #define ESCAPE_P(c)	(sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
158 
159 /*
160  * Procedures for using an async tty interface for PPP.
161  */
162 
163 /* This is a NetBSD-1.0 or later kernel. */
164 #define CCOUNT(q)	((q)->c_cc)
165 
166 #define PPP_LOWAT	100	/* Process more output when < LOWAT on queue */
167 #define	PPP_HIWAT	400	/* Don't start a new packet if HIWAT on que */
168 
169 /*
170  * Line specific open routine for async tty devices.
171  * Attach the given tty to the first available ppp unit.
172  * Called from device open routine or ttioctl.
173  */
174 /* ARGSUSED */
175 int
176 pppopen(dev, tp)
177     dev_t dev;
178     struct tty *tp;
179 {
180     struct proc *p = curproc;		/* XXX */
181     struct ppp_softc *sc;
182     int error, s;
183 
184     if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
185 	return (error);
186 
187     s = spltty();
188 
189     if (tp->t_linesw->l_no == PPPDISC) {
190 	sc = (struct ppp_softc *) tp->t_sc;
191 	if (sc != NULL && sc->sc_devp == (void *) tp) {
192 	    splx(s);
193 	    return (0);
194 	}
195     }
196 
197     if ((sc = pppalloc(p->p_pid)) == NULL) {
198 	splx(s);
199 	return ENXIO;
200     }
201 
202     if (sc->sc_relinq)
203 	(*sc->sc_relinq)(sc);	/* get previous owner to relinquish the unit */
204 
205 #if NBPFILTER > 0
206     /* Switch DLT to PPP-over-serial. */
207     bpf_change_type(&sc->sc_if, DLT_PPP_SERIAL, PPP_HDRLEN);
208 #endif
209 
210     sc->sc_ilen = 0;
211     sc->sc_m = NULL;
212     memset(sc->sc_asyncmap, 0, sizeof(sc->sc_asyncmap));
213     sc->sc_asyncmap[0] = 0xffffffff;
214     sc->sc_asyncmap[3] = 0x60000000;
215     sc->sc_rasyncmap = 0;
216     sc->sc_devp = (void *) tp;
217     sc->sc_start = pppasyncstart;
218     sc->sc_ctlp = pppasyncctlp;
219     sc->sc_relinq = pppasyncrelinq;
220     sc->sc_outm = NULL;
221     pppgetm(sc);
222     sc->sc_if.if_flags |= IFF_RUNNING;
223     sc->sc_if.if_baudrate = tp->t_ospeed;
224 
225     tp->t_sc = (caddr_t) sc;
226     ttyflush(tp, FREAD | FWRITE);
227 
228     splx(s);
229     return (0);
230 }
231 
232 /*
233  * Line specific close routine, called from device close routine
234  * and from ttioctl.
235  * Detach the tty from the ppp unit.
236  * Mimics part of ttyclose().
237  */
238 int
239 pppclose(tp, flag)
240     struct tty *tp;
241     int flag;
242 {
243     struct ppp_softc *sc;
244     int s;
245 
246     s = spltty();
247     ttyflush(tp, FREAD|FWRITE);
248     tp->t_linesw = linesw[0]; /* default line discipline */
249     sc = (struct ppp_softc *) tp->t_sc;
250     if (sc != NULL) {
251 	tp->t_sc = NULL;
252 	if (tp == (struct tty *) sc->sc_devp) {
253 	    pppasyncrelinq(sc);
254 	    pppdealloc(sc);
255 	}
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 #if NBPFILTER > 0
271     /* Change DLT to back none. */
272     bpf_change_type(&sc->sc_if, DLT_NULL, 0);
273 #endif
274 
275     s = spltty();
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_timo_ch);
286 	sc->sc_flags &= ~SC_TIMEOUT;
287     }
288     splx(s);
289 }
290 
291 /*
292  * Line specific (tty) read routine.
293  */
294 int
295 pppread(tp, uio, flag)
296     struct tty *tp;
297     struct uio *uio;
298     int flag;
299 {
300     struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
301     struct mbuf *m, *m0;
302     int s;
303     int error = 0;
304 
305     if (sc == NULL)
306 	return 0;
307     /*
308      * Loop waiting for input, checking that nothing disasterous
309      * happens in the meantime.
310      */
311     s = spltty();
312     for (;;) {
313 	if (tp != (struct tty *) sc->sc_devp ||
314 	    tp->t_linesw->l_no != PPPDISC) {
315 	    splx(s);
316 	    return 0;
317 	}
318 	if (sc->sc_inq.ifq_head != NULL)
319 	    break;
320 	if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0
321 	    && (tp->t_state & TS_ISOPEN)) {
322 	    splx(s);
323 	    return 0;		/* end of file */
324 	}
325 	if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
326 	    splx(s);
327 	    return (EWOULDBLOCK);
328 	}
329 	error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI|PCATCH, ttyin, 0);
330 	if (error) {
331 	    splx(s);
332 	    return error;
333 	}
334     }
335 
336     /* Pull place-holder byte out of canonical queue */
337     getc(&tp->t_canq);
338 
339     /* Get the packet from the input queue */
340     IF_DEQUEUE(&sc->sc_inq, m0);
341     splx(s);
342 
343     for (m = m0; m && uio->uio_resid; m = m->m_next)
344 	if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
345 	    break;
346     m_freem(m0);
347     return (error);
348 }
349 
350 /*
351  * Line specific (tty) write routine.
352  */
353 int
354 pppwrite(tp, uio, flag)
355     struct tty *tp;
356     struct uio *uio;
357     int flag;
358 {
359     struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
360     struct mbuf *m, *m0, **mp;
361     struct sockaddr dst;
362     int len, error;
363 
364     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
365 	return 0;		/* wrote 0 bytes */
366     if (tp->t_linesw->l_no != PPPDISC)
367 	return (EINVAL);
368     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
369 	return EIO;
370     if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
371 	uio->uio_resid < PPP_HDRLEN)
372 	return (EMSGSIZE);
373     for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
374 	MGET(m, M_WAIT, MT_DATA);
375 	if ((*mp = m) == NULL) {
376 	    m_freem(m0);
377 	    return (ENOBUFS);
378 	}
379 	m->m_len = 0;
380 	if (uio->uio_resid >= MCLBYTES / 2)
381 	    MCLGET(m, M_DONTWAIT);
382 	len = M_TRAILINGSPACE(m);
383 	if (len > uio->uio_resid)
384 	    len = uio->uio_resid;
385 	if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
386 	    m_freem(m0);
387 	    return (error);
388 	}
389 	m->m_len = len;
390     }
391     dst.sa_family = AF_UNSPEC;
392     bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
393     m0->m_data += PPP_HDRLEN;
394     m0->m_len -= PPP_HDRLEN;
395     return ((*sc->sc_if.if_output)(&sc->sc_if, m0, &dst, (struct rtentry *)0));
396 }
397 
398 /*
399  * Line specific (tty) ioctl routine.
400  * This discipline requires that tty device drivers call
401  * the line specific l_ioctl routine from their ioctl routines.
402  */
403 /* ARGSUSED */
404 int
405 ppptioctl(tp, cmd, data, flag, p)
406     struct tty *tp;
407     u_long cmd;
408     caddr_t data;
409     int flag;
410     struct proc *p;
411 {
412     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
413     int error, s;
414 
415     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
416 	return (EPASSTHROUGH);
417 
418     error = 0;
419     switch (cmd) {
420     case TIOCRCVFRAME:
421     	ppprcvframe(sc,*((struct mbuf **)data));
422 	break;
423 
424     case PPPIOCSASYNCMAP:
425 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
426 	    break;
427 	sc->sc_asyncmap[0] = *(u_int *)data;
428 	break;
429 
430     case PPPIOCGASYNCMAP:
431 	*(u_int *)data = sc->sc_asyncmap[0];
432 	break;
433 
434     case PPPIOCSRASYNCMAP:
435 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
436 	    break;
437 	sc->sc_rasyncmap = *(u_int *)data;
438 	break;
439 
440     case PPPIOCGRASYNCMAP:
441 	*(u_int *)data = sc->sc_rasyncmap;
442 	break;
443 
444     case PPPIOCSXASYNCMAP:
445 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
446 	    break;
447 	s = spltty();
448 	bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
449 	sc->sc_asyncmap[1] = 0;		    /* mustn't escape 0x20 - 0x3f */
450 	sc->sc_asyncmap[2] &= ~0x40000000;  /* mustn't escape 0x5e */
451 	sc->sc_asyncmap[3] |= 0x60000000;   /* must escape 0x7d, 0x7e */
452 	splx(s);
453 	break;
454 
455     case PPPIOCGXASYNCMAP:
456 	bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
457 	break;
458 
459     default:
460 	error = pppioctl(sc, cmd, data, flag, p);
461 	if (error == 0 && cmd == PPPIOCSMRU)
462 	    pppgetm(sc);
463     }
464 
465     return error;
466 }
467 
468 /* receive a complete ppp frame from device in synchronous
469  * hdlc mode. caller gives up ownership of mbuf
470  */
471 static void
472 ppprcvframe(sc, m)
473 	struct ppp_softc *sc;
474 	struct mbuf *m;
475 {
476 	int len, s;
477 	struct mbuf *n;
478 	u_char hdr[4];
479 	int hlen,count;
480 
481 	for (n=m,len=0;n != NULL;n = n->m_next)
482 		len += n->m_len;
483 	if (len==0) {
484 		m_freem(m);
485 		return;
486 	}
487 
488 	/* extract PPP header from mbuf chain (1 to 4 bytes) */
489 	for (n=m,hlen=0;n!=NULL && hlen<sizeof(hdr);n=n->m_next) {
490 		count = (sizeof(hdr)-hlen) < n->m_len ?
491 				sizeof(hdr)-hlen : n->m_len;
492 		bcopy(mtod(n,u_char*),&hdr[hlen],count);
493 		hlen+=count;
494 	}
495 
496 	s = spltty();
497 
498 	/* if AFCF compressed then prepend AFCF */
499 	if (hdr[0] != PPP_ALLSTATIONS) {
500 		if (sc->sc_flags & SC_REJ_COMP_AC) {
501 			if (sc->sc_flags & SC_DEBUG)
502 				printf(
503 				    "%s: garbage received: 0x%x (need 0xFF)\n",
504 				    sc->sc_if.if_xname, hdr[0]);
505 				goto bail;
506 			}
507 		M_PREPEND(m,2,M_DONTWAIT);
508 		if (m==NULL) {
509 			splx(s);
510 			return;
511 		}
512 		hdr[3] = hdr[1];
513 		hdr[2] = hdr[0];
514 		hdr[0] = PPP_ALLSTATIONS;
515 		hdr[1] = PPP_UI;
516 		len += 2;
517 	}
518 
519 	/* if protocol field compressed, add MSB of protocol field = 0 */
520 	if (hdr[2] & 1) {
521 		/* a compressed protocol */
522 		M_PREPEND(m,1,M_DONTWAIT);
523 		if (m==NULL) {
524 			splx(s);
525 			return;
526 		}
527 		hdr[3] = hdr[2];
528 		hdr[2] = 0;
529 		len++;
530 	}
531 
532 	/* valid LSB of protocol field has bit0 set */
533 	if (!(hdr[3] & 1)) {
534 		if (sc->sc_flags & SC_DEBUG)
535 			printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
536 				(hdr[2] << 8) + hdr[3]);
537 			goto bail;
538 	}
539 
540 	/* packet beyond configured mru? */
541 	if (len > sc->sc_mru + PPP_HDRLEN) {
542 		if (sc->sc_flags & SC_DEBUG)
543 			printf("%s: packet too big\n", sc->sc_if.if_xname);
544 		goto bail;
545 	}
546 
547 	/* add expanded 4 byte header to mbuf chain */
548 	for (n=m,hlen=0;n!=NULL && hlen<sizeof(hdr);n=n->m_next) {
549 		count = (sizeof(hdr)-hlen) < n->m_len ?
550 				sizeof(hdr)-hlen : n->m_len;
551 		bcopy(&hdr[hlen],mtod(n,u_char*),count);
552 		hlen+=count;
553 	}
554 
555 	/* if_ppp.c requires the PPP header and IP header */
556 	/* to be contiguous */
557 	count = len < MHLEN ? len : MHLEN;
558 	if (m->m_len < count) {
559 		m = m_pullup(m,count);
560 		if (m==NULL)
561 			goto bail;
562 	}
563 
564 	sc->sc_stats.ppp_ibytes += len;
565 
566 	if (sc->sc_flags & SC_LOG_RAWIN)
567 		pppdumpframe(sc,m,0);
568 
569 	ppppktin(sc, m, 0);
570 	splx(s);
571 	return;
572 bail:
573 	m_freem(m);
574 	splx(s);
575 }
576 
577 /*
578  * FCS lookup table as calculated by genfcstab.
579  */
580 static const u_int16_t fcstab[256] = {
581 	0x0000,	0x1189,	0x2312,	0x329b,	0x4624,	0x57ad,	0x6536,	0x74bf,
582 	0x8c48,	0x9dc1,	0xaf5a,	0xbed3,	0xca6c,	0xdbe5,	0xe97e,	0xf8f7,
583 	0x1081,	0x0108,	0x3393,	0x221a,	0x56a5,	0x472c,	0x75b7,	0x643e,
584 	0x9cc9,	0x8d40,	0xbfdb,	0xae52,	0xdaed,	0xcb64,	0xf9ff,	0xe876,
585 	0x2102,	0x308b,	0x0210,	0x1399,	0x6726,	0x76af,	0x4434,	0x55bd,
586 	0xad4a,	0xbcc3,	0x8e58,	0x9fd1,	0xeb6e,	0xfae7,	0xc87c,	0xd9f5,
587 	0x3183,	0x200a,	0x1291,	0x0318,	0x77a7,	0x662e,	0x54b5,	0x453c,
588 	0xbdcb,	0xac42,	0x9ed9,	0x8f50,	0xfbef,	0xea66,	0xd8fd,	0xc974,
589 	0x4204,	0x538d,	0x6116,	0x709f,	0x0420,	0x15a9,	0x2732,	0x36bb,
590 	0xce4c,	0xdfc5,	0xed5e,	0xfcd7,	0x8868,	0x99e1,	0xab7a,	0xbaf3,
591 	0x5285,	0x430c,	0x7197,	0x601e,	0x14a1,	0x0528,	0x37b3,	0x263a,
592 	0xdecd,	0xcf44,	0xfddf,	0xec56,	0x98e9,	0x8960,	0xbbfb,	0xaa72,
593 	0x6306,	0x728f,	0x4014,	0x519d,	0x2522,	0x34ab,	0x0630,	0x17b9,
594 	0xef4e,	0xfec7,	0xcc5c,	0xddd5,	0xa96a,	0xb8e3,	0x8a78,	0x9bf1,
595 	0x7387,	0x620e,	0x5095,	0x411c,	0x35a3,	0x242a,	0x16b1,	0x0738,
596 	0xffcf,	0xee46,	0xdcdd,	0xcd54,	0xb9eb,	0xa862,	0x9af9,	0x8b70,
597 	0x8408,	0x9581,	0xa71a,	0xb693,	0xc22c,	0xd3a5,	0xe13e,	0xf0b7,
598 	0x0840,	0x19c9,	0x2b52,	0x3adb,	0x4e64,	0x5fed,	0x6d76,	0x7cff,
599 	0x9489,	0x8500,	0xb79b,	0xa612,	0xd2ad,	0xc324,	0xf1bf,	0xe036,
600 	0x18c1,	0x0948,	0x3bd3,	0x2a5a,	0x5ee5,	0x4f6c,	0x7df7,	0x6c7e,
601 	0xa50a,	0xb483,	0x8618,	0x9791,	0xe32e,	0xf2a7,	0xc03c,	0xd1b5,
602 	0x2942,	0x38cb,	0x0a50,	0x1bd9,	0x6f66,	0x7eef,	0x4c74,	0x5dfd,
603 	0xb58b,	0xa402,	0x9699,	0x8710,	0xf3af,	0xe226,	0xd0bd,	0xc134,
604 	0x39c3,	0x284a,	0x1ad1,	0x0b58,	0x7fe7,	0x6e6e,	0x5cf5,	0x4d7c,
605 	0xc60c,	0xd785,	0xe51e,	0xf497,	0x8028,	0x91a1,	0xa33a,	0xb2b3,
606 	0x4a44,	0x5bcd,	0x6956,	0x78df,	0x0c60,	0x1de9,	0x2f72,	0x3efb,
607 	0xd68d,	0xc704,	0xf59f,	0xe416,	0x90a9,	0x8120,	0xb3bb,	0xa232,
608 	0x5ac5,	0x4b4c,	0x79d7,	0x685e,	0x1ce1,	0x0d68,	0x3ff3,	0x2e7a,
609 	0xe70e,	0xf687,	0xc41c,	0xd595,	0xa12a,	0xb0a3,	0x8238,	0x93b1,
610 	0x6b46,	0x7acf,	0x4854,	0x59dd,	0x2d62,	0x3ceb,	0x0e70,	0x1ff9,
611 	0xf78f,	0xe606,	0xd49d,	0xc514,	0xb1ab,	0xa022,	0x92b9,	0x8330,
612 	0x7bc7,	0x6a4e,	0x58d5,	0x495c,	0x3de3,	0x2c6a,	0x1ef1,	0x0f78
613 };
614 
615 /*
616  * Calculate a new FCS given the current FCS and the new data.
617  */
618 static u_int16_t
619 pppfcs(fcs, cp, len)
620     u_int16_t fcs;
621     u_char *cp;
622     int len;
623 {
624     while (len--)
625 	fcs = PPP_FCS(fcs, *cp++);
626     return (fcs);
627 }
628 
629 /* This gets called at splsoftnet from pppasyncstart at various times
630  * when there is data ready to be sent.
631  */
632 static void
633 pppsyncstart(sc)
634 	struct ppp_softc *sc;
635 {
636 	struct tty *tp = (struct tty *) sc->sc_devp;
637 	struct mbuf *m, *n;
638 	int len;
639 
640 	for(m = sc->sc_outm;;) {
641 		if (m == NULL) {
642 			m = ppp_dequeue(sc);	/* get new packet */
643 			if (m == NULL)
644 				break;		/* no more packets */
645 			if (sc->sc_flags & SC_DEBUG)
646 				pppdumpframe(sc,m,1);
647 		}
648 		for(n=m,len=0;n!=NULL;n=n->m_next)
649 			len += n->m_len;
650 
651 		/* call device driver IOCTL to transmit a frame */
652 		if ((*cdevsw[major(tp->t_dev)].d_ioctl)
653 			(tp->t_dev, TIOCXMTFRAME, (caddr_t)&m, 0, 0)) {
654 			/* busy or error, set as current packet */
655 			sc->sc_outm = m;
656 			break;
657 		}
658 		sc->sc_outm = m = NULL;
659 		sc->sc_stats.ppp_obytes += len;
660 	}
661 }
662 
663 /*
664  * This gets called at splsoftnet from if_ppp.c at various times
665  * when there is data ready to be sent.
666  */
667 static void
668 pppasyncstart(sc)
669     struct ppp_softc *sc;
670 {
671     struct tty *tp = (struct tty *) sc->sc_devp;
672     struct mbuf *m;
673     int len;
674     u_char *start, *stop, *cp;
675     int n, ndone, done, idle;
676     struct mbuf *m2;
677     int s;
678 
679     if (sc->sc_flags & SC_SYNC){
680 	pppsyncstart(sc);
681 	return;
682     }
683 
684     idle = 0;
685     while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
686 	/*
687 	 * See if we have an existing packet partly sent.
688 	 * If not, get a new packet and start sending it.
689 	 */
690 	m = sc->sc_outm;
691 	if (m == NULL) {
692 	    /*
693 	     * Get another packet to be sent.
694 	     */
695 	    m = ppp_dequeue(sc);
696 	    if (m == NULL) {
697 		idle = 1;
698 		break;
699 	    }
700 
701 	    /*
702 	     * The extra PPP_FLAG will start up a new packet, and thus
703 	     * will flush any accumulated garbage.  We do this whenever
704 	     * the line may have been idle for some time.
705 	     */
706 	    if (CCOUNT(&tp->t_outq) == 0) {
707 		++sc->sc_stats.ppp_obytes;
708 		(void) putc(PPP_FLAG, &tp->t_outq);
709 	    }
710 
711 	    /* Calculate the FCS for the first mbuf's worth. */
712 	    sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
713 	}
714 
715 	for (;;) {
716 	    start = mtod(m, u_char *);
717 	    len = m->m_len;
718 	    stop = start + len;
719 	    while (len > 0) {
720 		/*
721 		 * Find out how many bytes in the string we can
722 		 * handle without doing something special.
723 		 */
724 		for (cp = start; cp < stop; cp++)
725 		    if (ESCAPE_P(*cp))
726 			break;
727 		n = cp - start;
728 		if (n) {
729 		    /* NetBSD (0.9 or later), 4.3-Reno or similar. */
730 		    ndone = n - b_to_q(start, n, &tp->t_outq);
731 		    len -= ndone;
732 		    start += ndone;
733 		    sc->sc_stats.ppp_obytes += ndone;
734 
735 		    if (ndone < n)
736 			break;	/* packet doesn't fit */
737 		}
738 		/*
739 		 * If there are characters left in the mbuf,
740 		 * the first one must be special.
741 		 * Put it out in a different form.
742 		 */
743 		if (len) {
744 		    s = spltty();
745 		    if (putc(PPP_ESCAPE, &tp->t_outq)) {
746 			splx(s);
747 			break;
748 		    }
749 		    if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
750 			(void) unputc(&tp->t_outq);
751 			splx(s);
752 			break;
753 		    }
754 		    splx(s);
755 		    sc->sc_stats.ppp_obytes += 2;
756 		    start++;
757 		    len--;
758 		}
759 	    }
760 
761 	    /*
762 	     * If we didn't empty this mbuf, remember where we're up to.
763 	     * If we emptied the last mbuf, try to add the FCS and closing
764 	     * flag, and if we can't, leave sc_outm pointing to m, but with
765 	     * m->m_len == 0, to remind us to output the FCS and flag later.
766 	     */
767 	    done = len == 0;
768 	    if (done && m->m_next == NULL) {
769 		u_char *p, *q;
770 		int c;
771 		u_char endseq[8];
772 
773 		/*
774 		 * We may have to escape the bytes in the FCS.
775 		 */
776 		p = endseq;
777 		c = ~sc->sc_outfcs & 0xFF;
778 		if (ESCAPE_P(c)) {
779 		    *p++ = PPP_ESCAPE;
780 		    *p++ = c ^ PPP_TRANS;
781 		} else
782 		    *p++ = c;
783 		c = (~sc->sc_outfcs >> 8) & 0xFF;
784 		if (ESCAPE_P(c)) {
785 		    *p++ = PPP_ESCAPE;
786 		    *p++ = c ^ PPP_TRANS;
787 		} else
788 		    *p++ = c;
789 		*p++ = PPP_FLAG;
790 
791 		/*
792 		 * Try to output the FCS and flag.  If the bytes
793 		 * don't all fit, back out.
794 		 */
795 		s = spltty();
796 		for (q = endseq; q < p; ++q)
797 		    if (putc(*q, &tp->t_outq)) {
798 			done = 0;
799 			for (; q > endseq; --q)
800 			    unputc(&tp->t_outq);
801 			break;
802 		    }
803 		splx(s);
804 		if (done)
805 		    sc->sc_stats.ppp_obytes += q - endseq;
806 	    }
807 
808 	    if (!done) {
809 		/* remember where we got to */
810 		m->m_data = start;
811 		m->m_len = len;
812 		break;
813 	    }
814 
815 	    /* Finished with this mbuf; free it and move on. */
816 	    MFREE(m, m2);
817 	    m = m2;
818 	    if (m == NULL) {
819 		/* Finished a packet */
820 		break;
821 	    }
822 	    sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
823 	}
824 
825 	/*
826 	 * If m == NULL, we have finished a packet.
827 	 * If m != NULL, we've either done as much work this time
828 	 * as we need to, or else we've filled up the output queue.
829 	 */
830 	sc->sc_outm = m;
831 	if (m)
832 	    break;
833     }
834 
835     /* Call pppstart to start output again if necessary. */
836     s = spltty();
837     pppstart(tp);
838 
839     /*
840      * This timeout is needed for operation on a pseudo-tty,
841      * because the pty code doesn't call pppstart after it has
842      * drained the t_outq.
843      */
844     if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
845 	callout_reset(&sc->sc_timo_ch, 1, ppp_timeout, sc);
846 	sc->sc_flags |= SC_TIMEOUT;
847     }
848 
849     splx(s);
850 }
851 
852 /*
853  * This gets called when a received packet is placed on
854  * the inq, at splsoftnet.
855  */
856 static void
857 pppasyncctlp(sc)
858     struct ppp_softc *sc;
859 {
860     struct tty *tp;
861     int s;
862 
863     /* Put a placeholder byte in canq for ttselect()/ttnread(). */
864     s = spltty();
865     tp = (struct tty *) sc->sc_devp;
866     putc(0, &tp->t_canq);
867     ttwakeup(tp);
868     splx(s);
869 }
870 
871 /*
872  * Start output on async tty interface.  If the transmit queue
873  * has drained sufficiently, arrange for pppasyncstart to be
874  * called later at splsoftnet.
875  * Called at spltty or higher.
876  */
877 int
878 pppstart(tp)
879     struct tty *tp;
880 {
881     struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
882 
883     /*
884      * If there is stuff in the output queue, send it now.
885      * We are being called in lieu of ttstart and must do what it would.
886      */
887     if (tp->t_oproc != NULL)
888 	(*tp->t_oproc)(tp);
889 
890     /*
891      * If the transmit queue has drained and the tty has not hung up
892      * or been disconnected from the ppp unit, then tell if_ppp.c that
893      * we need more output.
894      */
895     if ((CCOUNT(&tp->t_outq) >= PPP_LOWAT)
896 	&& ((sc == NULL) || (sc->sc_flags & SC_TIMEOUT)))
897 	return 0;
898 #ifdef ALTQ
899     /*
900      * if ALTQ is enabled, don't invoke NETISR_PPP.
901      * pppintr() could loop without doing anything useful
902      * under rate-limiting.
903      */
904     if (ALTQ_IS_ENABLED(&sc->sc_if.if_snd))
905 	return 0;
906 #endif
907     if (!((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
908 	&& sc != NULL && tp == (struct tty *) sc->sc_devp) {
909 	ppp_restart(sc);
910     }
911 
912     return 0;
913 }
914 
915 /*
916  * Timeout routine - try to start some more output.
917  */
918 static void
919 ppp_timeout(x)
920     void *x;
921 {
922     struct ppp_softc *sc = (struct ppp_softc *) x;
923     struct tty *tp = (struct tty *) sc->sc_devp;
924     int s;
925 
926     s = spltty();
927     sc->sc_flags &= ~SC_TIMEOUT;
928     pppstart(tp);
929     splx(s);
930 }
931 
932 /*
933  * Allocate enough mbuf to handle current MRU.
934  */
935 static void
936 pppgetm(sc)
937     struct ppp_softc *sc;
938 {
939     struct mbuf *m, **mp;
940     int len;
941 
942     mp = &sc->sc_m;
943     for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
944 	if ((m = *mp) == NULL) {
945 	    MGETHDR(m, M_DONTWAIT, MT_DATA);
946 	    if (m == NULL)
947 		break;
948 	    *mp = m;
949 	    MCLGET(m, M_DONTWAIT);
950 	}
951 	len -= M_DATASIZE(m);
952 	mp = &m->m_next;
953     }
954 }
955 
956 /*
957  * tty interface receiver interrupt.
958  */
959 static const unsigned paritytab[8] = {
960     0x96696996, 0x69969669, 0x69969669, 0x96696996,
961     0x69969669, 0x96696996, 0x96696996, 0x69969669
962 };
963 
964 int
965 pppinput(c, tp)
966     int c;
967     struct tty *tp;
968 {
969     struct ppp_softc *sc;
970     struct mbuf *m;
971     int ilen, s;
972 
973     sc = (struct ppp_softc *) tp->t_sc;
974     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
975 	return 0;
976 
977     ++tk_nin;
978     ++sc->sc_stats.ppp_ibytes;
979 
980     if (c & TTY_FE) {
981 	/* framing error or overrun on this char - abort packet */
982 	if (sc->sc_flags & SC_DEBUG)
983 	    printf("%s: bad char %x\n", sc->sc_if.if_xname, c);
984 	goto flush;
985     }
986 
987     c &= 0xff;
988 
989     /*
990      * Handle software flow control of output.
991      */
992     if (tp->t_iflag & IXON) {
993 	if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
994 	    if ((tp->t_state & TS_TTSTOP) == 0) {
995 		tp->t_state |= TS_TTSTOP;
996 		(*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
997 	    }
998 	    return 0;
999 	}
1000 	if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
1001 	    tp->t_state &= ~TS_TTSTOP;
1002 	    if (tp->t_oproc != NULL)
1003 		(*tp->t_oproc)(tp);
1004 	    return 0;
1005 	}
1006     }
1007 
1008     s = spltty();
1009     if (c & 0x80)
1010 	sc->sc_flags |= SC_RCV_B7_1;
1011     else
1012 	sc->sc_flags |= SC_RCV_B7_0;
1013     if (paritytab[c >> 5] & (1 << (c & 0x1F)))
1014 	sc->sc_flags |= SC_RCV_ODDP;
1015     else
1016 	sc->sc_flags |= SC_RCV_EVNP;
1017     splx(s);
1018 
1019     if (sc->sc_flags & SC_LOG_RAWIN)
1020 	ppplogchar(sc, c);
1021 
1022     if (c == PPP_FLAG) {
1023 	ilen = sc->sc_ilen;
1024 	sc->sc_ilen = 0;
1025 
1026 	if (sc->sc_rawin_count > 0)
1027 	    ppplogchar(sc, -1);
1028 
1029 	/*
1030 	 * If SC_ESCAPED is set, then we've seen the packet
1031 	 * abort sequence "}~".
1032 	 */
1033 	if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
1034 	    || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
1035 	    s = spltty();
1036 	    sc->sc_flags |= SC_PKTLOST;	/* note the dropped packet */
1037 	    if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
1038 		if (sc->sc_flags & SC_DEBUG)
1039 		    printf("%s: bad fcs %x\n", sc->sc_if.if_xname,
1040 			sc->sc_fcs);
1041 		sc->sc_if.if_ierrors++;
1042 		sc->sc_stats.ppp_ierrors++;
1043 	    } else
1044 		sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
1045 	    splx(s);
1046 	    return 0;
1047 	}
1048 
1049 	if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
1050 	    if (ilen) {
1051 		if (sc->sc_flags & SC_DEBUG)
1052 		    printf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen);
1053 		s = spltty();
1054 		sc->sc_if.if_ierrors++;
1055 		sc->sc_stats.ppp_ierrors++;
1056 		sc->sc_flags |= SC_PKTLOST;
1057 		splx(s);
1058 	    }
1059 	    return 0;
1060 	}
1061 
1062 	/*
1063 	 * Remove FCS trailer.  Somewhat painful...
1064 	 */
1065 	ilen -= 2;
1066 	if (--sc->sc_mc->m_len == 0) {
1067 	    for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
1068 		;
1069 	    sc->sc_mc = m;
1070 	}
1071 	sc->sc_mc->m_len--;
1072 
1073 	/* excise this mbuf chain */
1074 	m = sc->sc_m;
1075 	sc->sc_m = sc->sc_mc->m_next;
1076 	sc->sc_mc->m_next = NULL;
1077 
1078 	ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
1079 	if (sc->sc_flags & SC_PKTLOST) {
1080 	    s = spltty();
1081 	    sc->sc_flags &= ~SC_PKTLOST;
1082 	    splx(s);
1083 	}
1084 
1085 	pppgetm(sc);
1086 	return 0;
1087     }
1088 
1089     if (sc->sc_flags & SC_FLUSH) {
1090 	if (sc->sc_flags & SC_LOG_FLUSH)
1091 	    ppplogchar(sc, c);
1092 	return 0;
1093     }
1094 
1095     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
1096 	return 0;
1097 
1098     s = spltty();
1099     if (sc->sc_flags & SC_ESCAPED) {
1100 	sc->sc_flags &= ~SC_ESCAPED;
1101 	c ^= PPP_TRANS;
1102     } else if (c == PPP_ESCAPE) {
1103 	sc->sc_flags |= SC_ESCAPED;
1104 	splx(s);
1105 	return 0;
1106     }
1107     splx(s);
1108 
1109     /*
1110      * Initialize buffer on first octet received.
1111      * First octet could be address or protocol (when compressing
1112      * address/control).
1113      * Second octet is control.
1114      * Third octet is first or second (when compressing protocol)
1115      * octet of protocol.
1116      * Fourth octet is second octet of protocol.
1117      */
1118     if (sc->sc_ilen == 0) {
1119 	/* reset the first input mbuf */
1120 	if (sc->sc_m == NULL) {
1121 	    pppgetm(sc);
1122 	    if (sc->sc_m == NULL) {
1123 		if (sc->sc_flags & SC_DEBUG)
1124 		    printf("%s: no input mbufs!\n", sc->sc_if.if_xname);
1125 		goto flush;
1126 	    }
1127 	}
1128 	m = sc->sc_m;
1129 	m->m_len = 0;
1130 	m->m_data = M_DATASTART(sc->sc_m);
1131 	sc->sc_mc = m;
1132 	sc->sc_mp = mtod(m, char *);
1133 	sc->sc_fcs = PPP_INITFCS;
1134 	if (c != PPP_ALLSTATIONS) {
1135 	    if (sc->sc_flags & SC_REJ_COMP_AC) {
1136 		if (sc->sc_flags & SC_DEBUG)
1137 		    printf("%s: garbage received: 0x%x (need 0xFF)\n",
1138 		    sc->sc_if.if_xname, c);
1139 		goto flush;
1140 	    }
1141 	    *sc->sc_mp++ = PPP_ALLSTATIONS;
1142 	    *sc->sc_mp++ = PPP_UI;
1143 	    sc->sc_ilen += 2;
1144 	    m->m_len += 2;
1145 	}
1146     }
1147     if (sc->sc_ilen == 1 && c != PPP_UI) {
1148 	if (sc->sc_flags & SC_DEBUG)
1149 	    printf("%s: missing UI (0x3), got 0x%x\n",
1150 		sc->sc_if.if_xname, c);
1151 	goto flush;
1152     }
1153     if (sc->sc_ilen == 2 && (c & 1) == 1) {
1154 	/* a compressed protocol */
1155 	*sc->sc_mp++ = 0;
1156 	sc->sc_ilen++;
1157 	sc->sc_mc->m_len++;
1158     }
1159     if (sc->sc_ilen == 3 && (c & 1) == 0) {
1160 	if (sc->sc_flags & SC_DEBUG)
1161 	    printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
1162 		(sc->sc_mp[-1] << 8) + c);
1163 	goto flush;
1164     }
1165 
1166     /* packet beyond configured mru? */
1167     if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1168 	if (sc->sc_flags & SC_DEBUG)
1169 	    printf("%s: packet too big\n", sc->sc_if.if_xname);
1170 	goto flush;
1171     }
1172 
1173     /* is this mbuf full? */
1174     m = sc->sc_mc;
1175     if (M_TRAILINGSPACE(m) <= 0) {
1176 	if (m->m_next == NULL) {
1177 	    pppgetm(sc);
1178 	    if (m->m_next == NULL) {
1179 		if (sc->sc_flags & SC_DEBUG)
1180 		    printf("%s: too few input mbufs!\n", sc->sc_if.if_xname);
1181 		goto flush;
1182 	    }
1183 	}
1184 	sc->sc_mc = m = m->m_next;
1185 	m->m_len = 0;
1186 	m->m_data = M_DATASTART(m);
1187 	sc->sc_mp = mtod(m, char *);
1188     }
1189 
1190     ++m->m_len;
1191     *sc->sc_mp++ = c;
1192     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1193     return 0;
1194 
1195  flush:
1196     if (!(sc->sc_flags & SC_FLUSH)) {
1197 	s = spltty();
1198 	sc->sc_if.if_ierrors++;
1199 	sc->sc_stats.ppp_ierrors++;
1200 	sc->sc_flags |= SC_FLUSH;
1201 	splx(s);
1202 	if (sc->sc_flags & SC_LOG_FLUSH)
1203 	    ppplogchar(sc, c);
1204     }
1205     return 0;
1206 }
1207 
1208 #define MAX_DUMP_BYTES	128
1209 
1210 static void
1211 ppplogchar(sc, c)
1212     struct ppp_softc *sc;
1213     int c;
1214 {
1215     if (c >= 0)
1216 	sc->sc_rawin[sc->sc_rawin_count++] = c;
1217     if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1218 	|| (c < 0 && sc->sc_rawin_count > 0)) {
1219 	printf("%s input: ", sc->sc_if.if_xname);
1220 	pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
1221 	sc->sc_rawin_count = 0;
1222     }
1223 }
1224 
1225 static void
1226 pppdumpb(b, l)
1227     u_char *b;
1228     int l;
1229 {
1230     char buf[3*MAX_DUMP_BYTES+4];
1231     char *bp = buf;
1232     static char digits[] = "0123456789abcdef";
1233 
1234     while (l--) {
1235 	if (bp >= buf + sizeof(buf) - 3) {
1236 	    *bp++ = '>';
1237 	    break;
1238 	}
1239 	*bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
1240 	*bp++ = digits[*b++ & 0xf];
1241 	*bp++ = ' ';
1242     }
1243 
1244     *bp = 0;
1245     printf("%s\n", buf);
1246 }
1247 
1248 static void
1249 pppdumpframe(sc, m, xmit)
1250 	struct ppp_softc *sc;
1251 	struct mbuf* m;
1252 	int xmit;
1253 {
1254 	int i,lcount,copycount,count;
1255 	char lbuf[16];
1256 	char *data;
1257 
1258 	if (m == NULL)
1259 		return;
1260 
1261 	for(count=m->m_len,data=mtod(m,char*);m != NULL;) {
1262 		/* build a line of output */
1263 		for(lcount=0;lcount < sizeof(lbuf);lcount += copycount) {
1264 			if (!count) {
1265 				m = m->m_next;
1266 				if (m == NULL)
1267 					break;
1268 				count = m->m_len;
1269 				data  = mtod(m,char*);
1270 			}
1271 			copycount = (count > sizeof(lbuf)-lcount) ?
1272 					sizeof(lbuf)-lcount : count;
1273 			bcopy(data,&lbuf[lcount],copycount);
1274 			data  += copycount;
1275 			count -= copycount;
1276 		}
1277 
1278 		/* output line (hex 1st, then ascii) */
1279 		printf("%s %s:", sc->sc_if.if_xname,
1280 		    xmit ? "output" : "input ");
1281 		for(i=0;i<lcount;i++)
1282 			printf("%02x ",(u_char)lbuf[i]);
1283 		for(;i<sizeof(lbuf);i++)
1284 			printf("   ");
1285 		for(i=0;i<lcount;i++)
1286 			printf("%c",(lbuf[i] >= 040 &&
1287 			    lbuf[i] <= 0176) ? lbuf[i] : '.');
1288 		printf("\n");
1289 	}
1290 }
1291