netfilter: add IPv4/6 IPComp extension match support
With this plugin, user could specify IPComp tagged with certain CPI that host not interested will be DROPped or any other action. For example: iptables -A INPUT -p 108 -m ipcomp --ipcompspi 0x87 -j DROP ip6tables -A INPUT -p 108 -m ipcomp --ipcompspi 0x87 -j DROP Then input IPComp packet with CPI equates 0x87 will not reach upper layer anymore. Signed-off-by: Fan Du <fan.du@windriver.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
		
					parent
					
						
							
								08c0cad69f
							
						
					
				
			
			
				commit
				
					
						6a649f3398
					
				
			
		
					 5 changed files with 138 additions and 0 deletions
				
			
		|  | @ -54,6 +54,7 @@ header-y += xt_ecn.h | |||
| header-y += xt_esp.h | ||||
| header-y += xt_hashlimit.h | ||||
| header-y += xt_helper.h | ||||
| header-y += xt_ipcomp.h | ||||
| header-y += xt_iprange.h | ||||
| header-y += xt_ipvs.h | ||||
| header-y += xt_length.h | ||||
|  |  | |||
							
								
								
									
										16
									
								
								include/uapi/linux/netfilter/xt_ipcomp.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								include/uapi/linux/netfilter/xt_ipcomp.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | |||
| #ifndef _XT_IPCOMP_H | ||||
| #define _XT_IPCOMP_H | ||||
| 
 | ||||
| #include <linux/types.h> | ||||
| 
 | ||||
| struct xt_ipcomp { | ||||
| 	__u32 spis[2];	/* Security Parameter Index */ | ||||
| 	__u8 invflags;	/* Inverse flags */ | ||||
| 	__u8 hdrres;	/* Test of the Reserved Filed */ | ||||
| }; | ||||
| 
 | ||||
| /* Values for "invflags" field in struct xt_ipcomp. */ | ||||
| #define XT_IPCOMP_INV_SPI	0x01	/* Invert the sense of spi. */ | ||||
| #define XT_IPCOMP_INV_MASK	0x01	/* All possible flags. */ | ||||
| 
 | ||||
| #endif /*_XT_IPCOMP_H*/ | ||||
|  | @ -1035,6 +1035,15 @@ config NETFILTER_XT_MATCH_HL | |||
| 	in the IPv6 header, or the time-to-live field in the IPv4 | ||||
| 	header of the packet. | ||||
| 
 | ||||
| config NETFILTER_XT_MATCH_IPCOMP | ||||
| 	tristate '"ipcomp" match support' | ||||
| 	depends on NETFILTER_ADVANCED | ||||
| 	help | ||||
| 	  This match extension allows you to match a range of CPIs(16 bits) | ||||
| 	  inside IPComp header of IPSec packets. | ||||
| 
 | ||||
| 	  To compile it as a module, choose M here.  If unsure, say N. | ||||
| 
 | ||||
| config NETFILTER_XT_MATCH_IPRANGE | ||||
| 	tristate '"iprange" address range match support' | ||||
| 	depends on NETFILTER_ADVANCED | ||||
|  |  | |||
|  | @ -133,6 +133,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o | |||
| obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o | ||||
| obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o | ||||
| obj-$(CONFIG_NETFILTER_XT_MATCH_HL) += xt_hl.o | ||||
| obj-$(CONFIG_NETFILTER_XT_MATCH_IPCOMP) += xt_ipcomp.o | ||||
| obj-$(CONFIG_NETFILTER_XT_MATCH_IPRANGE) += xt_iprange.o | ||||
| obj-$(CONFIG_NETFILTER_XT_MATCH_IPVS) += xt_ipvs.o | ||||
| obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o | ||||
|  |  | |||
							
								
								
									
										111
									
								
								net/netfilter/xt_ipcomp.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								net/netfilter/xt_ipcomp.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,111 @@ | |||
| /*  Kernel module to match IPComp parameters for IPv4 and IPv6
 | ||||
|  * | ||||
|  *  Copyright (C) 2013 WindRiver | ||||
|  * | ||||
|  *  Author: | ||||
|  *  Fan Du <fan.du@windriver.com> | ||||
|  * | ||||
|  *  Based on: | ||||
|  *  net/netfilter/xt_esp.c | ||||
|  * | ||||
|  *  This program is free software; you can redistribute it and/or | ||||
|  *  modify it under the terms of the GNU General Public License | ||||
|  *  as published by the Free Software Foundation; either version | ||||
|  *  2 of the License, or (at your option) any later version. | ||||
|  */ | ||||
| 
 | ||||
