1 /* $NetBSD: if_ppp.c,v 1.172 2022/09/03 02:47:59 thorpej Exp $ */ 2 /* Id: if_ppp.c,v 1.6 1997/03/04 03:33:00 paulus Exp */ 3 4 /* 5 * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver. 6 * 7 * Copyright (c) 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 Regents of the University of California. 49 * All rights reserved. 50 * 51 * Redistribution and use in source and binary forms are permitted 52 * provided that the above copyright notice and this paragraph are 53 * duplicated in all such forms and that any documentation, 54 * advertising materials, and other materials related to such 55 * distribution and use acknowledge that the software was developed 56 * by the University of California, Berkeley. The name of the 57 * University may not be used to endorse or promote products derived 58 * from this software without specific prior written permission. 59 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 60 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 61 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 62 * 63 * Serial Line interface 64 * 65 * Rick Adams 66 * Center for Seismic Studies 67 * 1300 N 17th Street, Suite 1450 68 * Arlington, Virginia 22209 69 * (703)276-7900 70 * rick@seismo.ARPA 71 * seismo!rick 72 * 73 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris). 74 * Converted to 4.3BSD Beta by Chris Torek. 75 * Other changes made at Berkeley, based in part on code by Kirk Smith. 76 * 77 * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com) 78 * Added VJ tcp header compression; more unified ioctls 79 * 80 * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au). 81 * Cleaned up a lot of the mbuf-related code to fix bugs that 82 * caused system crashes and packet corruption. Changed pppstart 83 * so that it doesn't just give up with a collision if the whole 84 * packet doesn't fit in the output ring buffer. 85 * 86 * Added priority queueing for interactive IP packets, following 87 * the model of if_sl.c, plus hooks for bpf. 88 * Paul Mackerras (paulus@cs.anu.edu.au). 89 */ 90 91 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */ 92 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */ 93 94 /* 95 * XXX IMP ME HARDER 96 * 97 * This is an explanation of that comment. This code used to use 98 * splimp() to block both network and tty interrupts. However, 99 * that call is deprecated. So, we have replaced the uses of 100 * splimp() with splhigh() in order to applomplish what it needs 101 * to accomplish, and added that happy little comment. 102 */ 103 104 #include <sys/cdefs.h> 105 __KERNEL_RCSID(0, "$NetBSD: if_ppp.c,v 1.172 2022/09/03 02:47:59 thorpej Exp $"); 106 107 #ifdef _KERNEL_OPT 108 #include "ppp.h" 109 #include "opt_inet.h" 110 #include "opt_gateway.h" 111 #include "opt_ppp.h" 112 #endif 113 114 #ifdef INET 115 #define VJC 116 #endif 117 #define PPP_COMPRESS 118 119 #include <sys/param.h> 120 #include <sys/proc.h> 121 #include <sys/mbuf.h> 122 #include <sys/socket.h> 123 #include <sys/ioctl.h> 124 #include <sys/kernel.h> 125 #include <sys/systm.h> 126 #include <sys/time.h> 127 #include <sys/malloc.h> 128 #include <sys/module.h> 129 #include <sys/mutex.h> 130 #include <sys/once.h> 131 #include <sys/conf.h> 132 #include <sys/kauth.h> 133 #include <sys/intr.h> 134 #include <sys/socketvar.h> 135 #include <sys/device.h> 136 #include <sys/module.h> 137 138 #include <net/if.h> 139 #include <net/if_types.h> 140 #include <net/route.h> 141 142 #include <netinet/in.h> 143 #include <netinet/in_systm.h> 144 #include <netinet/in_var.h> 145 #ifdef INET 146 #include <netinet/ip.h> 147 #endif 148 149 #include <net/bpf.h> 150 #include <net/slip.h> 151 152 #ifdef VJC 153 #include <net/slcompress.h> 154 #endif 155 156 #include <net/ppp_defs.h> 157 #include <net/if_ppp.h> 158 #include <net/if_pppvar.h> 159 #include <sys/cpu.h> 160 161 #ifdef PPP_COMPRESS 162 #define PACKETPTR struct mbuf * 163 #include <net/ppp-comp.h> 164 #endif 165 166 #include "ioconf.h" 167 168 static int pppsioctl(struct ifnet *, u_long, void *); 169 static void ppp_requeue(struct ppp_softc *); 170 static void ppp_ccp(struct ppp_softc *, struct mbuf *m, int rcvd); 171 static void ppp_ccp_closed(struct ppp_softc *); 172 static void ppp_inproc(struct ppp_softc *, struct mbuf *); 173 static void pppdumpm(struct mbuf *m0); 174 #ifdef ALTQ 175 static void ppp_ifstart(struct ifnet *ifp); 176 #endif 177 178 static void pppintr(void *); 179 180 extern struct linesw ppp_disc; 181 182 /* 183 * We define two link layer specific mbuf flags, to mark high-priority 184 * packets for output, and received packets following lost/corrupted 185 * packets. 186 */ 187 #define M_HIGHPRI M_LINK0 /* output packet for sc_fastq */ 188 #define M_ERRMARK M_LINK1 /* rx packet following lost/corrupted pkt */ 189 190 static int ppp_clone_create(struct if_clone *, int); 191 static int ppp_clone_destroy(struct ifnet *); 192 193 static struct ppp_softc *ppp_create(const char *, int); 194 195 static struct { 196 LIST_HEAD(ppp_sclist, ppp_softc) list; 197 kmutex_t lock; 198 } ppp_softcs __cacheline_aligned; 199 200 struct if_clone ppp_cloner = 201 IF_CLONE_INITIALIZER("ppp", ppp_clone_create, ppp_clone_destroy); 202 203 #ifdef PPP_COMPRESS 204 static LIST_HEAD(, compressor) ppp_compressors = { NULL }; 205 static kmutex_t ppp_compressors_mtx; 206 207 static int ppp_compressor_init(void); 208 static int ppp_compressor_destroy(void); 209 static struct compressor *ppp_get_compressor(uint8_t); 210 static void ppp_compressor_rele(struct compressor *); 211 #endif /* PPP_COMPRESS */ 212 213 214 /* 215 * Called from boot code to establish ppp interfaces. 216 */ 217 void 218 pppattach(int n __unused) 219 { 220 221 /* 222 * Nothing to do here, initialization is handled by the 223 * module initialization code in pppinit() below). 224 */ 225 } 226 227 static void 228 pppinit(void) 229 { 230 /* Init the compressor sub-sub-system */ 231 ppp_compressor_init(); 232 233 if (ttyldisc_attach(&ppp_disc) != 0) 234 panic("%s", __func__); 235 236 mutex_init(&ppp_softcs.lock, MUTEX_DEFAULT, IPL_NONE); 237 LIST_INIT(&ppp_softcs.list); 238 if_clone_attach(&ppp_cloner); 239 } 240 241 static int 242 pppdetach(void) 243 { 244 int error = 0; 245 246 if (!LIST_EMPTY(&ppp_softcs.list)) 247 error = EBUSY; 248 249 if (error == 0) 250 error = ttyldisc_detach(&ppp_disc); 251 252 if (error == 0) { 253 mutex_destroy(&ppp_softcs.lock); 254 if_clone_detach(&ppp_cloner); 255 ppp_compressor_destroy(); 256 } 257 258 return error; 259 } 260 261 static struct ppp_softc * 262 ppp_create(const char *name, int unit) 263 { 264 struct ppp_softc *sc, *sci, *scl = NULL; 265 266 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAIT|M_ZERO); 267 268 mutex_enter(&ppp_softcs.lock); 269 if (unit == -1) { 270 int i = 0; 271 LIST_FOREACH(sci, &ppp_softcs.list, sc_iflist) { 272 scl = sci; 273 if (i < sci->sc_unit) { 274 unit = i; 275 break; 276 } else { 277 #ifdef DIAGNOSTIC 278 KASSERT(i == sci->sc_unit); 279 #endif 280 i++; 281 } 282 } 283 if (unit == -1) 284 unit = i; 285 } else { 286 LIST_FOREACH(sci, &ppp_softcs.list, sc_iflist) { 287 scl = sci; 288 if (unit < sci->sc_unit) 289 break; 290 else if (unit == sci->sc_unit) { 291 free(sc, M_DEVBUF); 292 mutex_exit(&ppp_softcs.lock); 293 return NULL; 294 } 295 } 296 } 297 298 if (sci != NULL) 299 LIST_INSERT_BEFORE(sci, sc, sc_iflist); 300 else if (scl != NULL) 301 LIST_INSERT_AFTER(scl, sc, sc_iflist); 302 else 303 LIST_INSERT_HEAD(&ppp_softcs.list, sc, sc_iflist); 304 305 mutex_exit(&ppp_softcs.lock); 306 307 if_initname(&sc->sc_if, name, sc->sc_unit = unit); 308 callout_init(&sc->sc_timo_ch, 0); 309 sc->sc_if.if_softc = sc; 310 sc->sc_if.if_mtu = PPP_MTU; 311 sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 312 sc->sc_if.if_type = IFT_PPP; 313 sc->sc_if.if_hdrlen = PPP_HDRLEN; 314 sc->sc_if.if_dlt = DLT_NULL; 315 sc->sc_if.if_ioctl = pppsioctl; 316 sc->sc_if.if_output = pppoutput; 317 #ifdef ALTQ 318 sc->sc_if.if_start = ppp_ifstart; 319 #endif 320 IFQ_SET_MAXLEN(&sc->sc_if.if_snd, IFQ_MAXLEN); 321 IFQ_SET_MAXLEN(&sc->sc_inq, IFQ_MAXLEN); 322 IFQ_SET_MAXLEN(&sc->sc_fastq, IFQ_MAXLEN); 323 IFQ_SET_MAXLEN(&sc->sc_rawq, IFQ_MAXLEN); 324 325 IFQ_LOCK_INIT(&sc->sc_fastq); 326 327 /* Ratio of 1:2 packets between the regular and the fast queue */ 328 sc->sc_maxfastq = 2; 329 IFQ_SET_READY(&sc->sc_if.if_snd); 330 if_attach(&sc->sc_if); 331 if_alloc_sadl(&sc->sc_if); 332 bpf_attach(&sc->sc_if, DLT_NULL, 0); 333 return sc; 334 } 335 336 static int 337 ppp_clone_create(struct if_clone *ifc, int unit) 338 { 339 return ppp_create(ifc->ifc_name, unit) == NULL ? EEXIST : 0; 340 } 341 342 static int 343 ppp_clone_destroy(struct ifnet *ifp) 344 { 345 struct ppp_softc *sc = (struct ppp_softc *)ifp->if_softc; 346 347 if (sc->sc_devp != NULL) 348 return EBUSY; /* Not removing it */ 349 350 mutex_enter(&ppp_softcs.lock); 351 LIST_REMOVE(sc, sc_iflist); 352 mutex_exit(&ppp_softcs.lock); 353 354 bpf_detach(ifp); 355 if_detach(ifp); 356 357 IFQ_LOCK_DESTROY(&sc->sc_fastq); 358 359 free(sc, M_DEVBUF); 360 return 0; 361 } 362 363 /* 364 * Allocate a ppp interface unit and initialize it. 365 */ 366 struct ppp_softc * 367 pppalloc(pid_t pid) 368 { 369 struct ppp_softc *sc = NULL, *scf; 370 int i; 371 372 mutex_enter(&ppp_softcs.lock); 373 LIST_FOREACH(scf, &ppp_softcs.list, sc_iflist) { 374 if (scf->sc_xfer == pid) { 375 scf->sc_xfer = 0; 376 mutex_exit(&ppp_softcs.lock); 377 return scf; 378 } 379 if (scf->sc_devp == NULL && sc == NULL) 380 sc = scf; 381 } 382 mutex_exit(&ppp_softcs.lock); 383 384 if (sc == NULL) 385 sc = ppp_create(ppp_cloner.ifc_name, -1); 386 387 sc->sc_si = softint_establish(SOFTINT_NET, pppintr, sc); 388 if (sc->sc_si == NULL) { 389 printf("%s: unable to establish softintr\n", 390 sc->sc_if.if_xname); 391 return NULL; 392 } 393 sc->sc_flags = 0; 394 sc->sc_mru = PPP_MRU; 395 sc->sc_relinq = NULL; 396 (void)memset(&sc->sc_stats, 0, sizeof(sc->sc_stats)); 397 #ifdef VJC 398 sc->sc_comp = malloc(sizeof(struct slcompress), M_DEVBUF, M_NOWAIT); 399 if (sc->sc_comp) 400 sl_compress_init(sc->sc_comp); 401 #endif 402 #ifdef PPP_COMPRESS 403 sc->sc_xc_state = NULL; 404 sc->sc_rc_state = NULL; 405 #endif /* PPP_COMPRESS */ 406 for (i = 0; i < NUM_NP; ++i) 407 sc->sc_npmode[i] = NPMODE_ERROR; 408 sc->sc_npqueue = NULL; 409 sc->sc_npqtail = &sc->sc_npqueue; 410 sc->sc_last_sent = sc->sc_last_recv = time_second; 411 412 return sc; 413 } 414 415 /* 416 * Deallocate a ppp unit. Must be called at splsoftnet or higher. 417 */ 418 void 419 pppdealloc(struct ppp_softc *sc) 420 { 421 struct mbuf *m; 422 423 softint_disestablish(sc->sc_si); 424 if_down(&sc->sc_if); 425 sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING); 426 sc->sc_devp = NULL; 427 sc->sc_xfer = 0; 428 for (;;) { 429 IF_DEQUEUE(&sc->sc_rawq, m); 430 if (m == NULL) 431 break; 432 m_freem(m); 433 } 434 for (;;) { 435 IF_DEQUEUE(&sc->sc_inq, m); 436 if (m == NULL) 437 break; 438 m_freem(m); 439 } 440 for (;;) { 441 IF_DEQUEUE(&sc->sc_fastq, m); 442 if (m == NULL) 443 break; 444 m_freem(m); 445 } 446 while ((m = sc->sc_npqueue) != NULL) { 447 sc->sc_npqueue = m->m_nextpkt; 448 m_freem(m); 449 } 450 if (sc->sc_togo != NULL) { 451 m_freem(sc->sc_togo); 452 sc->sc_togo = NULL; 453 } 454 #ifdef PPP_COMPRESS 455 ppp_ccp_closed(sc); 456 sc->sc_xc_state = NULL; 457 sc->sc_rc_state = NULL; 458 #endif /* PPP_COMPRESS */ 459 #ifdef PPP_FILTER 460 if (sc->sc_pass_filt_in.bf_insns != 0) { 461 free(sc->sc_pass_filt_in.bf_insns, M_DEVBUF); 462 sc->sc_pass_filt_in.bf_insns = 0; 463 sc->sc_pass_filt_in.bf_len = 0; 464 } 465 if (sc->sc_pass_filt_out.bf_insns != 0) { 466 free(sc->sc_pass_filt_out.bf_insns, M_DEVBUF); 467 sc->sc_pass_filt_out.bf_insns = 0; 468 sc->sc_pass_filt_out.bf_len = 0; 469 } 470 if (sc->sc_active_filt_in.bf_insns != 0) { 471 free(sc->sc_active_filt_in.bf_insns, M_DEVBUF); 472 sc->sc_active_filt_in.bf_insns = 0; 473 sc->sc_active_filt_in.bf_len = 0; 474 } 475 if (sc->sc_active_filt_out.bf_insns != 0) { 476 free(sc->sc_active_filt_out.bf_insns, M_DEVBUF); 477 sc->sc_active_filt_out.bf_insns = 0; 478 sc->sc_active_filt_out.bf_len = 0; 479 } 480 #endif /* PPP_FILTER */ 481 #ifdef VJC 482 if (sc->sc_comp != 0) { 483 free(sc->sc_comp, M_DEVBUF); 484 sc->sc_comp = 0; 485 } 486 #endif 487 (void)ppp_clone_destroy(&sc->sc_if); 488 } 489 490 /* 491 * Ioctl routine for generic ppp devices. 492 */ 493 int 494 pppioctl(struct ppp_softc *sc, u_long cmd, void *data, int flag, 495 struct lwp *l) 496 { 497 int s, error, flags, mru, npx; 498 u_int nb; 499 struct ppp_option_data *odp; 500 struct compressor *cp; 501 struct npioctl *npi; 502 time_t t; 503 #ifdef PPP_FILTER 504 struct bpf_program *bp, *nbp; 505 struct bpf_insn *newcode, *oldcode; 506 int newcodelen; 507 #endif /* PPP_FILTER */ 508 #ifdef PPP_COMPRESS 509 u_char ccp_option[CCP_MAX_OPTION_LENGTH]; 510 #endif 511 512 switch (cmd) { 513 case PPPIOCSFLAGS: 514 case PPPIOCSMRU: 515 case PPPIOCSMAXCID: 516 case PPPIOCSCOMPRESS: 517 case PPPIOCSNPMODE: 518 if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE, 519 KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, &sc->sc_if, 520 KAUTH_ARG(cmd), NULL) != 0) 521 return EPERM; 522 break; 523 case PPPIOCXFERUNIT: 524 /* XXX: Why is this privileged?! */ 525 if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE, 526 KAUTH_REQ_NETWORK_INTERFACE_GETPRIV, &sc->sc_if, 527 KAUTH_ARG(cmd), NULL) != 0) 528 return EPERM; 529 break; 530 default: 531 break; 532 } 533 534 switch (cmd) { 535 case FIONREAD: 536 *(int *)data = sc->sc_inq.ifq_len; 537 break; 538 539 case PPPIOCGUNIT: 540 *(int *)data = sc->sc_unit; 541 break; 542 543 case PPPIOCGFLAGS: 544 *(u_int *)data = sc->sc_flags; 545 break; 546 547 case PPPIOCGRAWIN: 548 { 549 struct ppp_rawin *rwin = (struct ppp_rawin *)data; 550 u_char c, q = 0; 551 552 for (c = sc->sc_rawin_start; c < sizeof(sc->sc_rawin.buf);) 553 rwin->buf[q++] = sc->sc_rawin.buf[c++]; 554 555 for (c = 0; c < sc->sc_rawin_start;) 556 rwin->buf[q++] = sc->sc_rawin.buf[c++]; 557 558 rwin->count = sc->sc_rawin.count; 559 } 560 break; 561 562 case PPPIOCSFLAGS: 563 flags = *(int *)data & SC_MASK; 564 s = splsoftnet(); 565 #ifdef PPP_COMPRESS 566 if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN)) 567 ppp_ccp_closed(sc); 568 #endif 569 splhigh(); /* XXX IMP ME HARDER */ 570 sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags; 571 splx(s); 572 break; 573 574 case PPPIOCSMRU: 575 mru = *(int *)data; 576 if (mru >= PPP_MINMRU && mru <= PPP_MAXMRU) 577 sc->sc_mru = mru; 578 break; 579 580 case PPPIOCGMRU: 581 *(int *)data = sc->sc_mru; 582 break; 583 584 #ifdef VJC 585 case PPPIOCSMAXCID: 586 if (sc->sc_comp) { 587 s = splsoftnet(); 588 sl_compress_setup(sc->sc_comp, *(int *)data); 589 splx(s); 590 } 591 break; 592 #endif 593 594 case PPPIOCXFERUNIT: 595 sc->sc_xfer = l->l_proc->p_pid; 596 break; 597 598 #ifdef PPP_COMPRESS 599 case PPPIOCSCOMPRESS: 600 odp = (struct ppp_option_data *)data; 601 nb = odp->length; 602 if (nb > sizeof(ccp_option)) 603 nb = sizeof(ccp_option); 604 if (nb < 3) 605 return EINVAL; 606 if ((error = copyin(odp->ptr, ccp_option, nb)) != 0) 607 return error; 608 /* preliminary check on the length byte */ 609 if (ccp_option[1] < 2) 610 return EINVAL; 611 cp = ppp_get_compressor(ccp_option[0]); 612 if (cp == NULL) { 613 if (sc->sc_flags & SC_DEBUG) 614 printf("%s: no compressor for [%x %x %x], %x\n", 615 sc->sc_if.if_xname, ccp_option[0], 616 ccp_option[1], ccp_option[2], nb); 617 return EINVAL; /* no handler found */ 618 } 619 /* 620 * Found a handler for the protocol - try to allocate 621 * a compressor or decompressor. 622 */ 623 error = 0; 624 if (odp->transmit) { 625 s = splsoftnet(); 626 if (sc->sc_xc_state != NULL) { 627 (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); 628 ppp_compressor_rele(sc->sc_xcomp); 629 } 630 sc->sc_xcomp = cp; 631 sc->sc_xc_state = cp->comp_alloc(ccp_option, nb); 632 if (sc->sc_xc_state == NULL) { 633 if (sc->sc_flags & SC_DEBUG) 634 printf("%s: comp_alloc failed\n", 635 sc->sc_if.if_xname); 636 error = ENOBUFS; 637 } 638 splhigh(); /* XXX IMP ME HARDER */ 639 sc->sc_flags &= ~SC_COMP_RUN; 640 splx(s); 641 } else { 642 s = splsoftnet(); 643 if (sc->sc_rc_state != NULL) { 644 (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); 645 ppp_compressor_rele(sc->sc_rcomp); 646 } 647 sc->sc_rcomp = cp; 648 sc->sc_rc_state = cp->decomp_alloc(ccp_option, nb); 649 if (sc->sc_rc_state == NULL) { 650 if (sc->sc_flags & SC_DEBUG) 651 printf("%s: decomp_alloc failed\n", 652 sc->sc_if.if_xname); 653 error = ENOBUFS; 654 } 655 splhigh(); /* XXX IMP ME HARDER */ 656 sc->sc_flags &= ~SC_DECOMP_RUN; 657 splx(s); 658 } 659 return error; 660 #endif /* PPP_COMPRESS */ 661 662 case PPPIOCGNPMODE: 663 case PPPIOCSNPMODE: 664 npi = (struct npioctl *)data; 665 switch (npi->protocol) { 666 case PPP_IP: 667 npx = NP_IP; 668 break; 669 case PPP_IPV6: 670 npx = NP_IPV6; 671 break; 672 default: 673 return EINVAL; 674 } 675 if (cmd == PPPIOCGNPMODE) { 676 npi->mode = sc->sc_npmode[npx]; 677 } else { 678 if (npi->mode != sc->sc_npmode[npx]) { 679 s = splnet(); 680 sc->sc_npmode[npx] = npi->mode; 681 if (npi->mode != NPMODE_QUEUE) { 682 ppp_requeue(sc); 683 ppp_restart(sc); 684 } 685 splx(s); 686 } 687 } 688 break; 689 690 case PPPIOCGIDLE: 691 s = splsoftnet(); 692 t = time_second; 693 ((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent; 694 ((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv; 695 splx(s); 696 break; 697 698 #ifdef PPP_FILTER 699 case PPPIOCSPASS: 700 case PPPIOCSACTIVE: 701 /* These are no longer supported. */ 702 return EOPNOTSUPP; 703 704 case PPPIOCSIPASS: 705 case PPPIOCSOPASS: 706 case PPPIOCSIACTIVE: 707 case PPPIOCSOACTIVE: 708 nbp = (struct bpf_program *)data; 709 if ((unsigned) nbp->bf_len > BPF_MAXINSNS) 710 return EINVAL; 711 newcodelen = nbp->bf_len * sizeof(struct bpf_insn); 712 if (newcodelen != 0) { 713 newcode = malloc(newcodelen, M_DEVBUF, M_WAITOK); 714 /* WAITOK -- malloc() never fails. */ 715 if ((error = copyin((void *)nbp->bf_insns, 716 (void *)newcode, newcodelen)) != 0) { 717 free(newcode, M_DEVBUF); 718 return error; 719 } 720 if (!bpf_validate(newcode, nbp->bf_len)) { 721 free(newcode, M_DEVBUF); 722 return EINVAL; 723 } 724 } else 725 newcode = 0; 726 switch (cmd) { 727 case PPPIOCSIPASS: 728 bp = &sc->sc_pass_filt_in; 729 break; 730 731 case PPPIOCSOPASS: 732 bp = &sc->sc_pass_filt_out; 733 break; 734 735 case PPPIOCSIACTIVE: 736 bp = &sc->sc_active_filt_in; 737 break; 738 739 case PPPIOCSOACTIVE: 740 bp = &sc->sc_active_filt_out; 741 break; 742 default: 743 free(newcode, M_DEVBUF); 744 return EPASSTHROUGH; 745 } 746 oldcode = bp->bf_insns; 747 s = splnet(); 748 bp->bf_len = nbp->bf_len; 749 bp->bf_insns = newcode; 750 splx(s); 751 if (oldcode != 0) 752 free(oldcode, M_DEVBUF); 753 break; 754 #endif /* PPP_FILTER */ 755 756 default: 757 return EPASSTHROUGH; 758 } 759 return 0; 760 } 761 762 /* 763 * Process an ioctl request to the ppp network interface. 764 */ 765 static int 766 pppsioctl(struct ifnet *ifp, u_long cmd, void *data) 767 { 768 struct ppp_softc *sc = ifp->if_softc; 769 struct ifaddr *ifa = (struct ifaddr *)data; 770 struct ifreq *ifr = (struct ifreq *)data; 771 struct ppp_stats *psp; 772 #ifdef PPP_COMPRESS 773 struct ppp_comp_stats *pcp; 774 #endif 775 int s = splnet(), error = 0; 776 777 switch (cmd) { 778 case SIOCSIFFLAGS: 779 if ((error = ifioctl_common(ifp, cmd, data)) != 0) 780 break; 781 if ((ifp->if_flags & IFF_RUNNING) == 0) 782 ifp->if_flags &= ~IFF_UP; 783 break; 784 785 case SIOCINITIFADDR: 786 switch (ifa->ifa_addr->sa_family) { 787 #ifdef INET 788 case AF_INET: 789 break; 790 #endif 791 #ifdef INET6 792 case AF_INET6: 793 break; 794 #endif 795 default: 796 printf("%s: af%d not supported\n", ifp->if_xname, 797 ifa->ifa_addr->sa_family); 798 error = EAFNOSUPPORT; 799 break; 800 } 801 ifa->ifa_rtrequest = p2p_rtrequest; 802 break; 803 804 case SIOCADDMULTI: 805 case SIOCDELMULTI: 806 if (ifr == NULL) { 807 error = EAFNOSUPPORT; 808 break; 809 } 810 switch (ifreq_getaddr(cmd, ifr)->sa_family) { 811 #ifdef INET 812 case AF_INET: 813 break; 814 #endif 815 #ifdef INET6 816 case AF_INET6: 817 break; 818 #endif 819 default: 820 error = EAFNOSUPPORT; 821 break; 822 } 823 break; 824 825 case SIOCGPPPSTATS: 826 psp = &((struct ifpppstatsreq *)data)->stats; 827 memset(psp, 0, sizeof(*psp)); 828 psp->p = sc->sc_stats; 829 #if defined(VJC) && !defined(SL_NO_STATS) 830 if (sc->sc_comp) { 831 psp->vj.vjs_packets = sc->sc_comp->sls_packets; 832 psp->vj.vjs_compressed = sc->sc_comp->sls_compressed; 833 psp->vj.vjs_searches = sc->sc_comp->sls_searches; 834 psp->vj.vjs_misses = sc->sc_comp->sls_misses; 835 psp->vj.vjs_uncompressedin = sc->sc_comp->sls_uncompressedin; 836 psp->vj.vjs_compressedin = sc->sc_comp->sls_compressedin; 837 psp->vj.vjs_errorin = sc->sc_comp->sls_errorin; 838 psp->vj.vjs_tossed = sc->sc_comp->sls_tossed; 839 } 840 #endif /* VJC */ 841 break; 842 843 #ifdef PPP_COMPRESS 844 case SIOCGPPPCSTATS: 845 pcp = &((struct ifpppcstatsreq *)data)->stats; 846 memset(pcp, 0, sizeof(*pcp)); 847 if (sc->sc_xc_state != NULL) 848 (*sc->sc_xcomp->comp_stat)(sc->sc_xc_state, &pcp->c); 849 if (sc->sc_rc_state != NULL) 850 (*sc->sc_rcomp->decomp_stat)(sc->sc_rc_state, &pcp->d); 851 break; 852 #endif /* PPP_COMPRESS */ 853 854 default: 855 if ((error = ifioctl_common(&sc->sc_if, cmd, data)) == ENETRESET) 856 error = 0; 857 break; 858 } 859 splx(s); 860 return error; 861 } 862 863 /* 864 * Queue a packet. Start transmission if not active. 865 * Packet is placed in Information field of PPP frame. 866 */ 867 int 868 pppoutput(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst, 869 const struct rtentry *rtp) 870 { 871 struct ppp_softc *sc = ifp->if_softc; 872 int protocol, address, control; 873 u_char *cp; 874 int s, error; 875 #ifdef INET 876 struct ip *ip; 877 #endif 878 struct ifqueue *ifq; 879 enum NPmode mode; 880 int len; 881 882 if (sc->sc_devp == NULL || 883 (ifp->if_flags & IFF_RUNNING) == 0 || 884 ((ifp->if_flags & IFF_UP) == 0 && 885 dst->sa_family != AF_UNSPEC)) { 886 error = ENETDOWN; /* sort of */ 887 goto bad; 888 } 889 890 IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family); 891 892 /* 893 * Compute PPP header. 894 */ 895 m0->m_flags &= ~M_HIGHPRI; 896 switch (dst->sa_family) { 897 #ifdef INET 898 case AF_INET: 899 address = PPP_ALLSTATIONS; 900 control = PPP_UI; 901 protocol = PPP_IP; 902 mode = sc->sc_npmode[NP_IP]; 903 904 /* 905 * If this packet has the "low delay" bit set in the IP header, 906 * put it on the fastq instead. 907 */ 908 ip = mtod(m0, struct ip *); 909 if (ip->ip_tos & IPTOS_LOWDELAY) 910 m0->m_flags |= M_HIGHPRI; 911 break; 912 #endif 913 #ifdef INET6 914 case AF_INET6: 915 address = PPP_ALLSTATIONS; /*XXX*/ 916 control = PPP_UI; /*XXX*/ 917 protocol = PPP_IPV6; 918 mode = sc->sc_npmode[NP_IPV6]; 919 920 #if 0 /* XXX flowinfo/traffic class, maybe? */ 921 /* 922 * If this packet has the "low delay" bit set in the IP header, 923 * put it on the fastq instead. 924 */ 925 ip = mtod(m0, struct ip *); 926 if (ip->ip_tos & IPTOS_LOWDELAY) 927 m0->m_flags |= M_HIGHPRI; 928 #endif 929 break; 930 #endif 931 case AF_UNSPEC: 932 address = PPP_ADDRESS(dst->sa_data); 933 control = PPP_CONTROL(dst->sa_data); 934 protocol = PPP_PROTOCOL(dst->sa_data); 935 mode = NPMODE_PASS; 936 break; 937 default: 938 printf("%s: af%d not supported\n", ifp->if_xname, 939 dst->sa_family); 940 error = EAFNOSUPPORT; 941 goto bad; 942 } 943 944 /* 945 * Drop this packet, or return an error, if necessary. 946 */ 947 if (mode == NPMODE_ERROR) { 948 error = ENETDOWN; 949 goto bad; 950 } 951 if (mode == NPMODE_DROP) { 952 error = 0; 953 goto bad; 954 } 955 956 /* 957 * Add PPP header. 958 */ 959 M_PREPEND(m0, PPP_HDRLEN, M_DONTWAIT); 960 if (m0 == NULL) { 961 error = ENOBUFS; 962 goto bad; 963 } 964 965 cp = mtod(m0, u_char *); 966 *cp++ = address; 967 *cp++ = control; 968 *cp++ = protocol >> 8; 969 *cp++ = protocol & 0xff; 970 971 len = m_length(m0); 972 973 if (sc->sc_flags & SC_LOG_OUTPKT) { 974 printf("%s output: ", ifp->if_xname); 975 pppdumpm(m0); 976 } 977 978 if ((protocol & 0x8000) == 0) { 979 #ifdef PPP_FILTER 980 /* 981 * Apply the pass and active filters to the packet, 982 * but only if it is a data packet. 983 */ 984 if (sc->sc_pass_filt_out.bf_insns != 0 && 985 bpf_filter(sc->sc_pass_filt_out.bf_insns, 986 (u_char *)m0, len, 0) == 0) { 987 error = 0; /* drop this packet */ 988 goto bad; 989 } 990 991 /* 992 * Update the time we sent the most recent packet. 993 */ 994 if (sc->sc_active_filt_out.bf_insns == 0 || 995 bpf_filter(sc->sc_active_filt_out.bf_insns, 996 (u_char *)m0, len, 0)) 997 sc->sc_last_sent = time_second; 998 #else 999 /* 1000 * Update the time we sent the most recent packet. 1001 */ 1002 sc->sc_last_sent = time_second; 1003 #endif /* PPP_FILTER */ 1004 } 1005 1006 /* 1007 * See if bpf wants to look at the packet. 1008 */ 1009 bpf_mtap(&sc->sc_if, m0, BPF_D_OUT); 1010 1011 /* 1012 * Put the packet on the appropriate queue. 1013 */ 1014 s = splnet(); 1015 if (mode == NPMODE_QUEUE) { 1016 /* XXX we should limit the number of packets on this queue */ 1017 *sc->sc_npqtail = m0; 1018 m0->m_nextpkt = NULL; 1019 sc->sc_npqtail = &m0->m_nextpkt; 1020 } else { 1021 ifq = (m0->m_flags & M_HIGHPRI) ? &sc->sc_fastq : NULL; 1022 if ((error = ifq_enqueue2(&sc->sc_if, ifq, m0)) != 0) { 1023 splx(s); 1024 if_statinc(&sc->sc_if, if_oerrors); 1025 sc->sc_stats.ppp_oerrors++; 1026 return error; 1027 } 1028 ppp_restart(sc); 1029 } 1030 if_statadd2(ifp, if_opackets, 1, if_obytes, len); 1031 1032 splx(s); 1033 return 0; 1034 1035 bad: 1036 m_freem(m0); 1037 return error; 1038 } 1039 1040 /* 1041 * After a change in the NPmode for some NP, move packets from the 1042 * npqueue to the send queue or the fast queue as appropriate. 1043 * Should be called at splnet, since we muck with the queues. 1044 */ 1045 static void 1046 ppp_requeue(struct ppp_softc *sc) 1047 { 1048 struct mbuf *m, **mpp; 1049 struct ifqueue *ifq; 1050 enum NPmode mode; 1051 int error; 1052 1053 for (mpp = &sc->sc_npqueue; (m = *mpp) != NULL; ) { 1054 switch (PPP_PROTOCOL(mtod(m, u_char *))) { 1055 case PPP_IP: 1056 mode = sc->sc_npmode[NP_IP]; 1057 break; 1058 case PPP_IPV6: 1059 mode = sc->sc_npmode[NP_IPV6]; 1060 break; 1061 default: 1062 mode = NPMODE_PASS; 1063 } 1064 1065 switch (mode) { 1066 case NPMODE_PASS: 1067 /* 1068 * This packet can now go on one of the queues to 1069 * be sent. 1070 */ 1071 *mpp = m->m_nextpkt; 1072 m->m_nextpkt = NULL; 1073 ifq = (m->m_flags & M_HIGHPRI) ? &sc->sc_fastq : NULL; 1074 if ((error = ifq_enqueue2(&sc->sc_if, ifq, m)) != 0) { 1075 if_statinc(&sc->sc_if, if_oerrors); 1076 sc->sc_stats.ppp_oerrors++; 1077 } 1078 break; 1079 1080 case NPMODE_DROP: 1081 case NPMODE_ERROR: 1082 *mpp = m->m_nextpkt; 1083 m_freem(m); 1084 break; 1085 1086 case NPMODE_QUEUE: 1087 mpp = &m->m_nextpkt; 1088 break; 1089 } 1090 } 1091 sc->sc_npqtail = mpp; 1092 } 1093 1094 /* 1095 * Transmitter has finished outputting some stuff; 1096 * remember to call sc->sc_start later at splsoftnet. 1097 */ 1098 void 1099 ppp_restart(struct ppp_softc *sc) 1100 { 1101 int s = splhigh(); /* XXX IMP ME HARDER */ 1102 1103 sc->sc_flags &= ~SC_TBUSY; 1104 softint_schedule(sc->sc_si); 1105 splx(s); 1106 } 1107 1108 /* 1109 * Get a packet to send. This procedure is intended to be called at 1110 * splsoftnet, since it may involve time-consuming operations such as 1111 * applying VJ compression, packet compression, address/control and/or 1112 * protocol field compression to the packet. 1113 */ 1114 struct mbuf * 1115 ppp_dequeue(struct ppp_softc *sc) 1116 { 1117 struct mbuf *m, *mp; 1118 u_char *cp; 1119 int address, control, protocol; 1120 int s; 1121 1122 /* 1123 * Grab a packet to send: first try the fast queue, then the 1124 * normal queue. 1125 */ 1126 s = splnet(); 1127 if (sc->sc_nfastq < sc->sc_maxfastq) { 1128 IF_DEQUEUE(&sc->sc_fastq, m); 1129 if (m != NULL) 1130 sc->sc_nfastq++; 1131 else 1132 IFQ_DEQUEUE(&sc->sc_if.if_snd, m); 1133 } else { 1134 sc->sc_nfastq = 0; 1135 IFQ_DEQUEUE(&sc->sc_if.if_snd, m); 1136 if (m == NULL) { 1137 IF_DEQUEUE(&sc->sc_fastq, m); 1138 if (m != NULL) 1139 sc->sc_nfastq++; 1140 } 1141 } 1142 splx(s); 1143 1144 if (m == NULL) 1145 return NULL; 1146 1147 ++sc->sc_stats.ppp_opackets; 1148 1149 /* 1150 * Extract the ppp header of the new packet. 1151 * The ppp header will be in one mbuf. 1152 */ 1153 cp = mtod(m, u_char *); 1154 address = PPP_ADDRESS(cp); 1155 control = PPP_CONTROL(cp); 1156 protocol = PPP_PROTOCOL(cp); 1157 1158 switch (protocol) { 1159 case PPP_IP: 1160 #ifdef VJC 1161 /* 1162 * If the packet is a TCP/IP packet, see if we can compress it. 1163 */ 1164 if ((sc->sc_flags & SC_COMP_TCP) && sc->sc_comp != NULL) { 1165 struct ip *ip; 1166 int type; 1167 1168 mp = m; 1169 ip = (struct ip *)(cp + PPP_HDRLEN); 1170 if (mp->m_len <= PPP_HDRLEN) { 1171 mp = mp->m_next; 1172 if (mp == NULL) 1173 break; 1174 ip = mtod(mp, struct ip *); 1175 } 1176 /* 1177 * This code assumes the IP/TCP header is in one 1178 * non-shared mbuf 1179 */ 1180 if (ip->ip_p == IPPROTO_TCP) { 1181 type = sl_compress_tcp(mp, ip, sc->sc_comp, 1182 !(sc->sc_flags & SC_NO_TCP_CCID)); 1183 switch (type) { 1184 case TYPE_UNCOMPRESSED_TCP: 1185 protocol = PPP_VJC_UNCOMP; 1186 break; 1187 case TYPE_COMPRESSED_TCP: 1188 protocol = PPP_VJC_COMP; 1189 cp = mtod(m, u_char *); 1190 cp[0] = address; /* Header has moved */ 1191 cp[1] = control; 1192 cp[2] = 0; 1193 break; 1194 } 1195 /* Update protocol in PPP header */ 1196 cp[3] = protocol; 1197 } 1198 } 1199 #endif /* VJC */ 1200 break; 1201 1202 #ifdef PPP_COMPRESS 1203 case PPP_CCP: 1204 ppp_ccp(sc, m, 0); 1205 break; 1206 #endif /* PPP_COMPRESS */ 1207 } 1208 1209 #ifdef PPP_COMPRESS 1210 if (protocol != PPP_LCP && protocol != PPP_CCP && 1211 sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) { 1212 struct mbuf *mcomp = NULL; 1213 int slen; 1214 1215 slen = 0; 1216 for (mp = m; mp != NULL; mp = mp->m_next) 1217 slen += mp->m_len; 1218 (*sc->sc_xcomp->compress) 1219 (sc->sc_xc_state, &mcomp, m, slen, sc->sc_if.if_mtu + PPP_HDRLEN); 1220 if (mcomp != NULL) { 1221 if (sc->sc_flags & SC_CCP_UP) { 1222 /* 1223 * Send the compressed packet instead of the 1224 * original. 1225 */ 1226 m_freem(m); 1227 m = mcomp; 1228 cp = mtod(m, u_char *); 1229 protocol = cp[3]; 1230 } else { 1231 /* 1232 * Can't transmit compressed packets until CCP 1233 * is up. 1234 */ 1235 m_freem(mcomp); 1236 } 1237 } 1238 } 1239 #endif /* PPP_COMPRESS */ 1240 1241 /* 1242 * Compress the address/control and protocol, if possible. 1243 */ 1244 if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS && 1245 control == PPP_UI && protocol != PPP_ALLSTATIONS && 1246 protocol != PPP_LCP) { 1247 /* can compress address/control */ 1248 m->m_data += 2; 1249 m->m_len -= 2; 1250 } 1251 if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) { 1252 /* can compress protocol */ 1253 if (mtod(m, u_char *) == cp) { 1254 cp[2] = cp[1]; /* move address/control up */ 1255 cp[1] = cp[0]; 1256 } 1257 ++m->m_data; 1258 --m->m_len; 1259 } 1260 1261 return m; 1262 } 1263 1264 /* 1265 * Software interrupt routine, called at splsoftnet. 1266 */ 1267 static void 1268 pppintr(void *arg) 1269 { 1270 struct ppp_softc *sc = arg; 1271 struct mbuf *m; 1272 int s; 1273 1274 mutex_enter(softnet_lock); 1275 if (!(sc->sc_flags & SC_TBUSY) && 1276 (IFQ_IS_EMPTY(&sc->sc_if.if_snd) == 0 || 1277 sc->sc_fastq.ifq_head || 1278 sc->sc_outm)) { 1279 s = splhigh(); /* XXX IMP ME HARDER */ 1280 sc->sc_flags |= SC_TBUSY; 1281 splx(s); 1282 (*sc->sc_start)(sc); 1283 } 1284 for (;;) { 1285 s = splnet(); 1286 IF_DEQUEUE(&sc->sc_rawq, m); 1287 splx(s); 1288 if (m == NULL) 1289 break; 1290 ppp_inproc(sc, m); 1291 } 1292 mutex_exit(softnet_lock); 1293 } 1294 1295 #ifdef PPP_COMPRESS 1296 /* 1297 * Handle a CCP packet. `rcvd' is 1 if the packet was received, 1298 * 0 if it is about to be transmitted. 1299 */ 1300 static void 1301 ppp_ccp(struct ppp_softc *sc, struct mbuf *m, int rcvd) 1302 { 1303 u_char *dp, *ep; 1304 struct mbuf *mp; 1305 int slen, s; 1306 1307 /* 1308 * Get a pointer to the data after the PPP header. 1309 */ 1310 if (m->m_len <= PPP_HDRLEN) { 1311 mp = m->m_next; 1312 if (mp == NULL) 1313 return; 1314 dp = mtod(mp, u_char *); 1315 } else { 1316 mp = m; 1317 dp = mtod(mp, u_char *) + PPP_HDRLEN; 1318 } 1319 1320 ep = mtod(mp, u_char *) + mp->m_len; 1321 if (dp + CCP_HDRLEN > ep) 1322 return; 1323 slen = CCP_LENGTH(dp); 1324 if (dp + slen > ep) { 1325 if (sc->sc_flags & SC_DEBUG) 1326 printf("if_ppp/ccp: not enough data in mbuf (%p+%x > %p+%x)\n", 1327 dp, slen, mtod(mp, u_char *), mp->m_len); 1328 return; 1329 } 1330 1331 switch (CCP_CODE(dp)) { 1332 case CCP_CONFREQ: 1333 case CCP_TERMREQ: 1334 case CCP_TERMACK: 1335 /* CCP must be going down - disable compression */ 1336 if (sc->sc_flags & SC_CCP_UP) { 1337 s = splhigh(); /* XXX IMP ME HARDER */ 1338 sc->sc_flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN); 1339 splx(s); 1340 } 1341 break; 1342 1343 case CCP_CONFACK: 1344 if (sc->sc_flags & SC_CCP_OPEN && 1345 !(sc->sc_flags & SC_CCP_UP) && 1346 slen >= CCP_HDRLEN + CCP_OPT_MINLEN && 1347 slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) { 1348 if (!rcvd) { 1349 /* We're agreeing to send compressed packets. */ 1350 if (sc->sc_xc_state != NULL && 1351 (*sc->sc_xcomp->comp_init)(sc->sc_xc_state, 1352 dp + CCP_HDRLEN, slen - CCP_HDRLEN, 1353 sc->sc_unit, 0, 1354 sc->sc_flags & SC_DEBUG)) { 1355 s = splhigh(); /* XXX IMP ME HARDER */ 1356 sc->sc_flags |= SC_COMP_RUN; 1357 splx(s); 1358 } 1359 } else { 1360 /* 1361 * Peer is agreeing to send compressed 1362 * packets. 1363 */ 1364 if (sc->sc_rc_state != NULL && 1365 (*sc->sc_rcomp->decomp_init)( 1366 sc->sc_rc_state, 1367 dp + CCP_HDRLEN, slen - CCP_HDRLEN, 1368 sc->sc_unit, 0, sc->sc_mru, 1369 sc->sc_flags & SC_DEBUG)) { 1370 s = splhigh(); /* XXX IMP ME HARDER */ 1371 sc->sc_flags |= SC_DECOMP_RUN; 1372 sc->sc_flags &= 1373 ~(SC_DC_ERROR | SC_DC_FERROR); 1374 splx(s); 1375 } 1376 } 1377 } 1378 break; 1379 1380 case CCP_RESETACK: 1381 if (sc->sc_flags & SC_CCP_UP) { 1382 if (!rcvd) { 1383 if (sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) 1384 (*sc->sc_xcomp->comp_reset)(sc->sc_xc_state); 1385 } else { 1386 if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) { 1387 (*sc->sc_rcomp->decomp_reset)(sc->sc_rc_state); 1388 s = splhigh(); /* XXX IMP ME HARDER */ 1389 sc->sc_flags &= ~SC_DC_ERROR; 1390 splx(s); 1391 } 1392 } 1393 } 1394 break; 1395 } 1396 } 1397 1398 /* 1399 * CCP is down; free (de)compressor state if necessary. 1400 */ 1401 static void 1402 ppp_ccp_closed(struct ppp_softc *sc) 1403 { 1404 if (sc->sc_xc_state) { 1405 (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); 1406 ppp_compressor_rele(sc->sc_xcomp); 1407 sc->sc_xc_state = NULL; 1408 } 1409 if (sc->sc_rc_state) { 1410 (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); 1411 ppp_compressor_rele(sc->sc_rcomp); 1412 sc->sc_rc_state = NULL; 1413 } 1414 } 1415 #endif /* PPP_COMPRESS */ 1416 1417 /* 1418 * PPP packet input routine. 1419 * The caller has checked and removed the FCS and has inserted 1420 * the address/control bytes and the protocol high byte if they 1421 * were omitted. 1422 */ 1423 void 1424 ppppktin(struct ppp_softc *sc, struct mbuf *m, int lost) 1425 { 1426 int s = splhigh(); /* XXX IMP ME HARDER */ 1427 1428 if (lost) 1429 m->m_flags |= M_ERRMARK; 1430 IF_ENQUEUE(&sc->sc_rawq, m); 1431 softint_schedule(sc->sc_si); 1432 splx(s); 1433 } 1434 1435 /* 1436 * Process a received PPP packet, doing decompression as necessary. 1437 * Should be called at splsoftnet. 1438 */ 1439 #define COMPTYPE(proto) \ 1440 ((proto) == PPP_VJC_COMP ? TYPE_COMPRESSED_TCP \ 1441 : TYPE_UNCOMPRESSED_TCP) 1442 1443 static void 1444 ppp_inproc(struct ppp_softc *sc, struct mbuf *m) 1445 { 1446 struct ifnet *ifp = &sc->sc_if; 1447 pktqueue_t *pktq = NULL; 1448 struct ifqueue *inq = NULL; 1449 int s, ilen, proto, rv; 1450 u_char *cp, adrs, ctrl; 1451 struct mbuf *mp, *dmp = NULL; 1452 #ifdef VJC 1453 int xlen; 1454 u_char *iphdr; 1455 u_int hlen; 1456 #endif 1457 1458 sc->sc_stats.ppp_ipackets++; 1459 1460 if (sc->sc_flags & SC_LOG_INPKT) { 1461 ilen = 0; 1462 for (mp = m; mp != NULL; mp = mp->m_next) 1463 ilen += mp->m_len; 1464 printf("%s: got %d bytes\n", ifp->if_xname, ilen); 1465 pppdumpm(m); 1466 } 1467 1468 cp = mtod(m, u_char *); 1469 adrs = PPP_ADDRESS(cp); 1470 ctrl = PPP_CONTROL(cp); 1471 proto = PPP_PROTOCOL(cp); 1472 1473 if (m->m_flags & M_ERRMARK) { 1474 m->m_flags &= ~M_ERRMARK; 1475 s = splhigh(); /* XXX IMP ME HARDER */ 1476 sc->sc_flags |= SC_VJ_RESET; 1477 splx(s); 1478 } 1479 1480 #ifdef PPP_COMPRESS 1481 /* 1482 * Decompress this packet if necessary, update the receiver's 1483 * dictionary, or take appropriate action on a CCP packet. 1484 */ 1485 if (proto == PPP_COMP && 1486 sc->sc_rc_state && 1487 (sc->sc_flags & SC_DECOMP_RUN) && 1488 !(sc->sc_flags & SC_DC_ERROR) && 1489 !(sc->sc_flags & SC_DC_FERROR)) { 1490 /* Decompress this packet */ 1491 rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp); 1492 if (rv == DECOMP_OK) { 1493 m_freem(m); 1494 if (dmp == NULL) { 1495 /* 1496 * No error, but no decompressed packet 1497 * produced 1498 */ 1499 return; 1500 } 1501 m = dmp; 1502 cp = mtod(m, u_char *); 1503 proto = PPP_PROTOCOL(cp); 1504 1505 } else { 1506 /* 1507 * An error has occurred in decompression. 1508 * Pass the compressed packet up to pppd, which may 1509 * take CCP down or issue a Reset-Req. 1510 */ 1511 if (sc->sc_flags & SC_DEBUG) 1512 printf("%s: decompress failed %d\n", 1513 ifp->if_xname, rv); 1514 s = splhigh(); /* XXX IMP ME HARDER */ 1515 sc->sc_flags |= SC_VJ_RESET; 1516 if (rv == DECOMP_ERROR) 1517 sc->sc_flags |= SC_DC_ERROR; 1518 else 1519 sc->sc_flags |= SC_DC_FERROR; 1520 splx(s); 1521 } 1522 1523 } else { 1524 if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) 1525 (*sc->sc_rcomp->incomp)(sc->sc_rc_state, m); 1526 if (proto == PPP_CCP) 1527 ppp_ccp(sc, m, 1); 1528 } 1529 #endif 1530 1531 ilen = 0; 1532 for (mp = m; mp != NULL; mp = mp->m_next) 1533 ilen += mp->m_len; 1534 1535 #ifdef VJC 1536 if (sc->sc_flags & SC_VJ_RESET) { 1537 /* 1538 * If we've missed a packet, we must toss subsequent compressed 1539 * packets which don't have an explicit connection ID. 1540 */ 1541 if (sc->sc_comp) 1542 sl_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp); 1543 s = splhigh(); /* XXX IMP ME HARDER */ 1544 sc->sc_flags &= ~SC_VJ_RESET; 1545 splx(s); 1546 } 1547 1548 /* 1549 * See if we have a VJ-compressed packet to uncompress. 1550 */ 1551 if (proto == PPP_VJC_COMP) { 1552 if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) 1553 goto bad; 1554 1555 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, 1556 m->m_len - PPP_HDRLEN, ilen - PPP_HDRLEN, 1557 TYPE_COMPRESSED_TCP, sc->sc_comp, &iphdr, &hlen); 1558 if (xlen <= 0) { 1559 if (sc->sc_flags & SC_DEBUG) { 1560 printf("%s: VJ uncompress failed" 1561 " on type comp\n", 1562 ifp->if_xname); 1563 } 1564 goto bad; 1565 } 1566 1567 /* Copy the PPP and IP headers into a new mbuf. */ 1568 MGETHDR(mp, M_DONTWAIT, MT_DATA); 1569 if (mp == NULL) 1570 goto bad; 1571 mp->m_len = 0; 1572 mp->m_next = NULL; 1573 if (hlen + PPP_HDRLEN > MHLEN) { 1574 MCLGET(mp, M_DONTWAIT); 1575 if (M_TRAILINGSPACE(mp) < hlen + PPP_HDRLEN) { 1576 /* Lose if big headers and no clusters */ 1577 m_freem(mp); 1578 goto bad; 1579 } 1580 } 1581 cp = mtod(mp, u_char *); 1582 cp[0] = adrs; 1583 cp[1] = ctrl; 1584 cp[2] = 0; 1585 cp[3] = PPP_IP; 1586 proto = PPP_IP; 1587 bcopy(iphdr, cp + PPP_HDRLEN, hlen); 1588 mp->m_len = hlen + PPP_HDRLEN; 1589 1590 /* 1591 * Trim the PPP and VJ headers off the old mbuf 1592 * and stick the new and old mbufs together. 1593 */ 1594 m->m_data += PPP_HDRLEN + xlen; 1595 m->m_len -= PPP_HDRLEN + xlen; 1596 if (m->m_len <= M_TRAILINGSPACE(mp)) { 1597 bcopy(mtod(m, u_char *), 1598 mtod(mp, u_char *) + mp->m_len, m->m_len); 1599 mp->m_len += m->m_len; 1600 mp->m_next = m_free(m); 1601 } else 1602 mp->m_next = m; 1603 m = mp; 1604 ilen += hlen - xlen; 1605 1606 } else if (proto == PPP_VJC_UNCOMP) { 1607 if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) 1608 goto bad; 1609 1610 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, 1611 m->m_len - PPP_HDRLEN, ilen - PPP_HDRLEN, 1612 TYPE_UNCOMPRESSED_TCP, sc->sc_comp, &iphdr, &hlen); 1613 if (xlen < 0) { 1614 if (sc->sc_flags & SC_DEBUG) { 1615 printf("%s: VJ uncompress failed" 1616 " on type uncomp\n", 1617 ifp->if_xname); 1618 } 1619 goto bad; 1620 } 1621 1622 proto = PPP_IP; 1623 cp[3] = PPP_IP; 1624 } 1625 #endif /* VJC */ 1626 1627 /* 1628 * If the packet will fit in a header mbuf, don't waste a 1629 * whole cluster on it. 1630 */ 1631 if (ilen <= MHLEN && (m->m_flags & M_EXT)) { 1632 MGETHDR(mp, M_DONTWAIT, MT_DATA); 1633 if (mp != NULL) { 1634 m_copydata(m, 0, ilen, mtod(mp, void *)); 1635 m_freem(m); 1636 m = mp; 1637 m->m_len = ilen; 1638 } 1639 } 1640 m->m_pkthdr.len = ilen; 1641 m_set_rcvif(m, ifp); 1642 1643 if ((proto & 0x8000) == 0) { 1644 #ifdef PPP_FILTER 1645 /* 1646 * See whether we want to pass this packet, and 1647 * if it counts as link activity. 1648 */ 1649 if (sc->sc_pass_filt_in.bf_insns != 0 && 1650 bpf_filter(sc->sc_pass_filt_in.bf_insns, 1651 (u_char *)m, ilen, 0) == 0) { 1652 /* drop this packet */ 1653 m_freem(m); 1654 return; 1655 } 1656 if (sc->sc_active_filt_in.bf_insns == 0 || 1657 bpf_filter(sc->sc_active_filt_in.bf_insns, 1658 (u_char *)m, ilen, 0)) 1659 sc->sc_last_recv = time_second; 1660 #else 1661 /* 1662 * Record the time that we received this packet. 1663 */ 1664 sc->sc_last_recv = time_second; 1665 #endif /* PPP_FILTER */ 1666 } 1667 1668 /* See if bpf wants to look at the packet. */ 1669 bpf_mtap(&sc->sc_if, m, BPF_D_IN); 1670 1671 switch (proto) { 1672 #ifdef INET 1673 case PPP_IP: 1674 /* 1675 * IP packet - take off the ppp header and pass it up to IP. 1676 */ 1677 if ((ifp->if_flags & IFF_UP) == 0 || 1678 sc->sc_npmode[NP_IP] != NPMODE_PASS) { 1679 /* Interface is down - drop the packet. */ 1680 m_freem(m); 1681 return; 1682 } 1683 m->m_pkthdr.len -= PPP_HDRLEN; 1684 m->m_data += PPP_HDRLEN; 1685 m->m_len -= PPP_HDRLEN; 1686 #ifdef GATEWAY 1687 if (ipflow_fastforward(m)) 1688 return; 1689 #endif 1690 pktq = ip_pktq; 1691 break; 1692 #endif 1693 1694 #ifdef INET6 1695 case PPP_IPV6: 1696 /* 1697 * IPv6 packet - take off the ppp header and pass it up to 1698 * IPv6. 1699 */ 1700 if ((ifp->if_flags & IFF_UP) == 0 || 1701 sc->sc_npmode[NP_IPV6] != NPMODE_PASS) { 1702 /* interface is down - drop the packet. */ 1703 m_freem(m); 1704 return; 1705 } 1706 m->m_pkthdr.len -= PPP_HDRLEN; 1707 m->m_data += PPP_HDRLEN; 1708 m->m_len -= PPP_HDRLEN; 1709 #ifdef GATEWAY 1710 if (ip6flow_fastforward(&m)) 1711 return; 1712 #endif 1713 pktq = ip6_pktq; 1714 break; 1715 #endif 1716 1717 default: 1718 /* 1719 * Some other protocol - place on input queue for read(). 1720 */ 1721 inq = &sc->sc_inq; 1722 pktq = NULL; 1723 break; 1724 } 1725 1726 /* 1727 * Put the packet on the appropriate input queue. 1728 */ 1729 s = splnet(); 1730 1731 /* pktq: inet or inet6 cases */ 1732 if (__predict_true(pktq)) { 1733 if (__predict_false(!pktq_enqueue(pktq, m, 0))) { 1734 splx(s); 1735 if_statinc(ifp, if_iqdrops); 1736 goto bad; 1737 } 1738 if_statadd2(ifp, if_ipackets, 1, if_ibytes, ilen); 1739 splx(s); 1740 return; 1741 } 1742 1743 /* ifq: other protocol cases */ 1744 if (!inq) { 1745 splx(s); 1746 goto bad; 1747 } 1748 if (IF_QFULL(inq)) { 1749 IF_DROP(inq); 1750 splx(s); 1751 if (sc->sc_flags & SC_DEBUG) 1752 printf("%s: input queue full\n", ifp->if_xname); 1753 if_statinc(ifp, if_iqdrops); 1754 goto bad; 1755 } 1756 IF_ENQUEUE(inq, m); 1757 splx(s); 1758 if_statadd2(ifp, if_ipackets, 1, if_ibytes, ilen); 1759 1760 (*sc->sc_ctlp)(sc); 1761 1762 return; 1763 1764 bad: 1765 m_freem(m); 1766 if_statinc(&sc->sc_if, if_ierrors); 1767 sc->sc_stats.ppp_ierrors++; 1768 } 1769 1770 #define MAX_DUMP_BYTES 128 1771 1772 static void 1773 pppdumpm(struct mbuf *m0) 1774 { 1775 char buf[3*MAX_DUMP_BYTES+4]; 1776 char *bp = buf; 1777 struct mbuf *m; 1778 1779 for (m = m0; m; m = m->m_next) { 1780 int l = m->m_len; 1781 u_char *rptr = (u_char *)m->m_data; 1782 1783 while (l--) { 1784 if (bp > buf + sizeof(buf) - 4) 1785 goto done; 1786 /* Convert byte to ascii hex */ 1787 *bp++ = hexdigits[*rptr >> 4]; 1788 *bp++ = hexdigits[*rptr++ & 0xf]; 1789 } 1790 1791 if (m->m_next) { 1792 if (bp > buf + sizeof(buf) - 3) 1793 goto done; 1794 *bp++ = '|'; 1795 } else 1796 *bp++ = ' '; 1797 } 1798 done: 1799 if (m) 1800 *bp++ = '>'; 1801 *bp = 0; 1802 printf("%s\n", buf); 1803 } 1804 1805 #ifdef ALTQ 1806 /* 1807 * A wrapper to transmit a packet from if_start since ALTQ uses 1808 * if_start to send a packet. 1809 */ 1810 static void 1811 ppp_ifstart(struct ifnet *ifp) 1812 { 1813 struct ppp_softc *sc; 1814 1815 sc = ifp->if_softc; 1816 (*sc->sc_start)(sc); 1817 } 1818 #endif 1819 1820 static const struct ppp_known_compressor { 1821 uint8_t code; 1822 const char *module; 1823 } ppp_known_compressors[] = { 1824 { CI_DEFLATE, "ppp_deflate" }, 1825 { CI_DEFLATE_DRAFT, "ppp_deflate" }, 1826 { CI_BSD_COMPRESS, "ppp_bsdcomp" }, 1827 { CI_MPPE, "ppp_mppe" }, 1828 { 0, NULL } 1829 }; 1830 1831 static int 1832 ppp_compressor_init(void) 1833 { 1834 1835 mutex_init(&ppp_compressors_mtx, MUTEX_DEFAULT, IPL_NONE); 1836 return 0; 1837 } 1838 1839 static int 1840 ppp_compressor_destroy(void) 1841 { 1842 1843 mutex_destroy(&ppp_compressors_mtx); 1844 return 0; 1845 } 1846 1847 static void 1848 ppp_compressor_rele(struct compressor *cp) 1849 { 1850 1851 mutex_enter(&ppp_compressors_mtx); 1852 --cp->comp_refcnt; 1853 mutex_exit(&ppp_compressors_mtx); 1854 } 1855 1856 static struct compressor * 1857 ppp_get_compressor_noload(uint8_t ci, bool hold) 1858 { 1859 struct compressor *cp; 1860 1861 KASSERT(mutex_owned(&ppp_compressors_mtx)); 1862 LIST_FOREACH(cp, &ppp_compressors, comp_list) { 1863 if (cp->compress_proto == ci) { 1864 if (hold) 1865 ++cp->comp_refcnt; 1866 return cp; 1867 } 1868 } 1869 1870 return NULL; 1871 } 1872 1873 static struct compressor * 1874 ppp_get_compressor(uint8_t ci) 1875 { 1876 struct compressor *cp = NULL; 1877 const struct ppp_known_compressor *pkc; 1878 1879 mutex_enter(&ppp_compressors_mtx); 1880 cp = ppp_get_compressor_noload(ci, true); 1881 mutex_exit(&ppp_compressors_mtx); 1882 if (cp != NULL) 1883 return cp; 1884 1885 kernconfig_lock(); 1886 mutex_enter(&ppp_compressors_mtx); 1887 cp = ppp_get_compressor_noload(ci, true); 1888 mutex_exit(&ppp_compressors_mtx); 1889 if (cp == NULL) { 1890 /* Not found, so try to autoload a module */ 1891 for (pkc = ppp_known_compressors; pkc->module != NULL; pkc++) { 1892 if (pkc->code == ci) { 1893 if (module_autoload(pkc->module, 1894 MODULE_CLASS_MISC) != 0) 1895 break; 1896 mutex_enter(&ppp_compressors_mtx); 1897 cp = ppp_get_compressor_noload(ci, true); 1898 mutex_exit(&ppp_compressors_mtx); 1899 break; 1900 } 1901 } 1902 } 1903 kernconfig_unlock(); 1904 1905 return cp; 1906 } 1907 1908 int 1909 ppp_register_compressor(struct compressor *pc, size_t ncomp) 1910 { 1911 int error = 0; 1912 size_t i; 1913 1914 mutex_enter(&ppp_compressors_mtx); 1915 for (i = 0; i < ncomp; i++) { 1916 if (ppp_get_compressor_noload(pc[i].compress_proto, 1917 false) != NULL) 1918 error = EEXIST; 1919 } 1920 if (!error) { 1921 for (i = 0; i < ncomp; i++) { 1922 pc[i].comp_refcnt = 0; 1923 LIST_INSERT_HEAD(&ppp_compressors, &pc[i], comp_list); 1924 } 1925 } 1926 mutex_exit(&ppp_compressors_mtx); 1927 1928 return error; 1929 } 1930 1931 int 1932 ppp_unregister_compressor(struct compressor *pc, size_t ncomp) 1933 { 1934 int error = 0; 1935 size_t i; 1936 1937 mutex_enter(&ppp_compressors_mtx); 1938 for (i = 0; i < ncomp; i++) { 1939 if (ppp_get_compressor_noload(pc[i].compress_proto, 1940 false) != &pc[i]) 1941 error = ENOENT; 1942 else if (pc[i].comp_refcnt != 0) 1943 error = EBUSY; 1944 } 1945 if (!error) { 1946 for (i = 0; i < ncomp; i++) { 1947 LIST_REMOVE(&pc[i], comp_list); 1948 } 1949 } 1950 mutex_exit(&ppp_compressors_mtx); 1951 1952 return error; 1953 } 1954 1955 /* 1956 * Module infrastructure 1957 */ 1958 #include "if_module.h" 1959 1960 #ifdef PPP_FILTER 1961 #define PPP_DEP "bpf_filter," 1962 #else 1963 #define PPP_DEP 1964 #endif 1965 1966 IF_MODULE(MODULE_CLASS_DRIVER, ppp, PPP_DEP "slcompress") 1967