Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * TTL modification target for IP tables
0004  * (C) 2000,2005 by Harald Welte <laforge@netfilter.org>
0005  *
0006  * Hop Limit modification target for ip6tables
0007  * Maciej Soltysiak <solt@dns.toxicfilms.tv>
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");