xt_CONNMARK.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /* This kernel module is used to modify the connection mark values, or
  2. * to optionally restore the skb nfmark from the connection mark
  3. *
  4. * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
  5. * by Henrik Nordstrom <hno@marasystems.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. */
  21. #include <linux/module.h>
  22. #include <linux/skbuff.h>
  23. #include <linux/ip.h>
  24. #include <net/checksum.h>
  25. MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
  26. MODULE_DESCRIPTION("IP tables CONNMARK matching module");
  27. MODULE_LICENSE("GPL");
  28. MODULE_ALIAS("ipt_CONNMARK");
  29. #include <linux/netfilter/x_tables.h>
  30. #include <linux/netfilter/xt_CONNMARK.h>
  31. #include <net/netfilter/nf_conntrack_compat.h>
  32. #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
  33. #include <net/netfilter/nf_conntrack_ecache.h>
  34. #endif
  35. static unsigned int
  36. target(struct sk_buff **pskb,
  37. const struct net_device *in,
  38. const struct net_device *out,
  39. unsigned int hooknum,
  40. const struct xt_target *target,
  41. const void *targinfo)
  42. {
  43. const struct xt_connmark_target_info *markinfo = targinfo;
  44. u_int32_t diff;
  45. u_int32_t mark;
  46. u_int32_t newmark;
  47. u_int32_t ctinfo;
  48. u_int32_t *ctmark = nf_ct_get_mark(*pskb, &ctinfo);
  49. if (ctmark) {
  50. switch(markinfo->mode) {
  51. case XT_CONNMARK_SET:
  52. newmark = (*ctmark & ~markinfo->mask) | markinfo->mark;
  53. if (newmark != *ctmark) {
  54. *ctmark = newmark;
  55. #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
  56. ip_conntrack_event_cache(IPCT_MARK, *pskb);
  57. #else
  58. nf_conntrack_event_cache(IPCT_MARK, *pskb);
  59. #endif
  60. }
  61. break;
  62. case XT_CONNMARK_SAVE:
  63. newmark = (*ctmark & ~markinfo->mask) |
  64. ((*pskb)->mark & markinfo->mask);
  65. if (*ctmark != newmark) {
  66. *ctmark = newmark;
  67. #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
  68. ip_conntrack_event_cache(IPCT_MARK, *pskb);
  69. #else
  70. nf_conntrack_event_cache(IPCT_MARK, *pskb);
  71. #endif
  72. }
  73. break;
  74. case XT_CONNMARK_RESTORE:
  75. mark = (*pskb)->mark;
  76. diff = (*ctmark ^ mark) & markinfo->mask;
  77. (*pskb)->mark = mark ^ diff;
  78. break;
  79. }
  80. }
  81. return XT_CONTINUE;
  82. }
  83. static int
  84. checkentry(const char *tablename,
  85. const void *entry,
  86. const struct xt_target *target,
  87. void *targinfo,
  88. unsigned int hook_mask)
  89. {
  90. struct xt_connmark_target_info *matchinfo = targinfo;
  91. if (nf_ct_l3proto_try_module_get(target->family) < 0) {
  92. printk(KERN_WARNING "can't load conntrack support for "
  93. "proto=%d\n", target->family);
  94. return 0;
  95. }
  96. if (matchinfo->mode == XT_CONNMARK_RESTORE) {
  97. if (strcmp(tablename, "mangle") != 0) {
  98. printk(KERN_WARNING "CONNMARK: restore can only be "
  99. "called from \"mangle\" table, not \"%s\"\n",
  100. tablename);
  101. return 0;
  102. }
  103. }
  104. if (matchinfo->mark > 0xffffffff || matchinfo->mask > 0xffffffff) {
  105. printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n");
  106. return 0;
  107. }
  108. return 1;
  109. }
  110. static void
  111. destroy(const struct xt_target *target, void *targinfo)
  112. {
  113. nf_ct_l3proto_module_put(target->family);
  114. }
  115. #ifdef CONFIG_COMPAT
  116. struct compat_xt_connmark_target_info {
  117. compat_ulong_t mark, mask;
  118. u_int8_t mode;
  119. u_int8_t __pad1;
  120. u_int16_t __pad2;
  121. };
  122. static void compat_from_user(void *dst, void *src)
  123. {
  124. struct compat_xt_connmark_target_info *cm = src;
  125. struct xt_connmark_target_info m = {
  126. .mark = cm->mark,
  127. .mask = cm->mask,
  128. .mode = cm->mode,
  129. };
  130. memcpy(dst, &m, sizeof(m));
  131. }
  132. static int compat_to_user(void __user *dst, void *src)
  133. {
  134. struct xt_connmark_target_info *m = src;
  135. struct compat_xt_connmark_target_info cm = {
  136. .mark = m->mark,
  137. .mask = m->mask,
  138. .mode = m->mode,
  139. };
  140. return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
  141. }
  142. #endif /* CONFIG_COMPAT */
  143. static struct xt_target xt_connmark_target[] = {
  144. {
  145. .name = "CONNMARK",
  146. .family = AF_INET,
  147. .checkentry = checkentry,
  148. .destroy = destroy,
  149. .target = target,
  150. .targetsize = sizeof(struct xt_connmark_target_info),
  151. #ifdef CONFIG_COMPAT
  152. .compatsize = sizeof(struct compat_xt_connmark_target_info),
  153. .compat_from_user = compat_from_user,
  154. .compat_to_user = compat_to_user,
  155. #endif
  156. .me = THIS_MODULE
  157. },
  158. {
  159. .name = "CONNMARK",
  160. .family = AF_INET6,
  161. .checkentry = checkentry,
  162. .destroy = destroy,
  163. .target = target,
  164. .targetsize = sizeof(struct xt_connmark_target_info),
  165. .me = THIS_MODULE
  166. },
  167. };
  168. static int __init xt_connmark_init(void)
  169. {
  170. return xt_register_targets(xt_connmark_target,
  171. ARRAY_SIZE(xt_connmark_target));
  172. }
  173. static void __exit xt_connmark_fini(void)
  174. {
  175. xt_unregister_targets(xt_connmark_target,
  176. ARRAY_SIZE(xt_connmark_target));
  177. }
  178. module_init(xt_connmark_init);
  179. module_exit(xt_connmark_fini);