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