diff -urN a/ipppd/configure.in b/ipppd/configure.in --- a/ipppd/configure.in 2002-07-19 20:51:41.000000000 +0200 +++ b/ipppd/configure.in 2003-09-05 00:06:42.000000000 +0200 @@ -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) diff -urN a/ipppd/ipppd.h b/ipppd/ipppd.h --- a/ipppd/ipppd.h 2002-07-06 02:34:08.000000000 +0200 +++ b/ipppd/ipppd.h 2003-09-05 00:06:42.000000000 +0200 @@ -215,6 +215,11 @@ #ifdef __linux__ extern int hostroute; /* Add a route to the host at the other end? */ #endif +#ifdef IPPP_FILTER +#include +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); diff -urN a/ipppd/ipppd.man.in b/ipppd/ipppd.man.in --- a/ipppd/ipppd.man.in 2000-10-05 22:45:25.000000000 +0200 +++ b/ipppd/ipppd.man.in 2003-09-05 00:06:42.000000000 +0200 @@ -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). @@ -515,6 +531,23 @@ will wait for the peer to authenticate itself with PAP to 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. protocol field compression disabled). diff -urN a/ipppd/ippp-filter-compat.h b/ipppd/ippp-filter-compat.h --- a/ipppd/ippp-filter-compat.h 1970-01-01 01:00:00.000000000 +0100 +++ b/ipppd/ippp-filter-compat.h 2003-09-05 00:07:04.000000000 +0200 @@ -0,0 +1,11 @@ +#ifndef _IPPP_FILTER_COMPAT_H +#define _IPPP_FILTER_COMPAT_H + +#ifndef PPPIOCSPASS +#define PPPIOCSPASS _IOW('t', 71, struct sock_fprog) /* set pass filter */ +#endif +#ifndef PPPIOCSACTIVE +#define PPPIOCSACTIVE _IOW('t', 70, struct sock_fprog) /* set active filt */ +#endif + +#endif /* _IPPP_FILTER_COMPAT_H */ diff -urN a/ipppd/main.c b/ipppd/main.c --- a/ipppd/main.c 2002-07-18 02:06:21.000000000 +0200 +++ b/ipppd/main.c 2003-09-05 00:06:42.000000000 +0200 @@ -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; } diff -urN a/ipppd/Makefile.in b/ipppd/Makefile.in --- a/ipppd/Makefile.in 2002-07-19 21:03:53.000000000 +0200 +++ b/ipppd/Makefile.in 2003-09-05 00:06:42.000000000 +0200 @@ -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) diff -urN a/ipppd/options.c b/ipppd/options.c --- a/ipppd/options.c 2002-07-06 02:34:08.000000000 +0200 +++ b/ipppd/options.c 2003-09-05 00:06:42.000000000 +0200 @@ -39,6 +39,10 @@ #include #endif +#ifdef IPPP_FILTER +#include +#endif /* IPPP_FILTER */ + #include "fsm.h" #include "ipppd.h" #include "pathnames.h" @@ -140,6 +144,10 @@ struct option_info auth_req_info; struct option_info devnam_info; +#ifdef IPPP_FILTER +struct bpf_program pass_filter;/* Filter program for packets to pass */ +struct bpf_program active_filter; /* Filter program for link-active pkts */ +#endif /* IPPP_FILTER */ /* * Prototypes @@ -292,6 +300,11 @@ int __P (radius_init ( void )); #endif +#ifdef IPPP_FILTER +static int setpassfilter __P((int,char **)); +static int setactivefilter __P((int,char **)); +#endif /* IPPP_FILTER */ + /* * Valid arguments. */ @@ -470,7 +483,10 @@ {"nohostroute", 0, setnohostroute}, /* Don't add host route */ #endif {"+force-driver",0,setforcedriver}, - +#ifdef IPPP_FILTER + { "pass-filter", 1, setpassfilter}, /* pass filter */ + { "active-filter", 1, setactivefilter}, /* link-active filter */ +#endif /* IPPP_FILTER */ {NULL, 0, NULL} }; @@ -2615,3 +2631,33 @@ force_driver = 1; return 1; } + +#ifdef IPPP_FILTER +/* + * setpassfilter - Set the pass filter for packets + */ +static int +setpassfilter(argc, argv) + int argc; + char **argv; +{ + if (pcap_compile_nopcap(PPP_HDRLEN, DLT_PPP, &pass_filter, *argv, 1, netmask) == 0) + return 1; + option_error("error in pass-filter expression.\n"); + return 0; +} + +/* + * setactivefilter - Set the active filter for packets + */ +static int +setactivefilter(argc, argv) + int argc; + char **argv; +{ + if (pcap_compile_nopcap(PPP_HDRLEN, DLT_PPP, &active_filter, *argv, 1, netmask) == 0) + return 1; + option_error("error in active-filter expression.\n"); + return 0; +} +#endif /* IPPP_FILTER */ diff -urN a/ipppd/sys-linux.c b/ipppd/sys-linux.c --- a/ipppd/sys-linux.c 2000-10-05 22:45:25.000000000 +0200 +++ b/ipppd/sys-linux.c 2003-09-05 00:06:42.000000000 +0200 @@ -57,6 +57,7 @@ #if defined __GLIBC__ && __GLIBC__ >= 2 # include # include +# include "ippp-filter-compat.h" # include # include "route.h" #else @@ -70,6 +71,11 @@ # include #endif +#ifdef IPPP_FILTER +#include +#include +#endif /* IPPP_FILTER */ + #include "fsm.h" #include "ipppd.h" #include "ipcp.h" @@ -515,6 +521,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. */