NETFILTER: remove unnecessary goto statement for error recovery
[tomato.git] / release / src-rt / linux / linux-2.6 / net / ipv4 / netfilter / ipt_ROUTE.c
blob66f0921d8518c69f5c4fd987cde975917fb179df
1 /*
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>
7 * v 1.11 2004/11/23
9 * This software is distributed under GNU GPL v2, 1991
12 #include <linux/module.h>
13 #include <linux/skbuff.h>
14 #include <linux/version.h>
15 #include <linux/ip.h>
16 #include <linux/netfilter_ipv4/ip_tables.h>
18 #include <linux/netfilter_ipv4/ipt_ROUTE.h>
19 #include <linux/netdevice.h>
20 #include <linux/route.h>
21 #include <linux/version.h>
22 #include <linux/if_arp.h>
23 #include <net/ip.h>
24 #include <net/route.h>
25 #include <net/icmp.h>
26 #include <net/checksum.h>
28 #include <net/netfilter/nf_conntrack.h>
30 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
31 #include <net/net_namespace.h>
32 #endif
34 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
35 #define NF_INET_PRE_ROUTING NF_IP_PRE_ROUTING
36 #define NF_INET_LOCAL_IN NF_IP_LOCAL_IN
37 #define NF_INET_FORWARD NF_IP_FORWARD
38 #define NF_INET_LOCAL_OUT NF_IP_LOCAL_OUT
39 #define NF_INET_POST_ROUTING NF_IP_POST_ROUTING
40 #endif
42 #if 0
43 #define DEBUGP printk
44 #else
45 #define DEBUGP(format, args...)
46 #endif
48 MODULE_LICENSE("GPL");
49 MODULE_AUTHOR("Cedric de Launois <delaunois@info.ucl.ac.be>");
50 MODULE_DESCRIPTION("iptables ROUTE target module");
52 /* Try to route the packet according to the routing keys specified in
53 * route_info. Keys are :
54 * - ifindex :
55 * 0 if no oif preferred,
56 * otherwise set to the index of the desired oif
57 * - route_info->gw :
58 * 0 if no gateway specified,
59 * otherwise set to the next host to which the pkt must be routed
60 * If success, skb->dev is the output device to which the packet must
61 * be sent and skb->dst is not NULL
63 * RETURN: -1 if an error occured
64 * 1 if the packet was succesfully routed to the
65 * destination desired
66 * 0 if the kernel routing table could not route the packet
67 * according to the keys specified
69 static int route(struct sk_buff *skb,
70 unsigned int ifindex,
71 const struct ipt_route_target_info *route_info)
73 int err;
74 struct rtable *rt;
75 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
76 struct iphdr *iph = ip_hdr(skb);
77 #else
78 struct iphdr *iph = skb->nh.iph;
79 #endif
80 struct flowi fl = {
81 .oif = ifindex,
82 .nl_u = {
83 .ip4_u = {
84 .daddr = iph->daddr,
85 .saddr = 0,
86 .tos = RT_TOS(iph->tos),
87 .scope = RT_SCOPE_UNIVERSE,
92 /* The destination address may be overloaded by the target */
93 if (route_info->gw)
94 fl.fl4_dst = route_info->gw;
96 /* Trying to route the packet using the standard routing table. */
97 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
98 if ((err = ip_route_output_key(&init_net, &rt, &fl))) {
99 #else
100 if ((err = ip_route_output_key(&rt, &fl))) {
101 #endif
102 if (net_ratelimit())
103 DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
104 return -1;
107 /* Drop old route. */
108 dst_release(skb->dst);
109 skb->dst = NULL;
111 /* Success if no oif specified or if the oif correspond to the
112 * one desired */
113 if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
114 skb->dst = &rt->u.dst;
115 skb->dev = skb->dst->dev;
116 skb->protocol = htons(ETH_P_IP);
117 return 1;
120 /* The interface selected by the routing table is not the one
121 * specified by the user. This may happen because the dst address
122 * is one of our own addresses.
124 if (net_ratelimit())
125 DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n",
126 NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
128 return 0;
132 /* Stolen from ip_finish_output2
133 * PRE : skb->dev is set to the device we are leaving by
134 * skb->dst is not NULL
135 * POST: the packet is sent with the link layer header pushed
136 * the packet is destroyed
138 static void ip_direct_send(struct sk_buff *skb)
140 struct dst_entry *dst = skb->dst;
141 struct hh_cache *hh = dst->hh;
142 struct net_device *dev = dst->dev;
143 int hh_len = LL_RESERVED_SPACE(dev);
144 unsigned seq;
146 /* Be paranoid, rather than too clever. */
147 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
148 if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) {
149 #else
150 if (unlikely(skb_headroom(skb) < hh_len && dev->hard_header)) {
151 #endif
152 struct sk_buff *skb2;
154 skb2 = skb_realloc_headroom(skb, LL_RESERVED_SPACE(dev));
155 if (skb2 == NULL) {
156 kfree_skb(skb);
157 return;
159 if (skb->sk)
160 skb_set_owner_w(skb2, skb->sk);
161 kfree_skb(skb);
162 skb = skb2;
165 if (hh) {
166 do {
167 int hh_alen;
169 seq = read_seqbegin(&hh->hh_lock);
170 hh_alen = HH_DATA_ALIGN(hh->hh_len);
171 memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
172 } while (read_seqretry(&hh->hh_lock, seq));
173 skb_push(skb, hh->hh_len);
174 hh->hh_output(skb);
175 } else if (dst->neighbour)
176 dst->neighbour->output(skb);
177 else {
178 if (net_ratelimit())
179 DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
180 kfree_skb(skb);
185 /* PRE : skb->dev is set to the device we are leaving by
186 * POST: - the packet is directly sent to the skb->dev device, without
187 * pushing the link layer header.
188 * - the packet is destroyed
190 static inline int dev_direct_send(struct sk_buff *skb)
192 return dev_queue_xmit(skb);
196 static unsigned int route_oif(const struct ipt_route_target_info *route_info,
197 struct sk_buff *skb)
199 unsigned int ifindex = 0;
200 struct net_device *dev_out = NULL;
202 /* The user set the interface name to use.
203 * Getting the current interface index.
205 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
206 if ((dev_out = dev_get_by_name(&init_net, route_info->oif))) {
207 #else
208 if ((dev_out = dev_get_by_name(route_info->oif))) {
209 #endif
210 ifindex = dev_out->ifindex;
211 } else {
212 /* Unknown interface name : packet dropped */
213 if (net_ratelimit())
214 DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
215 return NF_DROP;
218 /* Trying the standard way of routing packets */
219 switch (route(skb, ifindex, route_info)) {
220 case 1:
221 dev_put(dev_out);
222 if (route_info->flags & IPT_ROUTE_CONTINUE)
223 return IPT_CONTINUE;
225 ip_direct_send(skb);
226 return NF_STOLEN;
228 case 0:
229 /* Failed to send to oif. Trying the hard way */
230 if (route_info->flags & IPT_ROUTE_CONTINUE)
231 return NF_DROP;
233 if (net_ratelimit())
234 DEBUGP("ipt_ROUTE: forcing the use of %i\n",
235 ifindex);
237 /* We have to force the use of an interface.
238 * This interface must be a tunnel interface since
239 * otherwise we can't guess the hw address for
240 * the packet. For a tunnel interface, no hw address
241 * is needed.
243 if ((dev_out->type != ARPHRD_TUNNEL)
244 && (dev_out->type != ARPHRD_IPGRE)) {
245 if (net_ratelimit())
246 DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
247 dev_put(dev_out);
248 return NF_DROP;
251 /* Send the packet. This will also free skb
252 * Do not go through the POST_ROUTING hook because
253 * skb->dst is not set and because it will probably
254 * get confused by the destination IP address.
256 skb->dev = dev_out;
257 dev_direct_send(skb);
258 dev_put(dev_out);
259 return NF_STOLEN;
261 default:
262 /* Unexpected error */
263 dev_put(dev_out);
264 return NF_DROP;
269 static unsigned int route_iif(const struct ipt_route_target_info *route_info,
270 struct sk_buff *skb)
272 struct net_device *dev_in = NULL;
274 /* Getting the current interface index. */
275 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
276 if (!(dev_in = dev_get_by_name(&init_net, route_info->iif))) {
277 #else
278 if (!(dev_in = dev_get_by_name(route_info->iif))) {
279 #endif
280 if (net_ratelimit())
281 DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->iif);
282 return NF_DROP;
285 skb->dev = dev_in;
286 dst_release(skb->dst);
287 skb->dst = NULL;
289 netif_rx(skb);
290 dev_put(dev_in);
291 return NF_STOLEN;
295 static unsigned int route_gw(const struct ipt_route_target_info *route_info,
296 struct sk_buff *skb)
298 if (route(skb, 0, route_info)!=1)
299 return NF_DROP;
301 if (route_info->flags & IPT_ROUTE_CONTINUE)
302 return IPT_CONTINUE;
304 ip_direct_send(skb);
305 return NF_STOLEN;
309 /* To detect and deter routed packet loopback when using the --tee option,
310 * we take a page out of the raw.patch book: on the copied skb, we set up
311 * a fake ->nfct entry, pointing to the local &route_tee_track. We skip
312 * routing packets when we see they already have that ->nfct.
315 static struct nf_conn route_tee_track;
317 static unsigned int
318 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
319 target(struct sk_buff **pskb,
320 unsigned int hooknum,
321 const struct net_device *in,
322 const struct net_device *out,
323 const void *targinfo,
324 void *userinfo)
325 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
326 target(struct sk_buff **pskb,
327 const struct net_device *in,
328 const struct net_device *out,
329 unsigned int hooknum,
330 const void *targinfo,
331 void *userinfo)
332 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
333 target(struct sk_buff **pskb,
334 const struct net_device *in,
335 const struct net_device *out,
336 unsigned int hooknum,
337 const struct xt_target *target,
338 const void *targinfo,
339 void *userinfo)
340 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
341 target(struct sk_buff **pskb,
342 const struct net_device *in,
343 const struct net_device *out,
344 unsigned int hooknum,
345 const struct xt_target *target,
346 const void *targinfo)
347 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
348 target(struct sk_buff *skb,
349 const struct net_device *in,
350 const struct net_device *out,
351 unsigned int hooknum,
352 const struct xt_target *target,
353 const void *targinfo)
354 #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) */
355 target(struct sk_buff *skb,
356 const struct xt_target_param *par)
357 #endif
359 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
360 const struct ipt_route_target_info *route_info = targinfo;
361 #else
362 const struct ipt_route_target_info *route_info = par->targinfo;
363 unsigned int hooknum = par->hooknum;
364 #endif
365 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
366 struct sk_buff *skb = *pskb;
367 #endif
368 unsigned int res;
370 if (skb->nfct == &route_tee_track.ct_general) {
371 /* Loopback - a packet we already routed, is to be
372 * routed another time. Avoid that, now.
374 if (net_ratelimit())
375 DEBUGP(KERN_DEBUG "ipt_ROUTE: loopback - DROP!\n");
376 return NF_DROP;
379 /* If we are at PREROUTING or INPUT hook
380 * the TTL isn't decreased by the IP stack
382 if (hooknum == NF_INET_PRE_ROUTING ||
383 hooknum == NF_INET_LOCAL_IN) {
385 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
386 struct iphdr *iph = ip_hdr(skb);
387 #else
388 struct iphdr *iph = skb->nh.iph;
389 #endif
390 if (iph->ttl <= 1) {
391 struct rtable *rt;
392 struct flowi fl = {
393 .oif = 0,
394 .nl_u = {
395 .ip4_u = {
396 .daddr = iph->daddr,
397 .saddr = iph->saddr,
398 .tos = RT_TOS(iph->tos),
399 .scope = ((iph->tos & RTO_ONLINK) ?
400 RT_SCOPE_LINK :
401 RT_SCOPE_UNIVERSE)
406 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
407 if (ip_route_output_key(&init_net, &rt, &fl)) {
408 #else
409 if (ip_route_output_key(&rt, &fl)) {
410 #endif
411 return NF_DROP;
414 if (skb->dev == rt->u.dst.dev) {
415 /* Drop old route. */
416 dst_release(skb->dst);
417 skb->dst = &rt->u.dst;
419 /* this will traverse normal stack, and
420 * thus call conntrack on the icmp packet */
421 icmp_send(skb, ICMP_TIME_EXCEEDED,
422 ICMP_EXC_TTL, 0);
425 return NF_DROP;
429 * If we are at INPUT the checksum must be recalculated since
430 * the length could change as the result of a defragmentation.
432 if(hooknum == NF_INET_LOCAL_IN) {
433 iph->ttl = iph->ttl - 1;
434 iph->check = 0;
435 iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
436 } else {
437 ip_decrease_ttl(iph);
441 if ((route_info->flags & IPT_ROUTE_TEE)) {
443 * Copy the skb, and route the copy. Will later return
444 * IPT_CONTINUE for the original skb, which should continue
445 * on its way as if nothing happened. The copy should be
446 * independantly delivered to the ROUTE --gw.
448 skb = skb_copy(skb, GFP_ATOMIC);
449 if (!skb) {
450 if (net_ratelimit())
451 DEBUGP(KERN_DEBUG "ipt_ROUTE: copy failed!\n");
452 return IPT_CONTINUE;
456 /* Tell conntrack to forget this packet since it may get confused
457 * when a packet is leaving with dst address == our address.
458 * Good idea ? Dunno. Need advice.
460 * NEW: mark the skb with our &route_tee_track, so we avoid looping
461 * on any already routed packet.
463 if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
464 nf_conntrack_put(skb->nfct);
465 skb->nfct = &route_tee_track.ct_general;
466 skb->nfctinfo = IP_CT_NEW;
467 nf_conntrack_get(skb->nfct);
470 if (route_info->oif[0] != '\0') {
471 res = route_oif(route_info, skb);
472 } else if (route_info->iif[0] != '\0') {
473 res = route_iif(route_info, skb);
474 } else if (route_info->gw) {
475 res = route_gw(route_info, skb);
476 } else {
477 if (net_ratelimit())
478 DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
479 res = IPT_CONTINUE;
482 if ((route_info->flags & IPT_ROUTE_TEE))
483 res = IPT_CONTINUE;
485 return res;
488 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
489 static int
490 checkentry(const char *tablename,
491 const struct ipt_entry *e,
492 void *targinfo,
493 unsigned int targinfosize,
494 unsigned int hook_mask)
495 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
496 static int
497 checkentry(const char *tablename,
498 const void *e,
499 void *targinfo,
500 unsigned int targinfosize,
501 unsigned int hook_mask)
502 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
503 static int
504 checkentry(const char *tablename,
505 const void *e,
506 const struct xt_target *target,
507 void *targinfo,
508 unsigned int targinfosize,
509 unsigned int hook_mask)
510 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
511 static int
512 checkentry(const char *tablename,
513 const void *e,
514 const struct xt_target *target,
515 void *targinfo,
516 unsigned int hook_mask)
517 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
518 static bool
519 checkentry(const char *tablename,
520 const void *e,
521 const struct xt_target *target,
522 void *targinfo,
523 unsigned int hook_mask)
524 #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) */
525 static bool
526 checkentry(const struct xt_tgchk_param *par)
527 #endif
530 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
531 const char *tablename = par->table;
532 unsigned int hook_mask = par->hook_mask;
533 #endif
535 if (strcmp(tablename, "mangle") != 0) {
536 printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
537 tablename);
538 return 0;
541 if (hook_mask & ~( (1 << NF_INET_PRE_ROUTING)
542 | (1 << NF_INET_LOCAL_IN)
543 | (1 << NF_INET_FORWARD)
544 | (1 << NF_INET_LOCAL_OUT)
545 | (1 << NF_INET_POST_ROUTING))) {
546 printk("ipt_ROUTE: bad hook\n");
547 return 0;
550 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
551 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
552 printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
553 targinfosize,
554 IPT_ALIGN(sizeof(struct ipt_route_target_info)));
555 return 0;
557 #endif
559 return 1;
562 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
563 static struct ipt_target xt_route_reg = {
564 #else
565 static struct ipt_target ipt_route_reg = {
566 #endif
567 .name = "ROUTE",
568 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
569 .family = AF_INET,
570 #endif
571 .target = target,
572 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
573 .targetsize = sizeof(struct ipt_route_target_info),
574 #endif
575 .checkentry = checkentry,
576 .me = THIS_MODULE,
579 static int __init init(void)
581 /* Set up fake conntrack (stolen from raw.patch):
582 - to never be deleted, not in any hashes */
583 atomic_set(&route_tee_track.ct_general.use, 1);
584 /* - and look it like as a confirmed connection */
585 set_bit(IPS_CONFIRMED_BIT, &route_tee_track.status);
586 /* Initialize fake conntrack so that NAT will skip it */
587 route_tee_track.status |= IPS_NAT_DONE_MASK;
589 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
590 return xt_register_target(&xt_route_reg);
591 #else
592 return ipt_register_target(&ipt_route_reg);
593 #endif
597 static void __exit fini(void)
599 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
600 xt_unregister_target(&xt_route_reg);
601 #else
602 ipt_unregister_target(&ipt_route_reg);
603 #endif
606 module_init(init);
607 module_exit(fini);