blob: 3ee190e9825d59591cd751e7cfe57e4bda652406 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* 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 <xtables.h>
16#include <linux/netfilter_ipv4/ipt_ecn.h>
17
18static void ecn_help(void)
19{
20 printf(
21"ECN match options\n"
22"[!] --ecn-tcp-cwr Match CWR bit of TCP header\n"
23"[!] --ecn-tcp-ece Match ECE bit of TCP header\n"
24"[!] --ecn-ip-ect [0..3] Match ECN codepoint in IPv4 header\n");
25}
26
27static const struct option ecn_opts[] = {
28 { .name = "ecn-tcp-cwr", .has_arg = 0, .val = 'F' },
29 { .name = "ecn-tcp-ece", .has_arg = 0, .val = 'G' },
30 { .name = "ecn-ip-ect", .has_arg = 1, .val = 'H' },
31 { .name = NULL }
32};
33
34static int ecn_parse(int c, char **argv, int invert, unsigned int *flags,
35 const void *entry, struct xt_entry_match **match)
36{
37 unsigned int result;
38 struct ipt_ecn_info *einfo
39 = (struct ipt_ecn_info *)(*match)->data;
40
41 switch (c) {
42 case 'F':
43 if (*flags & IPT_ECN_OP_MATCH_CWR)
44 xtables_error(PARAMETER_PROBLEM,
45 "ECN match: can only use parameter ONCE!");
46 xtables_check_inverse(optarg, &invert, &optind, 0);
47 einfo->operation |= IPT_ECN_OP_MATCH_CWR;
48 if (invert)
49 einfo->invert |= IPT_ECN_OP_MATCH_CWR;
50 *flags |= IPT_ECN_OP_MATCH_CWR;
51 break;
52
53 case 'G':
54 if (*flags & IPT_ECN_OP_MATCH_ECE)
55 xtables_error(PARAMETER_PROBLEM,
56 "ECN match: can only use parameter ONCE!");
57 xtables_check_inverse(optarg, &invert, &optind, 0);
58 einfo->operation |= IPT_ECN_OP_MATCH_ECE;
59 if (invert)
60 einfo->invert |= IPT_ECN_OP_MATCH_ECE;
61 *flags |= IPT_ECN_OP_MATCH_ECE;
62 break;
63
64 case 'H':
65 if (*flags & IPT_ECN_OP_MATCH_IP)
66 xtables_error(PARAMETER_PROBLEM,
67 "ECN match: can only use parameter ONCE!");
68 xtables_check_inverse(optarg, &invert, &optind, 0);
69 if (invert)
70 einfo->invert |= IPT_ECN_OP_MATCH_IP;
71 *flags |= IPT_ECN_OP_MATCH_IP;
72 einfo->operation |= IPT_ECN_OP_MATCH_IP;
73 if (!xtables_strtoui(optarg, NULL, &result, 0, 3))
74 xtables_error(PARAMETER_PROBLEM,
75 "ECN match: Value out of range");
76 einfo->ip_ect = result;
77 break;
78 default:
79 return 0;
80 }
81
82 return 1;
83}
84
85static void ecn_check(unsigned int flags)
86{
87 if (!flags)
88 xtables_error(PARAMETER_PROBLEM,
89 "ECN match: some option required");
90}
91
92static void ecn_print(const void *ip, const struct xt_entry_match *match,
93 int numeric)
94{
95 const struct ipt_ecn_info *einfo =
96 (const struct ipt_ecn_info *)match->data;
97
98 printf("ECN match ");
99
100 if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
101 if (einfo->invert & IPT_ECN_OP_MATCH_ECE)
102 fputc('!', stdout);
103 printf("ECE ");
104 }
105
106 if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
107 if (einfo->invert & IPT_ECN_OP_MATCH_CWR)
108 fputc('!', stdout);
109 printf("CWR ");
110 }
111
112 if (einfo->operation & IPT_ECN_OP_MATCH_IP) {
113 if (einfo->invert & IPT_ECN_OP_MATCH_IP)
114 fputc('!', stdout);
115 printf("ECT=%d ", einfo->ip_ect);
116 }
117}
118
119static void ecn_save(const void *ip, const struct xt_entry_match *match)
120{
121 const struct ipt_ecn_info *einfo =
122 (const struct ipt_ecn_info *)match->data;
123
124 if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
125 if (einfo->invert & IPT_ECN_OP_MATCH_ECE)
126 printf("! ");
127 printf("--ecn-tcp-ece ");
128 }
129
130 if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
131 if (einfo->invert & IPT_ECN_OP_MATCH_CWR)
132 printf("! ");
133 printf("--ecn-tcp-cwr ");
134 }
135
136 if (einfo->operation & IPT_ECN_OP_MATCH_IP) {
137 if (einfo->invert & IPT_ECN_OP_MATCH_IP)
138 printf("! ");
139 printf("--ecn-ip-ect %d", einfo->ip_ect);
140 }
141}
142
143static struct xtables_match ecn_mt_reg = {
144 .name = "ecn",
145 .version = XTABLES_VERSION,
146 .family = NFPROTO_IPV4,
147 .size = XT_ALIGN(sizeof(struct ipt_ecn_info)),
148 .userspacesize = XT_ALIGN(sizeof(struct ipt_ecn_info)),
149 .help = ecn_help,
150 .parse = ecn_parse,
151 .final_check = ecn_check,
152 .print = ecn_print,
153 .save = ecn_save,
154 .extra_opts = ecn_opts,
155};
156
157void _init(void)
158{
159 xtables_register_match(&ecn_mt_reg);
160}