libipt_ECN.c revision 1829ed482efbc8b390cc760d012b3a4450494e1a
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 <xtables.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 options\n" 24" --ecn-tcp-remove Remove all ECN bits from TCP header\n"); 25} 26 27#if 0 28"ECN target v%s EXPERIMENTAL options (use with extreme care!)\n" 29" --ecn-ip-ect Set the IPv4 ECT codepoint (0 to 3)\n" 30" --ecn-tcp-cwr Set the IPv4 CWR bit (0 or 1)\n" 31" --ecn-tcp-ece Set the IPv4 ECE bit (0 or 1)\n", 32#endif 33 34 35static const struct option ECN_opts[] = { 36 { "ecn-tcp-remove", 0, NULL, 'F' }, 37 { "ecn-tcp-cwr", 1, NULL, 'G' }, 38 { "ecn-tcp-ece", 1, NULL, 'H' }, 39 { "ecn-ip-ect", 1, NULL, '9' }, 40 { .name = NULL } 41}; 42 43static int ECN_parse(int c, char **argv, int invert, unsigned int *flags, 44 const void *entry, struct xt_entry_target **target) 45{ 46 unsigned int result; 47 struct ipt_ECN_info *einfo 48 = (struct ipt_ECN_info *)(*target)->data; 49 50 switch (c) { 51 case 'F': 52 if (*flags) 53 xtables_error(PARAMETER_PROBLEM, 54 "ECN target: Only use --ecn-tcp-remove ONCE!"); 55 einfo->operation = IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR; 56 einfo->proto.tcp.ece = 0; 57 einfo->proto.tcp.cwr = 0; 58 *flags = 1; 59 break; 60 case 'G': 61 if (*flags & IPT_ECN_OP_SET_CWR) 62 xtables_error(PARAMETER_PROBLEM, 63 "ECN target: Only use --ecn-tcp-cwr ONCE!"); 64 if (!xtables_strtoui(optarg, NULL, &result, 0, 1)) 65 xtables_error(PARAMETER_PROBLEM, 66 "ECN target: Value out of range"); 67 einfo->operation |= IPT_ECN_OP_SET_CWR; 68 einfo->proto.tcp.cwr = result; 69 *flags |= IPT_ECN_OP_SET_CWR; 70 break; 71 case 'H': 72 if (*flags & IPT_ECN_OP_SET_ECE) 73 xtables_error(PARAMETER_PROBLEM, 74 "ECN target: Only use --ecn-tcp-ece ONCE!"); 75 if (!xtables_strtoui(optarg, NULL, &result, 0, 1)) 76 xtables_error(PARAMETER_PROBLEM, 77 "ECN target: Value out of range"); 78 einfo->operation |= IPT_ECN_OP_SET_ECE; 79 einfo->proto.tcp.ece = result; 80 *flags |= IPT_ECN_OP_SET_ECE; 81 break; 82 case '9': 83 if (*flags & IPT_ECN_OP_SET_IP) 84 xtables_error(PARAMETER_PROBLEM, 85 "ECN target: Only use --ecn-ip-ect ONCE!"); 86 if (!xtables_strtoui(optarg, NULL, &result, 0, 3)) 87 xtables_error(PARAMETER_PROBLEM, 88 "ECN target: Value out of range"); 89 einfo->operation |= IPT_ECN_OP_SET_IP; 90 einfo->ip_ect = result; 91 *flags |= IPT_ECN_OP_SET_IP; 92 break; 93 default: 94 return 0; 95 } 96 97 return 1; 98} 99 100static void ECN_check(unsigned int flags) 101{ 102 if (!flags) 103 xtables_error(PARAMETER_PROBLEM, 104 "ECN target: Parameter --ecn-tcp-remove is required"); 105} 106 107static void ECN_print(const void *ip, const struct xt_entry_target *target, 108 int numeric) 109{ 110 const struct ipt_ECN_info *einfo = 111 (const struct ipt_ECN_info *)target->data; 112 113 printf("ECN "); 114 115 if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR) 116 && einfo->proto.tcp.ece == 0 117 && einfo->proto.tcp.cwr == 0) 118 printf("TCP remove "); 119 else { 120 if (einfo->operation & IPT_ECN_OP_SET_ECE) 121 printf("ECE=%u ", einfo->proto.tcp.ece); 122 123 if (einfo->operation & IPT_ECN_OP_SET_CWR) 124 printf("CWR=%u ", einfo->proto.tcp.cwr); 125 126 if (einfo->operation & IPT_ECN_OP_SET_IP) 127 printf("ECT codepoint=%u ", einfo->ip_ect); 128 } 129} 130 131static void ECN_save(const void *ip, const struct xt_entry_target *target) 132{ 133 const struct ipt_ECN_info *einfo = 134 (const struct ipt_ECN_info *)target->data; 135 136 if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR) 137 && einfo->proto.tcp.ece == 0 138 && einfo->proto.tcp.cwr == 0) 139 printf("--ecn-tcp-remove "); 140 else { 141 142 if (einfo->operation & IPT_ECN_OP_SET_ECE) 143 printf("--ecn-tcp-ece %d ", einfo->proto.tcp.ece); 144 145 if (einfo->operation & IPT_ECN_OP_SET_CWR) 146 printf("--ecn-tcp-cwr %d ", einfo->proto.tcp.cwr); 147 148 if (einfo->operation & IPT_ECN_OP_SET_IP) 149 printf("--ecn-ip-ect %d ", einfo->ip_ect); 150 } 151} 152 153static struct xtables_target ecn_tg_reg = { 154 .name = "ECN", 155 .version = XTABLES_VERSION, 156 .family = NFPROTO_IPV4, 157 .size = XT_ALIGN(sizeof(struct ipt_ECN_info)), 158 .userspacesize = XT_ALIGN(sizeof(struct ipt_ECN_info)), 159 .help = ECN_help, 160 .parse = ECN_parse, 161 .final_check = ECN_check, 162 .print = ECN_print, 163 .save = ECN_save, 164 .extra_opts = ECN_opts, 165}; 166 167void _init(void) 168{ 169 xtables_register_target(&ecn_tg_reg); 170} 171