From ad87b5f63767961a88676b65db8620affa643fb2 Mon Sep 17 00:00:00 2001 From: Detlef Wengorz Date: Sun, 10 Sep 2000 20:29:18 +0000 Subject: [PATCH] add support for iptables version 1.1.1 and 1.1.2 (alpha-state) for testing the user-space-tools (add-ons for iptables) are in the i4l-utilitys/isdnctrl directory --- drivers/isdn/Config.in | 14 + drivers/isdn/isdn_dwabc.c | 636 ++++++++++++++++++++++++++++++++++++- drivers/isdn/isdn_net.c | 106 +++++-- include/linux/isdn.h | 38 ++- include/linux/isdn_dwabc.h | 79 ++++- v2.2.13.ctrl | 3 + v2.2.ctrl | 3 + v2.3.ctrl | 3 + v2.4.ctrl | 3 + 9 files changed, 831 insertions(+), 54 deletions(-) diff --git a/drivers/isdn/Config.in b/drivers/isdn/Config.in index 96472ee1..970eabf1 100644 --- a/drivers/isdn/Config.in +++ b/drivers/isdn/Config.in @@ -31,6 +31,20 @@ if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then bool ' Rewrite socket and frame saddr-field (udp-ip4 only and very experimental)' CONFIG_ISDN_WITH_ABC_IPV4_RWUDP_SOCKADDR fi bool ' RX dont reset hanguptimeout' CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER + if [ "$CONFIG_NETFILTER" != "n" ]; then + if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then + bool ' Iptables-support (IPV4 kernel >= 2.4.0)' CONFIG_ISDN_WITH_ABC_IPTABLES_NETFILTER + fi + if [ "$CONFIG_IP6_NF_IPTABLES" != "n" ]; then + bool ' Iptables-support (IPV6 kernel >= 2.4.0)' CONFIG_ISDN_WITH_ABC_IPV6TABLES_NETFILTER + fi + bool ' Iptables_DWISDN target support (kernel >= 2.4.0' CONFIG_ISDN_WITH_ABC_IPT_TARGET + if [ "$CONFIG_ISDN_WITH_ABC_IPT_TARGET" != "n" ]; then + int ' skb->nfmark bit (1-32) for tx without huptime-reset' CONFIG_ISDN_WITH_ABC_IPT_TARGET_HBIT 25 + int ' Bit (1-32) for send icmp-unreach in offline case ' CONFIG_ISDN_WITH_ABC_IPT_TARGET_DBIT 26 + fi + fi + bool ' Support (device-channel)<->(bind-groups)' CONFIG_ISDN_WITH_ABC_ICALL_BIND bool ' Skip channel if used external (dial only)' CONFIG_ISDN_WITH_ABC_CH_EXTINUSE bool ' Support interface-auto-disable if config-error' CONFIG_ISDN_WITH_ABC_CONN_ERROR diff --git a/drivers/isdn/isdn_dwabc.c b/drivers/isdn/isdn_dwabc.c index 1aca9e53..403953cb 100644 --- a/drivers/isdn/isdn_dwabc.c +++ b/drivers/isdn/isdn_dwabc.c @@ -33,10 +33,38 @@ static char *dwabcrevison = "$Revision$"; #include +#define CONFIG_ISDN_WITH_ABC_NEED_DWSJIFFIES 1 #include #include "isdn_common.h" #include "isdn_net.h" +#if CONFIG_ISDN_WITH_ABC_IPTABLES_NETFILTER || CONFIG_ISDN_WITH_ABC_IPV6TABLES_NETFILTER +#include +#endif + +#ifdef CONFIG_ISDN_WITH_ABC_IPTABLES_NETFILTER +#include +static void dwabcnetfilter_init(void); +static void dwabcnetfilter_fini(void); +#define IPTV6_hook_priorities MYV6_nf_ip_hook_priorities +#endif + +#ifdef CONFIG_ISDN_WITH_ABC_IPV6TABLES_NETFILTER + +#ifdef IPTV6_hook_priorities +/* +** stop compiler warning (redefine of nf_ip_hook_priorities) +*/ +#define nf_ip_hook_priorities IPTV6_hook_priorities +#else +#define IPTV6_hook_priorities nf_ip_hook_priorities +#endif +#include +static void dwabcv6netfilter_init(void); +static void dwabcv6netfilter_fini(void); +#endif + + struct PSH { u_long saddr; u_long daddr; @@ -44,9 +72,9 @@ struct PSH { u_short len; }; +#include #ifdef CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE -#include #include #include #ifdef CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR @@ -70,7 +98,7 @@ static struct isdn_ppp_comp_data BSD_COMP_INIT_DATA; #endif #define NBYTEORDER_30BYTES 0x1e00 -#define DWABC_TMRES (HZ) +#define DWABC_TMRES (HZ / 10) //#define KEEPALIVE_VERBOSE 1 //#define DYNADDR_VERBOSE 1 @@ -540,16 +568,18 @@ void isdn_dw_clear_if(ulong pm,isdn_net_local *lp) static void dw_abc_timer_func(u_long dont_need_yet) { - static int recu = 0; + register u_long t; + + if(!((t = ++isdn_dwabc_jiffies.msec_100) & 1)) + if(isdn_dwabc_jiffies.msec_200++ & 1) + isdn_dwabc_jiffies.msec_400++; + if(!(t % 5)) + if(isdn_dwabc_jiffies.msec_500++ & 1) + isdn_dwabc_jiffies.msec_1000++; + dw_abc_timer.expires = jiffies + DWABC_TMRES; add_timer(&dw_abc_timer); - dwsjiffies++; - - if(test_and_set_bit(0,&recu)) - return; - - clear_bit(0,&recu); } @@ -1345,8 +1375,9 @@ void isdn_dw_abc_init_func(void) init_timer(&dw_abc_timer); dw_abc_timer.function = dw_abc_timer_func; + printk( KERN_INFO - "abc-extension %s\n" + "abc-extension %s Kernel 0x%06X\n" "written by\nDetlef Wengorz \n" "Thanks for test's etc. to:\n" "Mario Schugowski \n" @@ -1393,17 +1424,35 @@ void isdn_dw_abc_init_func(void) #endif #ifdef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS "CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS\n" +#endif +#ifdef CONFIG_ISDN_WITH_ABC_IPTABLES_NETFILTER + "CONFIG_ISDN_WITH_ABC_IPTABLES_NETFILTER\n" +#endif +#ifdef CONFIG_ISDN_WITH_ABC_IPV6TABLES_NETFILTER + "CONFIG_ISDN_WITH_ABC_IPV6TABLES_NETFILTER\n" #endif "loaded\n", - dwabcrevison); + dwabcrevison,LINUX_VERSION_CODE); dwsjiffies = 0; dw_abc_timer.expires = jiffies + DWABC_TMRES; add_timer(&dw_abc_timer); +#ifdef CONFIG_ISDN_WITH_ABC_IPTABLES_NETFILTER + dwabcnetfilter_init(); +#endif +#ifdef CONFIG_ISDN_WITH_ABC_IPV6TABLES_NETFILTER + dwabcv6netfilter_init(); +#endif } void isdn_dw_abc_release_func(void) { +#ifdef CONFIG_ISDN_WITH_ABC_IPTABLES_NETFILTER + dwabcnetfilter_fini(); +#endif +#ifdef CONFIG_ISDN_WITH_ABC_IPV6TABLES_NETFILTER + dwabcv6netfilter_fini(); +#endif del_timer(&dw_abc_timer); #ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT dw_lcr_clear_all(); @@ -1412,14 +1461,14 @@ void isdn_dw_abc_release_func(void) isdn_tcp_keepalive_done(); #endif printk( KERN_INFO - "abc-extension %s\n" + "abc-extension %s Kernel 0x%06X\n" "written by\n" "Detlef Wengorz \n" "Thanks for test's etc. to:\n" "Mario Schugowski \n" "unloaded\n" "For more details see http://i4l.mediatronix.de\n", - dwabcrevison); + dwabcrevison,LINUX_VERSION_CODE); } @@ -2274,4 +2323,565 @@ struct sk_buff *dwabc_bsd_compress(isdn_net_local *lp,struct sk_buff *skb,struct struct sk_buff *dwabc_bsd_rx_pkt(isdn_net_local *lp,struct sk_buff *skb,struct net_device *ndev) { return(skb); } #endif + + +#if CONFIG_ISDN_WITH_ABC_IPTABLES_NETFILTER || CONFIG_ISDN_WITH_ABC_IPV6TABLES_NETFILTER + +static isdn_net_local *dwisdn_get_lp(const struct net_device *nd) +{ + isdn_net_local *r = NULL; + + if(nd != NULL) { + + isdn_net_dev *p = dev->netdev; + int shl = 0; + + for(;shl < 5000 && p != NULL && &p->dev != nd;shl++,p = p->next); + + if(p != NULL && nd == &p->dev) + r = p->local; + } + + return(r); +} + + + +static int isdn_ipt_dwisdn( const struct net_device *in_ndev, + const struct net_device *out_ndev, + const void *info) +{ + int retw = 0; + + if(info != NULL) { + + int shl = 0; + const IPTDWISDN_INFO *dw = (IPTDWISDN_INFO *)info; + isdn_net_local *lp = NULL; + + if(dw->parcount > 0 && + (*dw->inst & ~IPT_DWISDN_NOT) == IPT_DWISDN_IDEV) { + + if(*dw->inst & IPT_DWISDN_NOT) + lp = dwisdn_get_lp(out_ndev); + else + lp = dwisdn_get_lp(in_ndev); + + shl = 1; + + } else lp = dwisdn_get_lp(out_ndev); + + retw = lp != NULL; + + for(;retw && shl < IPTDWISDN_MAXOPS && shl < dw->parcount; shl++) { + + enum iptdwisdn inst = dw->inst[shl]; + u_long v = dw->value[shl]; + int not; + + if((not = (inst & IPT_DWISDN_NOT))) + inst &= ~IPT_DWISDN_NOT; + + switch(inst) { + + default: + + printk(KERN_DEBUG + "ipt_dwisdn instruction %0x unknown\n",inst); + retw = 0; + break; + + case IPT_DWISDN_DIALMODE: + + retw = 0; + + switch(v) { + + case 1: + retw = ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO; + break; + + case 2: + retw = ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_MANUAL; + break; + + case 3: + retw = ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF; + break; + } + + break; + + case IPT_DWISDN_CBOUT: + + retw = 0; + + if(lp->flags & ISDN_NET_CALLBACK) { + + retw = !!(lp->flags & ISDN_NET_CBOUT); + + if(not) + retw = !retw; + } + + continue; + + case IPT_DWISDN_OUTGOING: + + if(lp->flags & ISDN_NET_CONNECTED) + retw = !!lp->outgoing; + else + retw = 0; + + break; + + case IPT_DWISDN_IDEV: + + if(not) + lp = dwisdn_get_lp(out_ndev); + else + lp = dwisdn_get_lp(in_ndev); + + retw = lp != NULL; + continue; + + case IPT_DWISDN_CHARGE: + + retw = lp->charge >= v; + break; + + case IPT_DWISDN_CON: + + retw = 0; + + if(v & IPTCS_DWISN_OFFL) { + + if(!(lp->flags & ISDN_NET_CONNECTED) && + !lp->dialstate) { + + retw = 1; + } + } + + if(v & IPTCS_DWISN_ONL) { + + if((lp->flags & ISDN_NET_CONNECTED) && + !lp->dialstate) { + + retw = 1; + } + } + + if(v & IPTCS_DWISN_DIAL) { + + if((lp->flags & ISDN_NET_CONNECTED) && + lp->dialstate) { + + retw = 1; + } + } + + break; + } + + if(not) + retw = !retw; + } + } + + return(retw); +} + + +static int dwisdn_match( const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + const void *hdr, + u_int16_t datalen, + int *hotdrop) +/************************************************************************ +*************************************************************************/ +{ + const IPTDWISDN_INFO *dw = matchinfo; + + if(dw == NULL) + return(0); + + return(isdn_ipt_dwisdn(in,out,dw)); +} + + +#ifdef CONFIG_ISDN_WITH_ABC_IPT_TARGET +static unsigned int DWISDN_target( + struct sk_buff **pskb, + unsigned int hooknum, + const struct net_device *in, + const struct net_device *out, + const void *info, + void *userinfo) +{ + unsigned int retw = IPT_CONTINUE; + + if(info != NULL) { + + int shl = 0; + const IPTDWISDN_INFO *dw = (IPTDWISDN_INFO *)info; + isdn_net_local *lp = dwisdn_get_lp(out); + struct sk_buff *p = (pskb != NULL) ? *pskb : NULL; + + for(shl = 0;shl < IPTDWISDN_MAXOPS && shl < dw->parcount; shl++) { + + enum tiptdwisdn inst = dw->inst[shl]; + u_long v = dw->value[shl]; + int not; + + if((not = (inst & TIPT_DWISDN_NOT))) + inst &= ~TIPT_DWISDN_NOT; + + switch(inst) { + + default: + + printk(KERN_DEBUG + "ipt_DWISDN instruction %0x unknown\n",inst); + break; + + case TIPT_DWISDN_HUPRESET: + + if(lp != NULL) + lp->huptimer = 0; + + break; + + case TIPT_DWISDN_DIALMODE: + + if(lp != NULL) { + + /* first all bits off */ + lp->flags &= ~ISDN_NET_DIALMODE_MASK; + + switch(v) { + case 1: lp->flags |= ISDN_NET_DM_AUTO; break; + case 2: lp->flags |= ISDN_NET_DM_MANUAL; break; + case 3: lp->flags |= ISDN_NET_DM_OFF; break; + } + } + + break; + + case TIPT_DWISDN_HANGUP: + + if(lp != NULL && (lp->flags & ISDN_NET_CONNECTED)) + isdn_net_hangup(&lp->netdev->dev); + + break; + + case TIPT_DWISDN_DIAL: + + if(lp != NULL && !(lp->flags & ISDN_NET_CONNECTED)) + isdn_net_force_dial_lp(lp); + + break; + + case TIPT_DWISDN_IDEV: + + lp = dwisdn_get_lp((not) ? out : in); + break; + + case TIPT_DWISDN_CLEAR: + + v = 0; + + if( CONFIG_ISDN_WITH_ABC_IPT_TARGET_HBIT > 0 && + CONFIG_ISDN_WITH_ABC_IPT_TARGET_HBIT < 33 ) { + + v |= (1lu << (CONFIG_ISDN_WITH_ABC_IPT_TARGET_HBIT -1)); + } + + if( CONFIG_ISDN_WITH_ABC_IPT_TARGET_DBIT > 0 && + CONFIG_ISDN_WITH_ABC_IPT_TARGET_DBIT < 33 ) { + + v |= (1lu << (CONFIG_ISDN_WITH_ABC_IPT_TARGET_DBIT -1)); + } + + if(p != NULL && (p->nfmark & v)) { + + p->nfmark &= ~v; + p->nfcache |= NFC_ALTERED; + } + + break; + + case TIPT_DWISDN_SET: + + v = 0; + + if( CONFIG_ISDN_WITH_ABC_IPT_TARGET_HBIT > 0 && + CONFIG_ISDN_WITH_ABC_IPT_TARGET_HBIT < 33 ) { + + v |= (1lu << (CONFIG_ISDN_WITH_ABC_IPT_TARGET_HBIT -1)); + } + + if(p != NULL && (p->nfmark & v) != v) { + + p->nfmark |= v; + p->nfcache |= NFC_ALTERED; + } + + break; + + case TIPT_DWISDN_UNREACH: + + v = 0; + + if( CONFIG_ISDN_WITH_ABC_IPT_TARGET_DBIT > 0 && + CONFIG_ISDN_WITH_ABC_IPT_TARGET_DBIT < 33 ) { + + v |= (1lu << (CONFIG_ISDN_WITH_ABC_IPT_TARGET_DBIT -1)); + } + + if(p != NULL && (p->nfmark & v) != v) { + + p->nfmark |= v; + p->nfcache |= NFC_ALTERED; + } + + break; + } + } + } + + return(retw); +} +#endif +#endif + +#ifdef CONFIG_ISDN_WITH_ABC_IPTABLES_NETFILTER + +static int dwisdn_checkentry( const char *tablename, + const struct ipt_ip *ip, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + const IPTDWISDN_INFO *dw = matchinfo; + + if (matchsize != IPT_ALIGN(sizeof(IPTDWISDN_INFO))) { + + printk(KERN_WARNING + "ipt_dwisdn: sizeof(IPTDWISDN_INFO) wrong (I think wrong Version)\n"); + + return 0; + } + + if(dw != NULL && dw->revision > IPTDWISDN_REVISION) { + + printk(KERN_WARNING + "ipt_dwisdn: iptables-revison > kernel-revision (%hu/%hu)\n", + dw->revision,IPTDWISDN_REVISION); + + return 0; + } + + return(1); +} + + +#ifdef CONFIG_ISDN_WITH_ABC_IPT_TARGET +static int DWISDN_checkentry( const char *tablename, + const struct ipt_entry *e, + void *targinfo, + unsigned int targinfosize, + unsigned int hook_mask) +{ + const IPTDWISDN_INFO *dt = targinfo; + + if (targinfosize != IPT_ALIGN(sizeof(IPTDWISDN_INFO))) { + + printk(KERN_WARNING + "ipt_DWISDN: sizeof(IPTDWISDN_INFO) wrong (I think wrong Version)\n"); + + return 0; + } + + if(dt != NULL && dt->revision > IPTDWISDN_REVISION) { + + printk(KERN_WARNING + "ipt_DWISDN: iptables-revison > kernel-revision (%hu/%hu)\n", + dt->revision,IPTDWISDN_REVISION); + + return 0; + } + + return 1; +} + + +static struct ipt_target ipt_DWISDN = { + + { NULL, NULL }, + "DWISDN", + DWISDN_target, + DWISDN_checkentry, + NULL, THIS_MODULE, +}; +#endif + + +static struct ipt_match ipt_dwisdn = { + + { NULL, NULL }, + "dwisdn", + dwisdn_match, + dwisdn_checkentry, + NULL, THIS_MODULE +}; + + +static void dwabcnetfilter_init(void) +{ + int r = ipt_register_match(&ipt_dwisdn); + + if(!r) + printk(KERN_WARNING "ipt_dwisdn: isdn-ipv4-netfilter installed\n"); + else + printk(KERN_WARNING + "ipt_dwisdn: isdn-ipv4-netfilter install failed (%d)\n",r); + +#ifdef CONFIG_ISDN_WITH_ABC_IPT_TARGET + r = ipt_register_target(&ipt_DWISDN); + + if(!r) + printk(KERN_WARNING "ipt_DWISDN: isdn-ipv4-netfilter installed\n"); + else + printk(KERN_WARNING + "ipt_DWISDN: isdn-ipv4-netfilter install failed (%d)\n",r); +#endif +} + + +static void dwabcnetfilter_fini(void) +{ + ipt_unregister_match(&ipt_dwisdn); +#ifdef CONFIG_ISDN_WITH_ABC_IPT_TARGET + ipt_unregister_target(&ipt_DWISDN); +#endif +} + +#endif + +#ifdef CONFIG_ISDN_WITH_ABC_IPV6TABLES_NETFILTER +static int dwisdn_checkentry_v6( const char *tablename, + const struct ip6t_ip6 *ip, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + const IPTDWISDN_INFO *dw = matchinfo; + + if (matchsize != IP6T_ALIGN(sizeof(IPTDWISDN_INFO))) { + + printk(KERN_WARNING + "ipt_dwisdn: sizeof(IPTDWISDN_INFO) wrong (I think wrong Version)\n"); + + return 0; + } + + if(dw != NULL && dw->revision > IPTDWISDN_REVISION) { + + printk(KERN_WARNING + "ipt_dwisdn: iptables-revison > kernel-revision (%hu/%hu)\n", + dw->revision,IPTDWISDN_REVISION); + + return 0; + } + + return(1); +} + + +static struct ip6t_match ip6t_dwisdn = { + + { NULL, NULL }, + "dwisdn", + dwisdn_match, + dwisdn_checkentry_v6, + NULL, THIS_MODULE +}; + +#ifdef CONFIG_ISDN_WITH_ABC_IPT_TARGET +static int DWISDN_checkentry_v6( + const char *tablename, + const struct ip6t_entry *ip, + void *targinfo, + unsigned int targinfosize, + unsigned int hook_mask) +{ + const IPTDWISDN_INFO *dt = targinfo; + + if (targinfosize != IP6T_ALIGN(sizeof(IPTDWISDN_INFO))) { + + printk(KERN_WARNING + "ipt_DWISDN: sizeof(IPTDWISDN_INFO) wrong (I think wrong Version)\n"); + + return 0; + } + + if(dt != NULL && dt->revision > IPTDWISDN_REVISION) { + + printk(KERN_WARNING + "ipt_DWISDN: iptables-revison > kernel-revision (%hu/%hu)\n", + dt->revision,IPTDWISDN_REVISION); + + return 0; + } + + return 1; +} + + +static struct ip6t_target ip6t_DWISDN = { + + { NULL, NULL }, + "DWISDN", + DWISDN_target, + DWISDN_checkentry_v6, + NULL, THIS_MODULE, +}; +#endif + + + +static void dwabcv6netfilter_init(void) +{ + int r = ip6t_register_match(&ip6t_dwisdn); + + if(!r) + printk(KERN_WARNING "ipt_dwisdn: isdn-ipv6-netfilter installed\n"); + else + printk(KERN_WARNING + "ipt_dwisdn: isdn-ipv6-netfilter install failed (%d)\n",r); + +#ifdef CONFIG_ISDN_WITH_ABC_IPT_TARGET + r = ip6t_register_target(&ip6t_DWISDN); + + if(!r) + printk(KERN_WARNING "ipt_DWISDN: isdn-ipv6-netfilter installed\n"); + else + printk(KERN_WARNING + "ipt_DWISDN: isdn-ipv6-netfilter install failed (%d)\n",r); +#endif +} + +static void dwabcv6netfilter_fini(void) +{ + ip6t_unregister_match(&ip6t_dwisdn); +#ifdef CONFIG_ISDN_WITH_ABC_IPT_TARGET + ip6t_unregister_target(&ip6t_DWISDN); +#endif +} + +#endif #endif diff --git a/drivers/isdn/isdn_net.c b/drivers/isdn/isdn_net.c index a2af5a55..b2d41feb 100644 --- a/drivers/isdn/isdn_net.c +++ b/drivers/isdn/isdn_net.c @@ -1416,6 +1416,15 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb) isdn_net_local *slp; isdn_net_local *lp = (isdn_net_local *) ndev->priv; int retv = 0; +#if CONFIG_ISDN_WITH_ABC && CONFIG_ISDN_WITH_ABC_IPT_TARGET + ulong old_huptimer = lp->huptimer; + + short d_reset_frame = + skb != NULL && + CONFIG_ISDN_WITH_ABC_IPT_TARGET_HBIT > 0 && + CONFIG_ISDN_WITH_ABC_IPT_TARGET_HBIT < 33 && + (skb->nfmark & ( 1lu << (CONFIG_ISDN_WITH_ABC_IPT_TARGET_HBIT - 1))); +#endif if (((isdn_net_local *) (ndev->priv))->master) { printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__); @@ -1426,12 +1435,19 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb) /* For the other encaps the header has already been built */ #ifdef CONFIG_ISDN_PPP if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) { +#if CONFIG_ISDN_WITH_ABC && CONFIG_ISDN_WITH_ABC_IPT_TARGET + int r = isdn_ppp_xmit(skb, ndev); + + if(d_reset_frame) + lp->huptimer = old_huptimer; + + return(r); +#else return isdn_ppp_xmit(skb, ndev); +#endif } #endif - nd = ((isdn_net_local *) ndev->priv)->netdev; - lp = isdn_net_get_locked_lp(nd); if (!lp) { printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name); @@ -1442,6 +1458,10 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb) /* Reset hangup-timeout */ lp->huptimer = 0; // FIXME? #ifdef CONFIG_ISDN_WITH_ABC +#ifdef CONFIG_ISDN_WITH_ABC_IPT_TARGET + if(d_reset_frame) + lp->huptimer = old_huptimer; +#endif #ifdef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS if( (lp->dw_abc_flags & ISDN_DW_ABC_FLAG_LEASED_LINE) && (lp->dw_abc_flags & ISDN_DW_ABC_FLAG_BSD_COMPRESS) && @@ -1451,7 +1471,7 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb) dwabc_bsd_first_gen(lp); } #endif - + { struct sk_buff *t_skb = NULL; @@ -1755,6 +1775,25 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) #endif if (!(lp->flags & ISDN_NET_CONNECTED)) { int chi; +#ifdef CONFIG_ISDN_WITH_ABC +#ifdef CONFIG_ISDN_WITH_ABC_IPT_TARGET + if( CONFIG_ISDN_WITH_ABC_IPT_TARGET_HBIT > 0 && + CONFIG_ISDN_WITH_ABC_IPT_TARGET_HBIT < 33 && + (skb->nfmark & ( 1lu << (CONFIG_ISDN_WITH_ABC_IPT_TARGET_HBIT - 1)))) { + + if( CONFIG_ISDN_WITH_ABC_IPT_TARGET_DBIT > 0 && + CONFIG_ISDN_WITH_ABC_IPT_TARGET_DBIT < 33 && + (skb->nfmark & ( 1lu << (CONFIG_ISDN_WITH_ABC_IPT_TARGET_DBIT - 1)))) { + + isdn_net_unreachable(ndev, skb, + "dial rejected: Iptables_DWISDN --hutimer --unreach"); + } + + dev_kfree_skb(skb); + return 0; + } +#endif +#endif /* only do autodial if allowed by config */ if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) { isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'"); @@ -2081,6 +2120,10 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb) #endif #ifdef CONFIG_ISDN_WITH_ABC struct net_device *ondev = ndev; +#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER + ulong lp_huptimer = 0; + ulong olp_huptimer = 0; +#endif #endif cisco_hdr *ch; @@ -2097,7 +2140,10 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb) lp->stats.rx_packets++; lp->stats.rx_bytes += skb->len; } - +#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER + lp_huptimer = lp->huptimer; + olp_huptimer = olp->huptimer; +#endif skb->dev = ndev; skb->pkt_type = PACKET_HOST; skb->mac.raw = skb->data; @@ -2107,26 +2153,14 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb) switch (lp->p_encap) { case ISDN_NET_ENCAP_ETHER: /* Ethernet over ISDN */ -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - if(!(olp->dw_abc_flags & ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER)) { -#endif olp->huptimer = 0; lp->huptimer = 0; -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - } -#endif skb->protocol = isdn_net_type_trans(skb, ndev); break; case ISDN_NET_ENCAP_UIHDLC: /* HDLC with UI-frame (for ispa with -h1 option) */ -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - if(!(olp->dw_abc_flags & ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER)) { -#endif olp->huptimer = 0; lp->huptimer = 0; -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - } -#endif skb_pull(skb, 2); /* Fall through */ case ISDN_NET_ENCAP_RAWIP: @@ -2157,15 +2191,9 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb) lp->stats.rx_bytes += skb->len - l; } } -#endif -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - if(!(olp->dw_abc_flags & ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER)) { #endif olp->huptimer = 0; lp->huptimer = 0; -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - } -#endif skb->protocol = htons(ETH_P_IP); #ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR if(isdn_dwabc_conerr_ippktok(skb)) @@ -2216,14 +2244,8 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb) /* Fall through */ case ISDN_NET_ENCAP_IPTYP: /* IP with type field */ -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - if(!(olp->dw_abc_flags & ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER)) { -#endif olp->huptimer = 0; lp->huptimer = 0; -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - } -#endif skb->protocol = *(unsigned short *) &(skb->data[0]); skb_pull(skb, 2); if (*(unsigned short *) skb->data == 0xFFFF) @@ -2236,18 +2258,20 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb) * huptimer on LCP packets. */ if (proto != PPP_LCP) { -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - if(!(olp->dw_abc_flags & ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER)) { -#endif olp->huptimer = 0; lp->huptimer = 0; -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - } -#endif } isdn_ppp_receive(lp->netdev, olp, skb); +#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER + if(olp->dw_abc_flags & ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER) { + + lp->huptimer = lp_huptimer + 1; + olp->huptimer = olp_huptimer+ 1; + } +#endif return; #endif + default: #ifdef CONFIG_ISDN_X25 /* try if there are generic sync_device receiver routines */ @@ -2256,6 +2280,12 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb) cprot -> pops -> data_ind(cprot,skb); #ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR lp->dw_abc_bchan_errcnt = 0; +#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER + if(olp->dw_abc_flags & ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER) { + lp->huptimer = lp_huptimer; + olp->huptimer = olp_huptimer; + } +#endif #endif return; }; @@ -2266,9 +2296,17 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb) return; } +#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR +#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER + if(olp->dw_abc_flags & ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER) { + lp->huptimer = lp_huptimer; + olp->huptimer = olp_huptimer; + } +#endif #ifdef CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE if(!(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_TCP_KEEPALIVE)) (void)isdn_dw_abc_ip4_keepalive_test(NULL,skb); +#endif #endif netif_rx(skb); return; diff --git a/include/linux/isdn.h b/include/linux/isdn.h index 62118cfc..fa4f48b6 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -70,10 +70,36 @@ #undef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS #undef CONFIG_ISDN_WITH_ABC_IPV4_RW_SOCKADDR #undef CONFIG_ISDN_WITH_ABC_IPV4_RWUDP_SOCKADDR +#undef CONFIG_ISDN_WITH_ABC_IPTABLES_NETFILTER +#undef CONFIG_ISDN_WITH_ABC_IPV6TABLES_NETFILTER +#undef CONFIG_ISDN_WITH_ABC_IPT_TARGET #else #include -volatile u_long dwsjiffies; +#ifndef CONFIG_NETFILTER +#undef CONFIG_ISDN_WITH_ABC_IPTABLES_NETFILTER +#endif + +#ifdef __KERNEL__ + +typedef struct DWABCJIFFIES { + + u_long msec_1000; + u_long msec_500; + u_long msec_400; + u_long msec_200; + u_long msec_100; + +} DWABCJIFFIES; + +#ifdef CONFIG_ISDN_WITH_ABC_NEED_DWSJIFFIES +DWABCJIFFIES isdn_dwabc_jiffies; +#else +extern DWABCJIFFIES isdn_dwabc_jiffies; +#endif +#define dwsjiffies (isdn_dwabc_jiffies.msec_1000) +#endif + #define ISDN_DW_ABC_FLAG_NO_TCP_KEEPALIVE 0x00000001L #define ISDN_DW_ABC_FLAG_NO_UDP_CHECK 0x00000002L #define ISDN_DW_ABC_FLAG_NO_UDP_HANGUP 0x00000004L @@ -88,13 +114,13 @@ volatile u_long dwsjiffies; #define ISDN_DW_ABC_FLAG_RWUDP_SOCKADDR 0x00000800L #define ISDN_DW_ABC_FLAG_LEASED_LINE 0x00001000L -#define ISDN_DW_ABC_IFFLAG_NODCHAN 0x00000001L -#define ISDN_DW_ABC_IFFLAG_BSDAKTIV 0x00000002L +#define ISDN_DW_ABC_IFFLAG_NODCHAN 0x00000001L +#define ISDN_DW_ABC_IFFLAG_BSDAKTIV 0x00000002L -#define ISDN_DW_ABC_BITLOCK_SEND 0 -#define ISDN_DW_ABC_BITLOCK_RECEIVE 1 +#define ISDN_DW_ABC_BITLOCK_SEND 0 +#define ISDN_DW_ABC_BITLOCK_RECEIVE 1 -#define ISDN_DW_ABC_MAX_CH_P_RIVER (32) +#define ISDN_DW_ABC_MAX_CH_P_RIVER (32) #endif diff --git a/include/linux/isdn_dwabc.h b/include/linux/isdn_dwabc.h index 15c97259..9c2ddd29 100644 --- a/include/linux/isdn_dwabc.h +++ b/include/linux/isdn_dwabc.h @@ -42,7 +42,84 @@ struct ISDN_DWABC_LCR_IOCTL { u_long lcr_ioctl_callid; /* callid from lcr-subsystem */ u_long lcr_ioctl_flags; /* see above */ char lcr_ioctl_nr[32]; /* new destination phonenumber */ - }; + +enum iptdwisdn { + IPT_DWISDN_NOT = 0x800, + IPT_DWISDN_CON = 1, + IPT_DWISDN_IDEV = 2, + IPT_DWISDN_CHARGE = 3, + IPT_DWISDN_OUTGOING = 4, + IPT_DWISDN_CBOUT = 5, + IPT_DWISDN_DIALMODE = 6, +}; + + +enum iptdwisdn_constat { + + IPTCS_DWISN_OFFL = 0x01, + IPTCS_DWISN_ONL = 0x02, + IPTCS_DWISN_DIAL = 0x04, +}; + +enum tiptdwisdn { + TIPT_DWISDN_NOT = 0x800, + TIPT_DWISDN_CLEAR = 1, + TIPT_DWISDN_SET = 2, + TIPT_DWISDN_DIAL = 3, + TIPT_DWISDN_HANGUP = 4, + TIPT_DWISDN_IDEV = 5, + TIPT_DWISDN_DIALMODE = 6, + TIPT_DWISDN_UNREACH = 7, + TIPT_DWISDN_HUPRESET = 8, +}; + + +#ifdef IPT_ISDN_DWISDN_H_NEED_OPTS +#include + +static struct option IPT_dwisdn_opts[] = { + + {"con_stat", 1,0,IPT_DWISDN_CON }, + {"in_dev", 0,0,IPT_DWISDN_IDEV }, + {"charge", 1,0,IPT_DWISDN_CHARGE }, + {"outgoing", 0,0,IPT_DWISDN_OUTGOING }, + {"cbout", 0,0,IPT_DWISDN_CBOUT }, + {"dialmode", 1,0,IPT_DWISDN_DIALMODE }, + {0}, +}; +#define IPTDWISDN_ANZOPS ((sizeof(IPT_dwisdn_opts)/sizeof(*IPT_dwisdn_opts))-1) +#endif + +#ifdef IPT_ISDN_DWISDN_TIPTH_NEED_OPTS +#include +static struct option TIPT_dwisdn_opts[] = { + {"clear", 0,0,TIPT_DWISDN_CLEAR }, + {"huptimer", 0,0,TIPT_DWISDN_SET }, + {"dial", 0,0,TIPT_DWISDN_DIAL }, + {"hangup", 0,0,TIPT_DWISDN_HANGUP }, + {"in_dev", 0,0,TIPT_DWISDN_IDEV }, + {"dialmode", 1,0,TIPT_DWISDN_DIALMODE }, + {"unreach", 0,0,TIPT_DWISDN_UNREACH }, + {"hupreset", 0,0,TIPT_DWISDN_HUPRESET }, + {0}, +}; +#define IPTDWISDN_ANZOPS ((sizeof(IPT_dwisdn_opts)/sizeof(*IPT_dwisdn_opts))-1) +#endif + +#define IPTDWISDN_MAXOPS 16 +#define IPTDWISDN_REVISION (u_short)2 + + +typedef struct IPTDWISDN_INFO { + + u_short revision; + u_short parcount; + + u_char inst[IPTDWISDN_MAXOPS]; + u_long value[IPTDWISDN_MAXOPS]; + +} IPTDWISDN_INFO; + #endif diff --git a/v2.2.13.ctrl b/v2.2.13.ctrl index eb065347..6e352ff2 100644 --- a/v2.2.13.ctrl +++ b/v2.2.13.ctrl @@ -46,6 +46,9 @@ #undef CONFIG_ISDN_WITH_ABC_CONN_ERROR #undef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS #undef CONFIG_ISDN_WITH_ABC_FRAME_LIMIT +#undef CONFIG_ISDN_WITH_ABC_IPTABLES_NETFILTER +#undef CONFIG_ISDN_WITH_ABC_IPV6TABLES_NETFILTER +#undef CONFIG_ISDN_WITH_ABC_IPT_TARGET #undef ISDN_NEW_TBUSY #delete #define ISDN_NEW_TBUSY #define COMPAT_NO_SOFTNET diff --git a/v2.2.ctrl b/v2.2.ctrl index 99214f3f..f66e3daf 100644 --- a/v2.2.ctrl +++ b/v2.2.ctrl @@ -53,6 +53,9 @@ #undef CONFIG_ISDN_WITH_ABC_CONN_ERROR #undef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS #undef CONFIG_ISDN_WITH_ABC_FRAME_LIMIT +#undef CONFIG_ISDN_WITH_ABC_IPTABLES_NETFILTER +#undef CONFIG_ISDN_WITH_ABC_IPV6TABLES_NETFILTER +#undef CONFIG_ISDN_WITH_ABC_IPT_TARGET #define COMPAT_NO_SOFTNET #undef HAVE_DEVFS_FS #define devfs_register_chrdev(m,n,f) register_chrdev(m,n,f) diff --git a/v2.3.ctrl b/v2.3.ctrl index 3e424d4e..ee46f7cf 100644 --- a/v2.3.ctrl +++ b/v2.3.ctrl @@ -48,6 +48,9 @@ #undef CONFIG_ISDN_WITH_ABC_CONN_ERROR #undef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS #undef CONFIG_ISDN_WITH_ABC_FRAME_LIMIT +#undef CONFIG_ISDN_WITH_ABC_IPTABLES_NETFILTER +#undef CONFIG_ISDN_WITH_ABC_IPV6TABLES_NETFILTER +#undef CONFIG_ISDN_WITH_ABC_IPT_TARGET #define BIG_PHONE_NUMBERS #undef COMPAT_NO_SOFTNET #define HAVE_DEVFS_FS diff --git a/v2.4.ctrl b/v2.4.ctrl index 9266484e..7a2e4b49 100644 --- a/v2.4.ctrl +++ b/v2.4.ctrl @@ -48,6 +48,9 @@ #undef CONFIG_ISDN_WITH_ABC_CONN_ERROR #undef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS #undef CONFIG_ISDN_WITH_ABC_FRAME_LIMIT +#undef CONFIG_ISDN_WITH_ABC_IPTABLES_NETFILTER +#undef CONFIG_ISDN_WITH_ABC_IPV6TABLES_NETFILTER +#undef CONFIG_ISDN_WITH_ABC_IPT_TARGET #define BIG_PHONE_NUMBERS #undef COMPAT_NO_SOFTNET #define HAVE_DEVFS_FS