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