diff options
| author | fan.du <fan.du@windriver.com> | 2013-12-17 22:27:02 -0500 |
|---|---|---|
| committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-12-24 06:37:58 -0500 |
| commit | 6a649f339802f104549e1fb211e381036661e244 (patch) | |
| tree | 673fd543f147e890e2cd34deceaa70606ff83054 | |
| parent | 08c0cad69f32ad1e881fa3fb7f5e0a25db5b07ce (diff) | |
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>
| -rw-r--r-- | include/uapi/linux/netfilter/Kbuild | 1 | ||||
| -rw-r--r-- | include/uapi/linux/netfilter/xt_ipcomp.h | 16 | ||||
| -rw-r--r-- | net/netfilter/Kconfig | 9 | ||||
| -rw-r--r-- | net/netfilter/Makefile | 1 | ||||
| -rw-r--r-- | net/netfilter/xt_ipcomp.c | 111 |
5 files changed, 138 insertions, 0 deletions
diff --git a/include/uapi/linux/netfilter/Kbuild b/include/uapi/linux/netfilter/Kbuild index 17c3af2c4bb9..91be8ce623f0 100644 --- a/include/uapi/linux/netfilter/Kbuild +++ b/include/uapi/linux/netfilter/Kbuild | |||
| @@ -54,6 +54,7 @@ header-y += xt_ecn.h | |||
| 54 | header-y += xt_esp.h | 54 | header-y += xt_esp.h |
| 55 | header-y += xt_hashlimit.h | 55 | header-y += xt_hashlimit.h |
| 56 | header-y += xt_helper.h | 56 | header-y += xt_helper.h |
| 57 | header-y += xt_ipcomp.h | ||
| 57 | header-y += xt_iprange.h | 58 | header-y += xt_iprange.h |
| 58 | header-y += xt_ipvs.h | 59 | header-y += xt_ipvs.h |
| 59 | header-y += xt_length.h | 60 | header-y += xt_length.h |
diff --git a/include/uapi/linux/netfilter/xt_ipcomp.h b/include/uapi/linux/netfilter/xt_ipcomp.h new file mode 100644 index 000000000000..45c7e40eb8e1 --- /dev/null +++ b/include/uapi/linux/netfilter/xt_ipcomp.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | #ifndef _XT_IPCOMP_H | ||
| 2 | #define _XT_IPCOMP_H | ||
| 3 | |||
| 4 | #include <linux/types.h> | ||
| 5 | |||
| 6 | struct xt_ipcomp { | ||
| 7 | __u32 spis[2]; /* Security Parameter Index */ | ||
| 8 | __u8 invflags; /* Inverse flags */ | ||
| 9 | __u8 hdrres; /* Test of the Reserved Filed */ | ||
| 10 | }; | ||
| 11 | |||
| 12 | /* Values for "invflags" field in struct xt_ipcomp. */ | ||
| 13 | #define XT_IPCOMP_INV_SPI 0x01 /* Invert the sense of spi. */ | ||
| 14 | #define XT_IPCOMP_INV_MASK 0x01 /* All possible flags. */ | ||
| 15 | |||
| 16 | #endif /*_XT_IPCOMP_H*/ | ||
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index c3398cd99b94..6d8e48b376fc 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
| @@ -1035,6 +1035,15 @@ config NETFILTER_XT_MATCH_HL | |||
| 1035 | in the IPv6 header, or the time-to-live field in the IPv4 | 1035 | in the IPv6 header, or the time-to-live field in the IPv4 |
| 1036 | header of the packet. | 1036 | header of the packet. |
| 1037 | 1037 | ||
| 1038 | config NETFILTER_XT_MATCH_IPCOMP | ||
| 1039 | tristate '"ipcomp" match support' | ||
| 1040 | depends on NETFILTER_ADVANCED | ||
| 1041 | help | ||
| 1042 | This match extension allows you to match a range of CPIs(16 bits) | ||
| 1043 | inside IPComp header of IPSec packets. | ||
| 1044 | |||
| 1045 | To compile it as a module, choose M here. If unsure, say N. | ||
| 1046 | |||
| 1038 | config NETFILTER_XT_MATCH_IPRANGE | 1047 | config NETFILTER_XT_MATCH_IPRANGE |
| 1039 | tristate '"iprange" address range match support' | 1048 | tristate '"iprange" address range match support' |
| 1040 | depends on NETFILTER_ADVANCED | 1049 | depends on NETFILTER_ADVANCED |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 394483b2c193..398cd709aa09 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
| @@ -133,6 +133,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o | |||
| 133 | obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o | 133 | obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o |
| 134 | obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o | 134 | obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o |
| 135 | obj-$(CONFIG_NETFILTER_XT_MATCH_HL) += xt_hl.o | 135 | obj-$(CONFIG_NETFILTER_XT_MATCH_HL) += xt_hl.o |
| 136 | obj-$(CONFIG_NETFILTER_XT_MATCH_IPCOMP) += xt_ipcomp.o | ||
| 136 | obj-$(CONFIG_NETFILTER_XT_MATCH_IPRANGE) += xt_iprange.o | 137 | obj-$(CONFIG_NETFILTER_XT_MATCH_IPRANGE) += xt_iprange.o |
| 137 | obj-$(CONFIG_NETFILTER_XT_MATCH_IPVS) += xt_ipvs.o | 138 | obj-$(CONFIG_NETFILTER_XT_MATCH_IPVS) += xt_ipvs.o |
| 138 | obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o | 139 | obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o |
diff --git a/net/netfilter/xt_ipcomp.c b/net/netfilter/xt_ipcomp.c new file mode 100644 index 000000000000..a4c7561698c5 --- /dev/null +++ b/net/netfilter/xt_ipcomp.c | |||
| @@ -0,0 +1,111 @@ | |||
| 1 | /* Kernel module to match IPComp parameters for IPv4 and IPv6 | ||
| 2 | * | ||
| 3 | * Copyright (C) 2013 WindRiver | ||
| 4 | * | ||
| 5 | * Author: | ||
| 6 | * Fan Du <fan.du@windriver.com> | ||
| 7 | * | ||
| 8 | * Based on: | ||
| 9 | * net/netfilter/xt_esp.c | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or | ||
| 12 | * modify it under the terms of the GNU General Public License | ||
| 13 | * as published by the Free Software Foundation; either version | ||
| 14 | * 2 of the License, or (at your option) any later version. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 18 | #include <linux/in.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/skbuff.h> | ||
| 21 | #include <linux/ip.h> | ||
| 22 | |||
| 23 | #include <linux/netfilter/xt_ipcomp.h> | ||
| 24 | #include <linux/netfilter/x_tables.h> | ||
| 25 | |||
| 26 | MODULE_LICENSE("GPL"); | ||
| 27 | MODULE_AUTHOR("Fan Du <fan.du@windriver.com>"); | ||
| 28 | MODULE_DESCRIPTION("Xtables: IPv4/6 IPsec-IPComp SPI match"); | ||
| 29 | |||
| 30 | /* Returns 1 if the spi is matched by the range, 0 otherwise */ | ||
| 31 | static inline bool | ||
| 32 | spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert) | ||
| 33 | { | ||
| 34 | bool r; | ||
| 35 | pr_debug("spi_match:%c 0x%x <= 0x%x <= 0x%x\n", | ||
| 36 | invert ? '!' : ' ', min, spi, max); | ||
| 37 | r = (spi >= min && spi <= max) ^ invert; | ||
| 38 | pr_debug(" result %s\n", r ? "PASS" : "FAILED"); | ||
| 39 | return r; | ||
| 40 | } | ||
| 41 | |||
| 42 | static bool comp_mt(const struct sk_buff *skb, struct xt_action_param *par) | ||
| 43 | { | ||
| 44 | struct ip_comp_hdr _comphdr; | ||
| 45 | const struct ip_comp_hdr *chdr; | ||
| 46 | const struct xt_ipcomp *compinfo = par->matchinfo; | ||
| 47 | |||
| 48 | /* Must not be a fragment. */ | ||
| 49 | if (par->fragoff != 0) | ||
| 50 | return false; | ||
| 51 | |||
| 52 | chdr = skb_header_pointer(skb, par->thoff, sizeof(_comphdr), &_comphdr); | ||
| 53 | if (chdr == NULL) { | ||
| 54 | /* We've been asked to examine this packet, and we | ||
| 55 | * can't. Hence, no choice but to drop. | ||
| 56 | */ | ||
| 57 | pr_debug("Dropping evil IPComp tinygram.\n"); | ||
| 58 | par->hotdrop = true; | ||
| 59 | return 0; | ||
| 60 | } | ||
| 61 | |||
| 62 | return spi_match(compinfo->spis[0], compinfo->spis[1], | ||
| 63 | ntohl(chdr->cpi << 16), | ||
| 64 | !!(compinfo->invflags & XT_IPCOMP_INV_SPI)); | ||
| 65 | } | ||
| 66 | |||
| 67 | static int comp_mt_check(const struct xt_mtchk_param *par) | ||
| 68 | { | ||
| 69 | const struct xt_ipcomp *compinfo = par->matchinfo; | ||
| 70 | |||
| 71 | /* Must specify no unknown invflags */ | ||
| 72 | if (compinfo->invflags & ~XT_IPCOMP_INV_MASK) { | ||
| 73 | pr_err("unknown flags %X\n", compinfo->invflags); | ||
| 74 | return -EINVAL; | ||
| 75 | } | ||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 79 | static struct xt_match comp_mt_reg[] __read_mostly = { | ||
| 80 | { | ||
| 81 | .name = "ipcomp", | ||
| 82 | .family = NFPROTO_IPV4, | ||
| 83 | .match = comp_mt, | ||
| 84 | .matchsize = sizeof(struct xt_ipcomp), | ||
| 85 | .proto = IPPROTO_COMP, | ||
| 86 | .checkentry = comp_mt_check, | ||
| 87 | .me = THIS_MODULE, | ||
| 88 | }, | ||
| 89 | { | ||
| 90 | .name = "ipcomp", | ||
| 91 | .family = NFPROTO_IPV6, | ||
| 92 | .match = comp_mt, | ||
| 93 | .matchsize = sizeof(struct xt_ipcomp), | ||
| 94 | .proto = IPPROTO_COMP, | ||
| 95 | .checkentry = comp_mt_check, | ||
| 96 | .me = THIS_MODULE, | ||
| 97 | }, | ||
| 98 | }; | ||
| 99 | |||
| 100 | static int __init comp_mt_init(void) | ||
| 101 | { | ||
| 102 | return xt_register_matches(comp_mt_reg, ARRAY_SIZE(comp_mt_reg)); | ||
| 103 | } | ||
| 104 | |||
| 105 | static void __exit comp_mt_exit(void) | ||
| 106 | { | ||
| 107 | xt_unregister_matches(comp_mt_reg, ARRAY_SIZE(comp_mt_reg)); | ||
| 108 | } | ||
| 109 | |||
| 110 | module_init(comp_mt_init); | ||
| 111 | module_exit(comp_mt_exit); | ||
