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