lkml.org 
[lkml]   [2000]   [Sep]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH] add PPP filtering
    Linus,

    The patch below adds the ability to filter packets going through a PPP
    interface. This allows users to specify that certain types of packets
    are not to count as activity, i.e. they don't reset the idle timer or
    bring up a demand-dialled link. This is something I have been getting
    a lot of requests for.

    It also allows users to specify that certain types of packets are to
    be dropped - this isn't a substitute for the netfilter stuff of
    course, but it comes virtually for free and it can sometimes be
    useful.

    (Users will need to use ppp-2.4.0 and compile pppd with the line in
    pppd/Makefile.linux that says "FILTER=y" uncommented.)

    I hope this can go into 2.4. It is a relatively small and
    self-contained set of changes. The only change to things outside the
    PPP generic module is a small change to make sure that sk_chk_filter
    is exported from the socket filtering code. There is also a small
    change where I have removed an unnecessary #include from
    ppp_channel.h.

    The files affected are:

    Documentation/Configure.help
    drivers/net/ppp_generic.c
    include/linux/filter.h
    include/linux/if_ppp.h
    include/linux/ppp_channel.h
    net/netsyms.c

    Regards,
    Paul.

    diff -urN linux/Documentation/Configure.help pmac/Documentation/Configure.help
    --- linux/Documentation/Configure.help Sat Sep 2 15:08:58 2000
    +++ pmac/Documentation/Configure.help Sat Sep 2 14:58:22 2000
    @@ -1748,6 +1748,10 @@
    certain types of data to get through the socket. Linux Socket
    Filtering works on all socket types except TCP for now. See the text
    file Documentation/networking/filter.txt for more information.
    +
    + You need to say Y here if you want to use PPP packet filtering
    + (see the CONFIG_PPP_FILTER option below).
    +
    If unsure, say N.

    Network packet filtering
    @@ -6719,6 +6723,17 @@

    This has to be supported at the other end as well and you need a
    version of the pppd daemon which understands the multilink protocol.
    +
    + If unsure, say N.
    +
    +PPP filtering (EXPERIMENTAL)
    +CONFIG_PPP_FILTER
    + Say Y here if you want to be able to filter the packets passing over
    + PPP interfaces. This allows you to control which packets count as
    + activity (i.e. which packets will reset the idle timer or bring up
    + a demand-dialled link) and which packets are to be dropped entirely.
    + You need to say Y here if you wish to use the pass-filter and
    + active-filter options to pppd.

    If unsure, say N.

    diff -urN linux/drivers/net/ppp_generic.c pmac/drivers/net/ppp_generic.c
    --- linux/drivers/net/ppp_generic.c Fri Jul 14 14:41:43 2000
    +++ pmac/drivers/net/ppp_generic.c Sat Sep 2 15:14:02 2000
    @@ -19,7 +19,7 @@
    * PPP driver, written by Michael Callahan and Al Longyear, and
    * subsequently hacked by Paul Mackerras.
    *
    - * ==FILEVERSION 20000417==
    + * ==FILEVERSION 20000902==
    */

    #include <linux/config.h>
    @@ -32,6 +32,7 @@
    #include <linux/netdevice.h>
    #include <linux/poll.h>
    #include <linux/ppp_defs.h>
    +#include <linux/filter.h>
    #include <linux/if_ppp.h>
    #include <linux/ppp_channel.h>
    #include <linux/ppp-comp.h>
    @@ -121,6 +122,10 @@
    struct sk_buff_head mrq; /* MP: receive reconstruction queue */
    #endif /* CONFIG_PPP_MULTILINK */
    struct net_device_stats stats; /* statistics */
    +#ifdef CONFIG_PPP_FILTER
    + struct sock_fprog pass_filter; /* filter for packets to pass */
    + struct sock_fprog active_filter;/* filter for pkts to reset idle */
    +#endif /* CONFIG_PPP_FILTER */
    };

    /*
    @@ -621,6 +626,43 @@
    err = 0;
    break;

    +#ifdef CONFIG_PPP_FILTER
    + case PPPIOCSPASS:
    + case PPPIOCSACTIVE:
    + {
    + struct sock_fprog uprog, *filtp;
    + struct sock_filter *code = NULL;
    + int len;
    +
    + if (copy_from_user(&uprog, (void *) arg, sizeof(uprog)))
    + break;
    + if (uprog.len > 0) {
    + err = -ENOMEM;
    + len = uprog.len * sizeof(struct sock_filter);
    + code = kmalloc(len, GFP_KERNEL);
    + if (code == 0)
    + break;
    + err = -EFAULT;
    + if (copy_from_user(code, uprog.filter, len))
    + break;
    + err = sk_chk_filter(code, uprog.len);
    + if (err) {
    + kfree(code);
    + break;
    + }
    + }
    + filtp = (cmd == PPPIOCSPASS)? &ppp->pass_filter: &ppp->active_filter;
    + ppp_lock(ppp);
    + if (filtp->filter)
    + kfree(filtp->filter);
    + filtp->filter = code;
    + filtp->len = uprog.len;
    + ppp_unlock(ppp);
    + err = 0;
    + break;
    + }
    +#endif /* CONFIG_PPP_FILTER */
    +
    #ifdef CONFIG_PPP_MULTILINK
    case PPPIOCSMRRU:
    if (get_user(val, (int *) arg))
    @@ -892,6 +934,33 @@
    int len;
    unsigned char *cp;

    + if (proto < 0x8000) {
    +#ifdef CONFIG_PPP_FILTER
    + /* check if we should pass this packet */
    + /* the filter instructions are constructed assuming
    + a four-byte PPP header on each packet */
    + *skb_push(skb, 2) = 1;
    + if (ppp->pass_filter.filter
    + && sk_run_filter(skb, ppp->pass_filter.filter,
    + ppp->pass_filter.len) == 0) {
    + if (ppp->debug & 1) {
    + printk(KERN_DEBUG "PPP: outbound frame not passed\n");
    + kfree_skb(skb);
    + return;
    + }
    + }
    + /* if this packet passes the active filter, record the time */
    + if (!(ppp->active_filter.filter
    + && sk_run_filter(skb, ppp->active_filter.filter,
    + ppp->active_filter.len) == 0))
    + ppp->last_xmit = jiffies;
    + skb_pull(skb, 2);
    +#else
    + /* for data packets, record the time */
    + ppp->last_xmit = jiffies;
    +#endif /* CONFIG_PPP_FILTER */
    + }
    +
    ++ppp->stats.tx_packets;
    ppp->stats.tx_bytes += skb->len - 2;

    @@ -964,10 +1033,6 @@
    }
    }

    - /* for data packets, record the time */
    - if (proto < 0x8000)
    - ppp->last_xmit = jiffies;
    -
    /*
    * If we are waiting for traffic (demand dialling),
    * queue it up for pppd to receive.
    @@ -1402,7 +1467,29 @@

    } else {
    /* network protocol frame - give it to the kernel */
    +
    +#ifdef CONFIG_PPP_FILTER
    + /* check if the packet passes the pass and active filters */
    + /* the filter instructions are constructed assuming
    + a four-byte PPP header on each packet */
    + *skb_push(skb, 2) = 0;
    + if (ppp->pass_filter.filter
    + && sk_run_filter(skb, ppp->pass_filter.filter,
    + ppp->pass_filter.len) == 0) {
    + if (ppp->debug & 1)
    + printk(KERN_DEBUG "PPP: inbound frame not passed\n");
    + kfree_skb(skb);
    + return;
    + }
    + if (!(ppp->active_filter.filter
    + && sk_run_filter(skb, ppp->active_filter.filter,
    + ppp->active_filter.len) == 0))
    + ppp->last_recv = jiffies;
    + skb_pull(skb, 2);
    +#else
    ppp->last_recv = jiffies;
    +#endif /* CONFIG_PPP_FILTER */
    +
    if ((ppp->dev->flags & IFF_UP) == 0
    || ppp->npmode[npi] != NPMODE_PASS) {
    kfree_skb(skb);
    @@ -2193,6 +2280,7 @@
    ppp->file.index = unit;
    ppp->mru = PPP_MRU;
    init_ppp_file(&ppp->file, INTERFACE);
    + ppp->file.hdrlen = PPP_HDRLEN - 2; /* don't count proto bytes */
    for (i = 0; i < NUM_NP; ++i)
    ppp->npmode[i] = NPMODE_PASS;
    INIT_LIST_HEAD(&ppp->channels);
    @@ -2264,6 +2352,16 @@
    #ifdef CONFIG_PPP_MULTILINK
    skb_queue_purge(&ppp->mrq);
    #endif /* CONFIG_PPP_MULTILINK */
    +#ifdef CONFIG_PPP_FILTER
    + if (ppp->pass_filter.filter) {
    + kfree(ppp->pass_filter.filter);
    + ppp->pass_filter.filter = NULL;
    + }
    + if (ppp->active_filter.filter) {
    + kfree(ppp->active_filter.filter);
    + ppp->active_filter.filter = 0;
    + }
    +#endif /* CONFIG_PPP_FILTER */
    dev = ppp->dev;
    ppp->dev = 0;
    ppp_unlock(ppp);
    diff -urN linux/include/linux/filter.h pmac/include/linux/filter.h
    --- linux/include/linux/filter.h Fri Apr 28 08:55:09 2000
    +++ pmac/include/linux/filter.h Mon Aug 7 11:29:07 2000
    @@ -135,6 +135,7 @@
    #ifdef __KERNEL__
    extern int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen);
    extern int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
    +extern int sk_chk_filter(struct sock_filter *filter, int flen);
    #endif /* __KERNEL__ */

    #endif /* __LINUX_FILTER_H__ */
    diff -urN linux/include/linux/if_ppp.h pmac/include/linux/if_ppp.h
    --- linux/include/linux/if_ppp.h Tue Mar 28 04:28:55 2000
    +++ pmac/include/linux/if_ppp.h Tue Jul 25 12:17:07 2000
    @@ -1,4 +1,4 @@
    -/* $Id: if_ppp.h,v 1.19 1999/03/31 06:07:57 paulus Exp $ */
    +/* $Id: if_ppp.h,v 1.21 2000/03/27 06:03:36 paulus Exp $ */

    /*
    * if_ppp.h - Point-to-Point Protocol definitions.
    @@ -21,7 +21,7 @@
    */

    /*
    - * ==FILEVERSION 20000324==
    + * ==FILEVERSION 20000724==
    *
    * NOTE TO MAINTAINERS:
    * If you modify this file at all, please set the above date.
    @@ -130,6 +130,8 @@
    #define PPPIOCSCOMPRESS _IOW('t', 77, struct ppp_option_data)
    #define PPPIOCGNPMODE _IOWR('t', 76, struct npioctl) /* get NP mode */
    #define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) /* set NP mode */
    +#define PPPIOCSPASS _IOW('t', 71, struct sock_fprog) /* set pass filter */
    +#define PPPIOCSACTIVE _IOW('t', 70, struct sock_fprog) /* set active filt */
    #define PPPIOCGDEBUG _IOR('t', 65, int) /* Read debug level */
    #define PPPIOCSDEBUG _IOW('t', 64, int) /* Set debug level */
    #define PPPIOCGIDLE _IOR('t', 63, struct ppp_idle) /* get idle time */
    diff -urN linux/include/linux/ppp_channel.h pmac/include/linux/ppp_channel.h
    --- linux/include/linux/ppp_channel.h Thu May 25 12:53:48 2000
    +++ pmac/include/linux/ppp_channel.h Wed Aug 30 14:48:06 2000
    @@ -22,7 +22,6 @@
    #include <linux/list.h>
    #include <linux/skbuff.h>
    #include <linux/poll.h>
    -#include <asm/atomic.h>

    struct ppp_channel;

    @@ -32,7 +31,6 @@
    int (*start_xmit)(struct ppp_channel *, struct sk_buff *);
    /* Handle an ioctl call that has come in via /dev/ppp. */
    int (*ioctl)(struct ppp_channel *, unsigned int, unsigned long);
    -
    };

    struct ppp_channel {
    diff -urN linux/net/netsyms.c pmac/net/netsyms.c
    --- linux/net/netsyms.c Thu Aug 24 17:52:19 2000
    +++ pmac/net/netsyms.c Fri Aug 25 11:20:12 2000
    @@ -141,6 +141,7 @@
    EXPORT_SYMBOL(sock_kfree_s);

    #ifdef CONFIG_FILTER
    +EXPORT_SYMBOL(sk_chk_filter);
    EXPORT_SYMBOL(sk_run_filter);
    #endif

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-03-22 12:38    [W:0.041 / U:0.636 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site