Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+22 −0
Original line number Original line Diff line number Diff line
/* 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
+16 −0
Original line number Original line Diff line number Diff line
@@ -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)'
+1 −0
Original line number Original line Diff line number Diff line
@@ -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
+118 −0
Original line number Original line Diff line number Diff line
/* 
 * 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);