X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=freebsd-2.0%2Fif_ppp.c;h=fc0fd69b4624c21f2218aa27c3c8d3d6d98097cf;hp=23a95b4d064eedd5266889f8fa765deb86e133cd;hb=e28f47d5e53abe7317d9a82703bbbee044482d4f;hpb=3fca15005a3eb1adb1ac4f94ec3eb6439e2dc865 diff --git a/freebsd-2.0/if_ppp.c b/freebsd-2.0/if_ppp.c index 23a95b4..fc0fd69 100644 --- a/freebsd-2.0/if_ppp.c +++ b/freebsd-2.0/if_ppp.c @@ -69,7 +69,7 @@ * Paul Mackerras (paulus@cs.anu.edu.au). */ -/* $Id: if_ppp.c,v 1.7 1996/07/01 01:00:27 paulus Exp $ */ +/* $Id: if_ppp.c,v 1.13 1998/02/04 01:36:39 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 */ @@ -93,6 +93,9 @@ #include #include #include +#ifdef PPP_FILTER +#include +#endif #if INET #include @@ -115,6 +118,8 @@ #include #include +#define splsoftnet splnet + #ifndef NETISR_PPP /* This definition should be moved to net/netisr.h */ #define NETISR_PPP 26 /* PPP software interrupt */ @@ -125,8 +130,8 @@ #include #endif +static int pppsioctl __P((struct ifnet *, int, caddr_t)); 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 *)); @@ -232,7 +237,7 @@ pppalloc(pid) 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); @@ -251,7 +256,7 @@ pppalloc(pid) } /* - * Deallocate a ppp unit. Must be called at splnet or higher. + * Deallocate a ppp unit. Must be called at splsoftnet or higher. */ void pppdealloc(sc) @@ -294,6 +299,18 @@ pppdealloc(sc) 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); @@ -308,7 +325,7 @@ pppdealloc(sc) int pppioctl(sc, cmd, data, flag, p) struct ppp_softc *sc; - u_long cmd; + int cmd; caddr_t data; int flag; struct proc *p; @@ -318,6 +335,11 @@ pppioctl(sc, cmd, data, flag, 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 @@ -339,7 +361,7 @@ pppioctl(sc, cmd, data, flag, p) if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) return (error); flags = *(int *)data & SC_MASK; - s = splnet(); + s = splsoftnet(); #ifdef PPP_COMPRESS if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN)) ppp_ccp_closed(sc); @@ -366,7 +388,7 @@ pppioctl(sc, cmd, data, flag, p) if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) return (error); if (sc->sc_comp) { - s = splnet(); + s = splsoftnet(); vj_compress_init(sc->sc_comp, *(int *)data); splx(s); } @@ -399,7 +421,7 @@ pppioctl(sc, cmd, data, flag, p) */ error = 0; if (odp->transmit) { - s = splnet(); + s = splsoftnet(); if (sc->sc_xc_state != NULL) (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); sc->sc_xcomp = *cp; @@ -414,7 +436,7 @@ pppioctl(sc, cmd, data, flag, p) sc->sc_flags &= ~SC_COMP_RUN; splx(s); } else { - s = splnet(); + s = splsoftnet(); if (sc->sc_rc_state != NULL) (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); sc->sc_rcomp = *cp; @@ -454,7 +476,7 @@ pppioctl(sc, cmd, data, flag, p) if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) return (error); if (npi->mode != sc->sc_npmode[npx]) { - s = splnet(); + s = splsoftnet(); sc->sc_npmode[npx] = npi->mode; if (npi->mode != NPMODE_QUEUE) { ppp_requeue(sc); @@ -466,13 +488,47 @@ pppioctl(sc, cmd, data, flag, p) break; case PPPIOCGIDLE: - s = splnet(); + 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; +#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); } @@ -482,10 +538,10 @@ pppioctl(sc, cmd, data, flag, p) /* * 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 */ @@ -595,6 +651,8 @@ pppoutput(ifp, m0, dst, rtp) struct ip *ip; struct ifqueue *ifq; enum NPmode mode; + int len; + struct mbuf *m; if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0 || ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) { @@ -668,16 +726,43 @@ pppoutput(ifp, m0, dst, rtp) *cp++ = protocol & 0xff; m0->m_len += PPP_HDRLEN; + len = 0; + for (m = m0; m != 0; m = m->m_next) + len += m->m_len; + if (sc->sc_flags & SC_LOG_OUTPKT) { printf("ppp%d output: ", ifp->if_unit); pppdumpm(m0); } 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 @@ -691,7 +776,7 @@ pppoutput(ifp, m0, dst, rtp) /* * Put the packet on the appropriate queue. */ - s = splnet(); + s = splsoftnet(); if (mode == NPMODE_QUEUE) { /* XXX we should limit the number of packets on this queue */ *sc->sc_npqtail = m0; @@ -725,7 +810,7 @@ bad: /* * After a change in the NPmode for some NP, move packets from the * npqueue to the send queue or the fast queue as appropriate. - * Should be called at splnet. + * Should be called at splsoftnet. */ static void ppp_requeue(sc) @@ -776,7 +861,7 @@ ppp_requeue(sc) /* * Transmitter has finished outputting some stuff; - * remember to call sc->sc_start later at splnet. + * remember to call sc->sc_start later at splsoftnet. */ void ppp_restart(sc) @@ -791,7 +876,7 @@ ppp_restart(sc) /* * Get a packet to send. This procedure is intended to be called at - * splnet, since it may involve time-consuming operations such as + * 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. */ @@ -802,7 +887,6 @@ ppp_dequeue(sc) 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 @@ -882,13 +966,18 @@ ppp_dequeue(sc) for (mp = m; mp != NULL; mp = mp->m_next) slen += mp->m_len; clen = (*sc->sc_xcomp->compress) - (sc->sc_xc_state, &mcomp, m, slen, - (sc->sc_flags & SC_CCP_UP? sc->sc_if.if_mtu: 0)); + (sc->sc_xc_state, &mcomp, m, slen, sc->sc_if.if_mtu + PPP_HDRLEN); if (mcomp != NULL) { - m_freem(m); - m = mcomp; - cp = mtod(m, u_char *); - protocol = cp[3]; + 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); + } } } #endif /* PPP_COMPRESS */ @@ -917,7 +1006,7 @@ ppp_dequeue(sc) } /* - * Software interrupt routine, called at splnet. + * Software interrupt routine, called at splsoftnet. */ void pppintr() @@ -927,7 +1016,7 @@ pppintr() struct mbuf *m; sc = ppp_softc; - s = splnet(); + s = splsoftnet(); for (i = 0; i < NPPP; ++i, ++sc) { if (!(sc->sc_flags & SC_TBUSY) && (sc->sc_if.if_snd.ifq_head || sc->sc_fastq.ifq_head)) { @@ -1088,7 +1177,7 @@ ppppktin(sc, m, lost) /* * Process a received PPP packet, doing decompression as necessary. - * Should be called at splnet. + * Should be called at splsoftnet. */ #define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \ TYPE_UNCOMPRESSED_TCP) @@ -1282,11 +1371,32 @@ ppp_inproc(sc, m) 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