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