]> git.proxmox.com Git - mirror_iproute2.git/blame - tc/m_xt.c
ipvrf: cleanup style issues
[mirror_iproute2.git] / tc / m_xt.c
CommitLineData
a36ceb85
AH
1/*
2 * m_xt.c xtables based targets
3d0b7439 3 * utilities mostly ripped from iptables <duh, its the linux way>
a36ceb85
AH
4 *
5 * This program is free software; you can distribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
10 * Authors: J Hadi Salim (hadi@cyberus.ca)
11 */
12
13#include <syslog.h>
14#include <sys/socket.h>
15#include <netinet/in.h>
16#include <arpa/inet.h>
17#include <net/if.h>
18#include <limits.h>
19#include <linux/netfilter.h>
20#include <linux/netfilter_ipv4/ip_tables.h>
21#include <xtables.h>
22#include "utils.h"
23#include "tc_util.h"
24#include <linux/tc_act/tc_ipt.h>
25#include <stdio.h>
26#include <dlfcn.h>
27#include <getopt.h>
28#include <errno.h>
29#include <string.h>
30#include <netdb.h>
31#include <stdlib.h>
32#include <ctype.h>
33#include <stdarg.h>
a36ceb85
AH
34#include <unistd.h>
35#include <fcntl.h>
36#include <sys/wait.h>
37#ifndef XT_LIB_DIR
38# define XT_LIB_DIR "/lib/xtables"
39#endif
40
cfa292de 41#ifndef __ALIGN_KERNEL
4b83a08c
SH
42#define __ALIGN_KERNEL(x, a) \
43 __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
44#define __ALIGN_KERNEL_MASK(x, mask) \
45 (((x) + (mask)) & ~(mask))
cfa292de
AD
46#endif
47
609ceb80 48#ifndef ALIGN
32a121cb 49#define ALIGN(x, a) __ALIGN_KERNEL((x), (a))
609ceb80
SH
50#endif
51
a36ceb85
AH
52static const char *tname = "mangle";
53
54char *lib_dir;
55
4b83a08c 56static const char * const ipthooks[] = {
a36ceb85
AH
57 "NF_IP_PRE_ROUTING",
58 "NF_IP_LOCAL_IN",
59 "NF_IP_FORWARD",
60 "NF_IP_LOCAL_OUT",
61 "NF_IP_POST_ROUTING",
62};
63
64static struct option original_opts[] = {
65 {
66 .name = "jump",
67 .has_arg = 1,
68 .val = 'j'
69 },
70 {0, 0, 0, 0}
71};
72
73static struct xtables_globals tcipt_globals = {
74 .option_offset = 0,
75 .program_name = "tc-ipt",
76 .program_version = "0.2",
77 .orig_opts = original_opts,
78 .opts = original_opts,
79 .exit_err = NULL,
80};
81
82/*
83 * we may need to check for version mismatch
84*/
d1f28cf1 85static int
a36ceb85
AH
86build_st(struct xtables_target *target, struct xt_entry_target *t)
87{
88
89 size_t size =
32a121cb 90 XT_ALIGN(sizeof(struct xt_entry_target)) + target->size;
a36ceb85 91
32a121cb 92 if (t == NULL) {
a36ceb85
AH
93 target->t = xtables_calloc(1, size);
94 target->t->u.target_size = size;
95 strcpy(target->t->u.user.name, target->name);
be3c4d4f 96 target->t->u.user.revision = target->revision;
a36ceb85
AH
97
98 if (target->init != NULL)
99 target->init(target->t);
100 } else {
101 target->t = t;
102 }
103 return 0;
104
105}
106
d1f28cf1 107static void set_lib_dir(void)
a36ceb85
AH
108{
109
110 lib_dir = getenv("XTABLES_LIBDIR");
111 if (!lib_dir) {
112 lib_dir = getenv("IPTABLES_LIB_DIR");
113 if (lib_dir)
32a121cb 114 fprintf(stderr, "using deprecated IPTABLES_LIB_DIR\n");
a36ceb85
AH
115 }
116 if (lib_dir == NULL)
117 lib_dir = XT_LIB_DIR;
118
119}
120
2ef40085
PS
121static int get_xtables_target_opts(struct xtables_globals *globals,
122 struct xtables_target *m)
123{
124 struct option *opts;
125
126#if (XTABLES_VERSION_CODE >= 6)
127 opts = xtables_options_xfrm(globals->orig_opts,
128 globals->opts,
129 m->x6_options,
130 &m->option_offset);
131#else
132 opts = xtables_merge_options(globals->opts,
133 m->extra_opts,
134 &m->option_offset);
135#endif
136 if (!opts)
137 return -1;
138 globals->opts = opts;
139 return 0;
140}
141
32a121cb 142static int parse_ipt(struct action_util *a, int *argc_p,
a36ceb85
AH
143 char ***argv_p, int tca_id, struct nlmsghdr *n)
144{
145 struct xtables_target *m = NULL;
a36ceb85 146 struct rtattr *tail;
852d5122 147
a36ceb85 148 int c;
a36ceb85 149 char **argv = *argv_p;
f6ddd9c5 150 int argc;
a36ceb85 151 char k[16];
a36ceb85
AH
152 int size = 0;
153 int iok = 0, ok = 0;
154 __u32 hook = 0, index = 0;
a36ceb85 155
8eee75a8
PS
156 /* copy tcipt_globals because .opts will be modified by iptables */
157 struct xtables_globals tmp_tcipt_globals = tcipt_globals;
4b83a08c 158
8eee75a8 159 xtables_init_all(&tmp_tcipt_globals, NFPROTO_IPV4);
a36ceb85
AH
160 set_lib_dir();
161
f6ddd9c5
PS
162 /* parse only up until the next action */
163 for (argc = 0; argc < *argc_p; argc++) {
164 if (!argv[argc] || !strcmp(argv[argc], "action"))
165 break;
a36ceb85
AH
166 }
167
168 if (argc <= 2) {
4b83a08c
SH
169 fprintf(stderr,
170 "too few arguments for xt, need at least '-j <target>'\n");
a36ceb85
AH
171 return -1;
172 }
173
174 while (1) {
8eee75a8 175 c = getopt_long(argc, argv, "j:", tmp_tcipt_globals.opts, NULL);
a36ceb85
AH
176 if (c == -1)
177 break;
178 switch (c) {
179 case 'j':
180 m = xtables_find_target(optarg, XTF_TRY_LOAD);
f1a7c7d8 181 if (!m) {
4b83a08c
SH
182 fprintf(stderr,
183 " failed to find target %s\n\n",
184 optarg);
f1a7c7d8
PS
185 return -1;
186 }
a36ceb85 187
f1a7c7d8
PS
188 if (build_st(m, NULL) < 0) {
189 printf(" %s error\n", m->name);
190 return -1;
191 }
2ef40085 192
4b83a08c
SH
193 if (get_xtables_target_opts(&tmp_tcipt_globals,
194 m) < 0) {
195 fprintf(stderr,
196 " failed to find additional options for target %s\n\n",
197 optarg);
852d5122 198 return -1;
2ef40085 199 }
a36ceb85
AH
200 ok++;
201 break;
202
203 default:
852d5122 204#if (XTABLES_VERSION_CODE >= 6)
f1a7c7d8
PS
205 if (m != NULL && m->x6_parse != NULL) {
206 xtables_option_tpcall(c, argv, 0, m, NULL);
852d5122 207#else
f1a7c7d8
PS
208 if (m != NULL && m->parse != NULL) {
209 m->parse(c - m->option_offset, argv, 0,
4b83a08c 210 &m->tflags, NULL, &m->t);
852d5122 211#endif
a36ceb85 212 } else {
4b83a08c
SH
213 fprintf(stderr,
214 "failed to find target %s\n\n", optarg);
a36ceb85
AH
215 return -1;
216
217 }
218 ok++;
219 break;
a36ceb85
AH
220 }
221 }
222
28432f37 223 if (argc > optind) {
a36ceb85
AH
224 if (matches(argv[optind], "index") == 0) {
225 if (get_u32(&index, argv[optind + 1], 10)) {
226 fprintf(stderr, "Illegal \"index\"\n");
227 xtables_free_opts(1);
228 return -1;
229 }
230 iok++;
231
232 optind += 2;
233 }
234 }
235
236 if (!ok && !iok) {
32a121cb 237 fprintf(stderr, " ipt Parser BAD!! (%s)\n", *argv);
a36ceb85
AH
238 return -1;
239 }
240
241 /* check that we passed the correct parameters to the target */
852d5122
JHS
242#if (XTABLES_VERSION_CODE >= 6)
243 if (m)
244 xtables_option_tfcall(m);
245#else
a36ceb85
AH
246 if (m && m->final_check)
247 m->final_check(m->tflags);
852d5122 248#endif
a36ceb85
AH
249
250 {
251 struct tcmsg *t = NLMSG_DATA(n);
32a121cb 252
a36ceb85
AH
253 if (t->tcm_parent != TC_H_ROOT
254 && t->tcm_parent == TC_H_MAJ(TC_H_INGRESS)) {
255 hook = NF_IP_PRE_ROUTING;
256 } else {
257 hook = NF_IP_POST_ROUTING;
258 }
259 }
260
261 tail = NLMSG_TAIL(n);
262 addattr_l(n, MAX_MSG, tca_id, NULL, 0);
263 fprintf(stdout, "tablename: %s hook: %s\n ", tname, ipthooks[hook]);
264 fprintf(stdout, "\ttarget: ");
265
44574522
PS
266 if (m) {
267 if (m->print)
268 m->print(NULL, m->t, 0);
269 else
270 printf("%s ", m->name);
271 }
a36ceb85
AH
272 fprintf(stdout, " index %d\n", index);
273
274 if (strlen(tname) > 16) {
275 size = 16;
276 k[15] = 0;
277 } else {
278 size = 1 + strlen(tname);
279 }
280 strncpy(k, tname, size);
281
282 addattr_l(n, MAX_MSG, TCA_IPT_TABLE, k, size);
283 addattr_l(n, MAX_MSG, TCA_IPT_HOOK, &hook, 4);
284 addattr_l(n, MAX_MSG, TCA_IPT_INDEX, &index, 4);
285 if (m)
286 addattr_l(n, MAX_MSG, TCA_IPT_TARG, m->t, m->t->u.target_size);
287 tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
288
a36ceb85 289 argv += optind;
28432f37 290 *argc_p -= argc;
a36ceb85
AH
291 *argv_p = argv;
292
293 optind = 0;
294 xtables_free_opts(1);
a36ceb85 295
4f3626f9
DM
296 if (m) {
297 /* Clear flags if target will be used again */
298 m->tflags = 0;
299 m->used = 0;
300 /* Free allocated memory */
301 if (m->t)
302 free(m->t);
303 }
a36ceb85
AH
304
305 return 0;
306
307}
308
309static int
4b83a08c 310print_ipt(struct action_util *au, FILE *f, struct rtattr *arg)
a36ceb85 311{
b45f9141 312 struct xtables_target *m;
a36ceb85
AH
313 struct rtattr *tb[TCA_IPT_MAX + 1];
314 struct xt_entry_target *t = NULL;
315
316 if (arg == NULL)
317 return -1;
318
6e2e5ec2
AG
319 /* copy tcipt_globals because .opts will be modified by iptables */
320 struct xtables_globals tmp_tcipt_globals = tcipt_globals;
321
322 xtables_init_all(&tmp_tcipt_globals, NFPROTO_IPV4);
a36ceb85
AH
323 set_lib_dir();
324
325 parse_rtattr_nested(tb, TCA_IPT_MAX, arg);
326
327 if (tb[TCA_IPT_TABLE] == NULL) {
328 fprintf(f, "[NULL ipt table name ] assuming mangle ");
329 } else {
330 fprintf(f, "tablename: %s ",
ff24746c 331 rta_getattr_str(tb[TCA_IPT_TABLE]));
a36ceb85
AH
332 }
333
334 if (tb[TCA_IPT_HOOK] == NULL) {
335 fprintf(f, "[NULL ipt hook name ]\n ");
336 return -1;
337 } else {
338 __u32 hook;
32a121cb 339
ff24746c 340 hook = rta_getattr_u32(tb[TCA_IPT_HOOK]);
32a121cb 341 fprintf(f, " hook: %s\n", ipthooks[hook]);
a36ceb85
AH
342 }
343
344 if (tb[TCA_IPT_TARG] == NULL) {
32a121cb 345 fprintf(f, "\t[NULL ipt target parameters ]\n");
a36ceb85 346 return -1;
b45f9141
PS
347 }
348
349 t = RTA_DATA(tb[TCA_IPT_TARG]);
350 m = xtables_find_target(t->u.user.name, XTF_TRY_LOAD);
351 if (!m) {
352 fprintf(stderr, " failed to find target %s\n\n",
353 t->u.user.name);
354 return -1;
355 }
356 if (build_st(m, t) < 0) {
357 fprintf(stderr, " %s error\n", m->name);
358 return -1;
359 }
a36ceb85 360
2ef40085
PS
361 if (get_xtables_target_opts(&tmp_tcipt_globals, m) < 0) {
362 fprintf(stderr,
4b83a08c 363 " failed to find additional options for target %s\n\n",
2ef40085 364 t->u.user.name);
b45f9141 365 return -1;
2ef40085 366 }
b45f9141
PS
367 fprintf(f, "\ttarget ");
368 m->print(NULL, m->t, 0);
369 if (tb[TCA_IPT_INDEX] == NULL) {
370 fprintf(f, " [NULL ipt target index ]\n");
371 } else {
372 __u32 index;
32a121cb 373
b45f9141
PS
374 index = rta_getattr_u32(tb[TCA_IPT_INDEX]);
375 fprintf(f, "\n\tindex %d", index);
376 }
a36ceb85 377
b45f9141
PS
378 if (tb[TCA_IPT_CNT]) {
379 struct tc_cnt *c = RTA_DATA(tb[TCA_IPT_CNT]);
32a121cb 380
b45f9141
PS
381 fprintf(f, " ref %d bind %d", c->refcnt, c->bindcnt);
382 }
383 if (show_stats) {
384 if (tb[TCA_IPT_TM]) {
385 struct tcf_t *tm = RTA_DATA(tb[TCA_IPT_TM]);
32a121cb 386
b45f9141 387 print_tm(f, tm);
a36ceb85 388 }
a36ceb85 389 }
b45f9141
PS
390 fprintf(f, "\n");
391
a36ceb85
AH
392 xtables_free_opts(1);
393
394 return 0;
395}
396
8e91a80d 397struct action_util xt_action_util = {
32a121cb
SH
398 .id = "xt",
399 .parse_aopt = parse_ipt,
400 .print_aopt = print_ipt,
a36ceb85 401};