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.1.1.1 2007/10/11 00:26:49 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 33 34static struct option opts[] = { 35 { "ecn-tcp-remove", 0, 0, 'F' }, 36 { "ecn-tcp-cwr", 1, 0, 'G' }, 37 { "ecn-tcp-ece", 1, 0, 'H' }, 38 { "ecn-ip-ect", 1, 0, '9' }, 39 { 0 } 40}; 41 42static int 43parse(int c, char **argv, int invert, unsigned int *flags, 44 const struct ipt_entry *entry, 45 struct ipt_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 102final_check(unsigned int flags) 103{ 104 if (!flags) 105 exit_error(PARAMETER_PROBLEM, 106 "ECN target: Parameter --ecn-tcp-remove is required"); 107} 108 109/* Prints out the targinfo. */ 110static void 111print(const struct ipt_ip *ip, 112 const struct ipt_entry_target *target, 113 int numeric) 114{ 115 const struct ipt_ECN_info *einfo = 116 (const struct ipt_ECN_info *)target->data; 117 118 printf("ECN "); 119 120 if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR) 121 && einfo->proto.tcp.ece == 0 122 && einfo->proto.tcp.cwr == 0) 123 printf("TCP remove "); 124 else { 125 if (einfo->operation & IPT_ECN_OP_SET_ECE) 126 printf("ECE=%u ", einfo->proto.tcp.ece); 127 128 if (einfo->operation & IPT_ECN_OP_SET_CWR) 129 printf("CWR=%u ", einfo->proto.tcp.cwr); 130 131 if (einfo->operation & IPT_ECN_OP_SET_IP) 132 printf("ECT codepoint=%u ", einfo->ip_ect); 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|IPT_ECN_OP_SET_CWR) 144 && einfo->proto.tcp.ece == 0 145 && einfo->proto.tcp.cwr == 0) 146 printf("--ecn-tcp-remove "); 147 else { 148 149 if (einfo->operation & IPT_ECN_OP_SET_ECE) 150 printf("--ecn-tcp-ece %d ", einfo->proto.tcp.ece); 151 152 if (einfo->operation & IPT_ECN_OP_SET_CWR) 153 printf("--ecn-tcp-cwr %d ", einfo->proto.tcp.cwr); 154 155 if (einfo->operation & IPT_ECN_OP_SET_IP) 156 printf("--ecn-ip-ect %d ", einfo->ip_ect); 157 } 158} 159 160static 161struct iptables_target ecn = { 162 .next = NULL, 163 .name = "ECN", 164 .version = IPTABLES_VERSION, 165 .size = IPT_ALIGN(sizeof(struct ipt_ECN_info)), 166 .userspacesize = IPT_ALIGN(sizeof(struct ipt_ECN_info)), 167 .help = &help, 168 .init = &init, 169 .parse = &parse, 170 .final_check = &final_check, 171 .print = &print, 172 .save = &save, 173 .extra_opts = opts 174}; 175 176void _init(void) 177{ 178 register_target(&ecn); 179} 180