Commit 0ac4f893 authored by Harald Welte's avatar Harald Welte Committed by David S. Miller

[NETFILTER6]: Add new ip6tables HOPLIMIT target

This target allows users to modify the hoplimit header field of the
IPv6 header.
Signed-off-by: default avatarHarald Welte <laforge@netfilter.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5f2c3b91
/* Hop Limit modification module for ip6tables
* Maciej Soltysiak <solt@dns.toxicfilms.tv>
* Based on HW's TTL module */
#ifndef _IP6T_HL_H
#define _IP6T_HL_H
enum {
IP6T_HL_SET = 0,
IP6T_HL_INC,
IP6T_HL_DEC
};
#define IP6T_HL_MAXMODE IP6T_HL_DEC
struct ip6t_HL_info {
u_int8_t mode;
u_int8_t hop_limit;
};
#endif
...@@ -239,6 +239,22 @@ config IP6_NF_TARGET_MARK ...@@ -239,6 +239,22 @@ config IP6_NF_TARGET_MARK
To compile it as a module, choose M here. If unsure, say N. To compile it as a module, choose M here. If unsure, say N.
config IP6_NF_TARGET_HL
tristate 'HL (hoplimit) target support'
depends on IP6_NF_MANGLE
help
This option adds a `HL' target, which enables the user to decrement
the hoplimit value of the IPv6 header or set it to a given (lower)
value.
While it is safe to decrement the hoplimit value, this option also
enables functionality to increment and set the hoplimit value of the
IPv6 header to arbitrary values. This is EXTREMELY DANGEROUS since
you can easily create immortal packets that loop forever on the
network.
To compile it as a module, choose M here. If unsure, say N.
#dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES #dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
config IP6_NF_RAW config IP6_NF_RAW
tristate 'raw table support (required for TRACE)' tristate 'raw table support (required for TRACE)'
......
...@@ -20,6 +20,7 @@ obj-$(CONFIG_IP6_NF_MATCH_PHYSDEV) += ip6t_physdev.o ...@@ -20,6 +20,7 @@ obj-$(CONFIG_IP6_NF_MATCH_PHYSDEV) += ip6t_physdev.o
obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
......
/*
* Hop Limit modification target for ip6tables
* Maciej Soltysiak <solt@dns.toxicfilms.tv>
* Based on HW's TTL module
*
* This software is distributed under the terms of GNU GPL
*/
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <linux/netfilter_ipv6/ip6t_HL.h>
MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
MODULE_DESCRIPTION("IP tables Hop Limit modification module");
MODULE_LICENSE("GPL");
static unsigned int ip6t_hl_target(struct sk_buff **pskb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
const void *targinfo, void *userinfo)
{
struct ipv6hdr *ip6h;
const struct ip6t_HL_info *info = targinfo;
u_int16_t diffs[2];
int new_hl;
if (!skb_make_writable(pskb, (*pskb)->len))
return NF_DROP;
ip6h = (*pskb)->nh.ipv6h;
switch (info->mode) {
case IP6T_HL_SET:
new_hl = info->hop_limit;
break;
case IP6T_HL_INC:
new_hl = ip6h->hop_limit + info->hop_limit;
if (new_hl > 255)
new_hl = 255;
break;
case IP6T_HL_DEC:
new_hl = ip6h->hop_limit - info->hop_limit;
if (new_hl < 0)
new_hl = 0;
break;
default:
new_hl = ip6h->hop_limit;
break;
}
if (new_hl != ip6h->hop_limit) {
diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
ip6h->hop_limit = new_hl;
diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
}
return IP6T_CONTINUE;
}
static int ip6t_hl_checkentry(const char *tablename,
const struct ip6t_entry *e,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
{
struct ip6t_HL_info *info = targinfo;
if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
printk(KERN_WARNING "ip6t_HL: targinfosize %u != %Zu\n",
targinfosize,
IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
return 0;
}
if (strcmp(tablename, "mangle")) {
printk(KERN_WARNING "ip6t_HL: can only be called from "
"\"mangle\" table, not \"%s\"\n", tablename);
return 0;
}
if (info->mode > IP6T_HL_MAXMODE) {
printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n",
info->mode);
return 0;
}
if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't "
"make sense with value 0\n");
return 0;
}
return 1;
}
static struct ip6t_target ip6t_HL = {
.name = "HL",
.target = ip6t_hl_target,
.checkentry = ip6t_hl_checkentry,
.me = THIS_MODULE
};
static int __init init(void)
{
return ip6t_register_target(&ip6t_HL);
}
static void __exit fini(void)
{
ip6t_unregister_target(&ip6t_HL);
}
module_init(init);
module_exit(fini);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment