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