Skip to contentSkip to conversation

updated isdn ppp filters

PATCH New Patrick McHardy 1 participant 1 message Jun 3, 2003

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 updated isdn ppp filters

Hi Kai,
since 2.4.21 is coming soon i'm sending you an updated isdn ppp filter patch. The only change since the last version fixes a memory leak in an ioctl error path. I've also updated the ipppd man page (cut-n-paste from pppd).

To build ipppd run autoconf in ipppd subdir after patching and add "--enable-ippp-filter" to the configure options.

Please submit to Marcello if you are comfortable with it.

Best regards,
Patrick

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas:
# ChangeSet 1.1192 -> 1.1193
# include/linux/isdn_ppp.h 1.5 -> 1.6
# drivers/isdn/isdn_ppp.h 1.3 -> 1.4
# drivers/isdn/Config.in 1.20 -> 1.21
# drivers/isdn/isdn_ppp.c 1.21 -> 1.22
# Documentation/Configure.help 1.182 -> 1.183
# drivers/isdn/isdn_net.c 1.16 -> 1.17
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/06/03 [email protected] 1.1193
# [ISDN] isdn ppp filter
# --------------------------------------------
#

Documentation/Configure.help +11 -0
diff -Nru a/Documentation/Configure.help b/Documentation/Configure.help
@@ -20673,6 +20673,17 @@
   feature. See <file:Documentation/isdn/README.syncppp> and
   <file:Documentation/isdn/syncPPP.FAQ> for more information.
 
+PPP filtering for ISDN
+CONFIG_IPPP_FILTER
+  Say Y here if you want to be able to filter the packets passing over
+  IPPP 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 ipppd.
+
+  If unsure, say N.
+
 Support generic MP (RFC 1717)
 CONFIG_ISDN_MPP
   With synchronous PPP enabled, it is possible to increase throughput
drivers/isdn/Config.in +1 -0
diff -Nru a/drivers/isdn/Config.in b/drivers/isdn/Config.in
@@ -8,6 +8,7 @@
 if [ "$CONFIG_INET" != "n" ]; then
    bool '  Support synchronous PPP' CONFIG_ISDN_PPP
    if [ "$CONFIG_ISDN_PPP" != "n" ]; then
+      bool         '    PPP filtering for ISDN' CONFIG_IPPP_FILTER $CONFIG_FILTER
       bool         '    Use VJ-compression with synchronous PPP' CONFIG_ISDN_PPP_VJ
       bool         '    Support generic MP (RFC 1717)' CONFIG_ISDN_MPP
       dep_tristate '    Support BSD compression' CONFIG_ISDN_PPP_BSDCOMP $CONFIG_ISDN
drivers/isdn/isdn_net.c +11 -11
diff -Nru a/drivers/isdn/isdn_net.c b/drivers/isdn/isdn_net.c
@@ -1296,6 +1296,16 @@
 						restore_flags(flags);
 						return 0;	/* STN (skb to nirvana) ;) */
 					}
+#ifdef CONFIG_IPPP_FILTER
+					if (isdn_ppp_autodial_filter(skb, lp)) {
+						isdn_ppp_free(lp);
+						isdn_net_unbind_channel(lp);
+						restore_flags(flags);
+						isdn_net_unreachable(ndev, skb, "dial rejected: packet filtered");
+						dev_kfree_skb(skb);
+						return 0;
+					}
+#endif
 					restore_flags(flags);
 					isdn_net_dial();	/* Initiate dialing */
 					netif_stop_queue(ndev);
