libxt_set.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  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 matching. */
  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 <errno.h>
  19. #include <xtables.h>
  20. #include <linux/netfilter/xt_set.h>
  21. #include "libxt_set.h"
  22. /* Revision 0 */
  23. static void
  24. set_help_v0(void)
  25. {
  26. printf("set match options:\n"
  27. " [!] --match-set name flags\n"
  28. " 'name' is the set name from to match,\n"
  29. " 'flags' are the comma separated list of\n"
  30. " 'src' and 'dst' specifications.\n");
  31. }
  32. static const struct option set_opts_v0[] = {
  33. {.name = "match-set", .has_arg = true, .val = '1'},
  34. {.name = "set", .has_arg = true, .val = '2'},
  35. XT_GETOPT_TABLEEND,
  36. };
  37. static void
  38. set_check_v0(unsigned int flags)
  39. {
  40. if (!flags)
  41. xtables_error(PARAMETER_PROBLEM,
  42. "You must specify `--match-set' with proper arguments");
  43. }
  44. static int
  45. set_parse_v0(int c, char **argv, int invert, unsigned int *flags,
  46. const void *entry, struct xt_entry_match **match)
  47. {
  48. struct xt_set_info_match_v0 *myinfo =
  49. (struct xt_set_info_match_v0 *) (*match)->data;
  50. struct xt_set_info_v0 *info = &myinfo->match_set;
  51. switch (c) {
  52. case '2':
  53. fprintf(stderr,
  54. "--set option deprecated, please use --match-set\n");
  55. case '1': /* --match-set <set> <flag>[,<flag> */
  56. if (info->u.flags[0])
  57. xtables_error(PARAMETER_PROBLEM,
  58. "--match-set can be specified only once");
  59. if (invert)
  60. info->u.flags[0] |= IPSET_MATCH_INV;
  61. if (!argv[optind]
  62. || argv[optind][0] == '-'
  63. || argv[optind][0] == '!')
  64. xtables_error(PARAMETER_PROBLEM,
  65. "--match-set requires two args.");
  66. if (strlen(optarg) > IPSET_MAXNAMELEN - 1)
  67. xtables_error(PARAMETER_PROBLEM,
  68. "setname `%s' too long, max %d characters.",
  69. optarg, IPSET_MAXNAMELEN - 1);
  70. get_set_byname(optarg, (struct xt_set_info *)info);
  71. parse_dirs_v0(argv[optind], info);
  72. DEBUGP("parse: set index %u\n", info->index);
  73. optind++;
  74. *flags = 1;
  75. break;
  76. }
  77. return 1;
  78. }
  79. static void
  80. print_match_v0(const char *prefix, const struct xt_set_info_v0 *info)
  81. {
  82. int i;
  83. char setname[IPSET_MAXNAMELEN];
  84. get_set_byid(setname, info->index);
  85. printf("%s %s %s",
  86. (info->u.flags[0] & IPSET_MATCH_INV) ? " !" : "",
  87. prefix,
  88. setname);
  89. for (i = 0; i < IPSET_DIM_MAX; i++) {
  90. if (!info->u.flags[i])
  91. break;
  92. printf("%s%s",
  93. i == 0 ? " " : ",",
  94. info->u.flags[i] & IPSET_SRC ? "src" : "dst");
  95. }
  96. }
  97. /* Prints out the matchinfo. */
  98. static void
  99. set_print_v0(const void *ip, const struct xt_entry_match *match, int numeric)
  100. {
  101. const struct xt_set_info_match_v0 *info = (const void *)match->data;
  102. print_match_v0("match-set", &info->match_set);
  103. }
  104. static void
  105. set_save_v0(const void *ip, const struct xt_entry_match *match)
  106. {
  107. const struct xt_set_info_match_v0 *info = (const void *)match->data;
  108. print_match_v0("--match-set", &info->match_set);
  109. }
  110. /* Revision 1 */
  111. static int
  112. set_parse_v1(int c, char **argv, int invert, unsigned int *flags,
  113. const void *entry, struct xt_entry_match **match)
  114. {
  115. struct xt_set_info_match_v1 *myinfo =
  116. (struct xt_set_info_match_v1 *) (*match)->data;
  117. struct xt_set_info *info = &myinfo->match_set;
  118. switch (c) {
  119. case '2':
  120. fprintf(stderr,
  121. "--set option deprecated, please use --match-set\n");
  122. case '1': /* --match-set <set> <flag>[,<flag> */
  123. if (info->dim)
  124. xtables_error(PARAMETER_PROBLEM,
  125. "--match-set can be specified only once");
  126. if (invert)
  127. info->flags |= IPSET_INV_MATCH;
  128. if (!argv[optind]
  129. || argv[optind][0] == '-'
  130. || argv[optind][0] == '!')
  131. xtables_error(PARAMETER_PROBLEM,
  132. "--match-set requires two args.");
  133. if (strlen(optarg) > IPSET_MAXNAMELEN - 1)
  134. xtables_error(PARAMETER_PROBLEM,
  135. "setname `%s' too long, max %d characters.",
  136. optarg, IPSET_MAXNAMELEN - 1);
  137. get_set_byname(optarg, info);
  138. parse_dirs(argv[optind], info);
  139. DEBUGP("parse: set index %u\n", info->index);
  140. optind++;
  141. *flags = 1;
  142. break;
  143. }
  144. return 1;
  145. }
  146. static void
  147. print_match(const char *prefix, const struct xt_set_info *info)
  148. {
  149. int i;
  150. char setname[IPSET_MAXNAMELEN];
  151. get_set_byid(setname, info->index);
  152. printf("%s %s %s",
  153. (info->flags & IPSET_INV_MATCH) ? " !" : "",
  154. prefix,
  155. setname);
  156. for (i = 1; i <= info->dim; i++) {
  157. printf("%s%s",
  158. i == 1 ? " " : ",",
  159. info->flags & (1 << i) ? "src" : "dst");
  160. }
  161. }
  162. /* Prints out the matchinfo. */
  163. static void
  164. set_print_v1(const void *ip, const struct xt_entry_match *match, int numeric)
  165. {
  166. const struct xt_set_info_match_v1 *info = (const void *)match->data;
  167. print_match("match-set", &info->match_set);
  168. }
  169. static void
  170. set_save_v1(const void *ip, const struct xt_entry_match *match)
  171. {
  172. const struct xt_set_info_match_v1 *info = (const void *)match->data;
  173. print_match("--match-set", &info->match_set);
  174. }
  175. /* Revision 2 */
  176. static void
  177. set_help_v2(void)
  178. {
  179. printf("set match options:\n"
  180. " [!] --match-set name flags [--return-nomatch]\n"
  181. " 'name' is the set name from to match,\n"
  182. " 'flags' are the comma separated list of\n"
  183. " 'src' and 'dst' specifications.\n");
  184. }
  185. static const struct option set_opts_v2[] = {
  186. {.name = "match-set", .has_arg = true, .val = '1'},
  187. {.name = "set", .has_arg = true, .val = '2'},
  188. {.name = "return-nomatch", .has_arg = false, .val = '3'},
  189. XT_GETOPT_TABLEEND,
  190. };
  191. static int
  192. set_parse_v2(int c, char **argv, int invert, unsigned int *flags,
  193. const void *entry, struct xt_entry_match **match)
  194. {
  195. struct xt_set_info_match_v1 *myinfo =
  196. (struct xt_set_info_match_v1 *) (*match)->data;
  197. struct xt_set_info *info = &myinfo->match_set;
  198. switch (c) {
  199. case '3':
  200. info->flags |= IPSET_RETURN_NOMATCH;
  201. break;
  202. case '2':
  203. fprintf(stderr,
  204. "--set option deprecated, please use --match-set\n");
  205. case '1': /* --match-set <set> <flag>[,<flag> */
  206. if (info->dim)
  207. xtables_error(PARAMETER_PROBLEM,
  208. "--match-set can be specified only once");
  209. if (invert)
  210. info->flags |= IPSET_INV_MATCH;
  211. if (!argv[optind]
  212. || argv[optind][0] == '-'
  213. || argv[optind][0] == '!')
  214. xtables_error(PARAMETER_PROBLEM,
  215. "--match-set requires two args.");
  216. if (strlen(optarg) > IPSET_MAXNAMELEN - 1)
  217. xtables_error(PARAMETER_PROBLEM,
  218. "setname `%s' too long, max %d characters.",
  219. optarg, IPSET_MAXNAMELEN - 1);
  220. get_set_byname(optarg, info);
  221. parse_dirs(argv[optind], info);
  222. DEBUGP("parse: set index %u\n", info->index);
  223. optind++;
  224. *flags = 1;
  225. break;
  226. }
  227. return 1;
  228. }
  229. /* Prints out the matchinfo. */
  230. static void
  231. set_print_v2(const void *ip, const struct xt_entry_match *match, int numeric)
  232. {
  233. const struct xt_set_info_match_v1 *info = (const void *)match->data;
  234. print_match("match-set", &info->match_set);
  235. if (info->match_set.flags & IPSET_RETURN_NOMATCH)
  236. printf(" return-nomatch");
  237. }
  238. static void
  239. set_save_v2(const void *ip, const struct xt_entry_match *match)
  240. {
  241. const struct xt_set_info_match_v1 *info = (const void *)match->data;
  242. print_match("--match-set", &info->match_set);
  243. if (info->match_set.flags & IPSET_RETURN_NOMATCH)
  244. printf(" --return-nomatch");
  245. }
  246. static struct xtables_match set_mt_reg[] = {
  247. {
  248. .name = "set",
  249. .revision = 0,
  250. .version = XTABLES_VERSION,
  251. .family = NFPROTO_IPV4,
  252. .size = XT_ALIGN(sizeof(struct xt_set_info_match_v0)),
  253. .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v0)),
  254. .help = set_help_v0,
  255. .parse = set_parse_v0,
  256. .final_check = set_check_v0,
  257. .print = set_print_v0,
  258. .save = set_save_v0,
  259. .extra_opts = set_opts_v0,
  260. },
  261. {
  262. .name = "set",
  263. .revision = 1,
  264. .version = XTABLES_VERSION,
  265. .family = NFPROTO_UNSPEC,
  266. .size = XT_ALIGN(sizeof(struct xt_set_info_match_v1)),
  267. .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v1)),
  268. .help = set_help_v0,
  269. .parse = set_parse_v1,
  270. .final_check = set_check_v0,
  271. .print = set_print_v1,
  272. .save = set_save_v1,
  273. .extra_opts = set_opts_v0,
  274. },
  275. {
  276. .name = "set",
  277. .revision = 2,
  278. .version = XTABLES_VERSION,
  279. .family = NFPROTO_UNSPEC,
  280. .size = XT_ALIGN(sizeof(struct xt_set_info_match_v1)),
  281. .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v1)),
  282. .help = set_help_v2,
  283. .parse = set_parse_v2,
  284. .final_check = set_check_v0,
  285. .print = set_print_v2,
  286. .save = set_save_v2,
  287. .extra_opts = set_opts_v2,
  288. },
  289. };
  290. void _init(void)
  291. {
  292. xtables_register_matches(set_mt_reg, ARRAY_SIZE(set_mt_reg));
  293. }