if_ppp.c revision 1.85
1/* $NetBSD: if_ppp.c,v 1.85 2003/09/01 16:51:25 christos Exp $ */ 2/* Id: if_ppp.c,v 1.6 1997/03/04 03:33:00 paulus Exp */ 3 4/* 5 * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver. 6 * 7 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. The name "Carnegie Mellon University" must not be used to 22 * endorse or promote products derived from this software without 23 * prior written permission. For permission or any legal 24 * details, please contact 25 * Office of Technology Transfer 26 * Carnegie Mellon University 27 * 5000 Forbes Avenue 28 * Pittsburgh, PA 15213-3890 29 * (412) 268-4387, fax: (412) 268-7395 30 * tech-transfer@andrew.cmu.edu 31 * 32 * 4. Redistributions of any form whatsoever must retain the following 33 * acknowledgment: 34 * "This product includes software developed by Computing Services 35 * at Carnegie Mellon University (http://www.cmu.edu/computing/)." 36 * 37 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO 38 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 39 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE 40 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 41 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 42 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 43 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 44 * 45 * Based on: 46 * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89 47 * 48 * Copyright (c) 1987 Regents of the University of California. 49 * All rights reserved. 50 * 51 * Redistribution and use in source and binary forms are permitted 52 * provided that the above copyright notice and this paragraph are 53 * duplicated in all such forms and that any documentation, 54 * advertising materials, and other materials related to such 55 * distribution and use acknowledge that the software was developed 56 * by the University of California, Berkeley. The name of the 57 * University may not be used to endorse or promote products derived 58 * from this software without specific prior written permission. 59 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 60 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 61 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 62 * 63 * Serial Line interface 64 * 65 * Rick Adams 66 * Center for Seismic Studies 67 * 1300 N 17th Street, Suite 1450 68 * Arlington, Virginia 22209 69 * (703)276-7900 70 * rick@seismo.ARPA 71 * seismo!rick 72 * 73 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris). 74 * Converted to 4.3BSD Beta by Chris Torek. 75 * Other changes made at Berkeley, based in part on code by Kirk Smith. 76 * 77 * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com) 78 * Added VJ tcp header compression; more unified ioctls 79 * 80 * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au). 81 * Cleaned up a lot of the mbuf-related code to fix bugs that 82 * caused system crashes and packet corruption. Changed pppstart 83 * so that it doesn't just give up with a collision if the whole 84 * packet doesn't fit in the output ring buffer. 85 * 86 * Added priority queueing for interactive IP packets, following 87 * the model of if_sl.c, plus hooks for bpf. 88 * Paul Mackerras (paulus@cs.anu.edu.au). 89 */ 90 91/* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */ 92/* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */ 93 94/* 95 * XXX IMP ME HARDER 96 * 97 * This is an explanation of that comment. This code used to use 98 * splimp() to block both network and tty interrupts. However, 99 * that call is deprecated. So, we have replaced the uses of 100 * splimp() with splhigh() in order to applomplish what it needs 101 * to accomplish, and added that happy little comment. 102 */ 103 104#include <sys/cdefs.h> 105__KERNEL_RCSID(0, "$NetBSD: if_ppp.c,v 1.85 2003/09/01 16:51:25 christos Exp $"); 106 107#include "ppp.h" 108 109#include "opt_inet.h" 110#include "opt_gateway.h" 111#include "opt_ppp.h" 112 113#ifdef INET 114#define VJC 115#endif 116#define PPP_COMPRESS 117 118#include <sys/param.h> 119#include <sys/proc.h> 120#include <sys/mbuf.h> 121#include <sys/socket.h> 122#include <sys/ioctl.h> 123#include <sys/kernel.h> 124#include <sys/systm.h> 125#include <sys/time.h> 126#include <sys/malloc.h> 127 128#include <net/if.h> 129#include <net/if_types.h> 130#include <net/netisr.h> 131#include <net/route.h> 132#ifdef PPP_FILTER 133#include <net/bpf.h> 134#endif 135 136#include <machine/intr.h> 137 138#include <netinet/in.h> 139#include <netinet/in_systm.h> 140#include <netinet/in_var.h> 141#ifdef INET 142#include <netinet/ip.h> 143#endif 144 145#include "bpfilter.h" 146#if NBPFILTER > 0 147#include <sys/time.h> 148#include <net/bpf.h> 149#endif 150 151#if defined(PPP_FILTER) || NBPFILTER > 0 152#include <net/slip.h> 153#endif 154 155#ifdef VJC 156#include <net/slcompress.h> 157#endif 158 159#include <net/ppp_defs.h> 160#include <net/if_ppp.h> 161#include <net/if_pppvar.h> 162#include <machine/cpu.h> 163 164#ifdef PPP_COMPRESS 165#define PACKETPTR struct mbuf * 166#include <net/ppp-comp.h> 167#endif 168 169static int pppsioctl __P((struct ifnet *, u_long, caddr_t)); 170static void ppp_requeue __P((struct ppp_softc *)); 171static void ppp_ccp __P((struct ppp_softc *, struct mbuf *m, int rcvd)); 172static void ppp_ccp_closed __P((struct ppp_softc *)); 173static void ppp_inproc __P((struct ppp_softc *, struct mbuf *)); 174static void pppdumpm __P((struct mbuf *m0)); 175#ifdef ALTQ 176static void ppp_ifstart __P((struct ifnet *ifp)); 177#endif 178 179#ifndef __HAVE_GENERIC_SOFT_INTERRUPTS 180void pppnetisr(void); 181#endif 182void pppintr(void *); 183 184/* 185 * Some useful mbuf macros not in mbuf.h. 186 */ 187#define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT) 188 189#define M_DATASTART(m) \ 190 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \ 191 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat) 192 193#define M_DATASIZE(m) \ 194 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \ 195 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN) 196 197/* 198 * We define two link layer specific mbuf flags, to mark high-priority 199 * packets for output, and received packets following lost/corrupted 200 * packets. 201 */ 202#define M_HIGHPRI M_LINK0 /* output packet for sc_fastq */ 203#define M_ERRMARK M_LINK1 /* rx packet following lost/corrupted pkt */ 204 205struct ppp_softc ppp_softc[NPPP]; 206 207#ifdef PPP_COMPRESS 208/* 209 * List of compressors we know about. 210 * We leave some space so maybe we can modload compressors. 211 */ 212 213extern struct compressor ppp_bsd_compress; 214extern struct compressor ppp_deflate, ppp_deflate_draft; 215 216struct compressor *ppp_compressors[PPP_COMPRESSORS_MAX] = { 217#if DO_BSD_COMPRESS && defined(PPP_BSDCOMP) 218 &ppp_bsd_compress, 219#endif 220#if DO_DEFLATE && defined(PPP_DEFLATE) 221 &ppp_deflate, 222 &ppp_deflate_draft, 223#endif 224 NULL 225}; 226#endif /* PPP_COMPRESS */ 227 228 229/* 230 * Called from boot code to establish ppp interfaces. 231 */ 232void 233pppattach() 234{ 235 struct ppp_softc *sc; 236 int i = 0; 237 238 for (sc = ppp_softc; i < NPPP; sc++) { 239 sc->sc_unit = i; /* XXX */ 240 sprintf(sc->sc_if.if_xname, "ppp%d", i++); 241 callout_init(&sc->sc_timo_ch); 242 sc->sc_if.if_softc = sc; 243 sc->sc_if.if_mtu = PPP_MTU; 244 sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 245 sc->sc_if.if_type = IFT_PPP; 246 sc->sc_if.if_hdrlen = PPP_HDRLEN; 247 sc->sc_if.if_dlt = DLT_NULL; 248 sc->sc_if.if_ioctl = pppsioctl; 249 sc->sc_if.if_output = pppoutput; 250#ifdef ALTQ 251 sc->sc_if.if_start = ppp_ifstart; 252#endif 253 IFQ_SET_MAXLEN(&sc->sc_if.if_snd, IFQ_MAXLEN); 254 sc->sc_inq.ifq_maxlen = IFQ_MAXLEN; 255 sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN; 256 sc->sc_rawq.ifq_maxlen = IFQ_MAXLEN; 257 IFQ_SET_READY(&sc->sc_if.if_snd); 258 if_attach(&sc->sc_if); 259 if_alloc_sadl(&sc->sc_if); 260#if NBPFILTER > 0 261 bpfattach(&sc->sc_if, DLT_NULL, 0); 262#endif 263 } 264} 265 266/* 267 * Allocate a ppp interface unit and initialize it. 268 */ 269struct ppp_softc * 270pppalloc(pid) 271 pid_t pid; 272{ 273 int nppp, i; 274 struct ppp_softc *sc; 275 276 for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++) 277 if (sc->sc_xfer == pid) { 278 sc->sc_xfer = 0; 279 return sc; 280 } 281 for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++) 282 if (sc->sc_devp == NULL) 283 break; 284 if (nppp >= NPPP) 285 return NULL; 286 287#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 288 sc->sc_si = softintr_establish(IPL_SOFTNET, pppintr, sc); 289 if (sc->sc_si == NULL) { 290 printf("ppp%d: unable to establish softintr\n", sc->sc_unit); 291 return (NULL); 292 } 293#endif 294 295 sc->sc_flags = 0; 296 sc->sc_mru = PPP_MRU; 297 sc->sc_relinq = NULL; 298 memset((char *)&sc->sc_stats, 0, sizeof(sc->sc_stats)); 299#ifdef VJC 300 MALLOC(sc->sc_comp, struct slcompress *, sizeof(struct slcompress), 301 M_DEVBUF, M_NOWAIT); 302 if (sc->sc_comp) 303 sl_compress_init(sc->sc_comp); 304#endif 305#ifdef PPP_COMPRESS 306 sc->sc_xc_state = NULL; 307 sc->sc_rc_state = NULL; 308#endif /* PPP_COMPRESS */ 309 for (i = 0; i < NUM_NP; ++i) 310 sc->sc_npmode[i] = NPMODE_ERROR; 311 sc->sc_npqueue = NULL; 312 sc->sc_npqtail = &sc->sc_npqueue; 313 sc->sc_last_sent = sc->sc_last_recv = time.tv_sec; 314 315 return sc; 316} 317 318/* 319 * Deallocate a ppp unit. Must be called at splsoftnet or higher. 320 */ 321void 322pppdealloc(sc) 323 struct ppp_softc *sc; 324{ 325 struct mbuf *m; 326 327#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 328 softintr_disestablish(sc->sc_si); 329#endif 330 if_down(&sc->sc_if); 331 sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING); 332 sc->sc_devp = NULL; 333 sc->sc_xfer = 0; 334 for (;;) { 335 IF_DEQUEUE(&sc->sc_rawq, m); 336 if (m == NULL) 337 break; 338 m_freem(m); 339 } 340 for (;;) { 341 IF_DEQUEUE(&sc->sc_inq, m); 342 if (m == NULL) 343 break; 344 m_freem(m); 345 } 346 for (;;) { 347 IF_DEQUEUE(&sc->sc_fastq, m); 348 if (m == NULL) 349 break; 350 m_freem(m); 351 } 352 while ((m = sc->sc_npqueue) != NULL) { 353 sc->sc_npqueue = m->m_nextpkt; 354 m_freem(m); 355 } 356 if (sc->sc_togo != NULL) { 357 m_freem(sc->sc_togo); 358 sc->sc_togo = NULL; 359 } 360#ifdef PPP_COMPRESS 361 ppp_ccp_closed(sc); 362 sc->sc_xc_state = NULL; 363 sc->sc_rc_state = NULL; 364#endif /* PPP_COMPRESS */ 365#ifdef PPP_FILTER 366 if (sc->sc_pass_filt_in.bf_insns != 0) { 367 FREE(sc->sc_pass_filt_in.bf_insns, M_DEVBUF); 368 sc->sc_pass_filt_in.bf_insns = 0; 369 sc->sc_pass_filt_in.bf_len = 0; 370 } 371 if (sc->sc_pass_filt_out.bf_insns != 0) { 372 FREE(sc->sc_pass_filt_out.bf_insns, M_DEVBUF); 373 sc->sc_pass_filt_out.bf_insns = 0; 374 sc->sc_pass_filt_out.bf_len = 0; 375 } 376 if (sc->sc_active_filt_in.bf_insns != 0) { 377 FREE(sc->sc_active_filt_in.bf_insns, M_DEVBUF); 378 sc->sc_active_filt_in.bf_insns = 0; 379 sc->sc_active_filt_in.bf_len = 0; 380 } 381 if (sc->sc_active_filt_out.bf_insns != 0) { 382 FREE(sc->sc_active_filt_out.bf_insns, M_DEVBUF); 383 sc->sc_active_filt_out.bf_insns = 0; 384 sc->sc_active_filt_out.bf_len = 0; 385 } 386#endif /* PPP_FILTER */ 387#ifdef VJC 388 if (sc->sc_comp != 0) { 389 FREE(sc->sc_comp, M_DEVBUF); 390 sc->sc_comp = 0; 391 } 392#endif 393} 394 395/* 396 * Ioctl routine for generic ppp devices. 397 */ 398int 399pppioctl(sc, cmd, data, flag, p) 400 struct ppp_softc *sc; 401 u_long cmd; 402 caddr_t data; 403 int flag; 404 struct proc *p; 405{ 406 int s, error, flags, mru, npx; 407 u_int nb; 408 struct ppp_option_data *odp; 409 struct compressor **cp; 410 struct npioctl *npi; 411 time_t t; 412#ifdef PPP_FILTER 413 struct bpf_program *bp, *nbp; 414 struct bpf_insn *newcode, *oldcode; 415 int newcodelen; 416#endif /* PPP_FILTER */ 417#ifdef PPP_COMPRESS 418 u_char ccp_option[CCP_MAX_OPTION_LENGTH]; 419#endif 420 421 switch (cmd) { 422 case FIONREAD: 423 *(int *)data = sc->sc_inq.ifq_len; 424 break; 425 426 case PPPIOCGUNIT: 427 *(int *)data = sc->sc_unit; /* XXX */ 428 break; 429 430 case PPPIOCGFLAGS: 431 *(u_int *)data = sc->sc_flags; 432 break; 433 434 case PPPIOCGRAWIN: 435 { 436 struct ppp_rawin *rwin = (struct ppp_rawin *)data; 437 u_char p, q = 0; 438 439 for (p = sc->sc_rawin_start; p < sizeof(sc->sc_rawin.buf);) 440 rwin->buf[q++] = sc->sc_rawin.buf[p++]; 441 442 for (p = 0; p < sc->sc_rawin_start;) 443 rwin->buf[q++] = sc->sc_rawin.buf[p++]; 444 445 rwin->count = sc->sc_rawin.count; 446 } 447 break; 448 449 case PPPIOCSFLAGS: 450 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 451 return (error); 452 flags = *(int *)data & SC_MASK; 453 s = splsoftnet(); 454#ifdef PPP_COMPRESS 455 if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN)) 456 ppp_ccp_closed(sc); 457#endif 458 splhigh(); /* XXX IMP ME HARDER */ 459 sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags; 460 splx(s); 461 break; 462 463 case PPPIOCSMRU: 464 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 465 return (error); 466 mru = *(int *)data; 467 if (mru >= PPP_MINMRU && mru <= PPP_MAXMRU) 468 sc->sc_mru = mru; 469 break; 470 471 case PPPIOCGMRU: 472 *(int *)data = sc->sc_mru; 473 break; 474 475#ifdef VJC 476 case PPPIOCSMAXCID: 477 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 478 return (error); 479 if (sc->sc_comp) { 480 s = splsoftnet(); 481 sl_compress_setup(sc->sc_comp, *(int *)data); 482 splx(s); 483 } 484 break; 485#endif 486 487 case PPPIOCXFERUNIT: 488 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 489 return (error); 490 sc->sc_xfer = p->p_pid; 491 break; 492 493#ifdef PPP_COMPRESS 494 case PPPIOCSCOMPRESS: 495 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 496 return (error); 497 odp = (struct ppp_option_data *) data; 498 nb = odp->length; 499 if (nb > sizeof(ccp_option)) 500 nb = sizeof(ccp_option); 501 if ((error = copyin(odp->ptr, ccp_option, nb)) != 0) 502 return (error); 503 if (ccp_option[1] < 2) /* preliminary check on the length byte */ 504 return (EINVAL); 505 for (cp = ppp_compressors; *cp != NULL; ++cp) 506 if ((*cp)->compress_proto == ccp_option[0]) { 507 /* 508 * Found a handler for the protocol - try to allocate 509 * a compressor or decompressor. 510 */ 511 error = 0; 512 if (odp->transmit) { 513 s = splsoftnet(); 514 if (sc->sc_xc_state != NULL) 515 (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); 516 sc->sc_xcomp = *cp; 517 sc->sc_xc_state = (*cp)->comp_alloc(ccp_option, nb); 518 if (sc->sc_xc_state == NULL) { 519 if (sc->sc_flags & SC_DEBUG) 520 printf("%s: comp_alloc failed\n", 521 sc->sc_if.if_xname); 522 error = ENOBUFS; 523 } 524 splhigh(); /* XXX IMP ME HARDER */ 525 sc->sc_flags &= ~SC_COMP_RUN; 526 splx(s); 527 } else { 528 s = splsoftnet(); 529 if (sc->sc_rc_state != NULL) 530 (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); 531 sc->sc_rcomp = *cp; 532 sc->sc_rc_state = (*cp)->decomp_alloc(ccp_option, nb); 533 if (sc->sc_rc_state == NULL) { 534 if (sc->sc_flags & SC_DEBUG) 535 printf("%s: decomp_alloc failed\n", 536 sc->sc_if.if_xname); 537 error = ENOBUFS; 538 } 539 splhigh(); /* XXX IMP ME HARDER */ 540 sc->sc_flags &= ~SC_DECOMP_RUN; 541 splx(s); 542 } 543 return (error); 544 } 545 if (sc->sc_flags & SC_DEBUG) 546 printf("%s: no compressor for [%x %x %x], %x\n", 547 sc->sc_if.if_xname, ccp_option[0], ccp_option[1], 548 ccp_option[2], nb); 549 return (EINVAL); /* no handler found */ 550#endif /* PPP_COMPRESS */ 551 552 case PPPIOCGNPMODE: 553 case PPPIOCSNPMODE: 554 npi = (struct npioctl *) data; 555 switch (npi->protocol) { 556 case PPP_IP: 557 npx = NP_IP; 558 break; 559 case PPP_IPV6: 560 npx = NP_IPV6; 561 break; 562 default: 563 return EINVAL; 564 } 565 if (cmd == PPPIOCGNPMODE) { 566 npi->mode = sc->sc_npmode[npx]; 567 } else { 568 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 569 return (error); 570 if (npi->mode != sc->sc_npmode[npx]) { 571 s = splnet(); 572 sc->sc_npmode[npx] = npi->mode; 573 if (npi->mode != NPMODE_QUEUE) { 574 ppp_requeue(sc); 575 ppp_restart(sc); 576 } 577 splx(s); 578 } 579 } 580 break; 581 582 case PPPIOCGIDLE: 583 s = splsoftnet(); 584 t = time.tv_sec; 585 ((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent; 586 ((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv; 587 splx(s); 588 break; 589 590#ifdef PPP_FILTER 591 case PPPIOCSPASS: 592 case PPPIOCSACTIVE: 593 /* These are no longer supported. */ 594 return EOPNOTSUPP; 595 596 case PPPIOCSIPASS: 597 case PPPIOCSOPASS: 598 case PPPIOCSIACTIVE: 599 case PPPIOCSOACTIVE: 600 nbp = (struct bpf_program *) data; 601 if ((unsigned) nbp->bf_len > BPF_MAXINSNS) 602 return EINVAL; 603 newcodelen = nbp->bf_len * sizeof(struct bpf_insn); 604 if (newcodelen != 0) { 605 newcode = malloc(newcodelen, M_DEVBUF, M_WAITOK); 606 /* WAITOK -- malloc() never fails. */ 607 if ((error = copyin((caddr_t)nbp->bf_insns, (caddr_t)newcode, 608 newcodelen)) != 0) { 609 free(newcode, M_DEVBUF); 610 return error; 611 } 612 if (!bpf_validate(newcode, nbp->bf_len)) { 613 free(newcode, M_DEVBUF); 614 return EINVAL; 615 } 616 } else 617 newcode = 0; 618 switch (cmd) { 619 case PPPIOCSIPASS: 620 bp = &sc->sc_pass_filt_in; 621 break; 622 623 case PPPIOCSOPASS: 624 bp = &sc->sc_pass_filt_out; 625 break; 626 627 case PPPIOCSIACTIVE: 628 bp = &sc->sc_active_filt_in; 629 break; 630 631 case PPPIOCSOACTIVE: 632 bp = &sc->sc_active_filt_out; 633 break; 634 } 635 oldcode = bp->bf_insns; 636 s = splnet(); 637 bp->bf_len = nbp->bf_len; 638 bp->bf_insns = newcode; 639 splx(s); 640 if (oldcode != 0) 641 free(oldcode, M_DEVBUF); 642 break; 643#endif /* PPP_FILTER */ 644 645 default: 646 return (EPASSTHROUGH); 647 } 648 return (0); 649} 650 651/* 652 * Process an ioctl request to the ppp network interface. 653 */ 654static int 655pppsioctl(ifp, cmd, data) 656 struct ifnet *ifp; 657 u_long cmd; 658 caddr_t data; 659{ 660 struct proc *p = curproc; /* XXX */ 661 struct ppp_softc *sc = ifp->if_softc; 662 struct ifaddr *ifa = (struct ifaddr *)data; 663 struct ifreq *ifr = (struct ifreq *)data; 664 struct ppp_stats *psp; 665#ifdef PPP_COMPRESS 666 struct ppp_comp_stats *pcp; 667#endif 668 int s = splnet(), error = 0; 669 670 switch (cmd) { 671 case SIOCSIFFLAGS: 672 if ((ifp->if_flags & IFF_RUNNING) == 0) 673 ifp->if_flags &= ~IFF_UP; 674 break; 675 676 case SIOCSIFADDR: 677 switch (ifa->ifa_addr->sa_family) { 678#ifdef INET 679 case AF_INET: 680 break; 681#endif 682#ifdef INET6 683 case AF_INET6: 684 break; 685#endif 686 default: 687 error = EAFNOSUPPORT; 688 break; 689 } 690 break; 691 692 case SIOCSIFDSTADDR: 693 switch (ifa->ifa_addr->sa_family) { 694#ifdef INET 695 case AF_INET: 696 break; 697#endif 698#ifdef INET6 699 case AF_INET6: 700 break; 701#endif 702 default: 703 error = EAFNOSUPPORT; 704 break; 705 } 706 break; 707 708 case SIOCSIFMTU: 709 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 710 break; 711 sc->sc_if.if_mtu = ifr->ifr_mtu; 712 break; 713 714 case SIOCGIFMTU: 715 ifr->ifr_mtu = sc->sc_if.if_mtu; 716 break; 717 718 case SIOCADDMULTI: 719 case SIOCDELMULTI: 720 if (ifr == 0) { 721 error = EAFNOSUPPORT; 722 break; 723 } 724 switch (ifr->ifr_addr.sa_family) { 725#ifdef INET 726 case AF_INET: 727 break; 728#endif 729#ifdef INET6 730 case AF_INET6: 731 break; 732#endif 733 default: 734 error = EAFNOSUPPORT; 735 break; 736 } 737 break; 738 739 case SIOCGPPPSTATS: 740 psp = &((struct ifpppstatsreq *) data)->stats; 741 memset(psp, 0, sizeof(*psp)); 742 psp->p = sc->sc_stats; 743#if defined(VJC) && !defined(SL_NO_STATS) 744 if (sc->sc_comp) { 745 psp->vj.vjs_packets = sc->sc_comp->sls_packets; 746 psp->vj.vjs_compressed = sc->sc_comp->sls_compressed; 747 psp->vj.vjs_searches = sc->sc_comp->sls_searches; 748 psp->vj.vjs_misses = sc->sc_comp->sls_misses; 749 psp->vj.vjs_uncompressedin = sc->sc_comp->sls_uncompressedin; 750 psp->vj.vjs_compressedin = sc->sc_comp->sls_compressedin; 751 psp->vj.vjs_errorin = sc->sc_comp->sls_errorin; 752 psp->vj.vjs_tossed = sc->sc_comp->sls_tossed; 753 } 754#endif /* VJC */ 755 break; 756 757#ifdef PPP_COMPRESS 758 case SIOCGPPPCSTATS: 759 pcp = &((struct ifpppcstatsreq *) data)->stats; 760 memset(pcp, 0, sizeof(*pcp)); 761 if (sc->sc_xc_state != NULL) 762 (*sc->sc_xcomp->comp_stat)(sc->sc_xc_state, &pcp->c); 763 if (sc->sc_rc_state != NULL) 764 (*sc->sc_rcomp->decomp_stat)(sc->sc_rc_state, &pcp->d); 765 break; 766#endif /* PPP_COMPRESS */ 767 768 default: 769 error = EINVAL; 770 } 771 splx(s); 772 return (error); 773} 774 775/* 776 * Queue a packet. Start transmission if not active. 777 * Packet is placed in Information field of PPP frame. 778 */ 779int 780pppoutput(ifp, m0, dst, rtp) 781 struct ifnet *ifp; 782 struct mbuf *m0; 783 struct sockaddr *dst; 784 struct rtentry *rtp; 785{ 786 struct ppp_softc *sc = ifp->if_softc; 787 int protocol, address, control; 788 u_char *cp; 789 int s, error; 790#ifdef INET 791 struct ip *ip; 792#endif 793 struct ifqueue *ifq; 794 enum NPmode mode; 795 int len; 796 struct mbuf *m; 797 ALTQ_DECL(struct altq_pktattr pktattr;) 798 799 if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0 800 || ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) { 801 error = ENETDOWN; /* sort of */ 802 goto bad; 803 } 804 805 IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family, &pktattr); 806 807 /* 808 * Compute PPP header. 809 */ 810 m0->m_flags &= ~M_HIGHPRI; 811 switch (dst->sa_family) { 812#ifdef INET 813 case AF_INET: 814 address = PPP_ALLSTATIONS; 815 control = PPP_UI; 816 protocol = PPP_IP; 817 mode = sc->sc_npmode[NP_IP]; 818 819 /* 820 * If this packet has the "low delay" bit set in the IP header, 821 * put it on the fastq instead. 822 */ 823 ip = mtod(m0, struct ip *); 824 if (ip->ip_tos & IPTOS_LOWDELAY) 825 m0->m_flags |= M_HIGHPRI; 826 break; 827#endif 828#ifdef INET6 829 case AF_INET6: 830 address = PPP_ALLSTATIONS; /*XXX*/ 831 control = PPP_UI; /*XXX*/ 832 protocol = PPP_IPV6; 833 mode = sc->sc_npmode[NP_IPV6]; 834 835#if 0 /* XXX flowinfo/traffic class, maybe? */ 836 /* 837 * If this packet has the "low delay" bit set in the IP header, 838 * put it on the fastq instead. 839 */ 840 ip = mtod(m0, struct ip *); 841 if (ip->ip_tos & IPTOS_LOWDELAY) 842 m0->m_flags |= M_HIGHPRI; 843#endif 844 break; 845#endif 846 case AF_UNSPEC: 847 address = PPP_ADDRESS(dst->sa_data); 848 control = PPP_CONTROL(dst->sa_data); 849 protocol = PPP_PROTOCOL(dst->sa_data); 850 mode = NPMODE_PASS; 851 break; 852 default: 853 printf("%s: af%d not supported\n", ifp->if_xname, dst->sa_family); 854 error = EAFNOSUPPORT; 855 goto bad; 856 } 857 858 /* 859 * Drop this packet, or return an error, if necessary. 860 */ 861 if (mode == NPMODE_ERROR) { 862 error = ENETDOWN; 863 goto bad; 864 } 865 if (mode == NPMODE_DROP) { 866 error = 0; 867 goto bad; 868 } 869 870 /* 871 * Add PPP header. If no space in first mbuf, allocate another. 872 * (This assumes M_LEADINGSPACE is always 0 for a cluster mbuf.) 873 */ 874 if (M_LEADINGSPACE(m0) < PPP_HDRLEN) { 875 m0 = m_prepend(m0, PPP_HDRLEN, M_DONTWAIT); 876 if (m0 == 0) { 877 error = ENOBUFS; 878 goto bad; 879 } 880 m0->m_len = 0; 881 } else 882 m0->m_data -= PPP_HDRLEN; 883 884 cp = mtod(m0, u_char *); 885 *cp++ = address; 886 *cp++ = control; 887 *cp++ = protocol >> 8; 888 *cp++ = protocol & 0xff; 889 m0->m_len += PPP_HDRLEN; 890 891 len = 0; 892 for (m = m0; m != 0; m = m->m_next) 893 len += m->m_len; 894 895 if (sc->sc_flags & SC_LOG_OUTPKT) { 896 printf("%s output: ", ifp->if_xname); 897 pppdumpm(m0); 898 } 899 900 if ((protocol & 0x8000) == 0) { 901#ifdef PPP_FILTER 902 /* 903 * Apply the pass and active filters to the packet, 904 * but only if it is a data packet. 905 */ 906 if (sc->sc_pass_filt_out.bf_insns != 0 907 && bpf_filter(sc->sc_pass_filt_out.bf_insns, (u_char *) m0, 908 len, 0) == 0) { 909 error = 0; /* drop this packet */ 910 goto bad; 911 } 912 913 /* 914 * Update the time we sent the most recent packet. 915 */ 916 if (sc->sc_active_filt_out.bf_insns == 0 917 || bpf_filter(sc->sc_active_filt_out.bf_insns, (u_char *) m0, 918 len, 0)) 919 sc->sc_last_sent = time.tv_sec; 920#else 921 /* 922 * Update the time we sent the most recent packet. 923 */ 924 sc->sc_last_sent = time.tv_sec; 925#endif /* PPP_FILTER */ 926 } 927 928#if NBPFILTER > 0 929 /* 930 * See if bpf wants to look at the packet. 931 */ 932 if (sc->sc_if.if_bpf) 933 bpf_mtap(sc->sc_if.if_bpf, m0); 934#endif 935 936 /* 937 * Put the packet on the appropriate queue. 938 */ 939 s = splnet(); 940 if (mode == NPMODE_QUEUE) { 941 /* XXX we should limit the number of packets on this queue */ 942 *sc->sc_npqtail = m0; 943 m0->m_nextpkt = NULL; 944 sc->sc_npqtail = &m0->m_nextpkt; 945 } else { 946 if ((m0->m_flags & M_HIGHPRI) 947#ifdef ALTQ 948 && ALTQ_IS_ENABLED(&sc->sc_if.if_snd) == 0 949#endif 950 ) { 951 ifq = &sc->sc_fastq; 952 if (IF_QFULL(ifq) && dst->sa_family != AF_UNSPEC) { 953 IF_DROP(ifq); 954 splx(s); 955 error = ENOBUFS; 956 goto bad; 957 } else { 958 IF_ENQUEUE(ifq, m0); 959 error = 0; 960 } 961 } else 962 IFQ_ENQUEUE(&sc->sc_if.if_snd, m0, &pktattr, error); 963 if (error) { 964 splx(s); 965 sc->sc_if.if_oerrors++; 966 sc->sc_stats.ppp_oerrors++; 967 return (error); 968 } 969 ppp_restart(sc); 970 } 971 ifp->if_opackets++; 972 ifp->if_obytes += len; 973 974 splx(s); 975 return (0); 976 977bad: 978 m_freem(m0); 979 return (error); 980} 981 982/* 983 * After a change in the NPmode for some NP, move packets from the 984 * npqueue to the send queue or the fast queue as appropriate. 985 * Should be called at splnet, since we muck with the queues. 986 */ 987static void 988ppp_requeue(sc) 989 struct ppp_softc *sc; 990{ 991 struct mbuf *m, **mpp; 992 struct ifqueue *ifq; 993 enum NPmode mode; 994 int error; 995 996 for (mpp = &sc->sc_npqueue; (m = *mpp) != NULL; ) { 997 switch (PPP_PROTOCOL(mtod(m, u_char *))) { 998 case PPP_IP: 999 mode = sc->sc_npmode[NP_IP]; 1000 break; 1001 case PPP_IPV6: 1002 mode = sc->sc_npmode[NP_IPV6]; 1003 break; 1004 default: 1005 mode = NPMODE_PASS; 1006 } 1007 1008 switch (mode) { 1009 case NPMODE_PASS: 1010 /* 1011 * This packet can now go on one of the queues to be sent. 1012 */ 1013 *mpp = m->m_nextpkt; 1014 m->m_nextpkt = NULL; 1015 if ((m->m_flags & M_HIGHPRI) 1016#ifdef ALTQ 1017 && ALTQ_IS_ENABLED(&sc->sc_if.if_snd) == 0 1018#endif 1019 ) { 1020 ifq = &sc->sc_fastq; 1021 if (IF_QFULL(ifq)) { 1022 IF_DROP(ifq); 1023 m_freem(m); 1024 error = ENOBUFS; 1025 } else { 1026 IF_ENQUEUE(ifq, m); 1027 error = 0; 1028 } 1029 } else 1030 IFQ_ENQUEUE(&sc->sc_if.if_snd, m, NULL, error); 1031 if (error) { 1032 sc->sc_if.if_oerrors++; 1033 sc->sc_stats.ppp_oerrors++; 1034 } 1035 break; 1036 1037 case NPMODE_DROP: 1038 case NPMODE_ERROR: 1039 *mpp = m->m_nextpkt; 1040 m_freem(m); 1041 break; 1042 1043 case NPMODE_QUEUE: 1044 mpp = &m->m_nextpkt; 1045 break; 1046 } 1047 } 1048 sc->sc_npqtail = mpp; 1049} 1050 1051/* 1052 * Transmitter has finished outputting some stuff; 1053 * remember to call sc->sc_start later at splsoftnet. 1054 */ 1055void 1056ppp_restart(sc) 1057 struct ppp_softc *sc; 1058{ 1059 int s = splhigh(); /* XXX IMP ME HARDER */ 1060 1061 sc->sc_flags &= ~SC_TBUSY; 1062#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 1063 softintr_schedule(sc->sc_si); 1064#else 1065 schednetisr(NETISR_PPP); 1066#endif 1067 splx(s); 1068} 1069 1070/* 1071 * Get a packet to send. This procedure is intended to be called at 1072 * splsoftnet, since it may involve time-consuming operations such as 1073 * applying VJ compression, packet compression, address/control and/or 1074 * protocol field compression to the packet. 1075 */ 1076struct mbuf * 1077ppp_dequeue(sc) 1078 struct ppp_softc *sc; 1079{ 1080 struct mbuf *m, *mp; 1081 u_char *cp; 1082 int address, control, protocol; 1083 int s; 1084 1085 /* 1086 * Grab a packet to send: first try the fast queue, then the 1087 * normal queue. 1088 */ 1089 s = splnet(); 1090 IF_DEQUEUE(&sc->sc_fastq, m); 1091 if (m == NULL) 1092 IFQ_DEQUEUE(&sc->sc_if.if_snd, m); 1093 splx(s); 1094 1095 if (m == NULL) 1096 return NULL; 1097 1098 ++sc->sc_stats.ppp_opackets; 1099 1100 /* 1101 * Extract the ppp header of the new packet. 1102 * The ppp header will be in one mbuf. 1103 */ 1104 cp = mtod(m, u_char *); 1105 address = PPP_ADDRESS(cp); 1106 control = PPP_CONTROL(cp); 1107 protocol = PPP_PROTOCOL(cp); 1108 1109 switch (protocol) { 1110 case PPP_IP: 1111#ifdef VJC 1112 /* 1113 * If the packet is a TCP/IP packet, see if we can compress it. 1114 */ 1115 if ((sc->sc_flags & SC_COMP_TCP) && sc->sc_comp != NULL) { 1116 struct ip *ip; 1117 int type; 1118 1119 mp = m; 1120 ip = (struct ip *) (cp + PPP_HDRLEN); 1121 if (mp->m_len <= PPP_HDRLEN) { 1122 mp = mp->m_next; 1123 if (mp == NULL) 1124 break; 1125 ip = mtod(mp, struct ip *); 1126 } 1127 /* this code assumes the IP/TCP header is in one non-shared mbuf */ 1128 if (ip->ip_p == IPPROTO_TCP) { 1129 type = sl_compress_tcp(mp, ip, sc->sc_comp, 1130 !(sc->sc_flags & SC_NO_TCP_CCID)); 1131 switch (type) { 1132 case TYPE_UNCOMPRESSED_TCP: 1133 protocol = PPP_VJC_UNCOMP; 1134 break; 1135 case TYPE_COMPRESSED_TCP: 1136 protocol = PPP_VJC_COMP; 1137 cp = mtod(m, u_char *); 1138 cp[0] = address; /* header has moved */ 1139 cp[1] = control; 1140 cp[2] = 0; 1141 break; 1142 } 1143 cp[3] = protocol; /* update protocol in PPP header */ 1144 } 1145 } 1146#endif /* VJC */ 1147 break; 1148 1149#ifdef PPP_COMPRESS 1150 case PPP_CCP: 1151 ppp_ccp(sc, m, 0); 1152 break; 1153#endif /* PPP_COMPRESS */ 1154 } 1155 1156#ifdef PPP_COMPRESS 1157 if (protocol != PPP_LCP && protocol != PPP_CCP 1158 && sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) { 1159 struct mbuf *mcomp = NULL; 1160 int slen; 1161 1162 slen = 0; 1163 for (mp = m; mp != NULL; mp = mp->m_next) 1164 slen += mp->m_len; 1165 (*sc->sc_xcomp->compress) 1166 (sc->sc_xc_state, &mcomp, m, slen, sc->sc_if.if_mtu + PPP_HDRLEN); 1167 if (mcomp != NULL) { 1168 if (sc->sc_flags & SC_CCP_UP) { 1169 /* Send the compressed packet instead of the original. */ 1170 m_freem(m); 1171 m = mcomp; 1172 cp = mtod(m, u_char *); 1173 protocol = cp[3]; 1174 } else { 1175 /* Can't transmit compressed packets until CCP is up. */ 1176 m_freem(mcomp); 1177 } 1178 } 1179 } 1180#endif /* PPP_COMPRESS */ 1181 1182 /* 1183 * Compress the address/control and protocol, if possible. 1184 */ 1185 if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS && 1186 control == PPP_UI && protocol != PPP_ALLSTATIONS && 1187 protocol != PPP_LCP) { 1188 /* can compress address/control */ 1189 m->m_data += 2; 1190 m->m_len -= 2; 1191 } 1192 if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) { 1193 /* can compress protocol */ 1194 if (mtod(m, u_char *) == cp) { 1195 cp[2] = cp[1]; /* move address/control up */ 1196 cp[1] = cp[0]; 1197 } 1198 ++m->m_data; 1199 --m->m_len; 1200 } 1201 1202 return m; 1203} 1204 1205#ifndef __HAVE_GENERIC_SOFT_INTERRUPTS 1206void 1207pppnetisr(void) 1208{ 1209 struct ppp_softc *sc; 1210 int i; 1211 1212 for (i = 0; i < NPPP; i++) { 1213 sc = &ppp_softc[i]; 1214 pppintr(sc); 1215 } 1216} 1217#endif 1218 1219/* 1220 * Software interrupt routine, called at splsoftnet. 1221 */ 1222void 1223pppintr(void *arg) 1224{ 1225 struct ppp_softc *sc = arg; 1226 struct mbuf *m; 1227 int s; 1228 1229 if (!(sc->sc_flags & SC_TBUSY) 1230 && (IFQ_IS_EMPTY(&sc->sc_if.if_snd) == 0 || sc->sc_fastq.ifq_head 1231 || sc->sc_outm)) { 1232 s = splhigh(); /* XXX IMP ME HARDER */ 1233 sc->sc_flags |= SC_TBUSY; 1234 splx(s); 1235 (*sc->sc_start)(sc); 1236 } 1237 for (;;) { 1238 s = splnet(); 1239 IF_DEQUEUE(&sc->sc_rawq, m); 1240 splx(s); 1241 if (m == NULL) 1242 break; 1243 ppp_inproc(sc, m); 1244 } 1245} 1246 1247#ifdef PPP_COMPRESS 1248/* 1249 * Handle a CCP packet. `rcvd' is 1 if the packet was received, 1250 * 0 if it is about to be transmitted. 1251 */ 1252static void 1253ppp_ccp(sc, m, rcvd) 1254 struct ppp_softc *sc; 1255 struct mbuf *m; 1256 int rcvd; 1257{ 1258 u_char *dp, *ep; 1259 struct mbuf *mp; 1260 int slen, s; 1261 1262 /* 1263 * Get a pointer to the data after the PPP header. 1264 */ 1265 if (m->m_len <= PPP_HDRLEN) { 1266 mp = m->m_next; 1267 if (mp == NULL) 1268 return; 1269 dp = (mp != NULL)? mtod(mp, u_char *): NULL; 1270 } else { 1271 mp = m; 1272 dp = mtod(mp, u_char *) + PPP_HDRLEN; 1273 } 1274 1275 ep = mtod(mp, u_char *) + mp->m_len; 1276 if (dp + CCP_HDRLEN > ep) 1277 return; 1278 slen = CCP_LENGTH(dp); 1279 if (dp + slen > ep) { 1280 if (sc->sc_flags & SC_DEBUG) 1281 printf("if_ppp/ccp: not enough data in mbuf (%p+%x > %p+%x)\n", 1282 dp, slen, mtod(mp, u_char *), mp->m_len); 1283 return; 1284 } 1285 1286 switch (CCP_CODE(dp)) { 1287 case CCP_CONFREQ: 1288 case CCP_TERMREQ: 1289 case CCP_TERMACK: 1290 /* CCP must be going down - disable compression */ 1291 if (sc->sc_flags & SC_CCP_UP) { 1292 s = splhigh(); /* XXX IMP ME HARDER */ 1293 sc->sc_flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN); 1294 splx(s); 1295 } 1296 break; 1297 1298 case CCP_CONFACK: 1299 if (sc->sc_flags & SC_CCP_OPEN && !(sc->sc_flags & SC_CCP_UP) 1300 && slen >= CCP_HDRLEN + CCP_OPT_MINLEN 1301 && slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) { 1302 if (!rcvd) { 1303 /* we're agreeing to send compressed packets. */ 1304 if (sc->sc_xc_state != NULL 1305 && (*sc->sc_xcomp->comp_init) 1306 (sc->sc_xc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, 1307 sc->sc_unit, 0, sc->sc_flags & SC_DEBUG)) { 1308 s = splhigh(); /* XXX IMP ME HARDER */ 1309 sc->sc_flags |= SC_COMP_RUN; 1310 splx(s); 1311 } 1312 } else { 1313 /* peer is agreeing to send compressed packets. */ 1314 if (sc->sc_rc_state != NULL 1315 && (*sc->sc_rcomp->decomp_init) 1316 (sc->sc_rc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, 1317 sc->sc_unit, 0, sc->sc_mru, 1318 sc->sc_flags & SC_DEBUG)) { 1319 s = splhigh(); /* XXX IMP ME HARDER */ 1320 sc->sc_flags |= SC_DECOMP_RUN; 1321 sc->sc_flags &= ~(SC_DC_ERROR | SC_DC_FERROR); 1322 splx(s); 1323 } 1324 } 1325 } 1326 break; 1327 1328 case CCP_RESETACK: 1329 if (sc->sc_flags & SC_CCP_UP) { 1330 if (!rcvd) { 1331 if (sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) 1332 (*sc->sc_xcomp->comp_reset)(sc->sc_xc_state); 1333 } else { 1334 if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) { 1335 (*sc->sc_rcomp->decomp_reset)(sc->sc_rc_state); 1336 s = splhigh(); /* XXX IMP ME HARDER */ 1337 sc->sc_flags &= ~SC_DC_ERROR; 1338 splx(s); 1339 } 1340 } 1341 } 1342 break; 1343 } 1344} 1345 1346/* 1347 * CCP is down; free (de)compressor state if necessary. 1348 */ 1349static void 1350ppp_ccp_closed(sc) 1351 struct ppp_softc *sc; 1352{ 1353 if (sc->sc_xc_state) { 1354 (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); 1355 sc->sc_xc_state = NULL; 1356 } 1357 if (sc->sc_rc_state) { 1358 (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); 1359 sc->sc_rc_state = NULL; 1360 } 1361} 1362#endif /* PPP_COMPRESS */ 1363 1364/* 1365 * PPP packet input routine. 1366 * The caller has checked and removed the FCS and has inserted 1367 * the address/control bytes and the protocol high byte if they 1368 * were omitted. 1369 */ 1370void 1371ppppktin(sc, m, lost) 1372 struct ppp_softc *sc; 1373 struct mbuf *m; 1374 int lost; 1375{ 1376 int s = splhigh(); /* XXX IMP ME HARDER */ 1377 1378 if (lost) 1379 m->m_flags |= M_ERRMARK; 1380 IF_ENQUEUE(&sc->sc_rawq, m); 1381#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 1382 softintr_schedule(sc->sc_si); 1383#else 1384 schednetisr(NETISR_PPP); 1385#endif 1386 splx(s); 1387} 1388 1389/* 1390 * Process a received PPP packet, doing decompression as necessary. 1391 * Should be called at splsoftnet. 1392 */ 1393#define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \ 1394 TYPE_UNCOMPRESSED_TCP) 1395 1396static void 1397ppp_inproc(sc, m) 1398 struct ppp_softc *sc; 1399 struct mbuf *m; 1400{ 1401 struct ifnet *ifp = &sc->sc_if; 1402 struct ifqueue *inq; 1403 int s, ilen, proto, rv; 1404 u_char *cp, adrs, ctrl; 1405 struct mbuf *mp, *dmp = NULL; 1406#ifdef VJC 1407 int xlen; 1408 u_char *iphdr; 1409 u_int hlen; 1410#endif 1411 1412 sc->sc_stats.ppp_ipackets++; 1413 1414 if (sc->sc_flags & SC_LOG_INPKT) { 1415 ilen = 0; 1416 for (mp = m; mp != NULL; mp = mp->m_next) 1417 ilen += mp->m_len; 1418 printf("%s: got %d bytes\n", ifp->if_xname, ilen); 1419 pppdumpm(m); 1420 } 1421 1422 cp = mtod(m, u_char *); 1423 adrs = PPP_ADDRESS(cp); 1424 ctrl = PPP_CONTROL(cp); 1425 proto = PPP_PROTOCOL(cp); 1426 1427 if (m->m_flags & M_ERRMARK) { 1428 m->m_flags &= ~M_ERRMARK; 1429 s = splhigh(); /* XXX IMP ME HARDER */ 1430 sc->sc_flags |= SC_VJ_RESET; 1431 splx(s); 1432 } 1433 1434#ifdef PPP_COMPRESS 1435 /* 1436 * Decompress this packet if necessary, update the receiver's 1437 * dictionary, or take appropriate action on a CCP packet. 1438 */ 1439 if (proto == PPP_COMP && sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN) 1440 && !(sc->sc_flags & SC_DC_ERROR) && !(sc->sc_flags & SC_DC_FERROR)) { 1441 /* decompress this packet */ 1442 rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp); 1443 if (rv == DECOMP_OK) { 1444 m_freem(m); 1445 if (dmp == NULL) { 1446 /* no error, but no decompressed packet produced */ 1447 return; 1448 } 1449 m = dmp; 1450 cp = mtod(m, u_char *); 1451 proto = PPP_PROTOCOL(cp); 1452 1453 } else { 1454 /* 1455 * An error has occurred in decompression. 1456 * Pass the compressed packet up to pppd, which may take 1457 * CCP down or issue a Reset-Req. 1458 */ 1459 if (sc->sc_flags & SC_DEBUG) 1460 printf("%s: decompress failed %d\n", ifp->if_xname, rv); 1461 s = splhigh(); /* XXX IMP ME HARDER */ 1462 sc->sc_flags |= SC_VJ_RESET; 1463 if (rv == DECOMP_ERROR) 1464 sc->sc_flags |= SC_DC_ERROR; 1465 else 1466 sc->sc_flags |= SC_DC_FERROR; 1467 splx(s); 1468 } 1469 1470 } else { 1471 if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) { 1472 (*sc->sc_rcomp->incomp)(sc->sc_rc_state, m); 1473 } 1474 if (proto == PPP_CCP) { 1475 ppp_ccp(sc, m, 1); 1476 } 1477 } 1478#endif 1479 1480 ilen = 0; 1481 for (mp = m; mp != NULL; mp = mp->m_next) 1482 ilen += mp->m_len; 1483 1484#ifdef VJC 1485 if (sc->sc_flags & SC_VJ_RESET) { 1486 /* 1487 * If we've missed a packet, we must toss subsequent compressed 1488 * packets which don't have an explicit connection ID. 1489 */ 1490 if (sc->sc_comp) 1491 sl_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp); 1492 s = splhigh(); /* XXX IMP ME HARDER */ 1493 sc->sc_flags &= ~SC_VJ_RESET; 1494 splx(s); 1495 } 1496 1497 /* 1498 * See if we have a VJ-compressed packet to uncompress. 1499 */ 1500 if (proto == PPP_VJC_COMP) { 1501 if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) 1502 goto bad; 1503 1504 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN, 1505 ilen - PPP_HDRLEN, TYPE_COMPRESSED_TCP, 1506 sc->sc_comp, &iphdr, &hlen); 1507 1508 if (xlen <= 0) { 1509 if (sc->sc_flags & SC_DEBUG) 1510 printf("%s: VJ uncompress failed on type comp\n", 1511 ifp->if_xname); 1512 goto bad; 1513 } 1514 1515 /* Copy the PPP and IP headers into a new mbuf. */ 1516 MGETHDR(mp, M_DONTWAIT, MT_DATA); 1517 if (mp == NULL) 1518 goto bad; 1519 mp->m_len = 0; 1520 mp->m_next = NULL; 1521 if (hlen + PPP_HDRLEN > MHLEN) { 1522 MCLGET(mp, M_DONTWAIT); 1523 if (M_TRAILINGSPACE(mp) < hlen + PPP_HDRLEN) { 1524 m_freem(mp); 1525 goto bad; /* lose if big headers and no clusters */ 1526 } 1527 } 1528 cp = mtod(mp, u_char *); 1529 cp[0] = adrs; 1530 cp[1] = ctrl; 1531 cp[2] = 0; 1532 cp[3] = PPP_IP; 1533 proto = PPP_IP; 1534 bcopy(iphdr, cp + PPP_HDRLEN, hlen); 1535 mp->m_len = hlen + PPP_HDRLEN; 1536 1537 /* 1538 * Trim the PPP and VJ headers off the old mbuf 1539 * and stick the new and old mbufs together. 1540 */ 1541 m->m_data += PPP_HDRLEN + xlen; 1542 m->m_len -= PPP_HDRLEN + xlen; 1543 if (m->m_len <= M_TRAILINGSPACE(mp)) { 1544 bcopy(mtod(m, u_char *), mtod(mp, u_char *) + mp->m_len, m->m_len); 1545 mp->m_len += m->m_len; 1546 MFREE(m, mp->m_next); 1547 } else 1548 mp->m_next = m; 1549 m = mp; 1550 ilen += hlen - xlen; 1551 1552 } else if (proto == PPP_VJC_UNCOMP) { 1553 if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) 1554 goto bad; 1555 1556 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN, 1557 ilen - PPP_HDRLEN, TYPE_UNCOMPRESSED_TCP, 1558 sc->sc_comp, &iphdr, &hlen); 1559 1560 if (xlen < 0) { 1561 if (sc->sc_flags & SC_DEBUG) 1562 printf("%s: VJ uncompress failed on type uncomp\n", 1563 ifp->if_xname); 1564 goto bad; 1565 } 1566 1567 proto = PPP_IP; 1568 cp[3] = PPP_IP; 1569 } 1570#endif /* VJC */ 1571 1572 /* 1573 * If the packet will fit in a header mbuf, don't waste a 1574 * whole cluster on it. 1575 */ 1576 if (ilen <= MHLEN && M_IS_CLUSTER(m)) { 1577 MGETHDR(mp, M_DONTWAIT, MT_DATA); 1578 if (mp != NULL) { 1579 m_copydata(m, 0, ilen, mtod(mp, caddr_t)); 1580 m_freem(m); 1581 m = mp; 1582 m->m_len = ilen; 1583 } 1584 } 1585 m->m_pkthdr.len = ilen; 1586 m->m_pkthdr.rcvif = ifp; 1587 1588 if ((proto & 0x8000) == 0) { 1589#ifdef PPP_FILTER 1590 /* 1591 * See whether we want to pass this packet, and 1592 * if it counts as link activity. 1593 */ 1594 if (sc->sc_pass_filt_in.bf_insns != 0 1595 && bpf_filter(sc->sc_pass_filt_in.bf_insns, (u_char *) m, 1596 ilen, 0) == 0) { 1597 /* drop this packet */ 1598 m_freem(m); 1599 return; 1600 } 1601 if (sc->sc_active_filt_in.bf_insns == 0 1602 || bpf_filter(sc->sc_active_filt_in.bf_insns, (u_char *) m, 1603 ilen, 0)) 1604 sc->sc_last_recv = time.tv_sec; 1605#else 1606 /* 1607 * Record the time that we received this packet. 1608 */ 1609 sc->sc_last_recv = time.tv_sec; 1610#endif /* PPP_FILTER */ 1611 } 1612 1613#if NBPFILTER > 0 1614 /* See if bpf wants to look at the packet. */ 1615 if (sc->sc_if.if_bpf) 1616 bpf_mtap(sc->sc_if.if_bpf, m); 1617#endif 1618 1619 rv = 0; 1620 switch (proto) { 1621#ifdef INET 1622 case PPP_IP: 1623 /* 1624 * IP packet - take off the ppp header and pass it up to IP. 1625 */ 1626 if ((ifp->if_flags & IFF_UP) == 0 1627 || sc->sc_npmode[NP_IP] != NPMODE_PASS) { 1628 /* interface is down - drop the packet. */ 1629 m_freem(m); 1630 return; 1631 } 1632 m->m_pkthdr.len -= PPP_HDRLEN; 1633 m->m_data += PPP_HDRLEN; 1634 m->m_len -= PPP_HDRLEN; 1635#ifdef GATEWAY 1636 if (ipflow_fastforward(m)) 1637 return; 1638#endif 1639 schednetisr(NETISR_IP); 1640 inq = &ipintrq; 1641 break; 1642#endif 1643 1644#ifdef INET6 1645 case PPP_IPV6: 1646 /* 1647 * IPv6 packet - take off the ppp header and pass it up to IPv6. 1648 */ 1649 if ((ifp->if_flags & IFF_UP) == 0 1650 || sc->sc_npmode[NP_IPV6] != NPMODE_PASS) { 1651 /* interface is down - drop the packet. */ 1652 m_freem(m); 1653 return; 1654 } 1655 m->m_pkthdr.len -= PPP_HDRLEN; 1656 m->m_data += PPP_HDRLEN; 1657 m->m_len -= PPP_HDRLEN; 1658 schednetisr(NETISR_IPV6); 1659 inq = &ip6intrq; 1660 break; 1661#endif 1662 1663 default: 1664 /* 1665 * Some other protocol - place on input queue for read(). 1666 */ 1667 inq = &sc->sc_inq; 1668 rv = 1; 1669 break; 1670 } 1671 1672 /* 1673 * Put the packet on the appropriate input queue. 1674 */ 1675 s = splnet(); 1676 if (IF_QFULL(inq)) { 1677 IF_DROP(inq); 1678 splx(s); 1679 if (sc->sc_flags & SC_DEBUG) 1680 printf("%s: input queue full\n", ifp->if_xname); 1681 ifp->if_iqdrops++; 1682 goto bad; 1683 } 1684 IF_ENQUEUE(inq, m); 1685 splx(s); 1686 ifp->if_ipackets++; 1687 ifp->if_ibytes += ilen; 1688 1689 if (rv) 1690 (*sc->sc_ctlp)(sc); 1691 1692 return; 1693 1694 bad: 1695 m_freem(m); 1696 sc->sc_if.if_ierrors++; 1697 sc->sc_stats.ppp_ierrors++; 1698} 1699 1700#define MAX_DUMP_BYTES 128 1701 1702static void 1703pppdumpm(m0) 1704 struct mbuf *m0; 1705{ 1706 char buf[3*MAX_DUMP_BYTES+4]; 1707 char *bp = buf; 1708 struct mbuf *m; 1709 static char digits[] = "0123456789abcdef"; 1710 1711 for (m = m0; m; m = m->m_next) { 1712 int l = m->m_len; 1713 u_char *rptr = (u_char *)m->m_data; 1714 1715 while (l--) { 1716 if (bp > buf + sizeof(buf) - 4) 1717 goto done; 1718 *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */ 1719 *bp++ = digits[*rptr++ & 0xf]; 1720 } 1721 1722 if (m->m_next) { 1723 if (bp > buf + sizeof(buf) - 3) 1724 goto done; 1725 *bp++ = '|'; 1726 } else 1727 *bp++ = ' '; 1728 } 1729done: 1730 if (m) 1731 *bp++ = '>'; 1732 *bp = 0; 1733 printf("%s\n", buf); 1734} 1735 1736#ifdef ALTQ 1737/* 1738 * a wrapper to transmit a packet from if_start since ALTQ uses 1739 * if_start to send a packet. 1740 */ 1741static void 1742ppp_ifstart(ifp) 1743 struct ifnet *ifp; 1744{ 1745 struct ppp_softc *sc; 1746 1747 sc = ifp->if_softc; 1748 (*sc->sc_start)(sc); 1749} 1750#endif 1751