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