0001
0002
0003
0004
0005
0006 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0007 #include <linux/module.h>
0008 #include <linux/skbuff.h>
0009 #include <linux/in.h>
0010 #include <linux/ip.h>
0011
0012 #include <linux/netfilter/xt_esp.h>
0013 #include <linux/netfilter/x_tables.h>
0014
0015 #include <linux/netfilter_ipv4/ip_tables.h>
0016 #include <linux/netfilter_ipv6/ip6_tables.h>
0017
0018 MODULE_LICENSE("GPL");
0019 MODULE_AUTHOR("Yon Uriarte <yon@astaro.de>");
0020 MODULE_DESCRIPTION("Xtables: IPsec-ESP packet match");
0021 MODULE_ALIAS("ipt_esp");
0022 MODULE_ALIAS("ip6t_esp");
0023
0024
0025 static inline bool
0026 spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert)
0027 {
0028 bool r;
0029 pr_debug("spi_match:%c 0x%x <= 0x%x <= 0x%x\n",
0030 invert ? '!' : ' ', min, spi, max);
0031 r = (spi >= min && spi <= max) ^ invert;
0032 pr_debug(" result %s\n", r ? "PASS" : "FAILED");
0033 return r;
0034 }
0035
0036 static bool esp_mt(const struct sk_buff *skb, struct xt_action_param *par)
0037 {
0038 const struct ip_esp_hdr *eh;
0039 struct ip_esp_hdr _esp;
0040 const struct xt_esp *espinfo = par->matchinfo;
0041
0042
0043 if (par->fragoff != 0)
0044 return false;
0045
0046 eh = skb_header_pointer(skb, par->thoff, sizeof(_esp), &_esp);
0047 if (eh == NULL) {
0048
0049
0050
0051 pr_debug("Dropping evil ESP tinygram.\n");
0052 par->hotdrop = true;
0053 return false;
0054 }
0055
0056 return spi_match(espinfo->spis[0], espinfo->spis[1], ntohl(eh->spi),
0057 !!(espinfo->invflags & XT_ESP_INV_SPI));
0058 }
0059
0060 static int esp_mt_check(const struct xt_mtchk_param *par)
0061 {
0062 const struct xt_esp *espinfo = par->matchinfo;
0063
0064 if (espinfo->invflags & ~XT_ESP_INV_MASK) {
0065 pr_debug("unknown flags %X\n", espinfo->invflags);
0066 return -EINVAL;
0067 }
0068
0069 return 0;
0070 }
0071
0072 static struct xt_match esp_mt_reg[] __read_mostly = {
0073 {
0074 .name = "esp",
0075 .family = NFPROTO_IPV4,
0076 .checkentry = esp_mt_check,
0077 .match = esp_mt,
0078 .matchsize = sizeof(struct xt_esp),
0079 .proto = IPPROTO_ESP,
0080 .me = THIS_MODULE,
0081 },
0082 {
0083 .name = "esp",
0084 .family = NFPROTO_IPV6,
0085 .checkentry = esp_mt_check,
0086 .match = esp_mt,
0087 .matchsize = sizeof(struct xt_esp),
0088 .proto = IPPROTO_ESP,
0089 .me = THIS_MODULE,
0090 },
0091 };
0092
0093 static int __init esp_mt_init(void)
0094 {
0095 return xt_register_matches(esp_mt_reg, ARRAY_SIZE(esp_mt_reg));
0096 }
0097
0098 static void __exit esp_mt_exit(void)
0099 {
0100 xt_unregister_matches(esp_mt_reg, ARRAY_SIZE(esp_mt_reg));
0101 }
0102
0103 module_init(esp_mt_init);
0104 module_exit(esp_mt_exit);