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