xt_connmark.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * xt_connmark - Netfilter module to operate on connection marks
  4. *
  5. * Copyright (C) 2002,2004 MARA Systems AB <https://www.marasystems.com>
  6. * by Henrik Nordstrom <hno@marasystems.com>
  7. * Copyright © CC Computer Consultants GmbH, 2007 - 2008
  8. * Jan Engelhardt <jengelh@medozas.de>
  9. */
  10. #include <linux/module.h>
  11. #include <linux/skbuff.h>
  12. #include <net/netfilter/nf_conntrack.h>
  13. #include <net/netfilter/nf_conntrack_ecache.h>
  14. #include <linux/netfilter/x_tables.h>
  15. #include <linux/netfilter/xt_connmark.h>
  16. MODULE_AUTHOR("Henrik Nordstrom <hno@marasystems.com>");
  17. MODULE_DESCRIPTION("Xtables: connection mark operations");
  18. MODULE_LICENSE("GPL");
  19. MODULE_ALIAS("ipt_CONNMARK");
  20. MODULE_ALIAS("ip6t_CONNMARK");
  21. MODULE_ALIAS("ipt_connmark");
  22. MODULE_ALIAS("ip6t_connmark");
  23. static unsigned int
  24. connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo2 *info)
  25. {
  26. enum ip_conntrack_info ctinfo;
  27. u_int32_t new_targetmark;
  28. struct nf_conn *ct;
  29. u_int32_t newmark;
  30. ct = nf_ct_get(skb, &ctinfo);
  31. if (ct == NULL)
  32. return XT_CONTINUE;
  33. switch (info->mode) {
  34. case XT_CONNMARK_SET:
  35. newmark = (ct->mark & ~info->ctmask) ^ info->ctmark;
  36. if (info->shift_dir == D_SHIFT_RIGHT)
  37. newmark >>= info->shift_bits;
  38. else
  39. newmark <<= info->shift_bits;
  40. if (ct->mark != newmark) {
  41. ct->mark = newmark;
  42. nf_conntrack_event_cache(IPCT_MARK, ct);
  43. }
  44. break;
  45. case XT_CONNMARK_SAVE:
  46. new_targetmark = (skb->mark & info->nfmask);
  47. if (info->shift_dir == D_SHIFT_RIGHT)
  48. new_targetmark >>= info->shift_bits;
  49. else
  50. new_targetmark <<= info->shift_bits;
  51. newmark = (ct->mark & ~info->ctmask) ^
  52. new_targetmark;
  53. if (ct->mark != newmark) {
  54. ct->mark = newmark;
  55. nf_conntrack_event_cache(IPCT_MARK, ct);
  56. }
  57. break;
  58. case XT_CONNMARK_RESTORE:
  59. new_targetmark = (ct->mark & info->ctmask);
  60. if (info->shift_dir == D_SHIFT_RIGHT)
  61. new_targetmark >>= info->shift_bits;
  62. else
  63. new_targetmark <<= info->shift_bits;
  64. newmark = (skb->mark & ~info->nfmask) ^
  65. new_targetmark;
  66. skb->mark = newmark;
  67. break;
  68. }
  69. return XT_CONTINUE;
  70. }
  71. static unsigned int
  72. connmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
  73. {
  74. const struct xt_connmark_tginfo1 *info = par->targinfo;
  75. const struct xt_connmark_tginfo2 info2 = {
  76. .ctmark = info->ctmark,
  77. .ctmask = info->ctmask,
  78. .nfmask = info->nfmask,
  79. .mode = info->mode,
  80. };
  81. return connmark_tg_shift(skb, &info2);
  82. }
  83. static unsigned int
  84. connmark_tg_v2(struct sk_buff *skb, const struct xt_action_param *par)
  85. {
  86. const struct xt_connmark_tginfo2 *info = par->targinfo;
  87. return connmark_tg_shift(skb, info);
  88. }
  89. static int connmark_tg_check(const struct xt_tgchk_param *par)
  90. {
  91. int ret;
  92. ret = nf_ct_netns_get(par->net, par->family);
  93. if (ret < 0)
  94. pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
  95. par->family);
  96. return ret;
  97. }
  98. static void connmark_tg_destroy(const struct xt_tgdtor_param *par)
  99. {
  100. nf_ct_netns_put(par->net, par->family);
  101. }
  102. static bool
  103. connmark_mt(const struct sk_buff *skb, struct xt_action_param *par)
  104. {
  105. const struct xt_connmark_mtinfo1 *info = par->matchinfo;
  106. enum ip_conntrack_info ctinfo;
  107. const struct nf_conn *ct;
  108. ct = nf_ct_get(skb, &ctinfo);
  109. if (ct == NULL)
  110. return false;
  111. return ((ct->mark & info->mask) == info->mark) ^ info->invert;
  112. }
  113. static int connmark_mt_check(const struct xt_mtchk_param *par)
  114. {
  115. int ret;
  116. ret = nf_ct_netns_get(par->net, par->family);
  117. if (ret < 0)
  118. pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
  119. par->family);
  120. return ret;
  121. }
  122. static void connmark_mt_destroy(const struct xt_mtdtor_param *par)
  123. {
  124. nf_ct_netns_put(par->net, par->family);
  125. }
  126. static struct xt_target connmark_tg_reg[] __read_mostly = {
  127. {
  128. .name = "CONNMARK",
  129. .revision = 1,
  130. .family = NFPROTO_UNSPEC,
  131. .checkentry = connmark_tg_check,
  132. .target = connmark_tg,
  133. .targetsize = sizeof(struct xt_connmark_tginfo1),
  134. .destroy = connmark_tg_destroy,
  135. .me = THIS_MODULE,
  136. },
  137. {
  138. .name = "CONNMARK",
  139. .revision = 2,
  140. .family = NFPROTO_UNSPEC,
  141. .checkentry = connmark_tg_check,
  142. .target = connmark_tg_v2,
  143. .targetsize = sizeof(struct xt_connmark_tginfo2),
  144. .destroy = connmark_tg_destroy,
  145. .me = THIS_MODULE,
  146. }
  147. };
  148. static struct xt_match connmark_mt_reg __read_mostly = {
  149. .name = "connmark",
  150. .revision = 1,
  151. .family = NFPROTO_UNSPEC,
  152. .checkentry = connmark_mt_check,
  153. .match = connmark_mt,
  154. .matchsize = sizeof(struct xt_connmark_mtinfo1),
  155. .destroy = connmark_mt_destroy,
  156. .me = THIS_MODULE,
  157. };
  158. static int __init connmark_mt_init(void)
  159. {
  160. int ret;
  161. ret = xt_register_targets(connmark_tg_reg,
  162. ARRAY_SIZE(connmark_tg_reg));
  163. if (ret < 0)
  164. return ret;
  165. ret = xt_register_match(&connmark_mt_reg);
  166. if (ret < 0) {
  167. xt_unregister_targets(connmark_tg_reg,
  168. ARRAY_SIZE(connmark_tg_reg));
  169. return ret;
  170. }
  171. return 0;
  172. }
  173. static void __exit connmark_mt_exit(void)
  174. {
  175. xt_unregister_match(&connmark_mt_reg);
  176. xt_unregister_targets(connmark_tg_reg, ARRAY_SIZE(connmark_tg_reg));
  177. }
  178. module_init(connmark_mt_init);
  179. module_exit(connmark_mt_exit);