libipt_ECN.c revision 9ee386a1b6d7704b259460152c959ab0e79e02aa
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$ 10 */ 11#include <stdio.h> 12#include <string.h> 13#include <stdlib.h> 14#include <getopt.h> 15 16#include <iptables.h> 17#include <linux/netfilter_ipv4/ip_tables.h> 18#include <linux/netfilter_ipv4/ipt_ECN.h> 19 20static void ECN_help(void) 21{ 22 printf( 23"ECN target v%s options\n" 24" --ecn-tcp-remove Remove all ECN bits from TCP header\n", 25 IPTABLES_VERSION); 26} 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 35 36static const struct option ECN_opts[] = { 37 { "ecn-tcp-remove", 0, NULL, 'F' }, 38 { "ecn-tcp-cwr", 1, NULL, 'G' }, 39 { "ecn-tcp-ece", 1, NULL, 'H' }, 40 { "ecn-ip-ect", 1, NULL, '9' }, 41 { .name = NULL } 42}; 43 44static int ECN_parse(int c, char **argv, int invert, unsigned int *flags, 45 const void *entry, struct xt_entry_target **target) 46{ 47 unsigned int result; 48 struct ipt_ECN_info *einfo 49 = (struct ipt_ECN_info *)(*target)->data; 50 51 switch (c) { 52 case 'F': 53 if (*flags) 54 exit_error(PARAMETER_PROBLEM, 55 "ECN target: Only use --ecn-tcp-remove ONCE!"); 56 einfo->operation = IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR; 57 einfo->proto.tcp.ece = 0; 58 einfo->proto.tcp.cwr = 0; 59 *flags = 1; 60 break; 61 case 'G': 62 if (*flags & IPT_ECN_OP_SET_CWR) 63 exit_error(PARAMETER_PROBLEM, 64 "ECN target: Only use --ecn-tcp-cwr ONCE!"); 65 if (string_to_number(optarg, 0, 1, &result)) 66 exit_error(PARAMETER_PROBLEM, 67 "ECN target: Value out of range"); 68 einfo->operation |= IPT_ECN_OP_SET_CWR; 69 einfo->proto.tcp.cwr = result; 70 *flags |= IPT_ECN_OP_SET_CWR; 71 break; 72 case 'H': 73 if (*flags & IPT_ECN_OP_SET_ECE) 74 exit_error(PARAMETER_PROBLEM, 75 "ECN target: Only use --ecn-tcp-ece ONCE!"); 76 if (string_to_number(optarg, 0, 1, &result)) 77 exit_error(PARAMETER_PROBLEM, 78 "ECN target: Value out of range"); 79 einfo->operation |= IPT_ECN_OP_SET_ECE; 80 einfo->proto.tcp.ece = result; 81 *flags |= IPT_ECN_OP_SET_ECE; 82 break; 83 case '9': 84 if (*flags & IPT_ECN_OP_SET_IP) 85 exit_error(PARAMETER_PROBLEM, 86 "ECN target: Only use --ecn-ip-ect ONCE!"); 87 if (string_to_number(optarg, 0, 3, &result)) 88 exit_error(PARAMETER_PROBLEM, 89 "ECN target: Value out of range"); 90 einfo->operation |= IPT_ECN_OP_SET_IP; 91 einfo->ip_ect = result; 92 *flags |= IPT_ECN_OP_SET_IP; 93 break; 94 default: 95 return 0; 96 } 97 98 return 1; 99} 100 101static void ECN_check(unsigned int flags) 102{ 103 if (!flags) 104 exit_error(PARAMETER_PROBLEM, 105 "ECN target: Parameter --ecn-tcp-remove is required"); 106} 107 108/* Prints out the targinfo. */ 109static void ECN_print(const void *ip, const struct xt_entry_target *target, 110 int numeric) 111{ 112 const struct ipt_ECN_info *einfo = 113 (const struct ipt_ECN_info *)target->data; 114 115 printf("ECN "); 116 117 if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR) 118 && einfo->proto.tcp.ece == 0 119 && einfo->proto.tcp.cwr == 0) 120 printf("TCP remove "); 121 else { 122 if (einfo->operation & IPT_ECN_OP_SET_ECE) 123 printf("ECE=%u ", einfo->proto.tcp.ece); 124 125 if (einfo->operation & IPT_ECN_OP_SET_CWR) 126 printf("CWR=%u ", einfo->proto.tcp.cwr); 127 128 if (einfo->operation & IPT_ECN_OP_SET_IP) 129 printf("ECT codepoint=%u ", einfo->ip_ect); 130 } 131} 132 133/* Saves the union ipt_targinfo in parsable form to stdout. */ 134static void ECN_save(const void *ip, const struct xt_entry_target *target) 135{ 136 const struct ipt_ECN_info *einfo = 137 (const struct ipt_ECN_info *)target->data; 138 139 if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR) 140 && einfo->proto.tcp.ece == 0 141 && einfo->proto.tcp.cwr == 0) 142 printf("--ecn-tcp-remove "); 143 else { 144 145 if (einfo->operation & IPT_ECN_OP_SET_ECE) 146 printf("--ecn-tcp-ece %d ", einfo->proto.tcp.ece); 147 148 if (einfo->operation & IPT_ECN_OP_SET_CWR) 149 printf("--ecn-tcp-cwr %d ", einfo->proto.tcp.cwr); 150 151 if (einfo->operation & IPT_ECN_OP_SET_IP) 152 printf("--ecn-ip-ect %d ", einfo->ip_ect); 153 } 154} 155 156static struct iptables_target ecn_target = { 157 .name = "ECN", 158 .version = IPTABLES_VERSION, 159 .size = IPT_ALIGN(sizeof(struct ipt_ECN_info)), 160 .userspacesize = IPT_ALIGN(sizeof(struct ipt_ECN_info)), 161 .help = ECN_help, 162 .parse = ECN_parse, 163 .final_check = ECN_check, 164 .print = ECN_print, 165 .save = ECN_save, 166 .extra_opts = ECN_opts, 167}; 168 169void _init(void) 170{ 171 register_target(&ecn_target); 172} 173