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