xt_ipcomp.c 2.7 KB

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