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