]> git.ozlabs.org Git - ppp.git/blob - ultrix/if_ppp.c
82d7d6c861a1d801ddc6dfc1c5c27d77d19c6571
[ppp.git] / ultrix / if_ppp.c
1 /*
2  * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver.
3  *
4  * Copyright (c) 1989 Carnegie Mellon University.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms are permitted
8  * provided that the above copyright notice and this paragraph are
9  * duplicated in all such forms and that any documentation,
10  * advertising materials, and other materials related to such
11  * distribution and use acknowledge that the software was developed
12  * by Carnegie Mellon University.  The name of the
13  * University may not be used to endorse or promote products derived
14  * from this software without specific prior written permission.
15  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18  *
19  * Drew D. Perkins
20  * Carnegie Mellon University
21  * 4910 Forbes Ave.
22  * Pittsburgh, PA 15213
23  * (412) 268-8576
24  * ddp@andrew.cmu.edu
25  *
26  * Based on:
27  *      @(#)if_sl.c     7.6.1.2 (Berkeley) 2/15/89
28  *
29  * Copyright (c) 1987 Regents of the University of California.
30  * All rights reserved.
31  *
32  * Redistribution and use in source and binary forms are permitted
33  * provided that the above copyright notice and this paragraph are
34  * duplicated in all such forms and that any documentation,
35  * advertising materials, and other materials related to such
36  * distribution and use acknowledge that the software was developed
37  * by the University of California, Berkeley.  The name of the
38  * University may not be used to endorse or promote products derived
39  * from this software without specific prior written permission.
40  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
41  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
42  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
43  *
44  * Serial Line interface
45  *
46  * Rick Adams
47  * Center for Seismic Studies
48  * 1300 N 17th Street, Suite 1450
49  * Arlington, Virginia 22209
50  * (703)276-7900
51  * rick@seismo.ARPA
52  * seismo!rick
53  *
54  * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
55  * Converted to 4.3BSD Beta by Chris Torek.
56  * Other changes made at Berkeley, based in part on code by Kirk Smith.
57  *
58  * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
59  * Added VJ tcp header compression; more unified ioctls
60  *
61  * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
62  * Cleaned up a lot of the mbuf-related code to fix bugs that
63  * caused system crashes and packet corruption.  Changed pppstart
64  * so that it doesn't just give up with a collision if the whole
65  * packet doesn't fit in the output ring buffer.
66  *
67  * Added priority queueing for interactive IP packets, following
68  * the model of if_sl.c, plus hooks for bpf.
69  * Paul Mackerras (paulus@cs.anu.edu.au).
70  *
71  * Ultrix port by Per Sundstrom <sundstrom@stkhlm.enet.dec.com>,
72  * Robert Olsson <robert@robur.slu.se> and Paul Mackerras.
73  */
74
75 /* $Id: if_ppp.c,v 1.1 1994/11/21 04:50:03 paulus Exp $ */
76 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
77
78 #include "ppp.h"
79 #if NPPP > 0
80
81 #define VJC
82 #define PPP_COMPRESS
83
84 #include "../h/param.h"
85 #include "../h/user.h"
86 #include "../h/proc.h"
87 #include "../h/mbuf.h"
88 #include "../h/buf.h"
89 #include "../h/socket.h"
90 #include "../h/ioctl.h"
91 #include "../h/file.h"
92 #include "../h/tty.h"
93 #include "../h/kernel.h"
94 #include "../h/conf.h"
95 #include "../h/uio.h"
96 #include "../h/systm.h"
97
98 #include "../net/net/if.h"
99 #include "../net/net/netisr.h"
100 #include "../net/net/route.h"
101 #if INET
102 #include "../net/netinet/in.h"
103 #include "../net/netinet/in_systm.h"
104 #include "../net/netinet/in_var.h"
105 #include "../net/netinet/ip.h"
106 #endif
107
108 #ifdef VJC
109 #include "slcompress.h"
110 #endif
111
112 #include "ppp_defs.h"
113 #include "if_ppp.h"
114 #include "if_pppvar.h"
115
116 #ifdef PPP_COMPRESS
117 #define PACKET  struct mbuf
118 #include "ppp-comp.h"
119 #endif
120
121 /*
122  * This is an Ultrix kernel, we've got clists.
123  */
124 #define CCOUNT(q)       ((q)->c_cc)
125
126 #define t_sc    T_LINEP
127 #define PPP_HIWAT       400     /* Don't start a new packet if HIWAT on que */
128
129 void    pppattach __P((void));
130 int     pppopen __P((dev_t dev, struct tty *tp));
131 int     pppclose __P((struct tty *tp, int flag));
132 int     pppread __P((struct tty *tp, struct uio *uio, int flag));
133 int     pppwrite __P((struct tty *tp, struct uio *uio, int flag));
134 int     ppptioctl __P((struct tty *tp, int cmd, caddr_t data, int flag,
135                        struct proc *));
136 int     pppoutput __P((struct ifnet *ifp, struct mbuf *m0,
137                        struct sockaddr *dst));
138 int     pppinput __P((int c, struct tty *tp));
139 int     pppioctl __P((struct ifnet *ifp, int cmd, caddr_t data));
140 int     pppstart __P((struct tty *tp));
141
142 static void     ppp_ccp_closed __P((struct ppp_softc *));
143 static int      ppp_ccp __P((struct ppp_softc *, struct mbuf *m, int rcvd));
144 static int      pppasyncstart __P((struct ppp_softc *));
145 static u_short  pppfcs __P((u_short fcs, u_char *cp, int len));
146 static int      pppgetm __P((struct ppp_softc *sc));
147 static void     pppdumpm __P((struct mbuf *m0, int pktlen));
148 static void     pppdumpb __P((u_char *b, int l));
149 static void     ppplogchar __P((struct ppp_softc *, int));
150
151 /*
152  * Some useful mbuf macros not in mbuf.h.
153  */
154 #define M_IS_CLUSTER(m) ((m)->m_off > MMAXOFF)
155
156 #define M_TRAILINGSPACE(m) \
157         ((M_IS_CLUSTER(m) ? (u_int)(m)->m_clptr + M_CLUSTERSZ : MSIZE) \
158          - ((m)->m_off + (m)->m_len))
159
160 #define M_OFFSTART(m)   \
161         (M_IS_CLUSTER(m) ? (u_int)(m)->m_clptr : MMINOFF)
162
163 #define M_DATASIZE(m)   \
164         (M_IS_CLUSTER(m) ? M_CLUSTERSZ : MLEN)
165
166 /*
167  * The following disgusting hack gets around the problem that IP TOS
168  * can't be set yet.  We want to put "interactive" traffic on a high
169  * priority queue.  To decide if traffic is interactive, we check that
170  * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control.
171  */
172 static u_short interactive_ports[8] = {
173         0,      513,    0,      0,
174         0,      21,     0,      23,
175 };
176 #define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p))
177
178 /*
179  * Does c need to be escaped?
180  */
181 #define ESCAPE_P(c)     (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
182
183 #ifdef PPP_COMPRESS
184 /*
185  * List of compressors we know about.
186  */
187
188 extern struct compressor ppp_bsd_compress;
189
190 struct compressor *ppp_compressors[] = {
191     &ppp_bsd_compress,
192     NULL
193 };
194 #endif /* PPP_COMPRESS */
195
196 /*
197  * Called from boot code to establish ppp interfaces.
198  */
199 void
200 pppattach()
201 {
202     register struct ppp_softc *sc;
203     register int i = 0;
204
205     for (sc = ppp_softc; i < NPPP; sc++) {
206         sc->sc_if.if_name = "ppp";
207         sc->sc_if.if_unit = i++;
208         sc->sc_if.if_mtu = PPP_MTU;
209         sc->sc_if.if_flags = IFF_POINTOPOINT;
210         sc->sc_if.if_type = IFT_PPP;
211         sc->sc_if.if_ioctl = pppioctl;
212         sc->sc_if.if_output = pppoutput;
213         sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
214         sc->sc_inq.ifq_maxlen = IFQ_MAXLEN;
215         sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN;
216         if_attach(&sc->sc_if);
217 #if NBPFILTER > 0
218         bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_PPP, PPP_HDRLEN);
219 #endif
220     }
221 }
222
223 /*
224  * Allocate a ppp interface unit and initialize it.
225  */
226 struct ppp_softc *
227 pppalloc(pid)
228     pid_t pid;
229 {
230     int nppp, i;
231     struct ppp_softc *sc;
232
233     for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
234         if (sc->sc_xfer == pid) {
235             sc->sc_xfer = 0;
236             break;
237         }
238     if (nppp >= NPPP)
239         for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
240             if (sc->sc_devp == NULL)
241                 break;
242     if (nppp >= NPPP)
243         return NULL;
244
245     sc->sc_flags = 0;
246     sc->sc_mru = PPP_MRU;
247 #ifdef VJC
248     sl_compress_init(&sc->sc_comp);
249 #endif
250 #ifdef PPP_COMPRESS
251     sc->sc_xc_state = NULL;
252     sc->sc_rc_state = NULL;
253 #endif /* PPP_COMPRESS */
254     for (i = 0; i < NUM_NP; ++i)
255         sc->sc_npmode[i] = NPMODE_ERROR;
256     sc->sc_if.if_flags |= IFF_RUNNING;
257
258     return sc;
259 }
260
261 /*
262  * Deallocate a ppp unit.
263  */
264 pppdealloc(sc)
265     struct ppp_softc *sc;
266 {
267     struct mbuf *m;
268
269     if_down(&sc->sc_if);
270     sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
271     sc->sc_devp = NULL;
272     sc->sc_xfer = 0;
273     for (;;) {
274         IF_DEQUEUE(&sc->sc_inq, m);
275         if (m == NULL)
276             break;
277         m_freem(m);
278     }
279     for (;;) {
280         IF_DEQUEUE(&sc->sc_fastq, m);
281         if (m == NULL)
282             break;
283         m_freem(m);
284     }
285 #ifdef PPP_COMPRESS
286     ppp_ccp_closed(sc);
287     sc->sc_xc_state = NULL;
288     sc->sc_rc_state = NULL;
289 #endif /* PPP_COMPRESS */
290 }
291     
292 /*
293  * Line specific open routine for async tty devices.
294  * Attach the given tty to the first available ppp unit.
295  */
296 /* ARGSUSED */
297 int
298 pppopen(dev, tp)
299     dev_t dev;
300     register struct tty *tp;
301 {
302     register struct ppp_softc *sc;
303     int error, s, i;
304     struct proc *p = u.u_procp;
305
306     if (!suser())
307         return EPERM;
308
309     if (tp->t_line == PPPDISC) {
310         sc = (struct ppp_softc *) tp->t_sc;
311         if (sc != NULL && sc->sc_devp == (void *) tp)
312             return (0);
313     }
314
315     if ((sc = pppalloc(p->p_pid)) == NULL)
316         return ENXIO;
317
318     if (sc->sc_outm != NULL) {
319         m_freem(sc->sc_outm);
320         sc->sc_outm = NULL;
321     }
322         
323     pppgetm(sc);
324
325     sc->sc_ilen = 0;
326     bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
327     sc->sc_asyncmap[0] = 0xffffffff;
328     sc->sc_asyncmap[3] = 0x60000000;
329     sc->sc_rasyncmap = 0;
330     sc->sc_devp = (void *) tp;
331     sc->sc_start = pppasyncstart;
332
333     tp->t_sc = (caddr_t) sc;
334     ttyflush(tp, FREAD | FWRITE);
335
336     return (0);
337 }
338
339 /*
340  * Line specific close routine.
341  * Detach the tty from the ppp unit.
342  * Mimics part of ttyclose().
343  */
344 int
345 pppclose(tp, flag)
346     struct tty *tp;
347     int flag;
348 {
349     register struct ppp_softc *sc;
350     struct mbuf *m;
351     int s;
352
353     ttywflush(tp);
354     s = splimp();               /* paranoid; splnet probably ok */
355     tp->t_line = 0;
356     sc = (struct ppp_softc *)tp->t_sc;
357     if (sc != NULL) {
358         tp->t_sc = NULL;
359         if (tp == (struct tty *) sc->sc_devp) {
360             m_freem(sc->sc_outm);
361             sc->sc_outm = NULL;
362             m_freem(sc->sc_m);
363             sc->sc_m = NULL;
364             pppdealloc(sc);
365         }
366     }
367     splx(s);
368     return 0;
369 }
370
371 /*
372  * Line specific (tty) read routine.
373  */
374 int
375 pppread(tp, uio, flag)
376     register struct tty *tp;
377     struct uio *uio;
378     int flag;
379 {
380     register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
381     struct mbuf *m, *m0;
382     register int s;
383     int error = 0;
384
385     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
386         return 0;               /* end of file */
387     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
388         return 0;
389     s = splimp();
390     while (sc->sc_inq.ifq_head == NULL && tp->t_line == PPPDISC) {
391         if (tp->t_state & (TS_ASYNC | TS_NBIO)) {
392             splx(s);
393             return (EWOULDBLOCK);
394         }
395         sleep((caddr_t) &tp->t_rawq, TTIPRI);
396     }
397     if (tp->t_line != PPPDISC) {
398         splx(s);
399         return (-1);
400     }
401
402     /* Pull place-holder byte out of canonical queue */
403     getc(&tp->t_canq);
404
405     /* Get the packet from the input queue */
406     IF_DEQUEUE(&sc->sc_inq, m0);
407     splx(s);
408
409     for (m = m0; m && uio->uio_resid; m = m->m_next)
410         if (error = uiomove(mtod(m, u_char *), m->m_len, UIO_READ, uio))
411             break;
412     m_freem(m0);
413     return (error);
414 }
415
416 /*
417  * Line specific (tty) write routine.
418  */
419 int
420 pppwrite(tp, uio, flag)
421     register struct tty *tp;
422     struct uio *uio;
423     int flag;
424 {
425     register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
426     struct mbuf *m, *m0, **mp, *p;
427     struct sockaddr dst;
428     int len, error;
429
430     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
431         return 0;               /* wrote 0 bytes */
432     if (tp->t_line != PPPDISC)
433         return (EINVAL);
434     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
435         return EIO;
436     if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
437         uio->uio_resid < PPP_HDRLEN)
438         return (EMSGSIZE);
439     for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
440         MGET(m, M_WAIT, MT_DATA);
441         if ((*mp = m) == NULL) {
442             m_freem(m0);
443             return (ENOBUFS);
444         }
445         if (uio->uio_resid >= CLBYTES / 2) {
446             MCLGET(m, p);
447         } else
448             m->m_len = MLEN;
449         len = MIN(m->m_len, uio->uio_resid);
450         if (error = uiomove(mtod(m, u_char *), len, UIO_WRITE, uio)) {
451             m_freem(m0);
452             return (error);
453         }
454         m->m_len = len;
455     }
456     dst.sa_family = AF_UNSPEC;
457     bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
458     m0->m_off += PPP_HDRLEN;
459     m0->m_len -= PPP_HDRLEN;
460     return (pppoutput(&sc->sc_if, m0, &dst));
461 }
462
463 /*
464  * Line specific (tty) ioctl routine.
465  * Provide a way to get the ppp unit number.
466  * This discipline requires that tty device drivers call
467  * the line specific l_ioctl routine from their ioctl routines.
468  */
469 /* ARGSUSED */
470 int
471 ppptioctl(tp, cmd, data, flag)
472     struct tty *tp;
473     caddr_t data;
474     int cmd, flag;
475 {
476     register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
477     struct proc *p = u.u_procp;
478     int s, error, flags, mru, nb, npx;
479     struct ppp_option_data *odp;
480     struct compressor **cp;
481     struct npioctl *npi;
482     u_char ccp_option[CCP_MAX_OPTION_LENGTH];
483
484     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
485         return -1;
486
487     switch (cmd) {
488     case FIONREAD:
489         *(int *)data = sc->sc_inq.ifq_len;
490         break;
491
492     case PPPIOCGUNIT:
493         *(int *)data = sc->sc_if.if_unit;
494         break;
495
496     case PPPIOCGFLAGS:
497         *(u_int *)data = sc->sc_flags;
498         break;
499
500     case PPPIOCSFLAGS:
501         if (!suser())
502             return EPERM;
503         flags = *(int *)data & SC_MASK;
504         s = splimp();
505         if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN))
506             ppp_ccp_closed(sc);
507         sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags;
508         splx(s);
509         break;
510
511     case PPPIOCSASYNCMAP:
512         if (!suser())
513             return EPERM;
514         sc->sc_asyncmap[0] = *(u_int *)data;
515         break;
516
517     case PPPIOCGASYNCMAP:
518         *(u_int *)data = sc->sc_asyncmap[0];
519         break;
520
521     case PPPIOCSRASYNCMAP:
522         if (!suser())
523             return EPERM;
524         sc->sc_rasyncmap = *(u_int *)data;
525         break;
526
527     case PPPIOCGRASYNCMAP:
528         *(u_int *)data = sc->sc_rasyncmap;
529         break;
530
531     case PPPIOCSXASYNCMAP:
532         if (!suser())
533             return EPERM;
534         bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
535         sc->sc_asyncmap[1] = 0;             /* mustn't escape 0x20 - 0x3f */
536         sc->sc_asyncmap[2] &= ~0x40000000;  /* mustn't escape 0x5e */
537         sc->sc_asyncmap[3] |= 0x60000000;   /* must escape 0x7d, 0x7e */
538         break;
539
540     case PPPIOCGXASYNCMAP:
541         bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
542         break;
543
544     case PPPIOCSMRU:
545         if (!suser())
546             return EPERM;
547         mru = *(int *)data;
548         if (mru >= PPP_MRU && mru <= PPP_MAXMRU) {
549             sc->sc_mru = mru;
550             pppgetm(sc);
551         }
552         break;
553
554     case PPPIOCGMRU:
555         *(int *)data = sc->sc_mru;
556         break;
557
558 #ifdef VJC
559     case PPPIOCSMAXCID:
560         if (!suser())
561             return EPERM;
562         sl_compress_setup(&sc->sc_comp, *(int *)data);
563         break;
564 #endif
565
566     case PPPIOCXFERUNIT:
567         if (!suser())
568             return EPERM;
569         sc->sc_xfer = p->p_pid;
570         break;
571
572 #ifdef PPP_COMPRESS
573     case PPPIOCSCOMPRESS:
574         if (!suser())
575             return EPERM;
576         odp = (struct ppp_option_data *) data;
577         nb = odp->length;
578         if (nb > sizeof(ccp_option))
579             nb = sizeof(ccp_option);
580         if (error = copyin(odp->ptr, ccp_option, nb))
581             return (error);
582         if (ccp_option[1] < 2)  /* preliminary check on the length byte */
583             return (EINVAL);
584         for (cp = ppp_compressors; *cp != NULL; ++cp)
585             if ((*cp)->compress_proto == ccp_option[0]) {
586                 /*
587                  * Found a handler for the protocol - try to allocate
588                  * a compressor or decompressor.
589                  */
590                 error = 0;
591                 s = splimp();
592                 if (odp->transmit) {
593                     if (sc->sc_xc_state != NULL)
594                         (*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
595                     sc->sc_xcomp = *cp;
596                     sc->sc_xc_state = (*cp)->comp_alloc(ccp_option, nb);
597                     if (sc->sc_xc_state == NULL) {
598                         if (sc->sc_flags & SC_DEBUG)
599                             printf("ppp%d: comp_alloc failed\n",
600                                sc->sc_if.if_unit);
601                         error = ENOBUFS;
602                     }
603                     sc->sc_flags &= ~SC_COMP_RUN;
604                 } else {
605                     if (sc->sc_rc_state != NULL)
606                         (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
607                     sc->sc_rcomp = *cp;
608                     sc->sc_rc_state = (*cp)->decomp_alloc(ccp_option, nb);
609                     if (sc->sc_rc_state == NULL) {
610                         if (sc->sc_flags & SC_DEBUG)
611                             printf("ppp%d: decomp_alloc failed\n",
612                                sc->sc_if.if_unit);
613                         error = ENOBUFS;
614                     }
615                     sc->sc_flags &= ~SC_DECOMP_RUN;
616                 }
617                 splx(s);
618                 return (error);
619             }
620         if (sc->sc_flags & SC_DEBUG)
621             printf("ppp%d: no compressor for [%x %x %x], %x\n",
622                    sc->sc_if.if_unit, ccp_option[0], ccp_option[1],
623                    ccp_option[2], nb);
624         return (EINVAL);        /* no handler found */
625 #endif /* PPP_COMPRESS */
626
627     case PPPIOCGNPMODE:
628     case PPPIOCSNPMODE:
629         npi = (struct npioctl *) data;
630         switch (npi->protocol) {
631         case PPP_IP:
632             npx = NP_IP;
633             break;
634         default:
635             return EINVAL;
636         }
637         if (cmd == PPPIOCGNPMODE) {
638             npi->mode = sc->sc_npmode[npx];
639         } else {
640             if (!suser())
641                 return EPERM;
642             if (npi->mode != sc->sc_npmode[npx]) {
643                 s = splimp();
644                 sc->sc_npmode[npx] = npi->mode;
645                 if (npi->mode != NPMODE_QUEUE)
646                     (*sc->sc_start)(sc);
647                 splx(s);
648             }
649         }
650         break;
651
652     default:
653         return (-1);
654     }
655     return (0);
656 }
657
658 /*
659  * FCS lookup table as calculated by genfcstab.
660  */
661 static u_short fcstab[256] = {
662         0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
663         0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
664         0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
665         0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
666         0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
667         0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
668         0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
669         0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
670         0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
671         0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
672         0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
673         0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
674         0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
675         0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
676         0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
677         0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
678         0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
679         0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
680         0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
681         0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
682         0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
683         0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
684         0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
685         0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
686         0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
687         0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
688         0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
689         0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
690         0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
691         0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
692         0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
693         0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
694 };
695
696 /*
697  * Calculate a new FCS given the current FCS and the new data.
698  */
699 static u_short
700 pppfcs(fcs, cp, len)
701     register u_short fcs;
702     register u_char *cp;
703     register int len;
704 {
705     while (len--)
706         fcs = PPP_FCS(fcs, *cp++);
707     return (fcs);
708 }
709
710 /*
711  * Queue a packet.  Start transmission if not active.
712  * Packet is placed in Information field of PPP frame.
713  */
714 int
715 pppoutput(ifp, m0, dst)
716     struct ifnet *ifp;
717     struct mbuf *m0;
718     struct sockaddr *dst;
719 {
720     register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
721     struct ppp_header *ph;
722     int protocol, address, control;
723     u_char *cp;
724     int s, error;
725     struct ip *ip;
726     struct ifqueue *ifq;
727     enum NPmode mode;
728
729     if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0
730         || (ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC) {
731         error = ENETDOWN;       /* sort of */
732         goto bad;
733     }
734
735     /*
736      * Compute PPP header.
737      */
738     ifq = &ifp->if_snd;
739     switch (dst->sa_family) {
740 #ifdef INET
741     case AF_INET:
742         address = PPP_ALLSTATIONS;
743         control = PPP_UI;
744         protocol = PPP_IP;
745         mode = sc->sc_npmode[NP_IP];
746         
747         /*
748          * If this is a TCP packet to or from an "interactive" port,
749          * put the packet on the fastq instead.
750          */
751         if ((ip = mtod(m0, struct ip *))->ip_p == IPPROTO_TCP) {
752             register int p = ntohl(((int *)ip)[ip->ip_hl]);
753             if (INTERACTIVE(p & 0xffff) || INTERACTIVE(p >> 16))
754                 ifq = &sc->sc_fastq;
755         }
756         break;
757 #endif
758     case AF_UNSPEC:
759         address = PPP_ADDRESS(dst->sa_data);
760         control = PPP_CONTROL(dst->sa_data);
761         protocol = PPP_PROTOCOL(dst->sa_data);
762         mode = NPMODE_PASS;
763         break;
764     default:
765         printf("ppp%d: af%d not supported\n", ifp->if_unit, dst->sa_family);
766         error = EAFNOSUPPORT;
767         goto bad;
768     }
769
770     /*
771      * Drop this packet, or return an error, if necessary.
772      */
773     if (mode == NPMODE_ERROR) {
774         error = ENETDOWN;
775         goto bad;
776     }
777     if (mode == NPMODE_DROP) {
778         error = 0;
779         goto bad;
780     }
781
782     /*
783      * Add PPP header.  If no space in first mbuf, allocate another.
784      */
785     if (M_IS_CLUSTER(m0) || m0->m_off < MMINOFF + PPP_HDRLEN) {
786         struct mbuf *m;
787
788         MGET(m, M_DONTWAIT, MT_DATA);
789         if (m == NULL) {
790             m_freem(m0);
791             return (ENOBUFS);
792         }
793         m->m_len = 0;
794         m->m_next = m0;
795         m0 = m;
796     } else
797         m0->m_off -= PPP_HDRLEN;
798
799     cp = mtod(m0, u_char *);
800     *cp++ = address;
801     *cp++ = control;
802     *cp++ = protocol >> 8;
803     *cp++ = protocol & 0xff;
804     m0->m_len += PPP_HDRLEN;
805
806     if (sc->sc_flags & SC_LOG_OUTPKT) {
807         printf("ppp%d output: ", ifp->if_unit);
808         pppdumpm(m0, -1);
809     }
810
811 #if NBPFILTER > 0
812     /*
813      * See if bpf wants to look at the packet.
814      */
815     if (sc->sc_bpf)
816         bpf_mtap(sc->sc_bpf, m0);
817 #endif
818
819     /*
820      * Put the packet on the appropriate queue.
821      */
822     s = splimp();
823     if (IF_QFULL(ifq)) {
824         IF_DROP(ifq);
825         splx(s);
826         sc->sc_if.if_oerrors++;
827         error = ENOBUFS;
828         goto bad;
829     }
830     IF_ENQUEUE(ifq, m0);
831
832     /*
833      * Tell the device to send it out.
834      */
835     if (mode == NPMODE_PASS)
836         (*sc->sc_start)(sc);
837
838     splx(s);
839     return (0);
840
841 bad:
842     m_freem(m0);
843     return (error);
844 }
845
846 /*
847  * Grab another packet off a queue and apply VJ compression,
848  * packet compression, address/control and/or protocol compression
849  * if enabled.
850  */
851 struct mbuf *
852 ppp_dequeue(sc)
853     struct ppp_softc *sc;
854 {
855     int s;
856     struct mbuf *m, *mp, **mpp;
857     u_char *cp;
858     int address, control, protocol;
859     struct ifqueue *ifq;
860     enum NPmode mode;
861
862     s = splimp();
863
864     /*
865      * Scan through the send queues looking for a packet
866      * which can be sent: first the fast queue, then the normal queue.
867      */
868     ifq = &sc->sc_fastq;
869     for (;;) {
870         mpp = &ifq->ifq_head;
871         mp = NULL;
872         while ((m = *mpp) != NULL) {
873             switch (PPP_PROTOCOL(mtod(m, u_char *))) {
874             case PPP_IP:
875                 mode = sc->sc_npmode[NP_IP];
876                 break;
877             default:
878                 mode = NPMODE_PASS;
879             }
880             if (mode == NPMODE_PASS)
881                 break;
882             switch (mode) {
883             case NPMODE_DROP:
884             case NPMODE_ERROR:
885                 *mpp = m->m_nextpkt;
886                 m_freem(m);
887                 break;
888             case NPMODE_QUEUE:
889                 mpp = &m->m_nextpkt;
890                 mp = m;
891                 break;
892             }
893         }
894         if (m != NULL)
895             break;
896
897         if (ifq == &sc->sc_if.if_snd)
898             break;
899         /* Finished the fast queue; do the normal queue. */
900         ifq = &sc->sc_if.if_snd;
901     }
902
903     if (m == NULL) {
904         splx(s);
905         return NULL;
906     }
907
908     if ((*mpp = m->m_nextpkt) == NULL)
909         ifq->ifq_tail = mp;
910     m->m_nextpkt = NULL;
911     --ifq->ifq_len;
912
913     splx(s);
914
915     /*
916      * Extract the ppp header of the new packet.
917      * The ppp header will be in one mbuf.
918      */
919     cp = mtod(m, u_char *);
920     address = PPP_ADDRESS(cp);
921     control = PPP_CONTROL(cp);
922     protocol = PPP_PROTOCOL(cp);
923
924     switch (protocol) {
925 #ifdef VJC
926     case PPP_IP:
927         /*
928          * If the packet is a TCP/IP packet, see if we can compress it.
929          */
930         if (sc->sc_flags & SC_COMP_TCP) {
931             struct ip *ip;
932             int type;
933
934             mp = m;
935             ip = (struct ip *) (cp + PPP_HDRLEN);
936             if (mp->m_len <= PPP_HDRLEN) {
937                 mp = mp->m_next;
938                 if (mp == NULL)
939                     break;
940                 ip = mtod(mp, struct ip *);
941             }
942             /* this code assumes the IP/TCP header is in one non-shared mbuf */
943             if (ip->ip_p == IPPROTO_TCP) {
944                 type = sl_compress_tcp(mp, ip, &sc->sc_comp,
945                                        !(sc->sc_flags & SC_NO_TCP_CCID));
946                 switch (type) {
947                 case TYPE_UNCOMPRESSED_TCP:
948                     protocol = PPP_VJC_UNCOMP;
949                     break;
950                 case TYPE_COMPRESSED_TCP:
951                     protocol = PPP_VJC_COMP;
952                     cp = mtod(m, u_char *);
953                     cp[0] = address;    /* header has moved */
954                     cp[1] = control;
955                     cp[2] = 0;
956                     break;
957                 }
958                 cp[3] = protocol;       /* update protocol in PPP header */
959             }
960         }
961         break;
962 #endif  /* VJC */
963
964 #ifdef PPP_COMPRESS
965     case PPP_CCP:
966         ppp_ccp(sc, m, 0);
967         break;
968 #endif  /* PPP_COMPRESS */
969     }
970
971 #ifdef PPP_COMPRESS
972     if (protocol != PPP_LCP && protocol != PPP_CCP
973         && sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) {
974         struct mbuf *mcomp;
975         int slen, clen;
976
977         slen = 0;
978         for (mp = m; mp != NULL; mp = mp->m_next)
979             slen += mp->m_len;
980         clen = (*sc->sc_xcomp->compress)
981             (sc->sc_xc_state, &mcomp, m, slen,
982              (sc->sc_flags & SC_CCP_UP? sc->sc_if.if_mtu: 0));
983         if (mcomp != NULL) {
984             m_freem(m);
985             m = mcomp;
986             cp = mtod(m, u_char *);
987             protocol = cp[3];
988         }
989     }
990 #endif  /* PPP_COMPRESS */
991
992     /*
993      * Compress the address/control and protocol, if possible.
994      */
995     if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS &&
996         control == PPP_UI && protocol != PPP_ALLSTATIONS &&
997         protocol != PPP_LCP) {
998         /* can compress address/control */
999         m->m_off += 2;
1000         m->m_len -= 2;
1001     }
1002     if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) {
1003         /* can compress protocol */
1004         if (mtod(m, u_char *) == cp) {
1005             cp[2] = cp[1];      /* move address/control up */
1006             cp[1] = cp[0];
1007         }
1008         ++m->m_off;
1009         --m->m_len;
1010     }
1011
1012     return m;
1013 }
1014
1015 #ifdef PPP_COMPRESS
1016 /*
1017  * Handle a CCP packet.  `rcvd' is 1 if the packet was received,
1018  * 0 if it is about to be transmitted.
1019  */
1020 static int
1021 ppp_ccp(sc, m, rcvd)
1022     struct ppp_softc *sc;
1023     struct mbuf *m;
1024     int rcvd;
1025 {
1026     u_char *dp, *ep;
1027     struct mbuf *mp;
1028     int slen;
1029     struct bsd_db *db;
1030
1031     /*
1032      * Get a pointer to the data after the PPP header.
1033      */
1034     if (m->m_len <= PPP_HDRLEN) {
1035         mp = m->m_next;
1036         if (mp == NULL)
1037             return;
1038         dp = (mp != NULL)? mtod(mp, u_char *): NULL;
1039     } else {
1040         mp = m;
1041         dp = mtod(mp, u_char *) + PPP_HDRLEN;
1042     }
1043
1044     ep = mtod(mp, u_char *) + mp->m_len;
1045     if (dp + CCP_HDRLEN > ep)
1046         return;
1047     slen = CCP_LENGTH(dp);
1048     if (dp + slen > ep) {
1049         if (sc->sc_flags & SC_DEBUG)
1050             printf("if_ppp/ccp: not enough data in mbuf (%x+%x > %x+%x)\n",
1051                    dp, slen, mtod(mp, u_char *), mp->m_len);
1052         return;
1053     }
1054
1055     switch (CCP_CODE(dp)) {
1056     case CCP_CONFREQ:
1057     case CCP_TERMREQ:
1058     case CCP_TERMACK:
1059         /* CCP must be going down - disable compression */
1060         if (sc->sc_flags & SC_CCP_UP)
1061             sc->sc_flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN);
1062         break;
1063
1064     case CCP_CONFACK:
1065         if (sc->sc_flags & SC_CCP_OPEN && !(sc->sc_flags & SC_CCP_UP)
1066             && slen >= CCP_HDRLEN + CCP_OPT_MINLEN
1067             && slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) {
1068             if (!rcvd) {
1069                 /* we're agreeing to send compressed packets. */
1070                 if (sc->sc_xc_state != NULL
1071                     && (*sc->sc_xcomp->comp_init)
1072                         (sc->sc_xc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN,
1073                          sc->sc_if.if_unit, sc->sc_flags & SC_DEBUG)) {
1074                     sc->sc_flags |= SC_COMP_RUN;
1075                 }
1076             } else {
1077                 /* peer is agreeing to send compressed packets. */
1078                 if (sc->sc_rc_state != NULL
1079                     && (*sc->sc_rcomp->decomp_init)
1080                         (sc->sc_rc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN,
1081                          sc->sc_if.if_unit, sc->sc_mru,
1082                          sc->sc_flags & SC_DEBUG)) {
1083                     sc->sc_flags |= SC_DECOMP_RUN;
1084                     sc->sc_flags &= ~(SC_DC_ERROR | SC_DC_FERROR);
1085                 }
1086             }
1087         }
1088         break;
1089
1090     case CCP_RESETACK:
1091         if (sc->sc_flags & SC_CCP_UP) {
1092             if (!rcvd) {
1093                 if (sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN))
1094                     (*sc->sc_xcomp->comp_reset)(sc->sc_xc_state);
1095             } else {
1096                 if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) {
1097                     (*sc->sc_rcomp->decomp_reset)(sc->sc_rc_state);
1098                     sc->sc_flags &= ~SC_DC_ERROR;
1099                 }
1100             }
1101         }
1102         break;
1103     }
1104 }
1105
1106 /*
1107  * CCP is down; free (de)compressor state if necessary.
1108  */
1109 void
1110 ppp_ccp_closed(sc)
1111     struct ppp_softc *sc;
1112 {
1113     if (sc->sc_xc_state) {
1114         (*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
1115         sc->sc_xc_state = NULL;
1116     }
1117     if (sc->sc_rc_state) {
1118         (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
1119         sc->sc_rc_state = NULL;
1120     }
1121 }
1122 #endif /* PPP_COMRPESS */
1123
1124 /*
1125  * This gets called from pppoutput when a new packet is
1126  * put on a queue.
1127  */
1128 static
1129 pppasyncstart(sc)
1130     register struct ppp_softc *sc;
1131 {
1132     register struct tty *tp = (struct tty *) sc->sc_devp;
1133
1134     pppstart(tp);
1135 }
1136
1137 /*
1138  * Start output on async tty interface.  Get another datagram
1139  * to send from the interface queue and start sending it.
1140  */
1141 int
1142 pppstart(tp)
1143     register struct tty *tp;
1144 {
1145     register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
1146     register struct mbuf *m;
1147     register int len;
1148     register u_char *start, *stop, *cp;
1149     int n, s, ndone, done;
1150     struct mbuf *m2;
1151
1152     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) {
1153         /* sorry, I can't talk now */
1154         return;
1155     }
1156     if (sc == NULL || tp != (struct tty *) sc->sc_devp) {
1157         (*tp->t_oproc)(tp);
1158         return;
1159     }
1160
1161     for (;;) {
1162         /*
1163          * If there is more in the output queue, just send it now.
1164          * We are being called in lieu of ttstart and must do what
1165          * it would.
1166          */
1167         if (CCOUNT(&tp->t_outq) != 0 && tp->t_oproc != NULL) {
1168             (*tp->t_oproc)(tp);
1169             if (CCOUNT(&tp->t_outq) > PPP_HIWAT)
1170                 return;
1171         }
1172
1173         /*
1174          * See if we have an existing packet partly sent.
1175          * If not, get a new packet and start sending it.
1176          */
1177         m = sc->sc_outm;
1178         if (m == NULL) {
1179             /*
1180              * Get another packet to be sent.
1181              */
1182             m = ppp_dequeue(sc);
1183             if (m == NULL)
1184                 return;
1185
1186             /*
1187              * The extra PPP_FLAG will start up a new packet, and thus
1188              * will flush any accumulated garbage.  We do this whenever
1189              * the line may have been idle for some time.
1190              */
1191             if (CCOUNT(&tp->t_outq) == 0) {
1192                 ++sc->sc_bytessent;
1193                 (void) putc(PPP_FLAG, &tp->t_outq);
1194             }
1195
1196             /* Calculate the FCS for the first mbuf's worth. */
1197             sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
1198         }
1199
1200         for (;;) {
1201             start = mtod(m, u_char *);
1202             len = m->m_len;
1203             stop = start + len;
1204             while (len > 0) {
1205                 /*
1206                  * Find out how many bytes in the string we can
1207                  * handle without doing something special.
1208                  */
1209                 for (cp = start; cp < stop; cp++)
1210                     if (ESCAPE_P(*cp))
1211                         break;
1212                 n = cp - start;
1213                 if (n) {
1214                     ndone = n - b_to_q(start, n, &tp->t_outq);
1215                     len -= ndone;
1216                     start += ndone;
1217                     sc->sc_bytessent += ndone;
1218
1219                     if (ndone < n)
1220                         break;  /* packet doesn't fit */
1221                 }
1222                 /*
1223                  * If there are characters left in the mbuf,
1224                  * the first one must be special..
1225                  * Put it out in a different form.
1226                  */
1227                 if (len) {
1228                     if (putc(PPP_ESCAPE, &tp->t_outq))
1229                         break;
1230                     if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
1231                         (void) unputc(&tp->t_outq);
1232                         break;
1233                     }
1234                     sc->sc_bytessent += 2;
1235                     start++;
1236                     len--;
1237                 }
1238             }
1239             /*
1240              * If we didn't empty this mbuf, remember where we're up to.
1241              * If we emptied the last mbuf, try to add the FCS and closing
1242              * flag, and if we can't, leave sc_outm pointing to m, but with
1243              * m->m_len == 0, to remind us to output the FCS and flag later.
1244              */
1245             done = len == 0;
1246             if (done && m->m_next == NULL) {
1247                 u_char *p, *q;
1248                 int c;
1249                 u_char endseq[8];
1250
1251                 /*
1252                  * We may have to escape the bytes in the FCS.
1253                  */
1254                 p = endseq;
1255                 c = ~sc->sc_outfcs & 0xFF;
1256                 if (ESCAPE_P(c)) {
1257                     *p++ = PPP_ESCAPE;
1258                     *p++ = c ^ PPP_TRANS;
1259                 } else
1260                     *p++ = c;
1261                 c = (~sc->sc_outfcs >> 8) & 0xFF;
1262                 if (ESCAPE_P(c)) {
1263                     *p++ = PPP_ESCAPE;
1264                     *p++ = c ^ PPP_TRANS;
1265                 } else
1266                     *p++ = c;
1267                 *p++ = PPP_FLAG;
1268
1269                 /*
1270                  * Try to output the FCS and flag.  If the bytes
1271                  * don't all fit, back out.
1272                  */
1273                 for (q = endseq; q < p; ++q)
1274                     if (putc(*q, &tp->t_outq)) {
1275                         done = 0;
1276                         for (; q > endseq; --q)
1277                             unputc(&tp->t_outq);
1278                         break;
1279                     }
1280             }
1281
1282             if (!done) {
1283                 m->m_off += m->m_len - len;
1284                 m->m_len = len;
1285                 sc->sc_outm = m;
1286                 if (tp->t_oproc != NULL)
1287                     (*tp->t_oproc)(tp);
1288                 return;         /* can't do any more at the moment */
1289             }
1290
1291             /* Finished with this mbuf; free it and move on. */
1292             MFREE(m, m2);
1293             if (m2 == NULL)
1294                 break;
1295
1296             m = m2;
1297             sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
1298         }
1299
1300         /* Finished a packet */
1301         sc->sc_outm = NULL;
1302         sc->sc_bytessent++;     /* account for closing flag */
1303         sc->sc_if.if_opackets++;
1304     }
1305 }
1306
1307 /*
1308  * Allocate enough mbuf to handle current MRU.
1309  */
1310 static int
1311 pppgetm(sc)
1312     register struct ppp_softc *sc;
1313 {
1314     struct mbuf *m, **mp, *p;
1315     int len;
1316     int s;
1317
1318     s = splimp();
1319     mp = &sc->sc_m;
1320     for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
1321         if ((m = *mp) == NULL) {
1322             MGET(m, M_DONTWAIT, MT_DATA);
1323             if (m == NULL)
1324                 break;
1325             *mp = m;
1326             MCLGET(m, p);
1327         }
1328         len -= M_DATASIZE(m);
1329         mp = &m->m_next;
1330     }
1331     splx(s);
1332     return len <= 0;
1333 }
1334
1335 /*
1336  * PPP packet input routine.
1337  * The caller has checked and removed the FCS and has inserted
1338  * the address/control bytes and the protocol high byte if they
1339  * were omitted.  The return value is 1 if the packet was put on
1340  * sc->sc_inq, 0 otherwise.
1341  */
1342 #define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \
1343                          TYPE_UNCOMPRESSED_TCP)
1344
1345 int
1346 ppppktin(sc, m)
1347     struct ppp_softc *sc;
1348     struct mbuf *m;
1349 {
1350     struct ifqueue *inq, *lock;
1351     int s, ilen, xlen, proto, rv;
1352     u_char *cp, adrs, ctrl;
1353     struct mbuf *mp, *dmp, *pc;
1354     u_char *iphdr;
1355     u_int hlen;
1356
1357     sc->sc_if.if_ipackets++;
1358     rv = 0;
1359
1360     cp = mtod(m, u_char *);
1361     adrs = PPP_ADDRESS(cp);
1362     ctrl = PPP_CONTROL(cp);
1363     proto = PPP_PROTOCOL(cp);
1364
1365 #ifdef PPP_COMPRESS
1366     /*
1367      * Decompress this packet if necessary, update the receiver's
1368      * dictionary, or take appropriate action on a CCP packet.
1369      */
1370     if (proto == PPP_COMP && sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)
1371         && !(sc->sc_flags & SC_DC_ERROR) && !(sc->sc_flags & SC_DC_FERROR)) {
1372         /* decompress this packet */
1373         rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp);
1374         if (dmp != NULL) {
1375             m_freem(m);
1376             m = dmp;
1377             cp = mtod(m, u_char *);
1378             proto = PPP_PROTOCOL(cp);
1379
1380         } else {
1381             /* pass the compressed packet up to pppd, which may take
1382                CCP down or issue a Reset-Req. */
1383             if (sc->sc_flags & SC_DEBUG)
1384                 printf("ppp%d: decompress failed %d\n", sc->sc_if.if_unit, rv);
1385             sc->sc_flags |= SC_VJ_RESET;
1386             switch (rv) {
1387             case DECOMP_OK:
1388                 /* no error, but no decompressed packet produced */
1389                 m_freem(m);
1390                 return 0;
1391             case DECOMP_ERROR:
1392                 sc->sc_flags |= SC_DC_ERROR;
1393                 break;
1394             case DECOMP_FATALERROR:
1395                 sc->sc_flags |= SC_DC_FERROR;
1396                 break;
1397             }
1398         }
1399
1400     } else {
1401         if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) {
1402             (*sc->sc_rcomp->incomp)(sc->sc_rc_state, m);
1403         }
1404         if (proto == PPP_CCP) {
1405             ppp_ccp(sc, m, 1);
1406         }
1407     }
1408 #endif
1409
1410     ilen = 0;
1411     for (mp = m; mp != NULL; mp = mp->m_next)
1412         ilen += mp->m_len;
1413
1414 #ifdef VJC
1415     /*
1416      * If we've missed a packet, we must toss subsequent compressed
1417      * packets which don't have an explicit connection ID.
1418      */
1419     if (sc->sc_flags & SC_VJ_RESET) {
1420         sl_uncompress_tcp(NULL, 0, TYPE_ERROR, &sc->sc_comp);
1421         sc->sc_flags &= ~SC_VJ_RESET;
1422     }
1423
1424     /*
1425      * See if we have a VJ-compressed packet to uncompress.
1426      */
1427     if (proto == PPP_VJC_COMP) {
1428         if (sc->sc_flags & SC_REJ_COMP_TCP)
1429             goto bad;
1430
1431         xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN,
1432                                       ilen - PPP_HDRLEN, TYPE_COMPRESSED_TCP,
1433                                       &sc->sc_comp, &iphdr, &hlen);
1434
1435         if (xlen <= 0) {
1436             if (sc->sc_flags & SC_DEBUG)
1437                 printf("ppp%d: VJ uncompress failed on type comp\n",
1438                         sc->sc_if.if_unit);
1439             goto bad;
1440         }
1441
1442         /* Copy the PPP and IP headers into a new mbuf. */
1443         MGET(mp, M_DONTWAIT, MT_DATA);
1444         if (mp == NULL)
1445             goto bad;
1446         mp->m_len = 0;
1447         mp->m_next = NULL;
1448         if (hlen + PPP_HDRLEN > MHLEN) {
1449             MCLGET(mp, pc);
1450             if (M_TRAILINGSPACE(mp) < hlen + PPP_HDRLEN) {
1451                 m_freem(mp);
1452                 goto bad;       /* lose if big headers and no clusters */
1453             }
1454         }
1455         cp = mtod(mp, u_char *);
1456         cp[0] = adrs;
1457         cp[1] = ctrl;
1458         cp[2] = 0;
1459         cp[3] = PPP_IP;
1460         proto = PPP_IP;
1461         bcopy(iphdr, cp + PPP_HDRLEN, hlen);
1462         mp->m_len = hlen + PPP_HDRLEN;
1463
1464         /*
1465          * Trim the PPP and VJ headers off the old mbuf
1466          * and stick the new and old mbufs together.
1467          */
1468         m->m_off += PPP_HDRLEN + xlen;
1469         m->m_len -= PPP_HDRLEN + xlen;
1470         if (m->m_len <= M_TRAILINGSPACE(mp)) {
1471             bcopy(mtod(m, u_char *), mtod(mp, u_char *) + mp->m_len, m->m_len);
1472             mp->m_len += m->m_len;
1473             MFREE(m, mp->m_next);
1474         } else
1475             mp->m_next = m;
1476         m = mp;
1477         ilen += hlen - xlen;
1478
1479     } else if (proto == PPP_VJC_UNCOMP) {
1480         if (sc->sc_flags & SC_REJ_COMP_TCP)
1481             goto bad;
1482
1483         xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN,
1484                                       ilen - PPP_HDRLEN, TYPE_UNCOMPRESSED_TCP,
1485                                       &sc->sc_comp, &iphdr, &hlen);
1486
1487         if (xlen < 0) {
1488             if (sc->sc_flags & SC_DEBUG)
1489                 printf("ppp%d: VJ uncompress failed on type uncomp\n",
1490                         sc->sc_if.if_unit);
1491             goto bad;
1492         }
1493
1494         proto = PPP_IP;
1495         cp[3] = PPP_IP;
1496     }
1497 #endif /* VJC */
1498
1499     /*
1500      * If the packet will fit in an ordinary mbuf, don't waste a
1501      * whole cluster on it.
1502      */
1503     if (ilen <= MLEN && M_IS_CLUSTER(m)) {
1504         MGET(mp, M_DONTWAIT, MT_DATA);
1505         if (mp != NULL) {
1506             m_copydata(m, 0, ilen, mtod(mp, caddr_t));
1507             m_freem(m);
1508             m = mp;
1509             m->m_len = ilen;
1510         }
1511     }
1512
1513 #if NBPFILTER > 0
1514     /* See if bpf wants to look at the packet. */
1515     if (sc->sc_bpf)
1516         bpf_mtap(sc->sc_bpf, m);
1517 #endif
1518
1519     switch (proto) {
1520 #ifdef INET
1521     case PPP_IP:
1522         /*
1523          * IP packet - take off the ppp header and pass it up to IP.
1524          */
1525         if ((sc->sc_if.if_flags & IFF_UP) == 0
1526             || sc->sc_npmode[NP_IP] != NPMODE_PASS) {
1527             /* interface is down - drop the packet. */
1528             m_freem(m);
1529             return 0;
1530         }
1531         m->m_off += PPP_HDRLEN;
1532         m->m_len -= PPP_HDRLEN;
1533         schednetisr(NETISR_IP);
1534         inq = &ipintrq;
1535         break;
1536 #endif
1537
1538     default:
1539         /*
1540          * Some other protocol - place on input queue for read().
1541          */
1542         inq = &sc->sc_inq;
1543         rv = 1;
1544         break;
1545     }
1546
1547     /*
1548      * Put the packet on the appropriate input queue.
1549      */
1550     s = splimp();
1551     lock = inq;
1552     smp_lock(&lock->lk_ifqueue, LK_RETRY);
1553     if (IF_QFULL(inq)) {
1554         IF_DROP(inq);
1555         /* XXX should we unlock here? */
1556         if (sc->sc_flags & SC_DEBUG)
1557             printf("ppp%d: queue full\n", sc->sc_if.if_unit);
1558         sc->sc_if.if_ierrors++;
1559         m_freem(m);
1560         rv = 0;
1561     } else {
1562         IF_ENQUEUEIF(inq, m, &sc->sc_if);
1563         smp_unlock(&lock->lk_ifqueue);
1564     }
1565
1566     splx(s);
1567     return rv;
1568
1569  bad:
1570     m_freem(m);
1571     sc->sc_if.if_ierrors++;
1572     return 0;
1573 }
1574
1575 /*
1576  * tty interface receiver interrupt.
1577  */
1578 static unsigned paritytab[8] = {
1579     0x96696996, 0x69969669, 0x69969669, 0x96696996,
1580     0x69969669, 0x96696996, 0x96696996, 0x69969669
1581 };
1582
1583 int
1584 pppinput(c, tp)
1585     int c;
1586     register struct tty *tp;
1587 {
1588     register struct ppp_softc *sc;
1589     struct mbuf *m;
1590     int ilen;
1591
1592     tk_nin++;
1593     sc = (struct ppp_softc *) tp->t_sc;
1594     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
1595         return;
1596
1597     sc->sc_bytesrcvd++;
1598
1599     c &= 0xff;
1600
1601     if (c & 0x80)
1602         sc->sc_flags |= SC_RCV_B7_1;
1603     else
1604         sc->sc_flags |= SC_RCV_B7_0;
1605     if (paritytab[c >> 5] & (1 << (c & 0x1F)))
1606         sc->sc_flags |= SC_RCV_ODDP;
1607     else
1608         sc->sc_flags |= SC_RCV_EVNP;
1609
1610     if (sc->sc_flags & SC_LOG_RAWIN)
1611         ppplogchar(sc, c);
1612
1613     if (c == PPP_FLAG) {
1614         ilen = sc->sc_ilen;
1615         sc->sc_ilen = 0;
1616
1617         if (sc->sc_rawin_count > 0) 
1618             ppplogchar(sc, -1);
1619
1620         /*
1621          * If SC_ESCAPED is set, then we've seen the packet
1622          * abort sequence "}~".
1623          */
1624         if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
1625             || ilen > 0 && sc->sc_fcs != PPP_GOODFCS) {
1626             sc->sc_flags |= SC_VJ_RESET;
1627             if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
1628                 if (sc->sc_flags & SC_DEBUG)
1629                     printf("ppp%d: bad fcs %x\n", sc->sc_if.if_unit,
1630                            sc->sc_fcs);
1631                 sc->sc_if.if_ierrors++;
1632             } else
1633                 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
1634             return;
1635         }
1636
1637         if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
1638             if (ilen) {
1639                 if (sc->sc_flags & SC_DEBUG)
1640                     printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
1641                 sc->sc_if.if_ierrors++;
1642             }
1643             return;
1644         }
1645
1646         /*
1647          * Remove FCS trailer.  Somewhat painful...
1648          */
1649         ilen -= 2;
1650         if (--sc->sc_mc->m_len == 0) {
1651             for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
1652                 ;
1653             sc->sc_mc = m;
1654         }
1655         sc->sc_mc->m_len--;
1656
1657         /* excise this mbuf chain */
1658         m = sc->sc_m;
1659         sc->sc_m = sc->sc_mc->m_next;
1660         sc->sc_mc->m_next = NULL;
1661
1662         if (sc->sc_flags & SC_LOG_INPKT) {
1663             printf("ppp%d: got %d bytes\n", sc->sc_if.if_unit, ilen);
1664             pppdumpm(m, ilen);
1665         }
1666
1667         if (ppppktin(sc, m)) {
1668             /* Put a placeholder byte in canq for ttselect()/ttnread(). */
1669             putc(0, &tp->t_canq);
1670             ttwakeup(tp);
1671         }
1672
1673         pppgetm(sc);
1674         return;
1675     }
1676
1677     if (sc->sc_flags & SC_FLUSH) {
1678         if (sc->sc_flags & SC_LOG_FLUSH)
1679             ppplogchar(sc, c);
1680         return;
1681     }
1682
1683     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
1684         return;
1685
1686     if (sc->sc_flags & SC_ESCAPED) {
1687         sc->sc_flags &= ~SC_ESCAPED;
1688         c ^= PPP_TRANS;
1689     } else if (c == PPP_ESCAPE) {
1690         sc->sc_flags |= SC_ESCAPED;
1691         return;
1692     }
1693
1694     /*
1695      * Initialize buffer on first octet received.
1696      * First octet could be address or protocol (when compressing
1697      * address/control).
1698      * Second octet is control.
1699      * Third octet is first or second (when compressing protocol)
1700      * octet of protocol.
1701      * Fourth octet is second octet of protocol.
1702      */
1703     if (sc->sc_ilen == 0) {
1704         /* reset the first input mbuf */
1705         if (sc->sc_m == NULL) {
1706             pppgetm(sc);
1707             if (sc->sc_m == NULL) {
1708                 if (sc->sc_flags & SC_DEBUG)
1709                     printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
1710                 goto flush;
1711             }
1712         }
1713         m = sc->sc_m;
1714         m->m_len = 0;
1715         m->m_off = M_OFFSTART(m);
1716         sc->sc_mc = m;
1717         sc->sc_mp = mtod(m, char *);
1718         sc->sc_fcs = PPP_INITFCS;
1719         if (c != PPP_ALLSTATIONS) {
1720             if (sc->sc_flags & SC_REJ_COMP_AC) {
1721                 if (sc->sc_flags & SC_DEBUG)
1722                     printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
1723                            sc->sc_if.if_unit, c);
1724                 goto flush;
1725             }
1726             *sc->sc_mp++ = PPP_ALLSTATIONS;
1727             *sc->sc_mp++ = PPP_UI;
1728             sc->sc_ilen += 2;
1729             m->m_len += 2;
1730         }
1731     }
1732     if (sc->sc_ilen == 1 && c != PPP_UI) {
1733         if (sc->sc_flags & SC_DEBUG)
1734             printf("ppp%d: missing UI (0x3), got 0x%x\n",
1735                    sc->sc_if.if_unit, c);
1736         goto flush;
1737     }
1738     if (sc->sc_ilen == 2 && (c & 1) == 1) {
1739         /* a compressed protocol */
1740         *sc->sc_mp++ = 0;
1741         sc->sc_ilen++;
1742         sc->sc_mc->m_len++;
1743     }
1744     if (sc->sc_ilen == 3 && (c & 1) == 0) {
1745         if (sc->sc_flags & SC_DEBUG)
1746             printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
1747                    (sc->sc_mp[-1] << 8) + c);
1748         goto flush;
1749     }
1750
1751     /* packet beyond configured mru? */
1752     if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1753         if (sc->sc_flags & SC_DEBUG)
1754             printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
1755         goto flush;
1756     }
1757
1758     /* is this mbuf full? */
1759     m = sc->sc_mc;
1760     if (M_TRAILINGSPACE(m) <= 0) {
1761         if (m->m_next == NULL) {
1762             pppgetm(sc);
1763             if (m->m_next == NULL) {
1764                 if (sc->sc_flags & SC_DEBUG)
1765                     printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
1766                 goto flush;
1767             }
1768         }
1769         sc->sc_mc = m = m->m_next;
1770         m->m_len = 0;
1771         m->m_off = M_OFFSTART(m);
1772         sc->sc_mp = mtod(m, char *);
1773     }
1774
1775     ++m->m_len;
1776     *sc->sc_mp++ = c;
1777     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1778     return;
1779
1780  flush:
1781     if (!(sc->sc_flags & SC_FLUSH)) {
1782         sc->sc_if.if_ierrors++;
1783         sc->sc_flags |= SC_FLUSH;
1784         if (sc->sc_flags & SC_LOG_FLUSH)
1785             ppplogchar(sc, c);
1786     }
1787 }
1788
1789 /*
1790  * Process an ioctl request to interface.
1791  */
1792 int
1793 pppioctl(ifp, cmd, data)
1794     register struct ifnet *ifp;
1795     int cmd;
1796     caddr_t data;
1797 {
1798     struct proc *p = u.u_procp;
1799     register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
1800     register struct ifaddr *ifa = (struct ifaddr *)data;
1801     register struct ifreq *ifr = (struct ifreq *)data;
1802     struct ppp_stats *psp;
1803     int s = splimp(), error = 0;
1804
1805     switch (cmd) {
1806     case SIOCSIFFLAGS:
1807         if ((ifp->if_flags & IFF_RUNNING) == 0)
1808             ifp->if_flags &= ~IFF_UP;
1809         break;
1810
1811     case SIOCSIFADDR:
1812         if (ifa->ifa_addr.sa_family != AF_INET)
1813             error = EAFNOSUPPORT;
1814         break;
1815
1816     case SIOCSIFDSTADDR:
1817         if (ifa->ifa_addr.sa_family != AF_INET)
1818             error = EAFNOSUPPORT;
1819         break;
1820
1821     case SIOCSIFMTU:
1822         if (!suser())
1823             return EPERM;
1824         sc->sc_if.if_mtu = ifr->ifr_mtu;
1825         break;
1826
1827     case SIOCGIFMTU:
1828         ifr->ifr_mtu = sc->sc_if.if_mtu;
1829         break;
1830
1831     case SIOCGPPPSTATS:
1832         psp = &((struct ifpppstatsreq *) data)->stats;
1833         bzero(psp, sizeof(*psp));
1834         psp->p.ppp_ibytes = sc->sc_bytesrcvd;
1835         psp->p.ppp_ipackets = ifp->if_ipackets;
1836         psp->p.ppp_ierrors = ifp->if_ierrors;
1837         psp->p.ppp_obytes = sc->sc_bytessent;
1838         psp->p.ppp_opackets = ifp->if_opackets;
1839         psp->p.ppp_oerrors = ifp->if_oerrors;
1840 #ifdef VJC
1841         psp->vj.vjs_packets = sc->sc_comp.sls_packets;
1842         psp->vj.vjs_compressed = sc->sc_comp.sls_compressed;
1843         psp->vj.vjs_searches = sc->sc_comp.sls_searches;
1844         psp->vj.vjs_misses = sc->sc_comp.sls_misses;
1845         psp->vj.vjs_uncompressedin = sc->sc_comp.sls_uncompressedin;
1846         psp->vj.vjs_compressedin = sc->sc_comp.sls_compressedin;
1847         psp->vj.vjs_errorin = sc->sc_comp.sls_errorin;
1848         psp->vj.vjs_tossed = sc->sc_comp.sls_tossed;
1849 #endif /* VJC */
1850 #ifdef PPP_COMPRESS
1851         if (sc->sc_xc_state != NULL)
1852             (*sc->sc_xcomp->comp_stat)(sc->sc_xc_state, &psp->c);
1853         if (sc->sc_rc_state != NULL)
1854             (*sc->sc_rcomp->decomp_stat)(sc->sc_rc_state, &psp->d);
1855 #endif /* PPP_COMPRESS */
1856         break;
1857
1858     default:
1859         error = EINVAL;
1860     }
1861     splx(s);
1862     return (error);
1863 }
1864
1865 #define MAX_DUMP_BYTES  128
1866
1867 static void
1868 pppdumpm(m0, pktlen)
1869     struct mbuf *m0;
1870     int pktlen;
1871 {
1872     char buf[3*MAX_DUMP_BYTES+4];
1873     char *bp = buf;
1874     struct mbuf *m;
1875     static char digits[] = "0123456789abcdef";
1876
1877     for (m = m0; m && pktlen; m = m->m_next) {
1878         int l = m->m_len;
1879         u_char *rptr = mtod(m, u_char *);
1880
1881         if (pktlen > 0) {
1882             if (l > pktlen)
1883                 l = pktlen;
1884             pktlen -= l;
1885         }
1886         while (l--) {
1887             if (bp > buf + sizeof(buf) - 4)
1888                 goto done;
1889             *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */
1890             *bp++ = digits[*rptr++ & 0xf];
1891         }
1892
1893         if (m->m_next) {
1894             if (bp > buf + sizeof(buf) - 3)
1895                 goto done;
1896             *bp++ = '|';
1897         } else
1898             *bp++ = ' ';
1899     }
1900 done:
1901     if (m && pktlen)
1902         *bp++ = '>';
1903     *bp = 0;
1904     printf("%s\n", buf);
1905 }
1906
1907 static void
1908 ppplogchar(sc, c)
1909     struct ppp_softc *sc;
1910     int c;
1911 {
1912     if (c >= 0)
1913         sc->sc_rawin[sc->sc_rawin_count++] = c;
1914     if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1915         || c < 0 && sc->sc_rawin_count > 0) {
1916         printf("ppp%d input: ", sc->sc_if.if_unit);
1917         pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
1918         sc->sc_rawin_count = 0;
1919     }
1920 }
1921
1922 static void
1923 pppdumpb(b, l)
1924     u_char *b;
1925     int l;
1926 {
1927     char buf[3*MAX_DUMP_BYTES+4];
1928     char *bp = buf;
1929     static char digits[] = "0123456789abcdef";
1930
1931     while (l--) {
1932         if (bp >= buf + sizeof(buf) - 3) {
1933             *bp++ = '>';
1934             break;
1935         }
1936         *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
1937         *bp++ = digits[*b++ & 0xf];
1938         *bp++ = ' ';
1939     }
1940
1941     *bp = 0;
1942     printf("%s\n", buf);
1943 }
1944
1945 #endif  /* NPPP > 0 */