xt_ipcomp.c (2714B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* Kernel module to match IPComp parameters for IPv4 and IPv6 3 * 4 * Copyright (C) 2013 WindRiver 5 * 6 * Author: 7 * Fan Du <fan.du@windriver.com> 8 * 9 * Based on: 10 * net/netfilter/xt_esp.c 11 */ 12 13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 14#include <linux/in.h> 15#include <linux/module.h> 16#include <linux/skbuff.h> 17#include <linux/ip.h> 18 19#include <linux/netfilter/xt_ipcomp.h> 20#include <linux/netfilter/x_tables.h> 21 22MODULE_LICENSE("GPL"); 23MODULE_AUTHOR("Fan Du <fan.du@windriver.com>"); 24MODULE_DESCRIPTION("Xtables: IPv4/6 IPsec-IPComp SPI match"); 25MODULE_ALIAS("ipt_ipcomp"); 26MODULE_ALIAS("ip6t_ipcomp"); 27 28/* Returns 1 if the spi is matched by the range, 0 otherwise */ 29static inline bool 30spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert) 31{ 32 bool r; 33 pr_debug("spi_match:%c 0x%x <= 0x%x <= 0x%x\n", 34 invert ? '!' : ' ', min, spi, max); 35 r = (spi >= min && spi <= max) ^ invert; 36 pr_debug(" result %s\n", r ? "PASS" : "FAILED"); 37 return r; 38} 39 40static bool comp_mt(const struct sk_buff *skb, struct xt_action_param *par) 41{ 42 struct ip_comp_hdr _comphdr; 43 const struct ip_comp_hdr *chdr; 44 const struct xt_ipcomp *compinfo = par->matchinfo; 45 46 /* Must not be a fragment. */ 47 if (par->fragoff != 0) 48 return false; 49 50 chdr = skb_header_pointer(skb, par->thoff, sizeof(_comphdr), &_comphdr); 51 if (chdr == NULL) { 52 /* We've been asked to examine this packet, and we 53 * can't. Hence, no choice but to drop. 54 */ 55 pr_debug("Dropping evil IPComp tinygram.\n"); 56 par->hotdrop = true; 57 return false; 58 } 59 60 return spi_match(compinfo->spis[0], compinfo->spis[1], 61 ntohs(chdr->cpi), 62 !!(compinfo->invflags & XT_IPCOMP_INV_SPI)); 63} 64 65static int comp_mt_check(const struct xt_mtchk_param *par) 66{ 67 const struct xt_ipcomp *compinfo = par->matchinfo; 68 69 /* Must specify no unknown invflags */ 70 if (compinfo->invflags & ~XT_IPCOMP_INV_MASK) { 71 pr_info_ratelimited("unknown flags %X\n", compinfo->invflags); 72 return -EINVAL; 73 } 74 return 0; 75} 76 77static struct xt_match comp_mt_reg[] __read_mostly = { 78 { 79 .name = "ipcomp", 80 .family = NFPROTO_IPV4, 81 .match = comp_mt, 82 .matchsize = sizeof(struct xt_ipcomp), 83 .proto = IPPROTO_COMP, 84 .checkentry = comp_mt_check, 85 .me = THIS_MODULE, 86 }, 87 { 88 .name = "ipcomp", 89 .family = NFPROTO_IPV6, 90 .match = comp_mt, 91 .matchsize = sizeof(struct xt_ipcomp), 92 .proto = IPPROTO_COMP, 93 .checkentry = comp_mt_check, 94 .me = THIS_MODULE, 95 }, 96}; 97 98static int __init comp_mt_init(void) 99{ 100 return xt_register_matches(comp_mt_reg, ARRAY_SIZE(comp_mt_reg)); 101} 102 103static void __exit comp_mt_exit(void) 104{ 105 xt_unregister_matches(comp_mt_reg, ARRAY_SIZE(comp_mt_reg)); 106} 107 108module_init(comp_mt_init); 109module_exit(comp_mt_exit);