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 */ 9385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte#include <stdio.h> 105d9678ad3eabc34ac40dfe055d7f6a8e44445a5aJan Engelhardt#include <xtables.h> 11385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte#include <linux/netfilter_ipv4/ipt_ECN.h> 12385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 13e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardtenum { 14e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt O_ECN_TCP_REMOVE = 0, 15e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt O_ECN_TCP_CWR, 16e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt O_ECN_TCP_ECE, 17e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt O_ECN_IP_ECT, 18e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt F_ECN_TCP_REMOVE = 1 << O_ECN_TCP_REMOVE, 19e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt F_ECN_TCP_CWR = 1 << O_ECN_TCP_CWR, 20e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt F_ECN_TCP_ECE = 1 << O_ECN_TCP_ECE, 21e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt}; 22e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt 231d5b63d12984d12c8d87242179855e17657be16dJan Engelhardtstatic void ECN_help(void) 24385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte{ 25385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte printf( 268b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"ECN target options\n" 278b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt" --ecn-tcp-remove Remove all ECN bits from TCP header\n"); 2831d12a598c80f609e68550cf043b1c6b2fd0e35eHarald Welte} 2931d12a598c80f609e68550cf043b1c6b2fd0e35eHarald Welte 3031d12a598c80f609e68550cf043b1c6b2fd0e35eHarald Welte#if 0 311c8fa733e6092029d97bc5b2b6a4cb13b513f2f0Harald Welte"ECN target v%s EXPERIMENTAL options (use with extreme care!)\n" 32c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte" --ecn-ip-ect Set the IPv4 ECT codepoint (0 to 3)\n" 33c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte" --ecn-tcp-cwr Set the IPv4 CWR bit (0 or 1)\n" 3492cad5f4a349daac294332b8f8f696b43c55d3fcHarald Welte" --ecn-tcp-ece Set the IPv4 ECE bit (0 or 1)\n", 3531d12a598c80f609e68550cf043b1c6b2fd0e35eHarald Welte#endif 3631d12a598c80f609e68550cf043b1c6b2fd0e35eHarald Welte 37e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardtstatic const struct xt_option_entry ECN_opts[] = { 38e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt {.name = "ecn-tcp-remove", .id = O_ECN_TCP_REMOVE, .type = XTTYPE_NONE, 39e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt .excl = F_ECN_TCP_CWR | F_ECN_TCP_ECE}, 40e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt {.name = "ecn-tcp-cwr", .id = O_ECN_TCP_CWR, .type = XTTYPE_UINT8, 41e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt .min = 0, .max = 1, .excl = F_ECN_TCP_REMOVE}, 42e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt {.name = "ecn-tcp-ece", .id = O_ECN_TCP_ECE, .type = XTTYPE_UINT8, 43e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt .min = 0, .max = 1, .excl = F_ECN_TCP_REMOVE}, 44e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt {.name = "ecn-ip-ect", .id = O_ECN_IP_ECT, .type = XTTYPE_UINT8, 45e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt .min = 0, .max = 3}, 46e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt XTOPT_TABLEEND, 47385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte}; 48385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 49e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardtstatic void ECN_parse(struct xt_option_call *cb) 50385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte{ 51e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt struct ipt_ECN_info *einfo = cb->data; 52e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt 53e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt xtables_option_parse(cb); 54e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt switch (cb->entry->id) { 55e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt case O_ECN_TCP_REMOVE: 56c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte einfo->operation = IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR; 57c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte einfo->proto.tcp.ece = 0; 58c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte einfo->proto.tcp.cwr = 0; 59385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte break; 60e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt case O_ECN_TCP_CWR: 61c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte einfo->operation |= IPT_ECN_OP_SET_CWR; 62e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt einfo->proto.tcp.cwr = cb->val.u8; 63c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte break; 64e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt case O_ECN_TCP_ECE: 65c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte einfo->operation |= IPT_ECN_OP_SET_ECE; 66e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt einfo->proto.tcp.ece = cb->val.u8; 67c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte break; 68e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt case O_ECN_IP_ECT: 69c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte einfo->operation |= IPT_ECN_OP_SET_IP; 70e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt einfo->ip_ect = cb->val.u8; 71c05c44fc6018fcd94df499c981d846ff20882c4cHarald Welte break; 72385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte } 73385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte} 74385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 75e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardtstatic void ECN_check(struct xt_fcheck_call *cb) 76385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte{ 77e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt if (cb->xflags == 0) 781829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 794e5d4bff933d77158d9d32b4f87c5842decf670eJan Engelhardt "ECN target: An operation is required"); 80385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte} 81385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 821d5b63d12984d12c8d87242179855e17657be16dJan Engelhardtstatic void ECN_print(const void *ip, const struct xt_entry_target *target, 831d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt int numeric) 84385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte{ 85385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte const struct ipt_ECN_info *einfo = 86385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte (const struct ipt_ECN_info *)target->data; 87385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 8873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" ECN"); 89385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 907b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR) 917b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte && einfo->proto.tcp.ece == 0 927b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte && einfo->proto.tcp.cwr == 0) 9373866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" TCP remove"); 947b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte else { 957b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte if (einfo->operation & IPT_ECN_OP_SET_ECE) 9673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" ECE=%u", einfo->proto.tcp.ece); 977b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte 987b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte if (einfo->operation & IPT_ECN_OP_SET_CWR) 9973866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" CWR=%u", einfo->proto.tcp.cwr); 1007b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte 1017b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte if (einfo->operation & IPT_ECN_OP_SET_IP) 10273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" ECT codepoint=%u", einfo->ip_ect); 103385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte } 104385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte} 105385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 1061d5b63d12984d12c8d87242179855e17657be16dJan Engelhardtstatic void ECN_save(const void *ip, const struct xt_entry_target *target) 107385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte{ 108385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte const struct ipt_ECN_info *einfo = 109385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte (const struct ipt_ECN_info *)target->data; 110385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 1117b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR) 1127b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte && einfo->proto.tcp.ece == 0 1137b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte && einfo->proto.tcp.cwr == 0) 11473866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --ecn-tcp-remove"); 1157b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte else { 116c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte 1177b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte if (einfo->operation & IPT_ECN_OP_SET_ECE) 11873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --ecn-tcp-ece %d", einfo->proto.tcp.ece); 1197b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte 1207b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte if (einfo->operation & IPT_ECN_OP_SET_CWR) 12173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --ecn-tcp-cwr %d", einfo->proto.tcp.cwr); 122c980a240bad8f8995805df3bfdfb18180dd08d03Harald Welte 1237b49af40179706d42d98cb72330a07df37dcb7eaHarald Welte if (einfo->operation & IPT_ECN_OP_SET_IP) 12473866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --ecn-ip-ect %d", einfo->ip_ect); 125385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte } 126385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte} 127385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 1288b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardtstatic struct xtables_target ecn_tg_reg = { 1298caee8b9e34fed4562fcff553197c161fc9d9979Pablo Neira .name = "ECN", 1308b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .version = XTABLES_VERSION, 13103d99486d8283552705b58dc55b6085dffc38792Jan Engelhardt .family = NFPROTO_IPV4, 1328b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .size = XT_ALIGN(sizeof(struct ipt_ECN_info)), 1338b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .userspacesize = XT_ALIGN(sizeof(struct ipt_ECN_info)), 1341d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt .help = ECN_help, 1351d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt .print = ECN_print, 1361d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt .save = ECN_save, 137e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt .x6_parse = ECN_parse, 138e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt .x6_fcheck = ECN_check, 139e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt .x6_options = ECN_opts, 140385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte}; 141385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte 142385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Weltevoid _init(void) 143385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte{ 1448b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt xtables_register_target(&ecn_tg_reg); 145385a1dd0f3b01fc0fbd6bcdee9796e0240ea77c1Harald Welte} 146