0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0010 #include <linux/module.h>
0011 #include <linux/skbuff.h>
0012 #include <linux/ip.h>
0013 #include <linux/ipv6.h>
0014 #include <net/checksum.h>
0015
0016 #include <linux/netfilter/x_tables.h>
0017 #include <linux/netfilter_ipv4/ipt_TTL.h>
0018 #include <linux/netfilter_ipv6/ip6t_HL.h>
0019
0020 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
0021 MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
0022 MODULE_DESCRIPTION("Xtables: Hoplimit/TTL Limit field modification target");
0023 MODULE_LICENSE("GPL");
0024
0025 static unsigned int
0026 ttl_tg(struct sk_buff *skb, const struct xt_action_param *par)
0027 {
0028 struct iphdr *iph;
0029 const struct ipt_TTL_info *info = par->targinfo;
0030 int new_ttl;
0031
0032 if (skb_ensure_writable(skb, sizeof(*iph)))
0033 return NF_DROP;
0034
0035 iph = ip_hdr(skb);
0036
0037 switch (info->mode) {
0038 case IPT_TTL_SET:
0039 new_ttl = info->ttl;
0040 break;
0041 case IPT_TTL_INC:
0042 new_ttl = iph->ttl + info->ttl;
0043 if (new_ttl > 255)
0044 new_ttl = 255;
0045 break;
0046 case IPT_TTL_DEC:
0047 new_ttl = iph->ttl - info->ttl;
0048 if (new_ttl < 0)
0049 new_ttl = 0;
0050 break;
0051 default:
0052 new_ttl = iph->ttl;
0053 break;
0054 }
0055
0056 if (new_ttl != iph->ttl) {
0057 csum_replace2(&iph->check, htons(iph->ttl << 8),
0058 htons(new_ttl << 8));
0059 iph->ttl = new_ttl;
0060 }
0061
0062 return XT_CONTINUE;
0063 }
0064
0065 static unsigned int
0066 hl_tg6(struct sk_buff *skb, const struct xt_action_param *par)
0067 {
0068 struct ipv6hdr *ip6h;
0069 const struct ip6t_HL_info *info = par->targinfo;
0070 int new_hl;
0071
0072 if (skb_ensure_writable(skb, sizeof(*ip6h)))
0073 return NF_DROP;
0074
0075 ip6h = ipv6_hdr(skb);
0076
0077 switch (info->mode) {
0078 case IP6T_HL_SET:
0079 new_hl = info->hop_limit;
0080 break;
0081 case IP6T_HL_INC:
0082 new_hl = ip6h->hop_limit + info->hop_limit;
0083 if (new_hl > 255)
0084 new_hl = 255;
0085 break;
0086 case IP6T_HL_DEC:
0087 new_hl = ip6h->hop_limit - info->hop_limit;
0088 if (new_hl < 0)
0089 new_hl = 0;
0090 break;
0091 default:
0092 new_hl = ip6h->hop_limit;
0093 break;
0094 }
0095
0096 ip6h->hop_limit = new_hl;
0097
0098 return XT_CONTINUE;
0099 }
0100
0101 static int ttl_tg_check(const struct xt_tgchk_param *par)
0102 {
0103 const struct ipt_TTL_info *info = par->targinfo;
0104
0105 if (info->mode > IPT_TTL_MAXMODE)
0106 return -EINVAL;
0107 if (info->mode != IPT_TTL_SET && info->ttl == 0)
0108 return -EINVAL;
0109 return 0;
0110 }
0111
0112 static int hl_tg6_check(const struct xt_tgchk_param *par)
0113 {
0114 const struct ip6t_HL_info *info = par->targinfo;
0115
0116 if (info->mode > IP6T_HL_MAXMODE)
0117 return -EINVAL;
0118 if (info->mode != IP6T_HL_SET && info->hop_limit == 0)
0119 return -EINVAL;
0120 return 0;
0121 }
0122
0123 static struct xt_target hl_tg_reg[] __read_mostly = {
0124 {
0125 .name = "TTL",
0126 .revision = 0,
0127 .family = NFPROTO_IPV4,
0128 .target = ttl_tg,
0129 .targetsize = sizeof(struct ipt_TTL_info),
0130 .table = "mangle",
0131 .checkentry = ttl_tg_check,
0132 .me = THIS_MODULE,
0133 },
0134 {
0135 .name = "HL",
0136 .revision = 0,
0137 .family = NFPROTO_IPV6,
0138 .target = hl_tg6,
0139 .targetsize = sizeof(struct ip6t_HL_info),
0140 .table = "mangle",
0141 .checkentry = hl_tg6_check,
0142 .me = THIS_MODULE,
0143 },
0144 };
0145
0146 static int __init hl_tg_init(void)
0147 {
0148 return xt_register_targets(hl_tg_reg, ARRAY_SIZE(hl_tg_reg));
0149 }
0150
0151 static void __exit hl_tg_exit(void)
0152 {
0153 xt_unregister_targets(hl_tg_reg, ARRAY_SIZE(hl_tg_reg));
0154 }
0155
0156 module_init(hl_tg_init);
0157 module_exit(hl_tg_exit);
0158 MODULE_ALIAS("ipt_TTL");
0159 MODULE_ALIAS("ip6t_HL");