libipt_ECN.c revision c980a240bad8f8995805df3bfdfb18180dd08d03
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.3 2002/04/10 13:12:53 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 options\n" 28" --ecn-tcp-remove Remove all ECN bits which may be present\n" 29" in the IPv4 header\n" 30"ECN target EXPERIMENTAL options (use with extreme care!)\n" 31" --ecn-ip-ect Set the IPv4 ECT codepoint (0 to 3)\n" 32" --ecn-tcp-cwr Set the IPv4 CWR bit (0 or 1)\n" 33" --ecn-tcp-ece Set the IPv4 CWR bit (0 or 1)\n" 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 default: 96 return 0; 97 } 98 99 return 1; 100} 101 102static void 103final_check(unsigned int flags) 104{ 105 if (!flags) 106 exit_error(PARAMETER_PROBLEM, 107 "ECN target: Parameter --ecn-remove is required"); 108} 109 110/* Prints out the targinfo. */ 111static void 112print(const struct ipt_ip *ip, 113 const struct ipt_entry_target *target, 114 int numeric) 115{ 116 const struct ipt_ECN_info *einfo = 117 (const struct ipt_ECN_info *)target->data; 118 119 printf("ECN "); 120 121 switch (einfo->operation) { 122 case IPT_ECN_OP_SET_ECE: 123 printf("ECE=%u ", einfo->proto.tcp.ece); 124 break; 125 case IPT_ECN_OP_SET_CWR: 126 printf("CWR=%u ", einfo->proto.tcp.cwr); 127 break; 128 case IPT_ECN_OP_SET_IP: 129 printf("ECT codepoint=%u ", einfo->ip_ect); 130 default: 131 printf("unsupported_ecn_operation "); 132 break; 133 } 134} 135 136/* Saves the union ipt_targinfo in parsable form to stdout. */ 137static void 138save(const struct ipt_ip *ip, const struct ipt_entry_target *target) 139{ 140 const struct ipt_ECN_info *einfo = 141 (const struct ipt_ECN_info *)target->data; 142 143 if (einfo->operation & IPT_ECN_OP_SET_ECE) { 144 printf("--ecn-tcp-ece %d ", einfo->proto.tcp.ece); 145 } 146 147 if (einfo->operation & IPT_ECN_OP_SET_CWR) { 148 printf("--ecn-tcp-cwr %d ", einfo->proto.tcp.cwr); 149 } 150 151 if (einfo->operation & IPT_ECN_OP_SET_IP) { 152 printf("--ecn-ip-ect %d ", einfo->ip_ect); 153 } 154} 155 156static 157struct iptables_target ecn 158= { NULL, 159 "ECN", 160 NETFILTER_VERSION, 161 IPT_ALIGN(sizeof(struct ipt_ECN_info)), 162 IPT_ALIGN(sizeof(struct ipt_ECN_info)), 163 &help, 164 &init, 165 &parse, 166 &final_check, 167 &print, 168 &save, 169 opts 170}; 171 172void _init(void) 173{ 174 register_target(&ecn); 175} 176