summaryrefslogtreecommitdiffstats
path: root/iptables/xshared.c
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2021-12-23 19:03:37 +0100
committerPhil Sutter <phil@nwl.cc>2022-01-12 14:08:54 +0100
commit62c3c93d4b0f5f6b9bb6c6829d507b57b976a644 (patch)
treebf02227c4b05acfcbe49695633d87fb319f72628 /iptables/xshared.c
parent3039a52c3ecf96df4e3b815d242f788c189093e1 (diff)
xshared: Move do_parse to shared space
Small adjustments were needed: - Pass line variable via xt_cmd_parse, xshared.c does not have it in namespace. - Replace opts, prog_name and prog_vers defines by the respective xt_params field reference. Signed-off-by: Phil Sutter <phil@nwl.cc>
Diffstat (limited to 'iptables/xshared.c')
-rw-r--r--iptables/xshared.c553
1 files changed, 553 insertions, 0 deletions
diff --git a/iptables/xshared.c b/iptables/xshared.c
index efee7a30..4c8ee3aa 100644
--- a/iptables/xshared.c
+++ b/iptables/xshared.c
@@ -1262,3 +1262,556 @@ void exit_tryhelp(int status, int line)
xtables_free_opts(1);
exit(status);
}
+
+static void check_empty_interface(struct xtables_args *args, const char *arg)
+{
+ const char *msg = "Empty interface is likely to be undesired";
+
+ if (*arg != '\0')
+ return;
+
+ if (args->family != NFPROTO_ARP)
+ xtables_error(PARAMETER_PROBLEM, msg);
+
+ fprintf(stderr, "%s", msg);
+}
+
+static void check_inverse(struct xtables_args *args, const char option[],
+ bool *invert, int *optidx, int argc)
+{
+ switch (args->family) {
+ case NFPROTO_ARP:
+ break;
+ default:
+ return;
+ }
+
+ if (!option || strcmp(option, "!"))
+ return;
+
+ fprintf(stderr, "Using intrapositioned negation (`--option ! this`) "
+ "is deprecated in favor of extrapositioned (`! --option this`).\n");
+
+ if (*invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "Multiple `!' flags not allowed");
+ *invert = true;
+ if (optidx) {
+ *optidx = *optidx + 1;
+ if (argc && *optidx > argc)
+ xtables_error(PARAMETER_PROBLEM,
+ "no argument following `!'");
+ }
+}
+
+void do_parse(int argc, char *argv[],
+ struct xt_cmd_parse *p, struct iptables_command_state *cs,
+ struct xtables_args *args)
+{
+ struct xtables_match *m;
+ struct xtables_rule_match *matchp;
+ bool wait_interval_set = false;
+ struct timeval wait_interval;
+ struct xtables_target *t;
+ bool table_set = false;
+ bool invert = false;
+ int wait = 0;
+
+ /* re-set optind to 0 in case do_command4 gets called
+ * a second time */
+ optind = 0;
+
+ /* clear mflags in case do_command4 gets called a second time
+ * (we clear the global list of all matches for security)*/
+ for (m = xtables_matches; m; m = m->next)
+ m->mflags = 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;
+
+ xt_params->opts = xt_params->orig_opts;
+ while ((cs->c = getopt_long(argc, argv, xt_params->optstring,
+ xt_params->opts, NULL)) != -1) {
+ switch (cs->c) {
+ /*
+ * Command selection
+ */
+ case 'A':
+ add_command(&p->command, CMD_APPEND, CMD_NONE, invert);
+ p->chain = optarg;
+ break;
+
+ case 'C':
+ add_command(&p->command, CMD_CHECK, CMD_NONE, invert);
+ p->chain = optarg;
+ break;
+
+ case 'D':
+ add_command(&p->command, CMD_DELETE, CMD_NONE, invert);
+ p->chain = optarg;
+ if (xs_has_arg(argc, argv)) {
+ p->rulenum = parse_rulenumber(argv[optind++]);
+ p->command = CMD_DELETE_NUM;
+ }
+ break;
+
+ case 'R':
+ add_command(&p->command, CMD_REPLACE, CMD_NONE, invert);
+ p->chain = optarg;
+ if (xs_has_arg(argc, argv))
+ p->rulenum = parse_rulenumber(argv[optind++]);
+ else
+ xtables_error(PARAMETER_PROBLEM,
+ "-%c requires a rule number",
+ cmd2char(CMD_REPLACE));
+ break;
+
+ case 'I':
+ add_command(&p->command, CMD_INSERT, CMD_NONE, invert);
+ p->chain = optarg;
+ if (xs_has_arg(argc, argv))
+ p->rulenum = parse_rulenumber(argv[optind++]);
+ else
+ p->rulenum = 1;
+ break;
+
+ case 'L':
+ add_command(&p->command, CMD_LIST,
+ CMD_ZERO | CMD_ZERO_NUM, invert);
+ if (optarg)
+ p->chain = optarg;
+ else if (xs_has_arg(argc, argv))
+ p->chain = argv[optind++];
+ if (xs_has_arg(argc, argv))
+ p->rulenum = parse_rulenumber(argv[optind++]);
+ break;
+
+ case 'S':
+ add_command(&p->command, CMD_LIST_RULES,
+ CMD_ZERO|CMD_ZERO_NUM, invert);
+ if (optarg)
+ p->chain = optarg;
+ else if (xs_has_arg(argc, argv))
+ p->chain = argv[optind++];
+ if (xs_has_arg(argc, argv))
+ p->rulenum = parse_rulenumber(argv[optind++]);
+ break;
+
+ case 'F':
+ add_command(&p->command, CMD_FLUSH, CMD_NONE, invert);
+ if (optarg)
+ p->chain = optarg;
+ else if (xs_has_arg(argc, argv))
+ p->chain = argv[optind++];
+ break;
+
+ case 'Z':
+ add_command(&p->command, CMD_ZERO,
+ CMD_LIST|CMD_LIST_RULES, invert);
+ if (optarg)
+ p->chain = optarg;
+ else if (xs_has_arg(argc, argv))
+ p->chain = argv[optind++];
+ if (xs_has_arg(argc, argv)) {
+ p->rulenum = parse_rulenumber(argv[optind++]);
+ p->command = CMD_ZERO_NUM;
+ }
+ break;
+
+ case 'N':
+ parse_chain(optarg);
+ add_command(&p->command, CMD_NEW_CHAIN, CMD_NONE,
+ invert);
+ p->chain = optarg;
+ break;
+
+ case 'X':
+ add_command(&p->command, CMD_DELETE_CHAIN, CMD_NONE,
+ invert);
+ if (optarg)
+ p->chain = optarg;
+ else if (xs_has_arg(argc, argv))
+ p->chain = argv[optind++];
+ break;
+
+ case 'E':
+ add_command(&p->command, CMD_RENAME_CHAIN, CMD_NONE,
+ invert);
+ p->chain = optarg;
+ if (xs_has_arg(argc, argv))
+ p->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(&p->command, CMD_SET_POLICY, CMD_NONE,
+ invert);
+ p->chain = optarg;
+ if (xs_has_arg(argc, argv))
+ p->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];
+
+ /* iptables -p icmp -h */
+ if (!cs->matches && cs->protocol)
+ xtables_find_match(cs->protocol,
+ XTF_TRY_LOAD, &cs->matches);
+
+ xt_params->print_help(cs->matches);
+ p->command = CMD_NONE;
+ return;
+
+ /*
+ * Option selection
+ */
+ case 'p':
+ check_inverse(args, optarg, &invert, &optind, argc);
+ set_option(&cs->options, OPT_PROTOCOL,
+ &args->invflags, invert);
+
+ /* Canonicalize into lower case */
+ for (cs->protocol = argv[optind - 1];
+ *cs->protocol; cs->protocol++)
+ *cs->protocol = tolower(*cs->protocol);
+
+ cs->protocol = argv[optind - 1];
+ args->proto = xtables_parse_protocol(cs->protocol);
+
+ if (args->proto == 0 &&
+ (args->invflags & XT_INV_PROTO))
+ xtables_error(PARAMETER_PROBLEM,
+ "rule would never match protocol");
+
+ /* This needs to happen here to parse extensions */
+ if (p->ops->proto_parse)
+ p->ops->proto_parse(cs, args);
+ break;
+
+ case 's':
+ check_inverse(args, optarg, &invert, &optind, argc);
+ set_option(&cs->options, OPT_SOURCE,
+ &args->invflags, invert);
+ args->shostnetworkmask = argv[optind - 1];
+ break;
+
+ case 'd':
+ check_inverse(args, optarg, &invert, &optind, argc);
+ set_option(&cs->options, OPT_DESTINATION,
+ &args->invflags, invert);
+ args->dhostnetworkmask = argv[optind - 1];
+ break;
+
+#ifdef IPT_F_GOTO
+ case 'g':
+ set_option(&cs->options, OPT_JUMP, &args->invflags,
+ invert);
+ args->goto_set = true;
+ cs->jumpto = xt_parse_target(optarg);
+ break;
+#endif
+
+ case 2:/* src-mac */
+ check_inverse(args, optarg, &invert, &optind, argc);
+ set_option(&cs->options, OPT_S_MAC, &args->invflags,
+ invert);
+ args->src_mac = argv[optind - 1];
+ break;
+
+ case 3:/* dst-mac */
+ check_inverse(args, optarg, &invert, &optind, argc);
+ set_option(&cs->options, OPT_D_MAC, &args->invflags,
+ invert);
+ args->dst_mac = argv[optind - 1];
+ break;
+
+ case 'l':/* hardware length */
+ check_inverse(args, optarg, &invert, &optind, argc);
+ set_option(&cs->options, OPT_H_LENGTH, &args->invflags,
+ invert);
+ args->arp_hlen = argv[optind - 1];
+ break;
+
+ case 8: /* was never supported, not even in arptables-legacy */
+ xtables_error(PARAMETER_PROBLEM, "not supported");
+ case 4:/* opcode */
+ check_inverse(args, optarg, &invert, &optind, argc);
+ set_option(&cs->options, OPT_OPCODE, &args->invflags,
+ invert);
+ args->arp_opcode = argv[optind - 1];
+ break;
+
+ case 5:/* h-type */
+ check_inverse(args, optarg, &invert, &optind, argc);
+ set_option(&cs->options, OPT_H_TYPE, &args->invflags,
+ invert);
+ args->arp_htype = argv[optind - 1];
+ break;
+
+ case 6:/* proto-type */
+ check_inverse(args, optarg, &invert, &optind, argc);
+ set_option(&cs->options, OPT_P_TYPE, &args->invflags,
+ invert);
+ args->arp_ptype = argv[optind - 1];
+ break;
+
+ case 'j':
+ set_option(&cs->options, OPT_JUMP, &args->invflags,
+ invert);
+ command_jump(cs, argv[optind - 1]);
+ break;
+
+ case 'i':
+ check_empty_interface(args, optarg);
+ check_inverse(args, optarg, &invert, &optind, argc);
+ set_option(&cs->options, OPT_VIANAMEIN,
+ &args->invflags, invert);
+ xtables_parse_interface(argv[optind - 1],
+ args->iniface,
+ args->iniface_mask);
+ break;
+
+ case 'o':
+ check_empty_interface(args, optarg);
+ check_inverse(args, optarg, &invert, &optind, argc);
+ set_option(&cs->options, OPT_VIANAMEOUT,
+ &args->invflags, invert);
+ xtables_parse_interface(argv[optind - 1],
+ args->outiface,
+ args->outiface_mask);
+ break;
+
+ case 'f':
+ if (args->family == AF_INET6) {
+ xtables_error(PARAMETER_PROBLEM,
+ "`-f' is not supported in IPv6, "
+ "use -m frag instead");
+ }
+ set_option(&cs->options, OPT_FRAGMENT, &args->invflags,
+ invert);
+ args->flags |= IPT_F_FRAG;
+ break;
+
+ case 'v':
+ if (!p->verbose)
+ set_option(&cs->options, OPT_VERBOSE,
+ &args->invflags, invert);
+ p->verbose++;
+ break;
+
+ case 'm':
+ command_match(cs, invert);
+ break;
+
+ case 'n':
+ set_option(&cs->options, OPT_NUMERIC, &args->invflags,
+ invert);
+ break;
+
+ case 't':
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "unexpected ! flag before --table");
+ if (p->restore && table_set)
+ xtables_error(PARAMETER_PROBLEM,
+ "The -t option cannot be used in %s.\n",
+ xt_params->program_name);
+ p->table = optarg;
+ table_set = true;
+ break;
+
+ case 'x':
+ set_option(&cs->options, OPT_EXPANDED, &args->invflags,
+ invert);
+ break;
+
+ case 'V':
+ if (invert)
+ printf("Not %s ;-)\n",
+ xt_params->program_version);
+ else
+ printf("%s v%s\n",
+ xt_params->program_name,
+ xt_params->program_version);
+ exit(0);
+
+ case 'w':
+ if (p->restore) {
+ xtables_error(PARAMETER_PROBLEM,
+ "You cannot use `-w' from "
+ "iptables-restore");
+ }
+
+ wait = parse_wait_time(argc, argv);
+ break;
+
+ case 'W':
+ if (p->restore) {
+ xtables_error(PARAMETER_PROBLEM,
+ "You cannot use `-W' from "
+ "iptables-restore");
+ }
+
+ parse_wait_interval(argc, argv, &wait_interval);
+ wait_interval_set = true;
+ break;
+
+ case '0':
+ set_option(&cs->options, OPT_LINENUMBERS,
+ &args->invflags, invert);
+ break;
+
+ case 'M':
+ xtables_modprobe_program = optarg;
+ break;
+
+ case 'c':
+ set_option(&cs->options, OPT_COUNTERS, &args->invflags,
+ invert);
+ args->pcnt = optarg;
+ args->bcnt = strchr(args->pcnt + 1, ',');
+ if (args->bcnt)
+ args->bcnt++;
+ if (!args->bcnt && xs_has_arg(argc, argv))
+ args->bcnt = argv[optind++];
+ if (!args->bcnt)
+ xtables_error(PARAMETER_PROBLEM,
+ "-%c requires packet and byte counter",
+ opt2char(OPT_COUNTERS));
+
+ if (sscanf(args->pcnt, "%llu", &args->pcnt_cnt) != 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "-%c packet counter not numeric",
+ opt2char(OPT_COUNTERS));
+
+ if (sscanf(args->bcnt, "%llu", &args->bcnt_cnt) != 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "-%c byte counter not numeric",
+ opt2char(OPT_COUNTERS));
+ break;
+
+ case '4':
+ if (args->family == AF_INET)
+ break;
+
+ if (p->restore && args->family == AF_INET6)
+ return;
+
+ exit_tryhelp(2, p->line);
+
+ case '6':
+ if (args->family == AF_INET6)
+ break;
+
+ if (p->restore && args->family == AF_INET)
+ return;
+
+ exit_tryhelp(2, p->line);
+
+ 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;
+ }
+ fprintf(stderr, "Bad argument `%s'\n", optarg);
+ exit_tryhelp(2, p->line);
+
+ default:
+ if (command_default(cs, xt_params, invert))
+ /* cf. ip6tables.c */
+ continue;
+ break;
+ }
+ invert = false;
+ }
+
+ if (strcmp(p->table, "nat") == 0 &&
+ ((p->policy != NULL && strcmp(p->policy, "DROP") == 0) ||
+ (cs->jumpto != NULL && strcmp(cs->jumpto, "DROP") == 0)))
+ xtables_error(PARAMETER_PROBLEM,
+ "\nThe \"nat\" table is not intended for filtering, "
+ "the use of DROP is therefore inhibited.\n\n");
+
+ if (!wait && wait_interval_set)
+ xtables_error(PARAMETER_PROBLEM,
+ "--wait-interval only makes sense with --wait\n");
+
+ for (matchp = cs->matches; matchp; matchp = matchp->next)
+ xtables_option_mfcall(matchp->match);
+ if (cs->target != NULL)
+ xtables_option_tfcall(cs->target);
+
+ /* Fix me: must put inverse options checking here --MN */
+
+ if (optind < argc)
+ xtables_error(PARAMETER_PROBLEM,
+ "unknown arguments found on commandline");
+ if (!p->command)
+ xtables_error(PARAMETER_PROBLEM, "no command specified");
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "nothing appropriate following !");
+
+ if (p->ops->post_parse)
+ p->ops->post_parse(p->command, cs, args);
+
+ if (p->command == CMD_REPLACE &&
+ (args->s.naddrs != 1 || args->d.naddrs != 1))
+ xtables_error(PARAMETER_PROBLEM, "Replacement rule does not "
+ "specify a unique address");
+
+ generic_opt_check(p->command, cs->options);
+
+ if (p->chain != NULL && strlen(p->chain) >= XT_EXTENSION_MAXNAMELEN)
+ xtables_error(PARAMETER_PROBLEM,
+ "chain name `%s' too long (must be under %u chars)",
+ p->chain, XT_EXTENSION_MAXNAMELEN);
+
+ if (p->command == CMD_APPEND ||
+ p->command == CMD_DELETE ||
+ p->command == CMD_DELETE_NUM ||
+ p->command == CMD_CHECK ||
+ p->command == CMD_INSERT ||
+ p->command == CMD_REPLACE) {
+ if (strcmp(p->chain, "PREROUTING") == 0
+ || strcmp(p->chain, "INPUT") == 0) {
+ /* -o not valid with incoming packets. */
+ if (cs->options & OPT_VIANAMEOUT)
+ xtables_error(PARAMETER_PROBLEM,
+ "Can't use -%c with %s\n",
+ opt2char(OPT_VIANAMEOUT),
+ p->chain);
+ }
+
+ if (strcmp(p->chain, "POSTROUTING") == 0
+ || strcmp(p->chain, "OUTPUT") == 0) {
+ /* -i not valid with outgoing packets */
+ if (cs->options & OPT_VIANAMEIN)
+ xtables_error(PARAMETER_PROBLEM,
+ "Can't use -%c with %s\n",
+ opt2char(OPT_VIANAMEIN),
+ p->chain);
+ }
+ }
+}