1 /* $NetBSD: if_ppp.c,v 1.119 2007/10/19 12:16:44 ad 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.119 2007/10/19 12:16:44 ad 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 131 #include <net/if.h> 132 #include <net/if_types.h> 133 #include <net/netisr.h> 134 #include <net/route.h> 135 #ifdef PPP_FILTER 136 #include <net/bpf.h> 137 #endif 138 139 #include <netinet/in.h> 140 #include <netinet/in_systm.h> 141 #include <netinet/in_var.h> 142 #ifdef INET 143 #include <netinet/ip.h> 144 #endif 145 146 #include "bpfilter.h" 147 #if NBPFILTER > 0 148 #include <net/bpf.h> 149 #endif 150 151 #if defined(PPP_FILTER) || NBPFILTER > 0 152 #include <net/slip.h> 153 #endif 154 155 #ifdef VJC 156 #include <net/slcompress.h> 157 #endif 158 159 #include <net/ppp_defs.h> 160 #include <net/if_ppp.h> 161 #include <net/if_pppvar.h> 162 #include <sys/cpu.h> 163 164 #ifdef PPP_COMPRESS 165 #define PACKETPTR struct mbuf * 166 #include <net/ppp-comp.h> 167 #endif 168 169 static int pppsioctl(struct ifnet *, u_long, void *); 170 static void ppp_requeue(struct ppp_softc *); 171 static void ppp_ccp(struct ppp_softc *, struct mbuf *m, int rcvd); 172 static void ppp_ccp_closed(struct ppp_softc *); 173 static void ppp_inproc(struct ppp_softc *, struct mbuf *); 174 static void pppdumpm(struct mbuf *m0); 175 #ifdef ALTQ 176 static void ppp_ifstart(struct ifnet *ifp); 177 #endif 178 179 static void pppintr(void *); 180 181 /* 182 * Some useful mbuf macros not in mbuf.h. 183 */ 184 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT) 185 186 #define M_DATASTART(m) \ 187 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \ 188 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat) 189 190 #define M_DATASIZE(m) \ 191 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \ 192 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN) 193 194 /* 195 * We define two link layer specific mbuf flags, to mark high-priority 196 * packets for output, and received packets following lost/corrupted 197 * packets. 198 */ 199 #define M_HIGHPRI M_LINK0 /* output packet for sc_fastq */ 200 #define M_ERRMARK M_LINK1 /* rx packet following lost/corrupted pkt */ 201 202 static int ppp_clone_create(struct if_clone *, int); 203 static int ppp_clone_destroy(struct ifnet *); 204 205 static struct ppp_softc *ppp_create(const char *, int); 206 207 static LIST_HEAD(, ppp_softc) ppp_softc_list; 208 209 struct if_clone ppp_cloner = 210 IF_CLONE_INITIALIZER("ppp", ppp_clone_create, ppp_clone_destroy); 211 212 static struct simplelock ppp_list_mutex = SIMPLELOCK_INITIALIZER; 213 214 #ifdef PPP_COMPRESS 215 /* 216 * List of compressors we know about. 217 * We leave some space so maybe we can modload compressors. 218 */ 219 220 extern struct compressor ppp_bsd_compress; 221 extern struct compressor ppp_deflate, ppp_deflate_draft; 222 223 struct compressor *ppp_compressors[PPP_COMPRESSORS_MAX] = { 224 #if DO_BSD_COMPRESS && defined(PPP_BSDCOMP) 225 &ppp_bsd_compress, 226 #endif 227 #if DO_DEFLATE && defined(PPP_DEFLATE) 228 &ppp_deflate, 229 &ppp_deflate_draft, 230 #endif 231 NULL 232 }; 233 #endif /* PPP_COMPRESS */ 234 235 236 /* 237 * Called from boot code to establish ppp interfaces. 238 */ 239 void 240 pppattach(void) 241 { 242 extern struct linesw ppp_disc; 243 244 if (ttyldisc_attach(&ppp_disc) != 0) 245 panic("pppattach"); 246 LIST_INIT(&ppp_softc_list); 247 if_clone_attach(&ppp_cloner); 248 } 249 250 static struct ppp_softc * 251 ppp_create(const char *name, int unit) 252 { 253 struct ppp_softc *sc, *sci, *scl = NULL; 254 255 MALLOC(sc, struct ppp_softc *, sizeof(*sc), M_DEVBUF, M_WAIT|M_ZERO); 256 257 simple_lock(&ppp_list_mutex); 258 if (unit == -1) { 259 int i = 0; 260 LIST_FOREACH(sci, &ppp_softc_list, sc_iflist) { 261 scl = sci; 262 if (i < sci->sc_unit) { 263 unit = i; 264 break; 265 } else { 266 #ifdef DIAGNOSTIC 267 KASSERT(i == sci->sc_unit); 268 #endif 269 i++; 270 } 271 } 272 if (unit == -1) 273 unit = i; 274 } else { 275 LIST_FOREACH(sci, &ppp_softc_list, sc_iflist) { 276 scl = sci; 277 if (unit < sci->sc_unit) 278 break; 279 else if (unit == sci->sc_unit) { 280 FREE(sc, M_DEVBUF); 281 return NULL; 282 } 283 } 284 } 285 286 if (sci != NULL) 287 LIST_INSERT_BEFORE(sci, sc, sc_iflist); 288 else if (scl != NULL) 289 LIST_INSERT_AFTER(scl, sc, sc_iflist); 290 else 291 LIST_INSERT_HEAD(&ppp_softc_list, sc, sc_iflist); 292 293 simple_unlock(&ppp_list_mutex); 294 295 (void)snprintf(sc->sc_if.if_xname, sizeof(sc->sc_if.if_xname), "%s%d", 296 name, sc->sc_unit = unit); 297 callout_init(&sc->sc_timo_ch, 0); 298 sc->sc_if.if_softc = sc; 299 sc->sc_if.if_mtu = PPP_MTU; 300 sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 301 sc->sc_if.if_type = IFT_PPP; 302 sc->sc_if.if_hdrlen = PPP_HDRLEN; 303 sc->sc_if.if_dlt = DLT_NULL; 304 sc->sc_if.if_ioctl = pppsioctl; 305 sc->sc_if.if_output = pppoutput; 306 #ifdef ALTQ 307 sc->sc_if.if_start = ppp_ifstart; 308 #endif 309 IFQ_SET_MAXLEN(&sc->sc_if.if_snd, IFQ_MAXLEN); 310 sc->sc_inq.ifq_maxlen = IFQ_MAXLEN; 311 sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN; 312 sc->sc_rawq.ifq_maxlen = IFQ_MAXLEN; 313 /* Ratio of 1:2 packets between the regular and the fast queue */ 314 sc->sc_maxfastq = 2; 315 IFQ_SET_READY(&sc->sc_if.if_snd); 316 if_attach(&sc->sc_if); 317 if_alloc_sadl(&sc->sc_if); 318 #if NBPFILTER > 0 319 bpfattach(&sc->sc_if, DLT_NULL, 0); 320 #endif 321 return sc; 322 } 323 324 static int 325 ppp_clone_create(struct if_clone *ifc, int unit) 326 { 327 return ppp_create(ifc->ifc_name, unit) == NULL ? EEXIST : 0; 328 } 329 330 static int 331 ppp_clone_destroy(struct ifnet *ifp) 332 { 333 struct ppp_softc *sc = (struct ppp_softc *)ifp->if_softc; 334 335 if (sc->sc_devp != NULL) 336 return EBUSY; /* Not removing it */ 337 338 simple_lock(&ppp_list_mutex); 339 LIST_REMOVE(sc, sc_iflist); 340 simple_unlock(&ppp_list_mutex); 341 342 #if NBPFILTER > 0 343 bpfdetach(ifp); 344 #endif 345 if_detach(ifp); 346 347 FREE(sc, M_DEVBUF); 348 return 0; 349 } 350 351 /* 352 * Allocate a ppp interface unit and initialize it. 353 */ 354 struct ppp_softc * 355 pppalloc(pid_t pid) 356 { 357 struct ppp_softc *sc = NULL, *scf; 358 int i; 359 360 simple_lock(&ppp_list_mutex); 361 for (scf = LIST_FIRST(&ppp_softc_list); scf != NULL; 362 scf = LIST_NEXT(scf, sc_iflist)) { 363 if (scf->sc_xfer == pid) { 364 scf->sc_xfer = 0; 365 simple_unlock(&ppp_list_mutex); 366 return scf; 367 } 368 if (scf->sc_devp == NULL && sc == NULL) 369 sc = scf; 370 } 371 simple_unlock(&ppp_list_mutex); 372 373 if (sc == NULL) 374 sc = ppp_create(ppp_cloner.ifc_name, -1); 375 376 sc->sc_si = softint_establish(SOFTINT_NET, pppintr, sc); 377 if (sc->sc_si == NULL) { 378 printf("%s: unable to establish softintr\n", sc->sc_if.if_xname); 379 return (NULL); 380 } 381 sc->sc_flags = 0; 382 sc->sc_mru = PPP_MRU; 383 sc->sc_relinq = NULL; 384 (void)memset(&sc->sc_stats, 0, sizeof(sc->sc_stats)); 385 #ifdef VJC 386 MALLOC(sc->sc_comp, struct slcompress *, sizeof(struct slcompress), 387 M_DEVBUF, M_NOWAIT); 388 if (sc->sc_comp) 389 sl_compress_init(sc->sc_comp); 390 #endif 391 #ifdef PPP_COMPRESS 392 sc->sc_xc_state = NULL; 393 sc->sc_rc_state = NULL; 394 #endif /* PPP_COMPRESS */ 395 for (i = 0; i < NUM_NP; ++i) 396 sc->sc_npmode[i] = NPMODE_ERROR; 397 sc->sc_npqueue = NULL; 398 sc->sc_npqtail = &sc->sc_npqueue; 399 sc->sc_last_sent = sc->sc_last_recv = time_second; 400 401 return sc; 402 } 403 404 /* 405 * Deallocate a ppp unit. Must be called at splsoftnet or higher. 406 */ 407 void 408 pppdealloc(struct ppp_softc *sc) 409 { 410 struct mbuf *m; 411 412 softint_disestablish(sc->sc_si); 413 if_down(&sc->sc_if); 414 sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING); 415 sc->sc_devp = NULL; 416 sc->sc_xfer = 0; 417 for (;;) { 418 IF_DEQUEUE(&sc->sc_rawq, m); 419 if (m == NULL) 420 break; 421 m_freem(m); 422 } 423 for (;;) { 424 IF_DEQUEUE(&sc->sc_inq, m); 425 if (m == NULL) 426 break; 427 m_freem(m); 428 } 429 for (;;) { 430 IF_DEQUEUE(&sc->sc_fastq, m); 431 if (m == NULL) 432 break; 433 m_freem(m); 434 } 435 while ((m = sc->sc_npqueue) != NULL) { 436 sc->sc_npqueue = m->m_nextpkt; 437 m_freem(m); 438 } 439 if (sc->sc_togo != NULL) { 440 m_freem(sc->sc_togo); 441 sc->sc_togo = NULL; 442 } 443 #ifdef PPP_COMPRESS 444 ppp_ccp_closed(sc); 445 sc->sc_xc_state = NULL; 446 sc->sc_rc_state = NULL; 447 #endif /* PPP_COMPRESS */ 448 #ifdef PPP_FILTER 449 if (sc->sc_pass_filt_in.bf_insns != 0) { 450 FREE(sc->sc_pass_filt_in.bf_insns, M_DEVBUF); 451 sc->sc_pass_filt_in.bf_insns = 0; 452 sc->sc_pass_filt_in.bf_len = 0; 453 } 454 if (sc->sc_pass_filt_out.bf_insns != 0) { 455 FREE(sc->sc_pass_filt_out.bf_insns, M_DEVBUF); 456 sc->sc_pass_filt_out.bf_insns = 0; 457 sc->sc_pass_filt_out.bf_len = 0; 458 } 459 if (sc->sc_active_filt_in.bf_insns != 0) { 460 FREE(sc->sc_active_filt_in.bf_insns, M_DEVBUF); 461 sc->sc_active_filt_in.bf_insns = 0; 462 sc->sc_active_filt_in.bf_len = 0; 463 } 464 if (sc->sc_active_filt_out.bf_insns != 0) { 465 FREE(sc->sc_active_filt_out.bf_insns, M_DEVBUF); 466 sc->sc_active_filt_out.bf_insns = 0; 467 sc->sc_active_filt_out.bf_len = 0; 468 } 469 #endif /* PPP_FILTER */ 470 #ifdef VJC 471 if (sc->sc_comp != 0) { 472 FREE(sc->sc_comp, M_DEVBUF); 473 sc->sc_comp = 0; 474 } 475 #endif 476 (void)ppp_clone_destroy(&sc->sc_if); 477 } 478 479 /* 480 * Ioctl routine for generic ppp devices. 481 */ 482 int 483 pppioctl(struct ppp_softc *sc, u_long cmd, void *data, int flag, 484 struct lwp *l) 485 { 486 int s, error, flags, mru, npx; 487 u_int nb; 488 struct ppp_option_data *odp; 489 struct compressor **cp; 490 struct npioctl *npi; 491 time_t t; 492 #ifdef PPP_FILTER 493 struct bpf_program *bp, *nbp; 494 struct bpf_insn *newcode, *oldcode; 495 int newcodelen; 496 #endif /* PPP_FILTER */ 497 #ifdef PPP_COMPRESS 498 u_char ccp_option[CCP_MAX_OPTION_LENGTH]; 499 #endif 500 501 switch (cmd) { 502 case PPPIOCSFLAGS: 503 case PPPIOCSMRU: 504 case PPPIOCSMAXCID: 505 case PPPIOCSCOMPRESS: 506 case PPPIOCSNPMODE: 507 if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE, 508 KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, &sc->sc_if, (void *)cmd, 509 NULL) != 0) 510 return (EPERM); 511 break; 512 case PPPIOCXFERUNIT: 513 /* XXX: Why is this privileged?! */ 514 if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE, 515 KAUTH_REQ_NETWORK_INTERFACE_GETPRIV, &sc->sc_if, (void *)cmd, 516 NULL) != 0) 517 return (EPERM); 518 break; 519 default: 520 break; 521 } 522 523 switch (cmd) { 524 case FIONREAD: 525 *(int *)data = sc->sc_inq.ifq_len; 526 break; 527 528 case PPPIOCGUNIT: 529 *(int *)data = sc->sc_unit; 530 break; 531 532 case PPPIOCGFLAGS: 533 *(u_int *)data = sc->sc_flags; 534 break; 535 536 case PPPIOCGRAWIN: 537 { 538 struct ppp_rawin *rwin = (struct ppp_rawin *)data; 539 u_char c, q = 0; 540 541 for (c = sc->sc_rawin_start; c < sizeof(sc->sc_rawin.buf);) 542 rwin->buf[q++] = sc->sc_rawin.buf[c++]; 543 544 for (c = 0; c < sc->sc_rawin_start;) 545 rwin->buf[q++] = sc->sc_rawin.buf[c++]; 546 547 rwin->count = sc->sc_rawin.count; 548 } 549 break; 550 551 case PPPIOCSFLAGS: 552 flags = *(int *)data & SC_MASK; 553 s = splsoftnet(); 554 #ifdef PPP_COMPRESS 555 if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN)) 556 ppp_ccp_closed(sc); 557 #endif 558 splhigh(); /* XXX IMP ME HARDER */ 559 sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags; 560 splx(s); 561 break; 562 563 case PPPIOCSMRU: 564 mru = *(int *)data; 565 if (mru >= PPP_MINMRU && mru <= PPP_MAXMRU) 566 sc->sc_mru = mru; 567 break; 568 569 case PPPIOCGMRU: 570 *(int *)data = sc->sc_mru; 571 break; 572 573 #ifdef VJC 574 case PPPIOCSMAXCID: 575 if (sc->sc_comp) { 576 s = splsoftnet(); 577 sl_compress_setup(sc->sc_comp, *(int *)data); 578 splx(s); 579 } 580 break; 581 #endif 582 583 case PPPIOCXFERUNIT: 584 sc->sc_xfer = l->l_proc->p_pid; 585 break; 586 587 #ifdef PPP_COMPRESS 588 case PPPIOCSCOMPRESS: 589 odp = (struct ppp_option_data *) data; 590 nb = odp->length; 591 if (nb > sizeof(ccp_option)) 592 nb = sizeof(ccp_option); 593 if ((error = copyin(odp->ptr, ccp_option, nb)) != 0) 594 return (error); 595 if (ccp_option[1] < 2) /* preliminary check on the length byte */ 596 return (EINVAL); 597 for (cp = ppp_compressors; *cp != NULL; ++cp) 598 if ((*cp)->compress_proto == ccp_option[0]) { 599 /* 600 * Found a handler for the protocol - try to allocate 601 * a compressor or decompressor. 602 */ 603 error = 0; 604 if (odp->transmit) { 605 s = splsoftnet(); 606 if (sc->sc_xc_state != NULL) 607 (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); 608 sc->sc_xcomp = *cp; 609 sc->sc_xc_state = (*cp)->comp_alloc(ccp_option, nb); 610 if (sc->sc_xc_state == NULL) { 611 if (sc->sc_flags & SC_DEBUG) 612 printf("%s: comp_alloc failed\n", 613 sc->sc_if.if_xname); 614 error = ENOBUFS; 615 } 616 splhigh(); /* XXX IMP ME HARDER */ 617 sc->sc_flags &= ~SC_COMP_RUN; 618 splx(s); 619 } else { 620 s = splsoftnet(); 621 if (sc->sc_rc_state != NULL) 622 (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); 623 sc->sc_rcomp = *cp; 624 sc->sc_rc_state = (*cp)->decomp_alloc(ccp_option, nb); 625 if (sc->sc_rc_state == NULL) { 626 if (sc->sc_flags & SC_DEBUG) 627 printf("%s: decomp_alloc failed\n", 628 sc->sc_if.if_xname); 629 error = ENOBUFS; 630 } 631 splhigh(); /* XXX IMP ME HARDER */ 632 sc->sc_flags &= ~SC_DECOMP_RUN; 633 splx(s); 634 } 635 return (error); 636 } 637 if (sc->sc_flags & SC_DEBUG) 638 printf("%s: no compressor for [%x %x %x], %x\n", 639 sc->sc_if.if_xname, ccp_option[0], ccp_option[1], 640 ccp_option[2], nb); 641 return (EINVAL); /* no handler found */ 642 #endif /* PPP_COMPRESS */ 643 644 case PPPIOCGNPMODE: 645 case PPPIOCSNPMODE: 646 npi = (struct npioctl *) data; 647 switch (npi->protocol) { 648 case PPP_IP: 649 npx = NP_IP; 650 break; 651 case PPP_IPV6: 652 npx = NP_IPV6; 653 break; 654 default: 655 return EINVAL; 656 } 657 if (cmd == PPPIOCGNPMODE) { 658 npi->mode = sc->sc_npmode[npx]; 659 } else { 660 if (npi->mode != sc->sc_npmode[npx]) { 661 s = splnet(); 662 sc->sc_npmode[npx] = npi->mode; 663 if (npi->mode != NPMODE_QUEUE) { 664 ppp_requeue(sc); 665 ppp_restart(sc); 666 } 667 splx(s); 668 } 669 } 670 break; 671 672 case PPPIOCGIDLE: 673 s = splsoftnet(); 674 t = time_second; 675 ((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent; 676 ((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv; 677 splx(s); 678 break; 679 680 #ifdef PPP_FILTER 681 case PPPIOCSPASS: 682 case PPPIOCSACTIVE: 683 /* These are no longer supported. */ 684 return EOPNOTSUPP; 685 686 case PPPIOCSIPASS: 687 case PPPIOCSOPASS: 688 case PPPIOCSIACTIVE: 689 case PPPIOCSOACTIVE: 690 nbp = (struct bpf_program *) data; 691 if ((unsigned) nbp->bf_len > BPF_MAXINSNS) 692 return EINVAL; 693 newcodelen = nbp->bf_len * sizeof(struct bpf_insn); 694 if (newcodelen != 0) { 695 newcode = malloc(newcodelen, M_DEVBUF, M_WAITOK); 696 /* WAITOK -- malloc() never fails. */ 697 if ((error = copyin((void *)nbp->bf_insns, (void *)newcode, 698 newcodelen)) != 0) { 699 free(newcode, M_DEVBUF); 700 return error; 701 } 702 if (!bpf_validate(newcode, nbp->bf_len)) { 703 free(newcode, M_DEVBUF); 704 return EINVAL; 705 } 706 } else 707 newcode = 0; 708 switch (cmd) { 709 case PPPIOCSIPASS: 710 bp = &sc->sc_pass_filt_in; 711 break; 712 713 case PPPIOCSOPASS: 714 bp = &sc->sc_pass_filt_out; 715 break; 716 717 case PPPIOCSIACTIVE: 718 bp = &sc->sc_active_filt_in; 719 break; 720 721 case PPPIOCSOACTIVE: 722 bp = &sc->sc_active_filt_out; 723 break; 724 default: 725 free(newcode, M_DEVBUF); 726 return (EPASSTHROUGH); 727 } 728 oldcode = bp->bf_insns; 729 s = splnet(); 730 bp->bf_len = nbp->bf_len; 731 bp->bf_insns = newcode; 732 splx(s); 733 if (oldcode != 0) 734 free(oldcode, M_DEVBUF); 735 break; 736 #endif /* PPP_FILTER */ 737 738 default: 739 return (EPASSTHROUGH); 740 } 741 return (0); 742 } 743 744 /* 745 * Process an ioctl request to the ppp network interface. 746 */ 747 static int 748 pppsioctl(struct ifnet *ifp, u_long cmd, void *data) 749 { 750 struct lwp *l = curlwp; /* XXX */ 751 struct ppp_softc *sc = ifp->if_softc; 752 struct ifaddr *ifa = (struct ifaddr *)data; 753 struct ifreq *ifr = (struct ifreq *)data; 754 struct ppp_stats *psp; 755 #ifdef PPP_COMPRESS 756 struct ppp_comp_stats *pcp; 757 #endif 758 int s = splnet(), error = 0; 759 760 switch (cmd) { 761 case SIOCSIFFLAGS: 762 if ((ifp->if_flags & IFF_RUNNING) == 0) 763 ifp->if_flags &= ~IFF_UP; 764 break; 765 766 case SIOCSIFADDR: 767 switch (ifa->ifa_addr->sa_family) { 768 #ifdef INET 769 case AF_INET: 770 break; 771 #endif 772 #ifdef INET6 773 case AF_INET6: 774 break; 775 #endif 776 default: 777 error = EAFNOSUPPORT; 778 break; 779 } 780 break; 781 782 case SIOCSIFDSTADDR: 783 switch (ifa->ifa_addr->sa_family) { 784 #ifdef INET 785 case AF_INET: 786 break; 787 #endif 788 #ifdef INET6 789 case AF_INET6: 790 break; 791 #endif 792 default: 793 error = EAFNOSUPPORT; 794 break; 795 } 796 break; 797 798 case SIOCSIFMTU: 799 if ((error = kauth_authorize_network(l->l_cred, 800 KAUTH_NETWORK_INTERFACE, KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, 801 ifp, (void *)cmd, NULL) != 0)) 802 break; 803 sc->sc_if.if_mtu = ifr->ifr_mtu; 804 break; 805 806 case SIOCGIFMTU: 807 ifr->ifr_mtu = sc->sc_if.if_mtu; 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 if (!(sc->sc_flags & SC_TBUSY) 1272 && (IFQ_IS_EMPTY(&sc->sc_if.if_snd) == 0 || sc->sc_fastq.ifq_head 1273 || sc->sc_outm)) { 1274 s = splhigh(); /* XXX IMP ME HARDER */ 1275 sc->sc_flags |= SC_TBUSY; 1276 splx(s); 1277 (*sc->sc_start)(sc); 1278 } 1279 for (;;) { 1280 s = splnet(); 1281 IF_DEQUEUE(&sc->sc_rawq, m); 1282 splx(s); 1283 if (m == NULL) 1284 break; 1285 ppp_inproc(sc, m); 1286 } 1287 } 1288 1289 #ifdef PPP_COMPRESS 1290 /* 1291 * Handle a CCP packet. `rcvd' is 1 if the packet was received, 1292 * 0 if it is about to be transmitted. 1293 */ 1294 static void 1295 ppp_ccp(struct ppp_softc *sc, struct mbuf *m, int rcvd) 1296 { 1297 u_char *dp, *ep; 1298 struct mbuf *mp; 1299 int slen, s; 1300 1301 /* 1302 * Get a pointer to the data after the PPP header. 1303 */ 1304 if (m->m_len <= PPP_HDRLEN) { 1305 mp = m->m_next; 1306 if (mp == NULL) 1307 return; 1308 dp = (mp != NULL)? mtod(mp, u_char *): NULL; 1309 } else { 1310 mp = m; 1311 dp = mtod(mp, u_char *) + PPP_HDRLEN; 1312 } 1313 1314 ep = mtod(mp, u_char *) + mp->m_len; 1315 if (dp + CCP_HDRLEN > ep) 1316 return; 1317 slen = CCP_LENGTH(dp); 1318 if (dp + slen > ep) { 1319 if (sc->sc_flags & SC_DEBUG) 1320 printf("if_ppp/ccp: not enough data in mbuf (%p+%x > %p+%x)\n", 1321 dp, slen, mtod(mp, u_char *), mp->m_len); 1322 return; 1323 } 1324 1325 switch (CCP_CODE(dp)) { 1326 case CCP_CONFREQ: 1327 case CCP_TERMREQ: 1328 case CCP_TERMACK: 1329 /* CCP must be going down - disable compression */ 1330 if (sc->sc_flags & SC_CCP_UP) { 1331 s = splhigh(); /* XXX IMP ME HARDER */ 1332 sc->sc_flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN); 1333 splx(s); 1334 } 1335 break; 1336 1337 case CCP_CONFACK: 1338 if (sc->sc_flags & SC_CCP_OPEN && !(sc->sc_flags & SC_CCP_UP) 1339 && slen >= CCP_HDRLEN + CCP_OPT_MINLEN 1340 && slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) { 1341 if (!rcvd) { 1342 /* we're agreeing to send compressed packets. */ 1343 if (sc->sc_xc_state != NULL 1344 && (*sc->sc_xcomp->comp_init) 1345 (sc->sc_xc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, 1346 sc->sc_unit, 0, sc->sc_flags & SC_DEBUG)) { 1347 s = splhigh(); /* XXX IMP ME HARDER */ 1348 sc->sc_flags |= SC_COMP_RUN; 1349 splx(s); 1350 } 1351 } else { 1352 /* peer is agreeing to send compressed packets. */ 1353 if (sc->sc_rc_state != NULL 1354 && (*sc->sc_rcomp->decomp_init) 1355 (sc->sc_rc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, 1356 sc->sc_unit, 0, sc->sc_mru, 1357 sc->sc_flags & SC_DEBUG)) { 1358 s = splhigh(); /* XXX IMP ME HARDER */ 1359 sc->sc_flags |= SC_DECOMP_RUN; 1360 sc->sc_flags &= ~(SC_DC_ERROR | SC_DC_FERROR); 1361 splx(s); 1362 } 1363 } 1364 } 1365 break; 1366 1367 case CCP_RESETACK: 1368 if (sc->sc_flags & SC_CCP_UP) { 1369 if (!rcvd) { 1370 if (sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) 1371 (*sc->sc_xcomp->comp_reset)(sc->sc_xc_state); 1372 } else { 1373 if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) { 1374 (*sc->sc_rcomp->decomp_reset)(sc->sc_rc_state); 1375 s = splhigh(); /* XXX IMP ME HARDER */ 1376 sc->sc_flags &= ~SC_DC_ERROR; 1377 splx(s); 1378 } 1379 } 1380 } 1381 break; 1382 } 1383 } 1384 1385 /* 1386 * CCP is down; free (de)compressor state if necessary. 1387 */ 1388 static void 1389 ppp_ccp_closed(struct ppp_softc *sc) 1390 { 1391 if (sc->sc_xc_state) { 1392 (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); 1393 sc->sc_xc_state = NULL; 1394 } 1395 if (sc->sc_rc_state) { 1396 (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); 1397 sc->sc_rc_state = NULL; 1398 } 1399 } 1400 #endif /* PPP_COMPRESS */ 1401 1402 /* 1403 * PPP packet input routine. 1404 * The caller has checked and removed the FCS and has inserted 1405 * the address/control bytes and the protocol high byte if they 1406 * were omitted. 1407 */ 1408 void 1409 ppppktin(struct ppp_softc *sc, struct mbuf *m, int lost) 1410 { 1411 int s = splhigh(); /* XXX IMP ME HARDER */ 1412 1413 if (lost) 1414 m->m_flags |= M_ERRMARK; 1415 IF_ENQUEUE(&sc->sc_rawq, m); 1416 softint_schedule(sc->sc_si); 1417 splx(s); 1418 } 1419 1420 /* 1421 * Process a received PPP packet, doing decompression as necessary. 1422 * Should be called at splsoftnet. 1423 */ 1424 #define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \ 1425 TYPE_UNCOMPRESSED_TCP) 1426 1427 static void 1428 ppp_inproc(struct ppp_softc *sc, struct mbuf *m) 1429 { 1430 struct ifnet *ifp = &sc->sc_if; 1431 struct ifqueue *inq; 1432 int s, ilen, proto, rv; 1433 u_char *cp, adrs, ctrl; 1434 struct mbuf *mp, *dmp = NULL; 1435 #ifdef VJC 1436 int xlen; 1437 u_char *iphdr; 1438 u_int hlen; 1439 #endif 1440 1441 sc->sc_stats.ppp_ipackets++; 1442 1443 if (sc->sc_flags & SC_LOG_INPKT) { 1444 ilen = 0; 1445 for (mp = m; mp != NULL; mp = mp->m_next) 1446 ilen += mp->m_len; 1447 printf("%s: got %d bytes\n", ifp->if_xname, ilen); 1448 pppdumpm(m); 1449 } 1450 1451 cp = mtod(m, u_char *); 1452 adrs = PPP_ADDRESS(cp); 1453 ctrl = PPP_CONTROL(cp); 1454 proto = PPP_PROTOCOL(cp); 1455 1456 if (m->m_flags & M_ERRMARK) { 1457 m->m_flags &= ~M_ERRMARK; 1458 s = splhigh(); /* XXX IMP ME HARDER */ 1459 sc->sc_flags |= SC_VJ_RESET; 1460 splx(s); 1461 } 1462 1463 #ifdef PPP_COMPRESS 1464 /* 1465 * Decompress this packet if necessary, update the receiver's 1466 * dictionary, or take appropriate action on a CCP packet. 1467 */ 1468 if (proto == PPP_COMP && sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN) 1469 && !(sc->sc_flags & SC_DC_ERROR) && !(sc->sc_flags & SC_DC_FERROR)) { 1470 /* decompress this packet */ 1471 rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp); 1472 if (rv == DECOMP_OK) { 1473 m_freem(m); 1474 if (dmp == NULL) { 1475 /* no error, but no decompressed packet produced */ 1476 return; 1477 } 1478 m = dmp; 1479 cp = mtod(m, u_char *); 1480 proto = PPP_PROTOCOL(cp); 1481 1482 } else { 1483 /* 1484 * An error has occurred in decompression. 1485 * Pass the compressed packet up to pppd, which may take 1486 * CCP down or issue a Reset-Req. 1487 */ 1488 if (sc->sc_flags & SC_DEBUG) 1489 printf("%s: decompress failed %d\n", ifp->if_xname, rv); 1490 s = splhigh(); /* XXX IMP ME HARDER */ 1491 sc->sc_flags |= SC_VJ_RESET; 1492 if (rv == DECOMP_ERROR) 1493 sc->sc_flags |= SC_DC_ERROR; 1494 else 1495 sc->sc_flags |= SC_DC_FERROR; 1496 splx(s); 1497 } 1498 1499 } else { 1500 if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) { 1501 (*sc->sc_rcomp->incomp)(sc->sc_rc_state, m); 1502 } 1503 if (proto == PPP_CCP) { 1504 ppp_ccp(sc, m, 1); 1505 } 1506 } 1507 #endif 1508 1509 ilen = 0; 1510 for (mp = m; mp != NULL; mp = mp->m_next) 1511 ilen += mp->m_len; 1512 1513 #ifdef VJC 1514 if (sc->sc_flags & SC_VJ_RESET) { 1515 /* 1516 * If we've missed a packet, we must toss subsequent compressed 1517 * packets which don't have an explicit connection ID. 1518 */ 1519 if (sc->sc_comp) 1520 sl_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp); 1521 s = splhigh(); /* XXX IMP ME HARDER */ 1522 sc->sc_flags &= ~SC_VJ_RESET; 1523 splx(s); 1524 } 1525 1526 /* 1527 * See if we have a VJ-compressed packet to uncompress. 1528 */ 1529 if (proto == PPP_VJC_COMP) { 1530 if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) 1531 goto bad; 1532 1533 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN, 1534 ilen - PPP_HDRLEN, TYPE_COMPRESSED_TCP, 1535 sc->sc_comp, &iphdr, &hlen); 1536 1537 if (xlen <= 0) { 1538 if (sc->sc_flags & SC_DEBUG) 1539 printf("%s: VJ uncompress failed on type comp\n", 1540 ifp->if_xname); 1541 goto bad; 1542 } 1543 1544 /* Copy the PPP and IP headers into a new mbuf. */ 1545 MGETHDR(mp, M_DONTWAIT, MT_DATA); 1546 if (mp == NULL) 1547 goto bad; 1548 mp->m_len = 0; 1549 mp->m_next = NULL; 1550 if (hlen + PPP_HDRLEN > MHLEN) { 1551 MCLGET(mp, M_DONTWAIT); 1552 if (M_TRAILINGSPACE(mp) < hlen + PPP_HDRLEN) { 1553 m_freem(mp); 1554 goto bad; /* lose if big headers and no clusters */ 1555 } 1556 } 1557 cp = mtod(mp, u_char *); 1558 cp[0] = adrs; 1559 cp[1] = ctrl; 1560 cp[2] = 0; 1561 cp[3] = PPP_IP; 1562 proto = PPP_IP; 1563 bcopy(iphdr, cp + PPP_HDRLEN, hlen); 1564 mp->m_len = hlen + PPP_HDRLEN; 1565 1566 /* 1567 * Trim the PPP and VJ headers off the old mbuf 1568 * and stick the new and old mbufs together. 1569 */ 1570 m->m_data += PPP_HDRLEN + xlen; 1571 m->m_len -= PPP_HDRLEN + xlen; 1572 if (m->m_len <= M_TRAILINGSPACE(mp)) { 1573 bcopy(mtod(m, u_char *), mtod(mp, u_char *) + mp->m_len, m->m_len); 1574 mp->m_len += m->m_len; 1575 MFREE(m, mp->m_next); 1576 } else 1577 mp->m_next = m; 1578 m = mp; 1579 ilen += hlen - xlen; 1580 1581 } else if (proto == PPP_VJC_UNCOMP) { 1582 if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) 1583 goto bad; 1584 1585 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN, 1586 ilen - PPP_HDRLEN, TYPE_UNCOMPRESSED_TCP, 1587 sc->sc_comp, &iphdr, &hlen); 1588 1589 if (xlen < 0) { 1590 if (sc->sc_flags & SC_DEBUG) 1591 printf("%s: VJ uncompress failed on type uncomp\n", 1592 ifp->if_xname); 1593 goto bad; 1594 } 1595 1596 proto = PPP_IP; 1597 cp[3] = PPP_IP; 1598 } 1599 #endif /* VJC */ 1600 1601 /* 1602 * If the packet will fit in a header mbuf, don't waste a 1603 * whole cluster on it. 1604 */ 1605 if (ilen <= MHLEN && M_IS_CLUSTER(m)) { 1606 MGETHDR(mp, M_DONTWAIT, MT_DATA); 1607 if (mp != NULL) { 1608 m_copydata(m, 0, ilen, mtod(mp, void *)); 1609 m_freem(m); 1610 m = mp; 1611 m->m_len = ilen; 1612 } 1613 } 1614 m->m_pkthdr.len = ilen; 1615 m->m_pkthdr.rcvif = ifp; 1616 1617 if ((proto & 0x8000) == 0) { 1618 #ifdef PPP_FILTER 1619 /* 1620 * See whether we want to pass this packet, and 1621 * if it counts as link activity. 1622 */ 1623 if (sc->sc_pass_filt_in.bf_insns != 0 1624 && bpf_filter(sc->sc_pass_filt_in.bf_insns, (u_char *) m, 1625 ilen, 0) == 0) { 1626 /* drop this packet */ 1627 m_freem(m); 1628 return; 1629 } 1630 if (sc->sc_active_filt_in.bf_insns == 0 1631 || bpf_filter(sc->sc_active_filt_in.bf_insns, (u_char *) m, 1632 ilen, 0)) 1633 sc->sc_last_recv = time_second; 1634 #else 1635 /* 1636 * Record the time that we received this packet. 1637 */ 1638 sc->sc_last_recv = time_second; 1639 #endif /* PPP_FILTER */ 1640 } 1641 1642 #if NBPFILTER > 0 1643 /* See if bpf wants to look at the packet. */ 1644 if (sc->sc_if.if_bpf) 1645 bpf_mtap(sc->sc_if.if_bpf, m); 1646 #endif 1647 1648 rv = 0; 1649 switch (proto) { 1650 #ifdef INET 1651 case PPP_IP: 1652 /* 1653 * IP packet - take off the ppp header and pass it up to IP. 1654 */ 1655 if ((ifp->if_flags & IFF_UP) == 0 1656 || sc->sc_npmode[NP_IP] != NPMODE_PASS) { 1657 /* interface is down - drop the packet. */ 1658 m_freem(m); 1659 return; 1660 } 1661 m->m_pkthdr.len -= PPP_HDRLEN; 1662 m->m_data += PPP_HDRLEN; 1663 m->m_len -= PPP_HDRLEN; 1664 #ifdef GATEWAY 1665 if (ipflow_fastforward(m)) 1666 return; 1667 #endif 1668 schednetisr(NETISR_IP); 1669 inq = &ipintrq; 1670 break; 1671 #endif 1672 1673 #ifdef INET6 1674 case PPP_IPV6: 1675 /* 1676 * IPv6 packet - take off the ppp header and pass it up to IPv6. 1677 */ 1678 if ((ifp->if_flags & IFF_UP) == 0 1679 || sc->sc_npmode[NP_IPV6] != NPMODE_PASS) { 1680 /* interface is down - drop the packet. */ 1681 m_freem(m); 1682 return; 1683 } 1684 m->m_pkthdr.len -= PPP_HDRLEN; 1685 m->m_data += PPP_HDRLEN; 1686 m->m_len -= PPP_HDRLEN; 1687 #ifdef GATEWAY 1688 if (ip6flow_fastforward(m)) 1689 return; 1690 #endif 1691 schednetisr(NETISR_IPV6); 1692 inq = &ip6intrq; 1693 break; 1694 #endif 1695 1696 default: 1697 /* 1698 * Some other protocol - place on input queue for read(). 1699 */ 1700 inq = &sc->sc_inq; 1701 rv = 1; 1702 break; 1703 } 1704 1705 /* 1706 * Put the packet on the appropriate input queue. 1707 */ 1708 s = splnet(); 1709 if (IF_QFULL(inq)) { 1710 IF_DROP(inq); 1711 splx(s); 1712 if (sc->sc_flags & SC_DEBUG) 1713 printf("%s: input queue full\n", ifp->if_xname); 1714 ifp->if_iqdrops++; 1715 goto bad; 1716 } 1717 IF_ENQUEUE(inq, m); 1718 splx(s); 1719 ifp->if_ipackets++; 1720 ifp->if_ibytes += ilen; 1721 1722 if (rv) 1723 (*sc->sc_ctlp)(sc); 1724 1725 return; 1726 1727 bad: 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 1735 static void 1736 pppdumpm(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 *bp++ = hexdigits[*rptr >> 4]; /* convert byte to ascii hex */ 1750 *bp++ = hexdigits[*rptr++ & 0xf]; 1751 } 1752 1753 if (m->m_next) { 1754 if (bp > buf + sizeof(buf) - 3) 1755 goto done; 1756 *bp++ = '|'; 1757 } else 1758 *bp++ = ' '; 1759 } 1760 done: 1761 if (m) 1762 *bp++ = '>'; 1763 *bp = 0; 1764 printf("%s\n", buf); 1765 } 1766 1767 #ifdef ALTQ 1768 /* 1769 * a wrapper to transmit a packet from if_start since ALTQ uses 1770 * if_start to send a packet. 1771 */ 1772 static void 1773 ppp_ifstart(struct ifnet *ifp) 1774 { 1775 struct ppp_softc *sc; 1776 1777 sc = ifp->if_softc; 1778 (*sc->sc_start)(sc); 1779 } 1780 #endif 1781