int wrap_tpcall(unsigned int c, char **argv, int inv, struct xtables_target *t, struct xt_entry_target *tt, void *fw) { int rv = 1; int err; if ((err = setjmp(env)) == 0) { t->t = tt; // FIXME: See above. xtables_option_tpcall(c, argv, inv, t, fw); } else { errno = err; } return rv; }
static int parse_ipt(struct action_util *a,int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) { struct xtables_target *m = NULL; struct ipt_entry fw; struct rtattr *tail; int c; int rargc = *argc_p; char **argv = *argv_p; int argc = 0, iargc = 0; char k[16]; int size = 0; int iok = 0, ok = 0; __u32 hook = 0, index = 0; struct option *opts = NULL; xtables_init_all(&tcipt_globals, NFPROTO_IPV4); set_lib_dir(); { int i; for (i = 0; i < rargc; i++) { if (NULL == argv[i] || 0 == strcmp(argv[i], "action")) { break; } } iargc = argc = i; } if (argc <= 2) { fprintf(stderr,"bad arguements to ipt %d vs %d \n", argc, rargc); return -1; } while (1) { c = getopt_long(argc, argv, "j:", tcipt_globals.opts, NULL); if (c == -1) break; switch (c) { case 'j': m = xtables_find_target(optarg, XTF_TRY_LOAD); if (NULL != m) { if (0 > build_st(m, NULL)) { printf(" %s error \n", m->name); return -1; } #if (XTABLES_VERSION_CODE >= 6) opts = xtables_options_xfrm(tcipt_globals.orig_opts, tcipt_globals.opts, m->x6_options, &m->option_offset); #else opts = xtables_merge_options(tcipt_globals.orig_opts, tcipt_globals.opts, m->extra_opts, &m->option_offset); #endif if (opts == NULL) { fprintf(stderr, " failed to find aditional options for target %s\n\n", optarg); return -1; } else tcipt_globals.opts = opts; } else { fprintf(stderr," failed to find target %s\n\n", optarg); return -1; } ok++; break; default: memset(&fw, 0, sizeof (fw)); #if (XTABLES_VERSION_CODE >= 6) if (m != NULL && m->x6_parse != NULL ) { xtables_option_tpcall(c, argv, 0 , m, NULL); #else if (m != NULL && m->parse != NULL ) { m->parse(c - m->option_offset, argv, 0, &m->tflags, NULL, &m->t); #endif } else { fprintf(stderr,"failed to find target %s\n\n", optarg); return -1; } ok++; break; } } if (iargc > optind) { if (matches(argv[optind], "index") == 0) { if (get_u32(&index, argv[optind + 1], 10)) { fprintf(stderr, "Illegal \"index\"\n"); xtables_free_opts(1); return -1; } iok++; optind += 2; } } if (!ok && !iok) { fprintf(stderr," ipt Parser BAD!! (%s)\n", *argv); return -1; } /* check that we passed the correct parameters to the target */ #if (XTABLES_VERSION_CODE >= 6) if (m) xtables_option_tfcall(m); #else if (m && m->final_check) m->final_check(m->tflags); #endif { struct tcmsg *t = NLMSG_DATA(n); if (t->tcm_parent != TC_H_ROOT && t->tcm_parent == TC_H_MAJ(TC_H_INGRESS)) { hook = NF_IP_PRE_ROUTING; } else { hook = NF_IP_POST_ROUTING; } } tail = NLMSG_TAIL(n); addattr_l(n, MAX_MSG, tca_id, NULL, 0); fprintf(stdout, "tablename: %s hook: %s\n ", tname, ipthooks[hook]); fprintf(stdout, "\ttarget: "); if (m) m->print(NULL, m->t, 0); fprintf(stdout, " index %d\n", index); if (strlen(tname) > 16) { size = 16; k[15] = 0; } else { size = 1 + strlen(tname); } strncpy(k, tname, size); addattr_l(n, MAX_MSG, TCA_IPT_TABLE, k, size); addattr_l(n, MAX_MSG, TCA_IPT_HOOK, &hook, 4); addattr_l(n, MAX_MSG, TCA_IPT_INDEX, &index, 4); if (m) addattr_l(n, MAX_MSG, TCA_IPT_TARG, m->t, m->t->u.target_size); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; argc -= optind; argv += optind; *argc_p = rargc - iargc; *argv_p = argv; optind = 0; xtables_free_opts(1); if (m) { /* Clear flags if target will be used again */ m->tflags = 0; m->used = 0; /* Free allocated memory */ if (m->t) free(m->t); } return 0; } static int print_ipt(struct action_util *au,FILE * f, struct rtattr *arg) { struct rtattr *tb[TCA_IPT_MAX + 1]; struct xt_entry_target *t = NULL; struct option *opts = NULL; if (arg == NULL) return -1; xtables_init_all(&tcipt_globals, NFPROTO_IPV4); set_lib_dir(); parse_rtattr_nested(tb, TCA_IPT_MAX, arg); if (tb[TCA_IPT_TABLE] == NULL) { fprintf(f, "[NULL ipt table name ] assuming mangle "); } else { fprintf(f, "tablename: %s ", rta_getattr_str(tb[TCA_IPT_TABLE])); } if (tb[TCA_IPT_HOOK] == NULL) { fprintf(f, "[NULL ipt hook name ]\n "); return -1; } else { __u32 hook; hook = rta_getattr_u32(tb[TCA_IPT_HOOK]); fprintf(f, " hook: %s \n", ipthooks[hook]); } if (tb[TCA_IPT_TARG] == NULL) { fprintf(f, "\t[NULL ipt target parameters ] \n"); return -1; } else { struct xtables_target *m = NULL; t = RTA_DATA(tb[TCA_IPT_TARG]); m = xtables_find_target(t->u.user.name, XTF_TRY_LOAD); if (NULL != m) { if (0 > build_st(m, t)) { fprintf(stderr, " %s error \n", m->name); return -1; } #if (XTABLES_VERSION_CODE >= 6) opts = xtables_options_xfrm(tcipt_globals.orig_opts, tcipt_globals.opts, m->x6_options, &m->option_offset); #else opts = xtables_merge_options(tcipt_globals.orig_opts, tcipt_globals.opts, m->extra_opts, &m->option_offset); #endif if (opts == NULL) { fprintf(stderr, " failed to find aditional options for target %s\n\n", optarg); return -1; } else tcipt_globals.opts = opts; } else { fprintf(stderr, " failed to find target %s\n\n", t->u.user.name); return -1; } fprintf(f, "\ttarget "); m->print(NULL, m->t, 0); if (tb[TCA_IPT_INDEX] == NULL) { fprintf(f, " [NULL ipt target index ]\n"); } else { __u32 index; index = rta_getattr_u32(tb[TCA_IPT_INDEX]); fprintf(f, " \n\tindex %d", index); } if (tb[TCA_IPT_CNT]) { struct tc_cnt *c = RTA_DATA(tb[TCA_IPT_CNT]);; fprintf(f, " ref %d bind %d", c->refcnt, c->bindcnt); } if (show_stats) { if (tb[TCA_IPT_TM]) { struct tcf_t *tm = RTA_DATA(tb[TCA_IPT_TM]); print_tm(f,tm); } } fprintf(f, " \n"); } xtables_free_opts(1); return 0; } struct action_util xt_action_util = { .id = "xt", .parse_aopt = parse_ipt, .print_aopt = print_ipt, };
int command_default(struct iptables_command_state *cs, struct xtables_globals *gl) { struct xtables_rule_match *matchp; struct xtables_match *m; if (cs->target != NULL && (cs->target->parse != NULL || cs->target->x6_parse != NULL) && cs->c >= cs->target->option_offset && cs->c < cs->target->option_offset + XT_OPTION_OFFSET_SCALE) { xtables_option_tpcall(cs->c, cs->argv, cs->invert, cs->target, &cs->fw); return 0; } for (matchp = cs->matches; matchp; matchp = matchp->next) { m = matchp->match; if (matchp->completed || (m->x6_parse == NULL && m->parse == NULL)) continue; if (cs->c < matchp->match->option_offset || cs->c >= matchp->match->option_offset + XT_OPTION_OFFSET_SCALE) continue; xtables_option_mpcall(cs->c, cs->argv, cs->invert, m, &cs->fw); return 0; } /* Try loading protocol */ m = load_proto(cs); if (m != NULL) { size_t size; cs->proto_used = 1; size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size; m->m = xtables_calloc(1, size); m->m->u.match_size = size; strcpy(m->m->u.user.name, m->name); m->m->u.user.revision = m->revision; xs_init_match(m); if (m->x6_options != NULL) gl->opts = xtables_options_xfrm(gl->orig_opts, gl->opts, m->x6_options, &m->option_offset); else gl->opts = xtables_merge_options(gl->orig_opts, gl->opts, m->extra_opts, &m->option_offset); if (gl->opts == NULL) xtables_error(OTHER_PROBLEM, "can't alloc memory!"); optind--; /* Indicate to rerun getopt *immediately* */ return 1; } if (cs->c == ':') xtables_error(PARAMETER_PROBLEM, "option \"%s\" " "requires an argument", cs->argv[optind-1]); if (cs->c == '?') xtables_error(PARAMETER_PROBLEM, "unknown option " "\"%s\"", cs->argv[optind-1]); xtables_error(PARAMETER_PROBLEM, "Unknown arg \"%s\"", optarg); return 0; }
int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table) { struct arptables_command_state cs; int invert = 0; unsigned int nsaddrs = 0, ndaddrs = 0; struct in_addr *saddrs = NULL, *daddrs = NULL; int c, verbose = 0; const char *chain = NULL; const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL; const char *policy = NULL, *newname = NULL; unsigned int rulenum = 0, options = 0, command = 0; const char *pcnt = NULL, *bcnt = NULL; int ret = 1; struct xtables_target *t; memset(&cs, 0, sizeof(cs)); cs.jumpto = ""; opts = original_opts; global_option_offset = 0; xtables_globals.orig_opts = original_opts; /* re-set optind to 0 in case do_command gets called * a second time */ optind = 0; for (t = xtables_targets; t; t = t->next) { t->tflags = 0; t->used = 0; } /* Suppress error messages: we may add new options if we demand-load a protocol. */ opterr = 0; while ((c = getopt_long(argc, argv, "-A:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:l:i:vnt:m:c:", opts, NULL)) != -1) { switch (c) { /* * Command selection */ case 'A': add_command(&command, CMD_APPEND, CMD_NONE, invert); chain = optarg; break; case 'D': add_command(&command, CMD_DELETE, CMD_NONE, invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') { rulenum = parse_rulenumber(argv[optind++]); command = CMD_DELETE_NUM; } break; case 'R': add_command(&command, CMD_REPLACE, CMD_NONE, invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') rulenum = parse_rulenumber(argv[optind++]); else xtables_error(PARAMETER_PROBLEM, "-%c requires a rule number", cmd2char(CMD_REPLACE)); break; case 'I': add_command(&command, CMD_INSERT, CMD_NONE, invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') rulenum = parse_rulenumber(argv[optind++]); else rulenum = 1; break; case 'L': add_command(&command, CMD_LIST, CMD_ZERO, invert); if (optarg) chain = optarg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') chain = argv[optind++]; break; case 'F': add_command(&command, CMD_FLUSH, CMD_NONE, invert); if (optarg) chain = optarg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') chain = argv[optind++]; break; case 'Z': add_command(&command, CMD_ZERO, CMD_LIST, invert); if (optarg) chain = optarg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') chain = argv[optind++]; break; case 'N': if (optarg && *optarg == '-') xtables_error(PARAMETER_PROBLEM, "chain name not allowed to start " "with `-'\n"); if (xtables_find_target(optarg, XTF_TRY_LOAD)) xtables_error(PARAMETER_PROBLEM, "chain name may not clash " "with target name\n"); add_command(&command, CMD_NEW_CHAIN, CMD_NONE, invert); chain = optarg; break; case 'X': add_command(&command, CMD_DELETE_CHAIN, CMD_NONE, invert); if (optarg) chain = optarg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') chain = argv[optind++]; break; case 'E': add_command(&command, CMD_RENAME_CHAIN, CMD_NONE, invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') newname = argv[optind++]; else xtables_error(PARAMETER_PROBLEM, "-%c requires old-chain-name and " "new-chain-name", cmd2char(CMD_RENAME_CHAIN)); break; case 'P': add_command(&command, CMD_SET_POLICY, CMD_NONE, invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') policy = argv[optind++]; else xtables_error(PARAMETER_PROBLEM, "-%c requires a chain and a policy", cmd2char(CMD_SET_POLICY)); break; case 'h': if (!optarg) optarg = argv[optind]; exit_printhelp(); break; case 's': check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_S_IP, &cs.fw.arp.invflags, invert); shostnetworkmask = argv[optind-1]; break; case 'd': check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_D_IP, &cs.fw.arp.invflags, invert); dhostnetworkmask = argv[optind-1]; break; case 2:/* src-mac */ check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_S_MAC, &cs.fw.arp.invflags, invert); if (getmac_and_mask(argv[optind - 1], cs.fw.arp.src_devaddr.addr, cs.fw.arp.src_devaddr.mask)) xtables_error(PARAMETER_PROBLEM, "Problem with specified " "source mac"); break; case 3:/* dst-mac */ check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_D_MAC, &cs.fw.arp.invflags, invert); if (getmac_and_mask(argv[optind - 1], cs.fw.arp.tgt_devaddr.addr, cs.fw.arp.tgt_devaddr.mask)) xtables_error(PARAMETER_PROBLEM, "Problem with specified " "destination mac"); break; case 'l':/* hardware length */ check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_H_LENGTH, &cs.fw.arp.invflags, invert); getlength_and_mask(argv[optind - 1], &cs.fw.arp.arhln, &cs.fw.arp.arhln_mask); if (cs.fw.arp.arhln != 6) { xtables_error(PARAMETER_PROBLEM, "Only harware address length of" " 6 is supported currently."); } break; case 8:/* protocol length */ xtables_error(PARAMETER_PROBLEM, "not supported"); /* check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_P_LENGTH, &cs.fw.arp.invflags, invert); getlength_and_mask(argv[optind - 1], &cs.fw.arp.arpln, &cs.fw.arp.arpln_mask); break; */ case 4:/* opcode */ check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_OPCODE, &cs.fw.arp.invflags, invert); if (get16_and_mask(argv[optind - 1], &cs.fw.arp.arpop, &cs.fw.arp.arpop_mask, 10)) { int i; for (i = 0; i < NUMOPCODES; i++) if (!strcasecmp(opcodes[i], optarg)) break; if (i == NUMOPCODES) xtables_error(PARAMETER_PROBLEM, "Problem with specified opcode"); cs.fw.arp.arpop = htons(i+1); } break; case 5:/* h-type */ check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_H_TYPE, &cs.fw.arp.invflags, invert); if (get16_and_mask(argv[optind - 1], &cs.fw.arp.arhrd, &cs.fw.arp.arhrd_mask, 16)) { if (strcasecmp(argv[optind-1], "Ethernet")) xtables_error(PARAMETER_PROBLEM, "Problem with specified hardware type"); cs.fw.arp.arhrd = htons(1); } break; case 6:/* proto-type */ check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_P_TYPE, &cs.fw.arp.invflags, invert); if (get16_and_mask(argv[optind - 1], &cs.fw.arp.arpro, &cs.fw.arp.arpro_mask, 0)) { if (strcasecmp(argv[optind-1], "ipv4")) xtables_error(PARAMETER_PROBLEM, "Problem with specified protocol type"); cs.fw.arp.arpro = htons(0x800); } break; case 'j': set_option(&options, OPT_JUMP, &cs.fw.arp.invflags, invert); cs.jumpto = parse_target(optarg); cs.target = command_jump(&cs.fw, cs.jumpto); break; case 'i': check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_VIANAMEIN, &cs.fw.arp.invflags, invert); parse_interface(argv[optind-1], cs.fw.arp.iniface, cs.fw.arp.iniface_mask); /* cs.fw.nfcache |= NFC_IP_IF_IN; */ break; case 'o': check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_VIANAMEOUT, &cs.fw.arp.invflags, invert); parse_interface(argv[optind-1], cs.fw.arp.outiface, cs.fw.arp.outiface_mask); /* cs.fw.nfcache |= NFC_IP_IF_OUT; */ break; case 'v': if (!verbose) set_option(&options, OPT_VERBOSE, &cs.fw.arp.invflags, invert); verbose++; break; case 'm': /*{ size_t size; if (invert) exit_error(PARAMETER_PROBLEM, "unexpected ! flag before --match"); m = find_match(optarg, LOAD_MUST_SUCCEED); size = ARPT_ALIGN(sizeof(struct arpt_entry_match)) + m->size; m->m = fw_calloc(1, size); m->m->u.match_size = size; strcpy(m->m->u.user.name, m->name); m->init(m->m, &fw.nfcache); opts = merge_options(opts, m->extra_opts, &m->option_offset); }*/ break; case 'n': set_option(&options, OPT_NUMERIC, &cs.fw.arp.invflags, invert); break; case 't': if (invert) xtables_error(PARAMETER_PROBLEM, "unexpected ! flag before --table"); *table = argv[optind-1]; break; case 'V': if (invert) printf("Not %s ;-)\n", program_version); else printf("%s v%s\n", program_name, program_version); exit(0); case '0': set_option(&options, OPT_LINENUMBERS, &cs.fw.arp.invflags, invert); break; case 'M': //modprobe = optarg; break; case 'c': set_option(&options, OPT_COUNTERS, &cs.fw.arp.invflags, invert); pcnt = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') bcnt = argv[optind++]; else xtables_error(PARAMETER_PROBLEM, "-%c requires packet and byte counter", opt2char(OPT_COUNTERS)); if (sscanf(pcnt, "%llu", &cs.fw.counters.pcnt) != 1) xtables_error(PARAMETER_PROBLEM, "-%c packet counter not numeric", opt2char(OPT_COUNTERS)); if (sscanf(bcnt, "%llu", &cs.fw.counters.bcnt) != 1) xtables_error(PARAMETER_PROBLEM, "-%c byte counter not numeric", opt2char(OPT_COUNTERS)); break; case 1: /* non option */ if (optarg[0] == '!' && optarg[1] == '\0') { if (invert) xtables_error(PARAMETER_PROBLEM, "multiple consecutive ! not" " allowed"); invert = TRUE; optarg[0] = '\0'; continue; } printf("Bad argument `%s'\n", optarg); exit_tryhelp(2); default: if (cs.target) { xtables_option_tpcall(c, argv, invert, cs.target, &cs.fw); } break; } invert = FALSE; } if (cs.target) xtables_option_tfcall(cs.target); if (optind < argc) xtables_error(PARAMETER_PROBLEM, "unknown arguments found on commandline"); if (!command) xtables_error(PARAMETER_PROBLEM, "no command specified"); if (invert) xtables_error(PARAMETER_PROBLEM, "nothing appropriate following !"); if (command & (CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND)) { if (!(options & OPT_D_IP)) dhostnetworkmask = "0.0.0.0/0"; if (!(options & OPT_S_IP)) shostnetworkmask = "0.0.0.0/0"; } if (shostnetworkmask) parse_hostnetworkmask(shostnetworkmask, &saddrs, &(cs.fw.arp.smsk), &nsaddrs); if (dhostnetworkmask) parse_hostnetworkmask(dhostnetworkmask, &daddrs, &(cs.fw.arp.tmsk), &ndaddrs); if ((nsaddrs > 1 || ndaddrs > 1) && (cs.fw.arp.invflags & (ARPT_INV_SRCIP | ARPT_INV_TGTIP))) xtables_error(PARAMETER_PROBLEM, "! not allowed with multiple" " source or destination IP addresses"); if (command == CMD_REPLACE && (nsaddrs != 1 || ndaddrs != 1)) xtables_error(PARAMETER_PROBLEM, "Replacement rule does not " "specify a unique address"); generic_opt_check(command, options); if (chain && strlen(chain) > ARPT_FUNCTION_MAXNAMELEN) xtables_error(PARAMETER_PROBLEM, "chain name `%s' too long (must be under %i chars)", chain, ARPT_FUNCTION_MAXNAMELEN); if (nft_init(h, xtables_arp) < 0) xtables_error(OTHER_PROBLEM, "Could not initialize nftables layer."); h->ops = nft_family_ops_lookup(h->family); if (h->ops == NULL) xtables_error(PARAMETER_PROBLEM, "Unknown family"); if (command == CMD_APPEND || command == CMD_DELETE || command == CMD_INSERT || command == CMD_REPLACE) { if (strcmp(chain, "PREROUTING") == 0 || strcmp(chain, "INPUT") == 0) { /* -o not valid with incoming packets. */ if (options & OPT_VIANAMEOUT) xtables_error(PARAMETER_PROBLEM, "Can't use -%c with %s\n", opt2char(OPT_VIANAMEOUT), chain); } if (strcmp(chain, "POSTROUTING") == 0 || strcmp(chain, "OUTPUT") == 0) { /* -i not valid with outgoing packets */ if (options & OPT_VIANAMEIN) xtables_error(PARAMETER_PROBLEM, "Can't use -%c with %s\n", opt2char(OPT_VIANAMEIN), chain); } if (!cs.target && strlen(cs.jumpto) != 0) { size_t size; cs.target = xtables_find_target(XT_STANDARD_TARGET, XTF_LOAD_MUST_SUCCEED); size = sizeof(struct arpt_entry_target) + cs.target->size; cs.target->t = xtables_calloc(1, size); cs.target->t->u.target_size = size; strcpy(cs.target->t->u.user.name, cs.jumpto); } } switch (command) { case CMD_APPEND: ret = append_entry(h, chain, *table, &cs, 0, nsaddrs, saddrs, ndaddrs, daddrs, options&OPT_VERBOSE, true); break; case CMD_DELETE: ret = delete_entry(chain, *table, &cs, nsaddrs, saddrs, ndaddrs, daddrs, options&OPT_VERBOSE, h); break; case CMD_DELETE_NUM: ret = nft_rule_delete_num(h, chain, *table, rulenum - 1, verbose); break; case CMD_REPLACE: ret = replace_entry(chain, *table, &cs, rulenum - 1, saddrs, daddrs, options&OPT_VERBOSE, h); break; case CMD_INSERT: ret = append_entry(h, chain, *table, &cs, rulenum - 1, nsaddrs, saddrs, ndaddrs, daddrs, options&OPT_VERBOSE, false); break; case CMD_LIST: ret = list_entries(h, chain, *table, rulenum, options&OPT_VERBOSE, options&OPT_NUMERIC, /*options&OPT_EXPANDED*/0, options&OPT_LINENUMBERS); break; case CMD_FLUSH: ret = nft_rule_flush(h, chain, *table); break; case CMD_ZERO: ret = nft_chain_zero_counters(h, chain, *table); break; case CMD_LIST|CMD_ZERO: ret = list_entries(h, chain, *table, rulenum, options&OPT_VERBOSE, options&OPT_NUMERIC, /*options&OPT_EXPANDED*/0, options&OPT_LINENUMBERS); if (ret) ret = nft_chain_zero_counters(h, chain, *table); break; case CMD_NEW_CHAIN: ret = nft_chain_user_add(h, chain, *table); break; case CMD_DELETE_CHAIN: ret = nft_chain_user_del(h, chain, *table); break; case CMD_RENAME_CHAIN: ret = nft_chain_user_rename(h, chain, *table, newname); break; case CMD_SET_POLICY: ret = nft_chain_set(h, *table, chain, policy, NULL); if (ret < 0) xtables_error(PARAMETER_PROBLEM, "Wrong policy `%s'\n", policy); break; default: /* We should never reach this... */ exit_tryhelp(2); } /* if (verbose > 1) dump_entries(*handle);*/ return ret; }