1 /* $NetBSD: if_ppp.c,v 1.109 2006/10/12 01:32:28 christos Exp $ */ 2 /* Id: if_ppp.c,v 1.6 1997/03/04 03:33:00 paulus Exp */ 3 4 /* 5 * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver. 6 * 7 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. The name "Carnegie Mellon University" must not be used to 22 * endorse or promote products derived from this software without 23 * prior written permission. For permission or any legal 24 * details, please contact 25 * Office of Technology Transfer 26 * Carnegie Mellon University 27 * 5000 Forbes Avenue 28 * Pittsburgh, PA 15213-3890 29 * (412) 268-4387, fax: (412) 268-7395 30 * tech-transfer@andrew.cmu.edu 31 * 32 * 4. Redistributions of any form whatsoever must retain the following 33 * acknowledgment: 34 * "This product includes software developed by Computing Services 35 * at Carnegie Mellon University (http://www.cmu.edu/computing/)." 36 * 37 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO 38 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 39 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE 40 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 41 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 42 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 43 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 44 * 45 * Based on: 46 * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89 47 * 48 * Copyright (c) 1987 Regents of the University of California. 49 * All rights reserved. 50 * 51 * Redistribution and use in source and binary forms are permitted 52 * provided that the above copyright notice and this paragraph are 53 * duplicated in all such forms and that any documentation, 54 * advertising materials, and other materials related to such 55 * distribution and use acknowledge that the software was developed 56 * by the University of California, Berkeley. The name of the 57 * University may not be used to endorse or promote products derived 58 * from this software without specific prior written permission. 59 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 60 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 61 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 62 * 63 * Serial Line interface 64 * 65 * Rick Adams 66 * Center for Seismic Studies 67 * 1300 N 17th Street, Suite 1450 68 * Arlington, Virginia 22209 69 * (703)276-7900 70 * rick@seismo.ARPA 71 * seismo!rick 72 * 73 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris). 74 * Converted to 4.3BSD Beta by Chris Torek. 75 * Other changes made at Berkeley, based in part on code by Kirk Smith. 76 * 77 * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com) 78 * Added VJ tcp header compression; more unified ioctls 79 * 80 * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au). 81 * Cleaned up a lot of the mbuf-related code to fix bugs that 82 * caused system crashes and packet corruption. Changed pppstart 83 * so that it doesn't just give up with a collision if the whole 84 * packet doesn't fit in the output ring buffer. 85 * 86 * Added priority queueing for interactive IP packets, following 87 * the model of if_sl.c, plus hooks for bpf. 88 * Paul Mackerras (paulus@cs.anu.edu.au). 89 */ 90 91 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */ 92 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */ 93 94 /* 95 * XXX IMP ME HARDER 96 * 97 * This is an explanation of that comment. This code used to use 98 * splimp() to block both network and tty interrupts. However, 99 * that call is deprecated. So, we have replaced the uses of 100 * splimp() with splhigh() in order to applomplish what it needs 101 * to accomplish, and added that happy little comment. 102 */ 103 104 #include <sys/cdefs.h> 105 __KERNEL_RCSID(0, "$NetBSD: if_ppp.c,v 1.109 2006/10/12 01:32:28 christos Exp $"); 106 107 #include "ppp.h" 108 109 #include "opt_inet.h" 110 #include "opt_gateway.h" 111 #include "opt_ppp.h" 112 113 #ifdef INET 114 #define VJC 115 #endif 116 #define PPP_COMPRESS 117 118 #include <sys/param.h> 119 #include <sys/proc.h> 120 #include <sys/mbuf.h> 121 #include <sys/socket.h> 122 #include <sys/ioctl.h> 123 #include <sys/kernel.h> 124 #include <sys/systm.h> 125 #include <sys/time.h> 126 #include <sys/malloc.h> 127 #include <sys/conf.h> 128 #include <sys/kauth.h> 129 130 #include <net/if.h> 131 #include <net/if_types.h> 132 #include <net/netisr.h> 133 #include <net/route.h> 134 #ifdef PPP_FILTER 135 #include <net/bpf.h> 136 #endif 137 138 #include <machine/intr.h> 139 140 #include <netinet/in.h> 141 #include <netinet/in_systm.h> 142 #include <netinet/in_var.h> 143 #ifdef INET 144 #include <netinet/ip.h> 145 #endif 146 147 #include "bpfilter.h" 148 #if NBPFILTER > 0 149 #include <net/bpf.h> 150 #endif 151 152 #if defined(PPP_FILTER) || NBPFILTER > 0 153 #include <net/slip.h> 154 #endif 155 156 #ifdef VJC 157 #include <net/slcompress.h> 158 #endif 159 160 #include <net/ppp_defs.h> 161 #include <net/if_ppp.h> 162 #include <net/if_pppvar.h> 163 #include <machine/cpu.h> 164 165 #ifdef PPP_COMPRESS 166 #define PACKETPTR struct mbuf * 167 #include <net/ppp-comp.h> 168 #endif 169 170 static int pppsioctl(struct ifnet *, u_long, caddr_t); 171 static void ppp_requeue(struct ppp_softc *); 172 static void ppp_ccp(struct ppp_softc *, struct mbuf *m, int rcvd); 173 static void ppp_ccp_closed(struct ppp_softc *); 174 static void ppp_inproc(struct ppp_softc *, struct mbuf *); 175 static void pppdumpm(struct mbuf *m0); 176 #ifdef ALTQ 177 static void ppp_ifstart(struct ifnet *ifp); 178 #endif 179 180 #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS 181 void pppnetisr(void); 182 #endif 183 static void pppintr(void *); 184 185 /* 186 * Some useful mbuf macros not in mbuf.h. 187 */ 188 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT) 189 190 #define M_DATASTART(m) \ 191 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \ 192 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat) 193 194 #define M_DATASIZE(m) \ 195 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \ 196 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN) 197 198 /* 199 * We define two link layer specific mbuf flags, to mark high-priority 200 * packets for output, and received packets following lost/corrupted 201 * packets. 202 */ 203 #define M_HIGHPRI M_LINK0 /* output packet for sc_fastq */ 204 #define M_ERRMARK M_LINK1 /* rx packet following lost/corrupted pkt */ 205 206 static int ppp_clone_create(struct if_clone *, int); 207 static int ppp_clone_destroy(struct ifnet *); 208 209 static struct ppp_softc *ppp_create(const char *, int); 210 211 static LIST_HEAD(, ppp_softc) ppp_softc_list; 212 213 struct if_clone ppp_cloner = 214 IF_CLONE_INITIALIZER("ppp", ppp_clone_create, ppp_clone_destroy); 215 216 static struct simplelock ppp_list_mutex = SIMPLELOCK_INITIALIZER; 217 218 #ifdef PPP_COMPRESS 219 /* 220 * List of compressors we know about. 221 * We leave some space so maybe we can modload compressors. 222 */ 223 224 extern struct compressor ppp_bsd_compress; 225 extern struct compressor ppp_deflate, ppp_deflate_draft; 226 227 struct compressor *ppp_compressors[PPP_COMPRESSORS_MAX] = { 228 #if DO_BSD_COMPRESS && defined(PPP_BSDCOMP) 229 &ppp_bsd_compress, 230 #endif 231 #if DO_DEFLATE && defined(PPP_DEFLATE) 232 &ppp_deflate, 233 &ppp_deflate_draft, 234 #endif 235 NULL 236 }; 237 #endif /* PPP_COMPRESS */ 238 239 240 /* 241 * Called from boot code to establish ppp interfaces. 242 */ 243 void 244 pppattach(void) 245 { 246 extern struct linesw ppp_disc; 247 248 if (ttyldisc_attach(&ppp_disc) != 0) 249 panic("pppattach"); 250 LIST_INIT(&ppp_softc_list); 251 if_clone_attach(&ppp_cloner); 252 } 253 254 static struct ppp_softc * 255 ppp_create(const char *name, int unit) 256 { 257 struct ppp_softc *sc, *sci, *scl = NULL; 258 259 MALLOC(sc, struct ppp_softc *, sizeof(*sc), M_DEVBUF, M_WAIT|M_ZERO); 260 261 simple_lock(&ppp_list_mutex); 262 if (unit == -1) { 263 int i = 0; 264 LIST_FOREACH(sci, &ppp_softc_list, sc_iflist) { 265 scl = sci; 266 if (i < sci->sc_unit) { 267 unit = i; 268 break; 269 } else { 270 #ifdef DIAGNOSTIC 271 KASSERT(i == sci->sc_unit); 272 #endif 273 i++; 274 } 275 } 276 if (unit == -1) 277 unit = i; 278 } else { 279 LIST_FOREACH(sci, &ppp_softc_list, sc_iflist) { 280 scl = sci; 281 if (unit < sci->sc_unit) 282 break; 283 else if (unit == sci->sc_unit) { 284 FREE(sc, M_DEVBUF); 285 return NULL; 286 } 287 } 288 } 289 290 if (sci != NULL) 291 LIST_INSERT_BEFORE(sci, sc, sc_iflist); 292 else if (scl != NULL) 293 LIST_INSERT_AFTER(scl, sc, sc_iflist); 294 else 295 LIST_INSERT_HEAD(&ppp_softc_list, sc, sc_iflist); 296 297 simple_unlock(&ppp_list_mutex); 298 299 (void)snprintf(sc->sc_if.if_xname, sizeof(sc->sc_if.if_xname), "%s%d", 300 name, sc->sc_unit = unit); 301 callout_init(&sc->sc_timo_ch); 302 sc->sc_if.if_softc = sc; 303 sc->sc_if.if_mtu = PPP_MTU; 304 sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 305 sc->sc_if.if_type = IFT_PPP; 306 sc->sc_if.if_hdrlen = PPP_HDRLEN; 307 sc->sc_if.if_dlt = DLT_NULL; 308 sc->sc_if.if_ioctl = pppsioctl; 309 sc->sc_if.if_output = pppoutput; 310 #ifdef ALTQ 311 sc->sc_if.if_start = ppp_ifstart; 312 #endif 313 IFQ_SET_MAXLEN(&sc->sc_if.if_snd, IFQ_MAXLEN); 314 sc->sc_inq.ifq_maxlen = IFQ_MAXLEN; 315 sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN; 316 sc->sc_rawq.ifq_maxlen = IFQ_MAXLEN; 317 /* Ratio of 1:2 packets between the regular and the fast queue */ 318 sc->sc_maxfastq = 2; 319 IFQ_SET_READY(&sc->sc_if.if_snd); 320 if_attach(&sc->sc_if); 321 if_alloc_sadl(&sc->sc_if); 322 #if NBPFILTER > 0 323 bpfattach(&sc->sc_if, DLT_NULL, 0); 324 #endif 325 return sc; 326 } 327 328 static int 329 ppp_clone_create(struct if_clone *ifc, int unit) 330 { 331 return ppp_create(ifc->ifc_name, unit) == NULL ? EEXIST : 0; 332 } 333 334 static int 335 ppp_clone_destroy(struct ifnet *ifp) 336 { 337 struct ppp_softc *sc = (struct ppp_softc *)ifp->if_softc; 338 339 if (sc->sc_devp != NULL) 340 return EBUSY; /* Not removing it */ 341 342 simple_lock(&ppp_list_mutex); 343 LIST_REMOVE(sc, sc_iflist); 344 simple_unlock(&ppp_list_mutex); 345 346 #if NBPFILTER > 0 347 bpfdetach(ifp); 348 #endif 349 if_detach(ifp); 350 351 FREE(sc, M_DEVBUF); 352 return 0; 353 } 354 355 /* 356 * Allocate a ppp interface unit and initialize it. 357 */ 358 struct ppp_softc * 359 pppalloc(pid_t pid) 360 { 361 struct ppp_softc *sc = NULL, *scf; 362 int i; 363 364 simple_lock(&ppp_list_mutex); 365 for (scf = LIST_FIRST(&ppp_softc_list); scf != NULL; 366 scf = LIST_NEXT(scf, sc_iflist)) { 367 if (scf->sc_xfer == pid) { 368 scf->sc_xfer = 0; 369 simple_unlock(&ppp_list_mutex); 370 return scf; 371 } 372 if (scf->sc_devp == NULL && sc == NULL) 373 sc = scf; 374 } 375 simple_unlock(&ppp_list_mutex); 376 377 if (sc == NULL) 378 sc = ppp_create(ppp_cloner.ifc_name, -1); 379 380 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 381 sc->sc_si = softintr_establish(IPL_SOFTNET, pppintr, sc); 382 if (sc->sc_si == NULL) { 383 printf("%s: unable to establish softintr\n", sc->sc_if.if_xname); 384 return (NULL); 385 } 386 #endif 387 sc->sc_flags = 0; 388 sc->sc_mru = PPP_MRU; 389 sc->sc_relinq = NULL; 390 (void)memset(&sc->sc_stats, 0, sizeof(sc->sc_stats)); 391 #ifdef VJC 392 MALLOC(sc->sc_comp, struct slcompress *, sizeof(struct slcompress), 393 M_DEVBUF, M_NOWAIT); 394 if (sc->sc_comp) 395 sl_compress_init(sc->sc_comp); 396 #endif 397 #ifdef PPP_COMPRESS 398 sc->sc_xc_state = NULL; 399 sc->sc_rc_state = NULL; 400 #endif /* PPP_COMPRESS */ 401 for (i = 0; i < NUM_NP; ++i) 402 sc->sc_npmode[i] = NPMODE_ERROR; 403 sc->sc_npqueue = NULL; 404 sc->sc_npqtail = &sc->sc_npqueue; 405 sc->sc_last_sent = sc->sc_last_recv = time_second; 406 407 return sc; 408 } 409 410 /* 411 * Deallocate a ppp unit. Must be called at splsoftnet or higher. 412 */ 413 void 414 pppdealloc(struct ppp_softc *sc) 415 { 416 struct mbuf *m; 417 418 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 419 softintr_disestablish(sc->sc_si); 420 #endif 421 if_down(&sc->sc_if); 422 sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING); 423 sc->sc_devp = NULL; 424 sc->sc_xfer = 0; 425 for (;;) { 426 IF_DEQUEUE(&sc->sc_rawq, m); 427 if (m == NULL) 428 break; 429 m_freem(m); 430 } 431 for (;;) { 432 IF_DEQUEUE(&sc->sc_inq, m); 433 if (m == NULL) 434 break; 435 m_freem(m); 436 } 437 for (;;) { 438 IF_DEQUEUE(&sc->sc_fastq, m); 439 if (m == NULL) 440 break; 441 m_freem(m); 442 } 443 while ((m = sc->sc_npqueue) != NULL) { 444 sc->sc_npqueue = m->m_nextpkt; 445 m_freem(m); 446 } 447 if (sc->sc_togo != NULL) { 448 m_freem(sc->sc_togo); 449 sc->sc_togo = NULL; 450 } 451 #ifdef PPP_COMPRESS 452 ppp_ccp_closed(sc); 453 sc->sc_xc_state = NULL; 454 sc->sc_rc_state = NULL; 455 #endif /* PPP_COMPRESS */ 456 #ifdef PPP_FILTER 457 if (sc->sc_pass_filt_in.bf_insns != 0) { 458 FREE(sc->sc_pass_filt_in.bf_insns, M_DEVBUF); 459 sc->sc_pass_filt_in.bf_insns = 0; 460 sc->sc_pass_filt_in.bf_len = 0; 461 } 462 if (sc->sc_pass_filt_out.bf_insns != 0) { 463 FREE(sc->sc_pass_filt_out.bf_insns, M_DEVBUF); 464 sc->sc_pass_filt_out.bf_insns = 0; 465 sc->sc_pass_filt_out.bf_len = 0; 466 } 467 if (sc->sc_active_filt_in.bf_insns != 0) { 468 FREE(sc->sc_active_filt_in.bf_insns, M_DEVBUF); 469 sc->sc_active_filt_in.bf_insns = 0; 470 sc->sc_active_filt_in.bf_len = 0; 471 } 472 if (sc->sc_active_filt_out.bf_insns != 0) { 473 FREE(sc->sc_active_filt_out.bf_insns, M_DEVBUF); 474 sc->sc_active_filt_out.bf_insns = 0; 475 sc->sc_active_filt_out.bf_len = 0; 476 } 477 #endif /* PPP_FILTER */ 478 #ifdef VJC 479 if (sc->sc_comp != 0) { 480 FREE(sc->sc_comp, M_DEVBUF); 481 sc->sc_comp = 0; 482 } 483 #endif 484 (void)ppp_clone_destroy(&sc->sc_if); 485 } 486 487 /* 488 * Ioctl routine for generic ppp devices. 489 */ 490 int 491 pppioctl(struct ppp_softc *sc, u_long cmd, caddr_t data, int flag __unused, 492 struct lwp *l) 493 { 494 int s, error, flags, mru, npx; 495 u_int nb; 496 struct ppp_option_data *odp; 497 struct compressor **cp; 498 struct npioctl *npi; 499 time_t t; 500 #ifdef PPP_FILTER 501 struct bpf_program *bp, *nbp; 502 struct bpf_insn *newcode, *oldcode; 503 int newcodelen; 504 #endif /* PPP_FILTER */ 505 #ifdef PPP_COMPRESS 506 u_char ccp_option[CCP_MAX_OPTION_LENGTH]; 507 #endif 508 509 switch (cmd) { 510 case PPPIOCSFLAGS: 511 case PPPIOCSMRU: 512 case PPPIOCSMAXCID: 513 case PPPIOCXFERUNIT: 514 case PPPIOCSCOMPRESS: 515 case PPPIOCSNPMODE: 516 if ((error = kauth_authorize_generic(l->l_cred, 517 KAUTH_GENERIC_ISSUSER, &l->l_acflag)) != 0) 518 return (error); 519 /* FALLTHROUGH */ 520 default: 521 break; 522 } 523 524 switch (cmd) { 525 case FIONREAD: 526 *(int *)data = sc->sc_inq.ifq_len; 527 break; 528 529 case PPPIOCGUNIT: 530 *(int *)data = sc->sc_unit; 531 break; 532 533 case PPPIOCGFLAGS: 534 *(u_int *)data = sc->sc_flags; 535 break; 536 537 case PPPIOCGRAWIN: 538 { 539 struct ppp_rawin *rwin = (struct ppp_rawin *)data; 540 u_char c, q = 0; 541 542 for (c = sc->sc_rawin_start; c < sizeof(sc->sc_rawin.buf);) 543 rwin->buf[q++] = sc->sc_rawin.buf[c++]; 544 545 for (c = 0; c < sc->sc_rawin_start;) 546 rwin->buf[q++] = sc->sc_rawin.buf[c++]; 547 548 rwin->count = sc->sc_rawin.count; 549 } 550 break; 551 552 case PPPIOCSFLAGS: 553 flags = *(int *)data & SC_MASK; 554 s = splsoftnet(); 555 #ifdef PPP_COMPRESS 556 if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN)) 557 ppp_ccp_closed(sc); 558 #endif 559 splhigh(); /* XXX IMP ME HARDER */ 560 sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags; 561 splx(s); 562 break; 563 564 case PPPIOCSMRU: 565 mru = *(int *)data; 566 if (mru >= PPP_MINMRU && mru <= PPP_MAXMRU) 567 sc->sc_mru = mru; 568 break; 569 570 case PPPIOCGMRU: 571 *(int *)data = sc->sc_mru; 572 break; 573 574 #ifdef VJC 575 case PPPIOCSMAXCID: 576 if (sc->sc_comp) { 577 s = splsoftnet(); 578 sl_compress_setup(sc->sc_comp, *(int *)data); 579 splx(s); 580 } 581 break; 582 #endif 583 584 case PPPIOCXFERUNIT: 585 sc->sc_xfer = l->l_proc->p_pid; 586 break; 587 588 #ifdef PPP_COMPRESS 589 case PPPIOCSCOMPRESS: 590 odp = (struct ppp_option_data *) data; 591 nb = odp->length; 592 if (nb > sizeof(ccp_option)) 593 nb = sizeof(ccp_option); 594 if ((error = copyin(odp->ptr, ccp_option, nb)) != 0) 595 return (error); 596 if (ccp_option[1] < 2) /* preliminary check on the length byte */ 597 return (EINVAL); 598 for (cp = ppp_compressors; *cp != NULL; ++cp) 599 if ((*cp)->compress_proto == ccp_option[0]) { 600 /* 601 * Found a handler for the protocol - try to allocate 602 * a compressor or decompressor. 603 */ 604 error = 0; 605 if (odp->transmit) { 606 s = splsoftnet(); 607 if (sc->sc_xc_state != NULL) 608 (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); 609 sc->sc_xcomp = *cp; 610 sc->sc_xc_state = (*cp)->comp_alloc(ccp_option, nb); 611 if (sc->sc_xc_state == NULL) { 612 if (sc->sc_flags & SC_DEBUG) 613 printf("%s: comp_alloc failed\n", 614 sc->sc_if.if_xname); 615 error = ENOBUFS; 616 } 617 splhigh(); /* XXX IMP ME HARDER */ 618 sc->sc_flags &= ~SC_COMP_RUN; 619 splx(s); 620 } else { 621 s = splsoftnet(); 622 if (sc->sc_rc_state != NULL) 623 (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); 624 sc->sc_rcomp = *cp; 625 sc->sc_rc_state = (*cp)->decomp_alloc(ccp_option, nb); 626 if (sc->sc_rc_state == NULL) { 627 if (sc->sc_flags & SC_DEBUG) 628 printf("%s: decomp_alloc failed\n", 629 sc->sc_if.if_xname); 630 error = ENOBUFS; 631 } 632 splhigh(); /* XXX IMP ME HARDER */ 633 sc->sc_flags &= ~SC_DECOMP_RUN; 634 splx(s); 635 } 636 return (error); 637 } 638 if (sc->sc_flags & SC_DEBUG) 639 printf("%s: no compressor for [%x %x %x], %x\n", 640 sc->sc_if.if_xname, ccp_option[0], ccp_option[1], 641 ccp_option[2], nb); 642 return (EINVAL); /* no handler found */ 643 #endif /* PPP_COMPRESS */ 644 645 case PPPIOCGNPMODE: 646 case PPPIOCSNPMODE: 647 npi = (struct npioctl *) data; 648 switch (npi->protocol) { 649 case PPP_IP: 650 npx = NP_IP; 651 break; 652 case PPP_IPV6: 653 npx = NP_IPV6; 654 break; 655 default: 656 return EINVAL; 657 } 658 if (cmd == PPPIOCGNPMODE) { 659 npi->mode = sc->sc_npmode[npx]; 660 } else { 661 if (npi->mode != sc->sc_npmode[npx]) { 662 s = splnet(); 663 sc->sc_npmode[npx] = npi->mode; 664 if (npi->mode != NPMODE_QUEUE) { 665 ppp_requeue(sc); 666 ppp_restart(sc); 667 } 668 splx(s); 669 } 670 } 671 break; 672 673 case PPPIOCGIDLE: 674 s = splsoftnet(); 675 t = time_second; 676 ((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent; 677 ((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv; 678 splx(s); 679 break; 680 681 #ifdef PPP_FILTER 682 case PPPIOCSPASS: 683 case PPPIOCSACTIVE: 684 /* These are no longer supported. */ 685 return EOPNOTSUPP; 686 687 case PPPIOCSIPASS: 688 case PPPIOCSOPASS: 689 case PPPIOCSIACTIVE: 690 case PPPIOCSOACTIVE: 691 nbp = (struct bpf_program *) data; 692 if ((unsigned) nbp->bf_len > BPF_MAXINSNS) 693 return EINVAL; 694 newcodelen = nbp->bf_len * sizeof(struct bpf_insn); 695 if (newcodelen != 0) { 696 newcode = malloc(newcodelen, M_DEVBUF, M_WAITOK); 697 /* WAITOK -- malloc() never fails. */ 698 if ((error = copyin((caddr_t)nbp->bf_insns, (caddr_t)newcode, 699 newcodelen)) != 0) { 700 free(newcode, M_DEVBUF); 701 return error; 702 } 703 if (!bpf_validate(newcode, nbp->bf_len)) { 704 free(newcode, M_DEVBUF); 705 return EINVAL; 706 } 707 } else 708 newcode = 0; 709 switch (cmd) { 710 case PPPIOCSIPASS: 711 bp = &sc->sc_pass_filt_in; 712 break; 713 714 case PPPIOCSOPASS: 715 bp = &sc->sc_pass_filt_out; 716 break; 717 718 case PPPIOCSIACTIVE: 719 bp = &sc->sc_active_filt_in; 720 break; 721 722 case PPPIOCSOACTIVE: 723 bp = &sc->sc_active_filt_out; 724 break; 725 default: 726 free(newcode, M_DEVBUF); 727 return (EPASSTHROUGH); 728 } 729 oldcode = bp->bf_insns; 730 s = splnet(); 731 bp->bf_len = nbp->bf_len; 732 bp->bf_insns = newcode; 733 splx(s); 734 if (oldcode != 0) 735 free(oldcode, M_DEVBUF); 736 break; 737 #endif /* PPP_FILTER */ 738 739 default: 740 return (EPASSTHROUGH); 741 } 742 return (0); 743 } 744 745 /* 746 * Process an ioctl request to the ppp network interface. 747 */ 748 static int 749 pppsioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 750 { 751 struct lwp *l = curlwp; /* XXX */ 752 struct ppp_softc *sc = ifp->if_softc; 753 struct ifaddr *ifa = (struct ifaddr *)data; 754 struct ifreq *ifr = (struct ifreq *)data; 755 struct ppp_stats *psp; 756 #ifdef PPP_COMPRESS 757 struct ppp_comp_stats *pcp; 758 #endif 759 int s = splnet(), error = 0; 760 761 switch (cmd) { 762 case SIOCSIFFLAGS: 763 if ((ifp->if_flags & IFF_RUNNING) == 0) 764 ifp->if_flags &= ~IFF_UP; 765 break; 766 767 case SIOCSIFADDR: 768 switch (ifa->ifa_addr->sa_family) { 769 #ifdef INET 770 case AF_INET: 771 break; 772 #endif 773 #ifdef INET6 774 case AF_INET6: 775 break; 776 #endif 777 default: 778 error = EAFNOSUPPORT; 779 break; 780 } 781 break; 782 783 case SIOCSIFDSTADDR: 784 switch (ifa->ifa_addr->sa_family) { 785 #ifdef INET 786 case AF_INET: 787 break; 788 #endif 789 #ifdef INET6 790 case AF_INET6: 791 break; 792 #endif 793 default: 794 error = EAFNOSUPPORT; 795 break; 796 } 797 break; 798 799 case SIOCSIFMTU: 800 if ((error = kauth_authorize_generic(l->l_cred, 801 KAUTH_GENERIC_ISSUSER, &l->l_acflag)) != 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 == 0) { 813 error = EAFNOSUPPORT; 814 break; 815 } 816 switch (ifr->ifr_addr.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, struct sockaddr *dst, 873 struct rtentry *rtp __unused) 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 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 1112 softintr_schedule(sc->sc_si); 1113 #else 1114 schednetisr(NETISR_PPP); 1115 #endif 1116 splx(s); 1117 } 1118 1119 /* 1120 * Get a packet to send. This procedure is intended to be called at 1121 * splsoftnet, since it may involve time-consuming operations such as 1122 * applying VJ compression, packet compression, address/control and/or 1123 * protocol field compression to the packet. 1124 */ 1125 struct mbuf * 1126 ppp_dequeue(struct ppp_softc *sc) 1127 { 1128 struct mbuf *m, *mp; 1129 u_char *cp; 1130 int address, control, protocol; 1131 int s; 1132 1133 /* 1134 * Grab a packet to send: first try the fast queue, then the 1135 * normal queue. 1136 */ 1137 s = splnet(); 1138 if (sc->sc_nfastq < sc->sc_maxfastq) { 1139 IF_DEQUEUE(&sc->sc_fastq, m); 1140 if (m != NULL) 1141 sc->sc_nfastq++; 1142 else 1143 IFQ_DEQUEUE(&sc->sc_if.if_snd, m); 1144 } else { 1145 sc->sc_nfastq = 0; 1146 IFQ_DEQUEUE(&sc->sc_if.if_snd, m); 1147 if (m == NULL) { 1148 IF_DEQUEUE(&sc->sc_fastq, m); 1149 if (m != NULL) 1150 sc->sc_nfastq++; 1151 } 1152 } 1153 splx(s); 1154 1155 if (m == NULL) 1156 return NULL; 1157 1158 ++sc->sc_stats.ppp_opackets; 1159 1160 /* 1161 * Extract the ppp header of the new packet. 1162 * The ppp header will be in one mbuf. 1163 */ 1164 cp = mtod(m, u_char *); 1165 address = PPP_ADDRESS(cp); 1166 control = PPP_CONTROL(cp); 1167 protocol = PPP_PROTOCOL(cp); 1168 1169 switch (protocol) { 1170 case PPP_IP: 1171 #ifdef VJC 1172 /* 1173 * If the packet is a TCP/IP packet, see if we can compress it. 1174 */ 1175 if ((sc->sc_flags & SC_COMP_TCP) && sc->sc_comp != NULL) { 1176 struct ip *ip; 1177 int type; 1178 1179 mp = m; 1180 ip = (struct ip *) (cp + PPP_HDRLEN); 1181 if (mp->m_len <= PPP_HDRLEN) { 1182 mp = mp->m_next; 1183 if (mp == NULL) 1184 break; 1185 ip = mtod(mp, struct ip *); 1186 } 1187 /* this code assumes the IP/TCP header is in one non-shared mbuf */ 1188 if (ip->ip_p == IPPROTO_TCP) { 1189 type = sl_compress_tcp(mp, ip, sc->sc_comp, 1190 !(sc->sc_flags & SC_NO_TCP_CCID)); 1191 switch (type) { 1192 case TYPE_UNCOMPRESSED_TCP: 1193 protocol = PPP_VJC_UNCOMP; 1194 break; 1195 case TYPE_COMPRESSED_TCP: 1196 protocol = PPP_VJC_COMP; 1197 cp = mtod(m, u_char *); 1198 cp[0] = address; /* header has moved */ 1199 cp[1] = control; 1200 cp[2] = 0; 1201 break; 1202 } 1203 cp[3] = protocol; /* update protocol in PPP header */ 1204 } 1205 } 1206 #endif /* VJC */ 1207 break; 1208 1209 #ifdef PPP_COMPRESS 1210 case PPP_CCP: 1211 ppp_ccp(sc, m, 0); 1212 break; 1213 #endif /* PPP_COMPRESS */ 1214 } 1215 1216 #ifdef PPP_COMPRESS 1217 if (protocol != PPP_LCP && protocol != PPP_CCP 1218 && sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) { 1219 struct mbuf *mcomp = NULL; 1220 int slen; 1221 1222 slen = 0; 1223 for (mp = m; mp != NULL; mp = mp->m_next) 1224 slen += mp->m_len; 1225 (*sc->sc_xcomp->compress) 1226 (sc->sc_xc_state, &mcomp, m, slen, sc->sc_if.if_mtu + PPP_HDRLEN); 1227 if (mcomp != NULL) { 1228 if (sc->sc_flags & SC_CCP_UP) { 1229 /* Send the compressed packet instead of the original. */ 1230 m_freem(m); 1231 m = mcomp; 1232 cp = mtod(m, u_char *); 1233 protocol = cp[3]; 1234 } else { 1235 /* Can't transmit compressed packets until CCP is up. */ 1236 m_freem(mcomp); 1237 } 1238 } 1239 } 1240 #endif /* PPP_COMPRESS */ 1241 1242 /* 1243 * Compress the address/control and protocol, if possible. 1244 */ 1245 if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS && 1246 control == PPP_UI && protocol != PPP_ALLSTATIONS && 1247 protocol != PPP_LCP) { 1248 /* can compress address/control */ 1249 m->m_data += 2; 1250 m->m_len -= 2; 1251 } 1252 if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) { 1253 /* can compress protocol */ 1254 if (mtod(m, u_char *) == cp) { 1255 cp[2] = cp[1]; /* move address/control up */ 1256 cp[1] = cp[0]; 1257 } 1258 ++m->m_data; 1259 --m->m_len; 1260 } 1261 1262 return m; 1263 } 1264 1265 #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS 1266 void 1267 pppnetisr(void) 1268 { 1269 struct ppp_softc *sc; 1270 1271 for (sc = LIST_FIRST(&ppp_softc_list); sc != NULL; 1272 sc = LIST_NEXT(sc, sc_iflist)) 1273 pppintr(sc); 1274 } 1275 #endif 1276 1277 /* 1278 * Software interrupt routine, called at splsoftnet. 1279 */ 1280 static void 1281 pppintr(void *arg) 1282 { 1283 struct ppp_softc *sc = arg; 1284 struct mbuf *m; 1285 int s; 1286 1287 if (!(sc->sc_flags & SC_TBUSY) 1288 && (IFQ_IS_EMPTY(&sc->sc_if.if_snd) == 0 || sc->sc_fastq.ifq_head 1289 || sc->sc_outm)) { 1290 s = splhigh(); /* XXX IMP ME HARDER */ 1291 sc->sc_flags |= SC_TBUSY; 1292 splx(s); 1293 (*sc->sc_start)(sc); 1294 } 1295 for (;;) { 1296 s = splnet(); 1297 IF_DEQUEUE(&sc->sc_rawq, m); 1298 splx(s); 1299 if (m == NULL) 1300 break; 1301 ppp_inproc(sc, m); 1302 } 1303 } 1304 1305 #ifdef PPP_COMPRESS 1306 /* 1307 * Handle a CCP packet. `rcvd' is 1 if the packet was received, 1308 * 0 if it is about to be transmitted. 1309 */ 1310 static void 1311 ppp_ccp(struct ppp_softc *sc, struct mbuf *m, int rcvd) 1312 { 1313 u_char *dp, *ep; 1314 struct mbuf *mp; 1315 int slen, s; 1316 1317 /* 1318 * Get a pointer to the data after the PPP header. 1319 */ 1320 if (m->m_len <= PPP_HDRLEN) { 1321 mp = m->m_next; 1322 if (mp == NULL) 1323 return; 1324 dp = (mp != NULL)? mtod(mp, u_char *): NULL; 1325 } else { 1326 mp = m; 1327 dp = mtod(mp, u_char *) + PPP_HDRLEN; 1328 } 1329 1330 ep = mtod(mp, u_char *) + mp->m_len; 1331 if (dp + CCP_HDRLEN > ep) 1332 return; 1333 slen = CCP_LENGTH(dp); 1334 if (dp + slen > ep) { 1335 if (sc->sc_flags & SC_DEBUG) 1336 printf("if_ppp/ccp: not enough data in mbuf (%p+%x > %p+%x)\n", 1337 dp, slen, mtod(mp, u_char *), mp->m_len); 1338 return; 1339 } 1340 1341 switch (CCP_CODE(dp)) { 1342 case CCP_CONFREQ: 1343 case CCP_TERMREQ: 1344 case CCP_TERMACK: 1345 /* CCP must be going down - disable compression */ 1346 if (sc->sc_flags & SC_CCP_UP) { 1347 s = splhigh(); /* XXX IMP ME HARDER */ 1348 sc->sc_flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN); 1349 splx(s); 1350 } 1351 break; 1352 1353 case CCP_CONFACK: 1354 if (sc->sc_flags & SC_CCP_OPEN && !(sc->sc_flags & SC_CCP_UP) 1355 && slen >= CCP_HDRLEN + CCP_OPT_MINLEN 1356 && slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) { 1357 if (!rcvd) { 1358 /* we're agreeing to send compressed packets. */ 1359 if (sc->sc_xc_state != NULL 1360 && (*sc->sc_xcomp->comp_init) 1361 (sc->sc_xc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, 1362 sc->sc_unit, 0, sc->sc_flags & SC_DEBUG)) { 1363 s = splhigh(); /* XXX IMP ME HARDER */ 1364 sc->sc_flags |= SC_COMP_RUN; 1365 splx(s); 1366 } 1367 } else { 1368 /* peer is agreeing to send compressed packets. */ 1369 if (sc->sc_rc_state != NULL 1370 && (*sc->sc_rcomp->decomp_init) 1371 (sc->sc_rc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, 1372 sc->sc_unit, 0, sc->sc_mru, 1373 sc->sc_flags & SC_DEBUG)) { 1374 s = splhigh(); /* XXX IMP ME HARDER */ 1375 sc->sc_flags |= SC_DECOMP_RUN; 1376 sc->sc_flags &= ~(SC_DC_ERROR | SC_DC_FERROR); 1377 splx(s); 1378 } 1379 } 1380 } 1381 break; 1382 1383 case CCP_RESETACK: 1384 if (sc->sc_flags & SC_CCP_UP) { 1385 if (!rcvd) { 1386 if (sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) 1387 (*sc->sc_xcomp->comp_reset)(sc->sc_xc_state); 1388 } else { 1389 if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) { 1390 (*sc->sc_rcomp->decomp_reset)(sc->sc_rc_state); 1391 s = splhigh(); /* XXX IMP ME HARDER */ 1392 sc->sc_flags &= ~SC_DC_ERROR; 1393 splx(s); 1394 } 1395 } 1396 } 1397 break; 1398 } 1399 } 1400 1401 /* 1402 * CCP is down; free (de)compressor state if necessary. 1403 */ 1404 static void 1405 ppp_ccp_closed(struct ppp_softc *sc) 1406 { 1407 if (sc->sc_xc_state) { 1408 (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); 1409 sc->sc_xc_state = NULL; 1410 } 1411 if (sc->sc_rc_state) { 1412 (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); 1413 sc->sc_rc_state = NULL; 1414 } 1415 } 1416 #endif /* PPP_COMPRESS */ 1417 1418 /* 1419 * PPP packet input routine. 1420 * The caller has checked and removed the FCS and has inserted 1421 * the address/control bytes and the protocol high byte if they 1422 * were omitted. 1423 */ 1424 void 1425 ppppktin(struct ppp_softc *sc, struct mbuf *m, int lost) 1426 { 1427 int s = splhigh(); /* XXX IMP ME HARDER */ 1428 1429 if (lost) 1430 m->m_flags |= M_ERRMARK; 1431 IF_ENQUEUE(&sc->sc_rawq, m); 1432 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 1433 softintr_schedule(sc->sc_si); 1434 #else 1435 schednetisr(NETISR_PPP); 1436 #endif 1437 splx(s); 1438 } 1439 1440 /* 1441 * Process a received PPP packet, doing decompression as necessary. 1442 * Should be called at splsoftnet. 1443 */ 1444 #define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \ 1445 TYPE_UNCOMPRESSED_TCP) 1446 1447 static void 1448 ppp_inproc(struct ppp_softc *sc, struct mbuf *m) 1449 { 1450 struct ifnet *ifp = &sc->sc_if; 1451 struct ifqueue *inq; 1452 int s, ilen, proto, rv; 1453 u_char *cp, adrs, ctrl; 1454 struct mbuf *mp, *dmp = NULL; 1455 #ifdef VJC 1456 int xlen; 1457 u_char *iphdr; 1458 u_int hlen; 1459 #endif 1460 1461 sc->sc_stats.ppp_ipackets++; 1462 1463 if (sc->sc_flags & SC_LOG_INPKT) { 1464 ilen = 0; 1465 for (mp = m; mp != NULL; mp = mp->m_next) 1466 ilen += mp->m_len; 1467 printf("%s: got %d bytes\n", ifp->if_xname, ilen); 1468 pppdumpm(m); 1469 } 1470 1471 cp = mtod(m, u_char *); 1472 adrs = PPP_ADDRESS(cp); 1473 ctrl = PPP_CONTROL(cp); 1474 proto = PPP_PROTOCOL(cp); 1475 1476 if (m->m_flags & M_ERRMARK) { 1477 m->m_flags &= ~M_ERRMARK; 1478 s = splhigh(); /* XXX IMP ME HARDER */ 1479 sc->sc_flags |= SC_VJ_RESET; 1480 splx(s); 1481 } 1482 1483 #ifdef PPP_COMPRESS 1484 /* 1485 * Decompress this packet if necessary, update the receiver's 1486 * dictionary, or take appropriate action on a CCP packet. 1487 */ 1488 if (proto == PPP_COMP && sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN) 1489 && !(sc->sc_flags & SC_DC_ERROR) && !(sc->sc_flags & SC_DC_FERROR)) { 1490 /* decompress this packet */ 1491 rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp); 1492 if (rv == DECOMP_OK) { 1493 m_freem(m); 1494 if (dmp == NULL) { 1495 /* no error, but no decompressed packet produced */ 1496 return; 1497 } 1498 m = dmp; 1499 cp = mtod(m, u_char *); 1500 proto = PPP_PROTOCOL(cp); 1501 1502 } else { 1503 /* 1504 * An error has occurred in decompression. 1505 * Pass the compressed packet up to pppd, which may take 1506 * CCP down or issue a Reset-Req. 1507 */ 1508 if (sc->sc_flags & SC_DEBUG) 1509 printf("%s: decompress failed %d\n", ifp->if_xname, rv); 1510 s = splhigh(); /* XXX IMP ME HARDER */ 1511 sc->sc_flags |= SC_VJ_RESET; 1512 if (rv == DECOMP_ERROR) 1513 sc->sc_flags |= SC_DC_ERROR; 1514 else 1515 sc->sc_flags |= SC_DC_FERROR; 1516 splx(s); 1517 } 1518 1519 } else { 1520 if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) { 1521 (*sc->sc_rcomp->incomp)(sc->sc_rc_state, m); 1522 } 1523 if (proto == PPP_CCP) { 1524 ppp_ccp(sc, m, 1); 1525 } 1526 } 1527 #endif 1528 1529 ilen = 0; 1530 for (mp = m; mp != NULL; mp = mp->m_next) 1531 ilen += mp->m_len; 1532 1533 #ifdef VJC 1534 if (sc->sc_flags & SC_VJ_RESET) { 1535 /* 1536 * If we've missed a packet, we must toss subsequent compressed 1537 * packets which don't have an explicit connection ID. 1538 */ 1539 if (sc->sc_comp) 1540 sl_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp); 1541 s = splhigh(); /* XXX IMP ME HARDER */ 1542 sc->sc_flags &= ~SC_VJ_RESET; 1543 splx(s); 1544 } 1545 1546 /* 1547 * See if we have a VJ-compressed packet to uncompress. 1548 */ 1549 if (proto == PPP_VJC_COMP) { 1550 if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) 1551 goto bad; 1552 1553 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN, 1554 ilen - PPP_HDRLEN, TYPE_COMPRESSED_TCP, 1555 sc->sc_comp, &iphdr, &hlen); 1556 1557 if (xlen <= 0) { 1558 if (sc->sc_flags & SC_DEBUG) 1559 printf("%s: VJ uncompress failed on type comp\n", 1560 ifp->if_xname); 1561 goto bad; 1562 } 1563 1564 /* Copy the PPP and IP headers into a new mbuf. */ 1565 MGETHDR(mp, M_DONTWAIT, MT_DATA); 1566 if (mp == NULL) 1567 goto bad; 1568 mp->m_len = 0; 1569 mp->m_next = NULL; 1570 if (hlen + PPP_HDRLEN > MHLEN) { 1571 MCLGET(mp, M_DONTWAIT); 1572 if (M_TRAILINGSPACE(mp) < hlen + PPP_HDRLEN) { 1573 m_freem(mp); 1574 goto bad; /* lose if big headers and no clusters */ 1575 } 1576 } 1577 cp = mtod(mp, u_char *); 1578 cp[0] = adrs; 1579 cp[1] = ctrl; 1580 cp[2] = 0; 1581 cp[3] = PPP_IP; 1582 proto = PPP_IP; 1583 bcopy(iphdr, cp + PPP_HDRLEN, hlen); 1584 mp->m_len = hlen + PPP_HDRLEN; 1585 1586 /* 1587 * Trim the PPP and VJ headers off the old mbuf 1588 * and stick the new and old mbufs together. 1589 */ 1590 m->m_data += PPP_HDRLEN + xlen; 1591 m->m_len -= PPP_HDRLEN + xlen; 1592 if (m->m_len <= M_TRAILINGSPACE(mp)) { 1593 bcopy(mtod(m, u_char *), mtod(mp, u_char *) + mp->m_len, m->m_len); 1594 mp->m_len += m->m_len; 1595 MFREE(m, mp->m_next); 1596 } else 1597 mp->m_next = m; 1598 m = mp; 1599 ilen += hlen - xlen; 1600 1601 } else if (proto == PPP_VJC_UNCOMP) { 1602 if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) 1603 goto bad; 1604 1605 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN, 1606 ilen - PPP_HDRLEN, TYPE_UNCOMPRESSED_TCP, 1607 sc->sc_comp, &iphdr, &hlen); 1608 1609 if (xlen < 0) { 1610 if (sc->sc_flags & SC_DEBUG) 1611 printf("%s: VJ uncompress failed on type uncomp\n", 1612 ifp->if_xname); 1613 goto bad; 1614 } 1615 1616 proto = PPP_IP; 1617 cp[3] = PPP_IP; 1618 } 1619 #endif /* VJC */ 1620 1621 /* 1622 * If the packet will fit in a header mbuf, don't waste a 1623 * whole cluster on it. 1624 */ 1625 if (ilen <= MHLEN && M_IS_CLUSTER(m)) { 1626 MGETHDR(mp, M_DONTWAIT, MT_DATA); 1627 if (mp != NULL) { 1628 m_copydata(m, 0, ilen, mtod(mp, caddr_t)); 1629 m_freem(m); 1630 m = mp; 1631 m->m_len = ilen; 1632 } 1633 } 1634 m->m_pkthdr.len = ilen; 1635 m->m_pkthdr.rcvif = ifp; 1636 1637 if ((proto & 0x8000) == 0) { 1638 #ifdef PPP_FILTER 1639 /* 1640 * See whether we want to pass this packet, and 1641 * if it counts as link activity. 1642 */ 1643 if (sc->sc_pass_filt_in.bf_insns != 0 1644 && bpf_filter(sc->sc_pass_filt_in.bf_insns, (u_char *) m, 1645 ilen, 0) == 0) { 1646 /* drop this packet */ 1647 m_freem(m); 1648 return; 1649 } 1650 if (sc->sc_active_filt_in.bf_insns == 0 1651 || bpf_filter(sc->sc_active_filt_in.bf_insns, (u_char *) m, 1652 ilen, 0)) 1653 sc->sc_last_recv = time_second; 1654 #else 1655 /* 1656 * Record the time that we received this packet. 1657 */ 1658 sc->sc_last_recv = time_second; 1659 #endif /* PPP_FILTER */ 1660 } 1661 1662 #if NBPFILTER > 0 1663 /* See if bpf wants to look at the packet. */ 1664 if (sc->sc_if.if_bpf) 1665 bpf_mtap(sc->sc_if.if_bpf, m); 1666 #endif 1667 1668 rv = 0; 1669 switch (proto) { 1670 #ifdef INET 1671 case PPP_IP: 1672 /* 1673 * IP packet - take off the ppp header and pass it up to IP. 1674 */ 1675 if ((ifp->if_flags & IFF_UP) == 0 1676 || sc->sc_npmode[NP_IP] != NPMODE_PASS) { 1677 /* interface is down - drop the packet. */ 1678 m_freem(m); 1679 return; 1680 } 1681 m->m_pkthdr.len -= PPP_HDRLEN; 1682 m->m_data += PPP_HDRLEN; 1683 m->m_len -= PPP_HDRLEN; 1684 #ifdef GATEWAY 1685 if (ipflow_fastforward(m)) 1686 return; 1687 #endif 1688 schednetisr(NETISR_IP); 1689 inq = &ipintrq; 1690 break; 1691 #endif 1692 1693 #ifdef INET6 1694 case PPP_IPV6: 1695 /* 1696 * IPv6 packet - take off the ppp header and pass it up to IPv6. 1697 */ 1698 if ((ifp->if_flags & IFF_UP) == 0 1699 || sc->sc_npmode[NP_IPV6] != NPMODE_PASS) { 1700 /* interface is down - drop the packet. */ 1701 m_freem(m); 1702 return; 1703 } 1704 m->m_pkthdr.len -= PPP_HDRLEN; 1705 m->m_data += PPP_HDRLEN; 1706 m->m_len -= PPP_HDRLEN; 1707 schednetisr(NETISR_IPV6); 1708 inq = &ip6intrq; 1709 break; 1710 #endif 1711 1712 default: 1713 /* 1714 * Some other protocol - place on input queue for read(). 1715 */ 1716 inq = &sc->sc_inq; 1717 rv = 1; 1718 break; 1719 } 1720 1721 /* 1722 * Put the packet on the appropriate input queue. 1723 */ 1724 s = splnet(); 1725 if (IF_QFULL(inq)) { 1726 IF_DROP(inq); 1727 splx(s); 1728 if (sc->sc_flags & SC_DEBUG) 1729 printf("%s: input queue full\n", ifp->if_xname); 1730 ifp->if_iqdrops++; 1731 goto bad; 1732 } 1733 IF_ENQUEUE(inq, m); 1734 splx(s); 1735 ifp->if_ipackets++; 1736 ifp->if_ibytes += ilen; 1737 1738 if (rv) 1739 (*sc->sc_ctlp)(sc); 1740 1741 return; 1742 1743 bad: 1744 m_freem(m); 1745 sc->sc_if.if_ierrors++; 1746 sc->sc_stats.ppp_ierrors++; 1747 } 1748 1749 #define MAX_DUMP_BYTES 128 1750 1751 static void 1752 pppdumpm(struct mbuf *m0) 1753 { 1754 char buf[3*MAX_DUMP_BYTES+4]; 1755 char *bp = buf; 1756 struct mbuf *m; 1757 1758 for (m = m0; m; m = m->m_next) { 1759 int l = m->m_len; 1760 u_char *rptr = (u_char *)m->m_data; 1761 1762 while (l--) { 1763 if (bp > buf + sizeof(buf) - 4) 1764 goto done; 1765 *bp++ = hexdigits[*rptr >> 4]; /* convert byte to ascii hex */ 1766 *bp++ = hexdigits[*rptr++ & 0xf]; 1767 } 1768 1769 if (m->m_next) { 1770 if (bp > buf + sizeof(buf) - 3) 1771 goto done; 1772 *bp++ = '|'; 1773 } else 1774 *bp++ = ' '; 1775 } 1776 done: 1777 if (m) 1778 *bp++ = '>'; 1779 *bp = 0; 1780 printf("%s\n", buf); 1781 } 1782 1783 #ifdef ALTQ 1784 /* 1785 * a wrapper to transmit a packet from if_start since ALTQ uses 1786 * if_start to send a packet. 1787 */ 1788 static void 1789 ppp_ifstart(struct ifnet *ifp) 1790 { 1791 struct ppp_softc *sc; 1792 1793 sc = ifp->if_softc; 1794 (*sc->sc_start)(sc); 1795 } 1796 #endif 1797