1 /* $NetBSD: if_ppp.c,v 1.89 2004/04/21 18:40:39 itojun 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.89 2004/04/21 18:40:39 itojun 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 struct mbuf *m; 801 ALTQ_DECL(struct altq_pktattr pktattr;) 802 803 if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0 804 || ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) { 805 error = ENETDOWN; /* sort of */ 806 goto bad; 807 } 808 809 IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family, &pktattr); 810 811 /* 812 * Compute PPP header. 813 */ 814 m0->m_flags &= ~M_HIGHPRI; 815 switch (dst->sa_family) { 816 #ifdef INET 817 case AF_INET: 818 address = PPP_ALLSTATIONS; 819 control = PPP_UI; 820 protocol = PPP_IP; 821 mode = sc->sc_npmode[NP_IP]; 822 823 /* 824 * If this packet has the "low delay" bit set in the IP header, 825 * put it on the fastq instead. 826 */ 827 ip = mtod(m0, struct ip *); 828 if (ip->ip_tos & IPTOS_LOWDELAY) 829 m0->m_flags |= M_HIGHPRI; 830 break; 831 #endif 832 #ifdef INET6 833 case AF_INET6: 834 address = PPP_ALLSTATIONS; /*XXX*/ 835 control = PPP_UI; /*XXX*/ 836 protocol = PPP_IPV6; 837 mode = sc->sc_npmode[NP_IPV6]; 838 839 #if 0 /* XXX flowinfo/traffic class, maybe? */ 840 /* 841 * If this packet has the "low delay" bit set in the IP header, 842 * put it on the fastq instead. 843 */ 844 ip = mtod(m0, struct ip *); 845 if (ip->ip_tos & IPTOS_LOWDELAY) 846 m0->m_flags |= M_HIGHPRI; 847 #endif 848 break; 849 #endif 850 case AF_UNSPEC: 851 address = PPP_ADDRESS(dst->sa_data); 852 control = PPP_CONTROL(dst->sa_data); 853 protocol = PPP_PROTOCOL(dst->sa_data); 854 mode = NPMODE_PASS; 855 break; 856 default: 857 printf("%s: af%d not supported\n", ifp->if_xname, dst->sa_family); 858 error = EAFNOSUPPORT; 859 goto bad; 860 } 861 862 /* 863 * Drop this packet, or return an error, if necessary. 864 */ 865 if (mode == NPMODE_ERROR) { 866 error = ENETDOWN; 867 goto bad; 868 } 869 if (mode == NPMODE_DROP) { 870 error = 0; 871 goto bad; 872 } 873 874 /* 875 * Add PPP header. If no space in first mbuf, allocate another. 876 * (This assumes M_LEADINGSPACE is always 0 for a cluster mbuf.) 877 */ 878 if (M_LEADINGSPACE(m0) < PPP_HDRLEN) { 879 m0 = m_prepend(m0, PPP_HDRLEN, M_DONTWAIT); 880 if (m0 == 0) { 881 error = ENOBUFS; 882 goto bad; 883 } 884 m0->m_len = 0; 885 } else 886 m0->m_data -= PPP_HDRLEN; 887 888 cp = mtod(m0, u_char *); 889 *cp++ = address; 890 *cp++ = control; 891 *cp++ = protocol >> 8; 892 *cp++ = protocol & 0xff; 893 m0->m_len += PPP_HDRLEN; 894 895 len = 0; 896 for (m = m0; m != 0; m = m->m_next) 897 len += m->m_len; 898 899 if (sc->sc_flags & SC_LOG_OUTPKT) { 900 printf("%s output: ", ifp->if_xname); 901 pppdumpm(m0); 902 } 903 904 if ((protocol & 0x8000) == 0) { 905 #ifdef PPP_FILTER 906 /* 907 * Apply the pass and active filters to the packet, 908 * but only if it is a data packet. 909 */ 910 if (sc->sc_pass_filt_out.bf_insns != 0 911 && bpf_filter(sc->sc_pass_filt_out.bf_insns, (u_char *) m0, 912 len, 0) == 0) { 913 error = 0; /* drop this packet */ 914 goto bad; 915 } 916 917 /* 918 * Update the time we sent the most recent packet. 919 */ 920 if (sc->sc_active_filt_out.bf_insns == 0 921 || bpf_filter(sc->sc_active_filt_out.bf_insns, (u_char *) m0, 922 len, 0)) 923 sc->sc_last_sent = time.tv_sec; 924 #else 925 /* 926 * Update the time we sent the most recent packet. 927 */ 928 sc->sc_last_sent = time.tv_sec; 929 #endif /* PPP_FILTER */ 930 } 931 932 #if NBPFILTER > 0 933 /* 934 * See if bpf wants to look at the packet. 935 */ 936 if (sc->sc_if.if_bpf) 937 bpf_mtap(sc->sc_if.if_bpf, m0); 938 #endif 939 940 /* 941 * Put the packet on the appropriate queue. 942 */ 943 s = splnet(); 944 if (mode == NPMODE_QUEUE) { 945 /* XXX we should limit the number of packets on this queue */ 946 *sc->sc_npqtail = m0; 947 m0->m_nextpkt = NULL; 948 sc->sc_npqtail = &m0->m_nextpkt; 949 } else { 950 if ((m0->m_flags & M_HIGHPRI) 951 #ifdef ALTQ 952 && ALTQ_IS_ENABLED(&sc->sc_if.if_snd) == 0 953 #endif 954 ) { 955 ifq = &sc->sc_fastq; 956 if (IF_QFULL(ifq) && dst->sa_family != AF_UNSPEC) { 957 IF_DROP(ifq); 958 splx(s); 959 error = ENOBUFS; 960 goto bad; 961 } else { 962 IF_ENQUEUE(ifq, m0); 963 error = 0; 964 } 965 } else 966 IFQ_ENQUEUE(&sc->sc_if.if_snd, m0, &pktattr, error); 967 if (error) { 968 splx(s); 969 sc->sc_if.if_oerrors++; 970 sc->sc_stats.ppp_oerrors++; 971 return (error); 972 } 973 ppp_restart(sc); 974 } 975 ifp->if_opackets++; 976 ifp->if_obytes += len; 977 978 splx(s); 979 return (0); 980 981 bad: 982 m_freem(m0); 983 return (error); 984 } 985 986 /* 987 * After a change in the NPmode for some NP, move packets from the 988 * npqueue to the send queue or the fast queue as appropriate. 989 * Should be called at splnet, since we muck with the queues. 990 */ 991 static void 992 ppp_requeue(sc) 993 struct ppp_softc *sc; 994 { 995 struct mbuf *m, **mpp; 996 struct ifqueue *ifq; 997 enum NPmode mode; 998 int error; 999 1000 for (mpp = &sc->sc_npqueue; (m = *mpp) != NULL; ) { 1001 switch (PPP_PROTOCOL(mtod(m, u_char *))) { 1002 case PPP_IP: 1003 mode = sc->sc_npmode[NP_IP]; 1004 break; 1005 case PPP_IPV6: 1006 mode = sc->sc_npmode[NP_IPV6]; 1007 break; 1008 default: 1009 mode = NPMODE_PASS; 1010 } 1011 1012 switch (mode) { 1013 case NPMODE_PASS: 1014 /* 1015 * This packet can now go on one of the queues to be sent. 1016 */ 1017 *mpp = m->m_nextpkt; 1018 m->m_nextpkt = NULL; 1019 if ((m->m_flags & M_HIGHPRI) 1020 #ifdef ALTQ 1021 && ALTQ_IS_ENABLED(&sc->sc_if.if_snd) == 0 1022 #endif 1023 ) { 1024 ifq = &sc->sc_fastq; 1025 if (IF_QFULL(ifq)) { 1026 IF_DROP(ifq); 1027 m_freem(m); 1028 error = ENOBUFS; 1029 } else { 1030 IF_ENQUEUE(ifq, m); 1031 error = 0; 1032 } 1033 } else 1034 IFQ_ENQUEUE(&sc->sc_if.if_snd, m, NULL, error); 1035 if (error) { 1036 sc->sc_if.if_oerrors++; 1037 sc->sc_stats.ppp_oerrors++; 1038 } 1039 break; 1040 1041 case NPMODE_DROP: 1042 case NPMODE_ERROR: 1043 *mpp = m->m_nextpkt; 1044 m_freem(m); 1045 break; 1046 1047 case NPMODE_QUEUE: 1048 mpp = &m->m_nextpkt; 1049 break; 1050 } 1051 } 1052 sc->sc_npqtail = mpp; 1053 } 1054 1055 /* 1056 * Transmitter has finished outputting some stuff; 1057 * remember to call sc->sc_start later at splsoftnet. 1058 */ 1059 void 1060 ppp_restart(sc) 1061 struct ppp_softc *sc; 1062 { 1063 int s = splhigh(); /* XXX IMP ME HARDER */ 1064 1065 sc->sc_flags &= ~SC_TBUSY; 1066 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 1067 softintr_schedule(sc->sc_si); 1068 #else 1069 schednetisr(NETISR_PPP); 1070 #endif 1071 splx(s); 1072 } 1073 1074 /* 1075 * Get a packet to send. This procedure is intended to be called at 1076 * splsoftnet, since it may involve time-consuming operations such as 1077 * applying VJ compression, packet compression, address/control and/or 1078 * protocol field compression to the packet. 1079 */ 1080 struct mbuf * 1081 ppp_dequeue(sc) 1082 struct ppp_softc *sc; 1083 { 1084 struct mbuf *m, *mp; 1085 u_char *cp; 1086 int address, control, protocol; 1087 int s; 1088 1089 /* 1090 * Grab a packet to send: first try the fast queue, then the 1091 * normal queue. 1092 */ 1093 s = splnet(); 1094 IF_DEQUEUE(&sc->sc_fastq, m); 1095 if (m == NULL) 1096 IFQ_DEQUEUE(&sc->sc_if.if_snd, m); 1097 splx(s); 1098 1099 if (m == NULL) 1100 return NULL; 1101 1102 ++sc->sc_stats.ppp_opackets; 1103 1104 /* 1105 * Extract the ppp header of the new packet. 1106 * The ppp header will be in one mbuf. 1107 */ 1108 cp = mtod(m, u_char *); 1109 address = PPP_ADDRESS(cp); 1110 control = PPP_CONTROL(cp); 1111 protocol = PPP_PROTOCOL(cp); 1112 1113 switch (protocol) { 1114 case PPP_IP: 1115 #ifdef VJC 1116 /* 1117 * If the packet is a TCP/IP packet, see if we can compress it. 1118 */ 1119 if ((sc->sc_flags & SC_COMP_TCP) && sc->sc_comp != NULL) { 1120 struct ip *ip; 1121 int type; 1122 1123 mp = m; 1124 ip = (struct ip *) (cp + PPP_HDRLEN); 1125 if (mp->m_len <= PPP_HDRLEN) { 1126 mp = mp->m_next; 1127 if (mp == NULL) 1128 break; 1129 ip = mtod(mp, struct ip *); 1130 } 1131 /* this code assumes the IP/TCP header is in one non-shared mbuf */ 1132 if (ip->ip_p == IPPROTO_TCP) { 1133 type = sl_compress_tcp(mp, ip, sc->sc_comp, 1134 !(sc->sc_flags & SC_NO_TCP_CCID)); 1135 switch (type) { 1136 case TYPE_UNCOMPRESSED_TCP: 1137 protocol = PPP_VJC_UNCOMP; 1138 break; 1139 case TYPE_COMPRESSED_TCP: 1140 protocol = PPP_VJC_COMP; 1141 cp = mtod(m, u_char *); 1142 cp[0] = address; /* header has moved */ 1143 cp[1] = control; 1144 cp[2] = 0; 1145 break; 1146 } 1147 cp[3] = protocol; /* update protocol in PPP header */ 1148 } 1149 } 1150 #endif /* VJC */ 1151 break; 1152 1153 #ifdef PPP_COMPRESS 1154 case PPP_CCP: 1155 ppp_ccp(sc, m, 0); 1156 break; 1157 #endif /* PPP_COMPRESS */ 1158 } 1159 1160 #ifdef PPP_COMPRESS 1161 if (protocol != PPP_LCP && protocol != PPP_CCP 1162 && sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) { 1163 struct mbuf *mcomp = NULL; 1164 int slen; 1165 1166 slen = 0; 1167 for (mp = m; mp != NULL; mp = mp->m_next) 1168 slen += mp->m_len; 1169 (*sc->sc_xcomp->compress) 1170 (sc->sc_xc_state, &mcomp, m, slen, sc->sc_if.if_mtu + PPP_HDRLEN); 1171 if (mcomp != NULL) { 1172 if (sc->sc_flags & SC_CCP_UP) { 1173 /* Send the compressed packet instead of the original. */ 1174 m_freem(m); 1175 m = mcomp; 1176 cp = mtod(m, u_char *); 1177 protocol = cp[3]; 1178 } else { 1179 /* Can't transmit compressed packets until CCP is up. */ 1180 m_freem(mcomp); 1181 } 1182 } 1183 } 1184 #endif /* PPP_COMPRESS */ 1185 1186 /* 1187 * Compress the address/control and protocol, if possible. 1188 */ 1189 if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS && 1190 control == PPP_UI && protocol != PPP_ALLSTATIONS && 1191 protocol != PPP_LCP) { 1192 /* can compress address/control */ 1193 m->m_data += 2; 1194 m->m_len -= 2; 1195 } 1196 if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) { 1197 /* can compress protocol */ 1198 if (mtod(m, u_char *) == cp) { 1199 cp[2] = cp[1]; /* move address/control up */ 1200 cp[1] = cp[0]; 1201 } 1202 ++m->m_data; 1203 --m->m_len; 1204 } 1205 1206 return m; 1207 } 1208 1209 #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS 1210 void 1211 pppnetisr(void) 1212 { 1213 struct ppp_softc *sc; 1214 int i; 1215 1216 for (i = 0; i < NPPP; i++) { 1217 sc = &ppp_softc[i]; 1218 pppintr(sc); 1219 } 1220 } 1221 #endif 1222 1223 /* 1224 * Software interrupt routine, called at splsoftnet. 1225 */ 1226 void 1227 pppintr(void *arg) 1228 { 1229 struct ppp_softc *sc = arg; 1230 struct mbuf *m; 1231 int s; 1232 1233 if (!(sc->sc_flags & SC_TBUSY) 1234 && (IFQ_IS_EMPTY(&sc->sc_if.if_snd) == 0 || sc->sc_fastq.ifq_head 1235 || sc->sc_outm)) { 1236 s = splhigh(); /* XXX IMP ME HARDER */ 1237 sc->sc_flags |= SC_TBUSY; 1238 splx(s); 1239 (*sc->sc_start)(sc); 1240 } 1241 for (;;) { 1242 s = splnet(); 1243 IF_DEQUEUE(&sc->sc_rawq, m); 1244 splx(s); 1245 if (m == NULL) 1246 break; 1247 ppp_inproc(sc, m); 1248 } 1249 } 1250 1251 #ifdef PPP_COMPRESS 1252 /* 1253 * Handle a CCP packet. `rcvd' is 1 if the packet was received, 1254 * 0 if it is about to be transmitted. 1255 */ 1256 static void 1257 ppp_ccp(sc, m, rcvd) 1258 struct ppp_softc *sc; 1259 struct mbuf *m; 1260 int rcvd; 1261 { 1262 u_char *dp, *ep; 1263 struct mbuf *mp; 1264 int slen, s; 1265 1266 /* 1267 * Get a pointer to the data after the PPP header. 1268 */ 1269 if (m->m_len <= PPP_HDRLEN) { 1270 mp = m->m_next; 1271 if (mp == NULL) 1272 return; 1273 dp = (mp != NULL)? mtod(mp, u_char *): NULL; 1274 } else { 1275 mp = m; 1276 dp = mtod(mp, u_char *) + PPP_HDRLEN; 1277 } 1278 1279 ep = mtod(mp, u_char *) + mp->m_len; 1280 if (dp + CCP_HDRLEN > ep) 1281 return; 1282 slen = CCP_LENGTH(dp); 1283 if (dp + slen > ep) { 1284 if (sc->sc_flags & SC_DEBUG) 1285 printf("if_ppp/ccp: not enough data in mbuf (%p+%x > %p+%x)\n", 1286 dp, slen, mtod(mp, u_char *), mp->m_len); 1287 return; 1288 } 1289 1290 switch (CCP_CODE(dp)) { 1291 case CCP_CONFREQ: 1292 case CCP_TERMREQ: 1293 case CCP_TERMACK: 1294 /* CCP must be going down - disable compression */ 1295 if (sc->sc_flags & SC_CCP_UP) { 1296 s = splhigh(); /* XXX IMP ME HARDER */ 1297 sc->sc_flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN); 1298 splx(s); 1299 } 1300 break; 1301 1302 case CCP_CONFACK: 1303 if (sc->sc_flags & SC_CCP_OPEN && !(sc->sc_flags & SC_CCP_UP) 1304 && slen >= CCP_HDRLEN + CCP_OPT_MINLEN 1305 && slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) { 1306 if (!rcvd) { 1307 /* we're agreeing to send compressed packets. */ 1308 if (sc->sc_xc_state != NULL 1309 && (*sc->sc_xcomp->comp_init) 1310 (sc->sc_xc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, 1311 sc->sc_unit, 0, sc->sc_flags & SC_DEBUG)) { 1312 s = splhigh(); /* XXX IMP ME HARDER */ 1313 sc->sc_flags |= SC_COMP_RUN; 1314 splx(s); 1315 } 1316 } else { 1317 /* peer is agreeing to send compressed packets. */ 1318 if (sc->sc_rc_state != NULL 1319 && (*sc->sc_rcomp->decomp_init) 1320 (sc->sc_rc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, 1321 sc->sc_unit, 0, sc->sc_mru, 1322 sc->sc_flags & SC_DEBUG)) { 1323 s = splhigh(); /* XXX IMP ME HARDER */ 1324 sc->sc_flags |= SC_DECOMP_RUN; 1325 sc->sc_flags &= ~(SC_DC_ERROR | SC_DC_FERROR); 1326 splx(s); 1327 } 1328 } 1329 } 1330 break; 1331 1332 case CCP_RESETACK: 1333 if (sc->sc_flags & SC_CCP_UP) { 1334 if (!rcvd) { 1335 if (sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) 1336 (*sc->sc_xcomp->comp_reset)(sc->sc_xc_state); 1337 } else { 1338 if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) { 1339 (*sc->sc_rcomp->decomp_reset)(sc->sc_rc_state); 1340 s = splhigh(); /* XXX IMP ME HARDER */ 1341 sc->sc_flags &= ~SC_DC_ERROR; 1342 splx(s); 1343 } 1344 } 1345 } 1346 break; 1347 } 1348 } 1349 1350 /* 1351 * CCP is down; free (de)compressor state if necessary. 1352 */ 1353 static void 1354 ppp_ccp_closed(sc) 1355 struct ppp_softc *sc; 1356 { 1357 if (sc->sc_xc_state) { 1358 (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); 1359 sc->sc_xc_state = NULL; 1360 } 1361 if (sc->sc_rc_state) { 1362 (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); 1363 sc->sc_rc_state = NULL; 1364 } 1365 } 1366 #endif /* PPP_COMPRESS */ 1367 1368 /* 1369 * PPP packet input routine. 1370 * The caller has checked and removed the FCS and has inserted 1371 * the address/control bytes and the protocol high byte if they 1372 * were omitted. 1373 */ 1374 void 1375 ppppktin(sc, m, lost) 1376 struct ppp_softc *sc; 1377 struct mbuf *m; 1378 int lost; 1379 { 1380 int s = splhigh(); /* XXX IMP ME HARDER */ 1381 1382 if (lost) 1383 m->m_flags |= M_ERRMARK; 1384 IF_ENQUEUE(&sc->sc_rawq, m); 1385 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 1386 softintr_schedule(sc->sc_si); 1387 #else 1388 schednetisr(NETISR_PPP); 1389 #endif 1390 splx(s); 1391 } 1392 1393 /* 1394 * Process a received PPP packet, doing decompression as necessary. 1395 * Should be called at splsoftnet. 1396 */ 1397 #define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \ 1398 TYPE_UNCOMPRESSED_TCP) 1399 1400 static void 1401 ppp_inproc(sc, m) 1402 struct ppp_softc *sc; 1403 struct mbuf *m; 1404 { 1405 struct ifnet *ifp = &sc->sc_if; 1406 struct ifqueue *inq; 1407 int s, ilen, proto, rv; 1408 u_char *cp, adrs, ctrl; 1409 struct mbuf *mp, *dmp = NULL; 1410 #ifdef VJC 1411 int xlen; 1412 u_char *iphdr; 1413 u_int hlen; 1414 #endif 1415 1416 sc->sc_stats.ppp_ipackets++; 1417 1418 if (sc->sc_flags & SC_LOG_INPKT) { 1419 ilen = 0; 1420 for (mp = m; mp != NULL; mp = mp->m_next) 1421 ilen += mp->m_len; 1422 printf("%s: got %d bytes\n", ifp->if_xname, ilen); 1423 pppdumpm(m); 1424 } 1425 1426 cp = mtod(m, u_char *); 1427 adrs = PPP_ADDRESS(cp); 1428 ctrl = PPP_CONTROL(cp); 1429 proto = PPP_PROTOCOL(cp); 1430 1431 if (m->m_flags & M_ERRMARK) { 1432 m->m_flags &= ~M_ERRMARK; 1433 s = splhigh(); /* XXX IMP ME HARDER */ 1434 sc->sc_flags |= SC_VJ_RESET; 1435 splx(s); 1436 } 1437 1438 #ifdef PPP_COMPRESS 1439 /* 1440 * Decompress this packet if necessary, update the receiver's 1441 * dictionary, or take appropriate action on a CCP packet. 1442 */ 1443 if (proto == PPP_COMP && sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN) 1444 && !(sc->sc_flags & SC_DC_ERROR) && !(sc->sc_flags & SC_DC_FERROR)) { 1445 /* decompress this packet */ 1446 rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp); 1447 if (rv == DECOMP_OK) { 1448 m_freem(m); 1449 if (dmp == NULL) { 1450 /* no error, but no decompressed packet produced */ 1451 return; 1452 } 1453 m = dmp; 1454 cp = mtod(m, u_char *); 1455 proto = PPP_PROTOCOL(cp); 1456 1457 } else { 1458 /* 1459 * An error has occurred in decompression. 1460 * Pass the compressed packet up to pppd, which may take 1461 * CCP down or issue a Reset-Req. 1462 */ 1463 if (sc->sc_flags & SC_DEBUG) 1464 printf("%s: decompress failed %d\n", ifp->if_xname, rv); 1465 s = splhigh(); /* XXX IMP ME HARDER */ 1466 sc->sc_flags |= SC_VJ_RESET; 1467 if (rv == DECOMP_ERROR) 1468 sc->sc_flags |= SC_DC_ERROR; 1469 else 1470 sc->sc_flags |= SC_DC_FERROR; 1471 splx(s); 1472 } 1473 1474 } else { 1475 if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) { 1476 (*sc->sc_rcomp->incomp)(sc->sc_rc_state, m); 1477 } 1478 if (proto == PPP_CCP) { 1479 ppp_ccp(sc, m, 1); 1480 } 1481 } 1482 #endif 1483 1484 ilen = 0; 1485 for (mp = m; mp != NULL; mp = mp->m_next) 1486 ilen += mp->m_len; 1487 1488 #ifdef VJC 1489 if (sc->sc_flags & SC_VJ_RESET) { 1490 /* 1491 * If we've missed a packet, we must toss subsequent compressed 1492 * packets which don't have an explicit connection ID. 1493 */ 1494 if (sc->sc_comp) 1495 sl_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp); 1496 s = splhigh(); /* XXX IMP ME HARDER */ 1497 sc->sc_flags &= ~SC_VJ_RESET; 1498 splx(s); 1499 } 1500 1501 /* 1502 * See if we have a VJ-compressed packet to uncompress. 1503 */ 1504 if (proto == PPP_VJC_COMP) { 1505 if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) 1506 goto bad; 1507 1508 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN, 1509 ilen - PPP_HDRLEN, TYPE_COMPRESSED_TCP, 1510 sc->sc_comp, &iphdr, &hlen); 1511 1512 if (xlen <= 0) { 1513 if (sc->sc_flags & SC_DEBUG) 1514 printf("%s: VJ uncompress failed on type comp\n", 1515 ifp->if_xname); 1516 goto bad; 1517 } 1518 1519 /* Copy the PPP and IP headers into a new mbuf. */ 1520 MGETHDR(mp, M_DONTWAIT, MT_DATA); 1521 if (mp == NULL) 1522 goto bad; 1523 mp->m_len = 0; 1524 mp->m_next = NULL; 1525 if (hlen + PPP_HDRLEN > MHLEN) { 1526 MCLGET(mp, M_DONTWAIT); 1527 if (M_TRAILINGSPACE(mp) < hlen + PPP_HDRLEN) { 1528 m_freem(mp); 1529 goto bad; /* lose if big headers and no clusters */ 1530 } 1531 } 1532 cp = mtod(mp, u_char *); 1533 cp[0] = adrs; 1534 cp[1] = ctrl; 1535 cp[2] = 0; 1536 cp[3] = PPP_IP; 1537 proto = PPP_IP; 1538 bcopy(iphdr, cp + PPP_HDRLEN, hlen); 1539 mp->m_len = hlen + PPP_HDRLEN; 1540 1541 /* 1542 * Trim the PPP and VJ headers off the old mbuf 1543 * and stick the new and old mbufs together. 1544 */ 1545 m->m_data += PPP_HDRLEN + xlen; 1546 m->m_len -= PPP_HDRLEN + xlen; 1547 if (m->m_len <= M_TRAILINGSPACE(mp)) { 1548 bcopy(mtod(m, u_char *), mtod(mp, u_char *) + mp->m_len, m->m_len); 1549 mp->m_len += m->m_len; 1550 MFREE(m, mp->m_next); 1551 } else 1552 mp->m_next = m; 1553 m = mp; 1554 ilen += hlen - xlen; 1555 1556 } else if (proto == PPP_VJC_UNCOMP) { 1557 if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0) 1558 goto bad; 1559 1560 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN, 1561 ilen - PPP_HDRLEN, TYPE_UNCOMPRESSED_TCP, 1562 sc->sc_comp, &iphdr, &hlen); 1563 1564 if (xlen < 0) { 1565 if (sc->sc_flags & SC_DEBUG) 1566 printf("%s: VJ uncompress failed on type uncomp\n", 1567 ifp->if_xname); 1568 goto bad; 1569 } 1570 1571 proto = PPP_IP; 1572 cp[3] = PPP_IP; 1573 } 1574 #endif /* VJC */ 1575 1576 /* 1577 * If the packet will fit in a header mbuf, don't waste a 1578 * whole cluster on it. 1579 */ 1580 if (ilen <= MHLEN && M_IS_CLUSTER(m)) { 1581 MGETHDR(mp, M_DONTWAIT, MT_DATA); 1582 if (mp != NULL) { 1583 m_copydata(m, 0, ilen, mtod(mp, caddr_t)); 1584 m_freem(m); 1585 m = mp; 1586 m->m_len = ilen; 1587 } 1588 } 1589 m->m_pkthdr.len = ilen; 1590 m->m_pkthdr.rcvif = ifp; 1591 1592 if ((proto & 0x8000) == 0) { 1593 #ifdef PPP_FILTER 1594 /* 1595 * See whether we want to pass this packet, and 1596 * if it counts as link activity. 1597 */ 1598 if (sc->sc_pass_filt_in.bf_insns != 0 1599 && bpf_filter(sc->sc_pass_filt_in.bf_insns, (u_char *) m, 1600 ilen, 0) == 0) { 1601 /* drop this packet */ 1602 m_freem(m); 1603 return; 1604 } 1605 if (sc->sc_active_filt_in.bf_insns == 0 1606 || bpf_filter(sc->sc_active_filt_in.bf_insns, (u_char *) m, 1607 ilen, 0)) 1608 sc->sc_last_recv = time.tv_sec; 1609 #else 1610 /* 1611 * Record the time that we received this packet. 1612 */ 1613 sc->sc_last_recv = time.tv_sec; 1614 #endif /* PPP_FILTER */ 1615 } 1616 1617 #if NBPFILTER > 0 1618 /* See if bpf wants to look at the packet. */ 1619 if (sc->sc_if.if_bpf) 1620 bpf_mtap(sc->sc_if.if_bpf, m); 1621 #endif 1622 1623 rv = 0; 1624 switch (proto) { 1625 #ifdef INET 1626 case PPP_IP: 1627 /* 1628 * IP packet - take off the ppp header and pass it up to IP. 1629 */ 1630 if ((ifp->if_flags & IFF_UP) == 0 1631 || sc->sc_npmode[NP_IP] != NPMODE_PASS) { 1632 /* interface is down - drop the packet. */ 1633 m_freem(m); 1634 return; 1635 } 1636 m->m_pkthdr.len -= PPP_HDRLEN; 1637 m->m_data += PPP_HDRLEN; 1638 m->m_len -= PPP_HDRLEN; 1639 #ifdef GATEWAY 1640 if (ipflow_fastforward(m)) 1641 return; 1642 #endif 1643 schednetisr(NETISR_IP); 1644 inq = &ipintrq; 1645 break; 1646 #endif 1647 1648 #ifdef INET6 1649 case PPP_IPV6: 1650 /* 1651 * IPv6 packet - take off the ppp header and pass it up to IPv6. 1652 */ 1653 if ((ifp->if_flags & IFF_UP) == 0 1654 || sc->sc_npmode[NP_IPV6] != NPMODE_PASS) { 1655 /* interface is down - drop the packet. */ 1656 m_freem(m); 1657 return; 1658 } 1659 m->m_pkthdr.len -= PPP_HDRLEN; 1660 m->m_data += PPP_HDRLEN; 1661 m->m_len -= PPP_HDRLEN; 1662 schednetisr(NETISR_IPV6); 1663 inq = &ip6intrq; 1664 break; 1665 #endif 1666 1667 default: 1668 /* 1669 * Some other protocol - place on input queue for read(). 1670 */ 1671 inq = &sc->sc_inq; 1672 rv = 1; 1673 break; 1674 } 1675 1676 /* 1677 * Put the packet on the appropriate input queue. 1678 */ 1679 s = splnet(); 1680 if (IF_QFULL(inq)) { 1681 IF_DROP(inq); 1682 splx(s); 1683 if (sc->sc_flags & SC_DEBUG) 1684 printf("%s: input queue full\n", ifp->if_xname); 1685 ifp->if_iqdrops++; 1686 goto bad; 1687 } 1688 IF_ENQUEUE(inq, m); 1689 splx(s); 1690 ifp->if_ipackets++; 1691 ifp->if_ibytes += ilen; 1692 1693 if (rv) 1694 (*sc->sc_ctlp)(sc); 1695 1696 return; 1697 1698 bad: 1699 m_freem(m); 1700 sc->sc_if.if_ierrors++; 1701 sc->sc_stats.ppp_ierrors++; 1702 } 1703 1704 #define MAX_DUMP_BYTES 128 1705 1706 static void 1707 pppdumpm(m0) 1708 struct mbuf *m0; 1709 { 1710 char buf[3*MAX_DUMP_BYTES+4]; 1711 char *bp = buf; 1712 struct mbuf *m; 1713 static char digits[] = "0123456789abcdef"; 1714 1715 for (m = m0; m; m = m->m_next) { 1716 int l = m->m_len; 1717 u_char *rptr = (u_char *)m->m_data; 1718 1719 while (l--) { 1720 if (bp > buf + sizeof(buf) - 4) 1721 goto done; 1722 *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */ 1723 *bp++ = digits[*rptr++ & 0xf]; 1724 } 1725 1726 if (m->m_next) { 1727 if (bp > buf + sizeof(buf) - 3) 1728 goto done; 1729 *bp++ = '|'; 1730 } else 1731 *bp++ = ' '; 1732 } 1733 done: 1734 if (m) 1735 *bp++ = '>'; 1736 *bp = 0; 1737 printf("%s\n", buf); 1738 } 1739 1740 #ifdef ALTQ 1741 /* 1742 * a wrapper to transmit a packet from if_start since ALTQ uses 1743 * if_start to send a packet. 1744 */ 1745 static void 1746 ppp_ifstart(ifp) 1747 struct ifnet *ifp; 1748 { 1749 struct ppp_softc *sc; 1750 1751 sc = ifp->if_softc; 1752 (*sc->sc_start)(sc); 1753 } 1754 #endif 1755