libxt_SET.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  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-2010 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. /* Shared library add-on to iptables to add IP set mangling target. */
  11. #include <stdbool.h>
  12. #include <stdio.h>
  13. #include <netdb.h>
  14. #include <string.h>
  15. #include <stdlib.h>
  16. #include <getopt.h>
  17. #include <ctype.h>
  18. #include <xtables.h>
  19. #include <linux/netfilter/xt_set.h>
  20. #include "libxt_set.h"
  21. /* Revision 0 */
  22. static void
  23. set_target_help_v0(void)
  24. {
  25. printf("SET target options:\n"
  26. " --add-set name flags\n"
  27. " --del-set name flags\n"
  28. " add/del src/dst IP/port from/to named sets,\n"
  29. " where flags are the comma separated list of\n"
  30. " 'src' and 'dst' specifications.\n");
  31. }
  32. static const struct option set_target_opts_v0[] = {
  33. {.name = "add-set", .has_arg = true, .val = '1'},
  34. {.name = "del-set", .has_arg = true, .val = '2'},
  35. XT_GETOPT_TABLEEND,
  36. };
  37. static void
  38. set_target_check_v0(unsigned int flags)
  39. {
  40. if (!flags)
  41. xtables_error(PARAMETER_PROBLEM,
  42. "You must specify either `--add-set' or `--del-set'");
  43. }
  44. static void
  45. set_target_init_v0(struct xt_entry_target *target)
  46. {
  47. struct xt_set_info_target_v0 *info =
  48. (struct xt_set_info_target_v0 *) target->data;
  49. info->add_set.index =
  50. info->del_set.index = IPSET_INVALID_ID;
  51. }
  52. static void
  53. parse_target_v0(char **argv, int invert, unsigned int *flags,
  54. struct xt_set_info_v0 *info, const char *what)
  55. {
  56. if (info->u.flags[0])
  57. xtables_error(PARAMETER_PROBLEM,
  58. "--%s can be specified only once", what);
  59. if (!argv[optind]
  60. || argv[optind][0] == '-' || argv[optind][0] == '!')
  61. xtables_error(PARAMETER_PROBLEM,
  62. "--%s requires two args.", what);
  63. if (strlen(optarg) > IPSET_MAXNAMELEN - 1)
  64. xtables_error(PARAMETER_PROBLEM,
  65. "setname `%s' too long, max %d characters.",
  66. optarg, IPSET_MAXNAMELEN - 1);
  67. get_set_byname(optarg, (struct xt_set_info *)info);
  68. parse_dirs_v0(argv[optind], info);
  69. optind++;
  70. *flags = 1;
  71. }
  72. static int
  73. set_target_parse_v0(int c, char **argv, int invert, unsigned int *flags,
  74. const void *entry, struct xt_entry_target **target)
  75. {
  76. struct xt_set_info_target_v0 *myinfo =
  77. (struct xt_set_info_target_v0 *) (*target)->data;
  78. switch (c) {
  79. case '1': /* --add-set <set> <flags> */
  80. parse_target_v0(argv, invert, flags,
  81. &myinfo->add_set, "add-set");
  82. break;
  83. case '2': /* --del-set <set>[:<flags>] <flags> */
  84. parse_target_v0(argv, invert, flags,
  85. &myinfo->del_set, "del-set");
  86. break;
  87. }
  88. return 1;
  89. }
  90. static void
  91. print_target_v0(const char *prefix, const struct xt_set_info_v0 *info)
  92. {
  93. int i;
  94. char setname[IPSET_MAXNAMELEN];
  95. if (info->index == IPSET_INVALID_ID)
  96. return;
  97. get_set_byid(setname, info->index);
  98. printf(" %s %s", prefix, setname);
  99. for (i = 0; i < IPSET_DIM_MAX; i++) {
  100. if (!info->u.flags[i])
  101. break;
  102. printf("%s%s",
  103. i == 0 ? " " : ",",
  104. info->u.flags[i] & IPSET_SRC ? "src" : "dst");
  105. }
  106. }
  107. static void
  108. set_target_print_v0(const void *ip, const struct xt_entry_target *target,
  109. int numeric)
  110. {
  111. const struct xt_set_info_target_v0 *info = (const void *)target->data;
  112. print_target_v0("add-set", &info->add_set);
  113. print_target_v0("del-set", &info->del_set);
  114. }
  115. static void
  116. set_target_save_v0(const void *ip, const struct xt_entry_target *target)
  117. {
  118. const struct xt_set_info_target_v0 *info = (const void *)target->data;
  119. print_target_v0("--add-set", &info->add_set);
  120. print_target_v0("--del-set", &info->del_set);
  121. }
  122. /* Revision 1 */
  123. static void
  124. set_target_init_v1(struct xt_entry_target *target)
  125. {
  126. struct xt_set_info_target_v1 *info =
  127. (struct xt_set_info_target_v1 *) target->data;
  128. info->add_set.index =
  129. info->del_set.index = IPSET_INVALID_ID;
  130. }
  131. #define SET_TARGET_ADD 0x1
  132. #define SET_TARGET_DEL 0x2
  133. #define SET_TARGET_EXIST 0x4
  134. #define SET_TARGET_TIMEOUT 0x8
  135. static void
  136. parse_target(char **argv, int invert, struct xt_set_info *info,
  137. const char *what)
  138. {
  139. if (info->dim)
  140. xtables_error(PARAMETER_PROBLEM,
  141. "--%s can be specified only once", what);
  142. if (!argv[optind]
  143. || argv[optind][0] == '-' || argv[optind][0] == '!')
  144. xtables_error(PARAMETER_PROBLEM,
  145. "--%s requires two args.", what);
  146. if (strlen(optarg) > IPSET_MAXNAMELEN - 1)
  147. xtables_error(PARAMETER_PROBLEM,
  148. "setname `%s' too long, max %d characters.",
  149. optarg, IPSET_MAXNAMELEN - 1);
  150. get_set_byname(optarg, info);
  151. parse_dirs(argv[optind], info);
  152. optind++;
  153. }
  154. static int
  155. set_target_parse_v1(int c, char **argv, int invert, unsigned int *flags,
  156. const void *entry, struct xt_entry_target **target)
  157. {
  158. struct xt_set_info_target_v1 *myinfo =
  159. (struct xt_set_info_target_v1 *) (*target)->data;
  160. switch (c) {
  161. case '1': /* --add-set <set> <flags> */
  162. parse_target(argv, invert, &myinfo->add_set, "add-set");
  163. *flags |= SET_TARGET_ADD;
  164. break;
  165. case '2': /* --del-set <set>[:<flags>] <flags> */
  166. parse_target(argv, invert, &myinfo->del_set, "del-set");
  167. *flags |= SET_TARGET_DEL;
  168. break;
  169. }
  170. return 1;
  171. }
  172. static void
  173. print_target(const char *prefix, const struct xt_set_info *info)
  174. {
  175. int i;
  176. char setname[IPSET_MAXNAMELEN];
  177. if (info->index == IPSET_INVALID_ID)
  178. return;
  179. get_set_byid(setname, info->index);
  180. printf(" %s %s", prefix, setname);
  181. for (i = 1; i <= info->dim; i++) {
  182. printf("%s%s",
  183. i == 1 ? " " : ",",
  184. info->flags & (1 << i) ? "src" : "dst");
  185. }
  186. }
  187. static void
  188. set_target_print_v1(const void *ip, const struct xt_entry_target *target,
  189. int numeric)
  190. {
  191. const struct xt_set_info_target_v1 *info = (const void *)target->data;
  192. print_target("add-set", &info->add_set);
  193. print_target("del-set", &info->del_set);
  194. }
  195. static void
  196. set_target_save_v1(const void *ip, const struct xt_entry_target *target)
  197. {
  198. const struct xt_set_info_target_v1 *info = (const void *)target->data;
  199. print_target("--add-set", &info->add_set);
  200. print_target("--del-set", &info->del_set);
  201. }
  202. /* Revision 2 */
  203. static void
  204. set_target_help_v2(void)
  205. {
  206. printf("SET target options:\n"
  207. " --add-set name flags [--exist] [--timeout n]\n"
  208. " --del-set name flags\n"
  209. " add/del src/dst IP/port from/to named sets,\n"
  210. " where flags are the comma separated list of\n"
  211. " 'src' and 'dst' specifications.\n");
  212. }
  213. static const struct option set_target_opts_v2[] = {
  214. {.name = "add-set", .has_arg = true, .val = '1'},
  215. {.name = "del-set", .has_arg = true, .val = '2'},
  216. {.name = "exist", .has_arg = false, .val = '3'},
  217. {.name = "timeout", .has_arg = true, .val = '4'},
  218. XT_GETOPT_TABLEEND,
  219. };
  220. static void
  221. set_target_check_v2(unsigned int flags)
  222. {
  223. if (!(flags & (SET_TARGET_ADD|SET_TARGET_DEL)))
  224. xtables_error(PARAMETER_PROBLEM,
  225. "You must specify either `--add-set' or `--del-set'");
  226. if (!(flags & SET_TARGET_ADD)) {
  227. if (flags & SET_TARGET_EXIST)
  228. xtables_error(PARAMETER_PROBLEM,
  229. "Flag `--exist' can be used with `--add-set' only");
  230. if (flags & SET_TARGET_TIMEOUT)
  231. xtables_error(PARAMETER_PROBLEM,
  232. "Option `--timeout' can be used with `--add-set' only");
  233. }
  234. }
  235. static void
  236. set_target_init_v2(struct xt_entry_target *target)
  237. {
  238. struct xt_set_info_target_v2 *info =
  239. (struct xt_set_info_target_v2 *) target->data;
  240. info->add_set.index =
  241. info->del_set.index = IPSET_INVALID_ID;
  242. info->timeout = UINT32_MAX;
  243. }
  244. static int
  245. set_target_parse_v2(int c, char **argv, int invert, unsigned int *flags,
  246. const void *entry, struct xt_entry_target **target)
  247. {
  248. struct xt_set_info_target_v2 *myinfo =
  249. (struct xt_set_info_target_v2 *) (*target)->data;
  250. unsigned int timeout;
  251. switch (c) {
  252. case '1': /* --add-set <set> <flags> */
  253. parse_target(argv, invert, &myinfo->add_set, "add-set");
  254. *flags |= SET_TARGET_ADD;
  255. break;
  256. case '2': /* --del-set <set>[:<flags>] <flags> */
  257. parse_target(argv, invert, &myinfo->del_set, "del-set");
  258. *flags |= SET_TARGET_DEL;
  259. break;
  260. case '3':
  261. myinfo->flags |= IPSET_FLAG_EXIST;
  262. *flags |= SET_TARGET_EXIST;
  263. break;
  264. case '4':
  265. if (!xtables_strtoui(optarg, NULL, &timeout, 0, UINT32_MAX - 1))
  266. xtables_error(PARAMETER_PROBLEM,
  267. "Invalid value for option --timeout "
  268. "or out of range 0-%u", UINT32_MAX - 1);
  269. myinfo->timeout = timeout;
  270. *flags |= SET_TARGET_TIMEOUT;
  271. break;
  272. }
  273. return 1;
  274. }
  275. static void
  276. set_target_print_v2(const void *ip, const struct xt_entry_target *target,
  277. int numeric)
  278. {
  279. const struct xt_set_info_target_v2 *info = (const void *)target->data;
  280. print_target("add-set", &info->add_set);
  281. if (info->flags & IPSET_FLAG_EXIST)
  282. printf(" exist");
  283. if (info->timeout != UINT32_MAX)
  284. printf(" timeout %u", info->timeout);
  285. print_target("del-set", &info->del_set);
  286. }
  287. static void
  288. set_target_save_v2(const void *ip, const struct xt_entry_target *target)
  289. {
  290. const struct xt_set_info_target_v2 *info = (const void *)target->data;
  291. print_target("--add-set", &info->add_set);
  292. if (info->flags & IPSET_FLAG_EXIST)
  293. printf(" --exist");
  294. if (info->timeout != UINT32_MAX)
  295. printf(" --timeout %u", info->timeout);
  296. print_target("--del-set", &info->del_set);
  297. }
  298. static struct xtables_target set_tg_reg[] = {
  299. {
  300. .name = "SET",
  301. .revision = 0,
  302. .version = XTABLES_VERSION,
  303. .family = NFPROTO_IPV4,
  304. .size = XT_ALIGN(sizeof(struct xt_set_info_target_v0)),
  305. .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_target_v0)),
  306. .help = set_target_help_v0,
  307. .init = set_target_init_v0,
  308. .parse = set_target_parse_v0,
  309. .final_check = set_target_check_v0,
  310. .print = set_target_print_v0,
  311. .save = set_target_save_v0,
  312. .extra_opts = set_target_opts_v0,
  313. },
  314. {
  315. .name = "SET",
  316. .revision = 1,
  317. .version = XTABLES_VERSION,
  318. .family = NFPROTO_UNSPEC,
  319. .size = XT_ALIGN(sizeof(struct xt_set_info_target_v1)),
  320. .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_target_v1)),
  321. .help = set_target_help_v0,
  322. .init = set_target_init_v1,
  323. .parse = set_target_parse_v1,
  324. .final_check = set_target_check_v0,
  325. .print = set_target_print_v1,
  326. .save = set_target_save_v1,
  327. .extra_opts = set_target_opts_v0,
  328. },
  329. {
  330. .name = "SET",
  331. .revision = 2,
  332. .version = XTABLES_VERSION,
  333. .family = NFPROTO_UNSPEC,
  334. .size = XT_ALIGN(sizeof(struct xt_set_info_target_v2)),
  335. .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_target_v2)),
  336. .help = set_target_help_v2,
  337. .init = set_target_init_v2,
  338. .parse = set_target_parse_v2,
  339. .final_check = set_target_check_v2,
  340. .print = set_target_print_v2,
  341. .save = set_target_save_v2,
  342. .extra_opts = set_target_opts_v2,
  343. },
  344. };
  345. void _init(void)
  346. {
  347. xtables_register_targets(set_tg_reg, ARRAY_SIZE(set_tg_reg));
  348. }