* Paul Mackerras (paulus@cs.anu.edu.au).
*/
-/* $Id: if_ppp.c,v 1.9 1996/09/26 06:24:39 paulus Exp $ */
+/* $Id: if_ppp.c,v 1.12 1997/04/30 05:42:07 paulus Exp $ */
/* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
/* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
#include <net/if_types.h>
#include <net/netisr.h>
#include <net/route.h>
+#ifdef PPP_FILTER
+#include <net/bpf.h>
+#endif
#if INET
#include <netinet/in.h>
#include <net/ppp-comp.h>
#endif
+static int pppsioctl __P((struct ifnet *, int, caddr_t));
+static int pppoutput __P((struct ifnet *, struct mbuf *,
+ struct sockaddr *, struct rtentry *));
static void ppp_requeue __P((struct ppp_softc *));
-static void ppp_outpkt __P((struct ppp_softc *));
static void ppp_ccp __P((struct ppp_softc *, struct mbuf *m, int rcvd));
static void ppp_ccp_closed __P((struct ppp_softc *));
static void ppp_inproc __P((struct ppp_softc *, struct mbuf *));
sc->sc_relinq = NULL;
bzero((char *)&sc->sc_stats, sizeof(sc->sc_stats));
#ifdef VJC
- MALLOC(sc->sc_comp, struct slcompress *, sizeof(struct slcompress),
+ MALLOC(sc->sc_comp, struct vjcompress *, sizeof(struct vjcompress),
M_DEVBUF, M_NOWAIT);
if (sc->sc_comp)
vj_compress_init(sc->sc_comp, -1);
sc->sc_xc_state = NULL;
sc->sc_rc_state = NULL;
#endif /* PPP_COMPRESS */
+#ifdef PPP_FILTER
+ if (sc->sc_pass_filt.bf_insns != 0) {
+ FREE(sc->sc_pass_filt.bf_insns, M_DEVBUF);
+ sc->sc_pass_filt.bf_insns = 0;
+ sc->sc_pass_filt.bf_len = 0;
+ }
+ if (sc->sc_active_filt.bf_insns != 0) {
+ FREE(sc->sc_active_filt.bf_insns, M_DEVBUF);
+ sc->sc_active_filt.bf_insns = 0;
+ sc->sc_active_filt.bf_len = 0;
+ }
+#endif /* PPP_FILTER */
#ifdef VJC
if (sc->sc_comp != 0) {
FREE(sc->sc_comp, M_DEVBUF);
int
pppioctl(sc, cmd, data, flag, p)
struct ppp_softc *sc;
- u_long cmd;
+ int cmd;
caddr_t data;
int flag;
struct proc *p;
struct compressor **cp;
struct npioctl *npi;
time_t t;
+#ifdef PPP_FILTER
+ struct bpf_program *bp, *nbp;
+ struct bpf_insn *newcode, *oldcode;
+ int newcodelen;
+#endif /* PPP_FILTER */
#ifdef PPP_COMPRESS
u_char ccp_option[CCP_MAX_OPTION_LENGTH];
#endif
splx(s);
break;
+#ifdef PPP_FILTER
+ case PPPIOCSPASS:
+ case PPPIOCSACTIVE:
+ 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) {
+ MALLOC(newcode, struct bpf_insn *, newcodelen, M_DEVBUF, M_WAITOK);
+ if (newcode == 0) {
+ return EINVAL; /* or sumpin */
+ }
+ if ((error = copyin((caddr_t)nbp->bf_insns, (caddr_t)newcode,
+ newcodelen)) != 0) {
+ FREE(newcode, M_DEVBUF);
+ return error;
+ }
+ if (!bpf_validate(newcode, nbp->bf_len)) {
+ FREE(newcode, M_DEVBUF);
+ return EINVAL;
+ }
+ } else
+ newcode = 0;
+ bp = (cmd == PPPIOCSPASS)? &sc->sc_pass_filt: &sc->sc_active_filt;
+ oldcode = bp->bf_insns;
+ s = splimp();
+ bp->bf_len = nbp->bf_len;
+ bp->bf_insns = newcode;
+ splx(s);
+ if (oldcode != 0)
+ FREE(oldcode, M_DEVBUF);
+ break;
+#endif
+
default:
return (-1);
}
/*
* Process an ioctl request to the ppp network interface.
*/
-int
+static int
pppsioctl(ifp, cmd, data)
register struct ifnet *ifp;
- u_long cmd;
+ int cmd;
caddr_t data;
{
struct proc *p = curproc; /* XXX */
}
if ((protocol & 0x8000) == 0) {
+#ifdef PPP_FILTER
+ /*
+ * Apply the pass and active filters to the packet,
+ * but only if it is a data packet.
+ */
+ *mtod(m0, u_char *) = 1; /* indicates outbound */
+ if (sc->sc_pass_filt.bf_insns != 0
+ && bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *) m0,
+ len, 0) == 0) {
+ error = 0; /* drop this packet */
+ goto bad;
+ }
+
+ /*
+ * Update the time we sent the most recent packet.
+ */
+ if (sc->sc_active_filt.bf_insns == 0
+ || bpf_filter(sc->sc_active_filt.bf_insns, (u_char *) m0, len, 0))
+ sc->sc_last_sent = time.tv_sec;
+
+ *mtod(m0, u_char *) = address;
+#else
/*
* Update the time we sent the most recent data packet.
*/
sc->sc_last_sent = time.tv_sec;
+#endif /* PPP_FILTER */
}
#if NBPFILTER > 0
struct mbuf *m, *mp;
u_char *cp;
int address, control, protocol;
- int s;
/*
* Grab a packet to send: first try the fast queue, then the
m->m_pkthdr.len = ilen;
m->m_pkthdr.rcvif = ifp;
- /*
- * Record the time that we received this packet.
- */
if ((proto & 0x8000) == 0) {
+#ifdef PPP_FILTER
+ /*
+ * See whether we want to pass this packet, and
+ * if it counts as link activity.
+ */
+ adrs = *mtod(m, u_char *); /* save address field */
+ *mtod(m, u_char *) = 0; /* indicate inbound */
+ if (sc->sc_pass_filt.bf_insns != 0
+ && bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *) m,
+ ilen, 0) == 0) {
+ /* drop this packet */
+ m_freem(m);
+ return;
+ }
+ if (sc->sc_active_filt.bf_insns == 0
+ || bpf_filter(sc->sc_active_filt.bf_insns, (u_char *) m, ilen, 0))
+ sc->sc_last_recv = time.tv_sec;
+
+ *mtod(m, u_char *) = adrs;
+#else
+ /*
+ * Record the time that we received this packet.
+ */
sc->sc_last_recv = time.tv_sec;
+#endif /* PPP_FILTER */
}
#if NBPFILTER > 0