libipt_ECN.c revision e0f47ada0d9b447333ef9f4ece4cc32438ab989a
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,v 1.10 2002/08/06 18:46:18 laforge Exp $ 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 init(struct ipt_entry_target *t, unsigned int *nfcache) 21{ 22} 23 24static void help(void) 25{ 26 printf( 27"ECN target v%s options\n" 28" --ecn-tcp-remove Remove all ECN bits from TCP header\n", 29 IPTABLES_VERSION); 30} 31 32#if 0 33"ECN target v%s EXPERIMENTAL options (use with extreme care!)\n" 34" --ecn-ip-ect Set the IPv4 ECT codepoint (0 to 3)\n" 35" --ecn-tcp-cwr Set the IPv4 CWR bit (0 or 1)\n" 36" --ecn-tcp-ece Set the IPv4 ECE bit (0 or 1)\n", 37#endif 38 39 40static struct option opts[] = { 41 { "ecn-tcp-remove", 0, 0, 'F' }, 42 { "ecn-tcp-cwr", 1, 0, 'G' }, 43 { "ecn-tcp-ece", 1, 0, 'H' }, 44 { "ecn-ip-ect", 1, 0, '9' }, 45 { 0 } 46}; 47 48static int 49parse(int c, char **argv, int invert, unsigned int *flags, 50 const struct ipt_entry *entry, 51 struct ipt_entry_target **target) 52{ 53 unsigned int result; 54 struct ipt_ECN_info *einfo 55 = (struct ipt_ECN_info *)(*target)->data; 56 57 switch (c) { 58 case 'F': 59 if (*flags) 60 exit_error(PARAMETER_PROBLEM, 61 "ECN target: Only use --ecn-tcp-remove ONCE!"); 62 einfo->operation = IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR; 63 einfo->proto.tcp.ece = 0; 64 einfo->proto.tcp.cwr = 0; 65 *flags = 1; 66 break; 67 case 'G': 68 if (*flags & IPT_ECN_OP_SET_CWR) 69 exit_error(PARAMETER_PROBLEM, 70 "ECN target: Only use --ecn-tcp-cwr ONCE!"); 71 if (string_to_number(optarg, 0, 1, &result)) 72 exit_error(PARAMETER_PROBLEM, 73 "ECN target: Value out of range"); 74 einfo->operation |= IPT_ECN_OP_SET_CWR; 75 einfo->proto.tcp.cwr = result; 76 *flags |= IPT_ECN_OP_SET_CWR; 77 break; 78 case 'H': 79 if (*flags & IPT_ECN_OP_SET_ECE) 80 exit_error(PARAMETER_PROBLEM, 81 "ECN target: Only use --ecn-tcp-ece ONCE!"); 82 if (string_to_number(optarg, 0, 1, &result)) 83 exit_error(PARAMETER_PROBLEM, 84 "ECN target: Value out of range"); 85 einfo->operation |= IPT_ECN_OP_SET_ECE; 86 einfo->proto.tcp.ece = result; 87 *flags |= IPT_ECN_OP_SET_ECE; 88 break; 89 case '9': 90 if (*flags & IPT_ECN_OP_SET_IP) 91 exit_error(PARAMETER_PROBLEM, 92 "ECN target: Only use --ecn-ip-ect ONCE!"); 93 if (string_to_number(optarg, 0, 3, &result)) 94 exit_error(PARAMETER_PROBLEM, 95 "ECN target: Value out of range"); 96 einfo->operation |= IPT_ECN_OP_SET_IP; 97 einfo->ip_ect = result; 98 *flags |= IPT_ECN_OP_SET_IP; 99 break; 100 default: 101 return 0; 102 } 103 104 return 1; 105} 106 107static void 108final_check(unsigned int flags) 109{ 110 if (!flags) 111 exit_error(PARAMETER_PROBLEM, 112 "ECN target: Parameter --ecn-remove is required"); 113} 114 115/* Prints out the targinfo. */ 116static void 117print(const struct ipt_ip *ip, 118 const struct ipt_entry_target *target, 119 int numeric) 120{ 121 const struct ipt_ECN_info *einfo = 122 (const struct ipt_ECN_info *)target->data; 123 124 printf("ECN "); 125 126 if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR) 127 && einfo->proto.tcp.ece == 0 128 && einfo->proto.tcp.cwr == 0) 129 printf("TCP remove "); 130 else { 131 if (einfo->operation & IPT_ECN_OP_SET_ECE) 132 printf("ECE=%u ", einfo->proto.tcp.ece); 133 134 if (einfo->operation & IPT_ECN_OP_SET_CWR) 135 printf("CWR=%u ", einfo->proto.tcp.cwr); 136 137 if (einfo->operation & IPT_ECN_OP_SET_IP) 138 printf("ECT codepoint=%u ", einfo->ip_ect); 139 } 140} 141 142/* Saves the union ipt_targinfo in parsable form to stdout. */ 143static void 144save(const struct ipt_ip *ip, const struct ipt_entry_target *target) 145{ 146 const struct ipt_ECN_info *einfo = 147 (const struct ipt_ECN_info *)target->data; 148 149 if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR) 150 && einfo->proto.tcp.ece == 0 151 && einfo->proto.tcp.cwr == 0) 152 printf("--ecn-tcp-remove "); 153 else { 154 155 if (einfo->operation & IPT_ECN_OP_SET_ECE) 156 printf("--ecn-tcp-ece %d ", einfo->proto.tcp.ece); 157 158 if (einfo->operation & IPT_ECN_OP_SET_CWR) 159 printf("--ecn-tcp-cwr %d ", einfo->proto.tcp.cwr); 160 161 if (einfo->operation & IPT_ECN_OP_SET_IP) 162 printf("--ecn-ip-ect %d ", einfo->ip_ect); 163 } 164} 165 166static 167struct iptables_target ecn 168= { NULL, 169 "ECN", 170 IPTABLES_VERSION, 171 IPT_ALIGN(sizeof(struct ipt_ECN_info)), 172 IPT_ALIGN(sizeof(struct ipt_ECN_info)), 173 &help, 174 &init, 175 &parse, 176 &final_check, 177 &print, 178 &save, 179 opts 180}; 181 182void _init(void) 183{ 184 register_target(&ecn); 185} 186