1/* Shared library add-on to iptables for ECN matching 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 */ 10#include <stdio.h> 11#include <xtables.h> 12#include <linux/netfilter_ipv4/ipt_ecn.h> 13 14enum { 15 O_ECN_TCP_CWR = 0, 16 O_ECN_TCP_ECE, 17 O_ECN_IP_ECT, 18}; 19 20static void ecn_help(void) 21{ 22 printf( 23"ECN match options\n" 24"[!] --ecn-tcp-cwr Match CWR bit of TCP header\n" 25"[!] --ecn-tcp-ece Match ECE bit of TCP header\n" 26"[!] --ecn-ip-ect [0..3] Match ECN codepoint in IPv4 header\n"); 27} 28 29static const struct xt_option_entry ecn_opts[] = { 30 {.name = "ecn-tcp-cwr", .id = O_ECN_TCP_CWR, .type = XTTYPE_NONE, 31 .flags = XTOPT_INVERT}, 32 {.name = "ecn-tcp-ece", .id = O_ECN_TCP_ECE, .type = XTTYPE_NONE, 33 .flags = XTOPT_INVERT}, 34 {.name = "ecn-ip-ect", .id = O_ECN_IP_ECT, .type = XTTYPE_UINT8, 35 .min = 0, .max = 3, .flags = XTOPT_INVERT}, 36 XTOPT_TABLEEND, 37}; 38 39static void ecn_parse(struct xt_option_call *cb) 40{ 41 struct ipt_ecn_info *einfo = cb->data; 42 43 xtables_option_parse(cb); 44 switch (cb->entry->id) { 45 case O_ECN_TCP_CWR: 46 einfo->operation |= IPT_ECN_OP_MATCH_CWR; 47 if (cb->invert) 48 einfo->invert |= IPT_ECN_OP_MATCH_CWR; 49 break; 50 case O_ECN_TCP_ECE: 51 einfo->operation |= IPT_ECN_OP_MATCH_ECE; 52 if (cb->invert) 53 einfo->invert |= IPT_ECN_OP_MATCH_ECE; 54 break; 55 case O_ECN_IP_ECT: 56 if (cb->invert) 57 einfo->invert |= IPT_ECN_OP_MATCH_IP; 58 einfo->operation |= IPT_ECN_OP_MATCH_IP; 59 einfo->ip_ect = cb->val.u8; 60 break; 61 } 62} 63 64static void ecn_check(struct xt_fcheck_call *cb) 65{ 66 if (cb->xflags == 0) 67 xtables_error(PARAMETER_PROBLEM, 68 "ECN match: some option required"); 69} 70 71static void ecn_print(const void *ip, const struct xt_entry_match *match, 72 int numeric) 73{ 74 const struct ipt_ecn_info *einfo = 75 (const struct ipt_ecn_info *)match->data; 76 77 printf(" ECN match"); 78 79 if (einfo->operation & IPT_ECN_OP_MATCH_ECE) { 80 printf(" %sECE", 81 (einfo->invert & IPT_ECN_OP_MATCH_ECE) ? "!" : ""); 82 } 83 84 if (einfo->operation & IPT_ECN_OP_MATCH_CWR) { 85 printf(" %sCWR", 86 (einfo->invert & IPT_ECN_OP_MATCH_CWR) ? "!" : ""); 87 } 88 89 if (einfo->operation & IPT_ECN_OP_MATCH_IP) { 90 printf(" %sECT=%d", 91 (einfo->invert & IPT_ECN_OP_MATCH_IP) ? "!" : "", 92 einfo->ip_ect); 93 } 94} 95 96static void ecn_save(const void *ip, const struct xt_entry_match *match) 97{ 98 const struct ipt_ecn_info *einfo = 99 (const struct ipt_ecn_info *)match->data; 100 101 if (einfo->operation & IPT_ECN_OP_MATCH_ECE) { 102 if (einfo->invert & IPT_ECN_OP_MATCH_ECE) 103 printf(" !"); 104 printf(" --ecn-tcp-ece"); 105 } 106 107 if (einfo->operation & IPT_ECN_OP_MATCH_CWR) { 108 if (einfo->invert & IPT_ECN_OP_MATCH_CWR) 109 printf(" !"); 110 printf(" --ecn-tcp-cwr"); 111 } 112 113 if (einfo->operation & IPT_ECN_OP_MATCH_IP) { 114 if (einfo->invert & IPT_ECN_OP_MATCH_IP) 115 printf(" !"); 116 printf(" --ecn-ip-ect %d", einfo->ip_ect); 117 } 118} 119 120static struct xtables_match ecn_mt_reg = { 121 .name = "ecn", 122 .version = XTABLES_VERSION, 123 .family = NFPROTO_IPV4, 124 .size = XT_ALIGN(sizeof(struct ipt_ecn_info)), 125 .userspacesize = XT_ALIGN(sizeof(struct ipt_ecn_info)), 126 .help = ecn_help, 127 .print = ecn_print, 128 .save = ecn_save, 129 .x6_parse = ecn_parse, 130 .x6_fcheck = ecn_check, 131 .x6_options = ecn_opts, 132}; 133 134void _init(void) 135{ 136 xtables_register_match(&ecn_mt_reg); 137} 138