if_ppp.c revision 1.28 1 /* $NetBSD: if_ppp.c,v 1.28 1996/02/13 22:00:18 christos Exp $ */
2
3 /*
4 * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver.
5 *
6 * Copyright (c) 1989 Carnegie Mellon University.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms are permitted
10 * provided that the above copyright notice and this paragraph are
11 * duplicated in all such forms and that any documentation,
12 * advertising materials, and other materials related to such
13 * distribution and use acknowledge that the software was developed
14 * by Carnegie Mellon University. The name of the
15 * University may not be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
19 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 * Drew D. Perkins
22 * Carnegie Mellon University
23 * 4910 Forbes Ave.
24 * Pittsburgh, PA 15213
25 * (412) 268-8576
26 * ddp (at) andrew.cmu.edu
27 *
28 * Based on:
29 * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
30 *
31 * Copyright (c) 1987 Regents of the University of California.
32 * All rights reserved.
33 *
34 * Redistribution and use in source and binary forms are permitted
35 * provided that the above copyright notice and this paragraph are
36 * duplicated in all such forms and that any documentation,
37 * advertising materials, and other materials related to such
38 * distribution and use acknowledge that the software was developed
39 * by the University of California, Berkeley. The name of the
40 * University may not be used to endorse or promote products derived
41 * from this software without specific prior written permission.
42 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
43 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
44 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
45 *
46 * Serial Line interface
47 *
48 * Rick Adams
49 * Center for Seismic Studies
50 * 1300 N 17th Street, Suite 1450
51 * Arlington, Virginia 22209
52 * (703)276-7900
53 * rick (at) seismo.ARPA
54 * seismo!rick
55 *
56 * Pounded on heavily by Chris Torek (chris (at) mimsy.umd.edu, umcp-cs!chris).
57 * Converted to 4.3BSD Beta by Chris Torek.
58 * Other changes made at Berkeley, based in part on code by Kirk Smith.
59 *
60 * Converted to 4.3BSD+ 386BSD by Brad Parker (brad (at) cayman.com)
61 * Added VJ tcp header compression; more unified ioctls
62 *
63 * Extensively modified by Paul Mackerras (paulus (at) cs.anu.edu.au).
64 * Cleaned up a lot of the mbuf-related code to fix bugs that
65 * caused system crashes and packet corruption. Changed pppstart
66 * so that it doesn't just give up with a collision if the whole
67 * packet doesn't fit in the output ring buffer.
68 *
69 * Added priority queueing for interactive IP packets, following
70 * the model of if_sl.c, plus hooks for bpf.
71 * Paul Mackerras (paulus (at) cs.anu.edu.au).
72 */
73
74 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
75 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
76
77 #include "ppp.h"
78 #if NPPP > 0
79
80 #define VJC
81 #define PPP_COMPRESS
82
83 #include <sys/param.h>
84 #include <sys/proc.h>
85 #include <sys/mbuf.h>
86 #include <sys/socket.h>
87 #include <sys/ioctl.h>
88 #include <sys/kernel.h>
89 #include <sys/systm.h>
90
91 #include <net/if.h>
92 #include <net/if_types.h>
93 #include <net/netisr.h>
94 #include <net/route.h>
95
96 #if INET
97 #include <netinet/in.h>
98 #include <netinet/in_systm.h>
99 #include <netinet/in_var.h>
100 #include <netinet/ip.h>
101 #endif
102
103 #include "bpfilter.h"
104 #if NBPFILTER > 0
105 #include <sys/time.h>
106 #include <net/bpf.h>
107 #endif
108
109 #ifdef VJC
110 #include <net/slcompress.h>
111 #endif
112
113 #include <net/ppp_defs.h>
114 #include <net/if_ppp.h>
115 #include <net/if_pppvar.h>
116 #include <machine/cpu.h>
117
118 #ifdef PPP_COMPRESS
119 #define PACKETPTR struct mbuf *
120 #include <net/ppp-comp.h>
121 #endif
122
123 static void ppp_requeue __P((struct ppp_softc *));
124 static void ppp_outpkt __P((struct ppp_softc *));
125 static void ppp_ccp __P((struct ppp_softc *, struct mbuf *m, int rcvd));
126 static void ppp_ccp_closed __P((struct ppp_softc *));
127 static void ppp_inproc __P((struct ppp_softc *, struct mbuf *));
128 static void pppdumpm __P((struct mbuf *m0));
129
130 /*
131 * Some useful mbuf macros not in mbuf.h.
132 */
133 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
134
135 #define M_DATASTART(m) \
136 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
137 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
138
139 #define M_DATASIZE(m) \
140 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
141 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
142
143 /*
144 * We steal two bits in the mbuf m_flags, to mark high-priority packets
145 * for output, and received packets following lost/corrupted packets.
146 */
147 #define M_HIGHPRI 0x2000 /* output packet for sc_fastq */
148 #define M_ERRMARK 0x4000 /* steal a bit in mbuf m_flags */
149
150
151 #ifdef PPP_COMPRESS
152 /*
153 * List of compressors we know about.
154 * We leave some space so maybe we can modload compressors.
155 */
156
157 extern struct compressor ppp_bsd_compress;
158
159 struct compressor *ppp_compressors[8] = {
160 #if DO_BSD_COMPRESS
161 &ppp_bsd_compress,
162 #endif
163 NULL
164 };
165 #endif /* PPP_COMPRESS */
166
167 /*
168 * Called from boot code to establish ppp interfaces.
169 */
170 void
171 pppattach()
172 {
173 register struct ppp_softc *sc;
174 register int i = 0;
175
176 for (sc = ppp_softc; i < NPPP; sc++) {
177 sc->sc_if.if_name = "ppp";
178 sc->sc_if.if_unit = i++;
179 sc->sc_if.if_mtu = PPP_MTU;
180 sc->sc_if.if_flags = IFF_POINTOPOINT;
181 sc->sc_if.if_type = IFT_PPP;
182 sc->sc_if.if_hdrlen = PPP_HDRLEN;
183 sc->sc_if.if_ioctl = pppsioctl;
184 sc->sc_if.if_output = pppoutput;
185 sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
186 sc->sc_inq.ifq_maxlen = IFQ_MAXLEN;
187 sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN;
188 sc->sc_rawq.ifq_maxlen = IFQ_MAXLEN;
189 if_attach(&sc->sc_if);
190 #if NBPFILTER > 0
191 bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_PPP, PPP_HDRLEN);
192 #endif
193 }
194 }
195
196 /*
197 * Allocate a ppp interface unit and initialize it.
198 */
199 struct ppp_softc *
200 pppalloc(pid)
201 pid_t pid;
202 {
203 int nppp, i;
204 struct ppp_softc *sc;
205
206 for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
207 if (sc->sc_xfer == pid) {
208 sc->sc_xfer = 0;
209 return sc;
210 }
211 for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
212 if (sc->sc_devp == NULL)
213 break;
214 if (nppp >= NPPP)
215 return NULL;
216
217 sc->sc_flags = 0;
218 sc->sc_mru = PPP_MRU;
219 sc->sc_relinq = NULL;
220 #ifdef VJC
221 sl_compress_init(&sc->sc_comp, -1);
222 #endif
223 #ifdef PPP_COMPRESS
224 sc->sc_xc_state = NULL;
225 sc->sc_rc_state = NULL;
226 #endif /* PPP_COMPRESS */
227 for (i = 0; i < NUM_NP; ++i)
228 sc->sc_npmode[i] = NPMODE_ERROR;
229 sc->sc_npqueue = NULL;
230 sc->sc_npqtail = &sc->sc_npqueue;
231 sc->sc_last_sent = sc->sc_last_recv = time.tv_sec;
232
233 return sc;
234 }
235
236 /*
237 * Deallocate a ppp unit. Must be called at splsoftnet or higher.
238 */
239 void
240 pppdealloc(sc)
241 struct ppp_softc *sc;
242 {
243 struct mbuf *m;
244
245 if_down(&sc->sc_if);
246 sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
247 sc->sc_devp = NULL;
248 sc->sc_xfer = 0;
249 for (;;) {
250 IF_DEQUEUE(&sc->sc_rawq, m);
251 if (m == NULL)
252 break;
253 m_freem(m);
254 }
255 for (;;) {
256 IF_DEQUEUE(&sc->sc_inq, m);
257 if (m == NULL)
258 break;
259 m_freem(m);
260 }
261 for (;;) {
262 IF_DEQUEUE(&sc->sc_fastq, m);
263 if (m == NULL)
264 break;
265 m_freem(m);
266 }
267 while ((m = sc->sc_npqueue) != NULL) {
268 sc->sc_npqueue = m->m_nextpkt;
269 m_freem(m);
270 }
271 if (sc->sc_togo != NULL) {
272 m_freem(sc->sc_togo);
273 sc->sc_togo = NULL;
274 }
275 #ifdef PPP_COMPRESS
276 ppp_ccp_closed(sc);
277 sc->sc_xc_state = NULL;
278 sc->sc_rc_state = NULL;
279 #endif /* PPP_COMPRESS */
280 }
281
282 /*
283 * Ioctl routine for generic ppp devices.
284 */
285 int
286 pppioctl(sc, cmd, data, flag, p)
287 struct ppp_softc *sc;
288 u_long cmd;
289 caddr_t data;
290 int flag;
291 struct proc *p;
292 {
293 int s, error, flags, mru, nb, npx;
294 struct ppp_option_data *odp;
295 struct compressor **cp;
296 struct npioctl *npi;
297 time_t t;
298 #ifdef PPP_COMPRESS
299 u_char ccp_option[CCP_MAX_OPTION_LENGTH];
300 #endif
301
302 switch (cmd) {
303 case FIONREAD:
304 *(int *)data = sc->sc_inq.ifq_len;
305 break;
306
307 case PPPIOCGUNIT:
308 *(int *)data = sc->sc_if.if_unit;
309 break;
310
311 case PPPIOCGFLAGS:
312 *(u_int *)data = sc->sc_flags;
313 break;
314
315 case PPPIOCSFLAGS:
316 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
317 return (error);
318 flags = *(int *)data & SC_MASK;
319 s = splsoftnet();
320 #ifdef PPP_COMPRESS
321 if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN))
322 ppp_ccp_closed(sc);
323 #endif
324 splhigh();
325 sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags;
326 splx(s);
327 break;
328
329 case PPPIOCSMRU:
330 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
331 return (error);
332 mru = *(int *)data;
333 if (mru >= PPP_MRU && mru <= PPP_MAXMRU)
334 sc->sc_mru = mru;
335 break;
336
337 case PPPIOCGMRU:
338 *(int *)data = sc->sc_mru;
339 break;
340
341 #ifdef VJC
342 case PPPIOCSMAXCID:
343 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
344 return (error);
345 s = splsoftnet();
346 sl_compress_init(&sc->sc_comp, *(int *)data);
347 splx(s);
348 break;
349 #endif
350
351 case PPPIOCXFERUNIT:
352 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
353 return (error);
354 sc->sc_xfer = p->p_pid;
355 break;
356
357 #ifdef PPP_COMPRESS
358 case PPPIOCSCOMPRESS:
359 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
360 return (error);
361 odp = (struct ppp_option_data *) data;
362 nb = odp->length;
363 if (nb > sizeof(ccp_option))
364 nb = sizeof(ccp_option);
365 if ((error = copyin(odp->ptr, ccp_option, nb)) != 0)
366 return (error);
367 if (ccp_option[1] < 2) /* preliminary check on the length byte */
368 return (EINVAL);
369 for (cp = ppp_compressors; *cp != NULL; ++cp)
370 if ((*cp)->compress_proto == ccp_option[0]) {
371 /*
372 * Found a handler for the protocol - try to allocate
373 * a compressor or decompressor.
374 */
375 error = 0;
376 if (odp->transmit) {
377 s = splsoftnet();
378 if (sc->sc_xc_state != NULL)
379 (*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
380 sc->sc_xcomp = *cp;
381 sc->sc_xc_state = (*cp)->comp_alloc(ccp_option, nb);
382 if (sc->sc_xc_state == NULL) {
383 if (sc->sc_flags & SC_DEBUG)
384 printf("ppp%d: comp_alloc failed\n",
385 sc->sc_if.if_unit);
386 error = ENOBUFS;
387 }
388 splhigh();
389 sc->sc_flags &= ~SC_COMP_RUN;
390 splx(s);
391 } else {
392 s = splsoftnet();
393 if (sc->sc_rc_state != NULL)
394 (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
395 sc->sc_rcomp = *cp;
396 sc->sc_rc_state = (*cp)->decomp_alloc(ccp_option, nb);
397 if (sc->sc_rc_state == NULL) {
398 if (sc->sc_flags & SC_DEBUG)
399 printf("ppp%d: decomp_alloc failed\n",
400 sc->sc_if.if_unit);
401 error = ENOBUFS;
402 }
403 splhigh();
404 sc->sc_flags &= ~SC_DECOMP_RUN;
405 splx(s);
406 }
407 return (error);
408 }
409 if (sc->sc_flags & SC_DEBUG)
410 printf("ppp%d: no compressor for [%x %x %x], %x\n",
411 sc->sc_if.if_unit, ccp_option[0], ccp_option[1],
412 ccp_option[2], nb);
413 return (EINVAL); /* no handler found */
414 #endif /* PPP_COMPRESS */
415
416 case PPPIOCGNPMODE:
417 case PPPIOCSNPMODE:
418 npi = (struct npioctl *) data;
419 switch (npi->protocol) {
420 case PPP_IP:
421 npx = NP_IP;
422 break;
423 default:
424 return EINVAL;
425 }
426 if (cmd == PPPIOCGNPMODE) {
427 npi->mode = sc->sc_npmode[npx];
428 } else {
429 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
430 return (error);
431 if (npi->mode != sc->sc_npmode[npx]) {
432 s = splsoftnet();
433 sc->sc_npmode[npx] = npi->mode;
434 if (npi->mode != NPMODE_QUEUE) {
435 ppp_requeue(sc);
436 (*sc->sc_start)(sc);
437 }
438 splx(s);
439 }
440 }
441 break;
442
443 case PPPIOCGIDLE:
444 s = splsoftnet();
445 t = time.tv_sec;
446 ((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent;
447 ((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv;
448 splx(s);
449 break;
450
451 default:
452 return (-1);
453 }
454 return (0);
455 }
456
457 /*
458 * Process an ioctl request to the ppp network interface.
459 */
460 int
461 pppsioctl(ifp, cmd, data)
462 register struct ifnet *ifp;
463 u_long cmd;
464 caddr_t data;
465 {
466 struct proc *p = curproc; /* XXX */
467 register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
468 register struct ifaddr *ifa = (struct ifaddr *)data;
469 register struct ifreq *ifr = (struct ifreq *)data;
470 struct ppp_stats *psp;
471 #ifdef PPP_COMPRESS
472 struct ppp_comp_stats *pcp;
473 #endif
474 int s = splimp(), error = 0;
475
476 switch (cmd) {
477 case SIOCSIFFLAGS:
478 if ((ifp->if_flags & IFF_RUNNING) == 0)
479 ifp->if_flags &= ~IFF_UP;
480 break;
481
482 case SIOCSIFADDR:
483 if (ifa->ifa_addr->sa_family != AF_INET)
484 error = EAFNOSUPPORT;
485 break;
486
487 case SIOCSIFDSTADDR:
488 if (ifa->ifa_addr->sa_family != AF_INET)
489 error = EAFNOSUPPORT;
490 break;
491
492 case SIOCSIFMTU:
493 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
494 break;
495 sc->sc_if.if_mtu = ifr->ifr_mtu;
496 break;
497
498 case SIOCGIFMTU:
499 ifr->ifr_mtu = sc->sc_if.if_mtu;
500 break;
501
502 case SIOCGPPPSTATS:
503 psp = &((struct ifpppstatsreq *) data)->stats;
504 bzero(psp, sizeof(*psp));
505 psp->p.ppp_ibytes = sc->sc_bytesrcvd;
506 psp->p.ppp_ipackets = ifp->if_ipackets;
507 psp->p.ppp_ierrors = ifp->if_ierrors;
508 psp->p.ppp_obytes = sc->sc_bytessent;
509 psp->p.ppp_opackets = ifp->if_opackets;
510 psp->p.ppp_oerrors = ifp->if_oerrors;
511 #ifdef VJC
512 psp->vj.vjs_packets = sc->sc_comp.sls_packets;
513 psp->vj.vjs_compressed = sc->sc_comp.sls_compressed;
514 psp->vj.vjs_searches = sc->sc_comp.sls_searches;
515 psp->vj.vjs_misses = sc->sc_comp.sls_misses;
516 psp->vj.vjs_uncompressedin = sc->sc_comp.sls_uncompressedin;
517 psp->vj.vjs_compressedin = sc->sc_comp.sls_compressedin;
518 psp->vj.vjs_errorin = sc->sc_comp.sls_errorin;
519 psp->vj.vjs_tossed = sc->sc_comp.sls_tossed;
520 #endif /* VJC */
521 break;
522
523 #ifdef PPP_COMPRESS
524 case SIOCGPPPCSTATS:
525 pcp = &((struct ifpppcstatsreq *) data)->stats;
526 bzero(pcp, sizeof(*pcp));
527 if (sc->sc_xc_state != NULL)
528 (*sc->sc_xcomp->comp_stat)(sc->sc_xc_state, &pcp->c);
529 if (sc->sc_rc_state != NULL)
530 (*sc->sc_rcomp->decomp_stat)(sc->sc_rc_state, &pcp->d);
531 break;
532 #endif /* PPP_COMPRESS */
533
534 default:
535 error = EINVAL;
536 }
537 splx(s);
538 return (error);
539 }
540
541 /*
542 * Queue a packet. Start transmission if not active.
543 * Packet is placed in Information field of PPP frame.
544 */
545 int
546 pppoutput(ifp, m0, dst, rtp)
547 struct ifnet *ifp;
548 struct mbuf *m0;
549 struct sockaddr *dst;
550 struct rtentry *rtp;
551 {
552 register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
553 int protocol, address, control;
554 u_char *cp;
555 int s, error;
556 struct ip *ip;
557 struct ifqueue *ifq;
558 enum NPmode mode;
559
560 if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0
561 || ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) {
562 error = ENETDOWN; /* sort of */
563 goto bad;
564 }
565
566 /*
567 * Compute PPP header.
568 */
569 m0->m_flags &= ~M_HIGHPRI;
570 switch (dst->sa_family) {
571 #ifdef INET
572 case AF_INET:
573 address = PPP_ALLSTATIONS;
574 control = PPP_UI;
575 protocol = PPP_IP;
576 mode = sc->sc_npmode[NP_IP];
577
578 /*
579 * If this packet has the "low delay" bit set in the IP header,
580 * put it on the fastq instead.
581 */
582 ip = mtod(m0, struct ip *);
583 if (ip->ip_tos & IPTOS_LOWDELAY)
584 m0->m_flags |= M_HIGHPRI;
585 break;
586 #endif
587 case AF_UNSPEC:
588 address = PPP_ADDRESS(dst->sa_data);
589 control = PPP_CONTROL(dst->sa_data);
590 protocol = PPP_PROTOCOL(dst->sa_data);
591 mode = NPMODE_PASS;
592 break;
593 default:
594 printf("ppp%d: af%d not supported\n", ifp->if_unit, dst->sa_family);
595 error = EAFNOSUPPORT;
596 goto bad;
597 }
598
599 /*
600 * Drop this packet, or return an error, if necessary.
601 */
602 if (mode == NPMODE_ERROR) {
603 error = ENETDOWN;
604 goto bad;
605 }
606 if (mode == NPMODE_DROP) {
607 error = 0;
608 goto bad;
609 }
610
611 /*
612 * Add PPP header. If no space in first mbuf, allocate another.
613 * (This assumes M_LEADINGSPACE is always 0 for a cluster mbuf.)
614 */
615 if (M_LEADINGSPACE(m0) < PPP_HDRLEN) {
616 m0 = m_prepend(m0, PPP_HDRLEN, M_DONTWAIT);
617 if (m0 == 0) {
618 error = ENOBUFS;
619 goto bad;
620 }
621 m0->m_len = 0;
622 } else
623 m0->m_data -= PPP_HDRLEN;
624
625 cp = mtod(m0, u_char *);
626 *cp++ = address;
627 *cp++ = control;
628 *cp++ = protocol >> 8;
629 *cp++ = protocol & 0xff;
630 m0->m_len += PPP_HDRLEN;
631
632 if (sc->sc_flags & SC_LOG_OUTPKT) {
633 printf("ppp%d output: ", ifp->if_unit);
634 pppdumpm(m0);
635 }
636
637 #if NBPFILTER > 0
638 /*
639 * See if bpf wants to look at the packet.
640 */
641 if (sc->sc_bpf)
642 bpf_mtap(sc->sc_bpf, m0);
643 #endif
644
645 /*
646 * Put the packet on the appropriate queue.
647 */
648 s = splsoftnet();
649 if (mode == NPMODE_QUEUE) {
650 /* XXX we should limit the number of packets on this queue */
651 *sc->sc_npqtail = m0;
652 m0->m_nextpkt = NULL;
653 sc->sc_npqtail = &m0->m_nextpkt;
654 } else {
655 ifq = (m0->m_flags & M_HIGHPRI)? &sc->sc_fastq: &ifp->if_snd;
656 if (IF_QFULL(ifq)) {
657 IF_DROP(ifq);
658 splx(s);
659 sc->sc_if.if_oerrors++;
660 error = ENOBUFS;
661 goto bad;
662 }
663 IF_ENQUEUE(ifq, m0);
664 (*sc->sc_start)(sc);
665 }
666 ifp->if_lastchange = time;
667
668 splx(s);
669 return (0);
670
671 bad:
672 m_freem(m0);
673 return (error);
674 }
675
676 /*
677 * After a change in the NPmode for some NP, move packets from the
678 * npqueue to the send queue or the fast queue as appropriate.
679 * Should be called at splsoftnet.
680 */
681 static void
682 ppp_requeue(sc)
683 struct ppp_softc *sc;
684 {
685 struct mbuf *m, **mpp;
686 struct ifqueue *ifq;
687 enum NPmode mode;
688
689 for (mpp = &sc->sc_npqueue; (m = *mpp) != NULL; ) {
690 switch (PPP_PROTOCOL(mtod(m, u_char *))) {
691 case PPP_IP:
692 mode = sc->sc_npmode[NP_IP];
693 break;
694 default:
695 mode = NPMODE_PASS;
696 }
697
698 switch (mode) {
699 case NPMODE_PASS:
700 /*
701 * This packet can now go on one of the queues to be sent.
702 */
703 *mpp = m->m_nextpkt;
704 m->m_nextpkt = NULL;
705 ifq = (m->m_flags & M_HIGHPRI)? &sc->sc_fastq: &sc->sc_if.if_snd;
706 if (IF_QFULL(ifq)) {
707 IF_DROP(ifq);
708 sc->sc_if.if_oerrors++;
709 } else
710 IF_ENQUEUE(ifq, m);
711 break;
712
713 case NPMODE_DROP:
714 case NPMODE_ERROR:
715 *mpp = m->m_nextpkt;
716 m_freem(m);
717 break;
718
719 case NPMODE_QUEUE:
720 mpp = &m->m_nextpkt;
721 break;
722 }
723 }
724 sc->sc_npqtail = mpp;
725 }
726
727 /*
728 * Get a packet to send. This procedure is intended to be called at
729 * spltty or splimp, so it takes little time. If there isn't a packet
730 * waiting to go out, it schedules a software interrupt to prepare a
731 * new packet; the device start routine gets called again when a
732 * packet is ready.
733 */
734 struct mbuf *
735 ppp_dequeue(sc)
736 struct ppp_softc *sc;
737 {
738 struct mbuf *m;
739 int s = splhigh();
740
741 m = sc->sc_togo;
742 if (m) {
743 /*
744 * Had a packet waiting - send it.
745 */
746 sc->sc_togo = NULL;
747 sc->sc_flags |= SC_TBUSY;
748 splx(s);
749 return m;
750 }
751 /*
752 * Remember we wanted a packet and schedule a software interrupt.
753 */
754 sc->sc_flags &= ~SC_TBUSY;
755 schednetisr(NETISR_PPP);
756 splx(s);
757 return NULL;
758 }
759
760 /*
761 * Software interrupt routine, called at splsoftnet.
762 */
763 void
764 pppintr()
765 {
766 struct ppp_softc *sc;
767 int i, s;
768 struct mbuf *m;
769
770 sc = ppp_softc;
771 for (i = 0; i < NPPP; ++i, ++sc) {
772 if (!(sc->sc_flags & SC_TBUSY) && sc->sc_togo == NULL
773 && (sc->sc_if.if_snd.ifq_head || sc->sc_fastq.ifq_head))
774 ppp_outpkt(sc);
775 for (;;) {
776 s = splhigh();
777 IF_DEQUEUE(&sc->sc_rawq, m);
778 splx(s);
779 if (m == NULL)
780 break;
781 ppp_inproc(sc, m);
782 }
783 }
784 }
785
786 /*
787 * Grab another packet off a queue and apply VJ compression,
788 * packet compression, address/control and/or protocol compression
789 * if enabled. Should be called at splsoftnet.
790 */
791 static void
792 ppp_outpkt(sc)
793 struct ppp_softc *sc;
794 {
795 struct mbuf *m, *mp;
796 u_char *cp;
797 int address, control, protocol;
798
799 /*
800 * Grab a packet to send: first try the fast queue, then the
801 * normal queue.
802 */
803 IF_DEQUEUE(&sc->sc_fastq, m);
804 if (m == NULL)
805 IF_DEQUEUE(&sc->sc_if.if_snd, m);
806 if (m == NULL)
807 return;
808
809 /*
810 * Extract the ppp header of the new packet.
811 * The ppp header will be in one mbuf.
812 */
813 cp = mtod(m, u_char *);
814 address = PPP_ADDRESS(cp);
815 control = PPP_CONTROL(cp);
816 protocol = PPP_PROTOCOL(cp);
817
818 switch (protocol) {
819 case PPP_IP:
820 /*
821 * Update the time we sent the most recent packet.
822 */
823 sc->sc_last_sent = time.tv_sec;
824
825 #ifdef VJC
826 /*
827 * If the packet is a TCP/IP packet, see if we can compress it.
828 */
829 if (sc->sc_flags & SC_COMP_TCP) {
830 struct ip *ip;
831 int type;
832
833 mp = m;
834 ip = (struct ip *) (cp + PPP_HDRLEN);
835 if (mp->m_len <= PPP_HDRLEN) {
836 mp = mp->m_next;
837 if (mp == NULL)
838 break;
839 ip = mtod(mp, struct ip *);
840 }
841 /* this code assumes the IP/TCP header is in one non-shared mbuf */
842 if (ip->ip_p == IPPROTO_TCP) {
843 type = sl_compress_tcp(mp, ip, &sc->sc_comp,
844 !(sc->sc_flags & SC_NO_TCP_CCID));
845 switch (type) {
846 case TYPE_UNCOMPRESSED_TCP:
847 protocol = PPP_VJC_UNCOMP;
848 break;
849 case TYPE_COMPRESSED_TCP:
850 protocol = PPP_VJC_COMP;
851 cp = mtod(m, u_char *);
852 cp[0] = address; /* header has moved */
853 cp[1] = control;
854 cp[2] = 0;
855 break;
856 }
857 cp[3] = protocol; /* update protocol in PPP header */
858 }
859 }
860 #endif /* VJC */
861 break;
862
863 #ifdef PPP_COMPRESS
864 case PPP_CCP:
865 ppp_ccp(sc, m, 0);
866 break;
867 #endif /* PPP_COMPRESS */
868 }
869
870 #ifdef PPP_COMPRESS
871 if (protocol != PPP_LCP && protocol != PPP_CCP
872 && sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) {
873 struct mbuf *mcomp;
874 int slen, clen;
875
876 slen = 0;
877 for (mp = m; mp != NULL; mp = mp->m_next)
878 slen += mp->m_len;
879 clen = (*sc->sc_xcomp->compress)
880 (sc->sc_xc_state, &mcomp, m, slen,
881 (sc->sc_flags & SC_CCP_UP? sc->sc_if.if_mtu: 0));
882 if (mcomp != NULL) {
883 m_freem(m);
884 m = mcomp;
885 cp = mtod(m, u_char *);
886 protocol = cp[3];
887 }
888 }
889 #endif /* PPP_COMPRESS */
890
891 /*
892 * Compress the address/control and protocol, if possible.
893 */
894 if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS &&
895 control == PPP_UI && protocol != PPP_ALLSTATIONS &&
896 protocol != PPP_LCP) {
897 /* can compress address/control */
898 m->m_data += 2;
899 m->m_len -= 2;
900 }
901 if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) {
902 /* can compress protocol */
903 if (mtod(m, u_char *) == cp) {
904 cp[2] = cp[1]; /* move address/control up */
905 cp[1] = cp[0];
906 }
907 ++m->m_data;
908 --m->m_len;
909 }
910
911 sc->sc_togo = m;
912 (*sc->sc_start)(sc);
913 }
914
915 #ifdef PPP_COMPRESS
916 /*
917 * Handle a CCP packet. `rcvd' is 1 if the packet was received,
918 * 0 if it is about to be transmitted.
919 */
920 static void
921 ppp_ccp(sc, m, rcvd)
922 struct ppp_softc *sc;
923 struct mbuf *m;
924 int rcvd;
925 {
926 u_char *dp, *ep;
927 struct mbuf *mp;
928 int slen, s;
929
930 /*
931 * Get a pointer to the data after the PPP header.
932 */
933 if (m->m_len <= PPP_HDRLEN) {
934 mp = m->m_next;
935 if (mp == NULL)
936 return;
937 dp = (mp != NULL)? mtod(mp, u_char *): NULL;
938 } else {
939 mp = m;
940 dp = mtod(mp, u_char *) + PPP_HDRLEN;
941 }
942
943 ep = mtod(mp, u_char *) + mp->m_len;
944 if (dp + CCP_HDRLEN > ep)
945 return;
946 slen = CCP_LENGTH(dp);
947 if (dp + slen > ep) {
948 if (sc->sc_flags & SC_DEBUG)
949 printf("if_ppp/ccp: not enough data in mbuf (%p+%x > %p+%x)\n",
950 dp, slen, mtod(mp, u_char *), mp->m_len);
951 return;
952 }
953
954 switch (CCP_CODE(dp)) {
955 case CCP_CONFREQ:
956 case CCP_TERMREQ:
957 case CCP_TERMACK:
958 /* CCP must be going down - disable compression */
959 if (sc->sc_flags & SC_CCP_UP) {
960 s = splhigh();
961 sc->sc_flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN);
962 splx(s);
963 }
964 break;
965
966 case CCP_CONFACK:
967 if (sc->sc_flags & SC_CCP_OPEN && !(sc->sc_flags & SC_CCP_UP)
968 && slen >= CCP_HDRLEN + CCP_OPT_MINLEN
969 && slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) {
970 if (!rcvd) {
971 /* we're agreeing to send compressed packets. */
972 if (sc->sc_xc_state != NULL
973 && (*sc->sc_xcomp->comp_init)
974 (sc->sc_xc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN,
975 sc->sc_if.if_unit, 0, sc->sc_flags & SC_DEBUG)) {
976 s = splhigh();
977 sc->sc_flags |= SC_COMP_RUN;
978 splx(s);
979 }
980 } else {
981 /* peer is agreeing to send compressed packets. */
982 if (sc->sc_rc_state != NULL
983 && (*sc->sc_rcomp->decomp_init)
984 (sc->sc_rc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN,
985 sc->sc_if.if_unit, 0, sc->sc_mru,
986 sc->sc_flags & SC_DEBUG)) {
987 s = splhigh();
988 sc->sc_flags |= SC_DECOMP_RUN;
989 sc->sc_flags &= ~(SC_DC_ERROR | SC_DC_FERROR);
990 splx(s);
991 }
992 }
993 }
994 break;
995
996 case CCP_RESETACK:
997 if (sc->sc_flags & SC_CCP_UP) {
998 if (!rcvd) {
999 if (sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN))
1000 (*sc->sc_xcomp->comp_reset)(sc->sc_xc_state);
1001 } else {
1002 if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) {
1003 (*sc->sc_rcomp->decomp_reset)(sc->sc_rc_state);
1004 s = splhigh();
1005 sc->sc_flags &= ~SC_DC_ERROR;
1006 splx(s);
1007 }
1008 }
1009 }
1010 break;
1011 }
1012 }
1013
1014 /*
1015 * CCP is down; free (de)compressor state if necessary.
1016 */
1017 static void
1018 ppp_ccp_closed(sc)
1019 struct ppp_softc *sc;
1020 {
1021 if (sc->sc_xc_state) {
1022 (*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
1023 sc->sc_xc_state = NULL;
1024 }
1025 if (sc->sc_rc_state) {
1026 (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
1027 sc->sc_rc_state = NULL;
1028 }
1029 }
1030 #endif /* PPP_COMPRESS */
1031
1032 /*
1033 * PPP packet input routine.
1034 * The caller has checked and removed the FCS and has inserted
1035 * the address/control bytes and the protocol high byte if they
1036 * were omitted.
1037 */
1038 void
1039 ppppktin(sc, m, lost)
1040 struct ppp_softc *sc;
1041 struct mbuf *m;
1042 int lost;
1043 {
1044 int s = splhigh();
1045
1046 if (lost)
1047 m->m_flags |= M_ERRMARK;
1048 IF_ENQUEUE(&sc->sc_rawq, m);
1049 schednetisr(NETISR_PPP);
1050 splx(s);
1051 }
1052
1053 /*
1054 * Process a received PPP packet, doing decompression as necessary.
1055 * Should be called at splsoftnet.
1056 */
1057 #define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \
1058 TYPE_UNCOMPRESSED_TCP)
1059
1060 static void
1061 ppp_inproc(sc, m)
1062 struct ppp_softc *sc;
1063 struct mbuf *m;
1064 {
1065 struct ifnet *ifp = &sc->sc_if;
1066 struct ifqueue *inq;
1067 int s, ilen = 0, xlen, proto, rv;
1068 u_char *cp, adrs, ctrl;
1069 struct mbuf *mp, *dmp;
1070 u_char *iphdr;
1071 u_int hlen;
1072
1073 ifp->if_ipackets++;
1074 ifp->if_lastchange = time;
1075
1076 if (sc->sc_flags & SC_LOG_INPKT) {
1077 register int len = 0;
1078 for (mp = m; mp != NULL; mp = mp->m_next)
1079 len += mp->m_len;
1080 printf("ppp%d: got %d bytes\n", ifp->if_unit, len);
1081 pppdumpm(m);
1082 }
1083
1084 cp = mtod(m, u_char *);
1085 adrs = PPP_ADDRESS(cp);
1086 ctrl = PPP_CONTROL(cp);
1087 proto = PPP_PROTOCOL(cp);
1088
1089 if (m->m_flags & M_ERRMARK) {
1090 m->m_flags &= ~M_ERRMARK;
1091 s = splhigh();
1092 sc->sc_flags |= SC_VJ_RESET;
1093 splx(s);
1094 }
1095
1096 #ifdef PPP_COMPRESS
1097 /*
1098 * Decompress this packet if necessary, update the receiver's
1099 * dictionary, or take appropriate action on a CCP packet.
1100 */
1101 if (proto == PPP_COMP && sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)
1102 && !(sc->sc_flags & SC_DC_ERROR) && !(sc->sc_flags & SC_DC_FERROR)) {
1103 /* decompress this packet */
1104 rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp);
1105 if (rv == DECOMP_OK) {
1106 m_freem(m);
1107 if (dmp == NULL) {
1108 /* no error, but no decompressed packet produced */
1109 return;
1110 }
1111 m = dmp;
1112 cp = mtod(m, u_char *);
1113 proto = PPP_PROTOCOL(cp);
1114
1115 } else {
1116 /*
1117 * An error has occurred in decompression.
1118 * Pass the compressed packet up to pppd, which may take
1119 * CCP down or issue a Reset-Req.
1120 */
1121 if (sc->sc_flags & SC_DEBUG)
1122 printf("ppp%d: decompress failed %d\n", ifp->if_unit, rv);
1123 s = splhigh();
1124 sc->sc_flags |= SC_VJ_RESET;
1125 if (rv == DECOMP_ERROR)
1126 sc->sc_flags |= SC_DC_ERROR;
1127 else
1128 sc->sc_flags |= SC_DC_FERROR;
1129 splx(s);
1130 }
1131
1132 } else {
1133 if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) {
1134 (*sc->sc_rcomp->incomp)(sc->sc_rc_state, m);
1135 }
1136 if (proto == PPP_CCP) {
1137 ppp_ccp(sc, m, 1);
1138 }
1139 }
1140 #endif
1141
1142 ilen = 0;
1143 for (mp = m; mp != NULL; mp = mp->m_next)
1144 ilen += mp->m_len;
1145
1146 #ifdef VJC
1147 if (sc->sc_flags & SC_VJ_RESET) {
1148 /*
1149 * If we've missed a packet, we must toss subsequent compressed
1150 * packets which don't have an explicit connection ID.
1151 */
1152 sl_uncompress_tcp(NULL, 0, TYPE_ERROR, &sc->sc_comp);
1153 s = splhigh();
1154 sc->sc_flags &= ~SC_VJ_RESET;
1155 splx(s);
1156 }
1157
1158 /*
1159 * See if we have a VJ-compressed packet to uncompress.
1160 */
1161 if (proto == PPP_VJC_COMP) {
1162 if (sc->sc_flags & SC_REJ_COMP_TCP)
1163 goto bad;
1164
1165 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN,
1166 ilen - PPP_HDRLEN, TYPE_COMPRESSED_TCP,
1167 &sc->sc_comp, &iphdr, &hlen);
1168
1169 if (xlen <= 0) {
1170 if (sc->sc_flags & SC_DEBUG)
1171 printf("ppp%d: VJ uncompress failed on type comp\n",
1172 ifp->if_unit);
1173 goto bad;
1174 }
1175
1176 /* Copy the PPP and IP headers into a new mbuf. */
1177 MGETHDR(mp, M_DONTWAIT, MT_DATA);
1178 if (mp == NULL)
1179 goto bad;
1180 mp->m_len = 0;
1181 mp->m_next = NULL;
1182 if (hlen + PPP_HDRLEN > MHLEN) {
1183 MCLGET(mp, M_DONTWAIT);
1184 if (M_TRAILINGSPACE(mp) < hlen + PPP_HDRLEN) {
1185 m_freem(mp);
1186 goto bad; /* lose if big headers and no clusters */
1187 }
1188 }
1189 cp = mtod(mp, u_char *);
1190 cp[0] = adrs;
1191 cp[1] = ctrl;
1192 cp[2] = 0;
1193 cp[3] = PPP_IP;
1194 proto = PPP_IP;
1195 bcopy(iphdr, cp + PPP_HDRLEN, hlen);
1196 mp->m_len = hlen + PPP_HDRLEN;
1197
1198 /*
1199 * Trim the PPP and VJ headers off the old mbuf
1200 * and stick the new and old mbufs together.
1201 */
1202 m->m_data += PPP_HDRLEN + xlen;
1203 m->m_len -= PPP_HDRLEN + xlen;
1204 if (m->m_len <= M_TRAILINGSPACE(mp)) {
1205 bcopy(mtod(m, u_char *), mtod(mp, u_char *) + mp->m_len, m->m_len);
1206 mp->m_len += m->m_len;
1207 MFREE(m, mp->m_next);
1208 } else
1209 mp->m_next = m;
1210 m = mp;
1211 ilen += hlen - xlen;
1212
1213 } else if (proto == PPP_VJC_UNCOMP) {
1214 if (sc->sc_flags & SC_REJ_COMP_TCP)
1215 goto bad;
1216
1217 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN,
1218 ilen - PPP_HDRLEN, TYPE_UNCOMPRESSED_TCP,
1219 &sc->sc_comp, &iphdr, &hlen);
1220
1221 if (xlen < 0) {
1222 if (sc->sc_flags & SC_DEBUG)
1223 printf("ppp%d: VJ uncompress failed on type uncomp\n",
1224 ifp->if_unit);
1225 goto bad;
1226 }
1227
1228 proto = PPP_IP;
1229 cp[3] = PPP_IP;
1230 }
1231 #endif /* VJC */
1232
1233 /*
1234 * If the packet will fit in a header mbuf, don't waste a
1235 * whole cluster on it.
1236 */
1237 if (ilen <= MHLEN && M_IS_CLUSTER(m)) {
1238 MGETHDR(mp, M_DONTWAIT, MT_DATA);
1239 if (mp != NULL) {
1240 m_copydata(m, 0, ilen, mtod(mp, caddr_t));
1241 m_freem(m);
1242 m = mp;
1243 m->m_len = ilen;
1244 }
1245 }
1246 m->m_pkthdr.len = ilen;
1247 m->m_pkthdr.rcvif = ifp;
1248
1249 #if NBPFILTER > 0
1250 /* See if bpf wants to look at the packet. */
1251 if (sc->sc_bpf)
1252 bpf_mtap(sc->sc_bpf, m);
1253 #endif
1254
1255 rv = 0;
1256 switch (proto) {
1257 #ifdef INET
1258 case PPP_IP:
1259 /*
1260 * IP packet - take off the ppp header and pass it up to IP.
1261 */
1262 if ((ifp->if_flags & IFF_UP) == 0
1263 || sc->sc_npmode[NP_IP] != NPMODE_PASS) {
1264 /* interface is down - drop the packet. */
1265 m_freem(m);
1266 return;
1267 }
1268 m->m_pkthdr.len -= PPP_HDRLEN;
1269 m->m_data += PPP_HDRLEN;
1270 m->m_len -= PPP_HDRLEN;
1271 schednetisr(NETISR_IP);
1272 inq = &ipintrq;
1273 sc->sc_last_recv = time.tv_sec; /* update time of last pkt rcvd */
1274 break;
1275 #endif
1276
1277 default:
1278 /*
1279 * Some other protocol - place on input queue for read().
1280 */
1281 inq = &sc->sc_inq;
1282 rv = 1;
1283 break;
1284 }
1285
1286 /*
1287 * Put the packet on the appropriate input queue.
1288 */
1289 s = splhigh();
1290 if (IF_QFULL(inq)) {
1291 IF_DROP(inq);
1292 splx(s);
1293 if (sc->sc_flags & SC_DEBUG)
1294 printf("ppp%d: input queue full\n", ifp->if_unit);
1295 ifp->if_iqdrops++;
1296 goto bad;
1297 }
1298 IF_ENQUEUE(inq, m);
1299 splx(s);
1300
1301 if (rv)
1302 (*sc->sc_ctlp)(sc);
1303
1304 return;
1305
1306 bad:
1307 m_freem(m);
1308 sc->sc_if.if_ierrors++;
1309 }
1310
1311 #define MAX_DUMP_BYTES 128
1312
1313 static void
1314 pppdumpm(m0)
1315 struct mbuf *m0;
1316 {
1317 char buf[3*MAX_DUMP_BYTES+4];
1318 char *bp = buf;
1319 struct mbuf *m;
1320 static char digits[] = "0123456789abcdef";
1321
1322 for (m = m0; m; m = m->m_next) {
1323 int l = m->m_len;
1324 u_char *rptr = (u_char *)m->m_data;
1325
1326 while (l--) {
1327 if (bp > buf + sizeof(buf) - 4)
1328 goto done;
1329 *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */
1330 *bp++ = digits[*rptr++ & 0xf];
1331 }
1332
1333 if (m->m_next) {
1334 if (bp > buf + sizeof(buf) - 3)
1335 goto done;
1336 *bp++ = '|';
1337 } else
1338 *bp++ = ' ';
1339 }
1340 done:
1341 if (m)
1342 *bp++ = '>';
1343 *bp = 0;
1344 printf("%s\n", buf);
1345 }
1346
1347 #endif /* NPPP > 0 */
1348