📄 160-netfilter_route.patch
字号:
Index: linux-2.6.21.7/include/linux/netfilter_ipv4/ipt_ROUTE.h===================================================================--- /dev/null+++ linux-2.6.21.7/include/linux/netfilter_ipv4/ipt_ROUTE.h@@ -0,0 +1,23 @@+/* Header file for iptables ipt_ROUTE target+ *+ * (C) 2002 by C閐ric de Launois <delaunois@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*/Index: linux-2.6.21.7/include/linux/netfilter_ipv6/ip6t_ROUTE.h===================================================================--- /dev/null+++ linux-2.6.21.7/include/linux/netfilter_ipv6/ip6t_ROUTE.h@@ -0,0 +1,23 @@+/* Header file for iptables ip6t_ROUTE target+ *+ * (C) 2003 by C閐ric de Launois <delaunois@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*/Index: linux-2.6.21.7/net/ipv4/netfilter/ipt_ROUTE.c===================================================================--- /dev/null+++ linux-2.6.21.7/net/ipv4/netfilter/ipt_ROUTE.c@@ -0,0 +1,483 @@+/*+ * 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@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 <linux/version.h>+#include <linux/if_arp.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@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,+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)+ const struct xt_target *target,+#endif+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)+ const void *targinfo,+ void *userinfo)+#else+ const void *targinfo)+#endif+{+ 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);+ }++ 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,+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)+ const void *e,+#else+ const struct ipt_ip *ip,+#endif+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -