1 /* $NetBSD: if_ppp.c,v 1.71 2001/08/05 18:07:55 jdolecek 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 memset((char *)&sc->sc_stats, 0, 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, npx; 384 u_int nb; 385 struct ppp_option_data *odp; 386 struct compressor **cp; 387 struct npioctl *npi; 388 time_t t; 389 #ifdef PPP_FILTER 390 struct bpf_program *bp, *nbp; 391 struct bpf_insn *newcode, *oldcode; 392 int newcodelen; 393 #endif /* PPP_FILTER */ 394 #ifdef PPP_COMPRESS 395 u_char ccp_option[CCP_MAX_OPTION_LENGTH]; 396 #endif 397 398 switch (cmd) { 399 case FIONREAD: 400 *(int *)data = sc->sc_inq.ifq_len; 401 break; 402 403 case PPPIOCGUNIT: 404 *(int *)data = sc->sc_unit; /* XXX */ 405 break; 406 407 case PPPIOCGFLAGS: 408 *(u_int *)data = sc->sc_flags; 409 break; 410 411 case PPPIOCSFLAGS: 412 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 413 return (error); 414 flags = *(int *)data & SC_MASK; 415 s = splsoftnet(); 416 #ifdef PPP_COMPRESS 417 if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN)) 418 ppp_ccp_closed(sc); 419 #endif 420 splhigh(); /* XXX IMP ME HARDER */ 421 sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags; 422 splx(s); 423 break; 424 425 case PPPIOCSMRU: 426 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 427 return (error); 428 mru = *(int *)data; 429 if (mru >= PPP_MINMRU && mru <= PPP_MAXMRU) 430 sc->sc_mru = mru; 431 break; 432 433 case PPPIOCGMRU: 434 *(int *)data = sc->sc_mru; 435 break; 436 437 #ifdef VJC 438 case PPPIOCSMAXCID: 439 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 440 return (error); 441 if (sc->sc_comp) { 442 s = splsoftnet(); 443 sl_compress_setup(sc->sc_comp, *(int *)data); 444 splx(s); 445 } 446 break; 447 #endif 448 449 case PPPIOCXFERUNIT: 450 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 451 return (error); 452 sc->sc_xfer = p->p_pid; 453 break; 454 455 #ifdef PPP_COMPRESS 456 case PPPIOCSCOMPRESS: 457 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 458 return (error); 459 odp = (struct ppp_option_data *) data; 460 nb = odp->length; 461 if (nb > sizeof(ccp_option)) 462 nb = sizeof(ccp_option); 463 if ((error = copyin(odp->ptr, ccp_option, nb)) != 0) 464 return (error); 465 if (ccp_option[1] < 2) /* preliminary check on the length byte */ 466 return (EINVAL); 467 for (cp = ppp_compressors; *cp != NULL; ++cp) 468 if ((*cp)->compress_proto == ccp_option[0]) { 469 /* 470 * Found a handler for the protocol - try to allocate 471 * a compressor or decompressor. 472 */ 473 error = 0; 474 if (odp->transmit) { 475 s = splsoftnet(); 476 if (sc->sc_xc_state != NULL) 477 (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); 478 sc->sc_xcomp = *cp; 479 sc->sc_xc_state = (*cp)->comp_alloc(ccp_option, nb); 480 if (sc->sc_xc_state == NULL) { 481 if (sc->sc_flags & SC_DEBUG) 482 printf("%s: comp_alloc failed\n", 483 sc->sc_if.if_xname); 484 error = ENOBUFS; 485 } 486 splhigh(); /* XXX IMP ME HARDER */ 487 sc->sc_flags &= ~SC_COMP_RUN; 488 splx(s); 489 } else { 490 s = splsoftnet(); 491 if (sc->sc_rc_state != NULL) 492 (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); 493 sc->sc_rcomp = *cp; 494 sc->sc_rc_state = (*cp)->decomp_alloc(ccp_option, nb); 495 if (sc->sc_rc_state == NULL) { 496 if (sc->sc_flags & SC_DEBUG) 497 printf("%s: decomp_alloc failed\n", 498 sc->sc_if.if_xname); 499 error = ENOBUFS; 500 } 501 splhigh(); /* XXX IMP ME HARDER */ 502 sc->sc_flags &= ~SC_DECOMP_RUN; 503 splx(s); 504 } 505 return (error); 506 } 507 if (sc->sc_flags & SC_DEBUG) 508 printf("%s: no compressor for [%x %x %x], %x\n", 509 sc->sc_if.if_xname, ccp_option[0], ccp_option[1], 510 ccp_option[2], nb); 511 return (EINVAL); /* no handler found */ 512 #endif /* PPP_COMPRESS */ 513 514 case PPPIOCGNPMODE: 515 case PPPIOCSNPMODE: 516 npi = (struct npioctl *) data; 517 switch (npi->protocol) { 518 case PPP_IP: 519 npx = NP_IP; 520 break; 521 case PPP_IPV6: 522 npx = NP_IPV6; 523 break; 524 default: 525 return EINVAL; 526 } 527 if (cmd == PPPIOCGNPMODE) { 528 npi->mode = sc->sc_npmode[npx]; 529 } else { 530 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 531 return (error); 532 if (npi->mode != sc->sc_npmode[npx]) { 533 s = splnet(); 534 sc->sc_npmode[npx] = npi->mode; 535 if (npi->mode != NPMODE_QUEUE) { 536 ppp_requeue(sc); 537 ppp_restart(sc); 538 } 539 splx(s); 540 } 541 } 542 break; 543 544 case PPPIOCGIDLE: 545 s = splsoftnet(); 546 t = time.tv_sec; 547 ((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent; 548 ((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv; 549 splx(s); 550 break; 551 552 #ifdef PPP_FILTER 553 case PPPIOCSPASS: 554 case PPPIOCSACTIVE: 555 /* These are no longer supported. */ 556 return EOPNOTSUPP; 557 558 case PPPIOCSIPASS: 559 case PPPIOCSOPASS: 560 case PPPIOCSIACTIVE: 561 case PPPIOCSOACTIVE: 562 nbp = (struct bpf_program *) data; 563 if ((unsigned) nbp->bf_len > BPF_MAXINSNS) 564 return EINVAL; 565 newcodelen = nbp->bf_len * sizeof(struct bpf_insn); 566 if (newcodelen != 0) { 567 newcode = malloc(newcodelen, M_DEVBUF, M_WAITOK); 568 /* WAITOK -- malloc() never fails. */ 569 if ((error = copyin((caddr_t)nbp->bf_insns, (caddr_t)newcode, 570 newcodelen)) != 0) { 571 free(newcode, M_DEVBUF); 572 return error; 573 } 574 if (!bpf_validate(newcode, nbp->bf_len)) { 575 free(newcode, M_DEVBUF); 576 return EINVAL; 577 } 578 } else 579 newcode = 0; 580 switch (cmd) { 581 case PPPIOCSIPASS: 582 bp = &sc->sc_pass_filt_in; 583 break; 584 585 case PPPIOCSOPASS: 586 bp = &sc->sc_pass_filt_out; 587 break; 588 589 case PPPIOCSIACTIVE: 590 bp = &sc->sc_active_filt_in; 591 break; 592 593 case PPPIOCSOACTIVE: 594 bp = &sc->sc_active_filt_out; 595 break; 596 } 597 oldcode = bp->bf_insns; 598 s = splnet(); 599 bp->bf_len = nbp->bf_len; 600 bp->bf_insns = newcode; 601 splx(s); 602 if (oldcode != 0) 603 free(oldcode, M_DEVBUF); 604 break; 605 #endif /* PPP_FILTER */ 606 607 default: 608 return (-1); 609 } 610 return (0); 611 } 612 613 /* 614 * Process an ioctl request to the ppp network interface. 615 */ 616 static int 617 pppsioctl(ifp, cmd, data) 618 struct ifnet *ifp; 619 u_long cmd; 620 caddr_t data; 621 { 622 struct proc *p = curproc; /* XXX */ 623 struct ppp_softc *sc = ifp->if_softc; 624 struct ifaddr *ifa = (struct ifaddr *)data; 625 struct ifreq *ifr = (struct ifreq *)data; 626 struct ppp_stats *psp; 627 #ifdef PPP_COMPRESS 628 struct ppp_comp_stats *pcp; 629 #endif 630 int s = splnet(), error = 0; 631 632 switch (cmd) { 633 case SIOCSIFFLAGS: 634 if ((ifp->if_flags & IFF_RUNNING) == 0) 635 ifp->if_flags &= ~IFF_UP; 636 break; 637 638 case SIOCSIFADDR: 639 switch (ifa->ifa_addr->sa_family) { 640 #ifdef INET 641 case AF_INET: 642 break; 643 #endif 644 #ifdef INET6 645 case AF_INET6: 646 break; 647 #endif 648 default: 649 error = EAFNOSUPPORT; 650 break; 651 } 652 break; 653 654 case SIOCSIFDSTADDR: 655 switch (ifa->ifa_addr->sa_family) { 656 #ifdef INET 657 case AF_INET: 658 break; 659 #endif 660 #ifdef INET6 661 case AF_INET6: 662 break; 663 #endif 664 default: 665 error = EAFNOSUPPORT; 666 break; 667 } 668 break; 669 670 case SIOCSIFMTU: 671 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 672 break; 673 sc->sc_if.if_mtu = ifr->ifr_mtu; 674 break; 675 676 case SIOCGIFMTU: 677 ifr->ifr_mtu = sc->sc_if.if_mtu; 678 break; 679 680 case SIOCADDMULTI: 681 case SIOCDELMULTI: 682 if (ifr == 0) { 683 error = EAFNOSUPPORT; 684 break; 685 } 686 switch(ifr->ifr_addr.sa_family) { 687 #ifdef INET 688 case AF_INET: 689 break; 690 #endif 691 #ifdef INET6 692 case AF_INET6: 693 break; 694 #endif 695 default: 696 error = EAFNOSUPPORT; 697 break; 698 } 699 break; 700 701 case SIOCGPPPSTATS: 702 psp = &((struct ifpppstatsreq *) data)->stats; 703 memset(psp, 0, sizeof(*psp)); 704 psp->p = sc->sc_stats; 705 #if defined(VJC) && !defined(SL_NO_STATS) 706 if (sc->sc_comp) { 707 psp->vj.vjs_packets = sc->sc_comp->sls_packets; 708 psp->vj.vjs_compressed = sc->sc_comp->sls_compressed; 709 psp->vj.vjs_searches = sc->sc_comp->sls_searches; 710 psp->vj.vjs_misses = sc->sc_comp->sls_misses; 711 psp->vj.vjs_uncompressedin = sc->sc_comp->sls_uncompressedin; 712 psp->vj.vjs_compressedin = sc->sc_comp->sls_compressedin; 713 psp->vj.vjs_errorin = sc->sc_comp->sls_errorin; 714 psp->vj.vjs_tossed = sc->sc_comp->sls_tossed; 715 } 716 #endif /* VJC */ 717 break; 718 719 #ifdef PPP_COMPRESS 720 case SIOCGPPPCSTATS: 721 pcp = &((struct ifpppcstatsreq *) data)->stats; 722 memset(pcp, 0, sizeof(*pcp)); 723 if (sc->sc_xc_state != NULL) 724 (*sc->sc_xcomp->comp_stat)(sc->sc_xc_state, &pcp->c); 725 if (sc->sc_rc_state != NULL) 726 (*sc->sc_rcomp->decomp_stat)(sc->sc_rc_state, &pcp->d); 727 break; 728 #endif /* PPP_COMPRESS */ 729 730 default: 731 error = EINVAL; 732 } 733 splx(s); 734 return (error); 735 } 736 737 /* 738 * Queue a packet. Start transmission if not active. 739 * Packet is placed in Information field of PPP frame. 740 */ 741 int 742 pppoutput(ifp, m0, dst, rtp) 743 struct ifnet *ifp; 744 struct mbuf *m0; 745 struct sockaddr *dst; 746 struct rtentry *rtp; 747 { 748 struct ppp_softc *sc = ifp->if_softc; 749 int protocol, address, control; 750 u_char *cp; 751 int s, error; 752 #ifdef INET 753 struct ip *ip; 754 #endif 755 struct ifqueue *ifq; 756 enum NPmode mode; 757 int len; 758 struct mbuf *m; 759 ALTQ_DECL(struct altq_pktattr pktattr;) 760 761 if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0 762 || ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) { 763 error = ENETDOWN; /* sort of */ 764 goto bad; 765 } 766 767 IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family, &pktattr); 768 769 /* 770 * Compute PPP header. 771 */ 772 m0->m_flags &= ~M_HIGHPRI; 773 switch (dst->sa_family) { 774 #ifdef INET 775 case AF_INET: 776 address = PPP_ALLSTATIONS; 777 control = PPP_UI; 778 protocol = PPP_IP; 779 mode = sc->sc_npmode[NP_IP]; 780 781 /* 782 * If this packet has the "low delay" bit set in the IP header, 783 * put it on the fastq instead. 784 */ 785 ip = mtod(m0, struct ip *); 786 if (ip->ip_tos & IPTOS_LOWDELAY) 787 m0->m_flags |= M_HIGHPRI; 788 break; 789 #endif 790 #ifdef INET6 791 case AF_INET6: 792 address = PPP_ALLSTATIONS; /*XXX*/ 793 control = PPP_UI; /*XXX*/ 794 protocol = PPP_IPV6; 795 mode = sc->sc_npmode[NP_IPV6]; 796 797 #if 0 /* XXX flowinfo/traffic class, maybe? */ 798 /* 799 * If this packet has the "low delay" bit set in the IP header, 800 * put it on the fastq instead. 801 */ 802 ip = mtod(m0, struct ip *); 803 if (ip->ip_tos & IPTOS_LOWDELAY) 804 m0->m_flags |= M_HIGHPRI; 805 #endif 806 break; 807 #endif 808 case AF_UNSPEC: 809 address = PPP_ADDRESS(dst->sa_data); 810 control = PPP_CONTROL(dst->sa_data); 811 protocol = PPP_PROTOCOL(dst->sa_data); 812 mode = NPMODE_PASS; 813 break; 814 default: 815 printf("%s: af%d not supported\n", ifp->if_xname, dst->sa_family); 816 error = EAFNOSUPPORT; 817 goto bad; 818 } 819 820 /* 821 * Drop this packet, or return an error, if necessary. 822 */ 823 if (mode == NPMODE_ERROR) { 824 error = ENETDOWN; 825 goto bad; 826 } 827 if (mode == NPMODE_DROP) { 828 error = 0; 829 goto bad; 830 } 831 832 /* 833 * Add PPP header. If no space in first mbuf, allocate another. 834 * (This assumes M_LEADINGSPACE is always 0 for a cluster mbuf.) 835 */ 836 if (M_LEADINGSPACE(m0) < PPP_HDRLEN) { 837 m0 = m_prepend(m0, PPP_HDRLEN, M_DONTWAIT); 838 if (m0 == 0) { 839 error = ENOBUFS; 840 goto bad; 841 } 842 m0->m_len = 0; 843 } else 844 m0->m_data -= PPP_HDRLEN; 845 846 cp = mtod(m0, u_char *); 847 *cp++ = address; 848 *cp++ = control; 849 *cp++ = protocol >> 8; 850 *cp++ = protocol & 0xff; 851 m0->m_len += PPP_HDRLEN; 852 853 len = 0; 854 for (m = m0; m != 0; m = m->m_next) 855 len += m->m_len; 856 857 if (sc->sc_flags & SC_LOG_OUTPKT) { 858 printf("%s output: ", ifp->if_xname); 859 pppdumpm(m0); 860 } 861 862 if ((protocol & 0x8000) == 0) { 863 #ifdef PPP_FILTER 864 /* 865 * Apply the pass and active filters to the packet, 866 * but only if it is a data packet. 867 */ 868 if (sc->sc_pass_filt_out.bf_insns != 0 869 && bpf_filter(sc->sc_pass_filt_out.bf_insns, (u_char *) m0, 870 len, 0) == 0) { 871 error = 0; /* drop this packet */ 872 goto bad; 873 } 874 875 /* 876 * Update the time we sent the most recent packet. 877 */ 878 if (sc->sc_active_filt_out.bf_insns == 0 879 || bpf_filter(sc->sc_active_filt_out.bf_insns, (u_char *) m0, 880 len, 0)) 881 sc->sc_last_sent = time.tv_sec; 882 #else 883 /* 884 * Update the time we sent the most recent packet. 885 */ 886 sc->sc_last_sent = time.tv_sec; 887 #endif /* PPP_FILTER */ 888 } 889 890 #if NBPFILTER > 0 891 /* 892 * See if bpf wants to look at the packet. 893 */ 894 if (sc->sc_if.if_bpf) 895 bpf_mtap(sc->sc_if.if_bpf, m0); 896 #endif 897 898 /* 899 * Put the packet on the appropriate queue. 900 */ 901 s = splnet(); 902 if (mode == NPMODE_QUEUE) { 903 /* XXX we should limit the number of packets on this queue */ 904 *sc->sc_npqtail = m0; 905 m0->m_nextpkt = NULL; 906 sc->sc_npqtail = &m0->m_nextpkt; 907 } else { 908 if ((m0->m_flags & M_HIGHPRI) 909 #ifdef ALTQ 910 && ALTQ_IS_ENABLED(&sc->sc_if.if_snd) == 0 911 #endif 912 ) { 913 ifq = &sc->sc_fastq; 914 if (IF_QFULL(ifq) && dst->sa_family != AF_UNSPEC) { 915 IF_DROP(ifq); 916 splx(s); 917 error = ENOBUFS; 918 goto bad; 919 } else { 920 IF_ENQUEUE(ifq, m0); 921 error = 0; 922 } 923 } else 924 IFQ_ENQUEUE(&sc->sc_if.if_snd, m0, &pktattr, error); 925 if (error) { 926 splx(s); 927 sc->sc_if.if_oerrors++; 928 sc->sc_stats.ppp_oerrors++; 929 return (error); 930 } 931 ppp_restart(sc); 932 } 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 1651 if (rv) 1652 (*sc->sc_ctlp)(sc); 1653 1654 return; 1655 1656 bad: 1657 m_freem(m); 1658 sc->sc_if.if_ierrors++; 1659 sc->sc_stats.ppp_ierrors++; 1660 } 1661 1662 #define MAX_DUMP_BYTES 128 1663 1664 static void 1665 pppdumpm(m0) 1666 struct mbuf *m0; 1667 { 1668 char buf[3*MAX_DUMP_BYTES+4]; 1669 char *bp = buf; 1670 struct mbuf *m; 1671 static char digits[] = "0123456789abcdef"; 1672 1673 for (m = m0; m; m = m->m_next) { 1674 int l = m->m_len; 1675 u_char *rptr = (u_char *)m->m_data; 1676 1677 while (l--) { 1678 if (bp > buf + sizeof(buf) - 4) 1679 goto done; 1680 *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */ 1681 *bp++ = digits[*rptr++ & 0xf]; 1682 } 1683 1684 if (m->m_next) { 1685 if (bp > buf + sizeof(buf) - 3) 1686 goto done; 1687 *bp++ = '|'; 1688 } else 1689 *bp++ = ' '; 1690 } 1691 done: 1692 if (m) 1693 *bp++ = '>'; 1694 *bp = 0; 1695 printf("%s\n", buf); 1696 } 1697 1698 #endif /* NPPP > 0 */ 1699