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