Fork for IVI and add .changes file
[profile/ivi/iptables.git] / extensions / libipt_ecn.c
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 <string.h>
12 #include <stdlib.h>
13 #include <getopt.h>
14
15 #include <xtables.h>
16 #include <linux/netfilter_ipv4/ipt_ecn.h>
17
18 static 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
27 static 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
34 static 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, argv);
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, argv);
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, argv);
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
85 static void ecn_check(unsigned int flags)
86 {
87         if (!flags)
88                 xtables_error(PARAMETER_PROBLEM,
89                            "ECN match: some option required");
90 }
91
92 static 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
119 static 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
143 static 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
157 void _init(void)
158 {
159         xtables_register_match(&ecn_mt_reg);
160 }