]>
Commit | Line | Data |
---|---|---|
563d36eb JE |
1 | /* |
2 | * TTL modification target for IP tables | |
3 | * (C) 2000,2005 by Harald Welte <laforge@netfilter.org> | |
4 | * | |
5 | * Hop Limit modification target for ip6tables | |
6 | * Maciej Soltysiak <solt@dns.toxicfilms.tv> | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License version 2 as | |
10 | * published by the Free Software Foundation. | |
11 | */ | |
8bee4bad | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
563d36eb JE |
13 | #include <linux/module.h> |
14 | #include <linux/skbuff.h> | |
15 | #include <linux/ip.h> | |
16 | #include <linux/ipv6.h> | |
17 | #include <net/checksum.h> | |
18 | ||
19 | #include <linux/netfilter/x_tables.h> | |
20 | #include <linux/netfilter_ipv4/ipt_TTL.h> | |
21 | #include <linux/netfilter_ipv6/ip6t_HL.h> | |
22 | ||
23 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | |
24 | MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>"); | |
25 | MODULE_DESCRIPTION("Xtables: Hoplimit/TTL Limit field modification target"); | |
26 | MODULE_LICENSE("GPL"); | |
27 | ||
28 | static unsigned int | |
4b560b44 | 29 | ttl_tg(struct sk_buff *skb, const struct xt_action_param *par) |
563d36eb JE |
30 | { |
31 | struct iphdr *iph; | |
32 | const struct ipt_TTL_info *info = par->targinfo; | |
33 | int new_ttl; | |
34 | ||
35 | if (!skb_make_writable(skb, skb->len)) | |
36 | return NF_DROP; | |
37 | ||
38 | iph = ip_hdr(skb); | |
39 | ||
40 | switch (info->mode) { | |
181b1e9c JP |
41 | case IPT_TTL_SET: |
42 | new_ttl = info->ttl; | |
43 | break; | |
44 | case IPT_TTL_INC: | |
45 | new_ttl = iph->ttl + info->ttl; | |
46 | if (new_ttl > 255) | |
47 | new_ttl = 255; | |
48 | break; | |
49 | case IPT_TTL_DEC: | |
50 | new_ttl = iph->ttl - info->ttl; | |
51 | if (new_ttl < 0) | |
52 | new_ttl = 0; | |
53 | break; | |
54 | default: | |
55 | new_ttl = iph->ttl; | |
56 | break; | |
563d36eb JE |
57 | } |
58 | ||
59 | if (new_ttl != iph->ttl) { | |
60 | csum_replace2(&iph->check, htons(iph->ttl << 8), | |
61 | htons(new_ttl << 8)); | |
62 | iph->ttl = new_ttl; | |
63 | } | |
64 | ||
65 | return XT_CONTINUE; | |
66 | } | |
67 | ||
68 | static unsigned int | |
4b560b44 | 69 | hl_tg6(struct sk_buff *skb, const struct xt_action_param *par) |
563d36eb JE |
70 | { |
71 | struct ipv6hdr *ip6h; | |
72 | const struct ip6t_HL_info *info = par->targinfo; | |
73 | int new_hl; | |
74 | ||
75 | if (!skb_make_writable(skb, skb->len)) | |
76 | return NF_DROP; | |
77 | ||
78 | ip6h = ipv6_hdr(skb); | |
79 | ||
80 | switch (info->mode) { | |
181b1e9c JP |
81 | case IP6T_HL_SET: |
82 | new_hl = info->hop_limit; | |
83 | break; | |
84 | case IP6T_HL_INC: | |
85 | new_hl = ip6h->hop_limit + info->hop_limit; | |
86 | if (new_hl > 255) | |
87 | new_hl = 255; | |
88 | break; | |
89 | case IP6T_HL_DEC: | |
90 | new_hl = ip6h->hop_limit - info->hop_limit; | |
91 | if (new_hl < 0) | |
92 | new_hl = 0; | |
93 | break; | |
94 | default: | |
95 | new_hl = ip6h->hop_limit; | |
96 | break; | |
563d36eb JE |
97 | } |
98 | ||
99 | ip6h->hop_limit = new_hl; | |
100 | ||
101 | return XT_CONTINUE; | |
102 | } | |
103 | ||
135367b8 | 104 | static int ttl_tg_check(const struct xt_tgchk_param *par) |
563d36eb JE |
105 | { |
106 | const struct ipt_TTL_info *info = par->targinfo; | |
107 | ||
108 | if (info->mode > IPT_TTL_MAXMODE) { | |
8bee4bad | 109 | pr_info("TTL: invalid or unknown mode %u\n", info->mode); |
4a5a5c73 | 110 | return -EINVAL; |
563d36eb JE |
111 | } |
112 | if (info->mode != IPT_TTL_SET && info->ttl == 0) | |
d6b00a53 JE |
113 | return -EINVAL; |
114 | return 0; | |
563d36eb JE |
115 | } |
116 | ||
135367b8 | 117 | static int hl_tg6_check(const struct xt_tgchk_param *par) |
563d36eb JE |
118 | { |
119 | const struct ip6t_HL_info *info = par->targinfo; | |
120 | ||
121 | if (info->mode > IP6T_HL_MAXMODE) { | |
8bee4bad | 122 | pr_info("invalid or unknown mode %u\n", info->mode); |
d6b00a53 | 123 | return -EINVAL; |
563d36eb JE |
124 | } |
125 | if (info->mode != IP6T_HL_SET && info->hop_limit == 0) { | |
8bee4bad | 126 | pr_info("increment/decrement does not " |
563d36eb | 127 | "make sense with value 0\n"); |
d6b00a53 | 128 | return -EINVAL; |
563d36eb | 129 | } |
d6b00a53 | 130 | return 0; |
563d36eb JE |
131 | } |
132 | ||
133 | static struct xt_target hl_tg_reg[] __read_mostly = { | |
134 | { | |
135 | .name = "TTL", | |
136 | .revision = 0, | |
137 | .family = NFPROTO_IPV4, | |
138 | .target = ttl_tg, | |
139 | .targetsize = sizeof(struct ipt_TTL_info), | |
140 | .table = "mangle", | |
141 | .checkentry = ttl_tg_check, | |
142 | .me = THIS_MODULE, | |
143 | }, | |
144 | { | |
145 | .name = "HL", | |
146 | .revision = 0, | |
147 | .family = NFPROTO_IPV6, | |
148 | .target = hl_tg6, | |
149 | .targetsize = sizeof(struct ip6t_HL_info), | |
150 | .table = "mangle", | |
151 | .checkentry = hl_tg6_check, | |
152 | .me = THIS_MODULE, | |
153 | }, | |
154 | }; | |
155 | ||
156 | static int __init hl_tg_init(void) | |
157 | { | |
158 | return xt_register_targets(hl_tg_reg, ARRAY_SIZE(hl_tg_reg)); | |
159 | } | |
160 | ||
161 | static void __exit hl_tg_exit(void) | |
162 | { | |
163 | xt_unregister_targets(hl_tg_reg, ARRAY_SIZE(hl_tg_reg)); | |
164 | } | |
165 | ||
166 | module_init(hl_tg_init); | |
167 | module_exit(hl_tg_exit); | |
168 | MODULE_ALIAS("ipt_TTL"); | |
169 | MODULE_ALIAS("ip6t_HL"); |