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