configure: Avoid addition assignment operators
[iptables-mirror.git] / iptables / ip6tables.c
blobf9ae18aed8041e7c90bfe9a2a38df268150b035d
1 /* Code to take an ip6tables-style command line and do it. */
3 /*
4 * Author: Paul.Russell@rustcorp.com.au and mneuling@radlogic.com.au
6 * (C) 2000-2002 by the netfilter coreteam <coreteam@netfilter.org>:
7 * Paul 'Rusty' Russell <rusty@rustcorp.com.au>
8 * Marc Boucher <marc+nf@mbsi.ca>
9 * James Morris <jmorris@intercode.com.au>
10 * Harald Welte <laforge@gnumonks.org>
11 * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include "config.h"
28 #include <getopt.h>
29 #include <string.h>
30 #include <netdb.h>
31 #include <errno.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <ctype.h>
35 #include <stdarg.h>
36 #include <stdbool.h>
37 #include <limits.h>
38 #include <ip6tables.h>
39 #include <xtables.h>
40 #include <arpa/inet.h>
41 #include <unistd.h>
42 #include <fcntl.h>
43 #include <sys/types.h>
44 #include <sys/socket.h>
45 #include "ip6tables-multi.h"
46 #include "xshared.h"
48 static const char unsupported_rev[] = " [unsupported revision]";
50 static struct option original_opts[] = {
51 {.name = "append", .has_arg = 1, .val = 'A'},
52 {.name = "delete", .has_arg = 1, .val = 'D'},
53 {.name = "check" , .has_arg = 1, .val = 'C'},
54 {.name = "insert", .has_arg = 1, .val = 'I'},
55 {.name = "replace", .has_arg = 1, .val = 'R'},
56 {.name = "list", .has_arg = 2, .val = 'L'},
57 {.name = "list-rules", .has_arg = 2, .val = 'S'},
58 {.name = "flush", .has_arg = 2, .val = 'F'},
59 {.name = "zero", .has_arg = 2, .val = 'Z'},
60 {.name = "new-chain", .has_arg = 1, .val = 'N'},
61 {.name = "delete-chain", .has_arg = 2, .val = 'X'},
62 {.name = "rename-chain", .has_arg = 1, .val = 'E'},
63 {.name = "policy", .has_arg = 1, .val = 'P'},
64 {.name = "source", .has_arg = 1, .val = 's'},
65 {.name = "destination", .has_arg = 1, .val = 'd'},
66 {.name = "src", .has_arg = 1, .val = 's'}, /* synonym */
67 {.name = "dst", .has_arg = 1, .val = 'd'}, /* synonym */
68 {.name = "protocol", .has_arg = 1, .val = 'p'},
69 {.name = "in-interface", .has_arg = 1, .val = 'i'},
70 {.name = "jump", .has_arg = 1, .val = 'j'},
71 {.name = "table", .has_arg = 1, .val = 't'},
72 {.name = "match", .has_arg = 1, .val = 'm'},
73 {.name = "numeric", .has_arg = 0, .val = 'n'},
74 {.name = "out-interface", .has_arg = 1, .val = 'o'},
75 {.name = "verbose", .has_arg = 0, .val = 'v'},
76 {.name = "wait", .has_arg = 2, .val = 'w'},
77 {.name = "wait-interval", .has_arg = 2, .val = 'W'},
78 {.name = "exact", .has_arg = 0, .val = 'x'},
79 {.name = "version", .has_arg = 0, .val = 'V'},
80 {.name = "help", .has_arg = 2, .val = 'h'},
81 {.name = "line-numbers", .has_arg = 0, .val = '0'},
82 {.name = "modprobe", .has_arg = 1, .val = 'M'},
83 {.name = "set-counters", .has_arg = 1, .val = 'c'},
84 {.name = "goto", .has_arg = 1, .val = 'g'},
85 {.name = "ipv4", .has_arg = 0, .val = '4'},
86 {.name = "ipv6", .has_arg = 0, .val = '6'},
87 {NULL},
90 struct xtables_globals ip6tables_globals = {
91 .option_offset = 0,
92 .program_version = PACKAGE_VERSION " (legacy)",
93 .orig_opts = original_opts,
94 .compat_rev = xtables_compatible_revision,
98 * All functions starting with "parse" should succeed, otherwise
99 * the program fails.
100 * Most routines return pointers to static data that may change
101 * between calls to the same or other routines with a few exceptions:
102 * "host_to_addr", "parse_hostnetwork", and "parse_hostnetworkmask"
103 * return global static data.
106 static int
107 print_match(const struct xt_entry_match *m,
108 const struct ip6t_ip6 *ip,
109 int numeric)
111 const char *name = m->u.user.name;
112 const int revision = m->u.user.revision;
113 struct xtables_match *match, *mt;
115 match = xtables_find_match(name, XTF_TRY_LOAD, NULL);
116 if (match) {
117 mt = xtables_find_match_revision(name, XTF_TRY_LOAD,
118 match, revision);
119 if (mt && mt->print)
120 mt->print(ip, m, numeric);
121 else if (match->print)
122 printf("%s%s ", match->name, unsupported_rev);
123 else
124 printf("%s ", match->name);
126 if (match->next == match)
127 free(match);
128 } else {
129 if (name[0])
130 printf("UNKNOWN match `%s' ", name);
132 /* Don't stop iterating. */
133 return 0;
136 /* e is called `fw' here for historical reasons */
137 static void
138 print_firewall(const struct ip6t_entry *fw,
139 const char *targname,
140 unsigned int num,
141 unsigned int format,
142 struct xtc_handle *const handle)
144 struct xtables_target *target, *tg;
145 const struct xt_entry_target *t;
147 if (!ip6tc_is_chain(targname, handle))
148 target = xtables_find_target(targname, XTF_TRY_LOAD);
149 else
150 target = xtables_find_target(XT_STANDARD_TARGET,
151 XTF_LOAD_MUST_SUCCEED);
153 t = ip6t_get_target((struct ip6t_entry *)fw);
155 print_rule_details(num, &fw->counters, targname, fw->ipv6.proto,
156 fw->ipv6.flags, fw->ipv6.invflags, format);
158 print_fragment(fw->ipv6.flags, fw->ipv6.invflags, format, true);
160 print_ifaces(fw->ipv6.iniface, fw->ipv6.outiface,
161 fw->ipv6.invflags, format);
163 print_ipv6_addresses(fw, format);
165 if (format & FMT_NOTABLE)
166 fputs(" ", stdout);
168 #ifdef IP6T_F_GOTO
169 if(fw->ipv6.flags & IP6T_F_GOTO)
170 printf("[goto] ");
171 #endif
173 IP6T_MATCH_ITERATE(fw, print_match, &fw->ipv6, format & FMT_NUMERIC);
175 if (target) {
176 const int revision = t->u.user.revision;
178 tg = xtables_find_target_revision(targname, XTF_TRY_LOAD,
179 target, revision);
180 if (tg && tg->print)
181 /* Print the target information. */
182 tg->print(&fw->ipv6, t, format & FMT_NUMERIC);
183 else if (target->print)
184 printf(" %s%s", target->name, unsupported_rev);
186 if (target->next == target)
187 free(target);
188 } else if (t->u.target_size != sizeof(*t))
189 printf("[%u bytes of unknown target data] ",
190 (unsigned int)(t->u.target_size - sizeof(*t)));
192 if (!(format & FMT_NONEWLINE))
193 fputc('\n', stdout);
196 static void
197 print_firewall_line(const struct ip6t_entry *fw,
198 struct xtc_handle *const h)
200 struct xt_entry_target *t;
202 t = ip6t_get_target((struct ip6t_entry *)fw);
203 print_firewall(fw, t->u.user.name, 0, FMT_PRINT_RULE, h);
206 static int
207 append_entry(const xt_chainlabel chain,
208 struct ip6t_entry *fw,
209 unsigned int nsaddrs,
210 const struct in6_addr saddrs[],
211 const struct in6_addr smasks[],
212 unsigned int ndaddrs,
213 const struct in6_addr daddrs[],
214 const struct in6_addr dmasks[],
215 int verbose,
216 struct xtc_handle *handle)
218 unsigned int i, j;
219 int ret = 1;
221 for (i = 0; i < nsaddrs; i++) {
222 fw->ipv6.src = saddrs[i];
223 fw->ipv6.smsk = smasks[i];
224 for (j = 0; j < ndaddrs; j++) {
225 fw->ipv6.dst = daddrs[j];
226 fw->ipv6.dmsk = dmasks[j];
227 if (verbose)
228 print_firewall_line(fw, handle);
229 ret &= ip6tc_append_entry(chain, fw, handle);
233 return ret;
236 static int
237 replace_entry(const xt_chainlabel chain,
238 struct ip6t_entry *fw,
239 unsigned int rulenum,
240 const struct in6_addr *saddr, const struct in6_addr *smask,
241 const struct in6_addr *daddr, const struct in6_addr *dmask,
242 int verbose,
243 struct xtc_handle *handle)
245 fw->ipv6.src = *saddr;
246 fw->ipv6.dst = *daddr;
247 fw->ipv6.smsk = *smask;
248 fw->ipv6.dmsk = *dmask;
250 if (verbose)
251 print_firewall_line(fw, handle);
252 return ip6tc_replace_entry(chain, fw, rulenum, handle);
255 static int
256 insert_entry(const xt_chainlabel chain,
257 struct ip6t_entry *fw,
258 unsigned int rulenum,
259 unsigned int nsaddrs,
260 const struct in6_addr saddrs[],
261 const struct in6_addr smasks[],
262 unsigned int ndaddrs,
263 const struct in6_addr daddrs[],
264 const struct in6_addr dmasks[],
265 int verbose,
266 struct xtc_handle *handle)
268 unsigned int i, j;
269 int ret = 1;
271 for (i = 0; i < nsaddrs; i++) {
272 fw->ipv6.src = saddrs[i];
273 fw->ipv6.smsk = smasks[i];
274 for (j = 0; j < ndaddrs; j++) {
275 fw->ipv6.dst = daddrs[j];
276 fw->ipv6.dmsk = dmasks[j];
277 if (verbose)
278 print_firewall_line(fw, handle);
279 ret &= ip6tc_insert_entry(chain, fw, rulenum, handle);
283 return ret;
286 static int
287 delete_entry(const xt_chainlabel chain,
288 struct ip6t_entry *fw,
289 unsigned int nsaddrs,
290 const struct in6_addr saddrs[],
291 const struct in6_addr smasks[],
292 unsigned int ndaddrs,
293 const struct in6_addr daddrs[],
294 const struct in6_addr dmasks[],
295 int verbose,
296 struct xtc_handle *handle,
297 struct xtables_rule_match *matches,
298 const struct xtables_target *target)
300 unsigned int i, j;
301 int ret = 1;
302 unsigned char *mask;
304 mask = make_delete_mask(matches, target, sizeof(*fw));
305 for (i = 0; i < nsaddrs; i++) {
306 fw->ipv6.src = saddrs[i];
307 fw->ipv6.smsk = smasks[i];
308 for (j = 0; j < ndaddrs; j++) {
309 fw->ipv6.dst = daddrs[j];
310 fw->ipv6.dmsk = dmasks[j];
311 if (verbose)
312 print_firewall_line(fw, handle);
313 ret &= ip6tc_delete_entry(chain, fw, mask, handle);
316 free(mask);
318 return ret;
321 static int
322 check_entry(const xt_chainlabel chain, struct ip6t_entry *fw,
323 unsigned int nsaddrs, const struct in6_addr *saddrs,
324 const struct in6_addr *smasks, unsigned int ndaddrs,
325 const struct in6_addr *daddrs, const struct in6_addr *dmasks,
326 bool verbose, struct xtc_handle *handle,
327 struct xtables_rule_match *matches,
328 const struct xtables_target *target)
330 unsigned int i, j;
331 int ret = 1;
332 unsigned char *mask;
334 mask = make_delete_mask(matches, target, sizeof(*fw));
335 for (i = 0; i < nsaddrs; i++) {
336 fw->ipv6.src = saddrs[i];
337 fw->ipv6.smsk = smasks[i];
338 for (j = 0; j < ndaddrs; j++) {
339 fw->ipv6.dst = daddrs[j];
340 fw->ipv6.dmsk = dmasks[j];
341 if (verbose)
342 print_firewall_line(fw, handle);
343 ret &= ip6tc_check_entry(chain, fw, mask, handle);
347 free(mask);
348 return ret;
352 for_each_chain6(int (*fn)(const xt_chainlabel, int, struct xtc_handle *),
353 int verbose, int builtinstoo, struct xtc_handle *handle)
355 int ret = 1;
356 const char *chain;
357 char *chains;
358 unsigned int i, chaincount = 0;
360 chain = ip6tc_first_chain(handle);
361 while (chain) {
362 chaincount++;
363 chain = ip6tc_next_chain(handle);
366 chains = xtables_malloc(sizeof(xt_chainlabel) * chaincount);
367 i = 0;
368 chain = ip6tc_first_chain(handle);
369 while (chain) {
370 strcpy(chains + i*sizeof(xt_chainlabel), chain);
371 i++;
372 chain = ip6tc_next_chain(handle);
375 for (i = 0; i < chaincount; i++) {
376 if (!builtinstoo
377 && ip6tc_builtin(chains + i*sizeof(xt_chainlabel),
378 handle) == 1)
379 continue;
380 ret &= fn(chains + i*sizeof(xt_chainlabel), verbose, handle);
383 free(chains);
384 return ret;
388 flush_entries6(const xt_chainlabel chain, int verbose,
389 struct xtc_handle *handle)
391 if (!chain)
392 return for_each_chain6(flush_entries6, verbose, 1, handle);
394 if (verbose)
395 fprintf(stdout, "Flushing chain `%s'\n", chain);
396 return ip6tc_flush_entries(chain, handle);
399 static int
400 zero_entries(const xt_chainlabel chain, int verbose,
401 struct xtc_handle *handle)
403 if (!chain)
404 return for_each_chain6(zero_entries, verbose, 1, handle);
406 if (verbose)
407 fprintf(stdout, "Zeroing chain `%s'\n", chain);
408 return ip6tc_zero_entries(chain, handle);
412 delete_chain6(const xt_chainlabel chain, int verbose,
413 struct xtc_handle *handle)
415 if (!chain)
416 return for_each_chain6(delete_chain6, verbose, 0, handle);
418 if (verbose)
419 fprintf(stdout, "Deleting chain `%s'\n", chain);
420 return ip6tc_delete_chain(chain, handle);
423 static int
424 list_entries(const xt_chainlabel chain, int rulenum, int verbose, int numeric,
425 int expanded, int linenumbers, struct xtc_handle *handle)
427 int found = 0;
428 unsigned int format;
429 const char *this;
431 format = FMT_OPTIONS;
432 if (!verbose)
433 format |= FMT_NOCOUNTS;
434 else
435 format |= FMT_VIA;
437 if (numeric)
438 format |= FMT_NUMERIC;
440 if (!expanded)
441 format |= FMT_KILOMEGAGIGA;
443 if (linenumbers)
444 format |= FMT_LINENUMBERS;
446 for (this = ip6tc_first_chain(handle);
447 this;
448 this = ip6tc_next_chain(handle)) {
449 const struct ip6t_entry *i;
450 unsigned int num;
452 if (chain && strcmp(chain, this) != 0)
453 continue;
455 if (found) printf("\n");
457 if (!rulenum) {
458 struct xt_counters counters;
459 unsigned int urefs;
460 const char *pol;
461 int refs = - 1;
463 pol = ip6tc_get_policy(this, &counters, handle);
464 if (!pol && ip6tc_get_references(&urefs, this, handle))
465 refs = urefs;
467 print_header(format, this, pol, &counters, refs, 0);
469 i = ip6tc_first_rule(this, handle);
471 num = 0;
472 while (i) {
473 num++;
474 if (!rulenum || num == rulenum)
475 print_firewall(i,
476 ip6tc_get_target(i, handle),
477 num,
478 format,
479 handle);
480 i = ip6tc_next_rule(i, handle);
482 found = 1;
485 errno = ENOENT;
486 return found;
489 /* We want this to be readable, so only print out necessary fields.
490 * Because that's the kind of world I want to live in.
492 void print_rule6(const struct ip6t_entry *e,
493 struct xtc_handle *h, const char *chain, int counters)
495 const struct xt_entry_target *t;
496 const char *target_name;
498 /* print counters for iptables-save */
499 if (counters > 0)
500 printf("[%llu:%llu] ", (unsigned long long)e->counters.pcnt, (unsigned long long)e->counters.bcnt);
502 /* print chain name */
503 printf("-A %s", chain);
505 /* Print IP part. */
506 save_ipv6_addr('s', &e->ipv6.src, &e->ipv6.smsk,
507 e->ipv6.invflags & IP6T_INV_SRCIP);
509 save_ipv6_addr('d', &e->ipv6.dst, &e->ipv6.dmsk,
510 e->ipv6.invflags & IP6T_INV_DSTIP);
512 save_rule_details(e->ipv6.iniface, e->ipv6.outiface,
513 e->ipv6.proto, 0, e->ipv6.invflags);
515 #if 0
516 /* not definied in ipv6
517 * FIXME: linux/netfilter_ipv6/ip6_tables: IP6T_INV_FRAG why definied? */
518 if (e->ipv6.flags & IPT_F_FRAG)
519 printf("%s -f",
520 e->ipv6.invflags & IP6T_INV_FRAG ? " !" : "");
521 #endif
523 if (e->ipv6.flags & IP6T_F_TOS)
524 printf("%s -? %d",
525 e->ipv6.invflags & IP6T_INV_TOS ? " !" : "",
526 e->ipv6.tos);
528 /* Print matchinfo part */
529 if (e->target_offset) {
530 IP6T_MATCH_ITERATE(e, print_match_save, &e->ipv6);
533 /* print counters for iptables -R */
534 if (counters < 0)
535 printf(" -c %llu %llu", (unsigned long long)e->counters.pcnt, (unsigned long long)e->counters.bcnt);
537 /* Print target name and targinfo part */
538 target_name = ip6tc_get_target(e, h);
539 t = ip6t_get_target((struct ip6t_entry *)e);
540 if (t->u.user.name[0]) {
541 const char *name = t->u.user.name;
542 const int revision = t->u.user.revision;
543 struct xtables_target *target, *tg, *tg2;
545 target = xtables_find_target(name, XTF_TRY_LOAD);
546 if (!target) {
547 fprintf(stderr, "Can't find library for target `%s'\n",
548 name);
549 exit(1);
552 tg = tg2 = xtables_find_target_revision(name, XTF_TRY_LOAD,
553 target, revision);
554 if (!tg2)
555 tg2 = target;
556 printf(" -j %s", tg2->alias ? tg2->alias(t) : target_name);
558 if (tg && tg->save)
559 tg->save(&e->ipv6, t);
560 else if (target->save)
561 printf(unsupported_rev);
562 else {
563 /* If the target size is greater than xt_entry_target
564 * there is something to be saved, we just don't know
565 * how to print it */
566 if (t->u.target_size !=
567 sizeof(struct xt_entry_target)) {
568 fprintf(stderr, "Target `%s' is missing "
569 "save function\n",
570 name);
571 exit(1);
574 } else if (target_name && (*target_name != '\0'))
575 #ifdef IP6T_F_GOTO
576 printf(" -%c %s", e->ipv6.flags & IP6T_F_GOTO ? 'g' : 'j', target_name);
577 #else
578 printf(" -j %s", target_name);
579 #endif
581 printf("\n");
584 static int
585 list_rules(const xt_chainlabel chain, int rulenum, int counters,
586 struct xtc_handle *handle)
588 const char *this = NULL;
589 int found = 0;
591 if (counters)
592 counters = -1; /* iptables -c format */
594 /* Dump out chain names first,
595 * thereby preventing dependency conflicts */
596 if (!rulenum) for (this = ip6tc_first_chain(handle);
597 this;
598 this = ip6tc_next_chain(handle)) {
599 if (chain && strcmp(this, chain) != 0)
600 continue;
602 if (ip6tc_builtin(this, handle)) {
603 struct xt_counters count;
604 printf("-P %s %s", this, ip6tc_get_policy(this, &count, handle));
605 if (counters)
606 printf(" -c %llu %llu", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt);
607 printf("\n");
608 } else {
609 printf("-N %s\n", this);
613 for (this = ip6tc_first_chain(handle);
614 this;
615 this = ip6tc_next_chain(handle)) {
616 const struct ip6t_entry *e;
617 int num = 0;
619 if (chain && strcmp(this, chain) != 0)
620 continue;
622 /* Dump out rules */
623 e = ip6tc_first_rule(this, handle);
624 while(e) {
625 num++;
626 if (!rulenum || num == rulenum)
627 print_rule6(e, handle, this, counters);
628 e = ip6tc_next_rule(e, handle);
630 found = 1;
633 errno = ENOENT;
634 return found;
637 static struct ip6t_entry *
638 generate_entry(const struct ip6t_entry *fw,
639 struct xtables_rule_match *matches,
640 struct xt_entry_target *target)
642 unsigned int size;
643 struct xtables_rule_match *matchp;
644 struct ip6t_entry *e;
646 size = sizeof(struct ip6t_entry);
647 for (matchp = matches; matchp; matchp = matchp->next)
648 size += matchp->match->m->u.match_size;
650 e = xtables_malloc(size + target->u.target_size);
651 *e = *fw;
652 e->target_offset = size;
653 e->next_offset = size + target->u.target_size;
655 size = 0;
656 for (matchp = matches; matchp; matchp = matchp->next) {
657 memcpy(e->elems + size, matchp->match->m, matchp->match->m->u.match_size);
658 size += matchp->match->m->u.match_size;
660 memcpy(e->elems + size, target, target->u.target_size);
662 return e;
665 int do_command6(int argc, char *argv[], char **table,
666 struct xtc_handle **handle, bool restore)
668 struct xt_cmd_parse_ops cmd_parse_ops = {
669 .proto_parse = ipv6_proto_parse,
670 .post_parse = ipv6_post_parse,
671 .option_name = ip46t_option_name,
672 .option_invert = ip46t_option_invert,
673 .command_default = command_default,
674 .print_help = xtables_printhelp,
676 struct xt_cmd_parse p = {
677 .table = *table,
678 .restore = restore,
679 .line = line,
680 .ops = &cmd_parse_ops,
682 struct iptables_command_state cs = {
683 .jumpto = "",
684 .argv = argv,
686 struct xtables_args args = {
687 .family = AF_INET6,
689 struct ip6t_entry *e = NULL;
690 unsigned int nsaddrs = 0, ndaddrs = 0;
691 struct in6_addr *saddrs = NULL, *daddrs = NULL;
692 struct in6_addr *smasks = NULL, *dmasks = NULL;
694 int verbose = 0;
695 int wait = 0;
696 const char *chain = NULL;
697 const char *policy = NULL, *newname = NULL;
698 unsigned int rulenum = 0, command = 0;
699 int ret = 1;
701 do_parse(argc, argv, &p, &cs, &args);
703 command = p.command;
704 chain = p.chain;
705 *table = p.table;
706 rulenum = p.rulenum;
707 policy = p.policy;
708 newname = p.newname;
709 verbose = p.verbose;
710 wait = args.wait;
711 nsaddrs = args.s.naddrs;
712 ndaddrs = args.d.naddrs;
713 saddrs = args.s.addr.v6;
714 daddrs = args.d.addr.v6;
715 smasks = args.s.mask.v6;
716 dmasks = args.d.mask.v6;
718 iface_to_mask(cs.fw6.ipv6.iniface, cs.fw6.ipv6.iniface_mask);
719 iface_to_mask(cs.fw6.ipv6.outiface, cs.fw6.ipv6.outiface_mask);
721 /* Attempt to acquire the xtables lock */
722 if (!restore)
723 xtables_lock_or_exit(wait);
725 /* only allocate handle if we weren't called with a handle */
726 if (!*handle)
727 *handle = ip6tc_init(*table);
729 /* try to insmod the module if iptc_init failed */
730 if (!*handle && xtables_load_ko(xtables_modprobe_program, false) != -1)
731 *handle = ip6tc_init(*table);
733 if (!*handle)
734 xtables_error(VERSION_PROBLEM,
735 "can't initialize ip6tables table `%s': %s",
736 *table, ip6tc_strerror(errno));
738 if (command == CMD_APPEND
739 || command == CMD_DELETE
740 || command == CMD_CHECK
741 || command == CMD_INSERT
742 || command == CMD_REPLACE) {
743 if (cs.target && ip6tc_is_chain(cs.jumpto, *handle)) {
744 fprintf(stderr,
745 "Warning: using chain %s, not extension\n",
746 cs.jumpto);
748 if (cs.target->t)
749 free(cs.target->t);
751 cs.target = NULL;
754 /* If they didn't specify a target, or it's a chain
755 name, use standard. */
756 if (!cs.target
757 && (strlen(cs.jumpto) == 0
758 || ip6tc_is_chain(cs.jumpto, *handle))) {
759 size_t size;
761 cs.target = xtables_find_target(XT_STANDARD_TARGET,
762 XTF_LOAD_MUST_SUCCEED);
764 size = sizeof(struct xt_entry_target)
765 + cs.target->size;
766 cs.target->t = xtables_calloc(1, size);
767 cs.target->t->u.target_size = size;
768 strcpy(cs.target->t->u.user.name, cs.jumpto);
769 xs_init_target(cs.target);
772 if (!cs.target) {
773 /* It is no chain, and we can't load a plugin.
774 * We cannot know if the plugin is corrupt, non
775 * existent OR if the user just misspelled a
776 * chain.
778 #ifdef IP6T_F_GOTO
779 if (cs.fw6.ipv6.flags & IP6T_F_GOTO)
780 xtables_error(PARAMETER_PROBLEM,
781 "goto '%s' is not a chain",
782 cs.jumpto);
783 #endif
784 xtables_find_target(cs.jumpto, XTF_LOAD_MUST_SUCCEED);
785 } else {
786 e = generate_entry(&cs.fw6, cs.matches, cs.target->t);
790 switch (command) {
791 case CMD_APPEND:
792 ret = append_entry(chain, e,
793 nsaddrs, saddrs, smasks,
794 ndaddrs, daddrs, dmasks,
795 cs.options&OPT_VERBOSE,
796 *handle);
797 break;
798 case CMD_DELETE:
799 ret = delete_entry(chain, e,
800 nsaddrs, saddrs, smasks,
801 ndaddrs, daddrs, dmasks,
802 cs.options&OPT_VERBOSE,
803 *handle, cs.matches, cs.target);
804 break;
805 case CMD_DELETE_NUM:
806 ret = ip6tc_delete_num_entry(chain, rulenum - 1, *handle);
807 break;
808 case CMD_CHECK:
809 ret = check_entry(chain, e,
810 nsaddrs, saddrs, smasks,
811 ndaddrs, daddrs, dmasks,
812 cs.options&OPT_VERBOSE,
813 *handle, cs.matches, cs.target);
814 break;
815 case CMD_REPLACE:
816 ret = replace_entry(chain, e, rulenum - 1,
817 saddrs, smasks, daddrs, dmasks,
818 cs.options&OPT_VERBOSE, *handle);
819 break;
820 case CMD_INSERT:
821 ret = insert_entry(chain, e, rulenum - 1,
822 nsaddrs, saddrs, smasks,
823 ndaddrs, daddrs, dmasks,
824 cs.options&OPT_VERBOSE,
825 *handle);
826 break;
827 case CMD_FLUSH:
828 ret = flush_entries6(chain, cs.options&OPT_VERBOSE, *handle);
829 break;
830 case CMD_ZERO:
831 ret = zero_entries(chain, cs.options&OPT_VERBOSE, *handle);
832 break;
833 case CMD_ZERO_NUM:
834 ret = ip6tc_zero_counter(chain, rulenum, *handle);
835 break;
836 case CMD_LIST:
837 case CMD_LIST|CMD_ZERO:
838 case CMD_LIST|CMD_ZERO_NUM:
839 ret = list_entries(chain,
840 rulenum,
841 cs.options&OPT_VERBOSE,
842 cs.options&OPT_NUMERIC,
843 cs.options&OPT_EXPANDED,
844 cs.options&OPT_LINENUMBERS,
845 *handle);
846 if (ret && (command & CMD_ZERO))
847 ret = zero_entries(chain,
848 cs.options&OPT_VERBOSE, *handle);
849 if (ret && (command & CMD_ZERO_NUM))
850 ret = ip6tc_zero_counter(chain, rulenum, *handle);
851 break;
852 case CMD_LIST_RULES:
853 case CMD_LIST_RULES|CMD_ZERO:
854 case CMD_LIST_RULES|CMD_ZERO_NUM:
855 ret = list_rules(chain,
856 rulenum,
857 cs.options&OPT_VERBOSE,
858 *handle);
859 if (ret && (command & CMD_ZERO))
860 ret = zero_entries(chain,
861 cs.options&OPT_VERBOSE, *handle);
862 if (ret && (command & CMD_ZERO_NUM))
863 ret = ip6tc_zero_counter(chain, rulenum, *handle);
864 break;
865 case CMD_NEW_CHAIN:
866 ret = ip6tc_create_chain(chain, *handle);
867 break;
868 case CMD_DELETE_CHAIN:
869 ret = delete_chain6(chain, cs.options&OPT_VERBOSE, *handle);
870 break;
871 case CMD_RENAME_CHAIN:
872 ret = ip6tc_rename_chain(chain, newname, *handle);
873 break;
874 case CMD_SET_POLICY:
875 ret = ip6tc_set_policy(chain, policy, cs.options&OPT_COUNTERS ? &cs.fw6.counters : NULL, *handle);
876 break;
877 case CMD_NONE:
878 /* do_parse ignored the line (eg: -4 with ip6tables-restore) */
879 break;
880 default:
881 /* We should never reach this... */
882 exit_tryhelp(2, line);
885 if (verbose > 1)
886 dump_entries6(*handle);
888 xtables_clear_iptables_command_state(&cs);
890 if (e != NULL) {
891 free(e);
892 e = NULL;
895 xtables_clear_args(&args);
896 xtables_free_opts(1);
898 return ret;