Home | History | Annotate | Download | only in extensions
      1 /* Shared library add-on to iptables for ECN matching
      2  *
      3  * (C) 2002 by Harald Welte <laforge (at) 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 
     14 enum {
     15 	O_ECN_TCP_CWR = 0,
     16 	O_ECN_TCP_ECE,
     17 	O_ECN_IP_ECT,
     18 };
     19 
     20 static 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 
     29 static 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 
     39 static 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 
     64 static 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 
     71 static 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 
     96 static 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 
    120 static 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 
    134 void _init(void)
    135 {
    136 	xtables_register_match(&ecn_mt_reg);
    137 }
    138