xt_CT.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2010 Patrick McHardy <kaber@trash.net>
  4. */
  5. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  6. #include <linux/module.h>
  7. #include <linux/gfp.h>
  8. #include <linux/skbuff.h>
  9. #include <linux/netfilter_ipv4/ip_tables.h>
  10. #include <linux/netfilter_ipv6/ip6_tables.h>
  11. #include <linux/netfilter/x_tables.h>
  12. #include <linux/netfilter/xt_CT.h>
  13. #include <net/netfilter/nf_conntrack.h>
  14. #include <net/netfilter/nf_conntrack_l4proto.h>
  15. #include <net/netfilter/nf_conntrack_helper.h>
  16. #include <net/netfilter/nf_conntrack_ecache.h>
  17. #include <net/netfilter/nf_conntrack_timeout.h>
  18. #include <net/netfilter/nf_conntrack_zones.h>
  19. static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct)
  20. {
  21. /* Previously seen (loopback)? Ignore. */
  22. if (skb->_nfct != 0)
  23. return XT_CONTINUE;
  24. if (ct) {
  25. atomic_inc(&ct->ct_general.use);
  26. nf_ct_set(skb, ct, IP_CT_NEW);
  27. } else {
  28. nf_ct_set(skb, ct, IP_CT_UNTRACKED);
  29. }
  30. return XT_CONTINUE;
  31. }
  32. static unsigned int xt_ct_target_v0(struct sk_buff *skb,
  33. const struct xt_action_param *par)
  34. {
  35. const struct xt_ct_target_info *info = par->targinfo;
  36. struct nf_conn *ct = info->ct;
  37. return xt_ct_target(skb, ct);
  38. }
  39. static unsigned int xt_ct_target_v1(struct sk_buff *skb,
  40. const struct xt_action_param *par)
  41. {
  42. const struct xt_ct_target_info_v1 *info = par->targinfo;
  43. struct nf_conn *ct = info->ct;
  44. return xt_ct_target(skb, ct);
  45. }
  46. static u8 xt_ct_find_proto(const struct xt_tgchk_param *par)
  47. {
  48. if (par->family == NFPROTO_IPV4) {
  49. const struct ipt_entry *e = par->entryinfo;
  50. if (e->ip.invflags & IPT_INV_PROTO)
  51. return 0;
  52. return e->ip.proto;
  53. } else if (par->family == NFPROTO_IPV6) {
  54. const struct ip6t_entry *e = par->entryinfo;
  55. if (e->ipv6.invflags & IP6T_INV_PROTO)
  56. return 0;
  57. return e->ipv6.proto;
  58. } else
  59. return 0;
  60. }
  61. static int
  62. xt_ct_set_helper(struct nf_conn *ct, const char *helper_name,
  63. const struct xt_tgchk_param *par)
  64. {
  65. struct nf_conntrack_helper *helper;
  66. struct nf_conn_help *help;
  67. u8 proto;
  68. proto = xt_ct_find_proto(par);
  69. if (!proto) {
  70. pr_info_ratelimited("You must specify a L4 protocol and not use inversions on it\n");
  71. return -ENOENT;
  72. }
  73. helper = nf_conntrack_helper_try_module_get(helper_name, par->family,
  74. proto);
  75. if (helper == NULL) {
  76. pr_info_ratelimited("No such helper \"%s\"\n", helper_name);
  77. return -ENOENT;
  78. }
  79. help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
  80. if (help == NULL) {
  81. nf_conntrack_helper_put(helper);
  82. return -ENOMEM;
  83. }
  84. help->helper = helper;
  85. return 0;
  86. }
  87. static int
  88. xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
  89. const char *timeout_name)
  90. {
  91. #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
  92. const struct nf_conntrack_l4proto *l4proto;
  93. u8 proto;
  94. proto = xt_ct_find_proto(par);
  95. if (!proto) {
  96. pr_info_ratelimited("You must specify a L4 protocol and not "
  97. "use inversions on it");
  98. return -EINVAL;
  99. }
  100. l4proto = nf_ct_l4proto_find(proto);
  101. return nf_ct_set_timeout(par->net, ct, par->family, l4proto->l4proto,
  102. timeout_name);
  103. #else
  104. return -EOPNOTSUPP;
  105. #endif
  106. }
  107. static u16 xt_ct_flags_to_dir(const struct xt_ct_target_info_v1 *info)
  108. {
  109. switch (info->flags & (XT_CT_ZONE_DIR_ORIG |
  110. XT_CT_ZONE_DIR_REPL)) {
  111. case XT_CT_ZONE_DIR_ORIG:
  112. return NF_CT_ZONE_DIR_ORIG;
  113. case XT_CT_ZONE_DIR_REPL:
  114. return NF_CT_ZONE_DIR_REPL;
  115. default:
  116. return NF_CT_DEFAULT_ZONE_DIR;
  117. }
  118. }
  119. static int xt_ct_tg_check(const struct xt_tgchk_param *par,
  120. struct xt_ct_target_info_v1 *info)
  121. {
  122. struct nf_conntrack_zone zone;
  123. struct nf_conn_help *help;
  124. struct nf_conn *ct;
  125. int ret = -EOPNOTSUPP;
  126. if (info->flags & XT_CT_NOTRACK) {
  127. ct = NULL;
  128. goto out;
  129. }
  130. #ifndef CONFIG_NF_CONNTRACK_ZONES
  131. if (info->zone || info->flags & (XT_CT_ZONE_DIR_ORIG |
  132. XT_CT_ZONE_DIR_REPL |
  133. XT_CT_ZONE_MARK))
  134. goto err1;
  135. #endif
  136. ret = nf_ct_netns_get(par->net, par->family);
  137. if (ret < 0)
  138. goto err1;
  139. memset(&zone, 0, sizeof(zone));
  140. zone.id = info->zone;
  141. zone.dir = xt_ct_flags_to_dir(info);
  142. if (info->flags & XT_CT_ZONE_MARK)
  143. zone.flags |= NF_CT_FLAG_MARK;
  144. ct = nf_ct_tmpl_alloc(par->net, &zone, GFP_KERNEL);
  145. if (!ct) {
  146. ret = -ENOMEM;
  147. goto err2;
  148. }
  149. ret = 0;
  150. if ((info->ct_events || info->exp_events) &&
  151. !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events,
  152. GFP_KERNEL)) {
  153. ret = -EINVAL;
  154. goto err3;
  155. }
  156. if (info->helper[0]) {
  157. if (strnlen(info->helper, sizeof(info->helper)) == sizeof(info->helper)) {
  158. ret = -ENAMETOOLONG;
  159. goto err3;
  160. }
  161. ret = xt_ct_set_helper(ct, info->helper, par);
  162. if (ret < 0)
  163. goto err3;
  164. }
  165. if (info->timeout[0]) {
  166. if (strnlen(info->timeout, sizeof(info->timeout)) == sizeof(info->timeout)) {
  167. ret = -ENAMETOOLONG;
  168. goto err4;
  169. }
  170. ret = xt_ct_set_timeout(ct, par, info->timeout);
  171. if (ret < 0)
  172. goto err4;
  173. }
  174. __set_bit(IPS_CONFIRMED_BIT, &ct->status);
  175. nf_conntrack_get(&ct->ct_general);
  176. out:
  177. info->ct = ct;
  178. return 0;
  179. err4:
  180. help = nfct_help(ct);
  181. if (help)
  182. nf_conntrack_helper_put(help->helper);
  183. err3:
  184. nf_ct_tmpl_free(ct);
  185. err2:
  186. nf_ct_netns_put(par->net, par->family);
  187. err1:
  188. return ret;
  189. }
  190. static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par)
  191. {
  192. struct xt_ct_target_info *info = par->targinfo;
  193. struct xt_ct_target_info_v1 info_v1 = {
  194. .flags = info->flags,
  195. .zone = info->zone,
  196. .ct_events = info->ct_events,
  197. .exp_events = info->exp_events,
  198. };
  199. int ret;
  200. if (info->flags & ~XT_CT_NOTRACK)
  201. return -EINVAL;
  202. memcpy(info_v1.helper, info->helper, sizeof(info->helper));
  203. ret = xt_ct_tg_check(par, &info_v1);
  204. if (ret < 0)
  205. return ret;
  206. info->ct = info_v1.ct;
  207. return ret;
  208. }
  209. static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
  210. {
  211. struct xt_ct_target_info_v1 *info = par->targinfo;
  212. if (info->flags & ~XT_CT_NOTRACK)
  213. return -EINVAL;
  214. return xt_ct_tg_check(par, par->targinfo);
  215. }
  216. static int xt_ct_tg_check_v2(const struct xt_tgchk_param *par)
  217. {
  218. struct xt_ct_target_info_v1 *info = par->targinfo;
  219. if (info->flags & ~XT_CT_MASK)
  220. return -EINVAL;
  221. return xt_ct_tg_check(par, par->targinfo);
  222. }
  223. static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par,
  224. struct xt_ct_target_info_v1 *info)
  225. {
  226. struct nf_conn *ct = info->ct;
  227. struct nf_conn_help *help;
  228. if (ct) {
  229. help = nfct_help(ct);
  230. if (help)
  231. nf_conntrack_helper_put(help->helper);
  232. nf_ct_netns_put(par->net, par->family);
  233. nf_ct_destroy_timeout(ct);
  234. nf_ct_put(info->ct);
  235. }
  236. }
  237. static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par)
  238. {
  239. struct xt_ct_target_info *info = par->targinfo;
  240. struct xt_ct_target_info_v1 info_v1 = {
  241. .flags = info->flags,
  242. .zone = info->zone,
  243. .ct_events = info->ct_events,
  244. .exp_events = info->exp_events,
  245. .ct = info->ct,
  246. };
  247. memcpy(info_v1.helper, info->helper, sizeof(info->helper));
  248. xt_ct_tg_destroy(par, &info_v1);
  249. }
  250. static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par)
  251. {
  252. xt_ct_tg_destroy(par, par->targinfo);
  253. }
  254. static struct xt_target xt_ct_tg_reg[] __read_mostly = {
  255. {
  256. .name = "CT",
  257. .family = NFPROTO_UNSPEC,
  258. .targetsize = sizeof(struct xt_ct_target_info),
  259. .usersize = offsetof(struct xt_ct_target_info, ct),
  260. .checkentry = xt_ct_tg_check_v0,
  261. .destroy = xt_ct_tg_destroy_v0,
  262. .target = xt_ct_target_v0,
  263. .table = "raw",
  264. .me = THIS_MODULE,
  265. },
  266. {
  267. .name = "CT",
  268. .family = NFPROTO_UNSPEC,
  269. .revision = 1,
  270. .targetsize = sizeof(struct xt_ct_target_info_v1),
  271. .usersize = offsetof(struct xt_ct_target_info, ct),
  272. .checkentry = xt_ct_tg_check_v1,
  273. .destroy = xt_ct_tg_destroy_v1,
  274. .target = xt_ct_target_v1,
  275. .table = "raw",
  276. .me = THIS_MODULE,
  277. },
  278. {
  279. .name = "CT",
  280. .family = NFPROTO_UNSPEC,
  281. .revision = 2,
  282. .targetsize = sizeof(struct xt_ct_target_info_v1),
  283. .usersize = offsetof(struct xt_ct_target_info, ct),
  284. .checkentry = xt_ct_tg_check_v2,
  285. .destroy = xt_ct_tg_destroy_v1,
  286. .target = xt_ct_target_v1,
  287. .table = "raw",
  288. .me = THIS_MODULE,
  289. },
  290. };
  291. static unsigned int
  292. notrack_tg(struct sk_buff *skb, const struct xt_action_param *par)
  293. {
  294. /* Previously seen (loopback)? Ignore. */
  295. if (skb->_nfct != 0)
  296. return XT_CONTINUE;
  297. nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
  298. return XT_CONTINUE;
  299. }
  300. static int notrack_chk(const struct xt_tgchk_param *par)
  301. {
  302. if (!par->net->xt.notrack_deprecated_warning) {
  303. pr_info("netfilter: NOTRACK target is deprecated, "
  304. "use CT instead or upgrade iptables\n");
  305. par->net->xt.notrack_deprecated_warning = true;
  306. }
  307. return 0;
  308. }
  309. static struct xt_target notrack_tg_reg __read_mostly = {
  310. .name = "NOTRACK",
  311. .revision = 0,
  312. .family = NFPROTO_UNSPEC,
  313. .checkentry = notrack_chk,
  314. .target = notrack_tg,
  315. .table = "raw",
  316. .me = THIS_MODULE,
  317. };
  318. static int __init xt_ct_tg_init(void)
  319. {
  320. int ret;
  321. ret = xt_register_target(&notrack_tg_reg);
  322. if (ret < 0)
  323. return ret;
  324. ret = xt_register_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
  325. if (ret < 0) {
  326. xt_unregister_target(&notrack_tg_reg);
  327. return ret;
  328. }
  329. return 0;
  330. }
  331. static void __exit xt_ct_tg_exit(void)
  332. {
  333. xt_unregister_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
  334. xt_unregister_target(&notrack_tg_reg);
  335. }
  336. module_init(xt_ct_tg_init);
  337. module_exit(xt_ct_tg_exit);
  338. MODULE_LICENSE("GPL");
  339. MODULE_DESCRIPTION("Xtables: connection tracking target");
  340. MODULE_ALIAS("ipt_CT");
  341. MODULE_ALIAS("ip6t_CT");
  342. MODULE_ALIAS("ipt_NOTRACK");
  343. MODULE_ALIAS("ip6t_NOTRACK");