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