1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * (C) 1999-2001 Paul `Rusty' Russell 4 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org> 5 * Copyright (c) 2011 Patrick McHardy <kaber@trash.net> 6 * 7 * Based on Rusty Russell's IPv4 REDIRECT target. Development of IPv6 8 * NAT funded by Astaro. 9 */ 10 11 #include <linux/if.h> 12 #include <linux/inetdevice.h> 13 #include <linux/ip.h> 14 #include <linux/kernel.h> 15 #include <linux/module.h> 16 #include <linux/netdevice.h> 17 #include <linux/netfilter.h> 18 #include <linux/types.h> 19 #include <linux/netfilter_ipv4.h> 20 #include <linux/netfilter_ipv6.h> 21 #include <linux/netfilter/x_tables.h> 22 #include <net/addrconf.h> 23 #include <net/checksum.h> 24 #include <net/protocol.h> 25 #include <net/netfilter/nf_nat.h> 26 #include <net/netfilter/nf_nat_redirect.h> 27 28 static unsigned int 29 redirect_tg6(struct sk_buff *skb, const struct xt_action_param *par) 30 { 31 return nf_nat_redirect_ipv6(skb, par->targinfo, xt_hooknum(par)); 32 } 33 34 static int redirect_tg6_checkentry(const struct xt_tgchk_param *par) 35 { 36 const struct nf_nat_range2 *range = par->targinfo; 37 38 if (range->flags & NF_NAT_RANGE_MAP_IPS) 39 return -EINVAL; 40 41 return nf_ct_netns_get(par->net, par->family); 42 } 43 44 static void redirect_tg_destroy(const struct xt_tgdtor_param *par) 45 { 46 nf_ct_netns_put(par->net, par->family); 47 } 48 49 static int redirect_tg4_check(const struct xt_tgchk_param *par) 50 { 51 const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; 52 53 if (mr->range[0].flags & NF_NAT_RANGE_MAP_IPS) { 54 pr_debug("bad MAP_IPS.\n"); 55 return -EINVAL; 56 } 57 if (mr->rangesize != 1) { 58 pr_debug("bad rangesize %u.\n", mr->rangesize); 59 return -EINVAL; 60 } 61 return nf_ct_netns_get(par->net, par->family); 62 } 63 64 static unsigned int 65 redirect_tg4(struct sk_buff *skb, const struct xt_action_param *par) 66 { 67 const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; 68 struct nf_nat_range2 range = { 69 .flags = mr->range[0].flags, 70 .min_proto = mr->range[0].min, 71 .max_proto = mr->range[0].max, 72 }; 73 74 return nf_nat_redirect_ipv4(skb, &range, xt_hooknum(par)); 75 } 76 77 static struct xt_target redirect_tg_reg[] __read_mostly = { 78 { 79 .name = "REDIRECT", 80 .family = NFPROTO_IPV6, 81 .revision = 0, 82 .table = "nat", 83 .checkentry = redirect_tg6_checkentry, 84 .destroy = redirect_tg_destroy, 85 .target = redirect_tg6, 86 .targetsize = sizeof(struct nf_nat_range), 87 .hooks = (1 << NF_INET_PRE_ROUTING) | 88 (1 << NF_INET_LOCAL_OUT), 89 .me = THIS_MODULE, 90 }, 91 { 92 .name = "REDIRECT", 93 .family = NFPROTO_IPV4, 94 .revision = 0, 95 .table = "nat", 96 .target = redirect_tg4, 97 .checkentry = redirect_tg4_check, 98 .destroy = redirect_tg_destroy, 99 .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), 100 .hooks = (1 << NF_INET_PRE_ROUTING) | 101 (1 << NF_INET_LOCAL_OUT), 102 .me = THIS_MODULE, 103 }, 104 }; 105 106 static int __init redirect_tg_init(void) 107 { 108 return xt_register_targets(redirect_tg_reg, 109 ARRAY_SIZE(redirect_tg_reg)); 110 } 111 112 static void __exit redirect_tg_exit(void) 113 { 114 xt_unregister_targets(redirect_tg_reg, ARRAY_SIZE(redirect_tg_reg)); 115 } 116 117 module_init(redirect_tg_init); 118 module_exit(redirect_tg_exit); 119 120 MODULE_LICENSE("GPL"); 121 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 122 MODULE_DESCRIPTION("Xtables: Connection redirection to localhost"); 123 MODULE_ALIAS("ip6t_REDIRECT"); 124 MODULE_ALIAS("ipt_REDIRECT"); 125