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