netfilter-2.6/patch-o-matic-ng/trunk: include/linux/netfilter_ipv4/ipt_ROUTE.h
include/linux/netfilt...
pluto
cvs at pld-linux.org
Thu Jul 28 11:55:34 CEST 2005
Author: pluto
Date: Thu Jul 28 11:55:24 2005
New Revision: 6250
Added:
netfilter-2.6/patch-o-matic-ng/trunk/include/linux/netfilter_ipv4/ipt_ROUTE.h
netfilter-2.6/patch-o-matic-ng/trunk/include/linux/netfilter_ipv4/ipt_connlimit.h
netfilter-2.6/patch-o-matic-ng/trunk/include/linux/netfilter_ipv6/ip6t_ROUTE.h
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_ROUTE.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_TARPIT.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_connlimit.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/ip6t_ROUTE.c
Modified:
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/Kconfig
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/Makefile
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/ipv6_syms.c
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/Kconfig
netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/Makefile
netfilter-2.6/patch-o-matic-ng/trunk/status
Log:
- ROUTE, TARPIT, connlimit.
Added: netfilter-2.6/patch-o-matic-ng/trunk/include/linux/netfilter_ipv4/ipt_ROUTE.h
==============================================================================
--- (empty file)
+++ netfilter-2.6/patch-o-matic-ng/trunk/include/linux/netfilter_ipv4/ipt_ROUTE.h Thu Jul 28 11:55:24 2005
@@ -0,0 +1,23 @@
+/* Header file for iptables ipt_ROUTE target
+ *
+ * (C) 2002 by Cédric de Launois <delaunois at info.ucl.ac.be>
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ */
+#ifndef _IPT_ROUTE_H_target
+#define _IPT_ROUTE_H_target
+
+#define IPT_ROUTE_IFNAMSIZ 16
+
+struct ipt_route_target_info {
+ char oif[IPT_ROUTE_IFNAMSIZ]; /* Output Interface Name */
+ char iif[IPT_ROUTE_IFNAMSIZ]; /* Input Interface Name */
+ u_int32_t gw; /* IP address of gateway */
+ u_int8_t flags;
+};
+
+/* Values for "flags" field */
+#define IPT_ROUTE_CONTINUE 0x01
+#define IPT_ROUTE_TEE 0x02
+
+#endif /*_IPT_ROUTE_H_target*/
Added: netfilter-2.6/patch-o-matic-ng/trunk/include/linux/netfilter_ipv4/ipt_connlimit.h
==============================================================================
--- (empty file)
+++ netfilter-2.6/patch-o-matic-ng/trunk/include/linux/netfilter_ipv4/ipt_connlimit.h Thu Jul 28 11:55:24 2005
@@ -0,0 +1,12 @@
+#ifndef _IPT_CONNLIMIT_H
+#define _IPT_CONNLIMIT_H
+
+struct ipt_connlimit_data;
+
+struct ipt_connlimit_info {
+ int limit;
+ int inverse;
+ u_int32_t mask;
+ struct ipt_connlimit_data *data;
+};
+#endif /* _IPT_CONNLIMIT_H */
Added: netfilter-2.6/patch-o-matic-ng/trunk/include/linux/netfilter_ipv6/ip6t_ROUTE.h
==============================================================================
--- (empty file)
+++ netfilter-2.6/patch-o-matic-ng/trunk/include/linux/netfilter_ipv6/ip6t_ROUTE.h Thu Jul 28 11:55:24 2005
@@ -0,0 +1,23 @@
+/* Header file for iptables ip6t_ROUTE target
+ *
+ * (C) 2003 by Cédric de Launois <delaunois at info.ucl.ac.be>
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ */
+#ifndef _IPT_ROUTE_H_target
+#define _IPT_ROUTE_H_target
+
+#define IP6T_ROUTE_IFNAMSIZ 16
+
+struct ip6t_route_target_info {
+ char oif[IP6T_ROUTE_IFNAMSIZ]; /* Output Interface Name */
+ char iif[IP6T_ROUTE_IFNAMSIZ]; /* Input Interface Name */
+ u_int32_t gw[4]; /* IPv6 address of gateway */
+ u_int8_t flags;
+};
+
+/* Values for "flags" field */
+#define IP6T_ROUTE_CONTINUE 0x01
+#define IP6T_ROUTE_TEE 0x02
+
+#endif /*_IP6T_ROUTE_H_target*/
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/Kconfig
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/Kconfig (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/Kconfig Thu Jul 28 11:55:24 2005
@@ -1068,5 +1068,49 @@
If you want to compile it as a module, say M here and read
Documentation/modules.txt. If unsure, say `N'.
+config IP_NF_TARGET_ROUTE
+ tristate 'ROUTE target support'
+ depends on IP_NF_MANGLE
+ help
+ This option adds a `ROUTE' target, which enables you to setup unusual
+ routes. For example, the ROUTE lets you route a received packet through
+ an interface or towards a host, even if the regular destination of the
+ packet is the router itself. The ROUTE target is also able to change the
+ incoming interface of a packet.
+
+ The target can be or not a final target. It has to be used inside the
+ mangle table.
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. The module will be called ipt_ROUTE.o.
+ If unsure, say `N'.
+
+config IP_NF_TARGET_TARPIT
+ tristate 'TARPIT target support'
+ depends on IP_NF_FILTER
+ help
+ Adds a TARPIT target to iptables, which captures and holds
+ incoming TCP connections using no local per-connection resources.
+ Connections are accepted, but immediately switched to the persist
+ state (0 byte window), in which the remote side stops sending data
+ and asks to continue every 60-240 seconds. Attempts to close the
+ connection are ignored, forcing the remote side to time out the
+ connection in 12-24 minutes.
+
+ This offers similar functionality to LaBrea
+ <http://www.hackbusters.net/LaBrea/> but doesn't require dedicated
+ hardware or IPs. Any TCP port that you would normally DROP or REJECT
+ can instead become a tarpit.
+
+config IP_NF_MATCH_CONNLIMIT
+ tristate 'Connections/IP limit match support'
+ depends on IP_NF_IPTABLES
+ help
+ This match allows you to restrict the number of parallel TCP
+ connections to a server per client IP address (or address block).
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. If unsure, say `N'.
+
endmenu
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/Makefile
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/Makefile (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/Makefile Thu Jul 28 11:55:24 2005
@@ -86,6 +86,7 @@
obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
+obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
@@ -97,6 +98,7 @@
# targets
obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
+obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
@@ -104,6 +106,7 @@
obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
+obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
Added: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_ROUTE.c
==============================================================================
--- (empty file)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_ROUTE.c Thu Jul 28 11:55:24 2005
@@ -0,0 +1,464 @@
+/*
+ * This implements the ROUTE target, which enables you to setup unusual
+ * routes not supported by the standard kernel routing table.
+ *
+ * Copyright (C) 2002 Cedric de Launois <delaunois at info.ucl.ac.be>
+ *
+ * v 1.11 2004/11/23
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ipt_ROUTE.h>
+#include <linux/netdevice.h>
+#include <linux/route.h>
+#include <net/ip.h>
+#include <net/route.h>
+#include <net/icmp.h>
+#include <net/checksum.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Cedric de Launois <delaunois at info.ucl.ac.be>");
+MODULE_DESCRIPTION("iptables ROUTE target module");
+
+/* Try to route the packet according to the routing keys specified in
+ * route_info. Keys are :
+ * - ifindex :
+ * 0 if no oif preferred,
+ * otherwise set to the index of the desired oif
+ * - route_info->gw :
+ * 0 if no gateway specified,
+ * otherwise set to the next host to which the pkt must be routed
+ * If success, skb->dev is the output device to which the packet must
+ * be sent and skb->dst is not NULL
+ *
+ * RETURN: -1 if an error occured
+ * 1 if the packet was succesfully routed to the
+ * destination desired
+ * 0 if the kernel routing table could not route the packet
+ * according to the keys specified
+ */
+static int route(struct sk_buff *skb,
+ unsigned int ifindex,
+ const struct ipt_route_target_info *route_info)
+{
+ int err;
+ struct rtable *rt;
+ struct iphdr *iph = skb->nh.iph;
+ struct flowi fl = {
+ .oif = ifindex,
+ .nl_u = {
+ .ip4_u = {
+ .daddr = iph->daddr,
+ .saddr = 0,
+ .tos = RT_TOS(iph->tos),
+ .scope = RT_SCOPE_UNIVERSE,
+ }
+ }
+ };
+
+ /* The destination address may be overloaded by the target */
+ if (route_info->gw)
+ fl.fl4_dst = route_info->gw;
+
+ /* Trying to route the packet using the standard routing table. */
+ if ((err = ip_route_output_key(&rt, &fl))) {
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
+ return -1;
+ }
+
+ /* Drop old route. */
+ dst_release(skb->dst);
+ skb->dst = NULL;
+
+ /* Success if no oif specified or if the oif correspond to the
+ * one desired */
+ if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
+ skb->dst = &rt->u.dst;
+ skb->dev = skb->dst->dev;
+ skb->protocol = htons(ETH_P_IP);
+ return 1;
+ }
+
+ /* The interface selected by the routing table is not the one
+ * specified by the user. This may happen because the dst address
+ * is one of our own addresses.
+ */
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n",
+ NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
+
+ return 0;
+}
+
+
+/* Stolen from ip_finish_output2
+ * PRE : skb->dev is set to the device we are leaving by
+ * skb->dst is not NULL
+ * POST: the packet is sent with the link layer header pushed
+ * the packet is destroyed
+ */
+static void ip_direct_send(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb->dst;
+ struct hh_cache *hh = dst->hh;
+ struct net_device *dev = dst->dev;
+ int hh_len = LL_RESERVED_SPACE(dev);
+
+ /* Be paranoid, rather than too clever. */
+ if (unlikely(skb_headroom(skb) < hh_len && dev->hard_header)) {
+ struct sk_buff *skb2;
+
+ skb2 = skb_realloc_headroom(skb, LL_RESERVED_SPACE(dev));
+ if (skb2 == NULL) {
+ kfree_skb(skb);
+ return;
+ }
+ if (skb->sk)
+ skb_set_owner_w(skb2, skb->sk);
+ kfree_skb(skb);
+ skb = skb2;
+ }
+
+ if (hh) {
+ int hh_alen;
+
+ read_lock_bh(&hh->hh_lock);
+ hh_alen = HH_DATA_ALIGN(hh->hh_len);
+ memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
+ read_unlock_bh(&hh->hh_lock);
+ skb_push(skb, hh->hh_len);
+ hh->hh_output(skb);
+ } else if (dst->neighbour)
+ dst->neighbour->output(skb);
+ else {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
+ kfree_skb(skb);
+ }
+}
+
+
+/* PRE : skb->dev is set to the device we are leaving by
+ * POST: - the packet is directly sent to the skb->dev device, without
+ * pushing the link layer header.
+ * - the packet is destroyed
+ */
+static inline int dev_direct_send(struct sk_buff *skb)
+{
+ return dev_queue_xmit(skb);
+}
+
+
+static unsigned int route_oif(const struct ipt_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ unsigned int ifindex = 0;
+ struct net_device *dev_out = NULL;
+
+ /* The user set the interface name to use.
+ * Getting the current interface index.
+ */
+ if ((dev_out = dev_get_by_name(route_info->oif))) {
+ ifindex = dev_out->ifindex;
+ } else {
+ /* Unknown interface name : packet dropped */
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
+ return NF_DROP;
+ }
+
+ /* Trying the standard way of routing packets */
+ switch (route(skb, ifindex, route_info)) {
+ case 1:
+ dev_put(dev_out);
+ if (route_info->flags & IPT_ROUTE_CONTINUE)
+ return IPT_CONTINUE;
+
+ ip_direct_send(skb);
+ return NF_STOLEN;
+
+ case 0:
+ /* Failed to send to oif. Trying the hard way */
+ if (route_info->flags & IPT_ROUTE_CONTINUE)
+ return NF_DROP;
+
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: forcing the use of %i\n",
+ ifindex);
+
+ /* We have to force the use of an interface.
+ * This interface must be a tunnel interface since
+ * otherwise we can't guess the hw address for
+ * the packet. For a tunnel interface, no hw address
+ * is needed.
+ */
+ if ((dev_out->type != ARPHRD_TUNNEL)
+ && (dev_out->type != ARPHRD_IPGRE)) {
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
+ dev_put(dev_out);
+ return NF_DROP;
+ }
+
+ /* Send the packet. This will also free skb
+ * Do not go through the POST_ROUTING hook because
+ * skb->dst is not set and because it will probably
+ * get confused by the destination IP address.
+ */
+ skb->dev = dev_out;
+ dev_direct_send(skb);
+ dev_put(dev_out);
+ return NF_STOLEN;
+
+ default:
+ /* Unexpected error */
+ dev_put(dev_out);
+ return NF_DROP;
+ }
+}
+
+
+static unsigned int route_iif(const struct ipt_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ struct net_device *dev_in = NULL;
+
+ /* Getting the current interface index. */
+ if (!(dev_in = dev_get_by_name(route_info->iif))) {
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->iif);
+ return NF_DROP;
+ }
+
+ skb->dev = dev_in;
+ dst_release(skb->dst);
+ skb->dst = NULL;
+
+ netif_rx(skb);
+ dev_put(dev_in);
+ return NF_STOLEN;
+}
+
+
+static unsigned int route_gw(const struct ipt_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ if (route(skb, 0, route_info)!=1)
+ return NF_DROP;
+
+ if (route_info->flags & IPT_ROUTE_CONTINUE)
+ return IPT_CONTINUE;
+
+ ip_direct_send(skb);
+ return NF_STOLEN;
+}
+
+
+/* To detect and deter routed packet loopback when using the --tee option,
+ * we take a page out of the raw.patch book: on the copied skb, we set up
+ * a fake ->nfct entry, pointing to the local &route_tee_track. We skip
+ * routing packets when we see they already have that ->nfct.
+ */
+
+static struct ip_conntrack route_tee_track;
+
+static unsigned int ipt_route_target(struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int hooknum,
+ const void *targinfo,
+ void *userinfo)
+{
+ const struct ipt_route_target_info *route_info = targinfo;
+ struct sk_buff *skb = *pskb;
+ unsigned int res;
+
+ if (skb->nfct == &route_tee_track.ct_general) {
+ /* Loopback - a packet we already routed, is to be
+ * routed another time. Avoid that, now.
+ */
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ipt_ROUTE: loopback - DROP!\n");
+ return NF_DROP;
+ }
+
+ /* If we are at PREROUTING or INPUT hook
+ * the TTL isn't decreased by the IP stack
+ */
+ if (hooknum == NF_IP_PRE_ROUTING ||
+ hooknum == NF_IP_LOCAL_IN) {
+
+ struct iphdr *iph = skb->nh.iph;
+
+ if (iph->ttl <= 1) {
+ struct rtable *rt;
+ struct flowi fl = {
+ .oif = 0,
+ .nl_u = {
+ .ip4_u = {
+ .daddr = iph->daddr,
+ .saddr = iph->saddr,
+ .tos = RT_TOS(iph->tos),
+ .scope = ((iph->tos & RTO_ONLINK) ?
+ RT_SCOPE_LINK :
+ RT_SCOPE_UNIVERSE)
+ }
+ }
+ };
+
+ if (ip_route_output_key(&rt, &fl)) {
+ return NF_DROP;
+ }
+
+ if (skb->dev == rt->u.dst.dev) {
+ /* Drop old route. */
+ dst_release(skb->dst);
+ skb->dst = &rt->u.dst;
+
+ /* this will traverse normal stack, and
+ * thus call conntrack on the icmp packet */
+ icmp_send(skb, ICMP_TIME_EXCEEDED,
+ ICMP_EXC_TTL, 0);
+ }
+
+ return NF_DROP;
+ }
+
+ /*
+ * If we are at INPUT the checksum must be recalculated since
+ * the length could change as the result of a defragmentation.
+ */
+ if(hooknum == NF_IP_LOCAL_IN) {
+ iph->ttl = iph->ttl - 1;
+ iph->check = 0;
+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+ } else {
+ ip_decrease_ttl(iph);
+ }
+ }
+
+ if ((route_info->flags & IPT_ROUTE_TEE)) {
+ /*
+ * Copy the *pskb, and route the copy. Will later return
+ * IPT_CONTINUE for the original skb, which should continue
+ * on its way as if nothing happened. The copy should be
+ * independantly delivered to the ROUTE --gw.
+ */
+ skb = skb_copy(*pskb, GFP_ATOMIC);
+ if (!skb) {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ipt_ROUTE: copy failed!\n");
+ return IPT_CONTINUE;
+ }
+ }
+
+ /* Tell conntrack to forget this packet since it may get confused
+ * when a packet is leaving with dst address == our address.
+ * Good idea ? Dunno. Need advice.
+ *
+ * NEW: mark the skb with our &route_tee_track, so we avoid looping
+ * on any already routed packet.
+ */
+ if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
+ nf_conntrack_put(skb->nfct);
+ skb->nfct = &route_tee_track.ct_general;
+ skb->nfctinfo = IP_CT_NEW;
+ nf_conntrack_get(skb->nfct);
+ skb->nfcache = 0;
+#ifdef CONFIG_NETFILTER_DEBUG
+ skb->nf_debug = 0;
+#endif
+ }
+
+ if (route_info->oif[0] != '\0') {
+ res = route_oif(route_info, skb);
+ } else if (route_info->iif[0] != '\0') {
+ res = route_iif(route_info, skb);
+ } else if (route_info->gw) {
+ res = route_gw(route_info, skb);
+ } else {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
+ res = IPT_CONTINUE;
+ }
+
+ if ((route_info->flags & IPT_ROUTE_TEE))
+ res = IPT_CONTINUE;
+
+ return res;
+}
+
+
+static int ipt_route_checkentry(const char *tablename,
+ const struct ipt_entry *e,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ if (strcmp(tablename, "mangle") != 0) {
+ printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
+ tablename);
+ return 0;
+ }
+
+ if (hook_mask & ~( (1 << NF_IP_PRE_ROUTING)
+ | (1 << NF_IP_LOCAL_IN)
+ | (1 << NF_IP_FORWARD)
+ | (1 << NF_IP_LOCAL_OUT)
+ | (1 << NF_IP_POST_ROUTING))) {
+ printk("ipt_ROUTE: bad hook\n");
+ return 0;
+ }
+
+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
+ printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
+ targinfosize,
+ IPT_ALIGN(sizeof(struct ipt_route_target_info)));
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static struct ipt_target ipt_route_reg = {
+ .name = "ROUTE",
+ .target = ipt_route_target,
+ .checkentry = ipt_route_checkentry,
+ .me = THIS_MODULE,
+};
+
+static int __init init(void)
+{
+ /* Set up fake conntrack (stolen from raw.patch):
+ - to never be deleted, not in any hashes */
+ atomic_set(&route_tee_track.ct_general.use, 1);
+ /* - and look it like as a confirmed connection */
+ set_bit(IPS_CONFIRMED_BIT, &route_tee_track.status);
+ /* Initialize fake conntrack so that NAT will skip it */
+ route_tee_track.status |= IPS_NAT_DONE_MASK;
+
+ return ipt_register_target(&ipt_route_reg);
+}
+
+
+static void __exit fini(void)
+{
+ ipt_unregister_target(&ipt_route_reg);
+}
+
+module_init(init);
+module_exit(fini);
Added: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_TARPIT.c
==============================================================================
--- (empty file)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_TARPIT.c Thu Jul 28 11:55:24 2005
@@ -0,0 +1,295 @@
+/*
+ * Kernel module to capture and hold incoming TCP connections using
+ * no local per-connection resources.
+ *
+ * Based on ipt_REJECT.c and offering functionality similar to
+ * LaBrea <http://www.hackbusters.net/LaBrea/>.
+ *
+ * Copyright (c) 2002 Aaron Hopkins <tools at die.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Goal:
+ * - Allow incoming TCP connections to be established.
+ * - Passing data should result in the connection being switched to the
+ * persist state (0 byte window), in which the remote side stops sending
+ * data and asks to continue every 60 seconds.
+ * - Attempts to shut down the connection should be ignored completely, so
+ * the remote side ends up having to time it out.
+ *
+ * This means:
+ * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
+ * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
+ * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <net/icmp.h>
+struct in_device;
+#include <net/route.h>
+#include <linux/random.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Aaron Hopkins <tools at die.net>");
+
+/* Stolen from ip_finish_output2 */
+static int ip_direct_send(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb->dst;
+ struct hh_cache *hh = dst->hh;
+
+ if (hh) {
+ read_lock_bh(&hh->hh_lock);
+ memcpy(skb->data - 16, hh->hh_data, 16);
+ read_unlock_bh(&hh->hh_lock);
+ skb_push(skb, hh->hh_len);
+ return hh->hh_output(skb);
+ } else if (dst->neighbour)
+ return dst->neighbour->output(skb);
+
+ if (net_ratelimit())
+ printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
+ kfree_skb(skb);
+ return -EINVAL;
+}
+
+
+/* Send reply */
+static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
+{
+ struct sk_buff *nskb;
+ struct rtable *nrt;
+ struct tcphdr *otcph, *ntcph;
+ struct flowi fl = {};
+ unsigned int otcplen;
+ u_int16_t tmp;
+
+ /* A truncated TCP header isn't going to be useful */
+ if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
+ return;
+
+ otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph
+ + oskb->nh.iph->ihl);
+ otcplen = oskb->len - oskb->nh.iph->ihl*4;
+
+ /* No replies for RST or FIN */
+ if (otcph->rst || otcph->fin)
+ return;
+
+ /* No reply to !SYN,!ACK. Rate-limit replies to !SYN,ACKs */
+ if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
+ return;
+
+ /* Check checksum. */
+ if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
+ oskb->nh.iph->daddr,
+ csum_partial((char *)otcph, otcplen, 0)) != 0)
+ return;
+
+ /* Copy skb (even if skb is about to be dropped, we can't just
+ clone it because there may be other things, such as tcpdump,
+ interested in it) */
+ nskb = skb_copy(oskb, GFP_ATOMIC);
+ if (!nskb)
+ return;
+
+ /* This packet will not be the same as the other: clear nf fields */
+ nf_conntrack_put(nskb->nfct);
+ nskb->nfct = NULL;
+ nskb->nfcache = 0;
+#ifdef CONFIG_NETFILTER_DEBUG
+ nskb->nf_debug = 0;
+#endif
+
+ ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
+
+ /* Truncate to length (no data) */
+ ntcph->doff = sizeof(struct tcphdr)/4;
+ skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
+ nskb->nh.iph->tot_len = htons(nskb->len);
+
+ /* Swap source and dest */
+ nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
+ tmp = ntcph->source;
+ ntcph->source = ntcph->dest;
+ ntcph->dest = tmp;
+
+ /* Use supplied sequence number or make a new one */
+ ntcph->seq = otcph->ack ? otcph->ack_seq
+ : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr,
+ nskb->nh.iph->daddr,
+ ntcph->source,
+ ntcph->dest));
+
+ /* Our SYN-ACKs must have a >0 window */
+ ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
+
+ ntcph->urg_ptr = 0;
+
+ /* Reset flags */
+ ((u_int8_t *)ntcph)[13] = 0;
+
+ if (otcph->syn && otcph->ack) {
+ ntcph->rst = 1;
+ ntcph->ack_seq = 0;
+ } else {
+ ntcph->syn = otcph->syn;
+ ntcph->ack = 1;
+ ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
+ }
+
+ /* Adjust TCP checksum */
+ ntcph->check = 0;
+ ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
+ nskb->nh.iph->saddr,
+ nskb->nh.iph->daddr,
+ csum_partial((char *)ntcph,
+ sizeof(struct tcphdr), 0));
+
+ /* Adjust IP TTL */
+ nskb->nh.iph->ttl = sysctl_ip_default_ttl;
+
+ /* Set DF, id = 0 */
+ nskb->nh.iph->frag_off = htons(IP_DF);
+ nskb->nh.iph->id = 0;
+
+ /* Adjust IP checksum */
+ nskb->nh.iph->check = 0;
+ nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
+ nskb->nh.iph->ihl);
+
+ fl.nl_u.ip4_u.daddr = nskb->nh.iph->daddr;
+ fl.nl_u.ip4_u.saddr = local ? nskb->nh.iph->saddr : 0;
+ fl.nl_u.ip4_u.tos = RT_TOS(nskb->nh.iph->tos) | RTO_CONN;
+ fl.oif = 0;
+
+ if (ip_route_output_key(&nrt, &fl))
+ goto free_nskb;
+
+ dst_release(nskb->dst);
+ nskb->dst = &nrt->u.dst;
+
+ /* "Never happens" */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
+ if (nskb->len > dst_mtu(nskb->dst))
+#else
+ if (nskb->len > dst_pmtu(nskb->dst))
+#endif
+ goto free_nskb;
+
+ ip_direct_send (nskb);
+
+ return;
+
+ free_nskb:
+ kfree_skb(nskb);
+}
+
+
+static unsigned int tarpit(struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int hooknum,
+ const void *targinfo,
+ void *userinfo)
+{
+ struct sk_buff *skb = *pskb;
+ struct rtable *rt = (struct rtable*)skb->dst;
+
+ /* Do we have an input route cache entry? */
+ if (!rt)
+ return NF_DROP;
+
+ /* No replies to physical multicast/broadcast */
+ if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
+ return NF_DROP;
+
+ /* Now check at the protocol level */
+ if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
+ return NF_DROP;
+
+ /* Our naive response construction doesn't deal with IP
+ options, and probably shouldn't try. */
+ if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
+ return NF_DROP;
+
+ /* We aren't interested in fragments */
+ if (skb->nh.iph->frag_off & htons(IP_OFFSET))
+ return NF_DROP;
+
+ tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
+
+ return NF_DROP;
+}
+
+
+static int check(const char *tablename,
+ const struct ipt_entry *e,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ /* Only allow these for input/forward packet filtering. */
+ if (strcmp(tablename, "filter") != 0) {
+ DEBUGP("TARPIT: bad table %s'.\n", tablename);
+ return 0;
+ }
+ if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
+ | (1 << NF_IP_FORWARD))) != 0) {
+ DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
+ return 0;
+ }
+
+ /* Must specify that it's a TCP packet */
+ if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
+ DEBUGP("TARPIT: not valid for non-tcp\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct ipt_target ipt_tarpit_reg = {
+ .name = "TARPIT",
+ .target = tarpit,
+ .checkentry = check,
+ .me = THIS_MODULE
+};
+
+static int __init init(void)
+{
+ return ipt_register_target(&ipt_tarpit_reg);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_target(&ipt_tarpit_reg);
+}
+
+module_init(init);
+module_exit(fini);
Added: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_connlimit.c
==============================================================================
--- (empty file)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_connlimit.c Thu Jul 28 11:55:24 2005
@@ -0,0 +1,228 @@
+/*
+ * netfilter module to limit the number of parallel tcp
+ * connections per IP address.
+ * (c) 2000 Gerd Knorr <kraxel at bytesex.org>
+ * Nov 2002: Martin Bene <martin.bene at icomedias.com>:
+ * only ignore TIME_WAIT or gone connections
+ *
+ * based on ...
+ *
+ * Kernel module to match connection tracking information.
+ * GPL (C) 1999 Rusty Russell (rusty at rustcorp.com.au).
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/list.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
+#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_connlimit.h>
+
+#define DEBUG 0
+
+MODULE_LICENSE("GPL");
+
+/* we'll save the tuples of all connections we care about */
+struct ipt_connlimit_conn
+{
+ struct list_head list;
+ struct ip_conntrack_tuple tuple;
+};
+
+struct ipt_connlimit_data {
+ spinlock_t lock;
+ struct list_head iphash[256];
+};
+
+static inline unsigned ipt_iphash(const unsigned addr)
+{
+ return ((addr ^ (addr >> 8) ^ (addr >> 16) ^ (addr >> 24)) & 0xff);
+}
+
+static int count_them(struct ipt_connlimit_data *data,
+ u_int32_t addr, u_int32_t mask,
+ struct ip_conntrack *ct)
+{
+#if DEBUG
+ const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
+ "fin_wait", "time_wait", "close", "close_wait",
+ "last_ack", "listen" };
+#endif
+ int addit = 1, matches = 0;
+ struct ip_conntrack_tuple tuple;
+ struct ip_conntrack_tuple_hash *found;
+ struct ipt_connlimit_conn *conn;
+ struct list_head *hash,*lh;
+
+ spin_lock_bh(&data->lock);
+ tuple = ct->tuplehash[0].tuple;
+ hash = &data->iphash[ipt_iphash(addr & mask)];
+
+ /* check the saved connections */
+ for (lh = hash->next; lh != hash; lh = lh->next) {
+ struct ip_conntrack *found_ct = NULL;
+ conn = list_entry(lh,struct ipt_connlimit_conn,list);
+ found = ip_conntrack_find_get(&conn->tuple,ct);
+ if (found != NULL
+ && (found_ct = tuplehash_to_ctrack(found)) != NULL
+ && 0 == memcmp(&conn->tuple,&tuple,sizeof(tuple))
+ && found_ct->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
+ /* Just to be sure we have it only once in the list.
+ We should'nt see tuples twice unless someone hooks this
+ into a table without "-p tcp --syn" */
+ addit = 0;
+ }
+#if DEBUG
+ printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
+ ipt_iphash(addr & mask),
+ NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
+ NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
+ (NULL != found) ? tcp[found_ct->proto.tcp.state] : "gone");
+#endif
+ if (NULL == found) {
+ /* this one is gone */
+ lh = lh->prev;
+ list_del(lh->next);
+ kfree(conn);
+ continue;
+ }
+ if (found_ct->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
+ /* we don't care about connections which are
+ closed already -> ditch it */
+ lh = lh->prev;
+ list_del(lh->next);
+ kfree(conn);
+ nf_conntrack_put(&found_ct->ct_general);
+ continue;
+ }
+ if ((addr & mask) == (conn->tuple.src.ip & mask)) {
+ /* same source IP address -> be counted! */
+ matches++;
+ }
+ nf_conntrack_put(&found_ct->ct_general);
+ }
+ if (addit) {
+ /* save the new connection in our list */
+#if DEBUG
+ printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
+ ipt_iphash(addr & mask),
+ NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
+ NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
+#endif
+ conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
+ if (NULL == conn) {
+ spin_unlock_bh(&data->lock);
+ return -1;
+ }
+ memset(conn,0,sizeof(*conn));
+ INIT_LIST_HEAD(&conn->list);
+ conn->tuple = tuple;
+ list_add(&conn->list,hash);
+ matches++;
+ }
+ spin_unlock_bh(&data->lock);
+ return matches;
+}
+
+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)
+{
+ const struct ipt_connlimit_info *info = matchinfo;
+ int connections, match;
+ struct ip_conntrack *ct;
+ enum ip_conntrack_info ctinfo;
+
+ ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
+ if (NULL == ct) {
+ printk("ipt_connlimit: Oops: invalid ct state ?\n");
+ *hotdrop = 1;
+ return 0;
+ }
+ connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
+ if (-1 == connections) {
+ printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
+ *hotdrop = 1; /* let's free some memory :-) */
+ return 0;
+ }
+ match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
+#if DEBUG
+ printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
+ "connections=%d limit=%d match=%s\n",
+ NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
+ connections, info->limit, match ? "yes" : "no");
+#endif
+
+ return match;
+}
+
+static int check(const char *tablename,
+ const struct ipt_ip *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ struct ipt_connlimit_info *info = matchinfo;
+ int i;
+
+ /* verify size */
+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
+ return 0;
+
+ /* refuse anything but tcp */
+ if (ip->proto != IPPROTO_TCP)
+ return 0;
+
+ /* init private data */
+ info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
+ spin_lock_init(&(info->data->lock));
+ for (i = 0; i < 256; i++)
+ INIT_LIST_HEAD(&(info->data->iphash[i]));
+
+ return 1;
+}
+
+static void destroy(void *matchinfo, unsigned int matchinfosize)
+{
+ struct ipt_connlimit_info *info = matchinfo;
+ struct ipt_connlimit_conn *conn;
+ struct list_head *hash;
+ int i;
+
+ /* cleanup */
+ for (i = 0; i < 256; i++) {
+ hash = &(info->data->iphash[i]);
+ while (hash != hash->next) {
+ conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
+ list_del(hash->next);
+ kfree(conn);
+ }
+ }
+ kfree(info->data);
+}
+
+static struct ipt_match connlimit_match = {
+ .name = "connlimit",
+ .match = &match,
+ .checkentry = &check,
+ .destroy = &destroy,
+ .me = THIS_MODULE
+};
+
+static int __init init(void)
+{
+ return ipt_register_match(&connlimit_match);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&connlimit_match);
+}
+
+module_init(init);
+module_exit(fini);
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/ipv6_syms.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/ipv6_syms.c (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/ipv6_syms.c Thu Jul 28 11:55:24 2005
@@ -12,6 +12,7 @@
EXPORT_SYMBOL(icmpv6_statistics);
EXPORT_SYMBOL(icmpv6_err_convert);
EXPORT_SYMBOL(ndisc_mc_map);
+EXPORT_SYMBOL(nd_tbl);
EXPORT_SYMBOL(register_inet6addr_notifier);
EXPORT_SYMBOL(unregister_inet6addr_notifier);
EXPORT_SYMBOL(ip6_route_output);
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/Kconfig
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/Kconfig (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/Kconfig Thu Jul 28 11:55:24 2005
@@ -306,5 +306,18 @@
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `N'.
+config IP6_NF_TARGET_ROUTE
+ tristate ' ROUTE target support'
+ depends on IP6_NF_MANGLE
+ help
+ This option adds a `ROUTE' target, which enables you to setup unusual
+ routes. The ROUTE target is also able to change the incoming interface
+ of a packet.
+
+ The target can be or not a final target. It has to be used inside the
+ mangle table.
+
+ Not working as a module.
+
endmenu
Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/Makefile
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/Makefile (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/Makefile Thu Jul 28 11:55:24 2005
@@ -22,6 +22,7 @@
obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
+obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
Added: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/ip6t_ROUTE.c
==============================================================================
--- (empty file)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv6/netfilter/ip6t_ROUTE.c Thu Jul 28 11:55:24 2005
@@ -0,0 +1,308 @@
+/*
+ * This implements the ROUTE v6 target, which enables you to setup unusual
+ * routes not supported by the standard kernel routing table.
+ *
+ * Copyright (C) 2003 Cedric de Launois <delaunois at info.ucl.ac.be>
+ *
+ * v 1.1 2004/11/23
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ipv6.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
+#include <linux/netdevice.h>
+#include <net/ipv6.h>
+#include <net/ndisc.h>
+#include <net/ip6_route.h>
+#include <linux/icmpv6.h>
+
+#if 1
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+#define NIP6(addr) \
+ ntohs((addr).s6_addr16[0]), \
+ ntohs((addr).s6_addr16[1]), \
+ ntohs((addr).s6_addr16[2]), \
+ ntohs((addr).s6_addr16[3]), \
+ ntohs((addr).s6_addr16[4]), \
+ ntohs((addr).s6_addr16[5]), \
+ ntohs((addr).s6_addr16[6]), \
+ ntohs((addr).s6_addr16[7])
+
+/* Route the packet according to the routing keys specified in
+ * route_info. Keys are :
+ * - ifindex :
+ * 0 if no oif preferred,
+ * otherwise set to the index of the desired oif
+ * - route_info->gw :
+ * 0 if no gateway specified,
+ * otherwise set to the next host to which the pkt must be routed
+ * If success, skb->dev is the output device to which the packet must
+ * be sent and skb->dst is not NULL
+ *
+ * RETURN: 1 if the packet was succesfully routed to the
+ * destination desired
+ * 0 if the kernel routing table could not route the packet
+ * according to the keys specified
+ */
+static int
+route6(struct sk_buff *skb,
+ unsigned int ifindex,
+ const struct ip6t_route_target_info *route_info)
+{
+ struct rt6_info *rt = NULL;
+ struct ipv6hdr *ipv6h = skb->nh.ipv6h;
+ struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
+
+ DEBUGP("ip6t_ROUTE: called with: ");
+ DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
+ DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
+ DEBUGP("OUT=%s\n", route_info->oif);
+
+ if (ipv6_addr_any(gw))
+ rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
+ else
+ rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
+
+ if (!rt)
+ goto no_route;
+
+ DEBUGP("ip6t_ROUTE: routing gives: ");
+ DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
+ DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
+ DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
+
+ if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
+ goto wrong_route;
+
+ if (!rt->rt6i_nexthop) {
+ DEBUGP("ip6t_ROUTE: discovering neighbour\n");
+ rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
+ }
+
+ /* Drop old route. */
+ dst_release(skb->dst);
+ skb->dst = &rt->u.dst;
+ skb->dev = rt->rt6i_dev;
+ return 1;
+
+ wrong_route:
+ dst_release(&rt->u.dst);
+ no_route:
+ if (!net_ratelimit())
+ return 0;
+
+ printk("ip6t_ROUTE: no explicit route found ");
+ if (ifindex)
+ printk("via interface %s ", route_info->oif);
+ if (!ipv6_addr_any(gw))
+ printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
+ printk("\n");
+ return 0;
+}
+
+
+/* Stolen from ip6_output_finish
+ * PRE : skb->dev is set to the device we are leaving by
+ * skb->dst is not NULL
+ * POST: the packet is sent with the link layer header pushed
+ * the packet is destroyed
+ */
+static void ip_direct_send(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb->dst;
+ struct hh_cache *hh = dst->hh;
+
+ if (hh) {
+ read_lock_bh(&hh->hh_lock);
+ memcpy(skb->data - 16, hh->hh_data, 16);
+ read_unlock_bh(&hh->hh_lock);
+ skb_push(skb, hh->hh_len);
+ hh->hh_output(skb);
+ } else if (dst->neighbour)
+ dst->neighbour->output(skb);
+ else {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
+ kfree_skb(skb);
+ }
+}
+
+
+static unsigned int
+route6_oif(const struct ip6t_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ unsigned int ifindex = 0;
+ struct net_device *dev_out = NULL;
+
+ /* The user set the interface name to use.
+ * Getting the current interface index.
+ */
+ if ((dev_out = dev_get_by_name(route_info->oif))) {
+ ifindex = dev_out->ifindex;
+ } else {
+ /* Unknown interface name : packet dropped */
+ if (net_ratelimit())
+ DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
+
+ if (route_info->flags & IP6T_ROUTE_CONTINUE)
+ return IP6T_CONTINUE;
+ else
+ return NF_DROP;
+ }
+
+ /* Trying the standard way of routing packets */
+ if (route6(skb, ifindex, route_info)) {
+ dev_put(dev_out);
+ if (route_info->flags & IP6T_ROUTE_CONTINUE)
+ return IP6T_CONTINUE;
+
+ ip_direct_send(skb);
+ return NF_STOLEN;
+ } else
+ return NF_DROP;
+}
+
+
+static unsigned int
+route6_gw(const struct ip6t_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ if (route6(skb, 0, route_info)) {
+ if (route_info->flags & IP6T_ROUTE_CONTINUE)
+ return IP6T_CONTINUE;
+
+ ip_direct_send(skb);
+ return NF_STOLEN;
+ } else
+ return NF_DROP;
+}
+
+
+static unsigned int
+ip6t_route_target(struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int hooknum,
+ const void *targinfo,
+ void *userinfo)
+{
+ const struct ip6t_route_target_info *route_info = targinfo;
+ struct sk_buff *skb = *pskb;
+ struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
+ unsigned int res;
+
+ if (route_info->flags & IP6T_ROUTE_CONTINUE)
+ goto do_it;
+
+ /* If we are at PREROUTING or INPUT hook
+ * the TTL isn't decreased by the IP stack
+ */
+ if (hooknum == NF_IP6_PRE_ROUTING ||
+ hooknum == NF_IP6_LOCAL_IN) {
+
+ struct ipv6hdr *ipv6h = skb->nh.ipv6h;
+
+ if (ipv6h->hop_limit <= 1) {
+ /* Force OUTPUT device used as source address */
+ skb->dev = skb->dst->dev;
+
+ icmpv6_send(skb, ICMPV6_TIME_EXCEED,
+ ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
+
+ return NF_DROP;
+ }
+
+ ipv6h->hop_limit--;
+ }
+
+ if ((route_info->flags & IP6T_ROUTE_TEE)) {
+ /*
+ * Copy the *pskb, and route the copy. Will later return
+ * IP6T_CONTINUE for the original skb, which should continue
+ * on its way as if nothing happened. The copy should be
+ * independantly delivered to the ROUTE --gw.
+ */
+ skb = skb_copy(*pskb, GFP_ATOMIC);
+ if (!skb) {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ip6t_ROUTE: copy failed!\n");
+ return IP6T_CONTINUE;
+ }
+ }
+
+do_it:
+ if (route_info->oif[0]) {
+ res = route6_oif(route_info, skb);
+ } else if (!ipv6_addr_any(gw)) {
+ res = route6_gw(route_info, skb);
+ } else {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
+ res = IP6T_CONTINUE;
+ }
+
+ if ((route_info->flags & IP6T_ROUTE_TEE))
+ res = IP6T_CONTINUE;
+
+ return res;
+}
+
+
+static int
+ip6t_route_checkentry(const char *tablename,
+ const struct ip6t_entry *e,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ if (strcmp(tablename, "mangle") != 0) {
+ printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
+ return 0;
+ }
+
+ if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
+ printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
+ targinfosize,
+ IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static struct ip6t_target ip6t_route_reg = {
+ .name = "ROUTE",
+ .target = ip6t_route_target,
+ .checkentry = ip6t_route_checkentry,
+ .me = THIS_MODULE
+};
+
+
+static int __init init(void)
+{
+ printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
+ if (ip6t_register_target(&ip6t_route_reg))
+ return -EINVAL;
+
+ return 0;
+}
+
+
+static void __exit fini(void)
+{
+ ip6t_unregister_target(&ip6t_route_reg);
+}
+
+module_init(init);
+module_exit(fini);
+MODULE_LICENSE("GPL");
Modified: netfilter-2.6/patch-o-matic-ng/trunk/status
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/status (original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/status Thu Jul 28 11:55:24 2005
@@ -5,7 +5,7 @@
addrtype updated
CLASSIFY updated
CLUSTERIP updated
-connlimit added
+connlimit 2005/07/27 added
conntrack-event-api 2005/07/27 updated
ctnetlink added (v0.60)
fuzzy 2005/07/27 added
@@ -34,12 +34,12 @@
realm updated
recent updated (v0.3.2)
REJECT updated
-ROUTE added (ipv6 / not working as a module)
+ROUTE 2005/07/27 added (ipv6 / not working as a module)
SAME updated
sctp updated
set 2005/07/27 added
string added
-TARPIT added
+TARPIT 2005/07/27 added
time 2005/07/27 added
TTL 2005/07/27 added
u32 added+updated
More information about the pld-cvs-commit
mailing list