/release/src/router/iptables/extensions/libipt_ECN.c

https://gitlab.com/envieidoc/tomato · C · 185 lines · 151 code · 22 blank · 12 comment · 29 complexity · 1e62024c1b906ea6e9a4672cca18157a MD5 · raw file

  1. /* Shared library add-on to iptables for ECN, $Version$
  2. *
  3. * (C) 2002 by Harald Welte <laforge@gnumonks.org>
  4. *
  5. * This program is distributed under the terms of GNU GPL v2, 1991
  6. *
  7. * libipt_ECN.c borrowed heavily from libipt_DSCP.c
  8. *
  9. * $Id: libipt_ECN.c 3507 2004-12-28 13:11:59Z /C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=rusty/emailAddress=rusty@netfilter.org $
  10. */
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <stdlib.h>
  14. #include <getopt.h>
  15. #include <iptables.h>
  16. #include <linux/netfilter_ipv4/ip_tables.h>
  17. #include <linux/netfilter_ipv4/ipt_ECN.h>
  18. static void init(struct ipt_entry_target *t, unsigned int *nfcache)
  19. {
  20. }
  21. static void help(void)
  22. {
  23. printf(
  24. "ECN target v%s options\n"
  25. " --ecn-tcp-remove Remove all ECN bits from TCP header\n",
  26. IPTABLES_VERSION);
  27. }
  28. #if 0
  29. "ECN target v%s EXPERIMENTAL options (use with extreme care!)\n"
  30. " --ecn-ip-ect Set the IPv4 ECT codepoint (0 to 3)\n"
  31. " --ecn-tcp-cwr Set the IPv4 CWR bit (0 or 1)\n"
  32. " --ecn-tcp-ece Set the IPv4 ECE bit (0 or 1)\n",
  33. #endif
  34. static struct option opts[] = {
  35. { "ecn-tcp-remove", 0, 0, 'F' },
  36. { "ecn-tcp-cwr", 1, 0, 'G' },
  37. { "ecn-tcp-ece", 1, 0, 'H' },
  38. { "ecn-ip-ect", 1, 0, '9' },
  39. { 0 }
  40. };
  41. static int
  42. parse(int c, char **argv, int invert, unsigned int *flags,
  43. const struct ipt_entry *entry,
  44. struct ipt_entry_target **target)
  45. {
  46. unsigned int result;
  47. struct ipt_ECN_info *einfo
  48. = (struct ipt_ECN_info *)(*target)->data;
  49. switch (c) {
  50. case 'F':
  51. if (*flags)
  52. exit_error(PARAMETER_PROBLEM,
  53. "ECN target: Only use --ecn-tcp-remove ONCE!");
  54. einfo->operation = IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR;
  55. einfo->proto.tcp.ece = 0;
  56. einfo->proto.tcp.cwr = 0;
  57. *flags = 1;
  58. break;
  59. case 'G':
  60. if (*flags & IPT_ECN_OP_SET_CWR)
  61. exit_error(PARAMETER_PROBLEM,
  62. "ECN target: Only use --ecn-tcp-cwr ONCE!");
  63. if (string_to_number(optarg, 0, 1, &result))
  64. exit_error(PARAMETER_PROBLEM,
  65. "ECN target: Value out of range");
  66. einfo->operation |= IPT_ECN_OP_SET_CWR;
  67. einfo->proto.tcp.cwr = result;
  68. *flags |= IPT_ECN_OP_SET_CWR;
  69. break;
  70. case 'H':
  71. if (*flags & IPT_ECN_OP_SET_ECE)
  72. exit_error(PARAMETER_PROBLEM,
  73. "ECN target: Only use --ecn-tcp-ece ONCE!");
  74. if (string_to_number(optarg, 0, 1, &result))
  75. exit_error(PARAMETER_PROBLEM,
  76. "ECN target: Value out of range");
  77. einfo->operation |= IPT_ECN_OP_SET_ECE;
  78. einfo->proto.tcp.ece = result;
  79. *flags |= IPT_ECN_OP_SET_ECE;
  80. break;
  81. case '9':
  82. if (*flags & IPT_ECN_OP_SET_IP)
  83. exit_error(PARAMETER_PROBLEM,
  84. "ECN target: Only use --ecn-ip-ect ONCE!");
  85. if (string_to_number(optarg, 0, 3, &result))
  86. exit_error(PARAMETER_PROBLEM,
  87. "ECN target: Value out of range");
  88. einfo->operation |= IPT_ECN_OP_SET_IP;
  89. einfo->ip_ect = result;
  90. *flags |= IPT_ECN_OP_SET_IP;
  91. break;
  92. default:
  93. return 0;
  94. }
  95. return 1;
  96. }
  97. static void
  98. final_check(unsigned int flags)
  99. {
  100. if (!flags)
  101. exit_error(PARAMETER_PROBLEM,
  102. "ECN target: Parameter --ecn-tcp-remove is required");
  103. }
  104. /* Prints out the targinfo. */
  105. static void
  106. print(const struct ipt_ip *ip,
  107. const struct ipt_entry_target *target,
  108. int numeric)
  109. {
  110. const struct ipt_ECN_info *einfo =
  111. (const struct ipt_ECN_info *)target->data;
  112. printf("ECN ");
  113. if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)
  114. && einfo->proto.tcp.ece == 0
  115. && einfo->proto.tcp.cwr == 0)
  116. printf("TCP remove ");
  117. else {
  118. if (einfo->operation & IPT_ECN_OP_SET_ECE)
  119. printf("ECE=%u ", einfo->proto.tcp.ece);
  120. if (einfo->operation & IPT_ECN_OP_SET_CWR)
  121. printf("CWR=%u ", einfo->proto.tcp.cwr);
  122. if (einfo->operation & IPT_ECN_OP_SET_IP)
  123. printf("ECT codepoint=%u ", einfo->ip_ect);
  124. }
  125. }
  126. /* Saves the union ipt_targinfo in parsable form to stdout. */
  127. static void
  128. save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
  129. {
  130. const struct ipt_ECN_info *einfo =
  131. (const struct ipt_ECN_info *)target->data;
  132. if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)
  133. && einfo->proto.tcp.ece == 0
  134. && einfo->proto.tcp.cwr == 0)
  135. printf("--ecn-tcp-remove ");
  136. else {
  137. if (einfo->operation & IPT_ECN_OP_SET_ECE)
  138. printf("--ecn-tcp-ece %d ", einfo->proto.tcp.ece);
  139. if (einfo->operation & IPT_ECN_OP_SET_CWR)
  140. printf("--ecn-tcp-cwr %d ", einfo->proto.tcp.cwr);
  141. if (einfo->operation & IPT_ECN_OP_SET_IP)
  142. printf("--ecn-ip-ect %d ", einfo->ip_ect);
  143. }
  144. }
  145. static
  146. struct iptables_target ecn = {
  147. .next = NULL,
  148. .name = "ECN",
  149. .version = IPTABLES_VERSION,
  150. .size = IPT_ALIGN(sizeof(struct ipt_ECN_info)),
  151. .userspacesize = IPT_ALIGN(sizeof(struct ipt_ECN_info)),
  152. .help = &help,
  153. .init = &init,
  154. .parse = &parse,
  155. .final_check = &final_check,
  156. .print = &print,
  157. .save = &save,
  158. .extra_opts = opts
  159. };
  160. void _init(void)
  161. {
  162. register_target(&ecn);
  163. }