Commit | Line | Data |
---|---|---|
1ab1457c | 1 | /* |
0ac4f893 HW |
2 | * Hop Limit modification target for ip6tables |
3 | * Maciej Soltysiak <solt@dns.toxicfilms.tv> | |
4 | * Based on HW's TTL module | |
5 | * | |
6 | * This software is distributed under the terms of GNU GPL | |
7 | */ | |
8 | ||
9 | #include <linux/module.h> | |
10 | #include <linux/skbuff.h> | |
11 | #include <linux/ip.h> | |
6709dbbb | 12 | #include <linux/ipv6.h> |
0ac4f893 | 13 | |
6709dbbb | 14 | #include <linux/netfilter/x_tables.h> |
0ac4f893 HW |
15 | #include <linux/netfilter_ipv6/ip6t_HL.h> |
16 | ||
17 | MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>"); | |
2ae15b64 | 18 | MODULE_DESCRIPTION("Xtables: IPv6 Hop Limit field modification target"); |
0ac4f893 HW |
19 | MODULE_LICENSE("GPL"); |
20 | ||
d3c5ee6d | 21 | static unsigned int |
7eb35586 | 22 | hl_tg6(struct sk_buff *skb, const struct xt_target_param *par) |
0ac4f893 HW |
23 | { |
24 | struct ipv6hdr *ip6h; | |
7eb35586 | 25 | const struct ip6t_HL_info *info = par->targinfo; |
0ac4f893 HW |
26 | int new_hl; |
27 | ||
3db05fea | 28 | if (!skb_make_writable(skb, skb->len)) |
0ac4f893 HW |
29 | return NF_DROP; |
30 | ||
3db05fea | 31 | ip6h = ipv6_hdr(skb); |
0ac4f893 HW |
32 | |
33 | switch (info->mode) { | |
34 | case IP6T_HL_SET: | |
35 | new_hl = info->hop_limit; | |
36 | break; | |
37 | case IP6T_HL_INC: | |
38 | new_hl = ip6h->hop_limit + info->hop_limit; | |
39 | if (new_hl > 255) | |
40 | new_hl = 255; | |
41 | break; | |
42 | case IP6T_HL_DEC: | |
43 | new_hl = ip6h->hop_limit - info->hop_limit; | |
44 | if (new_hl < 0) | |
45 | new_hl = 0; | |
46 | break; | |
47 | default: | |
48 | new_hl = ip6h->hop_limit; | |
49 | break; | |
50 | } | |
51 | ||
2822b0d9 | 52 | ip6h->hop_limit = new_hl; |
0ac4f893 | 53 | |
6709dbbb | 54 | return XT_CONTINUE; |
0ac4f893 HW |
55 | } |
56 | ||
d3c5ee6d JE |
57 | static bool |
58 | hl_tg6_check(const char *tablename, const void *entry, | |
59 | const struct xt_target *target, void *targinfo, | |
60 | unsigned int hook_mask) | |
0ac4f893 | 61 | { |
a47362a2 | 62 | const struct ip6t_HL_info *info = targinfo; |
0ac4f893 | 63 | |
0ac4f893 | 64 | if (info->mode > IP6T_HL_MAXMODE) { |
1ab1457c | 65 | printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n", |
0ac4f893 | 66 | info->mode); |
e1931b78 | 67 | return false; |
0ac4f893 | 68 | } |
7c4e36bc | 69 | if (info->mode != IP6T_HL_SET && info->hop_limit == 0) { |
0ac4f893 HW |
70 | printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't " |
71 | "make sense with value 0\n"); | |
e1931b78 | 72 | return false; |
0ac4f893 | 73 | } |
e1931b78 | 74 | return true; |
0ac4f893 HW |
75 | } |
76 | ||
d3c5ee6d | 77 | static struct xt_target hl_tg6_reg __read_mostly = { |
1ab1457c | 78 | .name = "HL", |
ee999d8b | 79 | .family = NFPROTO_IPV6, |
d3c5ee6d | 80 | .target = hl_tg6, |
7f939713 PM |
81 | .targetsize = sizeof(struct ip6t_HL_info), |
82 | .table = "mangle", | |
d3c5ee6d | 83 | .checkentry = hl_tg6_check, |
0ac4f893 HW |
84 | .me = THIS_MODULE |
85 | }; | |
86 | ||
d3c5ee6d | 87 | static int __init hl_tg6_init(void) |
0ac4f893 | 88 | { |
d3c5ee6d | 89 | return xt_register_target(&hl_tg6_reg); |
0ac4f893 HW |
90 | } |
91 | ||
d3c5ee6d | 92 | static void __exit hl_tg6_exit(void) |
0ac4f893 | 93 | { |
d3c5ee6d | 94 | xt_unregister_target(&hl_tg6_reg); |
0ac4f893 HW |
95 | } |
96 | ||
d3c5ee6d JE |
97 | module_init(hl_tg6_init); |
98 | module_exit(hl_tg6_exit); |