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