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    [from the cache]
©2003-2011 Jasper Spaans