xt_set.c 20 KB

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