xt_set.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
  3. * Patrick Schaaf <bof@bof.de>
  4. * Martin Josefsson <gandalf@wlug.westbo.se>
  5. * Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@netfilter.org>
  6. */
  7. /* Kernel module which implements the set match and SET target
  8. * for netfilter/iptables.
  9. */
  10. #include <linux/module.h>
  11. #include <linux/skbuff.h>
  12. #include <linux/netfilter/x_tables.h>
  13. #include <linux/netfilter/ipset/ip_set.h>
  14. #include <uapi/linux/netfilter/xt_set.h>
  15. MODULE_LICENSE("GPL");
  16. MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
  17. MODULE_DESCRIPTION("Xtables: IP set match and target module");
  18. MODULE_ALIAS("xt_SET");
  19. MODULE_ALIAS("ipt_set");
  20. MODULE_ALIAS("ip6t_set");
  21. MODULE_ALIAS("ipt_SET");
  22. MODULE_ALIAS("ip6t_SET");
  23. static inline int
  24. match_set(ip_set_id_t index, const struct sk_buff *skb,
  25. const struct xt_action_param *par,
  26. struct ip_set_adt_opt *opt, int inv)
  27. {
  28. if (ip_set_test(index, skb, par, opt))
  29. inv = !inv;
  30. return inv;
  31. }
  32. #define ADT_OPT(n, f, d, fs, cfs, t, p, b, po, bo) \
  33. struct ip_set_adt_opt n = { \
  34. .family = f, \
  35. .dim = d, \
  36. .flags = fs, \
  37. .cmdflags = cfs, \
  38. .ext.timeout = t, \
  39. .ext.packets = p, \
  40. .ext.bytes = b, \
  41. .ext.packets_op = po, \
  42. .ext.bytes_op = bo, \
  43. }
  44. /* Revision 0 interface: backward compatible with netfilter/iptables */
  45. static bool
  46. set_match_v0(const struct sk_buff *skb, struct xt_action_param *par)
  47. {
  48. const struct xt_set_info_match_v0 *info = par->matchinfo;
  49. ADT_OPT(opt, xt_family(par), info->match_set.u.compat.dim,
  50. info->match_set.u.compat.flags, 0, UINT_MAX,
  51. 0, 0, 0, 0);
  52. return match_set(info->match_set.index, skb, par, &opt,
  53. info->match_set.u.compat.flags & IPSET_INV_MATCH);
  54. }
  55. static void
  56. compat_flags(struct xt_set_info_v0 *info)
  57. {
  58. u_int8_t i;
  59. /* Fill out compatibility data according to enum ip_set_kopt */
  60. info->u.compat.dim = IPSET_DIM_ZERO;
  61. if (info->u.flags[0] & IPSET_MATCH_INV)
  62. info->u.compat.flags |= IPSET_INV_MATCH;
  63. for (i = 0; i < IPSET_DIM_MAX - 1 && info->u.flags[i]; i++) {
  64. info->u.compat.dim++;
  65. if (info->u.flags[i] & IPSET_SRC)
  66. info->u.compat.flags |= (1 << info->u.compat.dim);
  67. }
  68. }
  69. static int
  70. set_match_v0_checkentry(const struct xt_mtchk_param *par)
  71. {
  72. struct xt_set_info_match_v0 *info = par->matchinfo;
  73. ip_set_id_t index;
  74. index = ip_set_nfnl_get_byindex(par->net, info->match_set.index);
  75. if (index == IPSET_INVALID_ID) {
  76. pr_info_ratelimited("Cannot find set identified by id %u to match\n",
  77. info->match_set.index);
  78. return -ENOENT;
  79. }
  80. if (info->match_set.u.flags[IPSET_DIM_MAX - 1] != 0) {
  81. pr_info_ratelimited("set match dimension is over the limit!\n");
  82. ip_set_nfnl_put(par->net, info->match_set.index);
  83. return -ERANGE;
  84. }
  85. /* Fill out compatibility data */
  86. compat_flags(&info->match_set);
  87. return 0;
  88. }
  89. static void
  90. set_match_v0_destroy(const struct xt_mtdtor_param *par)
  91. {
  92. struct xt_set_info_match_v0 *info = par->matchinfo;
  93. ip_set_nfnl_put(par->net, info->match_set.index);
  94. }
  95. /* Revision 1 match */
  96. static bool
  97. set_match_v1(const struct sk_buff *skb, struct xt_action_param *par)
  98. {
  99. const struct xt_set_info_match_v1 *info = par->matchinfo;
  100. ADT_OPT(opt, xt_family(par), info->match_set.dim,
  101. info->match_set.flags, 0, UINT_MAX,
  102. 0, 0, 0, 0);
  103. if (opt.flags & IPSET_RETURN_NOMATCH)
  104. opt.cmdflags |= IPSET_FLAG_RETURN_NOMATCH;
  105. return match_set(info->match_set.index, skb, par, &opt,
  106. info->match_set.flags & IPSET_INV_MATCH);
  107. }
  108. static int
  109. set_match_v1_checkentry(const struct xt_mtchk_param *par)
  110. {
  111. struct xt_set_info_match_v1 *info = par->matchinfo;
  112. ip_set_id_t index;
  113. index = ip_set_nfnl_get_byindex(par->net, info->match_set.index);
  114. if (index == IPSET_INVALID_ID) {
  115. pr_info_ratelimited("Cannot find set identified by id %u to match\n",
  116. info->match_set.index);
  117. return -ENOENT;
  118. }
  119. if (info->match_set.dim > IPSET_DIM_MAX) {
  120. pr_info_ratelimited("set match dimension is over the limit!\n");
  121. ip_set_nfnl_put(par->net, info->match_set.index);
  122. return -ERANGE;
  123. }
  124. return 0;
  125. }
  126. static void
  127. set_match_v1_destroy(const struct xt_mtdtor_param *par)
  128. {
  129. struct xt_set_info_match_v1 *info = par->matchinfo;
  130. ip_set_nfnl_put(par->net, info->match_set.index);
  131. }
  132. /* Revision 3 match */
  133. static bool
  134. set_match_v3(const struct sk_buff *skb, struct xt_action_param *par)
  135. {
  136. const struct xt_set_info_match_v3 *info = par->matchinfo;
  137. ADT_OPT(opt, xt_family(par), info->match_set.dim,
  138. info->match_set.flags, info->flags, UINT_MAX,
  139. info->packets.value, info->bytes.value,
  140. info->packets.op, info->bytes.op);
  141. if (info->packets.op != IPSET_COUNTER_NONE ||
  142. info->bytes.op != IPSET_COUNTER_NONE)
  143. opt.cmdflags |= IPSET_FLAG_MATCH_COUNTERS;
  144. return match_set(info->match_set.index, skb, par, &opt,
  145. info->match_set.flags & IPSET_INV_MATCH);
  146. }
  147. #define set_match_v3_checkentry set_match_v1_checkentry
  148. #define set_match_v3_destroy set_match_v1_destroy
  149. /* Revision 4 match */
  150. static bool
  151. set_match_v4(const struct sk_buff *skb, struct xt_action_param *par)
  152. {
  153. const struct xt_set_info_match_v4 *info = par->matchinfo;
  154. ADT_OPT(opt, xt_family(par), info->match_set.dim,
  155. info->match_set.flags, info->flags, UINT_MAX,
  156. info->packets.value, info->bytes.value,
  157. info->packets.op, info->bytes.op);
  158. if (info->packets.op != IPSET_COUNTER_NONE ||
  159. info->bytes.op != IPSET_COUNTER_NONE)
  160. opt.cmdflags |= IPSET_FLAG_MATCH_COUNTERS;
  161. return match_set(info->match_set.index, skb, par, &opt,
  162. info->match_set.flags & IPSET_INV_MATCH);
  163. }
  164. #define set_match_v4_checkentry set_match_v1_checkentry
  165. #define set_match_v4_destroy set_match_v1_destroy
  166. /* Revision 0 interface: backward compatible with netfilter/iptables */
  167. static unsigned int
  168. set_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
  169. {
  170. const struct xt_set_info_target_v0 *info = par->targinfo;
  171. ADT_OPT(add_opt, xt_family(par), info->add_set.u.compat.dim,
  172. info->add_set.u.compat.flags, 0, UINT_MAX,
  173. 0, 0, 0, 0);
  174. ADT_OPT(del_opt, xt_family(par), info->del_set.u.compat.dim,
  175. info->del_set.u.compat.flags, 0, UINT_MAX,
  176. 0, 0, 0, 0);
  177. if (info->add_set.index != IPSET_INVALID_ID)
  178. ip_set_add(info->add_set.index, skb, par, &add_opt);
  179. if (info->del_set.index != IPSET_INVALID_ID)
  180. ip_set_del(info->del_set.index, skb, par, &del_opt);
  181. return XT_CONTINUE;
  182. }
  183. static int
  184. set_target_v0_checkentry(const struct xt_tgchk_param *par)
  185. {
  186. struct xt_set_info_target_v0 *info = par->targinfo;
  187. ip_set_id_t index;
  188. if (info->add_set.index != IPSET_INVALID_ID) {
  189. index = ip_set_nfnl_get_byindex(par->net, info->add_set.index);
  190. if (index == IPSET_INVALID_ID) {
  191. pr_info_ratelimited("Cannot find add_set index %u as target\n",
  192. info->add_set.index);
  193. return -ENOENT;
  194. }
  195. }
  196. if (info->del_set.index != IPSET_INVALID_ID) {
  197. index = ip_set_nfnl_get_byindex(par->net, info->del_set.index);
  198. if (index == IPSET_INVALID_ID) {
  199. pr_info_ratelimited("Cannot find del_set index %u as target\n",
  200. info->del_set.index);
  201. if (info->add_set.index != IPSET_INVALID_ID)
  202. ip_set_nfnl_put(par->net, info->add_set.index);
  203. return -ENOENT;
  204. }
  205. }
  206. if (info->add_set.u.flags[IPSET_DIM_MAX - 1] != 0 ||
  207. info->del_set.u.flags[IPSET_DIM_MAX - 1] != 0) {
  208. pr_info_ratelimited("SET target dimension over the limit!\n");
  209. if (info->add_set.index != IPSET_INVALID_ID)
  210. ip_set_nfnl_put(par->net, info->add_set.index);
  211. if (info->del_set.index != IPSET_INVALID_ID)
  212. ip_set_nfnl_put(par->net, info->del_set.index);
  213. return -ERANGE;
  214. }
  215. /* Fill out compatibility data */
  216. compat_flags(&info->add_set);
  217. compat_flags(&info->del_set);
  218. return 0;
  219. }
  220. static void
  221. set_target_v0_destroy(const struct xt_tgdtor_param *par)
  222. {
  223. const struct xt_set_info_target_v0 *info = par->targinfo;
  224. if (info->add_set.index != IPSET_INVALID_ID)
  225. ip_set_nfnl_put(par->net, info->add_set.index);
  226. if (info->del_set.index != IPSET_INVALID_ID)
  227. ip_set_nfnl_put(par->net, info->del_set.index);
  228. }
  229. /* Revision 1 target */
  230. static unsigned int
  231. set_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
  232. {
  233. const struct xt_set_info_target_v1 *info = par->targinfo;
  234. ADT_OPT(add_opt, xt_family(par), info->add_set.dim,
  235. info->add_set.flags, 0, UINT_MAX,
  236. 0, 0, 0, 0);
  237. ADT_OPT(del_opt, xt_family(par), info->del_set.dim,
  238. info->del_set.flags, 0, UINT_MAX,
  239. 0, 0, 0, 0);
  240. if (info->add_set.index != IPSET_INVALID_ID)
  241. ip_set_add(info->add_set.index, skb, par, &add_opt);
  242. if (info->del_set.index != IPSET_INVALID_ID)
  243. ip_set_del(info->del_set.index, skb, par, &del_opt);
  244. return XT_CONTINUE;
  245. }
  246. static int
  247. set_target_v1_checkentry(const struct xt_tgchk_param *par)
  248. {
  249. const struct xt_set_info_target_v1 *info = par->targinfo;
  250. ip_set_id_t index;
  251. if (info->add_set.index != IPSET_INVALID_ID) {
  252. index = ip_set_nfnl_get_byindex(par->net, info->add_set.index);
  253. if (index == IPSET_INVALID_ID) {
  254. pr_info_ratelimited("Cannot find add_set index %u as target\n",
  255. info->add_set.index);
  256. return -ENOENT;
  257. }
  258. }
  259. if (info->del_set.index != IPSET_INVALID_ID) {
  260. index = ip_set_nfnl_get_byindex(par->net, info->del_set.index);
  261. if (index == IPSET_INVALID_ID) {
  262. pr_info_ratelimited("Cannot find del_set index %u as target\n",
  263. info->del_set.index);
  264. if (info->add_set.index != IPSET_INVALID_ID)
  265. ip_set_nfnl_put(par->net, info->add_set.index);
  266. return -ENOENT;
  267. }
  268. }
  269. if (info->add_set.dim > IPSET_DIM_MAX ||
  270. info->del_set.dim > IPSET_DIM_MAX) {
  271. pr_info_ratelimited("SET target dimension over the limit!\n");
  272. if (info->add_set.index != IPSET_INVALID_ID)
  273. ip_set_nfnl_put(par->net, info->add_set.index);
  274. if (info->del_set.index != IPSET_INVALID_ID)
  275. ip_set_nfnl_put(par->net, info->del_set.index);
  276. return -ERANGE;
  277. }
  278. return 0;
  279. }
  280. static void
  281. set_target_v1_destroy(const struct xt_tgdtor_param *par)
  282. {
  283. const struct xt_set_info_target_v1 *info = par->targinfo;
  284. if (info->add_set.index != IPSET_INVALID_ID)
  285. ip_set_nfnl_put(par->net, info->add_set.index);
  286. if (info->del_set.index != IPSET_INVALID_ID)
  287. ip_set_nfnl_put(par->net, info->del_set.index);
  288. }
  289. /* Revision 2 target */
  290. static unsigned int
  291. set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
  292. {
  293. const struct xt_set_info_target_v2 *info = par->targinfo;
  294. ADT_OPT(add_opt, xt_family(par), info->add_set.dim,
  295. info->add_set.flags, info->flags, info->timeout,
  296. 0, 0, 0, 0);
  297. ADT_OPT(del_opt, xt_family(par), info->del_set.dim,
  298. info->del_set.flags, 0, UINT_MAX,
  299. 0, 0, 0, 0);
  300. /* Normalize to fit into jiffies */
  301. if (add_opt.ext.timeout != IPSET_NO_TIMEOUT &&
  302. add_opt.ext.timeout > IPSET_MAX_TIMEOUT)
  303. add_opt.ext.timeout = IPSET_MAX_TIMEOUT;
  304. if (info->add_set.index != IPSET_INVALID_ID)
  305. ip_set_add(info->add_set.index, skb, par, &add_opt);
  306. if (info->del_set.index != IPSET_INVALID_ID)
  307. ip_set_del(info->del_set.index, skb, par, &del_opt);
  308. return XT_CONTINUE;
  309. }
  310. #define set_target_v2_checkentry set_target_v1_checkentry
  311. #define set_target_v2_destroy set_target_v1_destroy
  312. /* Revision 3 target */
  313. #define MOPT(opt, member) ((opt).ext.skbinfo.member)
  314. static unsigned int
  315. set_target_v3(struct sk_buff *skb, const struct xt_action_param *par)
  316. {
  317. const struct xt_set_info_target_v3 *info = par->targinfo;
  318. int ret;
  319. ADT_OPT(add_opt, xt_family(par), info->add_set.dim,
  320. info->add_set.flags, info->flags, info->timeout,
  321. 0, 0, 0, 0);
  322. ADT_OPT(del_opt, xt_family(par), info->del_set.dim,
  323. info->del_set.flags, 0, UINT_MAX,
  324. 0, 0, 0, 0);
  325. ADT_OPT(map_opt, xt_family(par), info->map_set.dim,
  326. info->map_set.flags, 0, UINT_MAX,
  327. 0, 0, 0, 0);
  328. /* Normalize to fit into jiffies */
  329. if (add_opt.ext.timeout != IPSET_NO_TIMEOUT &&
  330. add_opt.ext.timeout > IPSET_MAX_TIMEOUT)
  331. add_opt.ext.timeout = IPSET_MAX_TIMEOUT;
  332. if (info->add_set.index != IPSET_INVALID_ID)
  333. ip_set_add(info->add_set.index, skb, par, &add_opt);
  334. if (info->del_set.index != IPSET_INVALID_ID)
  335. ip_set_del(info->del_set.index, skb, par, &del_opt);
  336. if (info->map_set.index != IPSET_INVALID_ID) {
  337. map_opt.cmdflags |= info->flags & (IPSET_FLAG_MAP_SKBMARK |
  338. IPSET_FLAG_MAP_SKBPRIO |
  339. IPSET_FLAG_MAP_SKBQUEUE);
  340. ret = match_set(info->map_set.index, skb, par, &map_opt,
  341. info->map_set.flags & IPSET_INV_MATCH);
  342. if (!ret)
  343. return XT_CONTINUE;
  344. if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBMARK)
  345. skb->mark = (skb->mark & ~MOPT(map_opt,skbmarkmask))
  346. ^ MOPT(map_opt, skbmark);
  347. if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBPRIO)
  348. skb->priority = MOPT(map_opt, skbprio);
  349. if ((map_opt.cmdflags & IPSET_FLAG_MAP_SKBQUEUE) &&
  350. skb->dev &&
  351. skb->dev->real_num_tx_queues > MOPT(map_opt, skbqueue))
  352. skb_set_queue_mapping(skb, MOPT(map_opt, skbqueue));
  353. }
  354. return XT_CONTINUE;
  355. }
  356. static int
  357. set_target_v3_checkentry(const struct xt_tgchk_param *par)
  358. {
  359. const struct xt_set_info_target_v3 *info = par->targinfo;
  360. ip_set_id_t index;
  361. int ret = 0;
  362. if (info->add_set.index != IPSET_INVALID_ID) {
  363. index = ip_set_nfnl_get_byindex(par->net,
  364. info->add_set.index);
  365. if (index == IPSET_INVALID_ID) {
  366. pr_info_ratelimited("Cannot find add_set index %u as target\n",
  367. info->add_set.index);
  368. return -ENOENT;
  369. }
  370. }
  371. if (info->del_set.index != IPSET_INVALID_ID) {
  372. index = ip_set_nfnl_get_byindex(par->net,
  373. info->del_set.index);
  374. if (index == IPSET_INVALID_ID) {
  375. pr_info_ratelimited("Cannot find del_set index %u as target\n",
  376. info->del_set.index);
  377. ret = -ENOENT;
  378. goto cleanup_add;
  379. }
  380. }
  381. if (info->map_set.index != IPSET_INVALID_ID) {
  382. if (strncmp(par->table, "mangle", 7)) {
  383. pr_info_ratelimited("--map-set only usable from mangle table\n");
  384. ret = -EINVAL;
  385. goto cleanup_del;
  386. }
  387. if (((info->flags & IPSET_FLAG_MAP_SKBPRIO) |
  388. (info->flags & IPSET_FLAG_MAP_SKBQUEUE)) &&
  389. (par->hook_mask & ~(1 << NF_INET_FORWARD |
  390. 1 << NF_INET_LOCAL_OUT |
  391. 1 << NF_INET_POST_ROUTING))) {
  392. pr_info_ratelimited("mapping of prio or/and queue is allowed only from OUTPUT/FORWARD/POSTROUTING chains\n");
  393. ret = -EINVAL;
  394. goto cleanup_del;
  395. }
  396. index = ip_set_nfnl_get_byindex(par->net,
  397. info->map_set.index);
  398. if (index == IPSET_INVALID_ID) {
  399. pr_info_ratelimited("Cannot find map_set index %u as target\n",
  400. info->map_set.index);
  401. ret = -ENOENT;
  402. goto cleanup_del;
  403. }
  404. }
  405. if (info->add_set.dim > IPSET_DIM_MAX ||
  406. info->del_set.dim > IPSET_DIM_MAX ||
  407. info->map_set.dim > IPSET_DIM_MAX) {
  408. pr_info_ratelimited("SET target dimension over the limit!\n");
  409. ret = -ERANGE;
  410. goto cleanup_mark;
  411. }
  412. return 0;
  413. cleanup_mark:
  414. if (info->map_set.index != IPSET_INVALID_ID)
  415. ip_set_nfnl_put(par->net, info->map_set.index);
  416. cleanup_del:
  417. if (info->del_set.index != IPSET_INVALID_ID)
  418. ip_set_nfnl_put(par->net, info->del_set.index);
  419. cleanup_add:
  420. if (info->add_set.index != IPSET_INVALID_ID)
  421. ip_set_nfnl_put(par->net, info->add_set.index);
  422. return ret;
  423. }
  424. static void
  425. set_target_v3_destroy(const struct xt_tgdtor_param *par)
  426. {
  427. const struct xt_set_info_target_v3 *info = par->targinfo;
  428. if (info->add_set.index != IPSET_INVALID_ID)
  429. ip_set_nfnl_put(par->net, info->add_set.index);
  430. if (info->del_set.index != IPSET_INVALID_ID)
  431. ip_set_nfnl_put(par->net, info->del_set.index);
  432. if (info->map_set.index != IPSET_INVALID_ID)
  433. ip_set_nfnl_put(par->net, info->map_set.index);
  434. }
  435. static struct xt_match set_matches[] __read_mostly = {
  436. {
  437. .name = "set",
  438. .family = NFPROTO_IPV4,
  439. .revision = 0,
  440. .match = set_match_v0,
  441. .matchsize = sizeof(struct xt_set_info_match_v0),
  442. .checkentry = set_match_v0_checkentry,
  443. .destroy = set_match_v0_destroy,
  444. .me = THIS_MODULE
  445. },
  446. {
  447. .name = "set",
  448. .family = NFPROTO_IPV4,
  449. .revision = 1,
  450. .match = set_match_v1,
  451. .matchsize = sizeof(struct xt_set_info_match_v1),
  452. .checkentry = set_match_v1_checkentry,
  453. .destroy = set_match_v1_destroy,
  454. .me = THIS_MODULE
  455. },
  456. {
  457. .name = "set",
  458. .family = NFPROTO_IPV6,
  459. .revision = 1,
  460. .match = set_match_v1,
  461. .matchsize = sizeof(struct xt_set_info_match_v1),
  462. .checkentry = set_match_v1_checkentry,
  463. .destroy = set_match_v1_destroy,
  464. .me = THIS_MODULE
  465. },
  466. /* --return-nomatch flag support */
  467. {
  468. .name = "set",
  469. .family = NFPROTO_IPV4,
  470. .revision = 2,
  471. .match = set_match_v1,
  472. .matchsize = sizeof(struct xt_set_info_match_v1),
  473. .checkentry = set_match_v1_checkentry,
  474. .destroy = set_match_v1_destroy,
  475. .me = THIS_MODULE
  476. },
  477. {
  478. .name = "set",
  479. .family = NFPROTO_IPV6,
  480. .revision = 2,
  481. .match = set_match_v1,
  482. .matchsize = sizeof(struct xt_set_info_match_v1),
  483. .checkentry = set_match_v1_checkentry,
  484. .destroy = set_match_v1_destroy,
  485. .me = THIS_MODULE
  486. },
  487. /* counters support: update, match */
  488. {
  489. .name = "set",
  490. .family = NFPROTO_IPV4,
  491. .revision = 3,
  492. .match = set_match_v3,
  493. .matchsize = sizeof(struct xt_set_info_match_v3),
  494. .checkentry = set_match_v3_checkentry,
  495. .destroy = set_match_v3_destroy,
  496. .me = THIS_MODULE
  497. },
  498. {
  499. .name = "set",
  500. .family = NFPROTO_IPV6,
  501. .revision = 3,
  502. .match = set_match_v3,
  503. .matchsize = sizeof(struct xt_set_info_match_v3),
  504. .checkentry = set_match_v3_checkentry,
  505. .destroy = set_match_v3_destroy,
  506. .me = THIS_MODULE
  507. },
  508. /* new revision for counters support: update, match */
  509. {
  510. .name = "set",
  511. .family = NFPROTO_IPV4,
  512. .revision = 4,
  513. .match = set_match_v4,
  514. .matchsize = sizeof(struct xt_set_info_match_v4),
  515. .checkentry = set_match_v4_checkentry,
  516. .destroy = set_match_v4_destroy,
  517. .me = THIS_MODULE
  518. },
  519. {
  520. .name = "set",
  521. .family = NFPROTO_IPV6,
  522. .revision = 4,
  523. .match = set_match_v4,
  524. .matchsize = sizeof(struct xt_set_info_match_v4),
  525. .checkentry = set_match_v4_checkentry,
  526. .destroy = set_match_v4_destroy,
  527. .me = THIS_MODULE
  528. },
  529. };
  530. static struct xt_target set_targets[] __read_mostly = {
  531. {
  532. .name = "SET",
  533. .revision = 0,
  534. .family = NFPROTO_IPV4,
  535. .target = set_target_v0,
  536. .targetsize = sizeof(struct xt_set_info_target_v0),
  537. .checkentry = set_target_v0_checkentry,
  538. .destroy = set_target_v0_destroy,
  539. .me = THIS_MODULE
  540. },
  541. {
  542. .name = "SET",
  543. .revision = 1,
  544. .family = NFPROTO_IPV4,
  545. .target = set_target_v1,
  546. .targetsize = sizeof(struct xt_set_info_target_v1),
  547. .checkentry = set_target_v1_checkentry,
  548. .destroy = set_target_v1_destroy,
  549. .me = THIS_MODULE
  550. },
  551. {
  552. .name = "SET",
  553. .revision = 1,
  554. .family = NFPROTO_IPV6,
  555. .target = set_target_v1,
  556. .targetsize = sizeof(struct xt_set_info_target_v1),
  557. .checkentry = set_target_v1_checkentry,
  558. .destroy = set_target_v1_destroy,
  559. .me = THIS_MODULE
  560. },
  561. /* --timeout and --exist flags support */
  562. {
  563. .name = "SET",
  564. .revision = 2,
  565. .family = NFPROTO_IPV4,
  566. .target = set_target_v2,
  567. .targetsize = sizeof(struct xt_set_info_target_v2),
  568. .checkentry = set_target_v2_checkentry,
  569. .destroy = set_target_v2_destroy,
  570. .me = THIS_MODULE
  571. },
  572. {
  573. .name = "SET",
  574. .revision = 2,
  575. .family = NFPROTO_IPV6,
  576. .target = set_target_v2,
  577. .targetsize = sizeof(struct xt_set_info_target_v2),
  578. .checkentry = set_target_v2_checkentry,
  579. .destroy = set_target_v2_destroy,
  580. .me = THIS_MODULE
  581. },
  582. /* --map-set support */
  583. {
  584. .name = "SET",
  585. .revision = 3,
  586. .family = NFPROTO_IPV4,
  587. .target = set_target_v3,
  588. .targetsize = sizeof(struct xt_set_info_target_v3),
  589. .checkentry = set_target_v3_checkentry,
  590. .destroy = set_target_v3_destroy,
  591. .me = THIS_MODULE
  592. },
  593. {
  594. .name = "SET",
  595. .revision = 3,
  596. .family = NFPROTO_IPV6,
  597. .target = set_target_v3,
  598. .targetsize = sizeof(struct xt_set_info_target_v3),
  599. .checkentry = set_target_v3_checkentry,
  600. .destroy = set_target_v3_destroy,
  601. .me = THIS_MODULE
  602. },
  603. };
  604. static int __init xt_set_init(void)
  605. {
  606. int ret = xt_register_matches(set_matches, ARRAY_SIZE(set_matches));
  607. if (!ret) {
  608. ret = xt_register_targets(set_targets,
  609. ARRAY_SIZE(set_targets));
  610. if (ret)
  611. xt_unregister_matches(set_matches,
  612. ARRAY_SIZE(set_matches));
  613. }
  614. return ret;
  615. }
  616. static void __exit xt_set_fini(void)
  617. {
  618. xt_unregister_matches(set_matches, ARRAY_SIZE(set_matches));
  619. xt_unregister_targets(set_targets, ARRAY_SIZE(set_targets));
  620. }
  621. module_init(xt_set_init);
  622. module_exit(xt_set_fini);