[NETFILTER6]: Add new ip6tables HOPLIMIT target

This target allows users to modify the hoplimit header field of the
IPv6 header.

Signed-off-by: Harald Welte <laforge@netfilter.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Harald Welte and committed by
David S. Miller
0ac4f893 5f2c3b91

+157
+22
include/linux/netfilter_ipv6/ip6t_HL.h
··· 1 + /* Hop Limit modification module for ip6tables 2 + * Maciej Soltysiak <solt@dns.toxicfilms.tv> 3 + * Based on HW's TTL module */ 4 + 5 + #ifndef _IP6T_HL_H 6 + #define _IP6T_HL_H 7 + 8 + enum { 9 + IP6T_HL_SET = 0, 10 + IP6T_HL_INC, 11 + IP6T_HL_DEC 12 + }; 13 + 14 + #define IP6T_HL_MAXMODE IP6T_HL_DEC 15 + 16 + struct ip6t_HL_info { 17 + u_int8_t mode; 18 + u_int8_t hop_limit; 19 + }; 20 + 21 + 22 + #endif
+16
net/ipv6/netfilter/Kconfig
··· 239 239 240 240 To compile it as a module, choose M here. If unsure, say N. 241 241 242 + config IP6_NF_TARGET_HL 243 + tristate 'HL (hoplimit) target support' 244 + depends on IP6_NF_MANGLE 245 + help 246 + This option adds a `HL' target, which enables the user to decrement 247 + the hoplimit value of the IPv6 header or set it to a given (lower) 248 + value. 249 + 250 + While it is safe to decrement the hoplimit value, this option also 251 + enables functionality to increment and set the hoplimit value of the 252 + IPv6 header to arbitrary values. This is EXTREMELY DANGEROUS since 253 + you can easily create immortal packets that loop forever on the 254 + network. 255 + 256 + To compile it as a module, choose M here. If unsure, say N. 257 + 242 258 #dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES 243 259 config IP6_NF_RAW 244 260 tristate 'raw table support (required for TRACE)'
+1
net/ipv6/netfilter/Makefile
··· 20 20 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o 21 21 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o 22 22 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o 23 + obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o 23 24 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o 24 25 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o 25 26 obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
+118
net/ipv6/netfilter/ip6t_HL.c
··· 1 + /* 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> 12 + 13 + #include <linux/netfilter_ipv6/ip6_tables.h> 14 + #include <linux/netfilter_ipv6/ip6t_HL.h> 15 + 16 + MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>"); 17 + MODULE_DESCRIPTION("IP tables Hop Limit modification module"); 18 + MODULE_LICENSE("GPL"); 19 + 20 + static unsigned int ip6t_hl_target(struct sk_buff **pskb, 21 + const struct net_device *in, 22 + const struct net_device *out, 23 + unsigned int hooknum, 24 + const void *targinfo, void *userinfo) 25 + { 26 + struct ipv6hdr *ip6h; 27 + const struct ip6t_HL_info *info = targinfo; 28 + u_int16_t diffs[2]; 29 + int new_hl; 30 + 31 + if (!skb_make_writable(pskb, (*pskb)->len)) 32 + return NF_DROP; 33 + 34 + ip6h = (*pskb)->nh.ipv6h; 35 + 36 + switch (info->mode) { 37 + case IP6T_HL_SET: 38 + new_hl = info->hop_limit; 39 + break; 40 + case IP6T_HL_INC: 41 + new_hl = ip6h->hop_limit + info->hop_limit; 42 + if (new_hl > 255) 43 + new_hl = 255; 44 + break; 45 + case IP6T_HL_DEC: 46 + new_hl = ip6h->hop_limit - info->hop_limit; 47 + if (new_hl < 0) 48 + new_hl = 0; 49 + break; 50 + default: 51 + new_hl = ip6h->hop_limit; 52 + break; 53 + } 54 + 55 + if (new_hl != ip6h->hop_limit) { 56 + diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF; 57 + ip6h->hop_limit = new_hl; 58 + diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8); 59 + } 60 + 61 + return IP6T_CONTINUE; 62 + } 63 + 64 + static int ip6t_hl_checkentry(const char *tablename, 65 + const struct ip6t_entry *e, 66 + void *targinfo, 67 + unsigned int targinfosize, 68 + unsigned int hook_mask) 69 + { 70 + struct ip6t_HL_info *info = targinfo; 71 + 72 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) { 73 + printk(KERN_WARNING "ip6t_HL: targinfosize %u != %Zu\n", 74 + targinfosize, 75 + IP6T_ALIGN(sizeof(struct ip6t_HL_info))); 76 + return 0; 77 + } 78 + 79 + if (strcmp(tablename, "mangle")) { 80 + printk(KERN_WARNING "ip6t_HL: can only be called from " 81 + "\"mangle\" table, not \"%s\"\n", tablename); 82 + return 0; 83 + } 84 + 85 + if (info->mode > IP6T_HL_MAXMODE) { 86 + printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n", 87 + info->mode); 88 + return 0; 89 + } 90 + 91 + if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) { 92 + printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't " 93 + "make sense with value 0\n"); 94 + return 0; 95 + } 96 + 97 + return 1; 98 + } 99 + 100 + static struct ip6t_target ip6t_HL = { 101 + .name = "HL", 102 + .target = ip6t_hl_target, 103 + .checkentry = ip6t_hl_checkentry, 104 + .me = THIS_MODULE 105 + }; 106 + 107 + static int __init init(void) 108 + { 109 + return ip6t_register_target(&ip6t_HL); 110 + } 111 + 112 + static void __exit fini(void) 113 + { 114 + ip6t_unregister_target(&ip6t_HL); 115 + } 116 + 117 + module_init(init); 118 + module_exit(fini);