• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
14 enum {
15 	O_ECN_TCP_CWR = 0,
16 	O_ECN_TCP_ECE,
17 	O_ECN_IP_ECT,
18 };
19 
ecn_help(void)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 
ecn_parse(struct xt_option_call * cb)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 
ecn_check(struct xt_fcheck_call * cb)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 
ecn_print(const void * ip,const struct xt_entry_match * match,int numeric)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 
ecn_save(const void * ip,const struct xt_entry_match * match)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 
_init(void)134 void _init(void)
135 {
136 	xtables_register_match(&ecn_mt_reg);
137 }
138