@@ -1793,9 +1803,6 @@
 {
 	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
 	isdn_net_local *olp = lp;	/* original 'lp' */
-#ifdef CONFIG_ISDN_PPP
-	int proto = PPP_PROTOCOL(skb->data);
-#endif
 #ifdef CONFIG_ISDN_X25
 	struct concap_proto *cprot = lp -> netdev -> cprot;
 #endif
@@ -1855,14 +1862,7 @@
 			break;
 #ifdef CONFIG_ISDN_PPP
 		case ISDN_NET_ENCAP_SYNCPPP:
-			/*
-			 * If encapsulation is syncppp, don't reset
-			 * huptimer on LCP packets.
-			 */
-			if (proto != PPP_LCP) {
-				olp->huptimer = 0;
-				lp->huptimer = 0;
-			}
+			/* huptimer is done in isdn_ppp_push_higher */
 			isdn_ppp_receive(lp->netdev, olp, skb);
 			return;
 #endif
drivers/isdn/isdn_ppp.c +155 -7

228 lines not on this page · raw message

drivers/isdn/isdn_ppp.h +1 -0
diff -Nru a/drivers/isdn/isdn_ppp.h b/drivers/isdn/isdn_ppp.h
@@ -19,6 +19,7 @@
 extern void isdn_ppp_cleanup(void);
 extern int isdn_ppp_free(isdn_net_local *);
 extern int isdn_ppp_bind(isdn_net_local *);
+extern int isdn_ppp_autodial_filter(struct sk_buff *, isdn_net_local *);
 extern int isdn_ppp_xmit(struct sk_buff *, struct net_device *);
 extern void isdn_ppp_receive(isdn_net_dev *, isdn_net_local *, struct sk_buff *);
 extern int isdn_ppp_dev_ioctl(struct net_device *, struct ifreq *, int);
include/linux/isdn_ppp.h +7 -0
diff -Nru a/include/linux/isdn_ppp.h b/include/linux/isdn_ppp.h
@@ -65,6 +65,9 @@
 
 #include <linux/config.h>
 
+#ifdef CONFIG_IPPP_FILTER
+#include <linux/filter.h>
+#endif
 
 #define DECOMP_ERR_NOMEM	(-10)
 
@@ -222,6 +225,10 @@
 #ifdef CONFIG_ISDN_PPP_VJ
   unsigned char *cbuf;
   struct slcompress *slcomp;
+#endif
+#ifdef CONFIG_IPPP_FILTER
+  struct sock_fprog pass_filter;	/* filter for packets to pass */
+  struct sock_fprog active_filter;	/* filter for pkts to reset idle */
 #endif
   unsigned long debug;
   struct isdn_ppp_compressor *compressor,*decompressor;

? ipppd/ippp-filter-compat.h
Index: ipppd/Makefile.in
===================================================================
RCS file: /i4ldev/isdn4k-utils/ipppd/Makefile.in,v retrieving revision 1.16

Makefile.in +5 -0
diff -u -r1.16 Makefile.in
@@ -7,6 +7,7 @@
 HAVE_LIBCRYPT := @HAVE_LIBCRYPT@
 HAVE_SHADOW_H := @HAVE_SHADOW_H@
 HAVE_LZSCOMP_H:= @HAVE_LZSCOMP_H@
+IPPP_FILTER   := @CONFIG_IPPP_FILTER@
 SBINDIR       := @CONFIG_SBINDIR@
 MANDIR        := @CONFIG_MANDIR@
 CC            := @CC@
@@ -77,6 +78,10 @@
 LIBS        = -lcrypt -lutil
 endif
 
+ifeq ($(IPPP_FILTER),1)
+CFLAGS     += -DIPPP_FILTER
+LIBS       += -lpcap
+endif
 
 SOURCE = RELNOTES configure *.in $(PPPDSRCS) $(HEADERS) $(MANPAGES)
 

Index: ipppd/configure.in
===================================================================
RCS file: /i4ldev/isdn4k-utils/ipppd/configure.in,v retrieving revision 1.8

configure.in +7 -0
diff -u -r1.8 configure.in
@@ -98,6 +98,12 @@
 	AC_DEFINE(CONFIG_IPPPD_DEBUGFLAGS,"-DDEBUGALL"),
 )
 
+AC_ARG_ENABLE(ippp-filter,
+	[  --enable-ippp-filter    Enable IPPP Filters (needs kernel supports) [no]],
+	CONFIG_IPPP_FILTER="1"
+	AC_DEFINE(CONFIG_IPPP_FILTER,"1"),
+)
+
 AC_SUBST(I4LVERSION)
 AC_SUBST(MANDATE)
 AC_SUBST(HAVE_LIBDES)
@@ -113,4 +119,5 @@
 AC_SUBST(RADIUS_CLIENT_CONFIG_FILE)
 AC_SUBST(CONFIG_RADIUS_WTMP_LOGGING)
 AC_SUBST(CONFIG_IPPPD_DEBUGFLAGS)
+AC_SUBST(CONFIG_IPPP_FILTER)
 AC_OUTPUT(Makefile ipppd.man pathnames.h)

Index: ipppd/ipppd.h
===================================================================
RCS file: /i4ldev/isdn4k-utils/ipppd/ipppd.h,v
retrieving revision 1.22

ipppd.h +8 -0
diff -u -r1.22 ipppd.h
@@ -215,6 +215,11 @@
 #ifdef __linux__
 extern int      hostroute;      /* Add a route to the host at the other end? */
 #endif
+#ifdef IPPP_FILTER
+#include <net/bpf.h>
+extern struct   bpf_program pass_filter;   /* Filter for pkts to pass */
+extern struct   bpf_program active_filter; /* Filter for link-active pkts */
+#endif /* IPPP_FILTER */
 
 /*
  * Values for phase.
@@ -288,6 +293,9 @@
 void link_terminated(int);
 void link_down(int);
 void link_established(int unit);
+#ifdef IPPP_FILTER
+int set_filters(int, struct bpf_program *, struct bpf_program *);
+#endif /* IPPP_FILTER */
 int device_script(char *program,int in,int out);
 void check_auth_options(void);
 void setipdefault(void);

Index: ipppd/ipppd.man.in
===================================================================
RCS file: /i4ldev/isdn4k-utils/ipppd/ipppd.man.in,v retrieving revision 1.10

ipppd.man.in +33 -0
diff -u -r1.10 ipppd.man.in
@@ -88,6 +88,22 @@
 .B ipcp-accept-remote
 options are given, respectively.
 .TP
