libipt_ECN.c revision 094f104af71ca859c7c44406baed401659ad9421
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#include <stdbool.h> 10#include <stdio.h> 11#include <string.h> 12#include <stdlib.h> 13#include <getopt.h> 14 15#include <xtables.h> 16#include <linux/netfilter_ipv4/ipt_ECN.h> 17 18static void ECN_help(void) 19{ 20 printf( 21"ECN target options\n" 22" --ecn-tcp-remove Remove all ECN bits from TCP header\n"); 23} 24 25#if 0 26"ECN target v%s EXPERIMENTAL options (use with extreme care!)\n" 27" --ecn-ip-ect Set the IPv4 ECT codepoint (0 to 3)\n" 28" --ecn-tcp-cwr Set the IPv4 CWR bit (0 or 1)\n" 29" --ecn-tcp-ece Set the IPv4 ECE bit (0 or 1)\n", 30#endif 31 32 33static const struct option ECN_opts[] = { 34 {.name = "ecn-tcp-remove", .has_arg = false, .val = 'F'}, 35 {.name = "ecn-tcp-cwr", .has_arg = true, .val = 'G'}, 36 {.name = "ecn-tcp-ece", .has_arg = true, .val = 'H'}, 37 {.name = "ecn-ip-ect", .has_arg = true, .val = '9'}, 38 XT_GETOPT_TABLEEND, 39}; 40 41static int ECN_parse(int c, char **argv, int invert, unsigned int *flags, 42 const void *entry, struct xt_entry_target **target) 43{ 44 unsigned int result; 45 struct ipt_ECN_info *einfo 46 = (struct ipt_ECN_info *)(*target)->data; 47 48 switch (c) { 49 case 'F': 50 if (*flags) 51 xtables_error(PARAMETER_PROBLEM, 52 "ECN target: Only use --ecn-tcp-remove ONCE!"); 53 einfo->operation = IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR; 54 einfo->proto.tcp.ece = 0; 55 einfo->proto.tcp.cwr = 0; 56 *flags |= IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR; 57 break; 58 case 'G': 59 if (*flags & IPT_ECN_OP_SET_CWR) 60 xtables_error(PARAMETER_PROBLEM, 61 "ECN target: Only use --ecn-tcp-cwr ONCE!"); 62 if (!xtables_strtoui(optarg, NULL, &result, 0, 1)) 63 xtables_error(PARAMETER_PROBLEM, 64 "ECN target: Value out of range"); 65 einfo->operation |= IPT_ECN_OP_SET_CWR; 66 einfo->proto.tcp.cwr = result; 67 *flags |= IPT_ECN_OP_SET_CWR; 68 break; 69 case 'H': 70 if (*flags & IPT_ECN_OP_SET_ECE) 71 xtables_error(PARAMETER_PROBLEM, 72 "ECN target: Only use --ecn-tcp-ece ONCE!"); 73 if (!xtables_strtoui(optarg, NULL, &result, 0, 1)) 74 xtables_error(PARAMETER_PROBLEM, 75 "ECN target: Value out of range"); 76 einfo->operation |= IPT_ECN_OP_SET_ECE; 77 einfo->proto.tcp.ece = result; 78 *flags |= IPT_ECN_OP_SET_ECE; 79 break; 80 case '9': 81 if (*flags & IPT_ECN_OP_SET_IP) 82 xtables_error(PARAMETER_PROBLEM, 83 "ECN target: Only use --ecn-ip-ect ONCE!"); 84 if (!xtables_strtoui(optarg, NULL, &result, 0, 3)) 85 xtables_error(PARAMETER_PROBLEM, 86 "ECN target: Value out of range"); 87 einfo->operation |= IPT_ECN_OP_SET_IP; 88 einfo->ip_ect = result; 89 *flags |= IPT_ECN_OP_SET_IP; 90 break; 91 } 92 93 return 1; 94} 95 96static void ECN_check(unsigned int flags) 97{ 98 if (!flags) 99 xtables_error(PARAMETER_PROBLEM, 100 "ECN target: An operation is required"); 101} 102 103static void ECN_print(const void *ip, const struct xt_entry_target *target, 104 int numeric) 105{ 106 const struct ipt_ECN_info *einfo = 107 (const struct ipt_ECN_info *)target->data; 108 109 printf(" ECN"); 110 111 if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR) 112 && einfo->proto.tcp.ece == 0 113 && einfo->proto.tcp.cwr == 0) 114 printf(" TCP remove"); 115 else { 116 if (einfo->operation & IPT_ECN_OP_SET_ECE) 117 printf(" ECE=%u", einfo->proto.tcp.ece); 118 119 if (einfo->operation & IPT_ECN_OP_SET_CWR) 120 printf(" CWR=%u", einfo->proto.tcp.cwr); 121 122 if (einfo->operation & IPT_ECN_OP_SET_IP) 123 printf(" ECT codepoint=%u", einfo->ip_ect); 124 } 125} 126 127static void ECN_save(const void *ip, const struct xt_entry_target *target) 128{ 129 const struct ipt_ECN_info *einfo = 130 (const struct ipt_ECN_info *)target->data; 131 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 138 if (einfo->operation & IPT_ECN_OP_SET_ECE) 139 printf(" --ecn-tcp-ece %d", einfo->proto.tcp.ece); 140 141 if (einfo->operation & IPT_ECN_OP_SET_CWR) 142 printf(" --ecn-tcp-cwr %d", einfo->proto.tcp.cwr); 143 144 if (einfo->operation & IPT_ECN_OP_SET_IP) 145 printf(" --ecn-ip-ect %d", einfo->ip_ect); 146 } 147} 148 149static struct xtables_target ecn_tg_reg = { 150 .name = "ECN", 151 .version = XTABLES_VERSION, 152 .family = NFPROTO_IPV4, 153 .size = XT_ALIGN(sizeof(struct ipt_ECN_info)), 154 .userspacesize = XT_ALIGN(sizeof(struct ipt_ECN_info)), 155 .help = ECN_help, 156 .parse = ECN_parse, 157 .final_check = ECN_check, 158 .print = ECN_print, 159 .save = ECN_save, 160 .extra_opts = ECN_opts, 161}; 162 163void _init(void) 164{ 165 xtables_register_target(&ecn_tg_reg); 166} 167