libipt_ECN.c revision 4ac9fddb50eb4898f145d6daf14cbf97702ee763
1385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte/* Shared library add-on to iptables for ECN, $Version$ 2385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte * 3385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte * (C) 2002 by Harald Welte <laforge@gnumonks.org> 4385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte * 5385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte * This program is distributed under the terms of GNU GPL v2, 1991 6385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte * 7385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte * libipt_ECN.c borrowed heavily from libipt_DSCP.c 8385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte * 94ac9fddb50eb4898f145d6daf14cbf97702ee763Harald Welte * $Id: libipt_ECN.c,v 1.11 2002/08/07 10:04:42 laforge Exp $ 10385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte */ 11385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte#include <stdio.h> 12385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte#include <string.h> 13385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte#include <stdlib.h> 14385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte#include <getopt.h> 15385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 16385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte#include <iptables.h> 17385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte#include <linux/netfilter_ipv4/ip_tables.h> 18385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte#include <linux/netfilter_ipv4/ipt_ECN.h> 19385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 20385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Weltestatic void init(struct ipt_entry_target *t, unsigned int *nfcache) 21385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte{ 22385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte} 23385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 24385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Weltestatic void help(void) 25385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte{ 26385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte printf( 271c8fa733e6092029d97bc5b2b6a4cb13b513f2f0Harald Welte"ECN target v%s options\n" 2831d12a598c80f609e68550cf043b1c6b2fd0e35eHarald Welte" --ecn-tcp-remove Remove all ECN bits from TCP header\n", 29e0f47ada0d9b447333ef9f4ece4cc32438ab989aHarald Welte IPTABLES_VERSION); 3031d12a598c80f609e68550cf043b1c6b2fd0e35eHarald Welte} 3131d12a598c80f609e68550cf043b1c6b2fd0e35eHarald Welte 3231d12a598c80f609e68550cf043b1c6b2fd0e35eHarald Welte#if 0 331c8fa733e6092029d97bc5b2b6a4cb13b513f2f0Harald Welte"ECN target v%s EXPERIMENTAL options (use with extreme care!)\n" 34c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte" --ecn-ip-ect Set the IPv4 ECT codepoint (0 to 3)\n" 35c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte" --ecn-tcp-cwr Set the IPv4 CWR bit (0 or 1)\n" 3692cad5f4a349daac294332b8f8f696b43c55d3fcHarald Welte" --ecn-tcp-ece Set the IPv4 ECE bit (0 or 1)\n", 3731d12a598c80f609e68550cf043b1c6b2fd0e35eHarald Welte#endif 3831d12a598c80f609e68550cf043b1c6b2fd0e35eHarald Welte 39385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 40385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Weltestatic struct option opts[] = { 41c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte { "ecn-tcp-remove", 0, 0, 'F' }, 42c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte { "ecn-tcp-cwr", 1, 0, 'G' }, 43c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte { "ecn-tcp-ece", 1, 0, 'H' }, 44c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte { "ecn-ip-ect", 1, 0, '9' }, 45385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte { 0 } 46385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte}; 47385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 48385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Weltestatic int 49385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welteparse(int c, char **argv, int invert, unsigned int *flags, 50385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte const struct ipt_entry *entry, 51385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte struct ipt_entry_target **target) 52385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte{ 53c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte unsigned int result; 545a15c9a8b29871fc3246ed91423f271041a87c21Harald Welte struct ipt_ECN_info *einfo 55385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte = (struct ipt_ECN_info *)(*target)->data; 56385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 57385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte switch (c) { 58385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte case 'F': 59385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte if (*flags) 60385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte exit_error(PARAMETER_PROBLEM, 61c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte "ECN target: Only use --ecn-tcp-remove ONCE!"); 62c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte einfo->operation = IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR; 63c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte einfo->proto.tcp.ece = 0; 64c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte einfo->proto.tcp.cwr = 0; 65385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte *flags = 1; 66385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte break; 67c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte case 'G': 68c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte if (*flags & IPT_ECN_OP_SET_CWR) 69c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte exit_error(PARAMETER_PROBLEM, 70c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte "ECN target: Only use --ecn-tcp-cwr ONCE!"); 71c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte if (string_to_number(optarg, 0, 1, &result)) 72c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte exit_error(PARAMETER_PROBLEM, 73c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte "ECN target: Value out of range"); 74c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte einfo->operation |= IPT_ECN_OP_SET_CWR; 75c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte einfo->proto.tcp.cwr = result; 76c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte *flags |= IPT_ECN_OP_SET_CWR; 77c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte break; 78c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte case 'H': 79c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte if (*flags & IPT_ECN_OP_SET_ECE) 80c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte exit_error(PARAMETER_PROBLEM, 81c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte "ECN target: Only use --ecn-tcp-ece ONCE!"); 82c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte if (string_to_number(optarg, 0, 1, &result)) 83c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte exit_error(PARAMETER_PROBLEM, 84c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte "ECN target: Value out of range"); 85c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte einfo->operation |= IPT_ECN_OP_SET_ECE; 86c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte einfo->proto.tcp.ece = result; 87c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte *flags |= IPT_ECN_OP_SET_ECE; 88c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte break; 89c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte case '9': 90c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte if (*flags & IPT_ECN_OP_SET_IP) 91c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte exit_error(PARAMETER_PROBLEM, 92c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte "ECN target: Only use --ecn-ip-ect ONCE!"); 93c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte if (string_to_number(optarg, 0, 3, &result)) 94c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte exit_error(PARAMETER_PROBLEM, 95c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte "ECN target: Value out of range"); 96c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte einfo->operation |= IPT_ECN_OP_SET_IP; 97c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte einfo->ip_ect = result; 98c05c44fc6018fcd94df499c981d846ff20882c4cHarald Welte *flags |= IPT_ECN_OP_SET_IP; 99c05c44fc6018fcd94df499c981d846ff20882c4cHarald Welte break; 100385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte default: 101385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte return 0; 102385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte } 103385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 104385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte return 1; 105385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte} 106385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 107385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Weltestatic void 108385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Weltefinal_check(unsigned int flags) 109385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte{ 110385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte if (!flags) 111385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte exit_error(PARAMETER_PROBLEM, 1124ac9fddb50eb4898f145d6daf14cbf97702ee763Harald Welte "ECN target: Parameter --ecn-tcp-remove is required"); 113385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte} 114385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 115385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte/* Prints out the targinfo. */ 116385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Weltestatic void 117385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welteprint(const struct ipt_ip *ip, 118385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte const struct ipt_entry_target *target, 119385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte int numeric) 120385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte{ 121385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte const struct ipt_ECN_info *einfo = 122385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte (const struct ipt_ECN_info *)target->data; 123385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 124385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte printf("ECN "); 125385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 1267b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR) 1277b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte && einfo->proto.tcp.ece == 0 1287b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte && einfo->proto.tcp.cwr == 0) 1297b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte printf("TCP remove "); 1307b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte else { 1317b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte if (einfo->operation & IPT_ECN_OP_SET_ECE) 132c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte printf("ECE=%u ", einfo->proto.tcp.ece); 1337b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte 1347b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte if (einfo->operation & IPT_ECN_OP_SET_CWR) 135c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte printf("CWR=%u ", einfo->proto.tcp.cwr); 1367b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte 1377b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte if (einfo->operation & IPT_ECN_OP_SET_IP) 138c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte printf("ECT codepoint=%u ", einfo->ip_ect); 139385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte } 140385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte} 141385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 142385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte/* Saves the union ipt_targinfo in parsable form to stdout. */ 143385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Weltestatic void 144385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Weltesave(const struct ipt_ip *ip, const struct ipt_entry_target *target) 145385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte{ 146385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte const struct ipt_ECN_info *einfo = 147385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte (const struct ipt_ECN_info *)target->data; 148385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 1497b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR) 1507b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte && einfo->proto.tcp.ece == 0 1517b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte && einfo->proto.tcp.cwr == 0) 1527b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte printf("--ecn-tcp-remove "); 1537b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte else { 154c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte 1557b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte if (einfo->operation & IPT_ECN_OP_SET_ECE) 1567b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte printf("--ecn-tcp-ece %d ", einfo->proto.tcp.ece); 1577b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte 1587b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte if (einfo->operation & IPT_ECN_OP_SET_CWR) 1597b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte printf("--ecn-tcp-cwr %d ", einfo->proto.tcp.cwr); 160c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte 1617b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte if (einfo->operation & IPT_ECN_OP_SET_IP) 1627b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte printf("--ecn-ip-ect %d ", einfo->ip_ect); 163385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte } 164385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte} 165385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 166385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Weltestatic 167385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Weltestruct iptables_target ecn 168385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte= { NULL, 169385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte "ECN", 17080fe35d6339b53a12ddaec41885613e4e37ed031Harald Welte IPTABLES_VERSION, 171385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte IPT_ALIGN(sizeof(struct ipt_ECN_info)), 172385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte IPT_ALIGN(sizeof(struct ipt_ECN_info)), 173385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte &help, 174385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte &init, 175385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte &parse, 176385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte &final_check, 177385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte &print, 178385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte &save, 179385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte opts 180385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte}; 181385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 182385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Weltevoid _init(void) 183385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte{ 184385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte register_target(&ecn); 185385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte} 186