1 /* Shared library add-on to iptables for ECN matching 2 * 3 * (C) 2002 by Harald Welte <laforge (at) netfilter.org> 4 * (C) 2011 by Patrick McHardy <kaber (at) trash.net> 5 * 6 * This program is distributed under the terms of GNU GPL v2, 1991 7 * 8 * libipt_ecn.c borrowed heavily from libipt_dscp.c 9 * 10 */ 11 #include <stdio.h> 12 #include <xtables.h> 13 #include <linux/netfilter/xt_ecn.h> 14 15 enum { 16 O_ECN_TCP_CWR = 0, 17 O_ECN_TCP_ECE, 18 O_ECN_IP_ECT, 19 }; 20 21 static void ecn_help(void) 22 { 23 printf( 24 "ECN match options\n" 25 "[!] --ecn-tcp-cwr Match CWR bit of TCP header\n" 26 "[!] --ecn-tcp-ece Match ECE bit of TCP header\n" 27 "[!] --ecn-ip-ect [0..3] Match ECN codepoint in IPv4/IPv6 header\n"); 28 } 29 30 static const struct xt_option_entry ecn_opts[] = { 31 {.name = "ecn-tcp-cwr", .id = O_ECN_TCP_CWR, .type = XTTYPE_NONE, 32 .flags = XTOPT_INVERT}, 33 {.name = "ecn-tcp-ece", .id = O_ECN_TCP_ECE, .type = XTTYPE_NONE, 34 .flags = XTOPT_INVERT}, 35 {.name = "ecn-ip-ect", .id = O_ECN_IP_ECT, .type = XTTYPE_UINT8, 36 .min = 0, .max = 3, .flags = XTOPT_INVERT}, 37 XTOPT_TABLEEND, 38 }; 39 40 static void ecn_parse(struct xt_option_call *cb) 41 { 42 struct xt_ecn_info *einfo = cb->data; 43 44 xtables_option_parse(cb); 45 switch (cb->entry->id) { 46 case O_ECN_TCP_CWR: 47 einfo->operation |= XT_ECN_OP_MATCH_CWR; 48 if (cb->invert) 49 einfo->invert |= XT_ECN_OP_MATCH_CWR; 50 break; 51 case O_ECN_TCP_ECE: 52 einfo->operation |= XT_ECN_OP_MATCH_ECE; 53 if (cb->invert) 54 einfo->invert |= XT_ECN_OP_MATCH_ECE; 55 break; 56 case O_ECN_IP_ECT: 57 if (cb->invert) 58 einfo->invert |= XT_ECN_OP_MATCH_IP; 59 einfo->operation |= XT_ECN_OP_MATCH_IP; 60 einfo->ip_ect = cb->val.u8; 61 break; 62 } 63 } 64 65 static void ecn_check(struct xt_fcheck_call *cb) 66 { 67 if (cb->xflags == 0) 68 xtables_error(PARAMETER_PROBLEM, 69 "ECN match: some option required"); 70 } 71 72 static void ecn_print(const void *ip, const struct xt_entry_match *match, 73 int numeric) 74 { 75 const struct xt_ecn_info *einfo = 76 (const struct xt_ecn_info *)match->data; 77 78 printf(" ECN match"); 79 80 if (einfo->operation & XT_ECN_OP_MATCH_ECE) { 81 printf(" %sECE", 82 (einfo->invert & XT_ECN_OP_MATCH_ECE) ? "!" : ""); 83 } 84 85 if (einfo->operation & XT_ECN_OP_MATCH_CWR) { 86 printf(" %sCWR", 87 (einfo->invert & XT_ECN_OP_MATCH_CWR) ? "!" : ""); 88 } 89 90 if (einfo->operation & XT_ECN_OP_MATCH_IP) { 91 printf(" %sECT=%d", 92 (einfo->invert & XT_ECN_OP_MATCH_IP) ? "!" : "", 93 einfo->ip_ect); 94 } 95 } 96 97 static void ecn_save(const void *ip, const struct xt_entry_match *match) 98 { 99 const struct xt_ecn_info *einfo = 100 (const struct xt_ecn_info *)match->data; 101 102 if (einfo->operation & XT_ECN_OP_MATCH_ECE) { 103 if (einfo->invert & XT_ECN_OP_MATCH_ECE) 104 printf(" !"); 105 printf(" --ecn-tcp-ece"); 106 } 107 108 if (einfo->operation & XT_ECN_OP_MATCH_CWR) { 109 if (einfo->invert & XT_ECN_OP_MATCH_CWR) 110 printf(" !"); 111 printf(" --ecn-tcp-cwr"); 112 } 113 114 if (einfo->operation & XT_ECN_OP_MATCH_IP) { 115 if (einfo->invert & XT_ECN_OP_MATCH_IP) 116 printf(" !"); 117 printf(" --ecn-ip-ect %d", einfo->ip_ect); 118 } 119 } 120 121 static int ecn_xlate(struct xt_xlate *xl, 122 const struct xt_xlate_mt_params *params) 123 { 124 const struct xt_ecn_info *einfo = 125 (const struct xt_ecn_info *)params->match->data; 126 127 if (!(einfo->operation & XT_ECN_OP_MATCH_IP)) 128 return 0; 129 130 xt_xlate_add(xl, "ip ecn "); 131 if (einfo->invert) 132 xt_xlate_add(xl,"!= "); 133 134 switch (einfo->ip_ect) { 135 case 0: 136 xt_xlate_add(xl, "not-ect"); 137 break; 138 case 1: 139 xt_xlate_add(xl, "ect1"); 140 break; 141 case 2: 142 xt_xlate_add(xl, "ect0"); 143 break; 144 case 3: 145 xt_xlate_add(xl, "ce"); 146 break; 147 } 148 return 1; 149 } 150 151 static struct xtables_match ecn_mt_reg = { 152 .name = "ecn", 153 .version = XTABLES_VERSION, 154 .family = NFPROTO_UNSPEC, 155 .size = XT_ALIGN(sizeof(struct xt_ecn_info)), 156 .userspacesize = XT_ALIGN(sizeof(struct xt_ecn_info)), 157 .help = ecn_help, 158 .print = ecn_print, 159 .save = ecn_save, 160 .x6_parse = ecn_parse, 161 .x6_fcheck = ecn_check, 162 .x6_options = ecn_opts, 163 .xlate = ecn_xlate, 164 }; 165 166 void _init(void) 167 { 168 xtables_register_match(&ecn_mt_reg); 169 } 170