blob: 0f47a8f48c3fc76bd715b981c087e498920b33a6 [file] [log] [blame]
Harald Welte469d18f2006-01-26 14:43:52 +00001/* Shared library add-on to iptables to add connmark matching support.
2 *
3 * (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
4 * by Henrik Nordstrom <hno@marasystems.com>
5 *
6 * Version 1.1
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22#include <stdio.h>
23#include <netdb.h>
24#include <string.h>
25#include <stdlib.h>
26#include <getopt.h>
27
Yasuyuki KOZAKAIc57c1552007-08-04 08:09:04 +000028#include <xtables.h>
29#include <linux/netfilter/xt_connmark.h>
Harald Welte469d18f2006-01-26 14:43:52 +000030
Jan Engelhardta7b07072008-01-20 13:32:01 +000031enum {
32 F_MARK = 1 << 0,
33};
34
35static void connmark_mt_help(void)
Harald Welte469d18f2006-01-26 14:43:52 +000036{
37 printf(
Jan Engelhardta7b07072008-01-20 13:32:01 +000038"connmark match options:\n"
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020039"[!] --mark value[/mask] Match ctmark value with optional mask\n");
Harald Welte469d18f2006-01-26 14:43:52 +000040}
41
Jan Engelhardta7b07072008-01-20 13:32:01 +000042static const struct option connmark_mt_opts[] = {
43 {.name = "mark", .has_arg = true, .val = '1'},
Max Kellermann9ee386a2008-01-29 13:48:05 +000044 { .name = NULL }
Harald Welte469d18f2006-01-26 14:43:52 +000045};
46
Jan Engelhardta7b07072008-01-20 13:32:01 +000047static int
48connmark_mt_parse(int c, char **argv, int invert, unsigned int *flags,
49 const void *entry, struct xt_entry_match **match)
50{
51 struct xt_connmark_mtinfo1 *info = (void *)(*match)->data;
Jan Engelhardta8097542009-01-27 17:39:01 +010052 unsigned int mark, mask = UINT32_MAX;
Jan Engelhardta7b07072008-01-20 13:32:01 +000053 char *end;
54
55 switch (c) {
56 case '1': /* --mark */
Jan Engelhardta41545c2009-01-27 21:27:19 +010057 xtables_param_act(XTF_ONLY_ONCE, "connmark", "--mark", *flags & F_MARK);
Jan Engelhardt5f2922c2009-01-27 18:43:01 +010058 if (!xtables_strtoui(optarg, &end, &mark, 0, UINT32_MAX))
Jan Engelhardta41545c2009-01-27 21:27:19 +010059 xtables_param_act(XTF_BAD_VALUE, "connmark", "--mark", optarg);
Jan Engelhardta7b07072008-01-20 13:32:01 +000060 if (*end == '/')
Jan Engelhardt5f2922c2009-01-27 18:43:01 +010061 if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
Jan Engelhardta41545c2009-01-27 21:27:19 +010062 xtables_param_act(XTF_BAD_VALUE, "connmark", "--mark", optarg);
Jan Engelhardta7b07072008-01-20 13:32:01 +000063 if (*end != '\0')
Jan Engelhardta41545c2009-01-27 21:27:19 +010064 xtables_param_act(XTF_BAD_VALUE, "connmark", "--mark", optarg);
Jan Engelhardta7b07072008-01-20 13:32:01 +000065
66 if (invert)
67 info->invert = true;
68 info->mark = mark;
69 info->mask = mask;
70 *flags |= F_MARK;
71 return true;
72 }
73 return false;
74}
75
Harald Welte469d18f2006-01-26 14:43:52 +000076static int
Jan Engelhardt181dead2007-10-04 16:27:07 +000077connmark_parse(int c, char **argv, int invert, unsigned int *flags,
78 const void *entry, struct xt_entry_match **match)
Harald Welte469d18f2006-01-26 14:43:52 +000079{
Yasuyuki KOZAKAIc57c1552007-08-04 08:09:04 +000080 struct xt_connmark_info *markinfo = (struct xt_connmark_info *)(*match)->data;
Harald Welte469d18f2006-01-26 14:43:52 +000081
82 switch (c) {
83 char *end;
84 case '1':
85 check_inverse(optarg, &invert, &optind, 0);
86
87 markinfo->mark = strtoul(optarg, &end, 0);
88 markinfo->mask = 0xffffffffUL;
89
90 if (*end == '/')
91 markinfo->mask = strtoul(end+1, &end, 0);
92
93 if (*end != '\0' || end == optarg)
94 exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
95 if (invert)
96 markinfo->invert = 1;
97 *flags = 1;
98 break;
99
100 default:
101 return 0;
102 }
103 return 1;
104}
105
Jan Engelhardta7b07072008-01-20 13:32:01 +0000106static void print_mark(unsigned int mark, unsigned int mask)
Harald Welte469d18f2006-01-26 14:43:52 +0000107{
Jan Engelhardta7b07072008-01-20 13:32:01 +0000108 if (mask != 0xffffffffU)
109 printf("0x%x/0x%x ", mark, mask);
Harald Welte469d18f2006-01-26 14:43:52 +0000110 else
Jan Engelhardta7b07072008-01-20 13:32:01 +0000111 printf("0x%x ", mark);
Harald Welte469d18f2006-01-26 14:43:52 +0000112}
113
Jan Engelhardta7b07072008-01-20 13:32:01 +0000114static void connmark_mt_check(unsigned int flags)
Harald Welte469d18f2006-01-26 14:43:52 +0000115{
Jan Engelhardta7b07072008-01-20 13:32:01 +0000116 if (flags == 0)
Harald Welte469d18f2006-01-26 14:43:52 +0000117 exit_error(PARAMETER_PROBLEM,
Jan Engelhardta7b07072008-01-20 13:32:01 +0000118 "connmark: The --mark option is required");
Harald Welte469d18f2006-01-26 14:43:52 +0000119}
120
Harald Welte469d18f2006-01-26 14:43:52 +0000121static void
Jan Engelhardt181dead2007-10-04 16:27:07 +0000122connmark_print(const void *ip, const struct xt_entry_match *match, int numeric)
Harald Welte469d18f2006-01-26 14:43:52 +0000123{
Yasuyuki KOZAKAIc57c1552007-08-04 08:09:04 +0000124 struct xt_connmark_info *info = (struct xt_connmark_info *)match->data;
Harald Welte469d18f2006-01-26 14:43:52 +0000125
126 printf("CONNMARK match ");
127 if (info->invert)
128 printf("!");
Jan Engelhardta7b07072008-01-20 13:32:01 +0000129 print_mark(info->mark, info->mask);
130}
131
132static void
133connmark_mt_print(const void *ip, const struct xt_entry_match *match, int numeric)
134{
135 const struct xt_connmark_mtinfo1 *info = (const void *)match->data;
136
137 printf("connmark match ");
138 if (info->invert)
139 printf("!");
140 print_mark(info->mark, info->mask);
Harald Welte469d18f2006-01-26 14:43:52 +0000141}
142
Jan Engelhardt181dead2007-10-04 16:27:07 +0000143static void connmark_save(const void *ip, const struct xt_entry_match *match)
Harald Welte469d18f2006-01-26 14:43:52 +0000144{
Yasuyuki KOZAKAIc57c1552007-08-04 08:09:04 +0000145 struct xt_connmark_info *info = (struct xt_connmark_info *)match->data;
Harald Welte469d18f2006-01-26 14:43:52 +0000146
147 if (info->invert)
148 printf("! ");
149
150 printf("--mark ");
Jan Engelhardta7b07072008-01-20 13:32:01 +0000151 print_mark(info->mark, info->mask);
Harald Welte469d18f2006-01-26 14:43:52 +0000152}
153
Jan Engelhardta7b07072008-01-20 13:32:01 +0000154static void
155connmark_mt_save(const void *ip, const struct xt_entry_match *match)
156{
157 const struct xt_connmark_mtinfo1 *info = (const void *)match->data;
158
159 if (info->invert)
160 printf("! ");
161
162 printf("--mark ");
163 print_mark(info->mark, info->mask);
164}
165
166static struct xtables_match connmark_mt_reg_v0 = {
Jan Engelhardt03d99482008-11-18 12:27:54 +0100167 .family = NFPROTO_IPV4,
Yasuyuki KOZAKAIc57c1552007-08-04 08:09:04 +0000168 .name = "connmark",
Jan Engelhardta7b07072008-01-20 13:32:01 +0000169 .revision = 0,
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200170 .version = XTABLES_VERSION,
Yasuyuki KOZAKAIc57c1552007-08-04 08:09:04 +0000171 .size = XT_ALIGN(sizeof(struct xt_connmark_info)),
172 .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_info)),
Jan Engelhardta7b07072008-01-20 13:32:01 +0000173 .help = connmark_mt_help,
Jan Engelhardt181dead2007-10-04 16:27:07 +0000174 .parse = connmark_parse,
Jan Engelhardta7b07072008-01-20 13:32:01 +0000175 .final_check = connmark_mt_check,
Jan Engelhardt181dead2007-10-04 16:27:07 +0000176 .print = connmark_print,
177 .save = connmark_save,
Jan Engelhardta7b07072008-01-20 13:32:01 +0000178 .extra_opts = connmark_mt_opts,
Yasuyuki KOZAKAIc57c1552007-08-04 08:09:04 +0000179};
180
Jan Engelhardta7b07072008-01-20 13:32:01 +0000181static struct xtables_match connmark_mt6_reg_v0 = {
Jan Engelhardt03d99482008-11-18 12:27:54 +0100182 .family = NFPROTO_IPV6,
Yasuyuki KOZAKAIc57c1552007-08-04 08:09:04 +0000183 .name = "connmark",
Jan Engelhardta7b07072008-01-20 13:32:01 +0000184 .revision = 0,
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200185 .version = XTABLES_VERSION,
Yasuyuki KOZAKAIc57c1552007-08-04 08:09:04 +0000186 .size = XT_ALIGN(sizeof(struct xt_connmark_info)),
187 .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_info)),
Jan Engelhardta7b07072008-01-20 13:32:01 +0000188 .help = connmark_mt_help,
Jan Engelhardt181dead2007-10-04 16:27:07 +0000189 .parse = connmark_parse,
Jan Engelhardta7b07072008-01-20 13:32:01 +0000190 .final_check = connmark_mt_check,
Jan Engelhardt181dead2007-10-04 16:27:07 +0000191 .print = connmark_print,
192 .save = connmark_save,
Jan Engelhardta7b07072008-01-20 13:32:01 +0000193 .extra_opts = connmark_mt_opts,
194};
195
196static struct xtables_match connmark_mt_reg = {
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200197 .version = XTABLES_VERSION,
Jan Engelhardta7b07072008-01-20 13:32:01 +0000198 .name = "connmark",
199 .revision = 1,
Jan Engelhardt03d99482008-11-18 12:27:54 +0100200 .family = NFPROTO_IPV4,
Jan Engelhardta7b07072008-01-20 13:32:01 +0000201 .size = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
202 .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
203 .help = connmark_mt_help,
204 .parse = connmark_mt_parse,
205 .final_check = connmark_mt_check,
206 .print = connmark_mt_print,
207 .save = connmark_mt_save,
208 .extra_opts = connmark_mt_opts,
209};
210
211static struct xtables_match connmark_mt6_reg = {
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200212 .version = XTABLES_VERSION,
Jan Engelhardta7b07072008-01-20 13:32:01 +0000213 .name = "connmark",
214 .revision = 1,
Jan Engelhardt03d99482008-11-18 12:27:54 +0100215 .family = NFPROTO_IPV6,
Jan Engelhardta7b07072008-01-20 13:32:01 +0000216 .size = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
217 .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
218 .help = connmark_mt_help,
219 .parse = connmark_mt_parse,
220 .final_check = connmark_mt_check,
221 .print = connmark_mt_print,
222 .save = connmark_mt_save,
223 .extra_opts = connmark_mt_opts,
Harald Welte469d18f2006-01-26 14:43:52 +0000224};
225
226void _init(void)
227{
Jan Engelhardta7b07072008-01-20 13:32:01 +0000228 xtables_register_match(&connmark_mt_reg_v0);
229 xtables_register_match(&connmark_mt6_reg_v0);
230 xtables_register_match(&connmark_mt_reg);
231 xtables_register_match(&connmark_mt6_reg);
Harald Welte469d18f2006-01-26 14:43:52 +0000232}