blob: 97e839da5539101badf39382b93616854050fe42 [file] [log] [blame]
Harald Welte7a447312002-05-29 15:11:49 +00001/* 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 <string.h>
12#include <stdlib.h>
13#include <getopt.h>
14
15#include <iptables.h>
16#include <linux/netfilter_ipv4/ip_tables.h>
17#include <linux/netfilter_ipv4/ipt_ecn.h>
18
Harald Welte7a447312002-05-29 15:11:49 +000019static void help(void)
20{
21 printf(
22"ECN match v%s options\n"
23"[!] --ecn-tcp-cwr Match CWR bit of TCP header\n"
24"[!] --ecn-tcp-ece Match ECE bit of TCP header\n"
25"[!] --ecn-ip-ect [0..3] Match ECN codepoint in IPv4 header\n",
26 IPTABLES_VERSION);
27}
28
29static struct option opts[] = {
Stephane Ouellettefb7ed722003-04-11 08:20:01 +000030 { .name = "ecn-tcp-cwr", .has_arg = 0, .flag = 0, .val = 'F' },
31 { .name = "ecn-tcp-ece", .has_arg = 0, .flag = 0, .val = 'G' },
32 { .name = "ecn-ip-ect", .has_arg = 1, .flag = 0, .val = 'H' },
33 { .name = 0 }
Harald Welte7a447312002-05-29 15:11:49 +000034};
35
36static int
37parse(int c, char **argv, int invert, unsigned int *flags,
38 const struct ipt_entry *entry,
39 unsigned int *nfcache,
40 struct ipt_entry_match **match)
41{
42 unsigned int result;
43 struct ipt_ecn_info *einfo
44 = (struct ipt_ecn_info *)(*match)->data;
45
46 switch (c) {
47 case 'F':
48 if (*flags & IPT_ECN_OP_MATCH_CWR)
49 exit_error(PARAMETER_PROBLEM,
50 "ECN match: can only use parameter ONCE!");
51 check_inverse(optarg, &invert, &optind, 0);
52 einfo->operation |= IPT_ECN_OP_MATCH_CWR;
53 if (invert)
54 einfo->invert |= IPT_ECN_OP_MATCH_CWR;
55 *flags |= IPT_ECN_OP_MATCH_CWR;
56 break;
57
58 case 'G':
59 if (*flags & IPT_ECN_OP_MATCH_ECE)
60 exit_error(PARAMETER_PROBLEM,
61 "ECN match: can only use parameter ONCE!");
62 check_inverse(optarg, &invert, &optind, 0);
63 einfo->operation |= IPT_ECN_OP_MATCH_ECE;
64 if (invert)
65 einfo->invert |= IPT_ECN_OP_MATCH_ECE;
66 *flags |= IPT_ECN_OP_MATCH_ECE;
67 break;
68
69 case 'H':
70 if (*flags & IPT_ECN_OP_MATCH_IP)
71 exit_error(PARAMETER_PROBLEM,
72 "ECN match: can only use parameter ONCE!");
73 check_inverse(optarg, &invert, &optind, 0);
74 if (invert)
75 einfo->invert |= IPT_ECN_OP_MATCH_IP;
76 *flags |= IPT_ECN_OP_MATCH_IP;
77 einfo->operation |= IPT_ECN_OP_MATCH_IP;
78 if (string_to_number(optarg, 0, 3, &result))
79 exit_error(PARAMETER_PROBLEM,
80 "ECN match: Value out of range");
Harald Welte0e9ed732002-08-05 19:35:52 +000081 einfo->ip_ect = result;
Harald Welte7a447312002-05-29 15:11:49 +000082 break;
83 default:
84 return 0;
85 }
86
87 return 1;
88}
89
90static void
91final_check(unsigned int flags)
92{
93 if (!flags)
94 exit_error(PARAMETER_PROBLEM,
95 "ECN match: some option required");
96}
97
Harald Welte7a447312002-05-29 15:11:49 +000098/* Prints out the matchinfo. */
99static void
100print(const struct ipt_ip *ip,
101 const struct ipt_entry_match *match,
102 int numeric)
103{
104 const struct ipt_ecn_info *einfo =
105 (const struct ipt_ecn_info *)match->data;
106
107 printf("ECN match ");
108
109 if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
110 if (einfo->invert & IPT_ECN_OP_MATCH_ECE)
111 fputc('!', stdout);
112 printf("ECE ");
113 }
114
115 if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
116 if (einfo->invert & IPT_ECN_OP_MATCH_CWR)
117 fputc('!', stdout);
118 printf("CWR ");
119 }
120
121 if (einfo->operation & IPT_ECN_OP_MATCH_IP) {
122 if (einfo->invert & IPT_ECN_OP_MATCH_IP)
123 fputc('!', stdout);
124 printf("ECT=%d ", einfo->ip_ect);
125 }
126}
127
128/* Saves the union ipt_matchinfo in parsable form to stdout. */
129static void
130save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
131{
132 const struct ipt_ecn_info *einfo =
133 (const struct ipt_ecn_info *)match->data;
134
135 if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
136 if (einfo->invert & IPT_ECN_OP_MATCH_ECE)
137 printf("! ");
138 printf("--ecn-tcp-ece ");
139 }
140
141 if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
142 if (einfo->invert & IPT_ECN_OP_MATCH_CWR)
143 printf("! ");
144 printf("--ecn-tcp-cwr ");
145 }
146
147 if (einfo->operation & IPT_ECN_OP_MATCH_IP) {
148 if (einfo->invert & IPT_ECN_OP_MATCH_IP)
149 printf("! ");
150 printf("--ecn-ip-ect %d", einfo->ip_ect);
151 }
152}
153
154static
155struct iptables_match ecn
Stephane Ouellettefb7ed722003-04-11 08:20:01 +0000156= { .name = "ecn",
157 .version = IPTABLES_VERSION,
158 .size = IPT_ALIGN(sizeof(struct ipt_ecn_info)),
159 .userspacesize = IPT_ALIGN(sizeof(struct ipt_ecn_info)),
160 .help = &help,
Stephane Ouellettefb7ed722003-04-11 08:20:01 +0000161 .parse = &parse,
162 .final_check = &final_check,
163 .print = &print,
164 .save = &save,
165 .extra_opts = opts
Harald Welte7a447312002-05-29 15:11:49 +0000166};
167
168void _init(void)
169{
170 register_match(&ecn);
171}