+.B active-filter \fIfilter-expression
+Specifies a packet filter to be applied to data packets to determine
+which packets are to be regarded as link activity, and therefore reset
+the idle timer, or cause the link to be brought up in demand-dialling
+mode.  This option is useful in conjunction with the
+\fBidle\fR option if there are packets being sent or received
+regularly over the link (for example, routing information packets)
+which would otherwise prevent the link from ever appearing to be idle.
+The \fIfilter-expression\fR syntax is as described for tcpdump(1),
+except that qualifiers which are inappropriate for a PPP link, such as
+\fBether\fR and \fBarp\fR, are not permitted.  Generally the filter
+expression should be enclosed in single-quotes to prevent whitespace
+in the expression from being interpreted by the shell. This option
+is currently only available if both the kernel and ipppd were compiled
+with IPPP_FILTER defined.
+.TP
 .B -ac
 Disable Address/Control compression negotiation (use default, i.e.
 address/control field compression disabled).
@@ -514,6 +530,23 @@
 .I ipppd
 will wait for the peer to authenticate itself with PAP to
 <n> seconds (0 means no limit).
+.TP
+.B pass-filter \fIfilter-expression
+Specifies a packet filter to applied to data packets being sent or
+received to determine which packets should be allowed to pass.
+Packets which are rejected by the filter are silently discarded.  This
+option can be used to prevent specific network daemons (such as
+routed) using up link bandwidth, or to provide a basic firewall
+capability.
+The \fIfilter-expression\fR syntax is as described for tcpdump(1),
+except that qualifiers which are inappropriate for a PPP link, such as
+\fBether\fR and \fBarp\fR, are not permitted.  Generally the filter
+expression should be enclosed in single-quotes to prevent whitespace
+in the expression from being interpreted by the shell.  Note that it
+is possible to apply different constraints to incoming and outgoing
+packets using the \fBinbound\fR and \fBoutbound\fR qualifiers. This
+option is currently only available if both the kernel and ipppd were
+compiled with IPPP_FILTER defined.
 .TP
 .B -pc
 Disable protocol field compression negotiation (use default, i.e.

Index: ipppd/main.c
===================================================================
RCS file: /i4ldev/isdn4k-utils/ipppd/main.c,v
retrieving revision 1.24

main.c +3 -0
diff -u -r1.24 main.c
@@ -564,6 +564,9 @@
 	lns[linkunit].upap_unit = lns[linkunit].chap_unit = lns[linkunit].lcp_unit;
 	upap[lns[linkunit].upap_unit].us_unit = chap[lns[linkunit].chap_unit].unit = linkunit;
 	lcp_lowerup(lns[linkunit].lcp_unit);
+#ifdef IPPP_FILTER
+	set_filters(linkunit, &pass_filter, &active_filter);
+#endif /* IPPP_FILTER */
 
 	return 0;
 }

Index: ipppd/options.c
===================================================================
RCS file: /i4ldev/isdn4k-utils/ipppd/options.c,v
retrieving revision 1.23

options.c +47 -1

75 lines not on this page · raw message

Index: ipppd/sys-linux.c
===================================================================
RCS file: /i4ldev/isdn4k-utils/ipppd/sys-linux.c,v retrieving revision 1.25

sys-linux.c +40 -0
diff -u -r1.25 sys-linux.c
@@ -57,6 +57,7 @@
 #if defined __GLIBC__ && __GLIBC__ >= 2
 # include </usr/include/net/ppp_defs.h>
 # include </usr/include/net/if_ppp.h>
+# include "ippp-filter-compat.h"
 # include </usr/include/net/ethernet.h>
 # include "route.h"
 #else
@@ -70,6 +71,11 @@
 # include <netipx/ipx.h>
 #endif
 
+#ifdef IPPP_FILTER
+#include <net/bpf.h>
+#include <linux/filter.h>
+#endif /* IPPP_FILTER */
+
 #include "fsm.h"
 #include "ipppd.h"
 #include "ipcp.h"
@@ -514,6 +520,40 @@
 
 	return 1;
 }
+
+#ifdef IPPP_FILTER
+/*
+ * set_filters - set the active and pass filters in the kernel driver.
+ */
+int set_filters(int u, struct bpf_program *pass, struct bpf_program *active)
+{       
+        struct sock_fprog fp;
+
+	/*
+	 *  unfortunately there is no way of checking for kernel support. the
+	 *  driver just returns 0 for unsupported ioctls, which means without
+	 *  kernel support we won't even notice the error.
+	 */
+
+	if (pass) {
+		fp.len = pass->bf_len;
+		fp.filter = (struct sock_filter *) pass->bf_insns;
+		if (ioctl(lns[u].fd, PPPIOCSPASS, &fp) < 0) {
+			syslog(LOG_ERR, "Couldn't set pass-filter in kernel.");
+			return 0;
+		}
+	}
+	if (active) {
+		fp.len = active->bf_len;
+		fp.filter = (struct sock_filter *) active->bf_insns;
+		if (ioctl(lns[u].fd, PPPIOCSACTIVE, &fp) < 0) {
+			syslog(LOG_ERR, "Couldn't set active-filter in kernel.");
+	        	return 0;
+		}
+	}
+	return 1;
+}
+#endif /* IPPP_FILTER */
 
 /*
  * sifup - Config the interface up and enable IP packets to pass.