libxt_devgroup.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /* Shared library add-on to iptables to add devgroup matching support.
  2. *
  3. * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
  4. */
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <stdlib.h>
  8. #include <errno.h>
  9. #include <xtables.h>
  10. #include <linux/netfilter/xt_devgroup.h>
  11. static void devgroup_help(void)
  12. {
  13. printf(
  14. "devgroup match options:\n"
  15. "[!] --src-group value[/mask] Match device group of incoming device\n"
  16. "[!] --dst-group value[/mask] Match device group of outgoing device\n"
  17. );
  18. }
  19. enum {
  20. O_SRC_GROUP = 0,
  21. O_DST_GROUP,
  22. };
  23. static const struct xt_option_entry devgroup_opts[] = {
  24. {.name = "src-group", .id = O_SRC_GROUP, .type = XTTYPE_STRING,
  25. .flags = XTOPT_INVERT},
  26. {.name = "dst-group", .id = O_DST_GROUP, .type = XTTYPE_STRING,
  27. .flags = XTOPT_INVERT},
  28. XTOPT_TABLEEND,
  29. };
  30. /* array of devgroups from /etc/iproute2/group_map */
  31. static struct xtables_lmap *devgroups;
  32. static void devgroup_init(struct xt_entry_match *match)
  33. {
  34. const char file[] = "/etc/iproute2/group_map";
  35. devgroups = xtables_lmap_init(file);
  36. if (devgroups == NULL && errno != ENOENT)
  37. fprintf(stderr, "Warning: %s: %s\n", file, strerror(errno));
  38. }
  39. static void devgroup_parse_groupspec(const char *arg, unsigned int *group,
  40. unsigned int *mask)
  41. {
  42. char *end;
  43. bool ok;
  44. ok = xtables_strtoui(arg, &end, group, 0, UINT32_MAX);
  45. if (ok && (*end == '/' || *end == '\0')) {
  46. if (*end == '/')
  47. ok = xtables_strtoui(end + 1, NULL, mask,
  48. 0, UINT32_MAX);
  49. else
  50. *mask = ~0U;
  51. if (!ok)
  52. xtables_error(PARAMETER_PROBLEM,
  53. "Bad group value \"%s\"", arg);
  54. } else {
  55. *group = xtables_lmap_name2id(devgroups, arg);
  56. if (*group == -1)
  57. xtables_error(PARAMETER_PROBLEM,
  58. "Device group \"%s\" not found", arg);
  59. *mask = ~0U;
  60. }
  61. }
  62. static void devgroup_parse(struct xt_option_call *cb)
  63. {
  64. struct xt_devgroup_info *info = cb->data;
  65. unsigned int id, mask;
  66. xtables_option_parse(cb);
  67. switch (cb->entry->id) {
  68. case O_SRC_GROUP:
  69. devgroup_parse_groupspec(cb->arg, &id, &mask);
  70. info->src_group = id;
  71. info->src_mask = mask;
  72. info->flags |= XT_DEVGROUP_MATCH_SRC;
  73. if (cb->invert)
  74. info->flags |= XT_DEVGROUP_INVERT_SRC;
  75. break;
  76. case O_DST_GROUP:
  77. devgroup_parse_groupspec(cb->arg, &id, &mask);
  78. info->dst_group = id;
  79. info->dst_mask = mask;
  80. info->flags |= XT_DEVGROUP_MATCH_DST;
  81. if (cb->invert)
  82. info->flags |= XT_DEVGROUP_INVERT_DST;
  83. break;
  84. }
  85. }
  86. static void
  87. print_devgroup(unsigned int id, unsigned int mask, int numeric)
  88. {
  89. const char *name = NULL;
  90. if (mask != 0xffffffff)
  91. printf("0x%x/0x%x", id, mask);
  92. else {
  93. if (numeric == 0)
  94. name = xtables_lmap_id2name(devgroups, id);
  95. if (name)
  96. printf("%s", name);
  97. else
  98. printf("0x%x", id);
  99. }
  100. }
  101. static void devgroup_show(const char *pfx, const struct xt_devgroup_info *info,
  102. int numeric)
  103. {
  104. if (info->flags & XT_DEVGROUP_MATCH_SRC) {
  105. if (info->flags & XT_DEVGROUP_INVERT_SRC)
  106. printf(" !");
  107. printf(" %ssrc-group ", pfx);
  108. print_devgroup(info->src_group, info->src_mask, numeric);
  109. }
  110. if (info->flags & XT_DEVGROUP_MATCH_DST) {
  111. if (info->flags & XT_DEVGROUP_INVERT_DST)
  112. printf(" !");
  113. printf(" %sdst-group ", pfx);
  114. print_devgroup(info->src_group, info->src_mask, numeric);
  115. }
  116. }
  117. static void devgroup_print(const void *ip, const struct xt_entry_match *match,
  118. int numeric)
  119. {
  120. const struct xt_devgroup_info *info = (const void *)match->data;
  121. devgroup_show("", info, numeric);
  122. }
  123. static void devgroup_save(const void *ip, const struct xt_entry_match *match)
  124. {
  125. const struct xt_devgroup_info *info = (const void *)match->data;
  126. devgroup_show("--", info, 0);
  127. }
  128. static void devgroup_check(struct xt_fcheck_call *cb)
  129. {
  130. if (cb->xflags == 0)
  131. xtables_error(PARAMETER_PROBLEM,
  132. "devgroup match: You must specify either "
  133. "'--src-group' or '--dst-group'");
  134. }
  135. static struct xtables_match devgroup_mt_reg = {
  136. .name = "devgroup",
  137. .version = XTABLES_VERSION,
  138. .family = NFPROTO_UNSPEC,
  139. .size = XT_ALIGN(sizeof(struct xt_devgroup_info)),
  140. .userspacesize = XT_ALIGN(sizeof(struct xt_devgroup_info)),
  141. .init = devgroup_init,
  142. .help = devgroup_help,
  143. .print = devgroup_print,
  144. .save = devgroup_save,
  145. .x6_parse = devgroup_parse,
  146. .x6_fcheck = devgroup_check,
  147. .x6_options = devgroup_opts,
  148. };
  149. void _init(void)
  150. {
  151. xtables_register_match(&devgroup_mt_reg);
  152. }