2001-01-17 03:30:49 +03:00
|
|
|
/* $NetBSD: if_ppp.c,v 1.67 2001/01/17 00:30:51 thorpej Exp $ */
|
1997-03-12 23:26:46 +03:00
|
|
|
/* Id: if_ppp.c,v 1.6 1997/03/04 03:33:00 paulus Exp */
|
1994-06-29 10:29:24 +04:00
|
|
|
|
1993-08-14 10:29:28 +04:00
|
|
|
/*
|
|
|
|
* if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver.
|
|
|
|
*
|
|
|
|
* Copyright (c) 1989 Carnegie Mellon University.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms are permitted
|
|
|
|
* provided that the above copyright notice and this paragraph are
|
|
|
|
* duplicated in all such forms and that any documentation,
|
|
|
|
* advertising materials, and other materials related to such
|
|
|
|
* distribution and use acknowledge that the software was developed
|
|
|
|
* by Carnegie Mellon University. The name of the
|
|
|
|
* University may not be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
|
|
|
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
*
|
|
|
|
* Drew D. Perkins
|
|
|
|
* Carnegie Mellon University
|
|
|
|
* 4910 Forbes Ave.
|
|
|
|
* Pittsburgh, PA 15213
|
|
|
|
* (412) 268-8576
|
|
|
|
* ddp@andrew.cmu.edu
|
|
|
|
*
|
|
|
|
* Based on:
|
|
|
|
* @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
|
|
|
|
*
|
|
|
|
* Copyright (c) 1987 Regents of the University of California.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms are permitted
|
|
|
|
* provided that the above copyright notice and this paragraph are
|
|
|
|
* duplicated in all such forms and that any documentation,
|
|
|
|
* advertising materials, and other materials related to such
|
|
|
|
* distribution and use acknowledge that the software was developed
|
|
|
|
* by the University of California, Berkeley. The name of the
|
|
|
|
* University may not be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
|
|
|
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
*
|
|
|
|
* Serial Line interface
|
|
|
|
*
|
|
|
|
* Rick Adams
|
|
|
|
* Center for Seismic Studies
|
|
|
|
* 1300 N 17th Street, Suite 1450
|
|
|
|
* Arlington, Virginia 22209
|
|
|
|
* (703)276-7900
|
|
|
|
* rick@seismo.ARPA
|
|
|
|
* seismo!rick
|
|
|
|
*
|
|
|
|
* Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
|
|
|
|
* Converted to 4.3BSD Beta by Chris Torek.
|
|
|
|
* Other changes made at Berkeley, based in part on code by Kirk Smith.
|
|
|
|
*
|
|
|
|
* Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
|
|
|
|
* Added VJ tcp header compression; more unified ioctls
|
|
|
|
*
|
|
|
|
* Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
|
|
|
|
* Cleaned up a lot of the mbuf-related code to fix bugs that
|
|
|
|
* caused system crashes and packet corruption. Changed pppstart
|
|
|
|
* so that it doesn't just give up with a collision if the whole
|
|
|
|
* packet doesn't fit in the output ring buffer.
|
|
|
|
*
|
1993-08-31 04:05:27 +04:00
|
|
|
* Added priority queueing for interactive IP packets, following
|
|
|
|
* the model of if_sl.c, plus hooks for bpf.
|
|
|
|
* Paul Mackerras (paulus@cs.anu.edu.au).
|
1993-08-14 10:29:28 +04:00
|
|
|
*/
|
|
|
|
|
1993-08-31 04:05:27 +04:00
|
|
|
/* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
|
1995-07-04 10:28:17 +04:00
|
|
|
/* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
|
1993-08-31 04:05:27 +04:00
|
|
|
|
1993-08-14 10:29:28 +04:00
|
|
|
#include "ppp.h"
|
2000-10-04 06:51:18 +04:00
|
|
|
|
1993-08-14 10:29:28 +04:00
|
|
|
#if NPPP > 0
|
|
|
|
|
2000-10-06 08:49:53 +04:00
|
|
|
#include "opt_inet.h"
|
|
|
|
#include "opt_gateway.h"
|
|
|
|
#include "opt_ppp.h"
|
|
|
|
|
2000-10-02 07:54:10 +04:00
|
|
|
#ifdef INET
|
1993-08-14 10:29:28 +04:00
|
|
|
#define VJC
|
2000-10-02 07:54:10 +04:00
|
|
|
#endif
|
1995-07-04 10:28:17 +04:00
|
|
|
#define PPP_COMPRESS
|
1993-08-14 10:29:28 +04:00
|
|
|
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/proc.h>
|
|
|
|
#include <sys/mbuf.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/kernel.h>
|
1996-02-14 00:59:53 +03:00
|
|
|
#include <sys/systm.h>
|
1996-03-15 05:28:00 +03:00
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/malloc.h>
|
1995-07-04 10:28:17 +04:00
|
|
|
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <net/if.h>
|
|
|
|
#include <net/if_types.h>
|
|
|
|
#include <net/netisr.h>
|
|
|
|
#include <net/route.h>
|
1997-03-12 23:26:46 +03:00
|
|
|
#ifdef PPP_FILTER
|
1996-03-15 05:28:00 +03:00
|
|
|
#include <net/bpf.h>
|
1997-03-12 23:26:46 +03:00
|
|
|
#endif
|
1993-08-14 10:29:28 +04:00
|
|
|
|
2001-01-15 19:33:30 +03:00
|
|
|
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
|
|
|
|
#include <machine/intr.h>
|
|
|
|
#endif
|
|
|
|
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <netinet/in_systm.h>
|
|
|
|
#include <netinet/in_var.h>
|
2000-10-02 07:54:10 +04:00
|
|
|
#ifdef INET
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <netinet/ip.h>
|
1993-08-14 10:29:28 +04:00
|
|
|
#endif
|
|
|
|
|
1993-08-31 04:05:27 +04:00
|
|
|
#include "bpfilter.h"
|
|
|
|
#if NBPFILTER > 0
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <sys/time.h>
|
|
|
|
#include <net/bpf.h>
|
1993-08-31 04:05:27 +04:00
|
|
|
#endif
|
|
|
|
|
1998-09-03 18:12:36 +04:00
|
|
|
#if defined(PPP_FILTER) || NBPFILTER > 0
|
|
|
|
#include <net/slip.h>
|
|
|
|
#endif
|
|
|
|
|
1993-08-14 10:29:28 +04:00
|
|
|
#ifdef VJC
|
1994-05-08 16:33:49 +04:00
|
|
|
#include <net/slcompress.h>
|
1993-08-14 10:29:28 +04:00
|
|
|
#endif
|
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
#include <net/ppp_defs.h>
|
1994-05-08 16:33:49 +04:00
|
|
|
#include <net/if_ppp.h>
|
1995-07-04 10:28:17 +04:00
|
|
|
#include <net/if_pppvar.h>
|
1993-12-23 10:36:06 +03:00
|
|
|
#include <machine/cpu.h>
|
1993-08-14 10:29:28 +04:00
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
#ifdef PPP_COMPRESS
|
|
|
|
#define PACKETPTR struct mbuf *
|
|
|
|
#include <net/ppp-comp.h>
|
|
|
|
#endif
|
1993-08-14 10:29:28 +04:00
|
|
|
|
1997-03-12 23:26:46 +03:00
|
|
|
static int pppsioctl __P((struct ifnet *, u_long, caddr_t));
|
1995-07-04 10:28:17 +04:00
|
|
|
static void ppp_requeue __P((struct ppp_softc *));
|
1996-02-14 00:59:53 +03:00
|
|
|
static void ppp_ccp __P((struct ppp_softc *, struct mbuf *m, int rcvd));
|
1995-07-04 10:28:17 +04:00
|
|
|
static void ppp_ccp_closed __P((struct ppp_softc *));
|
|
|
|
static void ppp_inproc __P((struct ppp_softc *, struct mbuf *));
|
|
|
|
static void pppdumpm __P((struct mbuf *m0));
|
1993-08-14 10:29:28 +04:00
|
|
|
|
2001-01-15 19:33:30 +03:00
|
|
|
#ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
|
|
|
|
void pppnetisr(void);
|
|
|
|
#endif
|
|
|
|
void pppintr(void *);
|
|
|
|
|
1993-08-14 10:29:28 +04:00
|
|
|
/*
|
|
|
|
* Some useful mbuf macros not in mbuf.h.
|
|
|
|
*/
|
1995-07-04 10:28:17 +04:00
|
|
|
#define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
|
|
|
|
|
1993-08-14 10:29:28 +04:00
|
|
|
#define M_DATASTART(m) \
|
1995-07-04 10:28:17 +04:00
|
|
|
(M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
|
1993-08-14 10:29:28 +04:00
|
|
|
(m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
|
|
|
|
|
|
|
|
#define M_DATASIZE(m) \
|
1995-07-04 10:28:17 +04:00
|
|
|
(M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
|
1993-08-14 10:29:28 +04:00
|
|
|
(m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
|
|
|
|
|
1993-08-31 04:05:27 +04:00
|
|
|
/*
|
1999-01-10 00:47:09 +03:00
|
|
|
* We define two link layer specific mbuf flags, to mark high-priority
|
|
|
|
* packets for output, and received packets following lost/corrupted
|
|
|
|
* packets.
|
1993-08-31 04:05:27 +04:00
|
|
|
*/
|
1999-01-10 00:47:09 +03:00
|
|
|
#define M_HIGHPRI M_LINK0 /* output packet for sc_fastq */
|
|
|
|
#define M_ERRMARK M_LINK1 /* rx packet following lost/corrupted pkt */
|
1995-07-04 10:28:17 +04:00
|
|
|
|
|
|
|
#ifdef PPP_COMPRESS
|
1993-08-31 04:05:27 +04:00
|
|
|
/*
|
1995-07-04 10:28:17 +04:00
|
|
|
* List of compressors we know about.
|
|
|
|
* We leave some space so maybe we can modload compressors.
|
1993-08-31 04:05:27 +04:00
|
|
|
*/
|
1995-07-04 10:28:17 +04:00
|
|
|
|
|
|
|
extern struct compressor ppp_bsd_compress;
|
1998-05-02 18:34:24 +04:00
|
|
|
extern struct compressor ppp_deflate, ppp_deflate_draft;
|
1995-07-04 10:28:17 +04:00
|
|
|
|
|
|
|
struct compressor *ppp_compressors[8] = {
|
1996-03-19 04:00:49 +03:00
|
|
|
#if DO_BSD_COMPRESS && defined(PPP_BSDCOMP)
|
1995-07-04 10:28:17 +04:00
|
|
|
&ppp_bsd_compress,
|
1996-03-15 05:28:00 +03:00
|
|
|
#endif
|
1996-03-19 04:00:49 +03:00
|
|
|
#if DO_DEFLATE && defined(PPP_DEFLATE)
|
1996-03-15 05:28:00 +03:00
|
|
|
&ppp_deflate,
|
1998-05-02 18:34:24 +04:00
|
|
|
&ppp_deflate_draft,
|
1995-07-04 10:28:17 +04:00
|
|
|
#endif
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
#endif /* PPP_COMPRESS */
|
|
|
|
|
1997-03-12 23:26:46 +03:00
|
|
|
|
1993-08-14 10:29:28 +04:00
|
|
|
/*
|
|
|
|
* Called from boot code to establish ppp interfaces.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
pppattach()
|
|
|
|
{
|
2000-03-30 13:45:33 +04:00
|
|
|
struct ppp_softc *sc;
|
|
|
|
int i = 0;
|
1993-08-14 10:29:28 +04:00
|
|
|
|
|
|
|
for (sc = ppp_softc; i < NPPP; sc++) {
|
1996-05-07 06:40:22 +04:00
|
|
|
sc->sc_unit = i; /* XXX */
|
1996-10-13 06:10:01 +04:00
|
|
|
sprintf(sc->sc_if.if_xname, "ppp%d", i++);
|
2000-03-23 10:01:25 +03:00
|
|
|
callout_init(&sc->sc_timo_ch);
|
1996-05-07 06:40:22 +04:00
|
|
|
sc->sc_if.if_softc = sc;
|
1993-08-14 10:29:28 +04:00
|
|
|
sc->sc_if.if_mtu = PPP_MTU;
|
1996-03-15 05:28:00 +03:00
|
|
|
sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
|
1993-08-14 10:29:28 +04:00
|
|
|
sc->sc_if.if_type = IFT_PPP;
|
1994-01-25 08:56:06 +03:00
|
|
|
sc->sc_if.if_hdrlen = PPP_HDRLEN;
|
2000-12-18 22:44:33 +03:00
|
|
|
sc->sc_if.if_dlt = DLT_NULL;
|
1995-07-04 10:28:17 +04:00
|
|
|
sc->sc_if.if_ioctl = pppsioctl;
|
1993-08-14 10:29:28 +04:00
|
|
|
sc->sc_if.if_output = pppoutput;
|
2000-12-18 21:57:21 +03:00
|
|
|
IFQ_SET_MAXLEN(&sc->sc_if.if_snd, IFQ_MAXLEN);
|
1993-08-14 10:29:28 +04:00
|
|
|
sc->sc_inq.ifq_maxlen = IFQ_MAXLEN;
|
1993-08-31 04:05:27 +04:00
|
|
|
sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN;
|
1995-07-04 10:28:17 +04:00
|
|
|
sc->sc_rawq.ifq_maxlen = IFQ_MAXLEN;
|
2000-12-18 21:57:21 +03:00
|
|
|
IFQ_SET_READY(&sc->sc_if.if_snd);
|
1993-08-14 10:29:28 +04:00
|
|
|
if_attach(&sc->sc_if);
|
2001-01-17 03:30:49 +03:00
|
|
|
if_alloc_sadl(&sc->sc_if);
|
1993-08-31 04:05:27 +04:00
|
|
|
#if NBPFILTER > 0
|
2000-12-12 21:00:22 +03:00
|
|
|
bpfattach(&sc->sc_if, DLT_NULL, 0);
|
1993-08-31 04:05:27 +04:00
|
|
|
#endif
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1994-05-08 16:33:49 +04:00
|
|
|
* Allocate a ppp interface unit and initialize it.
|
|
|
|
*/
|
|
|
|
struct ppp_softc *
|
|
|
|
pppalloc(pid)
|
|
|
|
pid_t pid;
|
|
|
|
{
|
1995-07-04 10:28:17 +04:00
|
|
|
int nppp, i;
|
1994-05-08 16:33:49 +04:00
|
|
|
struct ppp_softc *sc;
|
|
|
|
|
|
|
|
for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
|
|
|
|
if (sc->sc_xfer == pid) {
|
|
|
|
sc->sc_xfer = 0;
|
1995-07-04 10:28:17 +04:00
|
|
|
return sc;
|
1994-05-08 16:33:49 +04:00
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
|
|
|
|
if (sc->sc_devp == NULL)
|
|
|
|
break;
|
1994-05-08 16:33:49 +04:00
|
|
|
if (nppp >= NPPP)
|
|
|
|
return NULL;
|
|
|
|
|
2001-01-15 19:33:30 +03:00
|
|
|
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
|
|
|
|
sc->sc_si = softintr_establish(IPL_SOFTNET, pppintr, sc);
|
|
|
|
if (sc->sc_si == NULL) {
|
|
|
|
printf("ppp%d: unable to establish softintr\n", sc->sc_unit);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
1994-05-08 16:33:49 +04:00
|
|
|
sc->sc_flags = 0;
|
|
|
|
sc->sc_mru = PPP_MRU;
|
1995-07-04 10:28:17 +04:00
|
|
|
sc->sc_relinq = NULL;
|
1996-03-15 05:28:00 +03:00
|
|
|
bzero((char *)&sc->sc_stats, sizeof(sc->sc_stats));
|
1994-05-08 16:33:49 +04:00
|
|
|
#ifdef VJC
|
1996-03-15 05:28:00 +03:00
|
|
|
MALLOC(sc->sc_comp, struct slcompress *, sizeof(struct slcompress),
|
|
|
|
M_DEVBUF, M_NOWAIT);
|
|
|
|
if (sc->sc_comp)
|
1997-05-18 01:11:59 +04:00
|
|
|
sl_compress_init(sc->sc_comp);
|
1994-05-08 16:33:49 +04:00
|
|
|
#endif
|
1995-07-04 10:28:17 +04:00
|
|
|
#ifdef PPP_COMPRESS
|
|
|
|
sc->sc_xc_state = NULL;
|
|
|
|
sc->sc_rc_state = NULL;
|
|
|
|
#endif /* PPP_COMPRESS */
|
|
|
|
for (i = 0; i < NUM_NP; ++i)
|
|
|
|
sc->sc_npmode[i] = NPMODE_ERROR;
|
|
|
|
sc->sc_npqueue = NULL;
|
|
|
|
sc->sc_npqtail = &sc->sc_npqueue;
|
|
|
|
sc->sc_last_sent = sc->sc_last_recv = time.tv_sec;
|
1994-05-08 16:33:49 +04:00
|
|
|
|
|
|
|
return sc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1995-07-04 10:28:17 +04:00
|
|
|
* Deallocate a ppp unit. Must be called at splsoftnet or higher.
|
1994-05-08 16:33:49 +04:00
|
|
|
*/
|
1995-07-04 10:28:17 +04:00
|
|
|
void
|
1994-05-08 16:33:49 +04:00
|
|
|
pppdealloc(sc)
|
|
|
|
struct ppp_softc *sc;
|
|
|
|
{
|
|
|
|
struct mbuf *m;
|
|
|
|
|
2001-01-15 19:33:30 +03:00
|
|
|
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
|
|
|
|
softintr_disestablish(sc->sc_si);
|
|
|
|
#endif
|
1994-05-08 16:33:49 +04:00
|
|
|
if_down(&sc->sc_if);
|
1995-07-04 10:28:17 +04:00
|
|
|
sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
|
1994-05-08 16:33:49 +04:00
|
|
|
sc->sc_devp = NULL;
|
|
|
|
sc->sc_xfer = 0;
|
1995-07-04 10:28:17 +04:00
|
|
|
for (;;) {
|
|
|
|
IF_DEQUEUE(&sc->sc_rawq, m);
|
|
|
|
if (m == NULL)
|
|
|
|
break;
|
|
|
|
m_freem(m);
|
|
|
|
}
|
1994-05-08 16:33:49 +04:00
|
|
|
for (;;) {
|
|
|
|
IF_DEQUEUE(&sc->sc_inq, m);
|
|
|
|
if (m == NULL)
|
|
|
|
break;
|
|
|
|
m_freem(m);
|
|
|
|
}
|
|
|
|
for (;;) {
|
|
|
|
IF_DEQUEUE(&sc->sc_fastq, m);
|
|
|
|
if (m == NULL)
|
|
|
|
break;
|
|
|
|
m_freem(m);
|
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
while ((m = sc->sc_npqueue) != NULL) {
|
|
|
|
sc->sc_npqueue = m->m_nextpkt;
|
|
|
|
m_freem(m);
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
if (sc->sc_togo != NULL) {
|
|
|
|
m_freem(sc->sc_togo);
|
|
|
|
sc->sc_togo = NULL;
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
#ifdef PPP_COMPRESS
|
|
|
|
ppp_ccp_closed(sc);
|
|
|
|
sc->sc_xc_state = NULL;
|
|
|
|
sc->sc_rc_state = NULL;
|
|
|
|
#endif /* PPP_COMPRESS */
|
1997-03-12 23:26:46 +03:00
|
|
|
#ifdef PPP_FILTER
|
1999-05-15 01:33:41 +04:00
|
|
|
if (sc->sc_pass_filt_in.bf_insns != 0) {
|
|
|
|
FREE(sc->sc_pass_filt_in.bf_insns, M_DEVBUF);
|
|
|
|
sc->sc_pass_filt_in.bf_insns = 0;
|
|
|
|
sc->sc_pass_filt_in.bf_len = 0;
|
1996-03-15 05:28:00 +03:00
|
|
|
}
|
1999-05-15 01:33:41 +04:00
|
|
|
if (sc->sc_pass_filt_out.bf_insns != 0) {
|
|
|
|
FREE(sc->sc_pass_filt_out.bf_insns, M_DEVBUF);
|
|
|
|
sc->sc_pass_filt_out.bf_insns = 0;
|
|
|
|
sc->sc_pass_filt_out.bf_len = 0;
|
|
|
|
}
|
|
|
|
if (sc->sc_active_filt_in.bf_insns != 0) {
|
|
|
|
FREE(sc->sc_active_filt_in.bf_insns, M_DEVBUF);
|
|
|
|
sc->sc_active_filt_in.bf_insns = 0;
|
|
|
|
sc->sc_active_filt_in.bf_len = 0;
|
|
|
|
}
|
|
|
|
if (sc->sc_active_filt_out.bf_insns != 0) {
|
|
|
|
FREE(sc->sc_active_filt_out.bf_insns, M_DEVBUF);
|
|
|
|
sc->sc_active_filt_out.bf_insns = 0;
|
|
|
|
sc->sc_active_filt_out.bf_len = 0;
|
1996-03-15 05:28:00 +03:00
|
|
|
}
|
1997-03-12 23:26:46 +03:00
|
|
|
#endif /* PPP_FILTER */
|
1996-03-15 05:28:00 +03:00
|
|
|
#ifdef VJC
|
|
|
|
if (sc->sc_comp != 0) {
|
|
|
|
FREE(sc->sc_comp, M_DEVBUF);
|
|
|
|
sc->sc_comp = 0;
|
|
|
|
}
|
|
|
|
#endif
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1995-07-04 10:28:17 +04:00
|
|
|
* Ioctl routine for generic ppp devices.
|
1993-08-14 10:29:28 +04:00
|
|
|
*/
|
|
|
|
int
|
1995-07-04 10:28:17 +04:00
|
|
|
pppioctl(sc, cmd, data, flag, p)
|
|
|
|
struct ppp_softc *sc;
|
1994-10-31 00:43:03 +03:00
|
|
|
u_long cmd;
|
1993-08-14 10:29:28 +04:00
|
|
|
caddr_t data;
|
1994-10-31 00:43:03 +03:00
|
|
|
int flag;
|
1994-05-08 16:33:49 +04:00
|
|
|
struct proc *p;
|
1993-08-14 10:29:28 +04:00
|
|
|
{
|
1995-07-04 10:28:17 +04:00
|
|
|
int s, error, flags, mru, nb, npx;
|
|
|
|
struct ppp_option_data *odp;
|
|
|
|
struct compressor **cp;
|
|
|
|
struct npioctl *npi;
|
|
|
|
time_t t;
|
1997-03-12 23:26:46 +03:00
|
|
|
#ifdef PPP_FILTER
|
1996-03-15 05:28:00 +03:00
|
|
|
struct bpf_program *bp, *nbp;
|
|
|
|
struct bpf_insn *newcode, *oldcode;
|
|
|
|
int newcodelen;
|
1997-03-12 23:26:46 +03:00
|
|
|
#endif /* PPP_FILTER */
|
1995-07-04 10:28:17 +04:00
|
|
|
#ifdef PPP_COMPRESS
|
|
|
|
u_char ccp_option[CCP_MAX_OPTION_LENGTH];
|
|
|
|
#endif
|
1994-05-08 16:33:49 +04:00
|
|
|
|
1993-08-14 10:29:28 +04:00
|
|
|
switch (cmd) {
|
|
|
|
case FIONREAD:
|
|
|
|
*(int *)data = sc->sc_inq.ifq_len;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PPPIOCGUNIT:
|
1996-05-07 06:40:22 +04:00
|
|
|
*(int *)data = sc->sc_unit; /* XXX */
|
1993-08-14 10:29:28 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PPPIOCGFLAGS:
|
|
|
|
*(u_int *)data = sc->sc_flags;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PPPIOCSFLAGS:
|
1996-02-14 00:59:53 +03:00
|
|
|
if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
|
1993-08-14 10:29:28 +04:00
|
|
|
return (error);
|
1993-08-31 04:05:27 +04:00
|
|
|
flags = *(int *)data & SC_MASK;
|
1995-07-04 10:28:17 +04:00
|
|
|
s = splsoftnet();
|
|
|
|
#ifdef PPP_COMPRESS
|
|
|
|
if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN))
|
|
|
|
ppp_ccp_closed(sc);
|
|
|
|
#endif
|
1997-03-05 00:40:07 +03:00
|
|
|
splimp();
|
1993-08-31 04:05:27 +04:00
|
|
|
sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags;
|
1993-08-14 10:29:28 +04:00
|
|
|
splx(s);
|
|
|
|
break;
|
|
|
|
|
1993-08-31 04:05:27 +04:00
|
|
|
case PPPIOCSMRU:
|
1996-02-14 00:59:53 +03:00
|
|
|
if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
|
1993-08-31 04:05:27 +04:00
|
|
|
return (error);
|
|
|
|
mru = *(int *)data;
|
2000-10-26 05:26:15 +04:00
|
|
|
if (mru >= PPP_MINMRU && mru <= PPP_MAXMRU)
|
1993-08-31 04:05:27 +04:00
|
|
|
sc->sc_mru = mru;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PPPIOCGMRU:
|
|
|
|
*(int *)data = sc->sc_mru;
|
|
|
|
break;
|
|
|
|
|
1994-05-08 16:33:49 +04:00
|
|
|
#ifdef VJC
|
|
|
|
case PPPIOCSMAXCID:
|
1996-02-14 00:59:53 +03:00
|
|
|
if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
|
1994-05-08 16:33:49 +04:00
|
|
|
return (error);
|
1996-03-15 05:28:00 +03:00
|
|
|
if (sc->sc_comp) {
|
|
|
|
s = splsoftnet();
|
1997-06-16 21:01:36 +04:00
|
|
|
sl_compress_setup(sc->sc_comp, *(int *)data);
|
1996-03-15 05:28:00 +03:00
|
|
|
splx(s);
|
|
|
|
}
|
1994-05-08 16:33:49 +04:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
case PPPIOCXFERUNIT:
|
1996-02-14 00:59:53 +03:00
|
|
|
if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
|
1994-05-08 16:33:49 +04:00
|
|
|
return (error);
|
|
|
|
sc->sc_xfer = p->p_pid;
|
|
|
|
break;
|
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
#ifdef PPP_COMPRESS
|
|
|
|
case PPPIOCSCOMPRESS:
|
1996-02-14 00:59:53 +03:00
|
|
|
if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
|
1995-07-04 10:28:17 +04:00
|
|
|
return (error);
|
|
|
|
odp = (struct ppp_option_data *) data;
|
|
|
|
nb = odp->length;
|
|
|
|
if (nb > sizeof(ccp_option))
|
|
|
|
nb = sizeof(ccp_option);
|
1996-02-14 00:59:53 +03:00
|
|
|
if ((error = copyin(odp->ptr, ccp_option, nb)) != 0)
|
1995-07-04 10:28:17 +04:00
|
|
|
return (error);
|
|
|
|
if (ccp_option[1] < 2) /* preliminary check on the length byte */
|
|
|
|
return (EINVAL);
|
|
|
|
for (cp = ppp_compressors; *cp != NULL; ++cp)
|
|
|
|
if ((*cp)->compress_proto == ccp_option[0]) {
|
|
|
|
/*
|
|
|
|
* Found a handler for the protocol - try to allocate
|
|
|
|
* a compressor or decompressor.
|
|
|
|
*/
|
|
|
|
error = 0;
|
|
|
|
if (odp->transmit) {
|
|
|
|
s = splsoftnet();
|
|
|
|
if (sc->sc_xc_state != NULL)
|
|
|
|
(*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
|
|
|
|
sc->sc_xcomp = *cp;
|
|
|
|
sc->sc_xc_state = (*cp)->comp_alloc(ccp_option, nb);
|
|
|
|
if (sc->sc_xc_state == NULL) {
|
|
|
|
if (sc->sc_flags & SC_DEBUG)
|
1996-10-13 06:10:01 +04:00
|
|
|
printf("%s: comp_alloc failed\n",
|
1996-10-11 02:59:41 +04:00
|
|
|
sc->sc_if.if_xname);
|
1995-07-04 10:28:17 +04:00
|
|
|
error = ENOBUFS;
|
|
|
|
}
|
1997-03-05 00:40:07 +03:00
|
|
|
splimp();
|
1995-07-04 10:28:17 +04:00
|
|
|
sc->sc_flags &= ~SC_COMP_RUN;
|
|
|
|
splx(s);
|
|
|
|
} else {
|
|
|
|
s = splsoftnet();
|
|
|
|
if (sc->sc_rc_state != NULL)
|
|
|
|
(*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
|
|
|
|
sc->sc_rcomp = *cp;
|
|
|
|
sc->sc_rc_state = (*cp)->decomp_alloc(ccp_option, nb);
|
|
|
|
if (sc->sc_rc_state == NULL) {
|
|
|
|
if (sc->sc_flags & SC_DEBUG)
|
1996-10-13 06:10:01 +04:00
|
|
|
printf("%s: decomp_alloc failed\n",
|
1996-10-11 02:59:41 +04:00
|
|
|
sc->sc_if.if_xname);
|
1995-07-04 10:28:17 +04:00
|
|
|
error = ENOBUFS;
|
|
|
|
}
|
1997-03-05 00:40:07 +03:00
|
|
|
splimp();
|
1995-07-04 10:28:17 +04:00
|
|
|
sc->sc_flags &= ~SC_DECOMP_RUN;
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
if (sc->sc_flags & SC_DEBUG)
|
1996-10-13 06:10:01 +04:00
|
|
|
printf("%s: no compressor for [%x %x %x], %x\n",
|
1996-10-11 02:59:41 +04:00
|
|
|
sc->sc_if.if_xname, ccp_option[0], ccp_option[1],
|
|
|
|
ccp_option[2], nb);
|
1995-07-04 10:28:17 +04:00
|
|
|
return (EINVAL); /* no handler found */
|
|
|
|
#endif /* PPP_COMPRESS */
|
|
|
|
|
|
|
|
case PPPIOCGNPMODE:
|
|
|
|
case PPPIOCSNPMODE:
|
|
|
|
npi = (struct npioctl *) data;
|
|
|
|
switch (npi->protocol) {
|
|
|
|
case PPP_IP:
|
|
|
|
npx = NP_IP;
|
|
|
|
break;
|
1999-07-30 14:35:34 +04:00
|
|
|
case PPP_IPV6:
|
|
|
|
npx = NP_IPV6;
|
|
|
|
break;
|
1995-07-04 10:28:17 +04:00
|
|
|
default:
|
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
if (cmd == PPPIOCGNPMODE) {
|
|
|
|
npi->mode = sc->sc_npmode[npx];
|
|
|
|
} else {
|
1996-02-14 00:59:53 +03:00
|
|
|
if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
|
1995-07-04 10:28:17 +04:00
|
|
|
return (error);
|
|
|
|
if (npi->mode != sc->sc_npmode[npx]) {
|
1998-07-08 22:05:48 +04:00
|
|
|
s = splimp();
|
1995-07-04 10:28:17 +04:00
|
|
|
sc->sc_npmode[npx] = npi->mode;
|
|
|
|
if (npi->mode != NPMODE_QUEUE) {
|
|
|
|
ppp_requeue(sc);
|
1998-07-08 22:05:48 +04:00
|
|
|
ppp_restart(sc);
|
1995-07-04 10:28:17 +04:00
|
|
|
}
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PPPIOCGIDLE:
|
|
|
|
s = splsoftnet();
|
|
|
|
t = time.tv_sec;
|
|
|
|
((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent;
|
|
|
|
((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv;
|
|
|
|
splx(s);
|
|
|
|
break;
|
|
|
|
|
1997-03-12 23:26:46 +03:00
|
|
|
#ifdef PPP_FILTER
|
1996-03-15 05:28:00 +03:00
|
|
|
case PPPIOCSPASS:
|
|
|
|
case PPPIOCSACTIVE:
|
Decouple inbound and outbound filters. Now instead of using "active-filter"
and "pass-filter" and "inbound" and "outbound" qualifiers in the filter
expression, use new "active-filter-in", "active-filter-out", "pass-filter-in",
and "pass-filter-out" without these qualifiers.
This is necessary due to the horrible, awful way "inbound" and "outbound"
were specified for the filter programs when a packet was passed through them.
Basically, the "address" byte in the serial PPP header was overwritten with
a value to indicate the direction. However, the "address" byte doesn't even
exist on PPP headers for all other PPP encaps! So, this old method worked
only for serial encaps, and corrupted packets for all others (PPPoE, ATM, etc.)
1999-05-12 22:50:51 +04:00
|
|
|
/* These are no longer supported. */
|
|
|
|
return EOPNOTSUPP;
|
|
|
|
|
|
|
|
case PPPIOCSIPASS:
|
|
|
|
case PPPIOCSOPASS:
|
|
|
|
case PPPIOCSIACTIVE:
|
|
|
|
case PPPIOCSOACTIVE:
|
1996-03-15 05:28:00 +03:00
|
|
|
nbp = (struct bpf_program *) data;
|
|
|
|
if ((unsigned) nbp->bf_len > BPF_MAXINSNS)
|
|
|
|
return EINVAL;
|
|
|
|
newcodelen = nbp->bf_len * sizeof(struct bpf_insn);
|
|
|
|
if (newcodelen != 0) {
|
Decouple inbound and outbound filters. Now instead of using "active-filter"
and "pass-filter" and "inbound" and "outbound" qualifiers in the filter
expression, use new "active-filter-in", "active-filter-out", "pass-filter-in",
and "pass-filter-out" without these qualifiers.
This is necessary due to the horrible, awful way "inbound" and "outbound"
were specified for the filter programs when a packet was passed through them.
Basically, the "address" byte in the serial PPP header was overwritten with
a value to indicate the direction. However, the "address" byte doesn't even
exist on PPP headers for all other PPP encaps! So, this old method worked
only for serial encaps, and corrupted packets for all others (PPPoE, ATM, etc.)
1999-05-12 22:50:51 +04:00
|
|
|
newcode = malloc(newcodelen, M_DEVBUF, M_WAITOK);
|
|
|
|
/* WAITOK -- malloc() never fails. */
|
1996-03-15 05:28:00 +03:00
|
|
|
if ((error = copyin((caddr_t)nbp->bf_insns, (caddr_t)newcode,
|
|
|
|
newcodelen)) != 0) {
|
Decouple inbound and outbound filters. Now instead of using "active-filter"
and "pass-filter" and "inbound" and "outbound" qualifiers in the filter
expression, use new "active-filter-in", "active-filter-out", "pass-filter-in",
and "pass-filter-out" without these qualifiers.
This is necessary due to the horrible, awful way "inbound" and "outbound"
were specified for the filter programs when a packet was passed through them.
Basically, the "address" byte in the serial PPP header was overwritten with
a value to indicate the direction. However, the "address" byte doesn't even
exist on PPP headers for all other PPP encaps! So, this old method worked
only for serial encaps, and corrupted packets for all others (PPPoE, ATM, etc.)
1999-05-12 22:50:51 +04:00
|
|
|
free(newcode, M_DEVBUF);
|
1996-03-15 05:28:00 +03:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
if (!bpf_validate(newcode, nbp->bf_len)) {
|
Decouple inbound and outbound filters. Now instead of using "active-filter"
and "pass-filter" and "inbound" and "outbound" qualifiers in the filter
expression, use new "active-filter-in", "active-filter-out", "pass-filter-in",
and "pass-filter-out" without these qualifiers.
This is necessary due to the horrible, awful way "inbound" and "outbound"
were specified for the filter programs when a packet was passed through them.
Basically, the "address" byte in the serial PPP header was overwritten with
a value to indicate the direction. However, the "address" byte doesn't even
exist on PPP headers for all other PPP encaps! So, this old method worked
only for serial encaps, and corrupted packets for all others (PPPoE, ATM, etc.)
1999-05-12 22:50:51 +04:00
|
|
|
free(newcode, M_DEVBUF);
|
1996-03-15 05:28:00 +03:00
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
newcode = 0;
|
Decouple inbound and outbound filters. Now instead of using "active-filter"
and "pass-filter" and "inbound" and "outbound" qualifiers in the filter
expression, use new "active-filter-in", "active-filter-out", "pass-filter-in",
and "pass-filter-out" without these qualifiers.
This is necessary due to the horrible, awful way "inbound" and "outbound"
were specified for the filter programs when a packet was passed through them.
Basically, the "address" byte in the serial PPP header was overwritten with
a value to indicate the direction. However, the "address" byte doesn't even
exist on PPP headers for all other PPP encaps! So, this old method worked
only for serial encaps, and corrupted packets for all others (PPPoE, ATM, etc.)
1999-05-12 22:50:51 +04:00
|
|
|
switch (cmd) {
|
|
|
|
case PPPIOCSIPASS:
|
|
|
|
bp = &sc->sc_pass_filt_in;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PPPIOCSOPASS:
|
|
|
|
bp = &sc->sc_pass_filt_out;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PPPIOCSIACTIVE:
|
|
|
|
bp = &sc->sc_active_filt_in;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PPPIOCSOACTIVE:
|
|
|
|
bp = &sc->sc_active_filt_out;
|
|
|
|
break;
|
|
|
|
}
|
1996-03-15 05:28:00 +03:00
|
|
|
oldcode = bp->bf_insns;
|
|
|
|
s = splimp();
|
|
|
|
bp->bf_len = nbp->bf_len;
|
|
|
|
bp->bf_insns = newcode;
|
|
|
|
splx(s);
|
|
|
|
if (oldcode != 0)
|
Decouple inbound and outbound filters. Now instead of using "active-filter"
and "pass-filter" and "inbound" and "outbound" qualifiers in the filter
expression, use new "active-filter-in", "active-filter-out", "pass-filter-in",
and "pass-filter-out" without these qualifiers.
This is necessary due to the horrible, awful way "inbound" and "outbound"
were specified for the filter programs when a packet was passed through them.
Basically, the "address" byte in the serial PPP header was overwritten with
a value to indicate the direction. However, the "address" byte doesn't even
exist on PPP headers for all other PPP encaps! So, this old method worked
only for serial encaps, and corrupted packets for all others (PPPoE, ATM, etc.)
1999-05-12 22:50:51 +04:00
|
|
|
free(oldcode, M_DEVBUF);
|
1996-03-15 05:28:00 +03:00
|
|
|
break;
|
Decouple inbound and outbound filters. Now instead of using "active-filter"
and "pass-filter" and "inbound" and "outbound" qualifiers in the filter
expression, use new "active-filter-in", "active-filter-out", "pass-filter-in",
and "pass-filter-out" without these qualifiers.
This is necessary due to the horrible, awful way "inbound" and "outbound"
were specified for the filter programs when a packet was passed through them.
Basically, the "address" byte in the serial PPP header was overwritten with
a value to indicate the direction. However, the "address" byte doesn't even
exist on PPP headers for all other PPP encaps! So, this old method worked
only for serial encaps, and corrupted packets for all others (PPPoE, ATM, etc.)
1999-05-12 22:50:51 +04:00
|
|
|
#endif /* PPP_FILTER */
|
1996-03-15 05:28:00 +03:00
|
|
|
|
1993-08-14 10:29:28 +04:00
|
|
|
default:
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1995-07-04 10:28:17 +04:00
|
|
|
* Process an ioctl request to the ppp network interface.
|
1993-08-14 10:29:28 +04:00
|
|
|
*/
|
1997-03-12 23:26:46 +03:00
|
|
|
static int
|
1995-07-04 10:28:17 +04:00
|
|
|
pppsioctl(ifp, cmd, data)
|
2000-03-30 13:45:33 +04:00
|
|
|
struct ifnet *ifp;
|
1995-07-04 10:28:17 +04:00
|
|
|
u_long cmd;
|
|
|
|
caddr_t data;
|
1993-08-14 10:29:28 +04:00
|
|
|
{
|
2000-03-30 13:45:33 +04:00
|
|
|
struct proc *p = curproc; /* XXX */
|
|
|
|
struct ppp_softc *sc = ifp->if_softc;
|
|
|
|
struct ifaddr *ifa = (struct ifaddr *)data;
|
|
|
|
struct ifreq *ifr = (struct ifreq *)data;
|
1995-07-04 10:28:17 +04:00
|
|
|
struct ppp_stats *psp;
|
|
|
|
#ifdef PPP_COMPRESS
|
|
|
|
struct ppp_comp_stats *pcp;
|
|
|
|
#endif
|
|
|
|
int s = splimp(), error = 0;
|
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case SIOCSIFFLAGS:
|
|
|
|
if ((ifp->if_flags & IFF_RUNNING) == 0)
|
|
|
|
ifp->if_flags &= ~IFF_UP;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SIOCSIFADDR:
|
1999-07-30 14:35:34 +04:00
|
|
|
switch (ifa->ifa_addr->sa_family) {
|
|
|
|
#ifdef INET
|
|
|
|
case AF_INET:
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
1998-12-10 20:48:40 +03:00
|
|
|
error = EAFNOSUPPORT;
|
1999-07-30 14:35:34 +04:00
|
|
|
break;
|
|
|
|
}
|
1998-12-10 20:48:40 +03:00
|
|
|
break;
|
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
case SIOCSIFDSTADDR:
|
1999-07-30 14:35:34 +04:00
|
|
|
switch (ifa->ifa_addr->sa_family) {
|
|
|
|
#ifdef INET
|
|
|
|
case AF_INET:
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
1995-07-04 10:28:17 +04:00
|
|
|
error = EAFNOSUPPORT;
|
1999-07-30 14:35:34 +04:00
|
|
|
break;
|
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SIOCSIFMTU:
|
1997-03-12 23:26:46 +03:00
|
|
|
if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
|
|
|
|
break;
|
1995-07-04 10:28:17 +04:00
|
|
|
sc->sc_if.if_mtu = ifr->ifr_mtu;
|
|
|
|
break;
|
|
|
|
|
1997-03-12 23:26:46 +03:00
|
|
|
case SIOCGIFMTU:
|
|
|
|
ifr->ifr_mtu = sc->sc_if.if_mtu;
|
|
|
|
break;
|
|
|
|
|
1996-03-15 05:28:00 +03:00
|
|
|
case SIOCADDMULTI:
|
|
|
|
case SIOCDELMULTI:
|
|
|
|
if (ifr == 0) {
|
|
|
|
error = EAFNOSUPPORT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch(ifr->ifr_addr.sa_family) {
|
|
|
|
#ifdef INET
|
|
|
|
case AF_INET:
|
|
|
|
break;
|
1999-07-30 14:35:34 +04:00
|
|
|
#endif
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
|
|
|
break;
|
1996-03-15 05:28:00 +03:00
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
error = EAFNOSUPPORT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
case SIOCGPPPSTATS:
|
|
|
|
psp = &((struct ifpppstatsreq *) data)->stats;
|
|
|
|
bzero(psp, sizeof(*psp));
|
1996-03-15 05:28:00 +03:00
|
|
|
psp->p = sc->sc_stats;
|
|
|
|
#if defined(VJC) && !defined(SL_NO_STATS)
|
|
|
|
if (sc->sc_comp) {
|
|
|
|
psp->vj.vjs_packets = sc->sc_comp->sls_packets;
|
|
|
|
psp->vj.vjs_compressed = sc->sc_comp->sls_compressed;
|
|
|
|
psp->vj.vjs_searches = sc->sc_comp->sls_searches;
|
|
|
|
psp->vj.vjs_misses = sc->sc_comp->sls_misses;
|
|
|
|
psp->vj.vjs_uncompressedin = sc->sc_comp->sls_uncompressedin;
|
|
|
|
psp->vj.vjs_compressedin = sc->sc_comp->sls_compressedin;
|
|
|
|
psp->vj.vjs_errorin = sc->sc_comp->sls_errorin;
|
|
|
|
psp->vj.vjs_tossed = sc->sc_comp->sls_tossed;
|
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
#endif /* VJC */
|
|
|
|
break;
|
|
|
|
|
|
|
|
#ifdef PPP_COMPRESS
|
|
|
|
case SIOCGPPPCSTATS:
|
|
|
|
pcp = &((struct ifpppcstatsreq *) data)->stats;
|
|
|
|
bzero(pcp, sizeof(*pcp));
|
|
|
|
if (sc->sc_xc_state != NULL)
|
|
|
|
(*sc->sc_xcomp->comp_stat)(sc->sc_xc_state, &pcp->c);
|
|
|
|
if (sc->sc_rc_state != NULL)
|
|
|
|
(*sc->sc_rcomp->decomp_stat)(sc->sc_rc_state, &pcp->d);
|
|
|
|
break;
|
|
|
|
#endif /* PPP_COMPRESS */
|
|
|
|
|
|
|
|
default:
|
|
|
|
error = EINVAL;
|
|
|
|
}
|
|
|
|
splx(s);
|
|
|
|
return (error);
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Queue a packet. Start transmission if not active.
|
|
|
|
* Packet is placed in Information field of PPP frame.
|
|
|
|
*/
|
|
|
|
int
|
1994-05-13 10:02:48 +04:00
|
|
|
pppoutput(ifp, m0, dst, rtp)
|
1993-08-14 10:29:28 +04:00
|
|
|
struct ifnet *ifp;
|
|
|
|
struct mbuf *m0;
|
|
|
|
struct sockaddr *dst;
|
1994-05-13 10:02:48 +04:00
|
|
|
struct rtentry *rtp;
|
1993-08-14 10:29:28 +04:00
|
|
|
{
|
2000-03-30 13:45:33 +04:00
|
|
|
struct ppp_softc *sc = ifp->if_softc;
|
1993-08-31 04:05:27 +04:00
|
|
|
int protocol, address, control;
|
|
|
|
u_char *cp;
|
|
|
|
int s, error;
|
2000-10-02 07:54:10 +04:00
|
|
|
#ifdef INET
|
1993-08-31 04:05:27 +04:00
|
|
|
struct ip *ip;
|
2000-10-02 07:54:10 +04:00
|
|
|
#endif
|
1993-08-31 04:05:27 +04:00
|
|
|
struct ifqueue *ifq;
|
1995-07-04 10:28:17 +04:00
|
|
|
enum NPmode mode;
|
1997-03-12 23:26:46 +03:00
|
|
|
int len;
|
1996-03-15 05:28:00 +03:00
|
|
|
struct mbuf *m;
|
2000-12-18 21:57:21 +03:00
|
|
|
ALTQ_DECL(struct altq_pktattr pktattr;)
|
1993-08-14 10:29:28 +04:00
|
|
|
|
1994-05-08 16:33:49 +04:00
|
|
|
if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0
|
1996-02-14 00:59:53 +03:00
|
|
|
|| ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) {
|
1993-08-14 10:29:28 +04:00
|
|
|
error = ENETDOWN; /* sort of */
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
2000-12-18 21:57:21 +03:00
|
|
|
IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family, &pktattr);
|
|
|
|
|
1993-08-14 10:29:28 +04:00
|
|
|
/*
|
|
|
|
* Compute PPP header.
|
|
|
|
*/
|
1995-07-04 10:28:17 +04:00
|
|
|
m0->m_flags &= ~M_HIGHPRI;
|
1993-08-14 10:29:28 +04:00
|
|
|
switch (dst->sa_family) {
|
|
|
|
#ifdef INET
|
|
|
|
case AF_INET:
|
1995-07-04 10:28:17 +04:00
|
|
|
address = PPP_ALLSTATIONS;
|
|
|
|
control = PPP_UI;
|
1993-08-14 10:29:28 +04:00
|
|
|
protocol = PPP_IP;
|
1995-07-04 10:28:17 +04:00
|
|
|
mode = sc->sc_npmode[NP_IP];
|
|
|
|
|
1993-08-31 04:05:27 +04:00
|
|
|
/*
|
1995-07-04 10:28:17 +04:00
|
|
|
* If this packet has the "low delay" bit set in the IP header,
|
|
|
|
* put it on the fastq instead.
|
1993-08-31 04:05:27 +04:00
|
|
|
*/
|
1995-07-04 10:28:17 +04:00
|
|
|
ip = mtod(m0, struct ip *);
|
|
|
|
if (ip->ip_tos & IPTOS_LOWDELAY)
|
|
|
|
m0->m_flags |= M_HIGHPRI;
|
1993-08-14 10:29:28 +04:00
|
|
|
break;
|
1999-07-30 14:35:34 +04:00
|
|
|
#endif
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
|
|
|
address = PPP_ALLSTATIONS; /*XXX*/
|
|
|
|
control = PPP_UI; /*XXX*/
|
|
|
|
protocol = PPP_IPV6;
|
|
|
|
mode = sc->sc_npmode[NP_IPV6];
|
|
|
|
|
|
|
|
#if 0 /* XXX flowinfo/traffic class, maybe? */
|
|
|
|
/*
|
|
|
|
* If this packet has the "low delay" bit set in the IP header,
|
|
|
|
* put it on the fastq instead.
|
|
|
|
*/
|
|
|
|
ip = mtod(m0, struct ip *);
|
|
|
|
if (ip->ip_tos & IPTOS_LOWDELAY)
|
|
|
|
m0->m_flags |= M_HIGHPRI;
|
|
|
|
#endif
|
1999-11-27 21:45:08 +03:00
|
|
|
break;
|
1993-08-14 10:29:28 +04:00
|
|
|
#endif
|
|
|
|
case AF_UNSPEC:
|
1995-07-04 10:28:17 +04:00
|
|
|
address = PPP_ADDRESS(dst->sa_data);
|
|
|
|
control = PPP_CONTROL(dst->sa_data);
|
|
|
|
protocol = PPP_PROTOCOL(dst->sa_data);
|
|
|
|
mode = NPMODE_PASS;
|
1993-08-14 10:29:28 +04:00
|
|
|
break;
|
|
|
|
default:
|
1996-10-13 06:10:01 +04:00
|
|
|
printf("%s: af%d not supported\n", ifp->if_xname, dst->sa_family);
|
1993-08-14 10:29:28 +04:00
|
|
|
error = EAFNOSUPPORT;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
/*
|
|
|
|
* Drop this packet, or return an error, if necessary.
|
|
|
|
*/
|
|
|
|
if (mode == NPMODE_ERROR) {
|
|
|
|
error = ENETDOWN;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
if (mode == NPMODE_DROP) {
|
|
|
|
error = 0;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
1993-08-14 10:29:28 +04:00
|
|
|
/*
|
|
|
|
* Add PPP header. If no space in first mbuf, allocate another.
|
1993-08-31 04:05:27 +04:00
|
|
|
* (This assumes M_LEADINGSPACE is always 0 for a cluster mbuf.)
|
1993-08-14 10:29:28 +04:00
|
|
|
*/
|
1994-01-25 08:56:06 +03:00
|
|
|
if (M_LEADINGSPACE(m0) < PPP_HDRLEN) {
|
|
|
|
m0 = m_prepend(m0, PPP_HDRLEN, M_DONTWAIT);
|
1993-08-14 10:29:28 +04:00
|
|
|
if (m0 == 0) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
m0->m_len = 0;
|
|
|
|
} else
|
1994-01-25 08:56:06 +03:00
|
|
|
m0->m_data -= PPP_HDRLEN;
|
1993-08-14 10:29:28 +04:00
|
|
|
|
|
|
|
cp = mtod(m0, u_char *);
|
1993-08-31 04:05:27 +04:00
|
|
|
*cp++ = address;
|
|
|
|
*cp++ = control;
|
|
|
|
*cp++ = protocol >> 8;
|
1993-08-14 10:29:28 +04:00
|
|
|
*cp++ = protocol & 0xff;
|
1994-01-25 08:56:06 +03:00
|
|
|
m0->m_len += PPP_HDRLEN;
|
1993-08-14 10:29:28 +04:00
|
|
|
|
1996-03-15 05:28:00 +03:00
|
|
|
len = 0;
|
|
|
|
for (m = m0; m != 0; m = m->m_next)
|
|
|
|
len += m->m_len;
|
|
|
|
|
1994-05-08 16:33:49 +04:00
|
|
|
if (sc->sc_flags & SC_LOG_OUTPKT) {
|
1996-10-13 06:10:01 +04:00
|
|
|
printf("%s output: ", ifp->if_xname);
|
1995-07-04 10:28:17 +04:00
|
|
|
pppdumpm(m0);
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
|
|
|
|
1996-03-15 05:28:00 +03:00
|
|
|
if ((protocol & 0x8000) == 0) {
|
1997-03-12 23:26:46 +03:00
|
|
|
#ifdef PPP_FILTER
|
|
|
|
/*
|
|
|
|
* Apply the pass and active filters to the packet,
|
|
|
|
* but only if it is a data packet.
|
|
|
|
*/
|
Decouple inbound and outbound filters. Now instead of using "active-filter"
and "pass-filter" and "inbound" and "outbound" qualifiers in the filter
expression, use new "active-filter-in", "active-filter-out", "pass-filter-in",
and "pass-filter-out" without these qualifiers.
This is necessary due to the horrible, awful way "inbound" and "outbound"
were specified for the filter programs when a packet was passed through them.
Basically, the "address" byte in the serial PPP header was overwritten with
a value to indicate the direction. However, the "address" byte doesn't even
exist on PPP headers for all other PPP encaps! So, this old method worked
only for serial encaps, and corrupted packets for all others (PPPoE, ATM, etc.)
1999-05-12 22:50:51 +04:00
|
|
|
if (sc->sc_pass_filt_out.bf_insns != 0
|
|
|
|
&& bpf_filter(sc->sc_pass_filt_out.bf_insns, (u_char *) m0,
|
1996-03-15 05:28:00 +03:00
|
|
|
len, 0) == 0) {
|
|
|
|
error = 0; /* drop this packet */
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Update the time we sent the most recent packet.
|
|
|
|
*/
|
Decouple inbound and outbound filters. Now instead of using "active-filter"
and "pass-filter" and "inbound" and "outbound" qualifiers in the filter
expression, use new "active-filter-in", "active-filter-out", "pass-filter-in",
and "pass-filter-out" without these qualifiers.
This is necessary due to the horrible, awful way "inbound" and "outbound"
were specified for the filter programs when a packet was passed through them.
Basically, the "address" byte in the serial PPP header was overwritten with
a value to indicate the direction. However, the "address" byte doesn't even
exist on PPP headers for all other PPP encaps! So, this old method worked
only for serial encaps, and corrupted packets for all others (PPPoE, ATM, etc.)
1999-05-12 22:50:51 +04:00
|
|
|
if (sc->sc_active_filt_out.bf_insns == 0
|
|
|
|
|| bpf_filter(sc->sc_active_filt_out.bf_insns, (u_char *) m0,
|
|
|
|
len, 0))
|
1996-03-15 05:28:00 +03:00
|
|
|
sc->sc_last_sent = time.tv_sec;
|
1997-03-12 23:26:46 +03:00
|
|
|
#else
|
|
|
|
/*
|
|
|
|
* Update the time we sent the most recent packet.
|
|
|
|
*/
|
|
|
|
sc->sc_last_sent = time.tv_sec;
|
|
|
|
#endif /* PPP_FILTER */
|
1996-03-15 05:28:00 +03:00
|
|
|
}
|
|
|
|
|
1993-08-31 04:05:27 +04:00
|
|
|
#if NBPFILTER > 0
|
1995-07-04 10:28:17 +04:00
|
|
|
/*
|
|
|
|
* See if bpf wants to look at the packet.
|
|
|
|
*/
|
2000-12-12 21:00:22 +03:00
|
|
|
if (sc->sc_if.if_bpf)
|
|
|
|
bpf_mtap(sc->sc_if.if_bpf, m0);
|
1993-08-31 04:05:27 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Put the packet on the appropriate queue.
|
|
|
|
*/
|
1998-07-08 22:05:48 +04:00
|
|
|
s = splimp();
|
1995-07-04 10:28:17 +04:00
|
|
|
if (mode == NPMODE_QUEUE) {
|
|
|
|
/* XXX we should limit the number of packets on this queue */
|
|
|
|
*sc->sc_npqtail = m0;
|
|
|
|
m0->m_nextpkt = NULL;
|
|
|
|
sc->sc_npqtail = &m0->m_nextpkt;
|
|
|
|
} else {
|
2000-12-18 21:57:21 +03:00
|
|
|
if ((m0->m_flags & M_HIGHPRI)
|
|
|
|
#ifdef ALTQ
|
|
|
|
&& ALTQ_IS_ENABLED(&sc->sc_if.if_snd) == 0
|
|
|
|
#endif
|
|
|
|
) {
|
|
|
|
ifq = &sc->sc_fastq;
|
|
|
|
if (IF_QFULL(ifq) && dst->sa_family != AF_UNSPEC) {
|
|
|
|
IF_DROP(ifq);
|
|
|
|
splx(s);
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto bad;
|
|
|
|
} else {
|
|
|
|
IF_ENQUEUE(ifq, m0);
|
|
|
|
error = 0;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
IFQ_ENQUEUE(&sc->sc_if.if_snd, m0, &pktattr, error);
|
|
|
|
if (error) {
|
1995-07-04 10:28:17 +04:00
|
|
|
splx(s);
|
|
|
|
sc->sc_if.if_oerrors++;
|
1996-03-15 05:28:00 +03:00
|
|
|
sc->sc_stats.ppp_oerrors++;
|
2000-12-18 21:57:21 +03:00
|
|
|
return (error);
|
1995-07-04 10:28:17 +04:00
|
|
|
}
|
1998-07-08 22:05:48 +04:00
|
|
|
ppp_restart(sc);
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
1995-10-05 08:55:09 +03:00
|
|
|
ifp->if_lastchange = time;
|
1996-03-15 05:28:00 +03:00
|
|
|
ifp->if_opackets++;
|
|
|
|
ifp->if_obytes += len;
|
1994-05-08 16:33:49 +04:00
|
|
|
|
1993-08-14 10:29:28 +04:00
|
|
|
splx(s);
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
bad:
|
|
|
|
m_freem(m0);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1995-07-04 10:28:17 +04:00
|
|
|
* After a change in the NPmode for some NP, move packets from the
|
|
|
|
* npqueue to the send queue or the fast queue as appropriate.
|
1998-07-08 22:05:48 +04:00
|
|
|
* Should be called at splimp, since we muck with the queues.
|
1994-05-08 16:33:49 +04:00
|
|
|
*/
|
1995-07-04 10:28:17 +04:00
|
|
|
static void
|
|
|
|
ppp_requeue(sc)
|
1994-05-08 16:33:49 +04:00
|
|
|
struct ppp_softc *sc;
|
|
|
|
{
|
1995-07-04 10:28:17 +04:00
|
|
|
struct mbuf *m, **mpp;
|
|
|
|
struct ifqueue *ifq;
|
|
|
|
enum NPmode mode;
|
2000-12-18 21:57:21 +03:00
|
|
|
int error;
|
1994-05-08 16:33:49 +04:00
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
for (mpp = &sc->sc_npqueue; (m = *mpp) != NULL; ) {
|
|
|
|
switch (PPP_PROTOCOL(mtod(m, u_char *))) {
|
|
|
|
case PPP_IP:
|
|
|
|
mode = sc->sc_npmode[NP_IP];
|
|
|
|
break;
|
1999-07-30 14:35:34 +04:00
|
|
|
case PPP_IPV6:
|
|
|
|
mode = sc->sc_npmode[NP_IPV6];
|
|
|
|
break;
|
1995-07-04 10:28:17 +04:00
|
|
|
default:
|
|
|
|
mode = NPMODE_PASS;
|
|
|
|
}
|
1994-05-08 16:33:49 +04:00
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
switch (mode) {
|
|
|
|
case NPMODE_PASS:
|
|
|
|
/*
|
|
|
|
* This packet can now go on one of the queues to be sent.
|
|
|
|
*/
|
|
|
|
*mpp = m->m_nextpkt;
|
|
|
|
m->m_nextpkt = NULL;
|
2000-12-18 21:57:21 +03:00
|
|
|
if ((m->m_flags & M_HIGHPRI)
|
|
|
|
#ifdef ALTQ
|
|
|
|
&& ALTQ_IS_ENABLED(&sc->sc_if.if_snd) == 0
|
|
|
|
#endif
|
|
|
|
) {
|
|
|
|
ifq = &sc->sc_fastq;
|
|
|
|
if (IF_QFULL(ifq)) {
|
|
|
|
IF_DROP(ifq);
|
|
|
|
m_freem(m);
|
|
|
|
error = ENOBUFS;
|
|
|
|
} else {
|
|
|
|
IF_ENQUEUE(ifq, m);
|
|
|
|
error = 0;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
IFQ_ENQUEUE(&sc->sc_if.if_snd, m, NULL, error);
|
|
|
|
if (error) {
|
1995-07-04 10:28:17 +04:00
|
|
|
sc->sc_if.if_oerrors++;
|
1996-03-15 05:28:00 +03:00
|
|
|
sc->sc_stats.ppp_oerrors++;
|
2000-12-18 21:57:21 +03:00
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
break;
|
1994-05-08 16:33:49 +04:00
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
case NPMODE_DROP:
|
|
|
|
case NPMODE_ERROR:
|
|
|
|
*mpp = m->m_nextpkt;
|
|
|
|
m_freem(m);
|
|
|
|
break;
|
1994-06-20 04:35:39 +04:00
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
case NPMODE_QUEUE:
|
|
|
|
mpp = &m->m_nextpkt;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sc->sc_npqtail = mpp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-03-12 23:26:46 +03:00
|
|
|
* Transmitter has finished outputting some stuff;
|
|
|
|
* remember to call sc->sc_start later at splsoftnet.
|
1995-07-04 10:28:17 +04:00
|
|
|
*/
|
1997-03-12 23:26:46 +03:00
|
|
|
void
|
|
|
|
ppp_restart(sc)
|
1995-07-04 10:28:17 +04:00
|
|
|
struct ppp_softc *sc;
|
|
|
|
{
|
1997-03-05 00:40:07 +03:00
|
|
|
int s = splimp();
|
1995-07-04 10:28:17 +04:00
|
|
|
|
|
|
|
sc->sc_flags &= ~SC_TBUSY;
|
2001-01-15 19:33:30 +03:00
|
|
|
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
|
|
|
|
softintr_schedule(sc->sc_si);
|
|
|
|
#else
|
1995-07-04 10:28:17 +04:00
|
|
|
schednetisr(NETISR_PPP);
|
2001-01-15 19:33:30 +03:00
|
|
|
#endif
|
1995-07-04 10:28:17 +04:00
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-03-12 23:26:46 +03:00
|
|
|
* Get a packet to send. This procedure is intended to be called at
|
|
|
|
* splsoftnet, since it may involve time-consuming operations such as
|
|
|
|
* applying VJ compression, packet compression, address/control and/or
|
|
|
|
* protocol field compression to the packet.
|
1995-07-04 10:28:17 +04:00
|
|
|
*/
|
1997-03-12 23:26:46 +03:00
|
|
|
struct mbuf *
|
|
|
|
ppp_dequeue(sc)
|
1995-07-04 10:28:17 +04:00
|
|
|
struct ppp_softc *sc;
|
|
|
|
{
|
|
|
|
struct mbuf *m, *mp;
|
|
|
|
u_char *cp;
|
|
|
|
int address, control, protocol;
|
1998-07-08 22:05:48 +04:00
|
|
|
int s;
|
1995-07-04 10:28:17 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Grab a packet to send: first try the fast queue, then the
|
|
|
|
* normal queue.
|
|
|
|
*/
|
1998-07-08 22:05:48 +04:00
|
|
|
s = splimp();
|
1995-07-04 10:28:17 +04:00
|
|
|
IF_DEQUEUE(&sc->sc_fastq, m);
|
|
|
|
if (m == NULL)
|
2000-12-18 21:57:21 +03:00
|
|
|
IFQ_DEQUEUE(&sc->sc_if.if_snd, m);
|
1998-07-08 22:05:48 +04:00
|
|
|
splx(s);
|
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
if (m == NULL)
|
1997-03-12 23:26:46 +03:00
|
|
|
return NULL;
|
1995-07-04 10:28:17 +04:00
|
|
|
|
1996-03-15 05:28:00 +03:00
|
|
|
++sc->sc_stats.ppp_opackets;
|
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
/*
|
|
|
|
* Extract the ppp header of the new packet.
|
|
|
|
* The ppp header will be in one mbuf.
|
|
|
|
*/
|
|
|
|
cp = mtod(m, u_char *);
|
|
|
|
address = PPP_ADDRESS(cp);
|
|
|
|
control = PPP_CONTROL(cp);
|
|
|
|
protocol = PPP_PROTOCOL(cp);
|
|
|
|
|
|
|
|
switch (protocol) {
|
|
|
|
case PPP_IP:
|
|
|
|
#ifdef VJC
|
|
|
|
/*
|
|
|
|
* If the packet is a TCP/IP packet, see if we can compress it.
|
|
|
|
*/
|
1996-03-15 05:28:00 +03:00
|
|
|
if ((sc->sc_flags & SC_COMP_TCP) && sc->sc_comp != NULL) {
|
1995-07-04 10:28:17 +04:00
|
|
|
struct ip *ip;
|
|
|
|
int type;
|
|
|
|
|
|
|
|
mp = m;
|
1994-06-20 04:35:39 +04:00
|
|
|
ip = (struct ip *) (cp + PPP_HDRLEN);
|
|
|
|
if (mp->m_len <= PPP_HDRLEN) {
|
|
|
|
mp = mp->m_next;
|
|
|
|
if (mp == NULL)
|
|
|
|
break;
|
|
|
|
ip = mtod(mp, struct ip *);
|
|
|
|
}
|
|
|
|
/* this code assumes the IP/TCP header is in one non-shared mbuf */
|
|
|
|
if (ip->ip_p == IPPROTO_TCP) {
|
1996-03-15 05:28:00 +03:00
|
|
|
type = sl_compress_tcp(mp, ip, sc->sc_comp,
|
1994-06-20 04:35:39 +04:00
|
|
|
!(sc->sc_flags & SC_NO_TCP_CCID));
|
|
|
|
switch (type) {
|
|
|
|
case TYPE_UNCOMPRESSED_TCP:
|
|
|
|
protocol = PPP_VJC_UNCOMP;
|
|
|
|
break;
|
|
|
|
case TYPE_COMPRESSED_TCP:
|
|
|
|
protocol = PPP_VJC_COMP;
|
|
|
|
cp = mtod(m, u_char *);
|
|
|
|
cp[0] = address; /* header has moved */
|
|
|
|
cp[1] = control;
|
|
|
|
cp[2] = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
cp[3] = protocol; /* update protocol in PPP header */
|
1994-05-08 16:33:49 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* VJC */
|
1995-07-04 10:28:17 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
#ifdef PPP_COMPRESS
|
|
|
|
case PPP_CCP:
|
|
|
|
ppp_ccp(sc, m, 0);
|
|
|
|
break;
|
|
|
|
#endif /* PPP_COMPRESS */
|
1994-05-08 16:33:49 +04:00
|
|
|
}
|
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
#ifdef PPP_COMPRESS
|
|
|
|
if (protocol != PPP_LCP && protocol != PPP_CCP
|
|
|
|
&& sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) {
|
1996-03-15 05:28:00 +03:00
|
|
|
struct mbuf *mcomp = NULL;
|
1995-07-04 10:28:17 +04:00
|
|
|
int slen, clen;
|
|
|
|
|
|
|
|
slen = 0;
|
|
|
|
for (mp = m; mp != NULL; mp = mp->m_next)
|
|
|
|
slen += mp->m_len;
|
|
|
|
clen = (*sc->sc_xcomp->compress)
|
1997-03-12 23:26:46 +03:00
|
|
|
(sc->sc_xc_state, &mcomp, m, slen, sc->sc_if.if_mtu + PPP_HDRLEN);
|
1995-07-04 10:28:17 +04:00
|
|
|
if (mcomp != NULL) {
|
1997-03-12 23:26:46 +03:00
|
|
|
if (sc->sc_flags & SC_CCP_UP) {
|
|
|
|
/* Send the compressed packet instead of the original. */
|
|
|
|
m_freem(m);
|
|
|
|
m = mcomp;
|
|
|
|
cp = mtod(m, u_char *);
|
|
|
|
protocol = cp[3];
|
|
|
|
} else {
|
|
|
|
/* Can't transmit compressed packets until CCP is up. */
|
|
|
|
m_freem(mcomp);
|
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* PPP_COMPRESS */
|
|
|
|
|
1994-05-08 16:33:49 +04:00
|
|
|
/*
|
|
|
|
* Compress the address/control and protocol, if possible.
|
|
|
|
*/
|
|
|
|
if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS &&
|
|
|
|
control == PPP_UI && protocol != PPP_ALLSTATIONS &&
|
|
|
|
protocol != PPP_LCP) {
|
|
|
|
/* can compress address/control */
|
|
|
|
m->m_data += 2;
|
|
|
|
m->m_len -= 2;
|
|
|
|
}
|
|
|
|
if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) {
|
|
|
|
/* can compress protocol */
|
|
|
|
if (mtod(m, u_char *) == cp) {
|
|
|
|
cp[2] = cp[1]; /* move address/control up */
|
|
|
|
cp[1] = cp[0];
|
|
|
|
}
|
|
|
|
++m->m_data;
|
|
|
|
--m->m_len;
|
|
|
|
}
|
|
|
|
|
1997-03-12 23:26:46 +03:00
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2001-01-15 19:33:30 +03:00
|
|
|
#ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
|
|
|
|
void
|
|
|
|
pppnetisr(void)
|
|
|
|
{
|
|
|
|
struct ppp_softc *sc;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < NPPP; i++) {
|
|
|
|
sc = &ppp_softc[i];
|
|
|
|
pppintr(sc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
1997-03-12 23:26:46 +03:00
|
|
|
/*
|
|
|
|
* Software interrupt routine, called at splsoftnet.
|
|
|
|
*/
|
|
|
|
void
|
2001-01-15 19:33:30 +03:00
|
|
|
pppintr(void *arg)
|
1997-03-12 23:26:46 +03:00
|
|
|
{
|
2001-01-15 19:33:30 +03:00
|
|
|
struct ppp_softc *sc = arg;
|
|
|
|
struct mbuf *m;
|
|
|
|
int s;
|
1997-03-12 23:26:46 +03:00
|
|
|
|
|
|
|
if (!(sc->sc_flags & SC_TBUSY)
|
2000-12-18 21:57:21 +03:00
|
|
|
&& (IFQ_IS_EMPTY(&sc->sc_if.if_snd) == 0 || sc->sc_fastq.ifq_head
|
1998-08-02 19:09:50 +04:00
|
|
|
|| sc->sc_outm)) {
|
2001-01-15 19:33:30 +03:00
|
|
|
s = splimp();
|
|
|
|
sc->sc_flags |= SC_TBUSY;
|
|
|
|
splx(s);
|
|
|
|
(*sc->sc_start)(sc);
|
1997-03-12 23:26:46 +03:00
|
|
|
}
|
|
|
|
for (;;) {
|
2001-01-15 19:33:30 +03:00
|
|
|
s = splimp();
|
|
|
|
IF_DEQUEUE(&sc->sc_rawq, m);
|
|
|
|
splx(s);
|
|
|
|
if (m == NULL)
|
|
|
|
break;
|
|
|
|
ppp_inproc(sc, m);
|
1997-03-12 23:26:46 +03:00
|
|
|
}
|
1994-05-08 16:33:49 +04:00
|
|
|
}
|
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
#ifdef PPP_COMPRESS
|
1994-05-08 16:33:49 +04:00
|
|
|
/*
|
1995-07-04 10:28:17 +04:00
|
|
|
* Handle a CCP packet. `rcvd' is 1 if the packet was received,
|
|
|
|
* 0 if it is about to be transmitted.
|
1994-05-08 16:33:49 +04:00
|
|
|
*/
|
1996-02-14 00:59:53 +03:00
|
|
|
static void
|
1995-07-04 10:28:17 +04:00
|
|
|
ppp_ccp(sc, m, rcvd)
|
|
|
|
struct ppp_softc *sc;
|
|
|
|
struct mbuf *m;
|
|
|
|
int rcvd;
|
1994-05-08 16:33:49 +04:00
|
|
|
{
|
1995-07-04 10:28:17 +04:00
|
|
|
u_char *dp, *ep;
|
|
|
|
struct mbuf *mp;
|
|
|
|
int slen, s;
|
1994-05-08 16:33:49 +04:00
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
/*
|
|
|
|
* Get a pointer to the data after the PPP header.
|
|
|
|
*/
|
|
|
|
if (m->m_len <= PPP_HDRLEN) {
|
|
|
|
mp = m->m_next;
|
|
|
|
if (mp == NULL)
|
|
|
|
return;
|
|
|
|
dp = (mp != NULL)? mtod(mp, u_char *): NULL;
|
|
|
|
} else {
|
|
|
|
mp = m;
|
|
|
|
dp = mtod(mp, u_char *) + PPP_HDRLEN;
|
|
|
|
}
|
1994-05-08 16:33:49 +04:00
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
ep = mtod(mp, u_char *) + mp->m_len;
|
|
|
|
if (dp + CCP_HDRLEN > ep)
|
1994-05-08 16:33:49 +04:00
|
|
|
return;
|
1995-07-04 10:28:17 +04:00
|
|
|
slen = CCP_LENGTH(dp);
|
|
|
|
if (dp + slen > ep) {
|
|
|
|
if (sc->sc_flags & SC_DEBUG)
|
1996-10-13 06:10:01 +04:00
|
|
|
printf("if_ppp/ccp: not enough data in mbuf (%p+%x > %p+%x)\n",
|
1996-10-11 02:59:41 +04:00
|
|
|
dp, slen, mtod(mp, u_char *), mp->m_len);
|
1994-05-08 16:33:49 +04:00
|
|
|
return;
|
|
|
|
}
|
1993-08-14 10:29:28 +04:00
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
switch (CCP_CODE(dp)) {
|
|
|
|
case CCP_CONFREQ:
|
|
|
|
case CCP_TERMREQ:
|
|
|
|
case CCP_TERMACK:
|
|
|
|
/* CCP must be going down - disable compression */
|
|
|
|
if (sc->sc_flags & SC_CCP_UP) {
|
1997-03-05 00:40:07 +03:00
|
|
|
s = splimp();
|
1995-07-04 10:28:17 +04:00
|
|
|
sc->sc_flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN);
|
|
|
|
splx(s);
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
break;
|
1993-08-14 10:29:28 +04:00
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
case CCP_CONFACK:
|
|
|
|
if (sc->sc_flags & SC_CCP_OPEN && !(sc->sc_flags & SC_CCP_UP)
|
|
|
|
&& slen >= CCP_HDRLEN + CCP_OPT_MINLEN
|
|
|
|
&& slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) {
|
|
|
|
if (!rcvd) {
|
|
|
|
/* we're agreeing to send compressed packets. */
|
|
|
|
if (sc->sc_xc_state != NULL
|
|
|
|
&& (*sc->sc_xcomp->comp_init)
|
|
|
|
(sc->sc_xc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN,
|
1996-05-07 06:40:22 +04:00
|
|
|
sc->sc_unit, 0, sc->sc_flags & SC_DEBUG)) {
|
1997-03-05 00:40:07 +03:00
|
|
|
s = splimp();
|
1995-07-04 10:28:17 +04:00
|
|
|
sc->sc_flags |= SC_COMP_RUN;
|
|
|
|
splx(s);
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
} else {
|
|
|
|
/* peer is agreeing to send compressed packets. */
|
|
|
|
if (sc->sc_rc_state != NULL
|
|
|
|
&& (*sc->sc_rcomp->decomp_init)
|
|
|
|
(sc->sc_rc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN,
|
1996-05-07 06:40:22 +04:00
|
|
|
sc->sc_unit, 0, sc->sc_mru,
|
1995-07-04 10:28:17 +04:00
|
|
|
sc->sc_flags & SC_DEBUG)) {
|
1997-03-05 00:40:07 +03:00
|
|
|
s = splimp();
|
1995-07-04 10:28:17 +04:00
|
|
|
sc->sc_flags |= SC_DECOMP_RUN;
|
|
|
|
sc->sc_flags &= ~(SC_DC_ERROR | SC_DC_FERROR);
|
|
|
|
splx(s);
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
}
|
|
|
|
break;
|
1993-08-31 04:05:27 +04:00
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
case CCP_RESETACK:
|
|
|
|
if (sc->sc_flags & SC_CCP_UP) {
|
|
|
|
if (!rcvd) {
|
|
|
|
if (sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN))
|
|
|
|
(*sc->sc_xcomp->comp_reset)(sc->sc_xc_state);
|
|
|
|
} else {
|
|
|
|
if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) {
|
|
|
|
(*sc->sc_rcomp->decomp_reset)(sc->sc_rc_state);
|
1997-03-05 00:40:07 +03:00
|
|
|
s = splimp();
|
1995-07-04 10:28:17 +04:00
|
|
|
sc->sc_flags &= ~SC_DC_ERROR;
|
|
|
|
splx(s);
|
|
|
|
}
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
1993-08-31 04:05:27 +04:00
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
break;
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1995-07-04 10:28:17 +04:00
|
|
|
* CCP is down; free (de)compressor state if necessary.
|
1993-08-14 10:29:28 +04:00
|
|
|
*/
|
1995-07-04 10:28:17 +04:00
|
|
|
static void
|
|
|
|
ppp_ccp_closed(sc)
|
|
|
|
struct ppp_softc *sc;
|
1993-08-14 10:29:28 +04:00
|
|
|
{
|
1995-07-04 10:28:17 +04:00
|
|
|
if (sc->sc_xc_state) {
|
|
|
|
(*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
|
|
|
|
sc->sc_xc_state = NULL;
|
|
|
|
}
|
|
|
|
if (sc->sc_rc_state) {
|
|
|
|
(*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
|
|
|
|
sc->sc_rc_state = NULL;
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
#endif /* PPP_COMPRESS */
|
1993-08-14 10:29:28 +04:00
|
|
|
|
|
|
|
/*
|
1994-05-08 16:33:49 +04:00
|
|
|
* PPP packet input routine.
|
1994-06-20 04:35:39 +04:00
|
|
|
* The caller has checked and removed the FCS and has inserted
|
|
|
|
* the address/control bytes and the protocol high byte if they
|
1995-07-04 10:28:17 +04:00
|
|
|
* were omitted.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
ppppktin(sc, m, lost)
|
|
|
|
struct ppp_softc *sc;
|
|
|
|
struct mbuf *m;
|
|
|
|
int lost;
|
|
|
|
{
|
1997-03-05 00:40:07 +03:00
|
|
|
int s = splimp();
|
1995-07-04 10:28:17 +04:00
|
|
|
|
|
|
|
if (lost)
|
|
|
|
m->m_flags |= M_ERRMARK;
|
|
|
|
IF_ENQUEUE(&sc->sc_rawq, m);
|
2001-01-15 19:33:30 +03:00
|
|
|
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
|
|
|
|
softintr_schedule(sc->sc_si);
|
|
|
|
#else
|
1995-07-04 10:28:17 +04:00
|
|
|
schednetisr(NETISR_PPP);
|
2001-01-15 19:33:30 +03:00
|
|
|
#endif
|
1995-07-04 10:28:17 +04:00
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Process a received PPP packet, doing decompression as necessary.
|
|
|
|
* Should be called at splsoftnet.
|
1993-08-14 10:29:28 +04:00
|
|
|
*/
|
|
|
|
#define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \
|
|
|
|
TYPE_UNCOMPRESSED_TCP)
|
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
static void
|
|
|
|
ppp_inproc(sc, m)
|
1994-05-08 16:33:49 +04:00
|
|
|
struct ppp_softc *sc;
|
|
|
|
struct mbuf *m;
|
|
|
|
{
|
1995-10-05 08:55:09 +03:00
|
|
|
struct ifnet *ifp = &sc->sc_if;
|
1994-05-08 16:33:49 +04:00
|
|
|
struct ifqueue *inq;
|
2000-10-02 07:54:10 +04:00
|
|
|
int s, ilen, proto, rv;
|
1994-06-20 04:35:39 +04:00
|
|
|
u_char *cp, adrs, ctrl;
|
1996-03-15 05:28:00 +03:00
|
|
|
struct mbuf *mp, *dmp = NULL;
|
2000-10-02 07:54:10 +04:00
|
|
|
#ifdef VJC
|
|
|
|
int xlen;
|
1995-07-04 10:28:17 +04:00
|
|
|
u_char *iphdr;
|
|
|
|
u_int hlen;
|
2000-10-02 07:54:10 +04:00
|
|
|
#endif
|
1994-05-08 16:33:49 +04:00
|
|
|
|
1996-03-15 05:28:00 +03:00
|
|
|
sc->sc_stats.ppp_ipackets++;
|
1995-07-04 10:28:17 +04:00
|
|
|
|
|
|
|
if (sc->sc_flags & SC_LOG_INPKT) {
|
1996-03-15 05:28:00 +03:00
|
|
|
ilen = 0;
|
1996-02-07 15:43:41 +03:00
|
|
|
for (mp = m; mp != NULL; mp = mp->m_next)
|
1996-03-15 05:28:00 +03:00
|
|
|
ilen += mp->m_len;
|
1996-10-13 06:10:01 +04:00
|
|
|
printf("%s: got %d bytes\n", ifp->if_xname, ilen);
|
1995-07-04 10:28:17 +04:00
|
|
|
pppdumpm(m);
|
|
|
|
}
|
1994-05-08 16:33:49 +04:00
|
|
|
|
1994-06-20 04:35:39 +04:00
|
|
|
cp = mtod(m, u_char *);
|
1995-07-04 10:28:17 +04:00
|
|
|
adrs = PPP_ADDRESS(cp);
|
|
|
|
ctrl = PPP_CONTROL(cp);
|
|
|
|
proto = PPP_PROTOCOL(cp);
|
|
|
|
|
|
|
|
if (m->m_flags & M_ERRMARK) {
|
|
|
|
m->m_flags &= ~M_ERRMARK;
|
1997-03-05 00:40:07 +03:00
|
|
|
s = splimp();
|
1995-07-04 10:28:17 +04:00
|
|
|
sc->sc_flags |= SC_VJ_RESET;
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef PPP_COMPRESS
|
|
|
|
/*
|
|
|
|
* Decompress this packet if necessary, update the receiver's
|
|
|
|
* dictionary, or take appropriate action on a CCP packet.
|
|
|
|
*/
|
|
|
|
if (proto == PPP_COMP && sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)
|
|
|
|
&& !(sc->sc_flags & SC_DC_ERROR) && !(sc->sc_flags & SC_DC_FERROR)) {
|
|
|
|
/* decompress this packet */
|
|
|
|
rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp);
|
|
|
|
if (rv == DECOMP_OK) {
|
|
|
|
m_freem(m);
|
|
|
|
if (dmp == NULL) {
|
|
|
|
/* no error, but no decompressed packet produced */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m = dmp;
|
|
|
|
cp = mtod(m, u_char *);
|
|
|
|
proto = PPP_PROTOCOL(cp);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* An error has occurred in decompression.
|
|
|
|
* Pass the compressed packet up to pppd, which may take
|
|
|
|
* CCP down or issue a Reset-Req.
|
|
|
|
*/
|
|
|
|
if (sc->sc_flags & SC_DEBUG)
|
1996-10-13 06:10:01 +04:00
|
|
|
printf("%s: decompress failed %d\n", ifp->if_xname, rv);
|
1997-03-05 00:40:07 +03:00
|
|
|
s = splimp();
|
1995-07-04 10:28:17 +04:00
|
|
|
sc->sc_flags |= SC_VJ_RESET;
|
|
|
|
if (rv == DECOMP_ERROR)
|
|
|
|
sc->sc_flags |= SC_DC_ERROR;
|
|
|
|
else
|
|
|
|
sc->sc_flags |= SC_DC_FERROR;
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) {
|
|
|
|
(*sc->sc_rcomp->incomp)(sc->sc_rc_state, m);
|
|
|
|
}
|
|
|
|
if (proto == PPP_CCP) {
|
|
|
|
ppp_ccp(sc, m, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
1994-06-20 04:35:39 +04:00
|
|
|
|
1996-02-07 15:43:41 +03:00
|
|
|
ilen = 0;
|
|
|
|
for (mp = m; mp != NULL; mp = mp->m_next)
|
|
|
|
ilen += mp->m_len;
|
|
|
|
|
1994-05-08 16:33:49 +04:00
|
|
|
#ifdef VJC
|
1995-07-04 10:28:17 +04:00
|
|
|
if (sc->sc_flags & SC_VJ_RESET) {
|
|
|
|
/*
|
|
|
|
* If we've missed a packet, we must toss subsequent compressed
|
|
|
|
* packets which don't have an explicit connection ID.
|
|
|
|
*/
|
1996-03-15 05:28:00 +03:00
|
|
|
if (sc->sc_comp)
|
|
|
|
sl_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp);
|
1997-03-05 00:40:07 +03:00
|
|
|
s = splimp();
|
1995-07-04 10:28:17 +04:00
|
|
|
sc->sc_flags &= ~SC_VJ_RESET;
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
|
1994-05-08 16:33:49 +04:00
|
|
|
/*
|
|
|
|
* See if we have a VJ-compressed packet to uncompress.
|
|
|
|
*/
|
1995-07-04 10:28:17 +04:00
|
|
|
if (proto == PPP_VJC_COMP) {
|
1996-03-15 05:28:00 +03:00
|
|
|
if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)
|
1995-07-04 10:28:17 +04:00
|
|
|
goto bad;
|
|
|
|
|
|
|
|
xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN,
|
|
|
|
ilen - PPP_HDRLEN, TYPE_COMPRESSED_TCP,
|
1996-03-15 05:28:00 +03:00
|
|
|
sc->sc_comp, &iphdr, &hlen);
|
1994-05-08 16:33:49 +04:00
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
if (xlen <= 0) {
|
1994-05-08 16:33:49 +04:00
|
|
|
if (sc->sc_flags & SC_DEBUG)
|
1996-10-13 06:10:01 +04:00
|
|
|
printf("%s: VJ uncompress failed on type comp\n",
|
1996-10-11 02:59:41 +04:00
|
|
|
ifp->if_xname);
|
1995-07-04 10:28:17 +04:00
|
|
|
goto bad;
|
1994-07-20 05:40:11 +04:00
|
|
|
}
|
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
/* Copy the PPP and IP headers into a new mbuf. */
|
|
|
|
MGETHDR(mp, M_DONTWAIT, MT_DATA);
|
|
|
|
if (mp == NULL)
|
|
|
|
goto bad;
|
|
|
|
mp->m_len = 0;
|
|
|
|
mp->m_next = NULL;
|
|
|
|
if (hlen + PPP_HDRLEN > MHLEN) {
|
|
|
|
MCLGET(mp, M_DONTWAIT);
|
|
|
|
if (M_TRAILINGSPACE(mp) < hlen + PPP_HDRLEN) {
|
|
|
|
m_freem(mp);
|
|
|
|
goto bad; /* lose if big headers and no clusters */
|
|
|
|
}
|
1994-05-08 16:33:49 +04:00
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
cp = mtod(mp, u_char *);
|
|
|
|
cp[0] = adrs;
|
|
|
|
cp[1] = ctrl;
|
|
|
|
cp[2] = 0;
|
|
|
|
cp[3] = PPP_IP;
|
|
|
|
proto = PPP_IP;
|
|
|
|
bcopy(iphdr, cp + PPP_HDRLEN, hlen);
|
|
|
|
mp->m_len = hlen + PPP_HDRLEN;
|
1994-05-08 16:33:49 +04:00
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
/*
|
|
|
|
* Trim the PPP and VJ headers off the old mbuf
|
|
|
|
* and stick the new and old mbufs together.
|
|
|
|
*/
|
|
|
|
m->m_data += PPP_HDRLEN + xlen;
|
|
|
|
m->m_len -= PPP_HDRLEN + xlen;
|
|
|
|
if (m->m_len <= M_TRAILINGSPACE(mp)) {
|
|
|
|
bcopy(mtod(m, u_char *), mtod(mp, u_char *) + mp->m_len, m->m_len);
|
|
|
|
mp->m_len += m->m_len;
|
|
|
|
MFREE(m, mp->m_next);
|
|
|
|
} else
|
|
|
|
mp->m_next = m;
|
|
|
|
m = mp;
|
|
|
|
ilen += hlen - xlen;
|
|
|
|
|
|
|
|
} else if (proto == PPP_VJC_UNCOMP) {
|
1996-03-15 05:28:00 +03:00
|
|
|
if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)
|
1995-07-04 10:28:17 +04:00
|
|
|
goto bad;
|
|
|
|
|
|
|
|
xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN,
|
|
|
|
ilen - PPP_HDRLEN, TYPE_UNCOMPRESSED_TCP,
|
1996-03-15 05:28:00 +03:00
|
|
|
sc->sc_comp, &iphdr, &hlen);
|
1994-05-08 16:33:49 +04:00
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
if (xlen < 0) {
|
1994-05-08 16:33:49 +04:00
|
|
|
if (sc->sc_flags & SC_DEBUG)
|
1996-10-13 06:10:01 +04:00
|
|
|
printf("%s: VJ uncompress failed on type uncomp\n",
|
1996-10-11 02:59:41 +04:00
|
|
|
ifp->if_xname);
|
1995-07-04 10:28:17 +04:00
|
|
|
goto bad;
|
1994-05-08 16:33:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
proto = PPP_IP;
|
1994-06-20 04:35:39 +04:00
|
|
|
cp[3] = PPP_IP;
|
1994-05-08 16:33:49 +04:00
|
|
|
}
|
|
|
|
#endif /* VJC */
|
|
|
|
|
1994-06-20 04:35:39 +04:00
|
|
|
/*
|
|
|
|
* If the packet will fit in a header mbuf, don't waste a
|
|
|
|
* whole cluster on it.
|
|
|
|
*/
|
1995-07-04 10:28:17 +04:00
|
|
|
if (ilen <= MHLEN && M_IS_CLUSTER(m)) {
|
1994-06-20 04:35:39 +04:00
|
|
|
MGETHDR(mp, M_DONTWAIT, MT_DATA);
|
|
|
|
if (mp != NULL) {
|
|
|
|
m_copydata(m, 0, ilen, mtod(mp, caddr_t));
|
|
|
|
m_freem(m);
|
|
|
|
m = mp;
|
|
|
|
m->m_len = ilen;
|
|
|
|
}
|
1994-05-08 16:33:49 +04:00
|
|
|
}
|
|
|
|
m->m_pkthdr.len = ilen;
|
1995-10-05 08:55:09 +03:00
|
|
|
m->m_pkthdr.rcvif = ifp;
|
1994-05-08 16:33:49 +04:00
|
|
|
|
1996-03-15 05:28:00 +03:00
|
|
|
if ((proto & 0x8000) == 0) {
|
1997-03-12 23:26:46 +03:00
|
|
|
#ifdef PPP_FILTER
|
|
|
|
/*
|
|
|
|
* See whether we want to pass this packet, and
|
|
|
|
* if it counts as link activity.
|
|
|
|
*/
|
Decouple inbound and outbound filters. Now instead of using "active-filter"
and "pass-filter" and "inbound" and "outbound" qualifiers in the filter
expression, use new "active-filter-in", "active-filter-out", "pass-filter-in",
and "pass-filter-out" without these qualifiers.
This is necessary due to the horrible, awful way "inbound" and "outbound"
were specified for the filter programs when a packet was passed through them.
Basically, the "address" byte in the serial PPP header was overwritten with
a value to indicate the direction. However, the "address" byte doesn't even
exist on PPP headers for all other PPP encaps! So, this old method worked
only for serial encaps, and corrupted packets for all others (PPPoE, ATM, etc.)
1999-05-12 22:50:51 +04:00
|
|
|
if (sc->sc_pass_filt_in.bf_insns != 0
|
|
|
|
&& bpf_filter(sc->sc_pass_filt_in.bf_insns, (u_char *) m,
|
1996-03-15 05:28:00 +03:00
|
|
|
ilen, 0) == 0) {
|
|
|
|
/* drop this packet */
|
|
|
|
m_freem(m);
|
|
|
|
return;
|
|
|
|
}
|
Decouple inbound and outbound filters. Now instead of using "active-filter"
and "pass-filter" and "inbound" and "outbound" qualifiers in the filter
expression, use new "active-filter-in", "active-filter-out", "pass-filter-in",
and "pass-filter-out" without these qualifiers.
This is necessary due to the horrible, awful way "inbound" and "outbound"
were specified for the filter programs when a packet was passed through them.
Basically, the "address" byte in the serial PPP header was overwritten with
a value to indicate the direction. However, the "address" byte doesn't even
exist on PPP headers for all other PPP encaps! So, this old method worked
only for serial encaps, and corrupted packets for all others (PPPoE, ATM, etc.)
1999-05-12 22:50:51 +04:00
|
|
|
if (sc->sc_active_filt_in.bf_insns == 0
|
|
|
|
|| bpf_filter(sc->sc_active_filt_in.bf_insns, (u_char *) m,
|
|
|
|
ilen, 0))
|
1996-03-15 05:28:00 +03:00
|
|
|
sc->sc_last_recv = time.tv_sec;
|
1997-03-12 23:26:46 +03:00
|
|
|
#else
|
|
|
|
/*
|
|
|
|
* Record the time that we received this packet.
|
|
|
|
*/
|
|
|
|
sc->sc_last_recv = time.tv_sec;
|
|
|
|
#endif /* PPP_FILTER */
|
1996-03-15 05:28:00 +03:00
|
|
|
}
|
|
|
|
|
1994-05-08 16:33:49 +04:00
|
|
|
#if NBPFILTER > 0
|
|
|
|
/* See if bpf wants to look at the packet. */
|
2000-12-12 21:00:22 +03:00
|
|
|
if (sc->sc_if.if_bpf)
|
|
|
|
bpf_mtap(sc->sc_if.if_bpf, m);
|
1994-05-08 16:33:49 +04:00
|
|
|
#endif
|
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
rv = 0;
|
1994-05-08 16:33:49 +04:00
|
|
|
switch (proto) {
|
|
|
|
#ifdef INET
|
|
|
|
case PPP_IP:
|
|
|
|
/*
|
|
|
|
* IP packet - take off the ppp header and pass it up to IP.
|
|
|
|
*/
|
1995-10-05 08:55:09 +03:00
|
|
|
if ((ifp->if_flags & IFF_UP) == 0
|
1995-07-04 10:28:17 +04:00
|
|
|
|| sc->sc_npmode[NP_IP] != NPMODE_PASS) {
|
1994-05-08 16:33:49 +04:00
|
|
|
/* interface is down - drop the packet. */
|
|
|
|
m_freem(m);
|
1995-07-04 10:28:17 +04:00
|
|
|
return;
|
1994-05-08 16:33:49 +04:00
|
|
|
}
|
|
|
|
m->m_pkthdr.len -= PPP_HDRLEN;
|
|
|
|
m->m_data += PPP_HDRLEN;
|
|
|
|
m->m_len -= PPP_HDRLEN;
|
1998-07-10 02:30:01 +04:00
|
|
|
#ifdef GATEWAY
|
|
|
|
if (ipflow_fastforward(m))
|
|
|
|
return;
|
|
|
|
#endif
|
1994-05-08 16:33:49 +04:00
|
|
|
schednetisr(NETISR_IP);
|
|
|
|
inq = &ipintrq;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
1999-07-30 14:35:34 +04:00
|
|
|
#ifdef INET6
|
|
|
|
case PPP_IPV6:
|
|
|
|
/*
|
|
|
|
* IPv6 packet - take off the ppp header and pass it up to IPv6.
|
|
|
|
*/
|
|
|
|
if ((ifp->if_flags & IFF_UP) == 0
|
|
|
|
|| sc->sc_npmode[NP_IPV6] != NPMODE_PASS) {
|
|
|
|
/* interface is down - drop the packet. */
|
|
|
|
m_freem(m);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m->m_pkthdr.len -= PPP_HDRLEN;
|
|
|
|
m->m_data += PPP_HDRLEN;
|
|
|
|
m->m_len -= PPP_HDRLEN;
|
|
|
|
schednetisr(NETISR_IPV6);
|
|
|
|
inq = &ip6intrq;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
1994-05-08 16:33:49 +04:00
|
|
|
default:
|
|
|
|
/*
|
|
|
|
* Some other protocol - place on input queue for read().
|
|
|
|
*/
|
|
|
|
inq = &sc->sc_inq;
|
|
|
|
rv = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Put the packet on the appropriate input queue.
|
|
|
|
*/
|
1997-03-05 00:40:07 +03:00
|
|
|
s = splimp();
|
1994-05-08 16:33:49 +04:00
|
|
|
if (IF_QFULL(inq)) {
|
|
|
|
IF_DROP(inq);
|
1995-07-04 10:28:17 +04:00
|
|
|
splx(s);
|
1994-05-08 16:33:49 +04:00
|
|
|
if (sc->sc_flags & SC_DEBUG)
|
1996-10-13 06:10:01 +04:00
|
|
|
printf("%s: input queue full\n", ifp->if_xname);
|
1995-10-05 08:55:09 +03:00
|
|
|
ifp->if_iqdrops++;
|
1995-07-04 10:28:17 +04:00
|
|
|
goto bad;
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
1995-07-04 10:28:17 +04:00
|
|
|
IF_ENQUEUE(inq, m);
|
|
|
|
splx(s);
|
1996-03-15 05:28:00 +03:00
|
|
|
ifp->if_ipackets++;
|
|
|
|
ifp->if_ibytes += ilen;
|
|
|
|
ifp->if_lastchange = time;
|
1993-08-14 10:29:28 +04:00
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
if (rv)
|
|
|
|
(*sc->sc_ctlp)(sc);
|
1993-08-14 10:29:28 +04:00
|
|
|
|
|
|
|
return;
|
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
bad:
|
|
|
|
m_freem(m);
|
|
|
|
sc->sc_if.if_ierrors++;
|
1996-03-15 05:28:00 +03:00
|
|
|
sc->sc_stats.ppp_ierrors++;
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#define MAX_DUMP_BYTES 128
|
|
|
|
|
|
|
|
static void
|
1995-07-04 10:28:17 +04:00
|
|
|
pppdumpm(m0)
|
1993-08-14 10:29:28 +04:00
|
|
|
struct mbuf *m0;
|
|
|
|
{
|
1994-05-08 16:33:49 +04:00
|
|
|
char buf[3*MAX_DUMP_BYTES+4];
|
1993-08-14 10:29:28 +04:00
|
|
|
char *bp = buf;
|
|
|
|
struct mbuf *m;
|
|
|
|
static char digits[] = "0123456789abcdef";
|
|
|
|
|
1995-07-04 10:28:17 +04:00
|
|
|
for (m = m0; m; m = m->m_next) {
|
1993-08-14 10:29:28 +04:00
|
|
|
int l = m->m_len;
|
|
|
|
u_char *rptr = (u_char *)m->m_data;
|
|
|
|
|
|
|
|
while (l--) {
|
|
|
|
if (bp > buf + sizeof(buf) - 4)
|
|
|
|
goto done;
|
|
|
|
*bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */
|
|
|
|
*bp++ = digits[*rptr++ & 0xf];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m->m_next) {
|
|
|
|
if (bp > buf + sizeof(buf) - 3)
|
|
|
|
goto done;
|
|
|
|
*bp++ = '|';
|
1994-05-08 16:33:49 +04:00
|
|
|
} else
|
|
|
|
*bp++ = ' ';
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
|
|
|
done:
|
1995-07-04 10:28:17 +04:00
|
|
|
if (m)
|
1993-08-14 10:29:28 +04:00
|
|
|
*bp++ = '>';
|
|
|
|
*bp = 0;
|
1996-10-13 06:10:01 +04:00
|
|
|
printf("%s\n", buf);
|
1993-08-14 10:29:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* NPPP > 0 */
|