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