1 /* $NetBSD: if_ppp.c,v 1.74 2002/01/14 18:19:15 kleink 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 <sys/cdefs.h> 89 __KERNEL_RCSID(0, "$NetBSD: if_ppp.c,v 1.74 2002/01/14 18:19:15 kleink Exp $"); 90 91 #include "ppp.h" 92 93 #include "opt_inet.h" 94 #include "opt_gateway.h" 95 #include "opt_ppp.h" 96 97 #ifdef INET 98 #define VJC 99 #endif 100 #define PPP_COMPRESS 101 102 #include <sys/param.h> 103 #include <sys/proc.h> 104 #include <sys/mbuf.h> 105 #include <sys/socket.h> 106 #include <sys/ioctl.h> 107 #include <sys/kernel.h> 108 #include <sys/systm.h> 109 #include <sys/time.h> 110 #include <sys/malloc.h> 111 112 #include <net/if.h> 113 #include <net/if_types.h> 114 #include <net/netisr.h> 115 #include <net/route.h> 116 #ifdef PPP_FILTER 117 #include <net/bpf.h> 118 #endif 119 120 #include <machine/intr.h> 121 122 #include <netinet/in.h> 123 #include <netinet/in_systm.h> 124 #include <netinet/in_var.h> 125 #ifdef INET 126 #include <netinet/ip.h> 127 #endif 128 129 #include "bpfilter.h" 130 #if NBPFILTER > 0 131 #include <sys/time.h> 132 #include <net/bpf.h> 133 #endif 134 135 #if defined(PPP_FILTER) || NBPFILTER > 0 136 #include <net/slip.h> 137 #endif 138 139 #ifdef VJC 140 #include <net/slcompress.h> 141 #endif 142 143 #include <net/ppp_defs.h> 144 #include <net/if_ppp.h> 145 #include <net/if_pppvar.h> 146 #include <machine/cpu.h> 147 148 #ifdef PPP_COMPRESS 149 #define PACKETPTR struct mbuf * 150 #include <net/ppp-comp.h> 151 #endif 152 153 static int pppsioctl __P((struct ifnet *, u_long, caddr_t)); 154 static void ppp_requeue __P((struct ppp_softc *)); 155 static void ppp_ccp __P((struct ppp_softc *, struct mbuf *m, int rcvd)); 156 static void ppp_ccp_closed __P((struct ppp_softc *)); 157 static void ppp_inproc __P((struct ppp_softc *, struct mbuf *)); 158 static void pppdumpm __P((struct mbuf *m0)); 159 160 #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS 161 void pppnetisr(void); 162 #endif 163 void pppintr(void *); 164 165 /* 166 * Some useful mbuf macros not in mbuf.h. 167 */ 168 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT) 169 170 #define M_DATASTART(m) \ 171 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \ 172 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat) 173 174 #define M_DATASIZE(m) \ 175 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \ 176 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN) 177 178 /* 179 * We define two link layer specific mbuf flags, to mark high-priority 180 * packets for output, and received packets following lost/corrupted 181 * packets. 182 */ 183 #define M_HIGHPRI M_LINK0 /* output packet for sc_fastq */ 184 #define M_ERRMARK M_LINK1 /* rx packet following lost/corrupted pkt */ 185 186 #ifdef PPP_COMPRESS 187 /* 188 * List of compressors we know about. 189 * We leave some space so maybe we can modload compressors. 190 */ 191 192 extern struct compressor ppp_bsd_compress; 193 extern struct compressor ppp_deflate, ppp_deflate_draft; 194 195 struct compressor *ppp_compressors[8] = { 196 #if DO_BSD_COMPRESS && defined(PPP_BSDCOMP) 197 &ppp_bsd_compress, 198 #endif 199 #if DO_DEFLATE && defined(PPP_DEFLATE) 200 &ppp_deflate, 201 &ppp_deflate_draft, 202 #endif 203 NULL 204 }; 205 #endif /* PPP_COMPRESS */ 206 207 208 /* 209 * Called from boot code to establish ppp interfaces. 210 */ 211 void 212 pppattach() 213 { 214 struct ppp_softc *sc; 215 int i = 0; 216 217 for (sc = ppp_softc; i < NPPP; sc++) { 218 sc->sc_unit = i; /* XXX */ 219 sprintf(sc->sc_if.if_xname, "ppp%d", i++); 220 callout_init(&sc->sc_timo_ch); 221 sc->sc_if.if_softc = sc; 222 sc->sc_if.if_mtu = PPP_MTU; 223 sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 224 sc->sc_if.if_type = IFT_PPP; 225 sc->sc_if.if_hdrlen = PPP_HDRLEN; 226 sc->sc_if.if_dlt = DLT_NULL; 227 sc->sc_if.if_ioctl = pppsioctl; 228 sc->sc_if.if_output = pppoutput; 229 IFQ_SET_MAXLEN(&sc->sc_if.if_snd, IFQ_MAXLEN); 230 sc->sc_inq.ifq_maxlen = IFQ_MAXLEN; 231 sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN; 232 sc->sc_rawq.ifq_maxlen = IFQ_MAXLEN; 233 IFQ_SET_READY(&sc->sc_if.if_snd); 234 if_attach(&sc->sc_if); 235 if_alloc_sadl(&sc->sc_if); 236 #if NBPFILTER > 0 237 bpfattach(&sc->sc_if, DLT_NULL, 0); 238 #endif 239 } 240 } 241 242 /* 243 * Allocate a ppp interface unit and initialize it. 244 */ 245 struct ppp_softc * 246 pppalloc(pid) 247 pid_t pid; 248 { 249 int nppp, i; 250 struct ppp_softc *sc; 251 252 for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++) 253 if (sc->sc_xfer == pid) { 254 sc->sc_xfer = 0; 255 return sc; 256 } 257 for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++) 258 if (sc->sc_devp == NULL) 259 break; 260 if (nppp >= NPPP) 261 return NULL; 262 263 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 264 sc->sc_si = softintr_establish(IPL_SOFTNET, pppintr, sc); 265 if (sc->sc_si == NULL) { 266 printf("ppp%d: unable to establish softintr\n", sc->sc_unit); 267 return (NULL); 268 } 269 #endif 270 271 sc->sc_flags = 0; 272 sc->sc_mru = PPP_MRU; 273 sc->sc_relinq = NULL; 274 memset((char *)&sc->sc_stats, 0, sizeof(sc->sc_stats)); 275 #ifdef VJC 276 MALLOC(sc->sc_comp, struct slcompress *, sizeof(struct slcompress), 277 M_DEVBUF, M_NOWAIT); 278 if (sc->sc_comp) 279 sl_compress_init(sc->sc_comp); 280 #endif 281 #ifdef PPP_COMPRESS 282 sc->sc_xc_state = NULL; 283 sc->sc_rc_state = NULL; 284 #endif /* PPP_COMPRESS */ 285 for (i = 0; i < NUM_NP; ++i) 286 sc->sc_npmode[i] = NPMODE_ERROR; 287 sc->sc_npqueue = NULL; 288 sc->sc_npqtail = &sc->sc_npqueue; 289 sc->sc_last_sent = sc->sc_last_recv = time.tv_sec; 290 291 return sc; 292 } 293 294 /* 295 * Deallocate a ppp unit. Must be called at splsoftnet or higher. 296 */ 297 void 298 pppdealloc(sc) 299 struct ppp_softc *sc; 300 { 301 struct mbuf *m; 302 303 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 304 softintr_disestablish(sc->sc_si); 305 #endif 306 if_down(&sc->sc_if); 307 sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING); 308 sc->sc_devp = NULL; 309 sc->sc_xfer = 0; 310 for (;;) { 311 IF_DEQUEUE(&sc->sc_rawq, m); 312 if (m == NULL) 313 break; 314 m_freem(m); 315 } 316 for (;;) { 317 IF_DEQUEUE(&sc->sc_inq, m); 318 if (m == NULL) 319 break; 320 m_freem(m); 321 } 322 for (;;) { 323 IF_DEQUEUE(&sc->sc_fastq, m); 324 if (m == NULL) 325 break; 326 m_freem(m); 327 } 328 while ((m = sc->sc_npqueue) != NULL) { 329 sc->sc_npqueue = m->m_nextpkt; 330 m_freem(m); 331 } 332 if (sc->sc_togo != NULL) { 333 m_freem(sc->sc_togo); 334 sc->sc_togo = NULL; 335 } 336 #ifdef PPP_COMPRESS 337 ppp_ccp_closed(sc); 338 sc->sc_xc_state = NULL; 339 sc->sc_rc_state = NULL; 340 #endif /* PPP_COMPRESS */ 341 #ifdef PPP_FILTER 342 if (sc->sc_pass_filt_in.bf_insns != 0) { 343 FREE(sc->sc_pass_filt_in.bf_insns, M_DEVBUF); 344 sc->sc_pass_filt_in.bf_insns = 0; 345 sc->sc_pass_filt_in.bf_len = 0; 346 } 347 if (sc->sc_pass_filt_out.bf_insns != 0) { 348 FREE(sc->sc_pass_filt_out.bf_insns, M_DEVBUF); 349 sc->sc_pass_filt_out.bf_insns = 0; 350 sc->sc_pass_filt_out.bf_len = 0; 351 } 352 if (sc->sc_active_filt_in.bf_insns != 0) { 353 FREE(sc->sc_active_filt_in.bf_insns, M_DEVBUF); 354 sc->sc_active_filt_in.bf_insns = 0; 355 sc->sc_active_filt_in.bf_len = 0; 356 } 357 if (sc->sc_active_filt_out.bf_insns != 0) { 358 FREE(sc->sc_active_filt_out.bf_insns, M_DEVBUF); 359 sc->sc_active_filt_out.bf_insns = 0; 360 sc->sc_active_filt_out.bf_len = 0; 361 } 362 #endif /* PPP_FILTER */ 363 #ifdef VJC 364 if (sc->sc_comp != 0) { 365 FREE(sc->sc_comp, M_DEVBUF); 366 sc->sc_comp = 0; 367 } 368 #endif 369 } 370 371 /* 372 * Ioctl routine for generic ppp devices. 373 */ 374 int 375 pppioctl(sc, cmd, data, flag, p) 376 struct ppp_softc *sc; 377 u_long cmd; 378 caddr_t data; 379 int flag; 380 struct proc *p; 381 { 382 int s, error, flags, mru, npx; 383 u_int nb; 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 memset(psp, 0, 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 memset(pcp, 0, 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_opackets++; 933 ifp->if_obytes += len; 934 935 splx(s); 936 return (0); 937 938 bad: 939 m_freem(m0); 940 return (error); 941 } 942 943 /* 944 * After a change in the NPmode for some NP, move packets from the 945 * npqueue to the send queue or the fast queue as appropriate. 946 * Should be called at splnet, since we muck with the queues. 947 */ 948 static void 949 ppp_requeue(sc) 950 struct ppp_softc *sc; 951 { 952 struct mbuf *m, **mpp; 953 struct ifqueue *ifq; 954 enum NPmode mode; 955 int error; 956 957 for (mpp = &sc->sc_npqueue; (m = *mpp) != NULL; ) { 958 switch (PPP_PROTOCOL(mtod(m, u_char *))) { 959 case PPP_IP: 960 mode = sc->sc_npmode[NP_IP]; 961 break; 962 case PPP_IPV6: 963 mode = sc->sc_npmode[NP_IPV6]; 964 break; 965 default: 966 mode = NPMODE_PASS; 967 } 968 969 switch (mode) { 970 case NPMODE_PASS: 971 /* 972 * This packet can now go on one of the queues to be sent. 973 */ 974 *mpp = m->m_nextpkt; 975 m->m_nextpkt = NULL; 976 if ((m->m_flags & M_HIGHPRI) 977 #ifdef ALTQ 978 && ALTQ_IS_ENABLED(&sc->sc_if.if_snd) == 0 979 #endif 980 ) { 981 ifq = &sc->sc_fastq; 982 if (IF_QFULL(ifq)) { 983 IF_DROP(ifq); 984 m_freem(m); 985 error = ENOBUFS; 986 } else { 987 IF_ENQUEUE(ifq, m); 988 error = 0; 989 } 990 } else 991 IFQ_ENQUEUE(&sc->sc_if.if_snd, m, NULL, error); 992 if (error) { 993 sc->sc_if.if_oerrors++; 994 sc->sc_stats.ppp_oerrors++; 995 } 996 break; 997 998 case NPMODE_DROP: 999 case NPMODE_ERROR: 1000 *mpp = m->m_nextpkt; 1001 m_freem(m); 1002 break; 1003 1004 case NPMODE_QUEUE: 1005 mpp = &m->m_nextpkt; 1006 break; 1007 } 1008 } 1009 sc->sc_npqtail = mpp; 1010 } 1011 1012 /* 1013 * Transmitter has finished outputting some stuff; 1014 * remember to call sc->sc_start later at splsoftnet. 1015 */ 1016 void 1017 ppp_restart(sc) 1018 struct ppp_softc *sc; 1019 { 1020 int s = splhigh(); /* XXX IMP ME HARDER */ 1021 1022 sc->sc_flags &= ~SC_TBUSY; 1023 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 1024 softintr_schedule(sc->sc_si); 1025 #else 1026 schednetisr(NETISR_PPP); 1027 #endif 1028 splx(s); 1029 } 1030 1031 /* 1032 * Get a packet to send. This procedure is intended to be called at 1033 * splsoftnet, since it may involve time-consuming operations such as 1034 * applying VJ compression, packet compression, address/control and/or 1035 * protocol field compression to the packet. 1036 */ 1037 struct mbuf * 1038 ppp_dequeue(sc) 1039 struct ppp_softc *sc; 1040 { 1041 struct mbuf *m, *mp; 1042 u_char *cp; 1043 int address, control, protocol; 1044 int s; 1045 1046 /* 1047 * Grab a packet to send: first try the fast queue, then the 1048 * normal queue. 1049 */ 1050 s = splnet(); 1051 IF_DEQUEUE(&sc->sc_fastq, m); 1052 if (m == NULL) 1053 IFQ_DEQUEUE(&sc->sc_if.if_snd, m); 1054 splx(s); 1055 1056 if (m == NULL) 1057 return NULL; 1058 1059 ++sc->sc_stats.ppp_opackets; 1060 1061 /* 1062 * Extract the ppp header of the new packet. 1063 * The ppp header will be in one mbuf. 1064 */ 1065 cp = mtod(m, u_char *); 1066 address = PPP_ADDRESS(cp); 1067 control = PPP_CONTROL(cp); 1068 protocol = PPP_PROTOCOL(cp); 1069 1070 switch (protocol) { 1071 case PPP_IP: 1072 #ifdef VJC 1073 /* 1074 * If the packet is a TCP/IP packet, see if we can compress it. 1075 */ 1076 if ((sc->sc_flags & SC_COMP_TCP) && sc->sc_comp != NULL) { 1077 struct ip *ip; 1078 int type; 1079 1080 mp = m; 1081 ip = (struct ip *) (cp + PPP_HDRLEN); 1082 if (mp->m_len <= PPP_HDRLEN) { 1083 mp = mp->m_next; 1084 if (mp == NULL) 1085 break; 1086 ip = mtod(mp, struct ip *); 1087 } 1088 /* this code assumes the IP/TCP header is in one non-shared mbuf */ 1089 if (ip->ip_p == IPPROTO_TCP) { 1090 type = sl_compress_tcp(mp, ip, sc->sc_comp, 1091 !(sc->sc_flags & SC_NO_TCP_CCID)); 1092 switch (type) { 1093 case TYPE_UNCOMPRESSED_TCP: 1094 protocol = PPP_VJC_UNCOMP; 1095 break; 1096 case TYPE_COMPRESSED_TCP: 1097 protocol = PPP_VJC_COMP; 1098 cp = mtod(m, u_char *); 1099 cp[0] = address; /* header has moved */ 1100 cp[1] = control; 1101 cp[2] = 0; 1102 break; 1103 } 1104 cp[3] = protocol; /* update protocol in PPP header */ 1105 } 1106 } 1107 #endif /* VJC */ 1108 break; 1109 1110 #ifdef PPP_COMPRESS 1111 case PPP_CCP: 1112 ppp_ccp(sc, m, 0); 1113 break; 1114 #endif /* PPP_COMPRESS */ 1115 } 1116 1117 #ifdef PPP_COMPRESS 1118 if (protocol != PPP_LCP && protocol != PPP_CCP 1119 && sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) { 1120 struct mbuf *mcomp = NULL; 1121 int slen, clen; 1122 1123 slen = 0; 1124 for (mp = m; mp != NULL; mp = mp->m_next) 1125 slen += mp->m_len; 1126 clen = (*sc->sc_xcomp->compress) 1127 (sc->sc_xc_state, &mcomp, m, slen, sc->sc_if.if_mtu + PPP_HDRLEN); 1128 if (mcomp != NULL) { 1129 if (sc->sc_flags & SC_CCP_UP) { 1130 /* Send the compressed packet instead of the original. */ 1131 m_freem(m); 1132 m = mcomp; 1133 cp = mtod(m, u_char *); 1134 protocol = cp[3]; 1135 } else { 1136 /* Can't transmit compressed packets until CCP is up. */ 1137 m_freem(mcomp); 1138 } 1139 } 1140 } 1141 #endif /* PPP_COMPRESS */ 1142 1143 /* 1144 * Compress the address/control and protocol, if possible. 1145 */ 1146 if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS && 1147 control == PPP_UI && protocol != PPP_ALLSTATIONS && 1148 protocol != PPP_LCP) { 1149 /* can compress address/control */ 1150 m->m_data += 2; 1151 m->m_len -= 2; 1152 } 1153 if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) { 1154 /* can compress protocol */ 1155 if (mtod(m, u_char *) == cp) { 1156 cp[2] = cp[1]; /* move address/control up */ 1157 cp[1] = cp[0]; 1158 } 1159 ++m->m_data; 1160 --m->m_len; 1161 } 1162 1163 return m; 1164 } 1165 1166 #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS 1167 void 1168 pppnetisr(void) 1169 { 1170 struct ppp_softc *sc; 1171 int i; 1172 1173 for (i = 0; i < NPPP; i++) { 1174 sc = &ppp_softc[i]; 1175 pppintr(sc); 1176 } 1177 } 1178 #endif 1179 1180 /* 1181 * Software interrupt routine, called at splsoftnet. 1182 */ 1183 void 1184 pppintr(void *arg) 1185 { 1186 struct ppp_softc *sc = arg; 1187 struct mbuf *m; 1188 int s; 1189 1190 if (!(sc->sc_flags & SC_TBUSY) 1191 && (IFQ_IS_EMPTY(&sc->sc_if.if_snd) == 0 || sc->sc_fastq.ifq_head 1192 || sc->sc_outm)) { 1193 s = splhigh(); /* XXX IMP ME HARDER */ 1194 sc->sc_flags |= SC_TBUSY; 1195 splx(s); 1196 (*sc->sc_start)(sc); 1197 } 1198 for (;;) { 1199 s = splnet(); 1200 IF_DEQUEUE(&sc->sc_rawq, m); 1201 splx(s); 1202 if (m == NULL) 1203 break; 1204 ppp_inproc(sc, m); 1205 } 1206 } 1207 1208 #ifdef PPP_COMPRESS 1209 /* 1210 * Handle a CCP packet. `rcvd' is 1 if the packet was received, 1211 * 0 if it is about to be transmitted. 1212 */ 1213 static void 1214 ppp_ccp(sc, m, rcvd) 1215 struct ppp_softc *sc; 1216 struct mbuf *m; 1217 int rcvd; 1218 { 1219 u_char *dp, *ep; 1220 struct mbuf *mp; 1221 int slen, s; 1222 1223 /* 1224 * Get a pointer to the data after the PPP header. 1225 */ 1226 if (m->m_len <= PPP_HDRLEN) { 1227 mp = m->m_next; 1228 if (mp == NULL) 1229 return; 1230 dp = (mp != NULL)? mtod(mp, u_char *): NULL; 1231 } else { 1232 mp = m; 1233 dp = mtod(mp, u_char *) + PPP_HDRLEN; 1234 } 1235 1236 ep = mtod(mp, u_char *) + mp->m_len; 1237 if (dp + CCP_HDRLEN > ep) 1238 return; 1239 slen = CCP_LENGTH(dp); 1240 if (dp + slen > ep) { 1241 if (sc->sc_flags & SC_DEBUG) 1242 printf("if_ppp/ccp: not enough data in mbuf (%p+%x > %p+%x)\n", 1243 dp, slen, mtod(mp, u_char *), mp->m_len); 1244 return; 1245 } 1246 1247 switch (CCP_CODE(dp)) { 1248 case CCP_CONFREQ: 1249 case CCP_TERMREQ: 1250 case CCP_TERMACK: 1251 /* CCP must be going down - disable compression */ 1252 if (sc->sc_flags & SC_CCP_UP) { 1253 s = splhigh(); /* XXX IMP ME HARDER */ 1254 sc->sc_flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN); 1255 splx(s); 1256 } 1257 break; 1258 1259 case CCP_CONFACK: 1260 if (sc->sc_flags & SC_CCP_OPEN && !(sc->sc_flags & SC_CCP_UP) 1261 && slen >= CCP_HDRLEN + CCP_OPT_MINLEN 1262 && slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) { 1263 if (!rcvd) { 1264 /* we're agreeing to send compressed packets. */ 1265 if (sc->sc_xc_state != NULL 1266 && (*sc->sc_xcomp->comp_init) 1267 (sc->sc_xc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, 1268 sc->sc_unit, 0, sc->sc_flags & SC_DEBUG)) { 1269 s = splhigh(); /* XXX IMP ME HARDER */ 1270 sc->sc_flags |= SC_COMP_RUN; 1271 splx(s); 1272 } 1273 } else { 1274 /* peer is agreeing to send compressed packets. */ 1275 if (sc->sc_rc_state != NULL 1276 && (*sc->sc_rcomp->decomp_init) 1277 (sc->sc_rc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, 1278 sc->sc_unit, 0, sc->sc_mru, 1279 sc->sc_flags & SC_DEBUG)) { 1280 s = splhigh(); /* XXX IMP ME HARDER */ 1281 sc->sc_flags |= SC_DECOMP_RUN; 1282 sc->sc_flags &= ~(SC_DC_ERROR | SC_DC_FERROR); 1283 splx(s); 1284 } 1285 } 1286 } 1287 break; 1288 1289 case CCP_RESETACK: 1290 if (sc->sc_flags & SC_CCP_UP) { 1291 if (!rcvd) { 1292 if (sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) 1293 (*sc->sc_xcomp->comp_reset)(sc->sc_xc_state); 1294 } else { 1295 if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) { 1296 (*sc->sc_rcomp->decomp_reset)(sc->sc_rc_state); 1297 s = splhigh(); /* XXX IMP ME HARDER */ 1298 sc->sc_flags &= ~SC_DC_ERROR; 1299 splx(s); 1300 } 1301 } 1302 } 1303 break; 1304 } 1305 } 1306 1307 /* 1308 * CCP is down; free (de)compressor state if necessary. 1309 */ 1310 static void 1311 ppp_ccp_closed(sc) 1312 struct ppp_softc *sc; 1313 { 1314 if (sc->sc_xc_state) { 1315 (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); 1316 sc->sc_xc_state = NULL; 1317 } 1318 if (sc->sc_rc_state) { 1319 (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); 1320 sc->sc_rc_state = NULL; 1321 } 1322 } 1323 #endif /* PPP_COMPRESS */ 1324 1325 /* 1326 * PPP packet input routine. 1327 * The caller has checked and removed the FCS and has inserted 1328 * the address/control bytes and the protocol high byte if they 1329 * were omitted. 1330 */ 1331 void 1332 ppppktin(sc, m, lost) 1333 struct ppp_softc *sc; 1334 struct mbuf *m; 1335 int lost; 1336 { 1337 int s = splhigh(); /* XXX IMP ME HARDER */ 1338 1339 if (lost) 1340 m->m_flags |= M_ERRMARK; 1341 IF_ENQUEUE(&sc->sc_rawq, m); 1342 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 1343 softintr_schedule(sc->sc_si); 1344 #else 1345 schednetisr(NETISR_PPP); 1346 #endif 1347 splx(s); 1348 } 1349 1350 /* 1351 * Process a received PPP packet, doing decompression as necessary. 1352 * Should be called at splsoftnet. 1353 */ 1354 #define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \ 1355 TYPE_UNCOMPRESSED_TCP) 1356 1357 static void 1358 ppp_inproc(sc, m) 1359 struct ppp_softc *sc; 1360 struct mbuf *m; 1361 { 1362 struct ifnet *ifp = &sc->sc_if; 1363 struct ifqueue *inq; 1364 int s, ilen, proto, rv; 1365 u_char *cp, adrs, ctrl; 1366 struct mbuf *mp, *dmp = NULL; 1367 #ifdef VJC 1368 int xlen; 1369 u_char *iphdr; 1370 u_int hlen; 1371 #endif 1372 1373 sc->sc_stats.ppp_ipackets++; 1374 1375 if (sc->sc_flags & SC_LOG_INPKT) { 1376 ilen = 0; 1377 for (mp = m; mp != NULL; mp = mp->m_next) 1378 ilen += mp->m_len; 1379 printf("%s: got %d bytes\n", ifp->if_xname, ilen); 1380 pppdumpm(m); 1381 } 1382 1383 cp = mtod(m, u_char *); 1384 adrs = PPP_ADDRESS(cp); 1385 ctrl = PPP_CONTROL(cp); 1386 proto = PPP_PROTOCOL(cp); 1387 1388 if (m->m_flags & M_ERRMARK) { 1389 m->m_flags &= ~M_ERRMARK; 1390 s = splhigh(); /* XXX IMP ME HARDER */ 1391 sc->sc_flags |= SC_VJ_RESET; 1392 splx(s); 1393 } 1394 1395 #ifdef PPP_COMPRESS 1396 /* 1397 * Decompress this packet if necessary, update the receiver's 1398 * dictionary, or take appropriate action on a CCP packet. 1399 */ 1400 if (proto == PPP_COMP && sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN) 1401 && !(sc->sc_flags & SC_DC_ERROR) && !(sc->sc_flags & SC_DC_FERROR)) { 1402 /* decompress this packet */ 1403 rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp); 1404 if (rv == DECOMP_OK) { 1405 m_freem(m); 1406 if (dmp == NULL) { 1407 /* no error, but no decompressed packet produced */ 1408 return; 1409 } 1410 m = dmp; 1411 cp = mtod(m, u_char *); 1412 proto = PPP_PROTOCOL(cp); 1413 1414 } else { 1415 /* 1416 * An error has occurred in decompression. 1417 * Pass the compressed packet up to pppd, which may take 1418 * CCP down or issue a Reset-Req. 1419 */ 1420 if (sc->sc_flags & SC_DEBUG) 1421 printf("%s: decompress failed %d\n", ifp->if_xname, rv); 1422 s = splhigh(); /* XXX IMP ME HARDER */ 1423 sc->sc_flags |= SC_VJ_RESET; 1424 if (rv == DECOMP_ERROR) 1425 sc->sc_flags |= SC_DC_ERROR; 1426 else 1427 sc->sc_flags |= SC_DC_FERROR; 1428 splx(s); 1429 } 1430 1431 } else { 1432 if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) { 1433 (*sc->sc_rcomp->incomp)(sc->sc_rc_state, m); 1434 } 1435 if (proto == PPP_CCP) { 1436 ppp_ccp(sc, m, 1); 1437 } 1438 } 1439 #endif 1440 1441 ilen = 0; 1442 for (mp = m; mp != NULL; mp = mp->m_next) 1443 ilen += mp->m_len; 1444 1445 #ifdef VJC 1446 if (sc->sc_flags & SC_VJ_RESET) { 1447 /* 1448 * If we've missed a packet, we must toss subsequent compressed 1449 * packets which don't have an explicit connection ID. 1450 */ 1451 if (sc->sc_comp) 1452 sl_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp); 1453 s = splhigh(); /* XXX IMP ME HARDER */ 1454 sc->sc_flags &= ~SC_VJ_RESET; 1455 splx(s); 1456 } 1457 1458 /* 1459 * See if we have a VJ-compressed packet to uncompress. 1460 */ 1461 if (proto == PPP_VJC_COMP) { 1462 if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) 1463 goto bad; 1464 1465 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN, 1466 ilen - PPP_HDRLEN, TYPE_COMPRESSED_TCP, 1467 sc->sc_comp, &iphdr, &hlen); 1468 1469 if (xlen <= 0) { 1470 if (sc->sc_flags & SC_DEBUG) 1471 printf("%s: VJ uncompress failed on type comp\n", 1472 ifp->if_xname); 1473 goto bad; 1474 } 1475 1476 /* Copy the PPP and IP headers into a new mbuf. */ 1477 MGETHDR(mp, M_DONTWAIT, MT_DATA); 1478 if (mp == NULL) 1479 goto bad; 1480 mp->m_len = 0; 1481 mp->m_next = NULL; 1482 if (hlen + PPP_HDRLEN > MHLEN) { 1483 MCLGET(mp, M_DONTWAIT); 1484 if (M_TRAILINGSPACE(mp) < hlen + PPP_HDRLEN) { 1485 m_freem(mp); 1486 goto bad; /* lose if big headers and no clusters */ 1487 } 1488 } 1489 cp = mtod(mp, u_char *); 1490 cp[0] = adrs; 1491 cp[1] = ctrl; 1492 cp[2] = 0; 1493 cp[3] = PPP_IP; 1494 proto = PPP_IP; 1495 bcopy(iphdr, cp + PPP_HDRLEN, hlen); 1496 mp->m_len = hlen + PPP_HDRLEN; 1497 1498 /* 1499 * Trim the PPP and VJ headers off the old mbuf 1500 * and stick the new and old mbufs together. 1501 */ 1502 m->m_data += PPP_HDRLEN + xlen; 1503 m->m_len -= PPP_HDRLEN + xlen; 1504 if (m->m_len <= M_TRAILINGSPACE(mp)) { 1505 bcopy(mtod(m, u_char *), mtod(mp, u_char *) + mp->m_len, m->m_len); 1506 mp->m_len += m->m_len; 1507 MFREE(m, mp->m_next); 1508 } else 1509 mp->m_next = m; 1510 m = mp; 1511 ilen += hlen - xlen; 1512 1513 } else if (proto == PPP_VJC_UNCOMP) { 1514 if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) 1515 goto bad; 1516 1517 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN, 1518 ilen - PPP_HDRLEN, TYPE_UNCOMPRESSED_TCP, 1519 sc->sc_comp, &iphdr, &hlen); 1520 1521 if (xlen < 0) { 1522 if (sc->sc_flags & SC_DEBUG) 1523 printf("%s: VJ uncompress failed on type uncomp\n", 1524 ifp->if_xname); 1525 goto bad; 1526 } 1527 1528 proto = PPP_IP; 1529 cp[3] = PPP_IP; 1530 } 1531 #endif /* VJC */ 1532 1533 /* 1534 * If the packet will fit in a header mbuf, don't waste a 1535 * whole cluster on it. 1536 */ 1537 if (ilen <= MHLEN && M_IS_CLUSTER(m)) { 1538 MGETHDR(mp, M_DONTWAIT, MT_DATA); 1539 if (mp != NULL) { 1540 m_copydata(m, 0, ilen, mtod(mp, caddr_t)); 1541 m_freem(m); 1542 m = mp; 1543 m->m_len = ilen; 1544 } 1545 } 1546 m->m_pkthdr.len = ilen; 1547 m->m_pkthdr.rcvif = ifp; 1548 1549 if ((proto & 0x8000) == 0) { 1550 #ifdef PPP_FILTER 1551 /* 1552 * See whether we want to pass this packet, and 1553 * if it counts as link activity. 1554 */ 1555 if (sc->sc_pass_filt_in.bf_insns != 0 1556 && bpf_filter(sc->sc_pass_filt_in.bf_insns, (u_char *) m, 1557 ilen, 0) == 0) { 1558 /* drop this packet */ 1559 m_freem(m); 1560 return; 1561 } 1562 if (sc->sc_active_filt_in.bf_insns == 0 1563 || bpf_filter(sc->sc_active_filt_in.bf_insns, (u_char *) m, 1564 ilen, 0)) 1565 sc->sc_last_recv = time.tv_sec; 1566 #else 1567 /* 1568 * Record the time that we received this packet. 1569 */ 1570 sc->sc_last_recv = time.tv_sec; 1571 #endif /* PPP_FILTER */ 1572 } 1573 1574 #if NBPFILTER > 0 1575 /* See if bpf wants to look at the packet. */ 1576 if (sc->sc_if.if_bpf) 1577 bpf_mtap(sc->sc_if.if_bpf, m); 1578 #endif 1579 1580 rv = 0; 1581 switch (proto) { 1582 #ifdef INET 1583 case PPP_IP: 1584 /* 1585 * IP packet - take off the ppp header and pass it up to IP. 1586 */ 1587 if ((ifp->if_flags & IFF_UP) == 0 1588 || sc->sc_npmode[NP_IP] != NPMODE_PASS) { 1589 /* interface is down - drop the packet. */ 1590 m_freem(m); 1591 return; 1592 } 1593 m->m_pkthdr.len -= PPP_HDRLEN; 1594 m->m_data += PPP_HDRLEN; 1595 m->m_len -= PPP_HDRLEN; 1596 #ifdef GATEWAY 1597 if (ipflow_fastforward(m)) 1598 return; 1599 #endif 1600 schednetisr(NETISR_IP); 1601 inq = &ipintrq; 1602 break; 1603 #endif 1604 1605 #ifdef INET6 1606 case PPP_IPV6: 1607 /* 1608 * IPv6 packet - take off the ppp header and pass it up to IPv6. 1609 */ 1610 if ((ifp->if_flags & IFF_UP) == 0 1611 || sc->sc_npmode[NP_IPV6] != NPMODE_PASS) { 1612 /* interface is down - drop the packet. */ 1613 m_freem(m); 1614 return; 1615 } 1616 m->m_pkthdr.len -= PPP_HDRLEN; 1617 m->m_data += PPP_HDRLEN; 1618 m->m_len -= PPP_HDRLEN; 1619 schednetisr(NETISR_IPV6); 1620 inq = &ip6intrq; 1621 break; 1622 #endif 1623 1624 default: 1625 /* 1626 * Some other protocol - place on input queue for read(). 1627 */ 1628 inq = &sc->sc_inq; 1629 rv = 1; 1630 break; 1631 } 1632 1633 /* 1634 * Put the packet on the appropriate input queue. 1635 */ 1636 s = splnet(); 1637 if (IF_QFULL(inq)) { 1638 IF_DROP(inq); 1639 splx(s); 1640 if (sc->sc_flags & SC_DEBUG) 1641 printf("%s: input queue full\n", ifp->if_xname); 1642 ifp->if_iqdrops++; 1643 goto bad; 1644 } 1645 IF_ENQUEUE(inq, m); 1646 splx(s); 1647 ifp->if_ipackets++; 1648 ifp->if_ibytes += ilen; 1649 1650 if (rv) 1651 (*sc->sc_ctlp)(sc); 1652 1653 return; 1654 1655 bad: 1656 m_freem(m); 1657 sc->sc_if.if_ierrors++; 1658 sc->sc_stats.ppp_ierrors++; 1659 } 1660 1661 #define MAX_DUMP_BYTES 128 1662 1663 static void 1664 pppdumpm(m0) 1665 struct mbuf *m0; 1666 { 1667 char buf[3*MAX_DUMP_BYTES+4]; 1668 char *bp = buf; 1669 struct mbuf *m; 1670 static char digits[] = "0123456789abcdef"; 1671 1672 for (m = m0; m; m = m->m_next) { 1673 int l = m->m_len; 1674 u_char *rptr = (u_char *)m->m_data; 1675 1676 while (l--) { 1677 if (bp > buf + sizeof(buf) - 4) 1678 goto done; 1679 *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */ 1680 *bp++ = digits[*rptr++ & 0xf]; 1681 } 1682 1683 if (m->m_next) { 1684 if (bp > buf + sizeof(buf) - 3) 1685 goto done; 1686 *bp++ = '|'; 1687 } else 1688 *bp++ = ' '; 1689 } 1690 done: 1691 if (m) 1692 *bp++ = '>'; 1693 *bp = 0; 1694 printf("%s\n", buf); 1695 } 1696