1 /* $NetBSD: if_ppp.c,v 1.146 2014/07/01 15:03:58 msaitoh Exp $ */ 2 /* Id: if_ppp.c,v 1.6 1997/03/04 03:33:00 paulus Exp */ 3 4 /* 5 * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver. 6 * 7 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. The name "Carnegie Mellon University" must not be used to 22 * endorse or promote products derived from this software without 23 * prior written permission. For permission or any legal 24 * details, please contact 25 * Office of Technology Transfer 26 * Carnegie Mellon University 27 * 5000 Forbes Avenue 28 * Pittsburgh, PA 15213-3890 29 * (412) 268-4387, fax: (412) 268-7395 30 * tech-transfer@andrew.cmu.edu 31 * 32 * 4. Redistributions of any form whatsoever must retain the following 33 * acknowledgment: 34 * "This product includes software developed by Computing Services 35 * at Carnegie Mellon University (http://www.cmu.edu/computing/)." 36 * 37 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO 38 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 39 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE 40 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 41 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 42 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 43 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 44 * 45 * Based on: 46 * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89 47 * 48 * Copyright (c) 1987 Regents of the University of California. 49 * All rights reserved. 50 * 51 * Redistribution and use in source and binary forms are permitted 52 * provided that the above copyright notice and this paragraph are 53 * duplicated in all such forms and that any documentation, 54 * advertising materials, and other materials related to such 55 * distribution and use acknowledge that the software was developed 56 * by the University of California, Berkeley. The name of the 57 * University may not be used to endorse or promote products derived 58 * from this software without specific prior written permission. 59 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 60 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 61 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 62 * 63 * Serial Line interface 64 * 65 * Rick Adams 66 * Center for Seismic Studies 67 * 1300 N 17th Street, Suite 1450 68 * Arlington, Virginia 22209 69 * (703)276-7900 70 * rick@seismo.ARPA 71 * seismo!rick 72 * 73 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris). 74 * Converted to 4.3BSD Beta by Chris Torek. 75 * Other changes made at Berkeley, based in part on code by Kirk Smith. 76 * 77 * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com) 78 * Added VJ tcp header compression; more unified ioctls 79 * 80 * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au). 81 * Cleaned up a lot of the mbuf-related code to fix bugs that 82 * caused system crashes and packet corruption. Changed pppstart 83 * so that it doesn't just give up with a collision if the whole 84 * packet doesn't fit in the output ring buffer. 85 * 86 * Added priority queueing for interactive IP packets, following 87 * the model of if_sl.c, plus hooks for bpf. 88 * Paul Mackerras (paulus@cs.anu.edu.au). 89 */ 90 91 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */ 92 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */ 93 94 /* 95 * XXX IMP ME HARDER 96 * 97 * This is an explanation of that comment. This code used to use 98 * splimp() to block both network and tty interrupts. However, 99 * that call is deprecated. So, we have replaced the uses of 100 * splimp() with splhigh() in order to applomplish what it needs 101 * to accomplish, and added that happy little comment. 102 */ 103 104 #include <sys/cdefs.h> 105 __KERNEL_RCSID(0, "$NetBSD: if_ppp.c,v 1.146 2014/07/01 15:03:58 msaitoh 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/socketvar.h> 134 135 #include <net/if.h> 136 #include <net/if_types.h> 137 #include <net/netisr.h> 138 #include <net/route.h> 139 #ifdef PPP_FILTER 140 #include <net/bpf.h> 141 #endif 142 143 #include <netinet/in.h> 144 #include <netinet/in_systm.h> 145 #include <netinet/in_var.h> 146 #ifdef INET 147 #include <netinet/ip.h> 148 #endif 149 150 #include <net/bpf.h> 151 152 #include <net/slip.h> 153 154 #ifdef VJC 155 #include <net/slcompress.h> 156 #endif 157 158 #include <net/ppp_defs.h> 159 #include <net/if_ppp.h> 160 #include <net/if_pppvar.h> 161 #include <sys/cpu.h> 162 163 #ifdef PPP_COMPRESS 164 #define PACKETPTR struct mbuf * 165 #include <net/ppp-comp.h> 166 #endif 167 168 static int pppsioctl(struct ifnet *, u_long, void *); 169 static void ppp_requeue(struct ppp_softc *); 170 static void ppp_ccp(struct ppp_softc *, struct mbuf *m, int rcvd); 171 static void ppp_ccp_closed(struct ppp_softc *); 172 static void ppp_inproc(struct ppp_softc *, struct mbuf *); 173 static void pppdumpm(struct mbuf *m0); 174 #ifdef ALTQ 175 static void ppp_ifstart(struct ifnet *ifp); 176 #endif 177 178 static void pppintr(void *); 179 180 /* 181 * Some useful mbuf macros not in mbuf.h. 182 */ 183 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT) 184 185 #define M_DATASTART(m) \ 186 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \ 187 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat) 188 189 #define M_DATASIZE(m) \ 190 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \ 191 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN) 192 193 /* 194 * We define two link layer specific mbuf flags, to mark high-priority 195 * packets for output, and received packets following lost/corrupted 196 * packets. 197 */ 198 #define M_HIGHPRI M_LINK0 /* output packet for sc_fastq */ 199 #define M_ERRMARK M_LINK1 /* rx packet following lost/corrupted pkt */ 200 201 static int ppp_clone_create(struct if_clone *, int); 202 static int ppp_clone_destroy(struct ifnet *); 203 204 static struct ppp_softc *ppp_create(const char *, int); 205 206 static LIST_HEAD(, ppp_softc) ppp_softc_list; 207 static kmutex_t ppp_list_lock; 208 209 struct if_clone ppp_cloner = 210 IF_CLONE_INITIALIZER("ppp", ppp_clone_create, ppp_clone_destroy); 211 212 #ifdef PPP_COMPRESS 213 ONCE_DECL(ppp_compressor_mtx_init); 214 static LIST_HEAD(, compressor) ppp_compressors = { NULL }; 215 static kmutex_t ppp_compressors_mtx; 216 217 static int ppp_compressor_init(void); 218 static struct compressor *ppp_get_compressor(uint8_t); 219 static void ppp_compressor_rele(struct compressor *); 220 #endif /* PPP_COMPRESS */ 221 222 223 /* 224 * Called from boot code to establish ppp interfaces. 225 */ 226 void 227 pppattach(void) 228 { 229 extern struct linesw ppp_disc; 230 231 if (ttyldisc_attach(&ppp_disc) != 0) 232 panic("pppattach"); 233 234 mutex_init(&ppp_list_lock, MUTEX_DEFAULT, IPL_NONE); 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 mutex_enter(&ppp_list_lock); 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 mutex_exit(&ppp_list_lock); 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_attach(&sc->sc_if, DLT_NULL, 0); 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 mutex_enter(&ppp_list_lock); 326 LIST_REMOVE(sc, sc_iflist); 327 mutex_exit(&ppp_list_lock); 328 329 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 mutex_enter(&ppp_list_lock); 346 LIST_FOREACH(scf, &ppp_softc_list, sc_iflist) { 347 if (scf->sc_xfer == pid) { 348 scf->sc_xfer = 0; 349 mutex_exit(&ppp_list_lock); 350 return scf; 351 } 352 if (scf->sc_devp == NULL && sc == NULL) 353 sc = scf; 354 } 355 mutex_exit(&ppp_list_lock); 356 357 if (sc == NULL) 358 sc = ppp_create(ppp_cloner.ifc_name, -1); 359 360 sc->sc_si = softint_establish(SOFTINT_NET, pppintr, sc); 361 if (sc->sc_si == NULL) { 362 printf("%s: unable to establish softintr\n", 363 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, 493 KAUTH_ARG(cmd), 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, 500 KAUTH_ARG(cmd), 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 /* preliminary check on the length byte */ 580 if (ccp_option[1] < 2) 581 return (EINVAL); 582 cp = ppp_get_compressor(ccp_option[0]); 583 if (cp == NULL) { 584 if (sc->sc_flags & SC_DEBUG) 585 printf("%s: no compressor for [%x %x %x], %x\n", 586 sc->sc_if.if_xname, ccp_option[0], 587 ccp_option[1], ccp_option[2], nb); 588 return (EINVAL); /* no handler found */ 589 } 590 /* 591 * Found a handler for the protocol - try to allocate 592 * a compressor or decompressor. 593 */ 594 error = 0; 595 if (odp->transmit) { 596 s = splsoftnet(); 597 if (sc->sc_xc_state != NULL) { 598 (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); 599 ppp_compressor_rele(sc->sc_xcomp); 600 } 601 sc->sc_xcomp = cp; 602 sc->sc_xc_state = cp->comp_alloc(ccp_option, nb); 603 if (sc->sc_xc_state == NULL) { 604 if (sc->sc_flags & SC_DEBUG) 605 printf("%s: comp_alloc failed\n", 606 sc->sc_if.if_xname); 607 error = ENOBUFS; 608 } 609 splhigh(); /* XXX IMP ME HARDER */ 610 sc->sc_flags &= ~SC_COMP_RUN; 611 splx(s); 612 } else { 613 s = splsoftnet(); 614 if (sc->sc_rc_state != NULL) { 615 (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); 616 ppp_compressor_rele(sc->sc_rcomp); 617 } 618 sc->sc_rcomp = cp; 619 sc->sc_rc_state = cp->decomp_alloc(ccp_option, nb); 620 if (sc->sc_rc_state == NULL) { 621 if (sc->sc_flags & SC_DEBUG) 622 printf("%s: decomp_alloc failed\n", 623 sc->sc_if.if_xname); 624 error = ENOBUFS; 625 } 626 splhigh(); /* XXX IMP ME HARDER */ 627 sc->sc_flags &= ~SC_DECOMP_RUN; 628 splx(s); 629 } 630 return (error); 631 #endif /* PPP_COMPRESS */ 632 633 case PPPIOCGNPMODE: 634 case PPPIOCSNPMODE: 635 npi = (struct npioctl *) data; 636 switch (npi->protocol) { 637 case PPP_IP: 638 npx = NP_IP; 639 break; 640 case PPP_IPV6: 641 npx = NP_IPV6; 642 break; 643 default: 644 return EINVAL; 645 } 646 if (cmd == PPPIOCGNPMODE) { 647 npi->mode = sc->sc_npmode[npx]; 648 } else { 649 if (npi->mode != sc->sc_npmode[npx]) { 650 s = splnet(); 651 sc->sc_npmode[npx] = npi->mode; 652 if (npi->mode != NPMODE_QUEUE) { 653 ppp_requeue(sc); 654 ppp_restart(sc); 655 } 656 splx(s); 657 } 658 } 659 break; 660 661 case PPPIOCGIDLE: 662 s = splsoftnet(); 663 t = time_second; 664 ((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent; 665 ((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv; 666 splx(s); 667 break; 668 669 #ifdef PPP_FILTER 670 case PPPIOCSPASS: 671 case PPPIOCSACTIVE: 672 /* These are no longer supported. */ 673 return EOPNOTSUPP; 674 675 case PPPIOCSIPASS: 676 case PPPIOCSOPASS: 677 case PPPIOCSIACTIVE: 678 case PPPIOCSOACTIVE: 679 nbp = (struct bpf_program *) data; 680 if ((unsigned) nbp->bf_len > BPF_MAXINSNS) 681 return EINVAL; 682 newcodelen = nbp->bf_len * sizeof(struct bpf_insn); 683 if (newcodelen != 0) { 684 newcode = malloc(newcodelen, M_DEVBUF, M_WAITOK); 685 /* WAITOK -- malloc() never fails. */ 686 if ((error = copyin((void *)nbp->bf_insns, 687 (void *)newcode, newcodelen)) != 0) { 688 free(newcode, M_DEVBUF); 689 return error; 690 } 691 if (!bpf_validate(newcode, nbp->bf_len)) { 692 free(newcode, M_DEVBUF); 693 return EINVAL; 694 } 695 } else 696 newcode = 0; 697 switch (cmd) { 698 case PPPIOCSIPASS: 699 bp = &sc->sc_pass_filt_in; 700 break; 701 702 case PPPIOCSOPASS: 703 bp = &sc->sc_pass_filt_out; 704 break; 705 706 case PPPIOCSIACTIVE: 707 bp = &sc->sc_active_filt_in; 708 break; 709 710 case PPPIOCSOACTIVE: 711 bp = &sc->sc_active_filt_out; 712 break; 713 default: 714 free(newcode, M_DEVBUF); 715 return (EPASSTHROUGH); 716 } 717 oldcode = bp->bf_insns; 718 s = splnet(); 719 bp->bf_len = nbp->bf_len; 720 bp->bf_insns = newcode; 721 splx(s); 722 if (oldcode != 0) 723 free(oldcode, M_DEVBUF); 724 break; 725 #endif /* PPP_FILTER */ 726 727 default: 728 return (EPASSTHROUGH); 729 } 730 return (0); 731 } 732 733 /* 734 * Process an ioctl request to the ppp network interface. 735 */ 736 static int 737 pppsioctl(struct ifnet *ifp, u_long cmd, void *data) 738 { 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 SIOCADDMULTI: 773 case SIOCDELMULTI: 774 if (ifr == NULL) { 775 error = EAFNOSUPPORT; 776 break; 777 } 778 switch (ifreq_getaddr(cmd, ifr)->sa_family) { 779 #ifdef INET 780 case AF_INET: 781 break; 782 #endif 783 #ifdef INET6 784 case AF_INET6: 785 break; 786 #endif 787 default: 788 error = EAFNOSUPPORT; 789 break; 790 } 791 break; 792 793 case SIOCGPPPSTATS: 794 psp = &((struct ifpppstatsreq *) data)->stats; 795 memset(psp, 0, sizeof(*psp)); 796 psp->p = sc->sc_stats; 797 #if defined(VJC) && !defined(SL_NO_STATS) 798 if (sc->sc_comp) { 799 psp->vj.vjs_packets = sc->sc_comp->sls_packets; 800 psp->vj.vjs_compressed = sc->sc_comp->sls_compressed; 801 psp->vj.vjs_searches = sc->sc_comp->sls_searches; 802 psp->vj.vjs_misses = sc->sc_comp->sls_misses; 803 psp->vj.vjs_uncompressedin = sc->sc_comp->sls_uncompressedin; 804 psp->vj.vjs_compressedin = sc->sc_comp->sls_compressedin; 805 psp->vj.vjs_errorin = sc->sc_comp->sls_errorin; 806 psp->vj.vjs_tossed = sc->sc_comp->sls_tossed; 807 } 808 #endif /* VJC */ 809 break; 810 811 #ifdef PPP_COMPRESS 812 case SIOCGPPPCSTATS: 813 pcp = &((struct ifpppcstatsreq *) data)->stats; 814 memset(pcp, 0, sizeof(*pcp)); 815 if (sc->sc_xc_state != NULL) 816 (*sc->sc_xcomp->comp_stat)(sc->sc_xc_state, &pcp->c); 817 if (sc->sc_rc_state != NULL) 818 (*sc->sc_rcomp->decomp_stat)(sc->sc_rc_state, &pcp->d); 819 break; 820 #endif /* PPP_COMPRESS */ 821 822 default: 823 if ((error = ifioctl_common(&sc->sc_if, cmd, data)) == ENETRESET) 824 error = 0; 825 break; 826 } 827 splx(s); 828 return (error); 829 } 830 831 /* 832 * Queue a packet. Start transmission if not active. 833 * Packet is placed in Information field of PPP frame. 834 */ 835 int 836 pppoutput(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst, 837 struct rtentry *rtp) 838 { 839 struct ppp_softc *sc = ifp->if_softc; 840 int protocol, address, control; 841 u_char *cp; 842 int s, error; 843 #ifdef INET 844 struct ip *ip; 845 #endif 846 struct ifqueue *ifq; 847 enum NPmode mode; 848 int len; 849 ALTQ_DECL(struct altq_pktattr pktattr;) 850 851 if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0 852 || ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) { 853 error = ENETDOWN; /* sort of */ 854 goto bad; 855 } 856 857 IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family, &pktattr); 858 859 /* 860 * Compute PPP header. 861 */ 862 m0->m_flags &= ~M_HIGHPRI; 863 switch (dst->sa_family) { 864 #ifdef INET 865 case AF_INET: 866 address = PPP_ALLSTATIONS; 867 control = PPP_UI; 868 protocol = PPP_IP; 869 mode = sc->sc_npmode[NP_IP]; 870 871 /* 872 * If this packet has the "low delay" bit set in the IP header, 873 * put it on the fastq instead. 874 */ 875 ip = mtod(m0, struct ip *); 876 if (ip->ip_tos & IPTOS_LOWDELAY) 877 m0->m_flags |= M_HIGHPRI; 878 break; 879 #endif 880 #ifdef INET6 881 case AF_INET6: 882 address = PPP_ALLSTATIONS; /*XXX*/ 883 control = PPP_UI; /*XXX*/ 884 protocol = PPP_IPV6; 885 mode = sc->sc_npmode[NP_IPV6]; 886 887 #if 0 /* XXX flowinfo/traffic class, maybe? */ 888 /* 889 * If this packet has the "low delay" bit set in the IP header, 890 * put it on the fastq instead. 891 */ 892 ip = mtod(m0, struct ip *); 893 if (ip->ip_tos & IPTOS_LOWDELAY) 894 m0->m_flags |= M_HIGHPRI; 895 #endif 896 break; 897 #endif 898 case AF_UNSPEC: 899 address = PPP_ADDRESS(dst->sa_data); 900 control = PPP_CONTROL(dst->sa_data); 901 protocol = PPP_PROTOCOL(dst->sa_data); 902 mode = NPMODE_PASS; 903 break; 904 default: 905 printf("%s: af%d not supported\n", ifp->if_xname, 906 dst->sa_family); 907 error = EAFNOSUPPORT; 908 goto bad; 909 } 910 911 /* 912 * Drop this packet, or return an error, if necessary. 913 */ 914 if (mode == NPMODE_ERROR) { 915 error = ENETDOWN; 916 goto bad; 917 } 918 if (mode == NPMODE_DROP) { 919 error = 0; 920 goto bad; 921 } 922 923 /* 924 * Add PPP header. 925 */ 926 M_PREPEND(m0, PPP_HDRLEN, M_DONTWAIT); 927 if (m0 == NULL) { 928 error = ENOBUFS; 929 goto bad; 930 } 931 932 cp = mtod(m0, u_char *); 933 *cp++ = address; 934 *cp++ = control; 935 *cp++ = protocol >> 8; 936 *cp++ = protocol & 0xff; 937 938 len = m_length(m0); 939 940 if (sc->sc_flags & SC_LOG_OUTPKT) { 941 printf("%s output: ", ifp->if_xname); 942 pppdumpm(m0); 943 } 944 945 if ((protocol & 0x8000) == 0) { 946 #ifdef PPP_FILTER 947 /* 948 * Apply the pass and active filters to the packet, 949 * but only if it is a data packet. 950 */ 951 if (sc->sc_pass_filt_out.bf_insns != 0 952 && bpf_filter(sc->sc_pass_filt_out.bf_insns, 953 (u_char *)m0, len, 0) == 0) { 954 error = 0; /* drop this packet */ 955 goto bad; 956 } 957 958 /* 959 * Update the time we sent the most recent packet. 960 */ 961 if (sc->sc_active_filt_out.bf_insns == 0 962 || bpf_filter(sc->sc_active_filt_out.bf_insns, 963 (u_char *)m0, len, 0)) 964 sc->sc_last_sent = time_second; 965 #else 966 /* 967 * Update the time we sent the most recent packet. 968 */ 969 sc->sc_last_sent = time_second; 970 #endif /* PPP_FILTER */ 971 } 972 973 /* 974 * See if bpf wants to look at the packet. 975 */ 976 bpf_mtap(&sc->sc_if, m0); 977 978 /* 979 * Put the packet on the appropriate queue. 980 */ 981 s = splnet(); 982 if (mode == NPMODE_QUEUE) { 983 /* XXX we should limit the number of packets on this queue */ 984 *sc->sc_npqtail = m0; 985 m0->m_nextpkt = NULL; 986 sc->sc_npqtail = &m0->m_nextpkt; 987 } else { 988 ifq = (m0->m_flags & M_HIGHPRI) ? &sc->sc_fastq : NULL; 989 if ((error = ifq_enqueue2(&sc->sc_if, ifq, m0 990 ALTQ_COMMA ALTQ_DECL(&pktattr))) != 0) { 991 splx(s); 992 sc->sc_if.if_oerrors++; 993 sc->sc_stats.ppp_oerrors++; 994 return (error); 995 } 996 ppp_restart(sc); 997 } 998 ifp->if_opackets++; 999 ifp->if_obytes += len; 1000 1001 splx(s); 1002 return (0); 1003 1004 bad: 1005 m_freem(m0); 1006 return (error); 1007 } 1008 1009 /* 1010 * After a change in the NPmode for some NP, move packets from the 1011 * npqueue to the send queue or the fast queue as appropriate. 1012 * Should be called at splnet, since we muck with the queues. 1013 */ 1014 static void 1015 ppp_requeue(struct ppp_softc *sc) 1016 { 1017 struct mbuf *m, **mpp; 1018 struct ifqueue *ifq; 1019 enum NPmode mode; 1020 int error; 1021 1022 for (mpp = &sc->sc_npqueue; (m = *mpp) != NULL; ) { 1023 switch (PPP_PROTOCOL(mtod(m, u_char *))) { 1024 case PPP_IP: 1025 mode = sc->sc_npmode[NP_IP]; 1026 break; 1027 case PPP_IPV6: 1028 mode = sc->sc_npmode[NP_IPV6]; 1029 break; 1030 default: 1031 mode = NPMODE_PASS; 1032 } 1033 1034 switch (mode) { 1035 case NPMODE_PASS: 1036 /* 1037 * This packet can now go on one of the queues to 1038 * be sent. 1039 */ 1040 *mpp = m->m_nextpkt; 1041 m->m_nextpkt = NULL; 1042 ifq = (m->m_flags & M_HIGHPRI) ? &sc->sc_fastq : NULL; 1043 if ((error = ifq_enqueue2(&sc->sc_if, ifq, m ALTQ_COMMA 1044 ALTQ_DECL(NULL))) != 0) { 1045 sc->sc_if.if_oerrors++; 1046 sc->sc_stats.ppp_oerrors++; 1047 } 1048 break; 1049 1050 case NPMODE_DROP: 1051 case NPMODE_ERROR: 1052 *mpp = m->m_nextpkt; 1053 m_freem(m); 1054 break; 1055 1056 case NPMODE_QUEUE: 1057 mpp = &m->m_nextpkt; 1058 break; 1059 } 1060 } 1061 sc->sc_npqtail = mpp; 1062 } 1063 1064 /* 1065 * Transmitter has finished outputting some stuff; 1066 * remember to call sc->sc_start later at splsoftnet. 1067 */ 1068 void 1069 ppp_restart(struct ppp_softc *sc) 1070 { 1071 int s = splhigh(); /* XXX IMP ME HARDER */ 1072 1073 sc->sc_flags &= ~SC_TBUSY; 1074 softint_schedule(sc->sc_si); 1075 splx(s); 1076 } 1077 1078 /* 1079 * Get a packet to send. This procedure is intended to be called at 1080 * splsoftnet, since it may involve time-consuming operations such as 1081 * applying VJ compression, packet compression, address/control and/or 1082 * protocol field compression to the packet. 1083 */ 1084 struct mbuf * 1085 ppp_dequeue(struct ppp_softc *sc) 1086 { 1087 struct mbuf *m, *mp; 1088 u_char *cp; 1089 int address, control, protocol; 1090 int s; 1091 1092 /* 1093 * Grab a packet to send: first try the fast queue, then the 1094 * normal queue. 1095 */ 1096 s = splnet(); 1097 if (sc->sc_nfastq < sc->sc_maxfastq) { 1098 IF_DEQUEUE(&sc->sc_fastq, m); 1099 if (m != NULL) 1100 sc->sc_nfastq++; 1101 else 1102 IFQ_DEQUEUE(&sc->sc_if.if_snd, m); 1103 } else { 1104 sc->sc_nfastq = 0; 1105 IFQ_DEQUEUE(&sc->sc_if.if_snd, m); 1106 if (m == NULL) { 1107 IF_DEQUEUE(&sc->sc_fastq, m); 1108 if (m != NULL) 1109 sc->sc_nfastq++; 1110 } 1111 } 1112 splx(s); 1113 1114 if (m == NULL) 1115 return NULL; 1116 1117 ++sc->sc_stats.ppp_opackets; 1118 1119 /* 1120 * Extract the ppp header of the new packet. 1121 * The ppp header will be in one mbuf. 1122 */ 1123 cp = mtod(m, u_char *); 1124 address = PPP_ADDRESS(cp); 1125 control = PPP_CONTROL(cp); 1126 protocol = PPP_PROTOCOL(cp); 1127 1128 switch (protocol) { 1129 case PPP_IP: 1130 #ifdef VJC 1131 /* 1132 * If the packet is a TCP/IP packet, see if we can compress it. 1133 */ 1134 if ((sc->sc_flags & SC_COMP_TCP) && sc->sc_comp != NULL) { 1135 struct ip *ip; 1136 int type; 1137 1138 mp = m; 1139 ip = (struct ip *) (cp + PPP_HDRLEN); 1140 if (mp->m_len <= PPP_HDRLEN) { 1141 mp = mp->m_next; 1142 if (mp == NULL) 1143 break; 1144 ip = mtod(mp, struct ip *); 1145 } 1146 /* 1147 * This code assumes the IP/TCP header is in one 1148 * non-shared mbuf 1149 */ 1150 if (ip->ip_p == IPPROTO_TCP) { 1151 type = sl_compress_tcp(mp, ip, sc->sc_comp, 1152 !(sc->sc_flags & SC_NO_TCP_CCID)); 1153 switch (type) { 1154 case TYPE_UNCOMPRESSED_TCP: 1155 protocol = PPP_VJC_UNCOMP; 1156 break; 1157 case TYPE_COMPRESSED_TCP: 1158 protocol = PPP_VJC_COMP; 1159 cp = mtod(m, u_char *); 1160 cp[0] = address; /* Header has moved */ 1161 cp[1] = control; 1162 cp[2] = 0; 1163 break; 1164 } 1165 /* Update protocol in PPP header */ 1166 cp[3] = protocol; 1167 } 1168 } 1169 #endif /* VJC */ 1170 break; 1171 1172 #ifdef PPP_COMPRESS 1173 case PPP_CCP: 1174 ppp_ccp(sc, m, 0); 1175 break; 1176 #endif /* PPP_COMPRESS */ 1177 } 1178 1179 #ifdef PPP_COMPRESS 1180 if (protocol != PPP_LCP && protocol != PPP_CCP 1181 && sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) { 1182 struct mbuf *mcomp = NULL; 1183 int slen; 1184 1185 slen = 0; 1186 for (mp = m; mp != NULL; mp = mp->m_next) 1187 slen += mp->m_len; 1188 (*sc->sc_xcomp->compress) 1189 (sc->sc_xc_state, &mcomp, m, slen, sc->sc_if.if_mtu + PPP_HDRLEN); 1190 if (mcomp != NULL) { 1191 if (sc->sc_flags & SC_CCP_UP) { 1192 /* 1193 * Send the compressed packet instead of the 1194 * original. 1195 */ 1196 m_freem(m); 1197 m = mcomp; 1198 cp = mtod(m, u_char *); 1199 protocol = cp[3]; 1200 } else { 1201 /* 1202 * Can't transmit compressed packets until CCP 1203 * is up. 1204 */ 1205 m_freem(mcomp); 1206 } 1207 } 1208 } 1209 #endif /* PPP_COMPRESS */ 1210 1211 /* 1212 * Compress the address/control and protocol, if possible. 1213 */ 1214 if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS && 1215 control == PPP_UI && protocol != PPP_ALLSTATIONS && 1216 protocol != PPP_LCP) { 1217 /* can compress address/control */ 1218 m->m_data += 2; 1219 m->m_len -= 2; 1220 } 1221 if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) { 1222 /* can compress protocol */ 1223 if (mtod(m, u_char *) == cp) { 1224 cp[2] = cp[1]; /* move address/control up */ 1225 cp[1] = cp[0]; 1226 } 1227 ++m->m_data; 1228 --m->m_len; 1229 } 1230 1231 return m; 1232 } 1233 1234 /* 1235 * Software interrupt routine, called at splsoftnet. 1236 */ 1237 static void 1238 pppintr(void *arg) 1239 { 1240 struct ppp_softc *sc = arg; 1241 struct mbuf *m; 1242 int s; 1243 1244 mutex_enter(softnet_lock); 1245 if (!(sc->sc_flags & SC_TBUSY) 1246 && (IFQ_IS_EMPTY(&sc->sc_if.if_snd) == 0 || sc->sc_fastq.ifq_head 1247 || sc->sc_outm)) { 1248 s = splhigh(); /* XXX IMP ME HARDER */ 1249 sc->sc_flags |= SC_TBUSY; 1250 splx(s); 1251 (*sc->sc_start)(sc); 1252 } 1253 for (;;) { 1254 s = splnet(); 1255 IF_DEQUEUE(&sc->sc_rawq, m); 1256 splx(s); 1257 if (m == NULL) 1258 break; 1259 ppp_inproc(sc, m); 1260 } 1261 mutex_exit(softnet_lock); 1262 } 1263 1264 #ifdef PPP_COMPRESS 1265 /* 1266 * Handle a CCP packet. `rcvd' is 1 if the packet was received, 1267 * 0 if it is about to be transmitted. 1268 */ 1269 static void 1270 ppp_ccp(struct ppp_softc *sc, struct mbuf *m, int rcvd) 1271 { 1272 u_char *dp, *ep; 1273 struct mbuf *mp; 1274 int slen, s; 1275 1276 /* 1277 * Get a pointer to the data after the PPP header. 1278 */ 1279 if (m->m_len <= PPP_HDRLEN) { 1280 mp = m->m_next; 1281 if (mp == NULL) 1282 return; 1283 dp = mtod(mp, u_char *); 1284 } else { 1285 mp = m; 1286 dp = mtod(mp, u_char *) + PPP_HDRLEN; 1287 } 1288 1289 ep = mtod(mp, u_char *) + mp->m_len; 1290 if (dp + CCP_HDRLEN > ep) 1291 return; 1292 slen = CCP_LENGTH(dp); 1293 if (dp + slen > ep) { 1294 if (sc->sc_flags & SC_DEBUG) 1295 printf("if_ppp/ccp: not enough data in mbuf (%p+%x > %p+%x)\n", 1296 dp, slen, mtod(mp, u_char *), mp->m_len); 1297 return; 1298 } 1299 1300 switch (CCP_CODE(dp)) { 1301 case CCP_CONFREQ: 1302 case CCP_TERMREQ: 1303 case CCP_TERMACK: 1304 /* CCP must be going down - disable compression */ 1305 if (sc->sc_flags & SC_CCP_UP) { 1306 s = splhigh(); /* XXX IMP ME HARDER */ 1307 sc->sc_flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN); 1308 splx(s); 1309 } 1310 break; 1311 1312 case CCP_CONFACK: 1313 if (sc->sc_flags & SC_CCP_OPEN && !(sc->sc_flags & SC_CCP_UP) 1314 && slen >= CCP_HDRLEN + CCP_OPT_MINLEN 1315 && slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) { 1316 if (!rcvd) { 1317 /* We're agreeing to send compressed packets. */ 1318 if (sc->sc_xc_state != NULL 1319 && (*sc->sc_xcomp->comp_init) 1320 (sc->sc_xc_state, dp + CCP_HDRLEN, 1321 slen - CCP_HDRLEN, sc->sc_unit, 0, 1322 sc->sc_flags & SC_DEBUG)) { 1323 s = splhigh(); /* XXX IMP ME HARDER */ 1324 sc->sc_flags |= SC_COMP_RUN; 1325 splx(s); 1326 } 1327 } else { 1328 /* 1329 * Peer is agreeing to send compressed 1330 * packets. 1331 */ 1332 if (sc->sc_rc_state != NULL 1333 && (*sc->sc_rcomp->decomp_init) 1334 (sc->sc_rc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, 1335 sc->sc_unit, 0, sc->sc_mru, 1336 sc->sc_flags & SC_DEBUG)) { 1337 s = splhigh(); /* XXX IMP ME HARDER */ 1338 sc->sc_flags |= SC_DECOMP_RUN; 1339 sc->sc_flags &= ~(SC_DC_ERROR | SC_DC_FERROR); 1340 splx(s); 1341 } 1342 } 1343 } 1344 break; 1345 1346 case CCP_RESETACK: 1347 if (sc->sc_flags & SC_CCP_UP) { 1348 if (!rcvd) { 1349 if (sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) 1350 (*sc->sc_xcomp->comp_reset)(sc->sc_xc_state); 1351 } else { 1352 if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) { 1353 (*sc->sc_rcomp->decomp_reset)(sc->sc_rc_state); 1354 s = splhigh(); /* XXX IMP ME HARDER */ 1355 sc->sc_flags &= ~SC_DC_ERROR; 1356 splx(s); 1357 } 1358 } 1359 } 1360 break; 1361 } 1362 } 1363 1364 /* 1365 * CCP is down; free (de)compressor state if necessary. 1366 */ 1367 static void 1368 ppp_ccp_closed(struct ppp_softc *sc) 1369 { 1370 if (sc->sc_xc_state) { 1371 (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); 1372 ppp_compressor_rele(sc->sc_xcomp); 1373 sc->sc_xc_state = NULL; 1374 } 1375 if (sc->sc_rc_state) { 1376 (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); 1377 ppp_compressor_rele(sc->sc_rcomp); 1378 sc->sc_rc_state = NULL; 1379 } 1380 } 1381 #endif /* PPP_COMPRESS */ 1382 1383 /* 1384 * PPP packet input routine. 1385 * The caller has checked and removed the FCS and has inserted 1386 * the address/control bytes and the protocol high byte if they 1387 * were omitted. 1388 */ 1389 void 1390 ppppktin(struct ppp_softc *sc, struct mbuf *m, int lost) 1391 { 1392 int s = splhigh(); /* XXX IMP ME HARDER */ 1393 1394 if (lost) 1395 m->m_flags |= M_ERRMARK; 1396 IF_ENQUEUE(&sc->sc_rawq, m); 1397 softint_schedule(sc->sc_si); 1398 splx(s); 1399 } 1400 1401 /* 1402 * Process a received PPP packet, doing decompression as necessary. 1403 * Should be called at splsoftnet. 1404 */ 1405 #define COMPTYPE(proto) ((proto) == PPP_VJC_COMP ? TYPE_COMPRESSED_TCP: \ 1406 TYPE_UNCOMPRESSED_TCP) 1407 1408 static void 1409 ppp_inproc(struct ppp_softc *sc, struct mbuf *m) 1410 { 1411 struct ifnet *ifp = &sc->sc_if; 1412 pktqueue_t *pktq = NULL; 1413 struct ifqueue *inq = NULL; 1414 int s, ilen, proto, rv; 1415 u_char *cp, adrs, ctrl; 1416 struct mbuf *mp, *dmp = NULL; 1417 #ifdef VJC 1418 int xlen; 1419 u_char *iphdr; 1420 u_int hlen; 1421 #endif 1422 1423 sc->sc_stats.ppp_ipackets++; 1424 1425 if (sc->sc_flags & SC_LOG_INPKT) { 1426 ilen = 0; 1427 for (mp = m; mp != NULL; mp = mp->m_next) 1428 ilen += mp->m_len; 1429 printf("%s: got %d bytes\n", ifp->if_xname, ilen); 1430 pppdumpm(m); 1431 } 1432 1433 cp = mtod(m, u_char *); 1434 adrs = PPP_ADDRESS(cp); 1435 ctrl = PPP_CONTROL(cp); 1436 proto = PPP_PROTOCOL(cp); 1437 1438 if (m->m_flags & M_ERRMARK) { 1439 m->m_flags &= ~M_ERRMARK; 1440 s = splhigh(); /* XXX IMP ME HARDER */ 1441 sc->sc_flags |= SC_VJ_RESET; 1442 splx(s); 1443 } 1444 1445 #ifdef PPP_COMPRESS 1446 /* 1447 * Decompress this packet if necessary, update the receiver's 1448 * dictionary, or take appropriate action on a CCP packet. 1449 */ 1450 if (proto == PPP_COMP && sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN) 1451 && !(sc->sc_flags & SC_DC_ERROR) && !(sc->sc_flags & SC_DC_FERROR)) { 1452 /* Decompress this packet */ 1453 rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp); 1454 if (rv == DECOMP_OK) { 1455 m_freem(m); 1456 if (dmp == NULL) { 1457 /* 1458 * No error, but no decompressed packet 1459 * produced 1460 */ 1461 return; 1462 } 1463 m = dmp; 1464 cp = mtod(m, u_char *); 1465 proto = PPP_PROTOCOL(cp); 1466 1467 } else { 1468 /* 1469 * An error has occurred in decompression. 1470 * Pass the compressed packet up to pppd, which may 1471 * take CCP down or issue a Reset-Req. 1472 */ 1473 if (sc->sc_flags & SC_DEBUG) 1474 printf("%s: decompress failed %d\n", 1475 ifp->if_xname, rv); 1476 s = splhigh(); /* XXX IMP ME HARDER */ 1477 sc->sc_flags |= SC_VJ_RESET; 1478 if (rv == DECOMP_ERROR) 1479 sc->sc_flags |= SC_DC_ERROR; 1480 else 1481 sc->sc_flags |= SC_DC_FERROR; 1482 splx(s); 1483 } 1484 1485 } else { 1486 if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) 1487 (*sc->sc_rcomp->incomp)(sc->sc_rc_state, m); 1488 if (proto == PPP_CCP) 1489 ppp_ccp(sc, m, 1); 1490 } 1491 #endif 1492 1493 ilen = 0; 1494 for (mp = m; mp != NULL; mp = mp->m_next) 1495 ilen += mp->m_len; 1496 1497 #ifdef VJC 1498 if (sc->sc_flags & SC_VJ_RESET) { 1499 /* 1500 * If we've missed a packet, we must toss subsequent compressed 1501 * packets which don't have an explicit connection ID. 1502 */ 1503 if (sc->sc_comp) 1504 sl_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp); 1505 s = splhigh(); /* XXX IMP ME HARDER */ 1506 sc->sc_flags &= ~SC_VJ_RESET; 1507 splx(s); 1508 } 1509 1510 /* 1511 * See if we have a VJ-compressed packet to uncompress. 1512 */ 1513 if (proto == PPP_VJC_COMP) { 1514 if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) 1515 goto bad; 1516 1517 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, 1518 m->m_len - PPP_HDRLEN, ilen - PPP_HDRLEN, 1519 TYPE_COMPRESSED_TCP, sc->sc_comp, &iphdr, &hlen); 1520 1521 if (xlen <= 0) { 1522 if (sc->sc_flags & SC_DEBUG) 1523 printf("%s: VJ uncompress failed on type comp\n", 1524 ifp->if_xname); 1525 goto bad; 1526 } 1527 1528 /* Copy the PPP and IP headers into a new mbuf. */ 1529 MGETHDR(mp, M_DONTWAIT, MT_DATA); 1530 if (mp == NULL) 1531 goto bad; 1532 mp->m_len = 0; 1533 mp->m_next = NULL; 1534 if (hlen + PPP_HDRLEN > MHLEN) { 1535 MCLGET(mp, M_DONTWAIT); 1536 if (M_TRAILINGSPACE(mp) < hlen + PPP_HDRLEN) { 1537 /* Lose if big headers and no clusters */ 1538 m_freem(mp); 1539 goto bad; 1540 } 1541 } 1542 cp = mtod(mp, u_char *); 1543 cp[0] = adrs; 1544 cp[1] = ctrl; 1545 cp[2] = 0; 1546 cp[3] = PPP_IP; 1547 proto = PPP_IP; 1548 bcopy(iphdr, cp + PPP_HDRLEN, hlen); 1549 mp->m_len = hlen + PPP_HDRLEN; 1550 1551 /* 1552 * Trim the PPP and VJ headers off the old mbuf 1553 * and stick the new and old mbufs together. 1554 */ 1555 m->m_data += PPP_HDRLEN + xlen; 1556 m->m_len -= PPP_HDRLEN + xlen; 1557 if (m->m_len <= M_TRAILINGSPACE(mp)) { 1558 bcopy(mtod(m, u_char *), 1559 mtod(mp, u_char *) + mp->m_len, m->m_len); 1560 mp->m_len += m->m_len; 1561 MFREE(m, mp->m_next); 1562 } else 1563 mp->m_next = m; 1564 m = mp; 1565 ilen += hlen - xlen; 1566 1567 } else if (proto == PPP_VJC_UNCOMP) { 1568 if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) 1569 goto bad; 1570 1571 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, 1572 m->m_len - PPP_HDRLEN, ilen - PPP_HDRLEN, 1573 TYPE_UNCOMPRESSED_TCP, sc->sc_comp, &iphdr, &hlen); 1574 1575 if (xlen < 0) { 1576 if (sc->sc_flags & SC_DEBUG) 1577 printf("%s: VJ uncompress failed on type uncomp\n", 1578 ifp->if_xname); 1579 goto bad; 1580 } 1581 1582 proto = PPP_IP; 1583 cp[3] = PPP_IP; 1584 } 1585 #endif /* VJC */ 1586 1587 /* 1588 * If the packet will fit in a header mbuf, don't waste a 1589 * whole cluster on it. 1590 */ 1591 if (ilen <= MHLEN && M_IS_CLUSTER(m)) { 1592 MGETHDR(mp, M_DONTWAIT, MT_DATA); 1593 if (mp != NULL) { 1594 m_copydata(m, 0, ilen, mtod(mp, void *)); 1595 m_freem(m); 1596 m = mp; 1597 m->m_len = ilen; 1598 } 1599 } 1600 m->m_pkthdr.len = ilen; 1601 m->m_pkthdr.rcvif = ifp; 1602 1603 if ((proto & 0x8000) == 0) { 1604 #ifdef PPP_FILTER 1605 /* 1606 * See whether we want to pass this packet, and 1607 * if it counts as link activity. 1608 */ 1609 if (sc->sc_pass_filt_in.bf_insns != 0 1610 && bpf_filter(sc->sc_pass_filt_in.bf_insns, 1611 (u_char *)m, ilen, 0) == 0) { 1612 /* drop this packet */ 1613 m_freem(m); 1614 return; 1615 } 1616 if (sc->sc_active_filt_in.bf_insns == 0 1617 || bpf_filter(sc->sc_active_filt_in.bf_insns, 1618 (u_char *)m, ilen, 0)) 1619 sc->sc_last_recv = time_second; 1620 #else 1621 /* 1622 * Record the time that we received this packet. 1623 */ 1624 sc->sc_last_recv = time_second; 1625 #endif /* PPP_FILTER */ 1626 } 1627 1628 /* See if bpf wants to look at the packet. */ 1629 bpf_mtap(&sc->sc_if, m); 1630 1631 switch (proto) { 1632 #ifdef INET 1633 case PPP_IP: 1634 /* 1635 * IP packet - take off the ppp header and pass it up to IP. 1636 */ 1637 if ((ifp->if_flags & IFF_UP) == 0 1638 || sc->sc_npmode[NP_IP] != NPMODE_PASS) { 1639 /* Interface is down - drop the packet. */ 1640 m_freem(m); 1641 return; 1642 } 1643 m->m_pkthdr.len -= PPP_HDRLEN; 1644 m->m_data += PPP_HDRLEN; 1645 m->m_len -= PPP_HDRLEN; 1646 #ifdef GATEWAY 1647 if (ipflow_fastforward(m)) 1648 return; 1649 #endif 1650 pktq = ip_pktq; 1651 break; 1652 #endif 1653 1654 #ifdef INET6 1655 case PPP_IPV6: 1656 /* 1657 * IPv6 packet - take off the ppp header and pass it up to 1658 * IPv6. 1659 */ 1660 if ((ifp->if_flags & IFF_UP) == 0 1661 || sc->sc_npmode[NP_IPV6] != NPMODE_PASS) { 1662 /* interface is down - drop the packet. */ 1663 m_freem(m); 1664 return; 1665 } 1666 m->m_pkthdr.len -= PPP_HDRLEN; 1667 m->m_data += PPP_HDRLEN; 1668 m->m_len -= PPP_HDRLEN; 1669 #ifdef GATEWAY 1670 if (ip6flow_fastforward(&m)) 1671 return; 1672 #endif 1673 pktq = ip6_pktq; 1674 break; 1675 #endif 1676 1677 default: 1678 /* 1679 * Some other protocol - place on input queue for read(). 1680 */ 1681 inq = &sc->sc_inq; 1682 pktq = NULL; 1683 break; 1684 } 1685 1686 /* 1687 * Put the packet on the appropriate input queue. 1688 */ 1689 s = splnet(); 1690 1691 /* pktq: inet or inet6 cases */ 1692 if (__predict_true(pktq)) { 1693 if (__predict_false(!pktq_enqueue(pktq, m, 0))) { 1694 ifp->if_iqdrops++; 1695 goto bad; 1696 } 1697 ifp->if_ipackets++; 1698 ifp->if_ibytes += ilen; 1699 splx(s); 1700 return; 1701 } 1702 1703 /* ifq: other protocol cases */ 1704 if (!inq) { 1705 goto bad; 1706 } 1707 if (IF_QFULL(inq)) { 1708 IF_DROP(inq); 1709 splx(s); 1710 if (sc->sc_flags & SC_DEBUG) 1711 printf("%s: input queue full\n", ifp->if_xname); 1712 ifp->if_iqdrops++; 1713 goto bad; 1714 } 1715 IF_ENQUEUE(inq, m); 1716 splx(s); 1717 ifp->if_ipackets++; 1718 ifp->if_ibytes += ilen; 1719 1720 (*sc->sc_ctlp)(sc); 1721 1722 return; 1723 1724 bad: 1725 m_freem(m); 1726 sc->sc_if.if_ierrors++; 1727 sc->sc_stats.ppp_ierrors++; 1728 } 1729 1730 #define MAX_DUMP_BYTES 128 1731 1732 static void 1733 pppdumpm(struct mbuf *m0) 1734 { 1735 char buf[3*MAX_DUMP_BYTES+4]; 1736 char *bp = buf; 1737 struct mbuf *m; 1738 1739 for (m = m0; m; m = m->m_next) { 1740 int l = m->m_len; 1741 u_char *rptr = (u_char *)m->m_data; 1742 1743 while (l--) { 1744 if (bp > buf + sizeof(buf) - 4) 1745 goto done; 1746 /* Convert byte to ascii hex */ 1747 *bp++ = hexdigits[*rptr >> 4]; 1748 *bp++ = hexdigits[*rptr++ & 0xf]; 1749 } 1750 1751 if (m->m_next) { 1752 if (bp > buf + sizeof(buf) - 3) 1753 goto done; 1754 *bp++ = '|'; 1755 } else 1756 *bp++ = ' '; 1757 } 1758 done: 1759 if (m) 1760 *bp++ = '>'; 1761 *bp = 0; 1762 printf("%s\n", buf); 1763 } 1764 1765 #ifdef ALTQ 1766 /* 1767 * A wrapper to transmit a packet from if_start since ALTQ uses 1768 * if_start to send a packet. 1769 */ 1770 static void 1771 ppp_ifstart(struct ifnet *ifp) 1772 { 1773 struct ppp_softc *sc; 1774 1775 sc = ifp->if_softc; 1776 (*sc->sc_start)(sc); 1777 } 1778 #endif 1779 1780 static const struct ppp_known_compressor { 1781 uint8_t code; 1782 const char *module; 1783 } ppp_known_compressors[] = { 1784 { CI_DEFLATE, "ppp_deflate" }, 1785 { CI_DEFLATE_DRAFT, "ppp_deflate" }, 1786 { CI_BSD_COMPRESS, "ppp_bsdcomp" }, 1787 { CI_MPPE, "ppp_mppe" }, 1788 { 0, NULL } 1789 }; 1790 1791 static int 1792 ppp_compressor_init(void) 1793 { 1794 1795 mutex_init(&ppp_compressors_mtx, MUTEX_DEFAULT, IPL_NONE); 1796 return 0; 1797 } 1798 1799 static void 1800 ppp_compressor_rele(struct compressor *cp) 1801 { 1802 1803 mutex_enter(&ppp_compressors_mtx); 1804 --cp->comp_refcnt; 1805 mutex_exit(&ppp_compressors_mtx); 1806 } 1807 1808 static struct compressor * 1809 ppp_get_compressor_noload(uint8_t ci, bool hold) 1810 { 1811 struct compressor *cp; 1812 1813 KASSERT(mutex_owned(&ppp_compressors_mtx)); 1814 LIST_FOREACH(cp, &ppp_compressors, comp_list) { 1815 if (cp->compress_proto == ci) { 1816 if (hold) 1817 ++cp->comp_refcnt; 1818 return cp; 1819 } 1820 } 1821 1822 return NULL; 1823 } 1824 1825 static struct compressor * 1826 ppp_get_compressor(uint8_t ci) 1827 { 1828 struct compressor *cp = NULL; 1829 const struct ppp_known_compressor *pkc; 1830 1831 mutex_enter(&ppp_compressors_mtx); 1832 cp = ppp_get_compressor_noload(ci, true); 1833 mutex_exit(&ppp_compressors_mtx); 1834 if (cp != NULL) 1835 return cp; 1836 1837 kernconfig_lock(); 1838 mutex_enter(&ppp_compressors_mtx); 1839 cp = ppp_get_compressor_noload(ci, true); 1840 mutex_exit(&ppp_compressors_mtx); 1841 if (cp == NULL) { 1842 /* Not found, so try to autoload a module */ 1843 for (pkc = ppp_known_compressors; pkc->module != NULL; pkc++) { 1844 if (pkc->code == ci) { 1845 if (module_autoload(pkc->module, 1846 MODULE_CLASS_MISC) != 0) 1847 break; 1848 mutex_enter(&ppp_compressors_mtx); 1849 cp = ppp_get_compressor_noload(ci, true); 1850 mutex_exit(&ppp_compressors_mtx); 1851 break; 1852 } 1853 } 1854 } 1855 kernconfig_unlock(); 1856 1857 return cp; 1858 } 1859 1860 int 1861 ppp_register_compressor(struct compressor *pc, size_t ncomp) 1862 { 1863 int error = 0; 1864 size_t i; 1865 1866 RUN_ONCE(&ppp_compressor_mtx_init, ppp_compressor_init); 1867 1868 mutex_enter(&ppp_compressors_mtx); 1869 for (i = 0; i < ncomp; i++) { 1870 if (ppp_get_compressor_noload(pc[i].compress_proto, 1871 false) != NULL) 1872 error = EEXIST; 1873 } 1874 if (!error) { 1875 for (i = 0; i < ncomp; i++) { 1876 pc[i].comp_refcnt = 0; 1877 LIST_INSERT_HEAD(&ppp_compressors, &pc[i], comp_list); 1878 } 1879 } 1880 mutex_exit(&ppp_compressors_mtx); 1881 1882 return error; 1883 } 1884 1885 int 1886 ppp_unregister_compressor(struct compressor *pc, size_t ncomp) 1887 { 1888 int error = 0; 1889 size_t i; 1890 1891 mutex_enter(&ppp_compressors_mtx); 1892 for (i = 0; i < ncomp; i++) { 1893 if (ppp_get_compressor_noload(pc[i].compress_proto, 1894 false) != &pc[i]) 1895 error = ENOENT; 1896 else if (pc[i].comp_refcnt != 0) 1897 error = EBUSY; 1898 } 1899 if (!error) { 1900 for (i = 0; i < ncomp; i++) { 1901 LIST_REMOVE(&pc[i], comp_list); 1902 } 1903 } 1904 mutex_exit(&ppp_compressors_mtx); 1905 1906 return error; 1907 } 1908