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_esp.h | ||||||
| header-y += xt_hashlimit.h | header-y += xt_hashlimit.h | ||||||
| header-y += xt_helper.h | header-y += xt_helper.h | ||||||
|  | header-y += xt_ipcomp.h | ||||||
| header-y += xt_iprange.h | header-y += xt_iprange.h | ||||||
| header-y += xt_ipvs.h | header-y += xt_ipvs.h | ||||||
| header-y += xt_length.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 | 	in the IPv6 header, or the time-to-live field in the IPv4 | ||||||
| 	header of the packet. | 	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 | config NETFILTER_XT_MATCH_IPRANGE | ||||||
| 	tristate '"iprange" address range match support' | 	tristate '"iprange" address range match support' | ||||||
| 	depends on NETFILTER_ADVANCED | 	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_HASHLIMIT) += xt_hashlimit.o | ||||||
| obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o | obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o | ||||||
| obj-$(CONFIG_NETFILTER_XT_MATCH_HL) += xt_hl.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_IPRANGE) += xt_iprange.o | ||||||
| obj-$(CONFIG_NETFILTER_XT_MATCH_IPVS) += xt_ipvs.o | obj-$(CONFIG_NETFILTER_XT_MATCH_IPVS) += xt_ipvs.o | ||||||
| obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.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