libxt_CONNMARK.c revision f36f4a8844132cbaacf3bbd5ec0254c17fcc97ae
1/* Shared library add-on to iptables to add CONNMARK target 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 <string.h>
24#include <stdlib.h>
25#include <getopt.h>
26
27#include <xtables.h>
28#include <linux/netfilter/x_tables.h>
29#include <linux/netfilter/xt_CONNMARK.h>
30
31#if 0
32struct markinfo {
33	struct xt_entry_target t;
34	struct ipt_connmark_target_info mark;
35};
36#endif
37
38/* Function which prints out usage message. */
39static void
40help(void)
41{
42	printf(
43"CONNMARK target v%s options:\n"
44"  --set-mark value[/mask]       Set conntrack mark value\n"
45"  --save-mark [--mask mask]     Save the packet nfmark in the connection\n"
46"  --restore-mark [--mask mask]  Restore saved nfmark value\n"
47"\n",
48IPTABLES_VERSION);
49}
50
51static const struct option opts[] = {
52	{ "set-mark", 1, 0, '1' },
53	{ "save-mark", 0, 0, '2' },
54	{ "restore-mark", 0, 0, '3' },
55	{ "mask", 1, 0, '4' },
56	{ 0 }
57};
58
59/* Initialize the target. */
60static void
61init(struct xt_entry_target *t, unsigned int *nfcache)
62{
63}
64
65/* Function which parses command options; returns true if it
66   ate an option */
67static int
68parse(int c, char **argv, int invert, unsigned int *flags,
69      const void *entry,
70      struct xt_entry_target **target)
71{
72	struct xt_connmark_target_info *markinfo
73		= (struct xt_connmark_target_info *)(*target)->data;
74
75	markinfo->mask = 0xffffffffUL;
76
77	switch (c) {
78		char *end;
79	case '1':
80		markinfo->mode = XT_CONNMARK_SET;
81
82		markinfo->mark = strtoul(optarg, &end, 0);
83		if (*end == '/' && end[1] != '\0')
84		    markinfo->mask = strtoul(end+1, &end, 0);
85
86		if (*end != '\0' || end == optarg)
87			exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
88		if (*flags)
89			exit_error(PARAMETER_PROBLEM,
90			           "CONNMARK target: Can't specify --set-mark twice");
91		*flags = 1;
92		break;
93	case '2':
94		markinfo->mode = XT_CONNMARK_SAVE;
95		if (*flags)
96			exit_error(PARAMETER_PROBLEM,
97			           "CONNMARK target: Can't specify --save-mark twice");
98		*flags = 1;
99		break;
100	case '3':
101		markinfo->mode = XT_CONNMARK_RESTORE;
102		if (*flags)
103			exit_error(PARAMETER_PROBLEM,
104			           "CONNMARK target: Can't specify --restore-mark twice");
105		*flags = 1;
106		break;
107	case '4':
108		if (!*flags)
109			exit_error(PARAMETER_PROBLEM,
110			           "CONNMARK target: Can't specify --mask without a operation");
111		markinfo->mask = strtoul(optarg, &end, 0);
112
113		if (*end != '\0' || end == optarg)
114			exit_error(PARAMETER_PROBLEM, "Bad MASK value `%s'", optarg);
115		break;
116	default:
117		return 0;
118	}
119
120	return 1;
121}
122
123static void
124final_check(unsigned int flags)
125{
126	if (!flags)
127		exit_error(PARAMETER_PROBLEM,
128		           "CONNMARK target: No operation specified");
129}
130
131static void
132print_mark(unsigned long mark)
133{
134	printf("0x%lx", mark);
135}
136
137static void
138print_mask(const char *text, unsigned long mask)
139{
140	if (mask != 0xffffffffUL)
141		printf("%s0x%lx", text, mask);
142}
143
144
145/* Prints out the target info. */
146static void
147print(const void *ip,
148      const struct xt_entry_target *target,
149      int numeric)
150{
151	const struct xt_connmark_target_info *markinfo =
152		(const struct xt_connmark_target_info *)target->data;
153	switch (markinfo->mode) {
154	case XT_CONNMARK_SET:
155	    printf("CONNMARK set ");
156	    print_mark(markinfo->mark);
157	    print_mask("/", markinfo->mask);
158	    printf(" ");
159	    break;
160	case XT_CONNMARK_SAVE:
161	    printf("CONNMARK save ");
162	    print_mask("mask ", markinfo->mask);
163	    printf(" ");
164	    break;
165	case XT_CONNMARK_RESTORE:
166	    printf("CONNMARK restore ");
167	    print_mask("mask ", markinfo->mask);
168	    break;
169	default:
170	    printf("ERROR: UNKNOWN CONNMARK MODE ");
171	    break;
172	}
173}
174
175/* Saves the target into in parsable form to stdout. */
176static void
177save(const void *ip, const struct xt_entry_target *target)
178{
179	const struct xt_connmark_target_info *markinfo =
180		(const struct xt_connmark_target_info *)target->data;
181
182	switch (markinfo->mode) {
183	case XT_CONNMARK_SET:
184	    printf("--set-mark ");
185	    print_mark(markinfo->mark);
186	    print_mask("/", markinfo->mask);
187	    printf(" ");
188	    break;
189	case XT_CONNMARK_SAVE:
190	    printf("--save-mark ");
191	    print_mask("--mask ", markinfo->mask);
192	    break;
193	case XT_CONNMARK_RESTORE:
194	    printf("--restore-mark ");
195	    print_mask("--mask ", markinfo->mask);
196	    break;
197	default:
198	    printf("ERROR: UNKNOWN CONNMARK MODE ");
199	    break;
200	}
201}
202
203static struct xtables_target connmark_target = {
204	.family		= AF_INET,
205	.name		= "CONNMARK",
206	.version	= IPTABLES_VERSION,
207	.size		= XT_ALIGN(sizeof(struct xt_connmark_target_info)),
208	.userspacesize	= XT_ALIGN(sizeof(struct xt_connmark_target_info)),
209	.help		= &help,
210	.init		= &init,
211	.parse		= &parse,
212	.final_check	= &final_check,
213	.print		= &print,
214	.save		= &save,
215	.extra_opts	= opts,
216};
217
218static struct xtables_target connmark_target6 = {
219	.family		= AF_INET6,
220	.name		= "CONNMARK",
221	.version	= IPTABLES_VERSION,
222	.size		= XT_ALIGN(sizeof(struct xt_connmark_target_info)),
223	.userspacesize	= XT_ALIGN(sizeof(struct xt_connmark_target_info)),
224	.help		= &help,
225	.init		= &init,
226	.parse		= &parse,
227	.final_check	= &final_check,
228	.print		= &print,
229	.save		= &save,
230	.extra_opts	= opts,
231};
232
233void _init(void)
234{
235	xtables_register_target(&connmark_target);
236	xtables_register_target(&connmark_target6);
237}
238