• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Shared library add-on to iptables to add MARK target support. */
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <getopt.h>
6 
7 #include <iptables.h>
8 #include <linux/netfilter_ipv4/ip_tables.h>
9 /* For 64bit kernel / 32bit userspace */
10 #include "../include/linux/netfilter_ipv4/ipt_MARK.h"
11 
12 /* Function which prints out usage message. */
13 static void
help(void)14 help(void)
15 {
16 	printf(
17 "MARK target v%s options:\n"
18 "  --set-mark value                   Set nfmark value\n"
19 "  --and-mark value                   Binary AND the nfmark with value\n"
20 "  --or-mark  value                   Binary OR  the nfmark with value\n"
21 "\n",
22 IPTABLES_VERSION);
23 }
24 
25 static struct option opts[] = {
26 	{ "set-mark", 1, 0, '1' },
27 	{ "and-mark", 1, 0, '2' },
28 	{ "or-mark", 1, 0, '3' },
29 	{ 0 }
30 };
31 
32 /* Initialize the target. */
33 static void
init(struct ipt_entry_target * t,unsigned int * nfcache)34 init(struct ipt_entry_target *t, unsigned int *nfcache)
35 {
36 }
37 
38 /* Function which parses command options; returns true if it
39    ate an option */
40 static int
parse_v0(int c,char ** argv,int invert,unsigned int * flags,const struct ipt_entry * entry,struct ipt_entry_target ** target)41 parse_v0(int c, char **argv, int invert, unsigned int *flags,
42 	 const struct ipt_entry *entry,
43 	 struct ipt_entry_target **target)
44 {
45 	struct ipt_mark_target_info *markinfo
46 		= (struct ipt_mark_target_info *)(*target)->data;
47 
48 	switch (c) {
49 	case '1':
50 #ifdef KERNEL_64_USERSPACE_32
51 		if (string_to_number_ll(optarg, 0, 0,
52 				     &markinfo->mark))
53 #else
54 		if (string_to_number_l(optarg, 0, 0,
55 				     &markinfo->mark))
56 #endif
57 			exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
58 		if (*flags)
59 			exit_error(PARAMETER_PROBLEM,
60 			           "MARK target: Can't specify --set-mark twice");
61 		*flags = 1;
62 		break;
63 	case '2':
64 		exit_error(PARAMETER_PROBLEM,
65 			   "MARK target: kernel too old for --and-mark");
66 	case '3':
67 		exit_error(PARAMETER_PROBLEM,
68 			   "MARK target: kernel too old for --or-mark");
69 	default:
70 		return 0;
71 	}
72 
73 	return 1;
74 }
75 
76 static void
final_check(unsigned int flags)77 final_check(unsigned int flags)
78 {
79 	if (!flags)
80 		exit_error(PARAMETER_PROBLEM,
81 		           "MARK target: Parameter --set/and/or-mark"
82 			   " is required");
83 }
84 
85 /* Function which parses command options; returns true if it
86    ate an option */
87 static int
parse_v1(int c,char ** argv,int invert,unsigned int * flags,const struct ipt_entry * entry,struct ipt_entry_target ** target)88 parse_v1(int c, char **argv, int invert, unsigned int *flags,
89 	 const struct ipt_entry *entry,
90 	 struct ipt_entry_target **target)
91 {
92 	struct ipt_mark_target_info_v1 *markinfo
93 		= (struct ipt_mark_target_info_v1 *)(*target)->data;
94 
95 	switch (c) {
96 	case '1':
97 	        markinfo->mode = IPT_MARK_SET;
98 		break;
99 	case '2':
100 	        markinfo->mode = IPT_MARK_AND;
101 		break;
102 	case '3':
103 	        markinfo->mode = IPT_MARK_OR;
104 		break;
105 	default:
106 		return 0;
107 	}
108 
109 #ifdef KERNEL_64_USERSPACE_32
110 	if (string_to_number_ll(optarg, 0, 0,  &markinfo->mark))
111 #else
112 	if (string_to_number_l(optarg, 0, 0, &markinfo->mark))
113 #endif
114 		exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
115 
116 	if (*flags)
117 		exit_error(PARAMETER_PROBLEM,
118 			   "MARK target: Can't specify --set-mark twice");
119 
120 	*flags = 1;
121 	return 1;
122 }
123 
124 #ifdef KERNEL_64_USERSPACE_32
125 static void
print_mark(unsigned long long mark)126 print_mark(unsigned long long mark)
127 {
128 	printf("0x%llx ", mark);
129 }
130 #else
131 static void
print_mark(unsigned long mark)132 print_mark(unsigned long mark)
133 {
134 	printf("0x%lx ", mark);
135 }
136 #endif
137 
138 /* Prints out the targinfo. */
139 static void
print_v0(const struct ipt_ip * ip,const struct ipt_entry_target * target,int numeric)140 print_v0(const struct ipt_ip *ip,
141 	 const struct ipt_entry_target *target,
142 	 int numeric)
143 {
144 	const struct ipt_mark_target_info *markinfo =
145 		(const struct ipt_mark_target_info *)target->data;
146 	printf("MARK set ");
147 	print_mark(markinfo->mark);
148 }
149 
150 /* Saves the union ipt_targinfo in parsable form to stdout. */
151 static void
save_v0(const struct ipt_ip * ip,const struct ipt_entry_target * target)152 save_v0(const struct ipt_ip *ip, const struct ipt_entry_target *target)
153 {
154 	const struct ipt_mark_target_info *markinfo =
155 		(const struct ipt_mark_target_info *)target->data;
156 
157 	printf("--set-mark ");
158 	print_mark(markinfo->mark);
159 }
160 
161 /* Prints out the targinfo. */
162 static void
print_v1(const struct ipt_ip * ip,const struct ipt_entry_target * target,int numeric)163 print_v1(const struct ipt_ip *ip,
164 	 const struct ipt_entry_target *target,
165 	 int numeric)
166 {
167 	const struct ipt_mark_target_info_v1 *markinfo =
168 		(const struct ipt_mark_target_info_v1 *)target->data;
169 
170 	switch (markinfo->mode) {
171 	case IPT_MARK_SET:
172 		printf("MARK set ");
173 		break;
174 	case IPT_MARK_AND:
175 		printf("MARK and ");
176 		break;
177 	case IPT_MARK_OR:
178 		printf("MARK or ");
179 		break;
180 	}
181 	print_mark(markinfo->mark);
182 }
183 
184 /* Saves the union ipt_targinfo in parsable form to stdout. */
185 static void
save_v1(const struct ipt_ip * ip,const struct ipt_entry_target * target)186 save_v1(const struct ipt_ip *ip, const struct ipt_entry_target *target)
187 {
188 	const struct ipt_mark_target_info_v1 *markinfo =
189 		(const struct ipt_mark_target_info_v1 *)target->data;
190 
191 	switch (markinfo->mode) {
192 	case IPT_MARK_SET:
193 		printf("--set-mark ");
194 		break;
195 	case IPT_MARK_AND:
196 		printf("--and-mark ");
197 		break;
198 	case IPT_MARK_OR:
199 		printf("--or-mark ");
200 		break;
201 	}
202 	print_mark(markinfo->mark);
203 }
204 
205 static
206 struct iptables_target mark_v0 = {
207 	.next		= NULL,
208 	.name		= "MARK",
209 	.version	= IPTABLES_VERSION,
210 	.revision	= 0,
211 	.size		= IPT_ALIGN(sizeof(struct ipt_mark_target_info)),
212 	.userspacesize	= IPT_ALIGN(sizeof(struct ipt_mark_target_info)),
213 	.help		= &help,
214 	.init		= &init,
215 	.parse		= &parse_v0,
216 	.final_check	= &final_check,
217 	.print		= &print_v0,
218 	.save		= &save_v0,
219 	.extra_opts	= opts
220 };
221 
222 static
223 struct iptables_target mark_v1 = {
224 	.next		= NULL,
225 	.name		= "MARK",
226 	.version	= IPTABLES_VERSION,
227 	.revision	= 1,
228 	.size		= IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1)),
229 	.userspacesize	= IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1)),
230 	.help		= &help,
231 	.init		= &init,
232 	.parse		= &parse_v1,
233 	.final_check	= &final_check,
234 	.print		= &print_v1,
235 	.save		= &save_v1,
236 	.extra_opts	= opts
237 };
238 
ipt_MARK_init(void)239 void ipt_MARK_init(void)
240 {
241 	register_target(&mark_v0);
242 	register_target(&mark_v1);
243 }
244