1 /* $ID: ppp_tty.c,v 1.4 1994/12/13 03:42:17 paulus Exp paulus $ */
4 * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous
7 * Copyright (c) 1989 Carnegie Mellon University.
10 * Redistribution and use in source and binary forms are permitted
11 * provided that the above copyright notice and this paragraph are
12 * duplicated in all such forms and that any documentation,
13 * advertising materials, and other materials related to such
14 * distribution and use acknowledge that the software was developed
15 * by Carnegie Mellon University. The name of the
16 * University may not be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 * Carnegie Mellon University
25 * Pittsburgh, PA 15213
30 * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
32 * Copyright (c) 1987 Regents of the University of California.
33 * All rights reserved.
35 * Redistribution and use in source and binary forms are permitted
36 * provided that the above copyright notice and this paragraph are
37 * duplicated in all such forms and that any documentation,
38 * advertising materials, and other materials related to such
39 * distribution and use acknowledge that the software was developed
40 * by the University of California, Berkeley. The name of the
41 * University may not be used to endorse or promote products derived
42 * from this software without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
44 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
45 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
47 * Serial Line interface
50 * Center for Seismic Studies
51 * 1300 N 17th Street, Suite 1450
52 * Arlington, Virginia 22209
57 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
58 * Converted to 4.3BSD Beta by Chris Torek.
59 * Other changes made at Berkeley, based in part on code by Kirk Smith.
61 * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
62 * Added VJ tcp header compression; more unified ioctls
64 * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
65 * Cleaned up a lot of the mbuf-related code to fix bugs that
66 * caused system crashes and packet corruption. Changed pppstart
67 * so that it doesn't just give up with a collision if the whole
68 * packet doesn't fit in the output ring buffer.
70 * Added priority queueing for interactive IP packets, following
71 * the model of if_sl.c, plus hooks for bpf.
72 * Paul Mackerras (paulus@cs.anu.edu.au).
74 * Rewritten for NextStep's funky kernel functions, I/O threads,
75 * and netbufs (instead of real mbufs). Also, ifnets don't install
76 * into the kernel under NS as they do under BSD. We have tried to
77 * make the code remain as similar to the NetBSD version without
78 * incurring too much hassle. This code is the merge of
79 * Philip Prindeville's <philipp@res.enst.fr>/Pete French's <pete@ohm.york.ac.uk>
80 * and Stephen Perkins' <perkins@cps.msu.edu> independent ports.
84 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
85 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:59 cgd Exp */
87 /* #include "ppp.h" */
91 #define KERNEL_FEATURES 1
94 #include <sys/param.h>
98 #include <sys/socket.h>
99 #include <sys/ioctl.h>
100 #include <sys/file.h>
102 #include <sys/conf.h>
105 #include <sys/errno.h>
106 #include <machine/param.h>
109 #include <kernserv/prototypes.h>
110 /* NeXT broke spl.h in 3.2/m68k. Thanks EPS! */
115 #include <driverkit/generalFuncs.h>
116 #import <kernserv/machine/spl.h>
119 #include <kernserv/kern_server_types.h>
122 #include <net/route.h>
125 #include <netinet/in.h>
126 #include <netinet/in_systm.h>
127 #include <netinet/ip.h>
130 #include <net/ppp_defs.h>
132 #include <net/vjcompress.h>
134 #include <net/if_ppp.h>
135 #include "if_pppvar.h"
139 int pppopen __P((dev_t dev, struct tty *tp));
140 void pppclose __P((struct tty *tp));
141 int pppread __P((struct tty *tp, struct uio *uio));
142 int pppwrite __P((struct tty *tp, struct uio *uio));
143 int ppptioctl __P((struct tty *tp, int cmd, void *data, int flag));
144 void pppinput __P((int c, struct tty *tp));
145 void pppstart __P((struct tty *tp));
148 * Must return an actual netbuf_t since other protocols
149 * use this to get our buffers.
151 netbuf_t pppgetbuf __P((netif_t));
154 * Must accept an actual netbuf_t since others use this
155 * Procedure to access our output routine.
157 int pppoutput __P((netif_t ifp, netbuf_t m, void *arg));
159 static u_int16_t pppfcs __P((u_int16_t fcs, u_char *cp, int len));
160 static void pppasyncstart __P((struct ppp_softc *));
161 static void pppasyncctlp __P((struct ppp_softc *));
162 static void pppasyncrelinq __P((struct ppp_softc *));
163 static int ppp_timeout __P((void *));
164 void pppgetm __P((struct ppp_softc *sc));
165 static void pppdumpb __P((u_char *b, int l));
166 void ppplogchar __P((struct ppp_softc *, int));
168 extern kern_server_t instance;
171 * Does c need to be escaped?
173 #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
175 #define CCOUNT(q) ((q)->c_cc)
177 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
179 #include "linedisc.h"
182 extern int ttymodem(struct tty*, int);
183 extern int ttselect(struct tty *tp, int rw);
187 pppgetinbuf(netif_t ifp)
189 register struct ppp_softc *sc = &ppp_softc[if_unit(ifp)];
191 int len = MAX(sc->sc_mru, PPP_MTU) + sizeof (struct ifnet *) +
195 PPP_HDRLEN + PPP_FCSLEN;
200 NB_SHRINK_TOP(nb, VJ_HDRLEN + PPP_HDRLEN);
202 NB_SHRINK_TOP(nb, PPP_HDRLEN);
210 * I was a bit worried about reentrancy here. +++SJP
214 pppfillfreeq(void *arg)
216 struct ppp_softc *sc = (struct ppp_softc *)arg;
218 volatile static int in = 0;
224 while(!nbq_high(&sc->sc_freeq)) {
225 nb = pppgetinbuf(sc->sc_if);
227 nbq_enqueue(&sc->sc_freeq, nb);
234 * Line specific open routine for async tty devices.
235 * Attach the given tty to the first available ppp unit.
241 register struct tty *tp;
243 struct proc *p = curproc; /* XXX */
244 register struct ppp_softc *sc;
250 if (tp->t_line == PPPDISC) {
251 sc = (struct ppp_softc *) tp->t_sc;
252 if (sc != NULL && sc->sc_devp == (void *) tp)
256 if ((sc = pppalloc(p->p_pid)) == NULL)
260 (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */
262 pppfillfreeq((void *) sc); /* fill the free queue - we may block */
267 bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
268 sc->sc_asyncmap[0] = 0xffffffff;
269 sc->sc_asyncmap[3] = 0x60000000; /* 0x7D and 0x7E */
270 sc->sc_rasyncmap = 0;
271 sc->sc_devp = (void *) tp;
272 sc->sc_start = pppasyncstart;
273 sc->sc_ctlp = pppasyncctlp;
274 sc->sc_relinq = pppasyncrelinq;
277 if_flags_set(sc->sc_if, if_flags(sc->sc_if) | IFF_RUNNING);
279 tp->t_sc = (caddr_t) sc;
280 ttyflush(tp, FREAD | FWRITE);
287 * Line specific close routine.
288 * Detach the tty from the ppp unit.
289 * Mimics part of ttyclose().
295 register struct ppp_softc *sc;
299 s = splimp(); /* paranoid; splnet probably ok */
301 sc = (struct ppp_softc *) tp->t_sc;
304 if (tp == (struct tty *) sc->sc_devp) {
314 * Relinquish the interface unit to another device.
318 struct ppp_softc *sc;
324 NB_FREE(sc->sc_outm);
331 if (sc->sc_flags & SC_TIMEOUT) {
332 ns_untimeout(ppp_timeout, (void *) sc);
333 sc->sc_flags &= ~SC_TIMEOUT;
339 * Line specific (tty) read routine.
343 register struct tty *tp;
346 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
350 struct nty *np = ttynty(tp);
353 if ((tp->t_state & TS_CARR_ON) == 0 && (np->t_pflags & TP_CLOCAL) == 0)
354 return 0; /* end of file */
358 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_flags & CLOCAL) == 0)
359 return 0; /* end of file */
361 #endif /* NEW_CLOCAL */
363 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
366 while (nbq_empty(&sc->sc_inq) && tp->t_line == PPPDISC) {
367 if (tp->t_state & (TS_ASYNC | TS_NBIO)) {
369 return (EWOULDBLOCK);
371 sleep((caddr_t)&tp->t_rawq, TTIPRI);
373 if (tp->t_line != PPPDISC) {
378 /* Pull place-holder byte out of canonical queue */
381 /* Get the packet from the input queue */
382 m = nbq_dequeue(&sc->sc_inq);
385 if (sc->sc_flags & SC_DEBUG)
386 IOLogDbg("Read didn't get a buffer at %s %d\n", __FILE__, __LINE__);
389 error = uiomove(NB_MAP(m), NB_SIZE(m), UIO_READ, uio);
395 * Line specific (tty) write routine.
399 register struct tty *tp;
402 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
406 struct nty *np = ttynty(tp);
410 if ((tp->t_state & TS_CARR_ON) == 0 && (np->t_pflags & TP_CLOCAL) == 0)
411 return 0; /* wrote 0 bytes */
415 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_flags & CLOCAL) == 0)
416 return 0; /* wrote 0 bytes */
418 #endif /* NEW_CLOCAL */
420 if (tp->t_line != PPPDISC)
422 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
424 if (uio->uio_resid > if_mtu(sc->sc_if) + PPP_HDRLEN ||
425 uio->uio_resid < PPP_HDRLEN)
427 m = nb_TO_NB(pppgetbuf(sc->sc_if));
430 if (sc->sc_flags & SC_DEBUG)
431 IOLogDbg("No buffers available for user level write()\n");
434 NB_GROW_TOP(m, PPP_HDRLEN);
435 len = uio->uio_resid;
436 if (error = uiomove(NB_MAP(m), NB_SIZE(m), UIO_WRITE, uio)) {
440 NB_SHRINK_BOT(m, NB_SIZE(m) - len);
441 dst.sa_family = AF_UNSPEC;
442 bcopy(mtod(m, u_char *), dst.sa_data, PPP_HDRLEN);
444 NB_SHRINK_TOP(m, PPP_HDRLEN);
445 return (pppoutput(sc->sc_if, NB_TO_nb(m), &dst));
449 * Line specific (tty) ioctl routine.
450 * This discipline requires that tty device drivers call
451 * the line specific l_ioctl routine from their ioctl routines.
455 ppptioctl(tp, cmd, data, flag)
460 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
463 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
468 case PPPIOCSASYNCMAP:
472 sc->sc_asyncmap[0] = *(u_int *)data;
475 case PPPIOCGASYNCMAP:
476 *(u_int *)data = sc->sc_asyncmap[0];
479 case PPPIOCSRASYNCMAP:
482 sc->sc_rasyncmap = *(u_int *)data;
485 case PPPIOCGRASYNCMAP:
486 *(u_int *)data = sc->sc_rasyncmap;
489 case PPPIOCSXASYNCMAP:
493 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
494 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
495 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
496 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
500 case PPPIOCGXASYNCMAP:
501 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
505 error = pppioctl(sc, cmd, data, flag);
506 if (error == 0 && cmd == PPPIOCSMRU)
511 if (! error && (cmd & IOC_OUT)) {
512 struct uthread *_u = uthread_from_thread(current_thread());
514 /* third arg is destination in ioctl() call... */
515 copyout(data, (caddr_t) _u->uu_arg[2], (cmd >> 16) & IOCPARM_MASK);
523 * FCS lookup table as calculated by genfcstab.
525 static const u_int16_t fcstab[256] = {
526 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
527 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
528 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
529 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
530 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
531 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
532 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
533 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
534 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
535 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
536 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
537 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
538 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
539 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
540 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
541 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
542 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
543 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
544 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
545 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
546 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
547 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
548 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
549 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
550 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
551 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
552 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
553 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
554 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
555 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
556 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
557 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
561 * Calculate a new FCS given the current FCS and the new data.
565 register u_int16_t fcs;
570 fcs = PPP_FCS(fcs, *cp++);
575 * This gets called from pppoutput when a new packet is
580 register struct ppp_softc *sc;
582 register struct tty *tp = (struct tty *) sc->sc_devp;
591 * This gets called when a received packet is placed on
596 struct ppp_softc *sc;
600 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
601 tp = (struct tty *) sc->sc_devp;
602 putc(0, &tp->t_canq);
607 * Start output on async tty interface. Get another datagram
608 * to send from the interface queue and start sending it.
612 register struct tty *tp;
614 register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
617 register u_char *start, *stop, *cp;
618 int n, ndone, done, idle;
619 struct nty *np = ttynty(tp);
623 if ((tp->t_state & TS_CARR_ON) == 0 && (np->t_pflags & TP_CLOCAL) == 0
627 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_flags & CLOCAL) == 0
629 #endif /* NEW_CLOCAL */
631 || sc == NULL || tp != (struct tty *) sc->sc_devp) {
632 if (tp->t_oproc != NULL)
639 while (CCOUNT(&tp->t_outq) == 0) {
641 while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
644 * See if we have an existing packet partly sent.
645 * If not, get a new packet and start sending it.
650 * Get another packet to be sent.
659 * The extra PPP_FLAG will start up a new packet, and thus
660 * will flush any accumulated garbage. We do this whenever
661 * the line may have been idle for some time.
663 if (CCOUNT(&tp->t_outq) == 0) {
665 (void) putc(PPP_FLAG, &tp->t_outq);
668 /* Calculate the FCS for the first netbuf's worth. */
669 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), NB_SIZE(m));
670 sc->sc_outfcs ^= 0xffff;
672 cp = mtod(m, u_char *) + NB_SIZE(m);
673 NB_GROW_BOT(m, PPP_FCSLEN);
674 *cp++ = sc->sc_outfcs & 0xFF;
675 *cp++ = (sc->sc_outfcs >> 8) & 0xFF;
679 m->pktinfo.fourth.tv_sec = time.tv_sec;
680 m->pktinfo.fourth.tv_usec = time.tv_usec;
684 start = mtod(m, u_char *);
689 * Find out how many bytes in the string we can
690 * handle without doing something special.
692 for (cp = start; cp < stop; cp++)
700 * b_to_q returns the number of characters
703 * NetBSD (0.9 or later), 4.3-Reno or similar.
705 ndone = n - b_to_q(start, n, &tp->t_outq);
708 sc->sc_bytessent += ndone;
711 break; /* packet doesn't fit */
716 * If there are characters left in the netbuf,
717 * the first one must be special..
718 * Put it out in a different form.
721 if (putc(PPP_ESCAPE, &tp->t_outq))
723 if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
724 (void) unputc(&tp->t_outq);
727 sc->sc_bytessent += 2;
731 ++(m->pktinfo.async_esc);
736 * If we didn't empty this netbuf, remember where we're up to.
741 /* remember where we got to */
742 NB_SHRINK_TOP(m, start - mtod(m, u_char *));
743 break; /* can't do any more at the moment */
747 * Output trailing PPP flag and finish packet.
748 * We make the length zero in case the flag
749 * cannot be output immediately.
751 NB_SHRINK_TOP(m, NB_SIZE(m));
752 if (putc(PPP_FLAG, &tp->t_outq))
758 m->pktinfo.fifth.tv_sec = time.tv_sec;
759 m->pktinfo.fifth.tv_usec = time.tv_usec;
763 #if defined(NBPFILTER) && defined(NETBUF_PROXY)
766 * See if bpf wants to look at the packet. Gotta be careful
767 * here because BPF want the uncompressed packet. For now we
768 * stash a copy that we hand off. In the future, we may try
769 * to modify BPF to handle compressed packets instead.
771 * The BPF process point will not work for
772 * non-NETBUF_PROXY points. In this case, we hand the packet
773 * to BPF earlier in the process (see if_ppp.c).
778 bpf_tap(sc->sc_bpf, m, 0);
782 /* Finished with this netbuf; free it and move on. */
785 incr_cnt(sc->sc_if, if_opackets);
791 * If there is stuff in the output queue, send it now.
792 * We are being called in lieu of ttstart and must do what it would.
794 if (tp->t_oproc != NULL)
798 * This timeout is needed for operation on a pseudo-tty,
799 * because the pty code doesn't call pppstart after it has
800 * drained the t_outq.
802 if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
803 ns_timeout(ppp_timeout, (void *) sc, 1 * (1000000000L / HZ), CALLOUT_PRI_SOFTINT0);
804 sc->sc_flags |= SC_TIMEOUT;
811 * Timeout routine - try to start some more output.
817 struct ppp_softc *sc = (struct ppp_softc *) x;
818 struct tty *tp = (struct tty *) sc->sc_devp;
822 sc->sc_flags &= ~SC_TIMEOUT;
829 * Allocate enough netbuf to handle current MRU.
831 * Warning Will Robinson: pppgetm() can get called at interrupt-level!
835 register struct ppp_softc *sc;
841 * When the MRU is being changed, we could conceivably end up
842 * nuking a packet being received, but I doubt it, since the
843 * hand-shake is lock-step (ie. single packet).
845 if (sc->sc_m != NULL)
847 sc->sc_m = nbq_dequeue(&sc->sc_freeq);
852 * 4.3 says this is an unused function. However,
853 * it appears to be returning a NULL terminated string
854 * of several characters. My guess is that the serial
855 * driver is doing a little buffering so that we don't
856 * get burdend with interrupts.
858 * This function gets called when you use the NeXT
859 * supplied serial drivers. It does not get called
860 * with the MuX driver.
862 * In order to expedite the work done here, we
863 * handle most things here that don't require
864 * processing of a PPP_FLAG.
875 #ifndef OPTIMIZE_PPPREND
876 #warning PPPREND Not optimized!!!
877 while (n--) pppinput((u_char) *cp++, tp);
881 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
884 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
886 printf("Warning, bad softc structure at %s %d\n", __FILE__, __LINE__);
891 * We can handle FLUSHs, ESCAPES, and non PPP_FLAG characters
896 if (sc->sc_flags & SC_FLUSH)
900 if (*(cp++) == PPP_FLAG)
902 pppinput(PPP_FLAG, tp);
906 else if (sc->sc_flags & SC_LOG_FLUSH)
911 else if (sc->sc_ilen > 3 &&
912 (NB_SIZE(sc->sc_m) - sc->sc_ilen) > n &&
914 *cp != PPP_ESCAPE) /* Dont really handle escapes properly...should */
916 unsigned char* cp1 = cp;
917 if (sc->sc_flags & SC_ESCAPED)
919 sc->sc_flags &= ~SC_ESCAPED;
925 sc->sc_fcs = PPP_FCS(sc->sc_fcs, *(cp++));
926 if (sc->sc_flags & SC_LOG_RAWIN)
929 } while(--n && *cp != PPP_FLAG && *cp != PPP_ESCAPE);
932 bcopy(cp1, sc->sc_mp, (cp-cp1));
934 sc->sc_bytesrcvd += (cp - cp1);
935 sc->sc_ilen += (cp-cp1);
936 sc->sc_mp += (cp-cp1);
942 pppinput(*(cp++), tp);
946 #endif /* OPTIMIZE_PPPREND */
950 * tty interface receiver interrupt.
952 static const unsigned paritytab[8] = {
953 0x96696996, 0x69969669, 0x69969669, 0x96696996,
954 0x69969669, 0x96696996, 0x96696996, 0x69969669
960 register struct tty *tp;
962 register struct ppp_softc *sc;
966 sc = (struct ppp_softc *) tp->t_sc;
967 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
974 /* framing error or overrun on this char - abort packet */
975 IOLogDbg("ppp%d: bad char 0x%x\n", if_unit(sc->sc_if), c);
982 sc->sc_flags |= SC_RCV_B7_1;
984 sc->sc_flags |= SC_RCV_B7_0;
985 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
986 sc->sc_flags |= SC_RCV_ODDP;
988 sc->sc_flags |= SC_RCV_EVNP;
990 if (sc->sc_flags & SC_LOG_RAWIN)
995 if (sc->sc_ilen == 0)
1001 if (sc->sc_rawin_count > 0)
1006 * Each Control Escape octet is also
1007 * removed, and the following octet is exclusive-or'd with hexadecimal
1008 * 0x20, unless it is the Flag Sequence (which aborts a frame).
1010 * So, if SC_ESCAPED is set, then we've seen the packet
1011 * abort sequence "}~".
1013 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) ||
1014 ((ilen > 0) && (sc->sc_fcs != PPP_GOODFCS)))
1016 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
1017 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0)
1019 IOLog("ppp%d: bad fcs 0x%04x\n", if_unit(sc->sc_if), sc->sc_fcs);
1020 incr_cnt(sc->sc_if, if_ierrors);
1024 IOLog("ppp%d: bad packet flushed...\n", if_unit(sc->sc_if));
1025 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
1030 if (ilen < (PPP_HDRLEN + PPP_FCSLEN))
1034 IOLogDbg("ppp%d: too short (%d)\n", if_unit(sc->sc_if), ilen);
1035 incr_cnt(sc->sc_if, if_ierrors);
1036 sc->sc_flags |= SC_PKTLOST;
1042 sc->sc_m->pktinfo.second.tv_sec = time.tv_sec;
1043 sc->sc_m->pktinfo.second.tv_usec = time.tv_usec;
1044 sc->sc_m->pktinfo.size1 = ilen;
1048 * Remove FCS trailer. Set packet length...
1051 NB_SHRINK_BOT(sc->sc_m, NB_SIZE(sc->sc_m) - ilen);
1053 /* excise this netbuf */
1057 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
1058 sc->sc_flags &= ~SC_PKTLOST;
1064 if (sc->sc_flags & SC_FLUSH) {
1065 if (sc->sc_flags & SC_LOG_FLUSH)
1072 * On reception, prior to FCS computation, each octet with value less
1073 * than hexadecimal 0x20 is checked. If it is flagged in the receiving
1074 * ACCM, it is simply removed (it may have been inserted by intervening
1075 * data communications equipment). Each Control Escape octet is also
1076 * removed, and the following octet is exclusive-or'd with hexadecimal
1077 * 0x20, unless it is the Flag Sequence (which aborts a frame).
1079 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) {
1083 if (sc->sc_flags & SC_ESCAPED) {
1084 sc->sc_flags &= ~SC_ESCAPED;
1086 } else if (c == PPP_ESCAPE) {
1087 sc->sc_flags |= SC_ESCAPED;
1089 ++(sc->sc_m->pktinfo.async_esc);
1095 * Initialize buffer on first octet received.
1096 * First octet could be address or protocol (when compressing
1098 * Second octet is control.
1099 * Third octet is first or second (when compressing protocol)
1100 * octet of protocol.
1101 * Fourth octet is second octet of protocol.
1103 if (sc->sc_ilen == 0) {
1105 /* reset the input netbuf */
1106 if (sc->sc_m == NULL) {
1108 if (sc->sc_m == NULL) {
1110 * We schedule a call here as pppindrain will
1111 * not get scheduled and we need the free buffers
1113 IOLog("ppp%d: no input netbufs!\n", if_unit(sc->sc_if));
1114 (void)pppsched(pppfillfreeq, sc);
1119 sc->sc_mp = mtod(m, char *);
1120 sc->sc_fcs = PPP_INITFCS;
1123 m->pktinfo.first.tv_sec = time.tv_sec;
1124 m->pktinfo.first.tv_usec = time.tv_usec;
1125 m->pktinfo.flags |= NBFLAG_INCOMING;
1127 if (c != PPP_ALLSTATIONS) {
1128 if (sc->sc_flags & SC_REJ_COMP_AC) {
1129 IOLogDbg("ppp%d: garbage received: 0x%02x (need 0x%02x)\n",
1130 if_unit(sc->sc_if), c, PPP_ALLSTATIONS);
1133 *sc->sc_mp++ = PPP_ALLSTATIONS;
1134 *sc->sc_mp++ = PPP_UI;
1137 m->pktinfo.flags |= NBFLAG_AC;
1143 if (sc->sc_ilen == 1 && c != PPP_UI) {
1144 IOLogDbg("ppp%d: missing UI (0x%02x), got 0x%02x\n",
1145 if_unit(sc->sc_if), PPP_UI, c);
1149 if (sc->sc_ilen == 2 && (c & 1) == 1) {
1150 /* a compressed protocol */
1154 m->pktinfo.flags |= NBFLAG_PC;
1158 if (sc->sc_ilen == 3 && (c & 1) == 0) {
1159 IOLogDbg("ppp%d: bad protocol %x\n", if_unit(sc->sc_if),
1160 (sc->sc_mp[-1] << 8) + c);
1164 /* packet beyond configured mru? */
1165 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1166 IOLogDbg("ppp%d: packet too big (%d bytes)\n", if_unit(sc->sc_if),
1171 /* ilen was incremented above... */
1173 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1177 if (!(sc->sc_flags & SC_FLUSH)) {
1178 incr_cnt(sc->sc_if, if_ierrors);
1179 sc->sc_flags |= SC_FLUSH;
1180 if (sc->sc_flags & SC_LOG_FLUSH)
1187 install_ppp_ld(void)
1189 return tty_ld_install(PPPDISC, NORMAL_LDISC, pppopen,
1190 pppclose, pppread, pppwrite, ppptioctl,
1191 pppinput, ppprend, pppstart, ttymodem,
1195 #define MAX_DUMP_BYTES 128
1199 struct ppp_softc *sc;
1203 sc->sc_rawin[sc->sc_rawin_count++] = c;
1204 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1205 || c < 0 && sc->sc_rawin_count > 0) {
1206 IOLog("ppp%d input:\n", if_unit(sc->sc_if));
1207 pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
1208 sc->sc_rawin_count = 0;
1217 char buf[3*MAX_DUMP_BYTES+4];
1219 static char digits[] = "0123456789abcdef";
1222 if (bp >= buf + sizeof(buf) - 3) {
1226 *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
1227 *bp++ = digits[*b++ & 0xf];
1234 #endif /* NUM_PPP > 0 */