xt_CT.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. /*
  2. * Copyright (c) 2010 Patrick McHardy <kaber@trash.net>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. */
  8. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  9. #include <linux/module.h>
  10. #include <linux/gfp.h>
  11. #include <linux/skbuff.h>
  12. #include <linux/netfilter_ipv4/ip_tables.h>
  13. #include <linux/netfilter_ipv6/ip6_tables.h>
  14. #include <linux/netfilter/x_tables.h>
  15. #include <linux/netfilter/xt_CT.h>
  16. #include <net/netfilter/nf_conntrack.h>
  17. #include <net/netfilter/nf_conntrack_l4proto.h>
  18. #include <net/netfilter/nf_conntrack_helper.h>
  19. #include <net/netfilter/nf_conntrack_ecache.h>
  20. #include <net/netfilter/nf_conntrack_timeout.h>
  21. #include <net/netfilter/nf_conntrack_zones.h>
  22. static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct)
  23. {
  24. /* Previously seen (loopback)? Ignore. */
  25. if (skb->nfct != NULL)
  26. return XT_CONTINUE;
  27. /* special case the untracked ct : we want the percpu object */
  28. if (!ct)
  29. ct = nf_ct_untracked_get();
  30. atomic_inc(&ct->ct_general.use);
  31. skb->nfct = &ct->ct_general;
  32. skb->nfctinfo = IP_CT_NEW;
  33. return XT_CONTINUE;
  34. }
  35. static unsigned int xt_ct_target_v0(struct sk_buff *skb,
  36. const struct xt_action_param *par)
  37. {
  38. const struct xt_ct_target_info *info = par->targinfo;
  39. struct nf_conn *ct = info->ct;
  40. return xt_ct_target(skb, ct);
  41. }
  42. static unsigned int xt_ct_target_v1(struct sk_buff *skb,
  43. const struct xt_action_param *par)
  44. {
  45. const struct xt_ct_target_info_v1 *info = par->targinfo;
  46. struct nf_conn *ct = info->ct;
  47. return xt_ct_target(skb, ct);
  48. }
  49. static u8 xt_ct_find_proto(const struct xt_tgchk_param *par)
  50. {
  51. if (par->family == NFPROTO_IPV4) {
  52. const struct ipt_entry *e = par->entryinfo;
  53. if (e->ip.invflags & IPT_INV_PROTO)
  54. return 0;
  55. return e->ip.proto;
  56. } else if (par->family == NFPROTO_IPV6) {
  57. const struct ip6t_entry *e = par->entryinfo;
  58. if (e->ipv6.invflags & IP6T_INV_PROTO)
  59. return 0;
  60. return e->ipv6.proto;
  61. } else
  62. return 0;
  63. }
  64. static int
  65. xt_ct_set_helper(struct nf_conn *ct, const char *helper_name,
  66. const struct xt_tgchk_param *par)
  67. {
  68. struct nf_conntrack_helper *helper;
  69. struct nf_conn_help *help;
  70. u8 proto;
  71. proto = xt_ct_find_proto(par);
  72. if (!proto) {
  73. pr_info("You must specify a L4 protocol, and not use "
  74. "inversions on it.\n");
  75. return -ENOENT;
  76. }
  77. helper = nf_conntrack_helper_try_module_get(helper_name, par->family,
  78. proto);
  79. if (helper == NULL) {
  80. pr_info("No such helper \"%s\"\n", helper_name);
  81. return -ENOENT;
  82. }
  83. help = nf_ct_helper_ext_add(ct, helper, GFP_KERNEL);
  84. if (help == NULL) {
  85. module_put(helper->me);
  86. return -ENOMEM;
  87. }
  88. help->helper = helper;
  89. return 0;
  90. }
  91. #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
  92. static void __xt_ct_tg_timeout_put(struct ctnl_timeout *timeout)
  93. {
  94. typeof(nf_ct_timeout_put_hook) timeout_put;
  95. timeout_put = rcu_dereference(nf_ct_timeout_put_hook);
  96. if (timeout_put)
  97. timeout_put(timeout);
  98. }
  99. #endif
  100. static int
  101. xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
  102. const char *timeout_name)
  103. {
  104. #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
  105. typeof(nf_ct_timeout_find_get_hook) timeout_find_get;
  106. struct ctnl_timeout *timeout;
  107. struct nf_conn_timeout *timeout_ext;
  108. struct nf_conntrack_l4proto *l4proto;
  109. int ret = 0;
  110. u8 proto;
  111. rcu_read_lock();
  112. timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook);
  113. if (timeout_find_get == NULL) {
  114. ret = -ENOENT;
  115. pr_info("Timeout policy base is empty\n");
  116. goto out;
  117. }
  118. proto = xt_ct_find_proto(par);
  119. if (!proto) {
  120. ret = -EINVAL;
  121. pr_info("You must specify a L4 protocol, and not use "
  122. "inversions on it.\n");
  123. goto out;
  124. }
  125. timeout = timeout_find_get(timeout_name);
  126. if (timeout == NULL) {
  127. ret = -ENOENT;
  128. pr_info("No such timeout policy \"%s\"\n", timeout_name);
  129. goto out;
  130. }
  131. if (timeout->l3num != par->family) {
  132. ret = -EINVAL;
  133. pr_info("Timeout policy `%s' can only be used by L3 protocol "
  134. "number %d\n", timeout_name, timeout->l3num);
  135. goto err_put_timeout;
  136. }
  137. /* Make sure the timeout policy matches any existing protocol tracker,
  138. * otherwise default to generic.
  139. */
  140. l4proto = __nf_ct_l4proto_find(par->family, proto);
  141. if (timeout->l4proto->l4proto != l4proto->l4proto) {
  142. ret = -EINVAL;
  143. pr_info("Timeout policy `%s' can only be used by L4 protocol "
  144. "number %d\n",
  145. timeout_name, timeout->l4proto->l4proto);
  146. goto err_put_timeout;
  147. }
  148. timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC);
  149. if (!timeout_ext) {
  150. ret = -ENOMEM;
  151. goto err_put_timeout;
  152. }
  153. rcu_read_unlock();
  154. return ret;
  155. err_put_timeout:
  156. __xt_ct_tg_timeout_put(timeout);
  157. out:
  158. rcu_read_unlock();
  159. return ret;
  160. #else
  161. return -EOPNOTSUPP;
  162. #endif
  163. }
  164. static u16 xt_ct_flags_to_dir(const struct xt_ct_target_info_v1 *info)
  165. {
  166. switch (info->flags & (XT_CT_ZONE_DIR_ORIG |
  167. XT_CT_ZONE_DIR_REPL)) {
  168. case XT_CT_ZONE_DIR_ORIG:
  169. return NF_CT_ZONE_DIR_ORIG;
  170. case XT_CT_ZONE_DIR_REPL:
  171. return NF_CT_ZONE_DIR_REPL;
  172. default:
  173. return NF_CT_DEFAULT_ZONE_DIR;
  174. }
  175. }
  176. static int xt_ct_tg_check(const struct xt_tgchk_param *par,
  177. struct xt_ct_target_info_v1 *info)
  178. {
  179. struct nf_conntrack_zone zone;
  180. struct nf_conn_help *help;
  181. struct nf_conn *ct;
  182. int ret = -EOPNOTSUPP;
  183. if (info->flags & XT_CT_NOTRACK) {
  184. ct = NULL;
  185. goto out;
  186. }
  187. #ifndef CONFIG_NF_CONNTRACK_ZONES
  188. if (info->zone || info->flags & (XT_CT_ZONE_DIR_ORIG |
  189. XT_CT_ZONE_DIR_REPL |
  190. XT_CT_ZONE_MARK))
  191. goto err1;
  192. #endif
  193. ret = nf_ct_l3proto_try_module_get(par->family);
  194. if (ret < 0)
  195. goto err1;
  196. memset(&zone, 0, sizeof(zone));
  197. zone.id = info->zone;
  198. zone.dir = xt_ct_flags_to_dir(info);
  199. if (info->flags & XT_CT_ZONE_MARK)
  200. zone.flags |= NF_CT_FLAG_MARK;
  201. ct = nf_ct_tmpl_alloc(par->net, &zone, GFP_KERNEL);
  202. if (!ct) {
  203. ret = -ENOMEM;
  204. goto err2;
  205. }
  206. ret = 0;
  207. if ((info->ct_events || info->exp_events) &&
  208. !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events,
  209. GFP_KERNEL)) {
  210. ret = -EINVAL;
  211. goto err3;
  212. }
  213. if (info->helper[0]) {
  214. ret = xt_ct_set_helper(ct, info->helper, par);
  215. if (ret < 0)
  216. goto err3;
  217. }
  218. if (info->timeout[0]) {
  219. ret = xt_ct_set_timeout(ct, par, info->timeout);
  220. if (ret < 0)
  221. goto err4;
  222. }
  223. __set_bit(IPS_CONFIRMED_BIT, &ct->status);
  224. nf_conntrack_get(&ct->ct_general);
  225. out:
  226. info->ct = ct;
  227. return 0;
  228. err4:
  229. help = nfct_help(ct);
  230. if (help)
  231. module_put(help->helper->me);
  232. err3:
  233. nf_ct_tmpl_free(ct);
  234. err2:
  235. nf_ct_l3proto_module_put(par->family);
  236. err1:
  237. return ret;
  238. }
  239. static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par)
  240. {
  241. struct xt_ct_target_info *info = par->targinfo;
  242. struct xt_ct_target_info_v1 info_v1 = {
  243. .flags = info->flags,
  244. .zone = info->zone,
  245. .ct_events = info->ct_events,
  246. .exp_events = info->exp_events,
  247. };
  248. int ret;
  249. if (info->flags & ~XT_CT_NOTRACK)
  250. return -EINVAL;
  251. memcpy(info_v1.helper, info->helper, sizeof(info->helper));
  252. ret = xt_ct_tg_check(par, &info_v1);
  253. if (ret < 0)
  254. return ret;
  255. info->ct = info_v1.ct;
  256. return ret;
  257. }
  258. static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
  259. {
  260. struct xt_ct_target_info_v1 *info = par->targinfo;
  261. if (info->flags & ~XT_CT_NOTRACK)
  262. return -EINVAL;
  263. return xt_ct_tg_check(par, par->targinfo);
  264. }
  265. static int xt_ct_tg_check_v2(const struct xt_tgchk_param *par)
  266. {
  267. struct xt_ct_target_info_v1 *info = par->targinfo;
  268. if (info->flags & ~XT_CT_MASK)
  269. return -EINVAL;
  270. return xt_ct_tg_check(par, par->targinfo);
  271. }
  272. static void xt_ct_destroy_timeout(struct nf_conn *ct)
  273. {
  274. #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
  275. struct nf_conn_timeout *timeout_ext;
  276. typeof(nf_ct_timeout_put_hook) timeout_put;
  277. rcu_read_lock();
  278. timeout_put = rcu_dereference(nf_ct_timeout_put_hook);
  279. if (timeout_put) {
  280. timeout_ext = nf_ct_timeout_find(ct);
  281. if (timeout_ext) {
  282. timeout_put(timeout_ext->timeout);
  283. RCU_INIT_POINTER(timeout_ext->timeout, NULL);
  284. }
  285. }
  286. rcu_read_unlock();
  287. #endif
  288. }
  289. static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par,
  290. struct xt_ct_target_info_v1 *info)
  291. {
  292. struct nf_conn *ct = info->ct;
  293. struct nf_conn_help *help;
  294. if (ct && !nf_ct_is_untracked(ct)) {
  295. help = nfct_help(ct);
  296. if (help)
  297. module_put(help->helper->me);
  298. nf_ct_l3proto_module_put(par->family);
  299. xt_ct_destroy_timeout(ct);
  300. nf_ct_put(info->ct);
  301. }
  302. }
  303. static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par)
  304. {
  305. struct xt_ct_target_info *info = par->targinfo;
  306. struct xt_ct_target_info_v1 info_v1 = {
  307. .flags = info->flags,
  308. .zone = info->zone,
  309. .ct_events = info->ct_events,
  310. .exp_events = info->exp_events,
  311. .ct = info->ct,
  312. };
  313. memcpy(info_v1.helper, info->helper, sizeof(info->helper));
  314. xt_ct_tg_destroy(par, &info_v1);
  315. }
  316. static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par)
  317. {
  318. xt_ct_tg_destroy(par, par->targinfo);
  319. }
  320. static struct xt_target xt_ct_tg_reg[] __read_mostly = {
  321. {
  322. .name = "CT",
  323. .family = NFPROTO_UNSPEC,
  324. .targetsize = sizeof(struct xt_ct_target_info),
  325. .checkentry = xt_ct_tg_check_v0,
  326. .destroy = xt_ct_tg_destroy_v0,
  327. .target = xt_ct_target_v0,
  328. .table = "raw",
  329. .me = THIS_MODULE,
  330. },
  331. {
  332. .name = "CT",
  333. .family = NFPROTO_UNSPEC,
  334. .revision = 1,
  335. .targetsize = sizeof(struct xt_ct_target_info_v1),
  336. .checkentry = xt_ct_tg_check_v1,
  337. .destroy = xt_ct_tg_destroy_v1,
  338. .target = xt_ct_target_v1,
  339. .table = "raw",
  340. .me = THIS_MODULE,
  341. },
  342. {
  343. .name = "CT",
  344. .family = NFPROTO_UNSPEC,
  345. .revision = 2,
  346. .targetsize = sizeof(struct xt_ct_target_info_v1),
  347. .checkentry = xt_ct_tg_check_v2,
  348. .destroy = xt_ct_tg_destroy_v1,
  349. .target = xt_ct_target_v1,
  350. .table = "raw",
  351. .me = THIS_MODULE,
  352. },
  353. };
  354. static unsigned int
  355. notrack_tg(struct sk_buff *skb, const struct xt_action_param *par)
  356. {
  357. /* Previously seen (loopback)? Ignore. */
  358. if (skb->nfct != NULL)
  359. return XT_CONTINUE;
  360. skb->nfct = &nf_ct_untracked_get()->ct_general;
  361. skb->nfctinfo = IP_CT_NEW;
  362. nf_conntrack_get(skb->nfct);
  363. return XT_CONTINUE;
  364. }
  365. static int notrack_chk(const struct xt_tgchk_param *par)
  366. {
  367. if (!par->net->xt.notrack_deprecated_warning) {
  368. pr_info("netfilter: NOTRACK target is deprecated, "
  369. "use CT instead or upgrade iptables\n");
  370. par->net->xt.notrack_deprecated_warning = true;
  371. }
  372. return 0;
  373. }
  374. static struct xt_target notrack_tg_reg __read_mostly = {
  375. .name = "NOTRACK",
  376. .revision = 0,
  377. .family = NFPROTO_UNSPEC,
  378. .checkentry = notrack_chk,
  379. .target = notrack_tg,
  380. .table = "raw",
  381. .me = THIS_MODULE,
  382. };
  383. static int __init xt_ct_tg_init(void)
  384. {
  385. int ret;
  386. ret = xt_register_target(&notrack_tg_reg);
  387. if (ret < 0)
  388. return ret;
  389. ret = xt_register_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
  390. if (ret < 0) {
  391. xt_unregister_target(&notrack_tg_reg);
  392. return ret;
  393. }
  394. return 0;
  395. }
  396. static void __exit xt_ct_tg_exit(void)
  397. {
  398. xt_unregister_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
  399. xt_unregister_target(&notrack_tg_reg);
  400. }
  401. module_init(xt_ct_tg_init);
  402. module_exit(xt_ct_tg_exit);
  403. MODULE_LICENSE("GPL");
  404. MODULE_DESCRIPTION("Xtables: connection tracking target");
  405. MODULE_ALIAS("ipt_CT");
  406. MODULE_ALIAS("ip6t_CT");
  407. MODULE_ALIAS("ipt_NOTRACK");
  408. MODULE_ALIAS("ip6t_NOTRACK");