xt_set.c 21 KB

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