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