2 * This implements the ROUTE target, which enables you to setup unusual
3 * routes not supported by the standard kernel routing table.
5 * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
9 * This software is distributed under GNU GPL v2, 1991
12 #include <linux/module.h>
13 #include <linux/skbuff.h>
15 #include <linux/netfilter_ipv4/ip_tables.h>
16 #include <linux/netfilter_ipv4/ip_conntrack.h>
17 #include <linux/netfilter_ipv4/ipt_ROUTE.h>
18 #include <linux/netdevice.h>
19 #include <linux/route.h>
21 #include <net/route.h>
23 #include <net/checksum.h>
28 #define DEBUGP(format, args...)
32 /* Try to route the packet according to the routing keys specified in
33 * route_info. Keys are :
35 * 0 if no oif preferred,
36 * otherwise set to the index of the desired oif
38 * 0 if no gateway specified,
39 * otherwise set to the next host to which the pkt must be routed
40 * If success, skb->dev is the output device to which the packet must
41 * be sent and skb->dst is not NULL
43 * RETURN: -1 if an error occured
44 * 1 if the packet was succesfully routed to the
46 * 0 if the kernel routing table could not route the packet
47 * according to the keys specified
49 static int route(struct sk_buff
*skb
,
51 const struct ipt_route_target_info
*route_info
)
55 struct iphdr
*iph
= skb
->nh
.iph
;
63 /* The destination address may be overloaded by the target */
65 key
.dst
= route_info
->gw
;
67 /* Trying to route the packet using the standard routing table. */
68 if ((err
= ip_route_output_key(&rt
, &key
))) {
70 DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err
);
75 dst_release(skb
->dst
);
78 /* Success if no oif specified or if the oif correspond to the
80 if (!ifindex
|| rt
->u
.dst
.dev
->ifindex
== ifindex
) {
81 skb
->dst
= &rt
->u
.dst
;
82 skb
->dev
= skb
->dst
->dev
;
86 /* The interface selected by the routing table is not the one
87 * specified by the user. This may happen because the dst address
88 * is one of our own addresses.
91 DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n",
92 NIPQUAD(route_info
->gw
), ifindex
, rt
->u
.dst
.dev
->ifindex
);
98 /* Stolen from ip_finish_output2
99 * PRE : skb->dev is set to the device we are leaving by
100 * skb->dst is not NULL
101 * POST: the packet is sent with the link layer header pushed
102 * the packet is destroyed
104 static void ip_direct_send(struct sk_buff
*skb
)
106 struct dst_entry
*dst
= skb
->dst
;
107 struct hh_cache
*hh
= dst
->hh
;
110 read_lock_bh(&hh
->hh_lock
);
111 memcpy(skb
->data
- 16, hh
->hh_data
, 16);
112 read_unlock_bh(&hh
->hh_lock
);
113 skb_push(skb
, hh
->hh_len
);
115 } else if (dst
->neighbour
)
116 dst
->neighbour
->output(skb
);
119 DEBUGP(KERN_DEBUG
"ipt_ROUTE: no hdr & no neighbour cache!\n");
125 /* PRE : skb->dev is set to the device we are leaving by
126 * POST: - the packet is directly sent to the skb->dev device, without
127 * pushing the link layer header.
128 * - the packet is destroyed
130 static inline int dev_direct_send(struct sk_buff
*skb
)
132 return dev_queue_xmit(skb
);
136 static unsigned int route_oif(const struct ipt_route_target_info
*route_info
,
139 unsigned int ifindex
= 0;
140 struct net_device
*dev_out
= NULL
;
142 /* The user set the interface name to use.
143 * Getting the current interface index.
145 if ((dev_out
= dev_get_by_name(route_info
->oif
))) {
146 ifindex
= dev_out
->ifindex
;
148 /* Unknown interface name : packet dropped */
150 DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info
->oif
);
154 /* Trying the standard way of routing packets */
155 switch (route(skb
, ifindex
, route_info
)) {
158 if (route_info
->flags
& IPT_ROUTE_CONTINUE
)
165 /* Failed to send to oif. Trying the hard way */
166 if (route_info
->flags
& IPT_ROUTE_CONTINUE
)
170 DEBUGP("ipt_ROUTE: forcing the use of %i\n",
173 /* We have to force the use of an interface.
174 * This interface must be a tunnel interface since
175 * otherwise we can't guess the hw address for
176 * the packet. For a tunnel interface, no hw address
179 if ((dev_out
->type
!= ARPHRD_TUNNEL
)
180 && (dev_out
->type
!= ARPHRD_IPGRE
)) {
182 DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
187 /* Send the packet. This will also free skb
188 * Do not go through the POST_ROUTING hook because
189 * skb->dst is not set and because it will probably
190 * get confused by the destination IP address.
193 dev_direct_send(skb
);
198 /* Unexpected error */
205 static unsigned int route_iif(const struct ipt_route_target_info
*route_info
,
208 struct net_device
*dev_in
= NULL
;
210 /* Getting the current interface index. */
211 if (!(dev_in
= dev_get_by_name(route_info
->iif
))) {
213 DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info
->iif
);
218 dst_release(skb
->dst
);
227 static unsigned int route_gw(const struct ipt_route_target_info
*route_info
,
230 if (route(skb
, 0, route_info
)!=1)
233 if (route_info
->flags
& IPT_ROUTE_CONTINUE
)
240 /* To detect and deter routed packet loopback when using the --tee option,
241 * we take a page out of the raw.patch book: on the copied skb, we set up
242 * a fake ->nfct entry, pointing to the local &route_tee_track. We skip
243 * routing packets when we see they already have that ->nfct.
246 static struct ip_conntrack route_tee_track
;
248 static unsigned int ipt_route_target(struct sk_buff
**pskb
,
249 unsigned int hooknum
,
250 const struct net_device
*in
,
251 const struct net_device
*out
,
252 const void *targinfo
,
255 const struct ipt_route_target_info
*route_info
= targinfo
;
256 struct sk_buff
*skb
= *pskb
;
259 /* If we are at PREROUTING or INPUT hook
260 * the TTL isn't decreased by the IP stack
262 if (hooknum
== NF_IP_PRE_ROUTING
||
263 hooknum
== NF_IP_LOCAL_IN
) {
265 struct iphdr
*iph
= skb
->nh
.iph
;
270 if (ip_route_output(&rt
, iph
->saddr
, iph
->daddr
,
271 RT_TOS(iph
->tos
) | RTO_CONN
,
276 if (skb
->dev
== rt
->u
.dst
.dev
) {
277 /* Drop old route. */
278 dst_release(skb
->dst
);
279 skb
->dst
= &rt
->u
.dst
;
281 /* this will traverse normal stack, and
282 * thus call conntrack on the icmp packet */
283 icmp_send(skb
, ICMP_TIME_EXCEEDED
,
291 * If we are at INPUT the checksum must be recalculated since
292 * the length could change as the result of a defragmentation.
295 if(hooknum
== NF_IP_LOCAL_IN
) {
296 iph
->ttl
= iph
->ttl
- 1;
298 iph
->check
= ip_fast_csum((unsigned char *)iph
, iph
->ihl
);
300 ip_decrease_ttl(iph
);
304 if ((route_info
->flags
& IPT_ROUTE_TEE
)) {
306 * Copy the *pskb, and route the copy. Will later return
307 * IPT_CONTINUE for the original skb, which should continue
308 * on its way as if nothing happened. The copy should be
309 * independantly delivered to the ROUTE --gw.
311 skb
= skb_copy(*pskb
, GFP_ATOMIC
);
314 DEBUGP(KERN_DEBUG
"ipt_ROUTE: copy failed!\n");
319 /* Tell conntrack to forget this packet since it may get confused
320 * when a packet is leaving with dst address == our address.
321 * Good idea ? Dunno. Need advice.
323 * NEW: mark the skb with our &route_tee_track, so we avoid looping
324 * on any already routed packet.
326 if (!(route_info
->flags
& IPT_ROUTE_CONTINUE
)) {
327 nf_conntrack_put(skb
->nfct
);
328 skb
->nfct
= &route_tee_track
.infos
[IP_CT_NEW
];
329 nf_conntrack_get(skb
->nfct
);
331 #ifdef CONFIG_NETFILTER_DEBUG
336 if (route_info
->oif
[0]) {
337 res
= route_oif(route_info
, skb
);
338 } else if (route_info
->iif
[0]) {
339 res
= route_iif(route_info
, skb
);
340 } else if (route_info
->gw
) {
341 res
= route_gw(route_info
, skb
);
344 DEBUGP(KERN_DEBUG
"ipt_ROUTE: no parameter !\n");
348 if ((route_info
->flags
& IPT_ROUTE_TEE
))
355 static int ipt_route_checkentry(const char *tablename
,
356 const struct ipt_entry
*e
,
358 unsigned int targinfosize
,
359 unsigned int hook_mask
)
361 if (strcmp(tablename
, "mangle") != 0) {
362 printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
367 if (hook_mask
& ~( (1 << NF_IP_PRE_ROUTING
)
368 | (1 << NF_IP_LOCAL_IN
)
369 | (1 << NF_IP_FORWARD
)
370 | (1 << NF_IP_LOCAL_OUT
)
371 | (1 << NF_IP_POST_ROUTING
))) {
372 printk("ipt_ROUTE: bad hook\n");
376 if (targinfosize
!= IPT_ALIGN(sizeof(struct ipt_route_target_info
))) {
377 printk(KERN_WARNING
"ipt_ROUTE: targinfosize %u != %Zu\n",
379 IPT_ALIGN(sizeof(struct ipt_route_target_info
)));
387 static struct ipt_target ipt_route_reg
388 = { { NULL
, NULL
}, "ROUTE", ipt_route_target
, ipt_route_checkentry
, NULL
,
392 static int __init
init(void)
394 /* Set up fake conntrack (stolen from raw.patch):
395 - to never be deleted, not in any hashes */
396 atomic_set(&route_tee_track
.ct_general
.use
, 1);
397 /* - and look it like as a confirmed connection */
398 set_bit(IPS_CONFIRMED_BIT
, &route_tee_track
.status
);
399 /* - and prepare the ctinfo field for REJECT/NAT. */
400 route_tee_track
.infos
[IP_CT_NEW
].master
=
401 route_tee_track
.infos
[IP_CT_RELATED
].master
=
402 route_tee_track
.infos
[IP_CT_RELATED
+ IP_CT_IS_REPLY
].master
=
403 &route_tee_track
.ct_general
;
404 /* Initialize fake conntrack so that NAT will skip it */
405 route_tee_track
.nat
.info
.initialized
|=
406 (1 << IP_NAT_MANIP_SRC
) | (1 << IP_NAT_MANIP_DST
);
408 if (ipt_register_target(&ipt_route_reg
))
415 static void __exit
fini(void)
417 ipt_unregister_target(&ipt_route_reg
);
422 MODULE_LICENSE("GPL");