1 diff -NurpP --minimal linux-2.6.21.a/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.6.21.b/include/linux/netfilter_ipv4/ipt_ROUTE.h
2 --- linux-2.6.21.a/include/linux/netfilter_ipv4/ipt_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.21.b/include/linux/netfilter_ipv4/ipt_ROUTE.h 2007-05-30 11:40:37.000000000 +0200
5 +/* Header file for iptables ipt_ROUTE target
7 + * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
9 + * This software is distributed under GNU GPL v2, 1991
11 +#ifndef _IPT_ROUTE_H_target
12 +#define _IPT_ROUTE_H_target
14 +#define IPT_ROUTE_IFNAMSIZ 16
16 +struct ipt_route_target_info {
17 + char oif[IPT_ROUTE_IFNAMSIZ]; /* Output Interface Name */
18 + char iif[IPT_ROUTE_IFNAMSIZ]; /* Input Interface Name */
19 + u_int32_t gw; /* IP address of gateway */
23 +/* Values for "flags" field */
24 +#define IPT_ROUTE_CONTINUE 0x01
25 +#define IPT_ROUTE_TEE 0x02
27 +#endif /*_IPT_ROUTE_H_target*/
28 diff -NurpP --minimal linux-2.6.21.a/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.6.21.b/include/linux/netfilter_ipv6/ip6t_ROUTE.h
29 --- linux-2.6.21.a/include/linux/netfilter_ipv6/ip6t_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
30 +++ linux-2.6.21.b/include/linux/netfilter_ipv6/ip6t_ROUTE.h 2007-05-30 11:40:37.000000000 +0200
32 +/* Header file for iptables ip6t_ROUTE target
34 + * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
36 + * This software is distributed under GNU GPL v2, 1991
38 +#ifndef _IPT_ROUTE_H_target
39 +#define _IPT_ROUTE_H_target
41 +#define IP6T_ROUTE_IFNAMSIZ 16
43 +struct ip6t_route_target_info {
44 + char oif[IP6T_ROUTE_IFNAMSIZ]; /* Output Interface Name */
45 + char iif[IP6T_ROUTE_IFNAMSIZ]; /* Input Interface Name */
46 + u_int32_t gw[4]; /* IPv6 address of gateway */
50 +/* Values for "flags" field */
51 +#define IP6T_ROUTE_CONTINUE 0x01
52 +#define IP6T_ROUTE_TEE 0x02
54 +#endif /*_IP6T_ROUTE_H_target*/
55 diff -NurpP --minimal linux-2.6.21.a/net/ipv4/netfilter/Kconfig linux-2.6.21.b/net/ipv4/netfilter/Kconfig
56 --- linux-2.6.21.a/net/ipv4/netfilter/Kconfig 2007-05-30 11:39:28.000000000 +0200
57 +++ linux-2.6.21.b/net/ipv4/netfilter/Kconfig 2007-05-30 11:40:37.000000000 +0200
58 @@ -813,5 +813,22 @@ config IP_NF_MATCH_U32
60 Details and examples are in the kernel module source.
62 +config IP_NF_TARGET_ROUTE
63 + tristate 'ROUTE target support'
64 + depends on IP_NF_MANGLE
66 + This option adds a `ROUTE' target, which enables you to setup unusual
67 + routes. For example, the ROUTE lets you route a received packet through
68 + an interface or towards a host, even if the regular destination of the
69 + packet is the router itself. The ROUTE target is also able to change the
70 + incoming interface of a packet.
72 + The target can be or not a final target. It has to be used inside the
75 + If you want to compile it as a module, say M here and read
76 + Documentation/modules.txt. The module will be called ipt_ROUTE.o.
81 diff -NurpP --minimal linux-2.6.21.a/net/ipv4/netfilter/Makefile linux-2.6.21.b/net/ipv4/netfilter/Makefile
82 --- linux-2.6.21.a/net/ipv4/netfilter/Makefile 2007-05-30 11:39:28.000000000 +0200
83 +++ linux-2.6.21.b/net/ipv4/netfilter/Makefile 2007-05-30 11:40:37.000000000 +0200
84 @@ -104,6 +104,7 @@ obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_EC
85 obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
86 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
87 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
88 +obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
89 obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
90 obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
91 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
92 diff -NurpP --minimal linux-2.6.21.a/net/ipv4/netfilter/ipt_ROUTE.c linux-2.6.21.b/net/ipv4/netfilter/ipt_ROUTE.c
93 --- linux-2.6.21.a/net/ipv4/netfilter/ipt_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
94 +++ linux-2.6.21.b/net/ipv4/netfilter/ipt_ROUTE.c 2007-05-30 11:40:37.000000000 +0200
97 + * This implements the ROUTE target, which enables you to setup unusual
98 + * routes not supported by the standard kernel routing table.
100 + * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
102 + * v 1.11 2004/11/23
104 + * This software is distributed under GNU GPL v2, 1991
107 +#include <linux/module.h>
108 +#include <linux/skbuff.h>
109 +#include <linux/ip.h>
110 +#include <linux/netfilter/x_tables.h>
111 +#include <linux/netfilter_ipv4/ip_tables.h>
112 +#include <net/netfilter/nf_conntrack.h>
113 +#include <linux/netfilter_ipv4/ipt_ROUTE.h>
114 +#include <linux/netdevice.h>
115 +#include <linux/route.h>
116 +#include <linux/if_arp.h>
118 +#include <net/route.h>
119 +#include <net/icmp.h>
120 +#include <net/checksum.h>
123 +#define DEBUGP printk
125 +#define DEBUGP(format, args...)
128 +MODULE_LICENSE("GPL");
129 +MODULE_AUTHOR("Cedric de Launois <delaunois@info.ucl.ac.be>");
130 +MODULE_DESCRIPTION("iptables ROUTE target module");
132 +/* Try to route the packet according to the routing keys specified in
133 + * route_info. Keys are :
135 + * 0 if no oif preferred,
136 + * otherwise set to the index of the desired oif
137 + * - route_info->gw :
138 + * 0 if no gateway specified,
139 + * otherwise set to the next host to which the pkt must be routed
140 + * If success, skb->dev is the output device to which the packet must
141 + * be sent and skb->dst is not NULL
143 + * RETURN: -1 if an error occured
144 + * 1 if the packet was succesfully routed to the
145 + * destination desired
146 + * 0 if the kernel routing table could not route the packet
147 + * according to the keys specified
149 +static int route(struct sk_buff *skb,
150 + unsigned int ifindex,
151 + const struct ipt_route_target_info *route_info)
155 + struct iphdr *iph = ip_hdr(skb);
156 + struct flowi fl = {
160 + .daddr = iph->daddr,
162 + .tos = RT_TOS(iph->tos),
163 + .scope = RT_SCOPE_UNIVERSE,
168 + /* The destination address may be overloaded by the target */
169 + if (route_info->gw)
170 + fl.fl4_dst = route_info->gw;
172 + /* Trying to route the packet using the standard routing table. */
173 + if ((err = ip_route_output_key(&rt, &fl))) {
174 + if (net_ratelimit())
175 + DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
179 + /* Drop old route. */
180 + dst_release(skb->dst);
183 + /* Success if no oif specified or if the oif correspond to the
185 + if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
186 + skb->dst = &rt->u.dst;
187 + skb->dev = skb->dst->dev;
188 + skb->protocol = htons(ETH_P_IP);
192 + /* The interface selected by the routing table is not the one
193 + * specified by the user. This may happen because the dst address
194 + * is one of our own addresses.
196 + if (net_ratelimit())
197 + DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n",
198 + NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
204 +/* Stolen from ip_finish_output2
205 + * PRE : skb->dev is set to the device we are leaving by
206 + * skb->dst is not NULL
207 + * POST: the packet is sent with the link layer header pushed
208 + * the packet is destroyed
210 +static void ip_direct_send(struct sk_buff *skb)
212 + struct dst_entry *dst = skb->dst;
213 + struct hh_cache *hh = dst->hh;
214 + struct net_device *dev = dst->dev;
215 + int hh_len = LL_RESERVED_SPACE(dev);
217 + /* Be paranoid, rather than too clever. */
218 + if (unlikely(skb_headroom(skb) < hh_len && dev->hard_header)) {
219 + struct sk_buff *skb2;
221 + skb2 = skb_realloc_headroom(skb, LL_RESERVED_SPACE(dev));
222 + if (skb2 == NULL) {
227 + skb_set_owner_w(skb2, skb->sk);
233 + neigh_hh_output(dst->hh, skb);
234 + } else if (dst->neighbour)
235 + dst->neighbour->output(skb);
237 + if (net_ratelimit())
238 + DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
244 +/* PRE : skb->dev is set to the device we are leaving by
245 + * POST: - the packet is directly sent to the skb->dev device, without
246 + * pushing the link layer header.
247 + * - the packet is destroyed
249 +static inline int dev_direct_send(struct sk_buff *skb)
251 + return dev_queue_xmit(skb);
255 +static unsigned int route_oif(const struct ipt_route_target_info *route_info,
256 + struct sk_buff *skb)
258 + unsigned int ifindex = 0;
259 + struct net_device *dev_out = NULL;
261 + /* The user set the interface name to use.
262 + * Getting the current interface index.
264 + if ((dev_out = dev_get_by_name(route_info->oif))) {
265 + ifindex = dev_out->ifindex;
267 + /* Unknown interface name : packet dropped */
268 + if (net_ratelimit())
269 + DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
273 + /* Trying the standard way of routing packets */
274 + switch (route(skb, ifindex, route_info)) {
277 + if (route_info->flags & IPT_ROUTE_CONTINUE)
278 + return IPT_CONTINUE;
280 + ip_direct_send(skb);
284 + /* Failed to send to oif. Trying the hard way */
285 + if (route_info->flags & IPT_ROUTE_CONTINUE)
288 + if (net_ratelimit())
289 + DEBUGP("ipt_ROUTE: forcing the use of %i\n",
292 + /* We have to force the use of an interface.
293 + * This interface must be a tunnel interface since
294 + * otherwise we can't guess the hw address for
295 + * the packet. For a tunnel interface, no hw address
298 + if ((dev_out->type != ARPHRD_TUNNEL)
299 + && (dev_out->type != ARPHRD_IPGRE)) {
300 + if (net_ratelimit())
301 + DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
306 + /* Send the packet. This will also free skb
307 + * Do not go through the POST_ROUTING hook because
308 + * skb->dst is not set and because it will probably
309 + * get confused by the destination IP address.
311 + skb->dev = dev_out;
312 + dev_direct_send(skb);
317 + /* Unexpected error */
324 +static unsigned int route_iif(const struct ipt_route_target_info *route_info,
325 + struct sk_buff *skb)
327 + struct net_device *dev_in = NULL;
329 + /* Getting the current interface index. */
330 + if (!(dev_in = dev_get_by_name(route_info->iif))) {
331 + if (net_ratelimit())
332 + DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->iif);
337 + dst_release(skb->dst);
346 +static unsigned int route_gw(const struct ipt_route_target_info *route_info,
347 + struct sk_buff *skb)
349 + if (route(skb, 0, route_info)!=1)
352 + if (route_info->flags & IPT_ROUTE_CONTINUE)
353 + return IPT_CONTINUE;
355 + ip_direct_send(skb);
360 +/* To detect and deter routed packet loopback when using the --tee option,
361 + * we take a page out of the raw.patch book: on the copied skb, we set up
362 + * a fake ->nfct entry, pointing to the local &route_tee_track. We skip
363 + * routing packets when we see they already have that ->nfct.
366 +static struct nf_conn route_tee_track;
368 +static unsigned int ipt_route_target(struct sk_buff **pskb,
369 + const struct net_device *in,
370 + const struct net_device *out,
371 + unsigned int hooknum,
372 + const struct xt_target *target,
373 + const void *targinfo
376 + const struct ipt_route_target_info *route_info = targinfo;
377 + struct sk_buff *skb = *pskb;
380 + if (skb->nfct == &route_tee_track.ct_general) {
381 + /* Loopback - a packet we already routed, is to be
382 + * routed another time. Avoid that, now.
384 + if (net_ratelimit())
385 + DEBUGP(KERN_DEBUG "ipt_ROUTE: loopback - DROP!\n");
389 + /* If we are at PREROUTING or INPUT hook
390 + * the TTL isn't decreased by the IP stack
392 + if (hooknum == NF_IP_PRE_ROUTING ||
393 + hooknum == NF_IP_LOCAL_IN) {
395 + struct iphdr *iph = ip_hdr(skb);
397 + if (iph->ttl <= 1) {
399 + struct flowi fl = {
403 + .daddr = iph->daddr,
404 + .saddr = iph->saddr,
405 + .tos = RT_TOS(iph->tos),
406 + .scope = ((iph->tos & RTO_ONLINK) ?
413 + if (ip_route_output_key(&rt, &fl)) {
417 + if (skb->dev == rt->u.dst.dev) {
418 + /* Drop old route. */
419 + dst_release(skb->dst);
420 + skb->dst = &rt->u.dst;
422 + /* this will traverse normal stack, and
423 + * thus call conntrack on the icmp packet */
424 + icmp_send(skb, ICMP_TIME_EXCEEDED,
432 + * If we are at INPUT the checksum must be recalculated since
433 + * the length could change as the result of a defragmentation.
435 + if(hooknum == NF_IP_LOCAL_IN) {
436 + iph->ttl = iph->ttl - 1;
438 + iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
440 + ip_decrease_ttl(iph);
444 + if ((route_info->flags & IPT_ROUTE_TEE)) {
446 + * Copy the *pskb, and route the copy. Will later return
447 + * IPT_CONTINUE for the original skb, which should continue
448 + * on its way as if nothing happened. The copy should be
449 + * independantly delivered to the ROUTE --gw.
451 + skb = skb_copy(*pskb, GFP_ATOMIC);
453 + if (net_ratelimit())
454 + DEBUGP(KERN_DEBUG "ipt_ROUTE: copy failed!\n");
455 + return IPT_CONTINUE;
459 + /* Tell conntrack to forget this packet since it may get confused
460 + * when a packet is leaving with dst address == our address.
461 + * Good idea ? Dunno. Need advice.
463 + * NEW: mark the skb with our &route_tee_track, so we avoid looping
464 + * on any already routed packet.
466 + if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
467 + nf_conntrack_put(skb->nfct);
468 + skb->nfct = &route_tee_track.ct_general;
469 + skb->nfctinfo = IP_CT_NEW;
470 + nf_conntrack_get(skb->nfct);
473 + if (route_info->oif[0] != '\0') {
474 + res = route_oif(route_info, skb);
475 + } else if (route_info->iif[0] != '\0') {
476 + res = route_iif(route_info, skb);
477 + } else if (route_info->gw) {
478 + res = route_gw(route_info, skb);
480 + if (net_ratelimit())
481 + DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
482 + res = IPT_CONTINUE;
485 + if ((route_info->flags & IPT_ROUTE_TEE))
486 + res = IPT_CONTINUE;
492 +static int ipt_route_checkentry(const char *tablename,
494 + const struct xt_target *target,
497 + unsigned int hook_mask)
499 + if (strcmp(tablename, "mangle") != 0) {
500 + printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
505 + if (hook_mask & ~( (1 << NF_IP_PRE_ROUTING)
506 + | (1 << NF_IP_LOCAL_IN)
507 + | (1 << NF_IP_FORWARD)
508 + | (1 << NF_IP_LOCAL_OUT)
509 + | (1 << NF_IP_POST_ROUTING))) {
510 + printk("ipt_ROUTE: bad hook\n");
525 +static struct ipt_target ipt_route_reg = {
527 + .target = ipt_route_target,
528 + .targetsize = sizeof(struct ipt_route_target_info),
529 + .checkentry = ipt_route_checkentry,
533 +static int __init init(void)
535 + /* Set up fake conntrack (stolen from raw.patch):
536 + - to never be deleted, not in any hashes */
537 + atomic_set(&route_tee_track.ct_general.use, 1);
538 + /* - and look it like as a confirmed connection */
539 + set_bit(IPS_CONFIRMED_BIT, &route_tee_track.status);
540 + /* Initialize fake conntrack so that NAT will skip it */
541 + route_tee_track.status |= IPS_NAT_DONE_MASK;
543 + return xt_register_target(&ipt_route_reg);
547 +static void __exit fini(void)
549 + xt_unregister_target(&ipt_route_reg);
554 diff -NurpP --minimal linux-2.6.21.a/net/ipv6/netfilter/Kconfig linux-2.6.21.b/net/ipv6/netfilter/Kconfig
555 --- linux-2.6.21.a/net/ipv6/netfilter/Kconfig 2007-05-30 11:13:04.000000000 +0200
556 +++ linux-2.6.21.b/net/ipv6/netfilter/Kconfig 2007-05-30 11:40:37.000000000 +0200
557 @@ -209,5 +209,18 @@ config IP6_NF_RAW
558 If you want to compile it as a module, say M here and read
559 <file:Documentation/modules.txt>. If unsure, say `N'.
561 +config IP6_NF_TARGET_ROUTE
562 + tristate 'ROUTE target support'
563 + depends on IP6_NF_MANGLE
565 + This option adds a `ROUTE' target, which enables you to setup unusual
566 + routes. The ROUTE target is also able to change the incoming interface
569 + The target can be or not a final target. It has to be used inside the
572 + Not working as a module.
576 diff -NurpP --minimal linux-2.6.21.a/net/ipv6/netfilter/Makefile linux-2.6.21.b/net/ipv6/netfilter/Makefile
577 --- linux-2.6.21.a/net/ipv6/netfilter/Makefile 2007-05-30 11:13:04.000000000 +0200
578 +++ linux-2.6.21.b/net/ipv6/netfilter/Makefile 2007-05-30 11:40:37.000000000 +0200
579 @@ -21,6 +21,7 @@ obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw
580 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
581 obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
582 obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o
583 +obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
585 # objects for l3 independent conntrack
586 nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o
587 diff -NurpP --minimal linux-2.6.21.a/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.21.b/net/ipv6/netfilter/ip6t_ROUTE.c
588 --- linux-2.6.21.a/net/ipv6/netfilter/ip6t_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
589 +++ linux-2.6.21.b/net/ipv6/netfilter/ip6t_ROUTE.c 2007-05-30 11:40:37.000000000 +0200
592 + * This implements the ROUTE v6 target, which enables you to setup unusual
593 + * routes not supported by the standard kernel routing table.
595 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
599 + * This software is distributed under GNU GPL v2, 1991
602 +#include <linux/module.h>
603 +#include <linux/skbuff.h>
604 +#include <linux/ipv6.h>
605 +#include <linux/netfilter/x_tables.h>
606 +#include <linux/netfilter_ipv6/ip6_tables.h>
607 +#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
608 +#include <linux/netdevice.h>
609 +#include <net/ipv6.h>
610 +#include <net/ndisc.h>
611 +#include <net/ip6_route.h>
612 +#include <linux/icmpv6.h>
615 +#define DEBUGP printk
617 +#define DEBUGP(format, args...)
620 +#define NIP6(addr) \
621 + ntohs((addr).s6_addr16[0]), \
622 + ntohs((addr).s6_addr16[1]), \
623 + ntohs((addr).s6_addr16[2]), \
624 + ntohs((addr).s6_addr16[3]), \
625 + ntohs((addr).s6_addr16[4]), \
626 + ntohs((addr).s6_addr16[5]), \
627 + ntohs((addr).s6_addr16[6]), \
628 + ntohs((addr).s6_addr16[7])
630 +/* Route the packet according to the routing keys specified in
631 + * route_info. Keys are :
633 + * 0 if no oif preferred,
634 + * otherwise set to the index of the desired oif
635 + * - route_info->gw :
636 + * 0 if no gateway specified,
637 + * otherwise set to the next host to which the pkt must be routed
638 + * If success, skb->dev is the output device to which the packet must
639 + * be sent and skb->dst is not NULL
641 + * RETURN: 1 if the packet was succesfully routed to the
642 + * destination desired
643 + * 0 if the kernel routing table could not route the packet
644 + * according to the keys specified
647 +route6(struct sk_buff *skb,
648 + unsigned int ifindex,
649 + const struct ip6t_route_target_info *route_info)
651 + struct rt6_info *rt = NULL;
652 + struct ipv6hdr *ipv6h = ipv6_hdr(skb);
653 + struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
655 + DEBUGP("ip6t_ROUTE: called with: ");
656 + DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
657 + DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
658 + DEBUGP("OUT=%s\n", route_info->oif);
660 + if (ipv6_addr_any(gw))
661 + rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
663 + rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
668 + DEBUGP("ip6t_ROUTE: routing gives: ");
669 + DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
670 + DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
671 + DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
673 + if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
676 + if (!rt->rt6i_nexthop) {
677 + DEBUGP("ip6t_ROUTE: discovering neighbour\n");
678 + rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
681 + /* Drop old route. */
682 + dst_release(skb->dst);
683 + skb->dst = &rt->u.dst;
684 + skb->dev = rt->rt6i_dev;
688 + dst_release(&rt->u.dst);
690 + if (!net_ratelimit())
693 + printk("ip6t_ROUTE: no explicit route found ");
695 + printk("via interface %s ", route_info->oif);
696 + if (!ipv6_addr_any(gw))
697 + printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
703 +/* Stolen from ip6_output_finish
704 + * PRE : skb->dev is set to the device we are leaving by
705 + * skb->dst is not NULL
706 + * POST: the packet is sent with the link layer header pushed
707 + * the packet is destroyed
709 +static void ip_direct_send(struct sk_buff *skb)
711 + struct dst_entry *dst = skb->dst;
712 + struct hh_cache *hh = dst->hh;
715 + neigh_hh_output(dst->hh, skb);
716 + } else if (dst->neighbour)
717 + dst->neighbour->output(skb);
719 + if (net_ratelimit())
720 + DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
727 +route6_oif(const struct ip6t_route_target_info *route_info,
728 + struct sk_buff *skb)
730 + unsigned int ifindex = 0;
731 + struct net_device *dev_out = NULL;
733 + /* The user set the interface name to use.
734 + * Getting the current interface index.
736 + if ((dev_out = dev_get_by_name(route_info->oif))) {
737 + ifindex = dev_out->ifindex;
739 + /* Unknown interface name : packet dropped */
740 + if (net_ratelimit())
741 + DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
743 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
744 + return IP6T_CONTINUE;
749 + /* Trying the standard way of routing packets */
750 + if (route6(skb, ifindex, route_info)) {
752 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
753 + return IP6T_CONTINUE;
755 + ip_direct_send(skb);
763 +route6_gw(const struct ip6t_route_target_info *route_info,
764 + struct sk_buff *skb)
766 + if (route6(skb, 0, route_info)) {
767 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
768 + return IP6T_CONTINUE;
770 + ip_direct_send(skb);
778 +ip6t_route_target(struct sk_buff **pskb,
779 + const struct net_device *in,
780 + const struct net_device *out,
781 + unsigned int hooknum,
782 + const struct xt_target *target,
783 + const void *targinfo
786 + const struct ip6t_route_target_info *route_info = targinfo;
787 + struct sk_buff *skb = *pskb;
788 + struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
791 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
794 + /* If we are at PREROUTING or INPUT hook
795 + * the TTL isn't decreased by the IP stack
797 + if (hooknum == NF_IP6_PRE_ROUTING ||
798 + hooknum == NF_IP6_LOCAL_IN) {
800 + struct ipv6hdr *ipv6h = ipv6_hdr(skb);
802 + if (ipv6h->hop_limit <= 1) {
803 + /* Force OUTPUT device used as source address */
804 + skb->dev = skb->dst->dev;
806 + icmpv6_send(skb, ICMPV6_TIME_EXCEED,
807 + ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
812 + ipv6h->hop_limit--;
815 + if ((route_info->flags & IP6T_ROUTE_TEE)) {
817 + * Copy the *pskb, and route the copy. Will later return
818 + * IP6T_CONTINUE for the original skb, which should continue
819 + * on its way as if nothing happened. The copy should be
820 + * independantly delivered to the ROUTE --gw.
822 + skb = skb_copy(*pskb, GFP_ATOMIC);
824 + if (net_ratelimit())
825 + DEBUGP(KERN_DEBUG "ip6t_ROUTE: copy failed!\n");
826 + return IP6T_CONTINUE;
831 + if (route_info->oif[0]) {
832 + res = route6_oif(route_info, skb);
833 + } else if (!ipv6_addr_any(gw)) {
834 + res = route6_gw(route_info, skb);
836 + if (net_ratelimit())
837 + DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
838 + res = IP6T_CONTINUE;
841 + if ((route_info->flags & IP6T_ROUTE_TEE))
842 + res = IP6T_CONTINUE;
849 +ip6t_route_checkentry(const char *tablename,
851 + const struct xt_target *target,
854 + unsigned int hook_mask)
856 + if (strcmp(tablename, "mangle") != 0) {
857 + printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
861 + /* if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
862 + printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
864 + IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
872 +static struct ip6t_target ip6t_route_reg = {
874 + .target = ip6t_route_target,
875 + .targetsize = sizeof(struct ip6t_route_target_info),
876 + .checkentry = ip6t_route_checkentry,
881 +static int __init init(void)
883 + printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
884 + if (xt_register_target(&ip6t_route_reg))
891 +static void __exit fini(void)
893 + xt_unregister_target(&ip6t_route_reg);
898 +MODULE_LICENSE("GPL");
899 --- a/net/ipv6/ndisc.c 2007-07-09 01:32:17.000000000 +0200
900 +++ b/net/ipv6/ndisc.c 2007-08-02 13:23:26.000000000 +0200
901 @@ -154,6 +154,8 @@ struct neigh_table nd_tbl = {
905 +EXPORT_SYMBOL(nd_tbl);
908 struct ndisc_options {
909 struct nd_opt_hdr *nd_opt_array[__ND_OPT_ARRAY_MAX];