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