| #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||||
| #include <linux/in.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/skbuff.h> | ||||
| #include <linux/ip.h> | ||||
| 
 | ||||
| #include <linux/netfilter/xt_ipcomp.h> | ||||
| #include <linux/netfilter/x_tables.h> | ||||
| 
 | ||||
| MODULE_LICENSE("GPL"); | ||||
| MODULE_AUTHOR("Fan Du <fan.du@windriver.com>"); | ||||
| MODULE_DESCRIPTION("Xtables: IPv4/6 IPsec-IPComp SPI match"); | ||||
| 
 | ||||
| /* Returns 1 if the spi is matched by the range, 0 otherwise */ | ||||
| static inline bool | ||||
| spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert) | ||||
| { | ||||
| 	bool r; | ||||
| 	pr_debug("spi_match:%c 0x%x <= 0x%x <= 0x%x\n", | ||||
| 		 invert ? '!' : ' ', min, spi, max); | ||||
| 	r = (spi >= min && spi <= max) ^ invert; | ||||
| 	pr_debug(" result %s\n", r ? "PASS" : "FAILED"); | ||||
| 	return r; | ||||
| } | ||||
| 
 | ||||
| static bool comp_mt(const struct sk_buff *skb, struct xt_action_param *par) | ||||
| { | ||||
| 	struct ip_comp_hdr _comphdr; | ||||
| 	const struct ip_comp_hdr *chdr; | ||||
| 	const struct xt_ipcomp *compinfo = par->matchinfo; | ||||
| 
 | ||||
| 	/* Must not be a fragment. */ | ||||
| 	if (par->fragoff != 0) | ||||
| 		return false; | ||||
| 
 | ||||
| 	chdr = skb_header_pointer(skb, par->thoff, sizeof(_comphdr), &_comphdr); | ||||
| 	if (chdr == NULL) { | ||||
| 		/* We've been asked to examine this packet, and we
 | ||||
| 		 * can't.  Hence, no choice but to drop. | ||||
| 		 */ | ||||
| 		pr_debug("Dropping evil IPComp tinygram.\n"); | ||||
| 		par->hotdrop = true; | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	return spi_match(compinfo->spis[0], compinfo->spis[1], | ||||
| 			 ntohl(chdr->cpi << 16), | ||||
| 			 !!(compinfo->invflags & XT_IPCOMP_INV_SPI)); | ||||
| } | ||||
| 
 | ||||
| static int comp_mt_check(const struct xt_mtchk_param *par) | ||||
| { | ||||
| 	const struct xt_ipcomp *compinfo = par->matchinfo; | ||||
| 
 | ||||
| 	/* Must specify no unknown invflags */ | ||||
| 	if (compinfo->invflags & ~XT_IPCOMP_INV_MASK) { | ||||
| 		pr_err("unknown flags %X\n", compinfo->invflags); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static struct xt_match comp_mt_reg[] __read_mostly = { | ||||
| 	{ | ||||
| 		.name		= "ipcomp", | ||||
| 		.family		= NFPROTO_IPV4, | ||||
| 		.match		= comp_mt, | ||||
| 		.matchsize	= sizeof(struct xt_ipcomp), | ||||
| 		.proto		= IPPROTO_COMP, | ||||
| 		.checkentry	= comp_mt_check, | ||||
| 		.me		= THIS_MODULE, | ||||
| 	}, | ||||
| 	{ | ||||
| 		.name		= "ipcomp", | ||||
| 		.family		= NFPROTO_IPV6, | ||||
| 		.match		= comp_mt, | ||||
| 		.matchsize	= sizeof(struct xt_ipcomp), | ||||
| 		.proto		= IPPROTO_COMP, | ||||
| 		.checkentry	= comp_mt_check, | ||||
| 		.me		= THIS_MODULE, | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| static int __init comp_mt_init(void) | ||||
| { | ||||
| 	return xt_register_matches(comp_mt_reg, ARRAY_SIZE(comp_mt_reg)); | ||||
| } | ||||
| 
 | ||||
| static void __exit comp_mt_exit(void) | ||||
| { | ||||
| 	xt_unregister_matches(comp_mt_reg, ARRAY_SIZE(comp_mt_reg)); | ||||
| } | ||||
| 
 | ||||
| module_init(comp_mt_init); | ||||
| module_exit(comp_mt_exit); | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 fan.du
				fan.du