blob: 56a0347e584e6a8f1294f6754c4d2fc35222174b [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>
Jan Engelhardt5d9678a2008-11-20 10:15:35 +010011#include <xtables.h>
Harald Welte7a447312002-05-29 15:11:49 +000012#include <linux/netfilter_ipv4/ipt_ecn.h>
13
Jan Engelhardte3646322011-03-03 00:51:16 +010014enum {
15 O_ECN_TCP_CWR = 0,
16 O_ECN_TCP_ECE,
17 O_ECN_IP_ECT,
18};
19
Jan Engelhardt59d16402007-10-04 16:28:39 +000020static void ecn_help(void)
Harald Welte7a447312002-05-29 15:11:49 +000021{
22 printf(
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020023"ECN match options\n"
Harald Welte7a447312002-05-29 15:11:49 +000024"[!] --ecn-tcp-cwr Match CWR bit of TCP header\n"
25"[!] --ecn-tcp-ece Match ECE bit of TCP header\n"
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020026"[!] --ecn-ip-ect [0..3] Match ECN codepoint in IPv4 header\n");
Harald Welte7a447312002-05-29 15:11:49 +000027}
28
Jan Engelhardte3646322011-03-03 00:51:16 +010029static 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,
Harald Welte7a447312002-05-29 15:11:49 +000037};
38
Jan Engelhardte3646322011-03-03 00:51:16 +010039static void ecn_parse(struct xt_option_call *cb)
Harald Welte7a447312002-05-29 15:11:49 +000040{
Jan Engelhardte3646322011-03-03 00:51:16 +010041 struct ipt_ecn_info *einfo = cb->data;
Harald Welte7a447312002-05-29 15:11:49 +000042
Jan Engelhardte3646322011-03-03 00:51:16 +010043 xtables_option_parse(cb);
44 switch (cb->entry->id) {
45 case O_ECN_TCP_CWR:
Harald Welte7a447312002-05-29 15:11:49 +000046 einfo->operation |= IPT_ECN_OP_MATCH_CWR;
Jan Engelhardte3646322011-03-03 00:51:16 +010047 if (cb->invert)
Harald Welte7a447312002-05-29 15:11:49 +000048 einfo->invert |= IPT_ECN_OP_MATCH_CWR;
Harald Welte7a447312002-05-29 15:11:49 +000049 break;
Jan Engelhardte3646322011-03-03 00:51:16 +010050 case O_ECN_TCP_ECE:
Harald Welte7a447312002-05-29 15:11:49 +000051 einfo->operation |= IPT_ECN_OP_MATCH_ECE;
Jan Engelhardte3646322011-03-03 00:51:16 +010052 if (cb->invert)
Harald Welte7a447312002-05-29 15:11:49 +000053 einfo->invert |= IPT_ECN_OP_MATCH_ECE;
Harald Welte7a447312002-05-29 15:11:49 +000054 break;
Jan Engelhardte3646322011-03-03 00:51:16 +010055 case O_ECN_IP_ECT:
56 if (cb->invert)
Harald Welte7a447312002-05-29 15:11:49 +000057 einfo->invert |= IPT_ECN_OP_MATCH_IP;
Harald Welte7a447312002-05-29 15:11:49 +000058 einfo->operation |= IPT_ECN_OP_MATCH_IP;
Jan Engelhardte3646322011-03-03 00:51:16 +010059 einfo->ip_ect = cb->val.u8;
Harald Welte7a447312002-05-29 15:11:49 +000060 break;
Harald Welte7a447312002-05-29 15:11:49 +000061 }
Harald Welte7a447312002-05-29 15:11:49 +000062}
63
Jan Engelhardte3646322011-03-03 00:51:16 +010064static void ecn_check(struct xt_fcheck_call *cb)
Harald Welte7a447312002-05-29 15:11:49 +000065{
Jan Engelhardte3646322011-03-03 00:51:16 +010066 if (cb->xflags == 0)
Jan Engelhardt1829ed42009-02-21 03:29:44 +010067 xtables_error(PARAMETER_PROBLEM,
Harald Welte7a447312002-05-29 15:11:49 +000068 "ECN match: some option required");
69}
70
Jan Engelhardt59d16402007-10-04 16:28:39 +000071static void ecn_print(const void *ip, const struct xt_entry_match *match,
72 int numeric)
Harald Welte7a447312002-05-29 15:11:49 +000073{
74 const struct ipt_ecn_info *einfo =
75 (const struct ipt_ecn_info *)match->data;
76
Jan Engelhardt73866352010-12-18 02:04:59 +010077 printf(" ECN match");
Harald Welte7a447312002-05-29 15:11:49 +000078
79 if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
Jan Engelhardt73866352010-12-18 02:04:59 +010080 printf(" %sECE",
81 (einfo->invert & IPT_ECN_OP_MATCH_ECE) ? "!" : "");
Harald Welte7a447312002-05-29 15:11:49 +000082 }
83
84 if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
Jan Engelhardt73866352010-12-18 02:04:59 +010085 printf(" %sCWR",
86 (einfo->invert & IPT_ECN_OP_MATCH_CWR) ? "!" : "");
Harald Welte7a447312002-05-29 15:11:49 +000087 }
88
89 if (einfo->operation & IPT_ECN_OP_MATCH_IP) {
Jan Engelhardt73866352010-12-18 02:04:59 +010090 printf(" %sECT=%d",
91 (einfo->invert & IPT_ECN_OP_MATCH_IP) ? "!" : "",
92 einfo->ip_ect);
Harald Welte7a447312002-05-29 15:11:49 +000093 }
94}
95
Jan Engelhardt59d16402007-10-04 16:28:39 +000096static void ecn_save(const void *ip, const struct xt_entry_match *match)
Harald Welte7a447312002-05-29 15:11:49 +000097{
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)
Jan Engelhardt73866352010-12-18 02:04:59 +0100103 printf(" !");
104 printf(" --ecn-tcp-ece");
Harald Welte7a447312002-05-29 15:11:49 +0000105 }
106
107 if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
108 if (einfo->invert & IPT_ECN_OP_MATCH_CWR)
Jan Engelhardt73866352010-12-18 02:04:59 +0100109 printf(" !");
110 printf(" --ecn-tcp-cwr");
Harald Welte7a447312002-05-29 15:11:49 +0000111 }
112
113 if (einfo->operation & IPT_ECN_OP_MATCH_IP) {
114 if (einfo->invert & IPT_ECN_OP_MATCH_IP)
Jan Engelhardt73866352010-12-18 02:04:59 +0100115 printf(" !");
116 printf(" --ecn-ip-ect %d", einfo->ip_ect);
Harald Welte7a447312002-05-29 15:11:49 +0000117 }
118}
119
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200120static struct xtables_match ecn_mt_reg = {
Jan Engelhardte1df2212011-02-15 12:02:51 +0100121 .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,
Jan Engelhardte1df2212011-02-15 12:02:51 +0100127 .print = ecn_print,
128 .save = ecn_save,
Jan Engelhardte3646322011-03-03 00:51:16 +0100129 .x6_parse = ecn_parse,
130 .x6_fcheck = ecn_check,
131 .x6_options = ecn_opts,
Harald Welte7a447312002-05-29 15:11:49 +0000132};
133
134void _init(void)
135{
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200136 xtables_register_match(&ecn_mt_reg);
Harald Welte7a447312002-05-29 15:11:49 +0000137}