libxt_ecn.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /* Shared library add-on to iptables for ECN matching
  2. *
  3. * (C) 2002 by Harald Welte <laforge@netfilter.org>
  4. * (C) 2011 by Patrick McHardy <kaber@trash.net>
  5. *
  6. * This program is distributed under the terms of GNU GPL v2, 1991
  7. *
  8. * libipt_ecn.c borrowed heavily from libipt_dscp.c
  9. *
  10. */
  11. #include <stdio.h>
  12. #include <xtables.h>
  13. #include <linux/netfilter/xt_ecn.h>
  14. enum {
  15. O_ECN_TCP_CWR = 0,
  16. O_ECN_TCP_ECE,
  17. O_ECN_IP_ECT,
  18. };
  19. static void ecn_help(void)
  20. {
  21. printf(
  22. "ECN match options\n"
  23. "[!] --ecn-tcp-cwr Match CWR bit of TCP header\n"
  24. "[!] --ecn-tcp-ece Match ECE bit of TCP header\n"
  25. "[!] --ecn-ip-ect [0..3] Match ECN codepoint in IPv4/IPv6 header\n");
  26. }
  27. static const struct xt_option_entry ecn_opts[] = {
  28. {.name = "ecn-tcp-cwr", .id = O_ECN_TCP_CWR, .type = XTTYPE_NONE,
  29. .flags = XTOPT_INVERT},
  30. {.name = "ecn-tcp-ece", .id = O_ECN_TCP_ECE, .type = XTTYPE_NONE,
  31. .flags = XTOPT_INVERT},
  32. {.name = "ecn-ip-ect", .id = O_ECN_IP_ECT, .type = XTTYPE_UINT8,
  33. .min = 0, .max = 3, .flags = XTOPT_INVERT},
  34. XTOPT_TABLEEND,
  35. };
  36. static void ecn_parse(struct xt_option_call *cb)
  37. {
  38. struct xt_ecn_info *einfo = cb->data;
  39. xtables_option_parse(cb);
  40. switch (cb->entry->id) {
  41. case O_ECN_TCP_CWR:
  42. einfo->operation |= XT_ECN_OP_MATCH_CWR;
  43. if (cb->invert)
  44. einfo->invert |= XT_ECN_OP_MATCH_CWR;
  45. break;
  46. case O_ECN_TCP_ECE:
  47. einfo->operation |= XT_ECN_OP_MATCH_ECE;
  48. if (cb->invert)
  49. einfo->invert |= XT_ECN_OP_MATCH_ECE;
  50. break;
  51. case O_ECN_IP_ECT:
  52. if (cb->invert)
  53. einfo->invert |= XT_ECN_OP_MATCH_IP;
  54. einfo->operation |= XT_ECN_OP_MATCH_IP;
  55. einfo->ip_ect = cb->val.u8;
  56. break;
  57. }
  58. }
  59. static void ecn_check(struct xt_fcheck_call *cb)
  60. {
  61. if (cb->xflags == 0)
  62. xtables_error(PARAMETER_PROBLEM,
  63. "ECN match: some option required");
  64. }
  65. static void ecn_print(const void *ip, const struct xt_entry_match *match,
  66. int numeric)
  67. {
  68. const struct xt_ecn_info *einfo =
  69. (const struct xt_ecn_info *)match->data;
  70. printf(" ECN match");
  71. if (einfo->operation & XT_ECN_OP_MATCH_ECE) {
  72. printf(" %sECE",
  73. (einfo->invert & XT_ECN_OP_MATCH_ECE) ? "!" : "");
  74. }
  75. if (einfo->operation & XT_ECN_OP_MATCH_CWR) {
  76. printf(" %sCWR",
  77. (einfo->invert & XT_ECN_OP_MATCH_CWR) ? "!" : "");
  78. }
  79. if (einfo->operation & XT_ECN_OP_MATCH_IP) {
  80. printf(" %sECT=%d",
  81. (einfo->invert & XT_ECN_OP_MATCH_IP) ? "!" : "",
  82. einfo->ip_ect);
  83. }
  84. }
  85. static void ecn_save(const void *ip, const struct xt_entry_match *match)
  86. {
  87. const struct xt_ecn_info *einfo =
  88. (const struct xt_ecn_info *)match->data;
  89. if (einfo->operation & XT_ECN_OP_MATCH_ECE) {
  90. if (einfo->invert & XT_ECN_OP_MATCH_ECE)
  91. printf(" !");
  92. printf(" --ecn-tcp-ece");
  93. }
  94. if (einfo->operation & XT_ECN_OP_MATCH_CWR) {
  95. if (einfo->invert & XT_ECN_OP_MATCH_CWR)
  96. printf(" !");
  97. printf(" --ecn-tcp-cwr");
  98. }
  99. if (einfo->operation & XT_ECN_OP_MATCH_IP) {
  100. if (einfo->invert & XT_ECN_OP_MATCH_IP)
  101. printf(" !");
  102. printf(" --ecn-ip-ect %d", einfo->ip_ect);
  103. }
  104. }
  105. static struct xtables_match ecn_mt_reg = {
  106. .name = "ecn",
  107. .version = XTABLES_VERSION,
  108. .family = NFPROTO_UNSPEC,
  109. .size = XT_ALIGN(sizeof(struct xt_ecn_info)),
  110. .userspacesize = XT_ALIGN(sizeof(struct xt_ecn_info)),
  111. .help = ecn_help,
  112. .print = ecn_print,
  113. .save = ecn_save,
  114. .x6_parse = ecn_parse,
  115. .x6_fcheck = ecn_check,
  116. .x6_options = ecn_opts,
  117. };
  118. void _init(void)
  119. {
  120. xtables_register_match(&ecn_mt_reg);
  121. }