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