Index: linux-2.6.12-rc3-Netfilter/include/linux/netfilter_ipv4/ipt_open_port.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.12-rc3-Netfilter/include/linux/netfilter_ipv4/ipt_open_port.h 2005-05-05 13:39:38.881764336 +1000 @@ -0,0 +1,5 @@ +#ifndef _IPT_OPEN_PORT_H +#define _IPT_OPEN_PORT_H + +/* For future expansion, and to indicate that this extension exists. */ +#endif /*_IPT_OPEN_PORT_H */ Index: linux-2.6.12-rc3-Netfilter/net/ipv4/netfilter/Kconfig =================================================================== --- linux-2.6.12-rc3-Netfilter.orig/net/ipv4/netfilter/Kconfig 2005-03-02 23:28:18.000000000 +1100 +++ linux-2.6.12-rc3-Netfilter/net/ipv4/netfilter/Kconfig 2005-05-05 12:12:02.000000000 +1000 @@ -375,6 +375,16 @@ destination IP' or `500pps from any given source IP' with a single IPtables rule. +config IP_NF_MATCH_OPEN_PORT + tristate 'TCP open port match support' + depends on IP_NF_IPTABLES && EXPERIMENTAL + help + This option adds a new iptables `open_port' match. + + This matches TCP packets in the INPUT (LOCAL_IN) chain which + are headed for an open TCP port. Some users like to drop packets + which would otherwise simply generate TCP RST responses. + # `filter', generic and specific targets config IP_NF_FILTER tristate "Packet filtering" Index: linux-2.6.12-rc3-Netfilter/net/ipv4/netfilter/Makefile =================================================================== --- linux-2.6.12-rc3-Netfilter.orig/net/ipv4/netfilter/Makefile 2005-03-02 23:28:18.000000000 +1100 +++ linux-2.6.12-rc3-Netfilter/net/ipv4/netfilter/Makefile 2005-05-05 12:35:46.000000000 +1000 @@ -59,6 +59,7 @@ obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o obj-$(CONFIG_IP_NF_MATCH_COMMENT) += ipt_comment.o +obj-$(CONFIG_IP_NF_MATCH_OPEN_PORT) += ipt_open_port.o # targets obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o Index: linux-2.6.12-rc3-Netfilter/net/ipv4/netfilter/ipt_open_port.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.12-rc3-Netfilter/net/ipv4/netfilter/ipt_open_port.c 2005-05-05 13:44:41.515756976 +1000 @@ -0,0 +1,111 @@ +/* Kernel module to match open (TCP) ports. */ + +/* Copyright (C) 2005 Rusty Russell, IBM Corporation. + * Part stolen from ipt_tcpmss.c Copyright (C) 2000 Marc Boucher + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Rusty Russell "); +MODULE_DESCRIPTION("iptables open TCP port matching module."); + +/* From tcp_ipv4.c */ +struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport,int dif); + +/* Stolen from tcp_ipv4.c */ +static __inline__ int tcp_v4_iif(const struct sk_buff *skb) +{ + return ((struct rtable *)skb->dst)->rt_iif; +} + +static int +match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + int *hotdrop) +{ + struct tcphdr _tcph, *th; + struct sock *sk; + + /* If we don't have the whole header, drop packet. */ + th = skb_header_pointer(skb, skb->nh.iph->ihl * 4, + sizeof(_tcph), &_tcph); + if (th == NULL) + goto dropit; + + /* Malformed. */ + if (th->doff*4 < sizeof(*th)) + goto dropit; + + sk = tcp_v4_lookup(skb->nh.iph->saddr, th->source, + skb->nh.iph->daddr, th->dest, tcp_v4_iif(skb)); + if (sk) { + if (sk->sk_state == TCP_TIME_WAIT) { + tcp_tw_put((struct tcp_tw_bucket *)sk); + return 0; + } + sock_put(sk); + return 1; + } + return 0; + +dropit: + *hotdrop = 1; + return 0; +} + +static int +checkentry(const char *tablename, + const struct ipt_ip *ip, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + if (matchsize != IPT_ALIGN(0)) + return 0; + + if (hook_mask & ~((1 << NF_IP_LOCAL_IN))) { + printk("ipt_open_port: only valid for LOCAL_IN.\n"); + return 0; + } + + /* Must specify -p tcp */ + if (ip->proto != IPPROTO_TCP || (ip->invflags & IPT_INV_PROTO)) { + printk("open_port: Only works on TCP packets\n"); + return 0; + } + + return 1; +} + +static struct ipt_match open_port_match = { + .name = "open_port", + .match = &match, + .checkentry = &checkentry, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + return ipt_register_match(&open_port_match); +} + +static void __exit fini(void) +{ + ipt_unregister_match(&open_port_match); +} + +module_init(init); +module_exit(fini);