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