17a44731615d950a2966737d1d1c960859023f3a3Harald Welte/* Shared library add-on to iptables for ECN matching 27a44731615d950a2966737d1d1c960859023f3a3Harald Welte * 398e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy * (C) 2002 by Harald Welte <laforge@netfilter.org> 498e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy * (C) 2011 by Patrick McHardy <kaber@trash.net> 57a44731615d950a2966737d1d1c960859023f3a3Harald Welte * 67a44731615d950a2966737d1d1c960859023f3a3Harald Welte * This program is distributed under the terms of GNU GPL v2, 1991 77a44731615d950a2966737d1d1c960859023f3a3Harald Welte * 87a44731615d950a2966737d1d1c960859023f3a3Harald Welte * libipt_ecn.c borrowed heavily from libipt_dscp.c 97a44731615d950a2966737d1d1c960859023f3a3Harald Welte * 107a44731615d950a2966737d1d1c960859023f3a3Harald Welte */ 117a44731615d950a2966737d1d1c960859023f3a3Harald Welte#include <stdio.h> 125d9678ad3eabc34ac40dfe055d7f6a8e44445a5aJan Engelhardt#include <xtables.h> 1398e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy#include <linux/netfilter/xt_ecn.h> 147a44731615d950a2966737d1d1c960859023f3a3Harald Welte 15e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardtenum { 16e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt O_ECN_TCP_CWR = 0, 17e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt O_ECN_TCP_ECE, 18e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt O_ECN_IP_ECT, 19e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt}; 20e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt 2159d164019340d110d302634e429320577f0db7beJan Engelhardtstatic void ecn_help(void) 227a44731615d950a2966737d1d1c960859023f3a3Harald Welte{ 237a44731615d950a2966737d1d1c960859023f3a3Harald Welte printf( 248b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"ECN match options\n" 257a44731615d950a2966737d1d1c960859023f3a3Harald Welte"[!] --ecn-tcp-cwr Match CWR bit of TCP header\n" 267a44731615d950a2966737d1d1c960859023f3a3Harald Welte"[!] --ecn-tcp-ece Match ECE bit of TCP header\n" 2798e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy"[!] --ecn-ip-ect [0..3] Match ECN codepoint in IPv4/IPv6 header\n"); 287a44731615d950a2966737d1d1c960859023f3a3Harald Welte} 297a44731615d950a2966737d1d1c960859023f3a3Harald Welte 30e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardtstatic const struct xt_option_entry ecn_opts[] = { 31e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt {.name = "ecn-tcp-cwr", .id = O_ECN_TCP_CWR, .type = XTTYPE_NONE, 32e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt .flags = XTOPT_INVERT}, 33e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt {.name = "ecn-tcp-ece", .id = O_ECN_TCP_ECE, .type = XTTYPE_NONE, 34e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt .flags = XTOPT_INVERT}, 35e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt {.name = "ecn-ip-ect", .id = O_ECN_IP_ECT, .type = XTTYPE_UINT8, 36e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt .min = 0, .max = 3, .flags = XTOPT_INVERT}, 37e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt XTOPT_TABLEEND, 387a44731615d950a2966737d1d1c960859023f3a3Harald Welte}; 397a44731615d950a2966737d1d1c960859023f3a3Harald Welte 40e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardtstatic void ecn_parse(struct xt_option_call *cb) 417a44731615d950a2966737d1d1c960859023f3a3Harald Welte{ 4298e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy struct xt_ecn_info *einfo = cb->data; 43e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt 44e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt xtables_option_parse(cb); 45e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt switch (cb->entry->id) { 46e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt case O_ECN_TCP_CWR: 4798e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy einfo->operation |= XT_ECN_OP_MATCH_CWR; 48e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt if (cb->invert) 4998e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy einfo->invert |= XT_ECN_OP_MATCH_CWR; 507a44731615d950a2966737d1d1c960859023f3a3Harald Welte break; 51e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt case O_ECN_TCP_ECE: 5298e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy einfo->operation |= XT_ECN_OP_MATCH_ECE; 53e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt if (cb->invert) 5498e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy einfo->invert |= XT_ECN_OP_MATCH_ECE; 557a44731615d950a2966737d1d1c960859023f3a3Harald Welte break; 56e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt case O_ECN_IP_ECT: 57e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt if (cb->invert) 5898e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy einfo->invert |= XT_ECN_OP_MATCH_IP; 5998e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy einfo->operation |= XT_ECN_OP_MATCH_IP; 60e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt einfo->ip_ect = cb->val.u8; 617a44731615d950a2966737d1d1c960859023f3a3Harald Welte break; 627a44731615d950a2966737d1d1c960859023f3a3Harald Welte } 637a44731615d950a2966737d1d1c960859023f3a3Harald Welte} 647a44731615d950a2966737d1d1c960859023f3a3Harald Welte 65e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardtstatic void ecn_check(struct xt_fcheck_call *cb) 667a44731615d950a2966737d1d1c960859023f3a3Harald Welte{ 67e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt if (cb->xflags == 0) 681829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 697a44731615d950a2966737d1d1c960859023f3a3Harald Welte "ECN match: some option required"); 707a44731615d950a2966737d1d1c960859023f3a3Harald Welte} 717a44731615d950a2966737d1d1c960859023f3a3Harald Welte 7259d164019340d110d302634e429320577f0db7beJan Engelhardtstatic void ecn_print(const void *ip, const struct xt_entry_match *match, 7359d164019340d110d302634e429320577f0db7beJan Engelhardt int numeric) 747a44731615d950a2966737d1d1c960859023f3a3Harald Welte{ 7598e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy const struct xt_ecn_info *einfo = 7698e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy (const struct xt_ecn_info *)match->data; 777a44731615d950a2966737d1d1c960859023f3a3Harald Welte 7873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" ECN match"); 797a44731615d950a2966737d1d1c960859023f3a3Harald Welte 8098e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy if (einfo->operation & XT_ECN_OP_MATCH_ECE) { 8173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" %sECE", 8298e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy (einfo->invert & XT_ECN_OP_MATCH_ECE) ? "!" : ""); 837a44731615d950a2966737d1d1c960859023f3a3Harald Welte } 847a44731615d950a2966737d1d1c960859023f3a3Harald Welte 8598e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy if (einfo->operation & XT_ECN_OP_MATCH_CWR) { 8673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" %sCWR", 8798e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy (einfo->invert & XT_ECN_OP_MATCH_CWR) ? "!" : ""); 887a44731615d950a2966737d1d1c960859023f3a3Harald Welte } 897a44731615d950a2966737d1d1c960859023f3a3Harald Welte 9098e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy if (einfo->operation & XT_ECN_OP_MATCH_IP) { 9173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" %sECT=%d", 9298e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy (einfo->invert & XT_ECN_OP_MATCH_IP) ? "!" : "", 9373866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt einfo->ip_ect); 947a44731615d950a2966737d1d1c960859023f3a3Harald Welte } 957a44731615d950a2966737d1d1c960859023f3a3Harald Welte} 967a44731615d950a2966737d1d1c960859023f3a3Harald Welte 9759d164019340d110d302634e429320577f0db7beJan Engelhardtstatic void ecn_save(const void *ip, const struct xt_entry_match *match) 987a44731615d950a2966737d1d1c960859023f3a3Harald Welte{ 9998e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy const struct xt_ecn_info *einfo = 10098e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy (const struct xt_ecn_info *)match->data; 10198e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy 10298e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy if (einfo->operation & XT_ECN_OP_MATCH_ECE) { 10398e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy if (einfo->invert & XT_ECN_OP_MATCH_ECE) 10473866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" !"); 10573866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --ecn-tcp-ece"); 1067a44731615d950a2966737d1d1c960859023f3a3Harald Welte } 1077a44731615d950a2966737d1d1c960859023f3a3Harald Welte 10898e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy if (einfo->operation & XT_ECN_OP_MATCH_CWR) { 10998e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy if (einfo->invert & XT_ECN_OP_MATCH_CWR) 11073866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" !"); 11173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --ecn-tcp-cwr"); 1127a44731615d950a2966737d1d1c960859023f3a3Harald Welte } 1137a44731615d950a2966737d1d1c960859023f3a3Harald Welte 11498e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy if (einfo->operation & XT_ECN_OP_MATCH_IP) { 11598e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy if (einfo->invert & XT_ECN_OP_MATCH_IP) 11673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" !"); 11773866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --ecn-ip-ect %d", einfo->ip_ect); 1187a44731615d950a2966737d1d1c960859023f3a3Harald Welte } 1197a44731615d950a2966737d1d1c960859023f3a3Harald Welte} 1207a44731615d950a2966737d1d1c960859023f3a3Harald Welte 1218b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardtstatic struct xtables_match ecn_mt_reg = { 122e1df221d7a1b3df0224d94865ec05ba336995608Jan Engelhardt .name = "ecn", 123e1df221d7a1b3df0224d94865ec05ba336995608Jan Engelhardt .version = XTABLES_VERSION, 12498e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy .family = NFPROTO_UNSPEC, 12598e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy .size = XT_ALIGN(sizeof(struct xt_ecn_info)), 12698e1769b65b71989e3f16b25529b40f374aef323Patrick McHardy .userspacesize = XT_ALIGN(sizeof(struct xt_ecn_info)), 127e1df221d7a1b3df0224d94865ec05ba336995608Jan Engelhardt .help = ecn_help, 128e1df221d7a1b3df0224d94865ec05ba336995608Jan Engelhardt .print = ecn_print, 129e1df221d7a1b3df0224d94865ec05ba336995608Jan Engelhardt .save = ecn_save, 130e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt .x6_parse = ecn_parse, 131e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt .x6_fcheck = ecn_check, 132e36463232e2f1fe9363700b2740c2a82dbf1821dJan Engelhardt .x6_options = ecn_opts, 1337a44731615d950a2966737d1d1c960859023f3a3Harald Welte}; 1347a44731615d950a2966737d1d1c960859023f3a3Harald Welte 1357a44731615d950a2966737d1d1c960859023f3a3Harald Weltevoid _init(void) 1367a44731615d950a2966737d1d1c960859023f3a3Harald Welte{ 1378b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt xtables_register_match(&ecn_mt_reg); 1387a44731615d950a2966737d1d1c960859023f3a3Harald Welte} 139