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