libxt_connbytes.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <xtables.h>
  4. #include <linux/netfilter/xt_connbytes.h>
  5. enum {
  6. O_CONNBYTES = 0,
  7. O_CONNBYTES_DIR,
  8. O_CONNBYTES_MODE,
  9. };
  10. static void connbytes_help(void)
  11. {
  12. printf(
  13. "connbytes match options:\n"
  14. " [!] --connbytes from:[to]\n"
  15. " --connbytes-dir [original, reply, both]\n"
  16. " --connbytes-mode [packets, bytes, avgpkt]\n");
  17. }
  18. static const struct xt_option_entry connbytes_opts[] = {
  19. {.name = "connbytes", .id = O_CONNBYTES, .type = XTTYPE_UINT64RC,
  20. .flags = XTOPT_MAND | XTOPT_INVERT},
  21. {.name = "connbytes-dir", .id = O_CONNBYTES_DIR, .type = XTTYPE_STRING,
  22. .flags = XTOPT_MAND},
  23. {.name = "connbytes-mode", .id = O_CONNBYTES_MODE,
  24. .type = XTTYPE_STRING, .flags = XTOPT_MAND},
  25. XTOPT_TABLEEND,
  26. };
  27. static void connbytes_parse(struct xt_option_call *cb)
  28. {
  29. struct xt_connbytes_info *sinfo = cb->data;
  30. unsigned long long i;
  31. xtables_option_parse(cb);
  32. switch (cb->entry->id) {
  33. case O_CONNBYTES:
  34. sinfo->count.from = cb->val.u64_range[0];
  35. sinfo->count.to = UINT64_MAX;
  36. if (cb->nvals == 2)
  37. sinfo->count.to = cb->val.u64_range[1];
  38. if (sinfo->count.to < sinfo->count.from)
  39. xtables_error(PARAMETER_PROBLEM, "%llu should be less than %llu",
  40. (unsigned long long)sinfo->count.from,
  41. (unsigned long long)sinfo->count.to);
  42. if (cb->invert) {
  43. i = sinfo->count.from;
  44. sinfo->count.from = sinfo->count.to;
  45. sinfo->count.to = i;
  46. }
  47. break;
  48. case O_CONNBYTES_DIR:
  49. if (strcmp(cb->arg, "original") == 0)
  50. sinfo->direction = XT_CONNBYTES_DIR_ORIGINAL;
  51. else if (strcmp(cb->arg, "reply") == 0)
  52. sinfo->direction = XT_CONNBYTES_DIR_REPLY;
  53. else if (strcmp(cb->arg, "both") == 0)
  54. sinfo->direction = XT_CONNBYTES_DIR_BOTH;
  55. else
  56. xtables_error(PARAMETER_PROBLEM,
  57. "Unknown --connbytes-dir `%s'", cb->arg);
  58. break;
  59. case O_CONNBYTES_MODE:
  60. if (strcmp(cb->arg, "packets") == 0)
  61. sinfo->what = XT_CONNBYTES_PKTS;
  62. else if (strcmp(cb->arg, "bytes") == 0)
  63. sinfo->what = XT_CONNBYTES_BYTES;
  64. else if (strcmp(cb->arg, "avgpkt") == 0)
  65. sinfo->what = XT_CONNBYTES_AVGPKT;
  66. else
  67. xtables_error(PARAMETER_PROBLEM,
  68. "Unknown --connbytes-mode `%s'", cb->arg);
  69. break;
  70. }
  71. }
  72. static void print_mode(const struct xt_connbytes_info *sinfo)
  73. {
  74. switch (sinfo->what) {
  75. case XT_CONNBYTES_PKTS:
  76. fputs(" packets", stdout);
  77. break;
  78. case XT_CONNBYTES_BYTES:
  79. fputs(" bytes", stdout);
  80. break;
  81. case XT_CONNBYTES_AVGPKT:
  82. fputs(" avgpkt", stdout);
  83. break;
  84. default:
  85. fputs(" unknown", stdout);
  86. break;
  87. }
  88. }
  89. static void print_direction(const struct xt_connbytes_info *sinfo)
  90. {
  91. switch (sinfo->direction) {
  92. case XT_CONNBYTES_DIR_ORIGINAL:
  93. fputs(" original", stdout);
  94. break;
  95. case XT_CONNBYTES_DIR_REPLY:
  96. fputs(" reply", stdout);
  97. break;
  98. case XT_CONNBYTES_DIR_BOTH:
  99. fputs(" both", stdout);
  100. break;
  101. default:
  102. fputs(" unknown", stdout);
  103. break;
  104. }
  105. }
  106. static void print_from_to(const struct xt_connbytes_info *sinfo, const char *prefix)
  107. {
  108. unsigned long long from, to;
  109. if (sinfo->count.from > sinfo->count.to) {
  110. fputs(" !", stdout);
  111. from = sinfo->count.to;
  112. to = sinfo->count.from;
  113. } else {
  114. to = sinfo->count.to;
  115. from = sinfo->count.from;
  116. }
  117. printf(" %sconnbytes %llu", prefix, from);
  118. if (to && to < UINT64_MAX)
  119. printf(":%llu", to);
  120. }
  121. static void
  122. connbytes_print(const void *ip, const struct xt_entry_match *match, int numeric)
  123. {
  124. const struct xt_connbytes_info *sinfo = (const void *)match->data;
  125. print_from_to(sinfo, "");
  126. fputs(" connbytes mode", stdout);
  127. print_mode(sinfo);
  128. fputs(" connbytes direction", stdout);
  129. print_direction(sinfo);
  130. }
  131. static void connbytes_save(const void *ip, const struct xt_entry_match *match)
  132. {
  133. const struct xt_connbytes_info *sinfo = (const void *)match->data;
  134. print_from_to(sinfo, "--");
  135. fputs(" --connbytes-mode", stdout);
  136. print_mode(sinfo);
  137. fputs(" --connbytes-dir", stdout);
  138. print_direction(sinfo);
  139. }
  140. static struct xtables_match connbytes_match = {
  141. .family = NFPROTO_UNSPEC,
  142. .name = "connbytes",
  143. .version = XTABLES_VERSION,
  144. .size = XT_ALIGN(sizeof(struct xt_connbytes_info)),
  145. .userspacesize = XT_ALIGN(sizeof(struct xt_connbytes_info)),
  146. .help = connbytes_help,
  147. .print = connbytes_print,
  148. .save = connbytes_save,
  149. .x6_parse = connbytes_parse,
  150. .x6_options = connbytes_opts,
  151. };
  152. void _init(void)
  153. {
  154. xtables_register_match(&connbytes_match);
  155. }