Example #1
0
/* Function which parses command options; returns true if it
   ate an option */
static int conntrack_parse(int c, char **argv, int invert, unsigned int *flags,
                           const void *entry, struct xt_entry_match **match)
{
	struct ipt_conntrack_info *sinfo = (struct ipt_conntrack_info *)(*match)->data;
	char *protocol = NULL;
	unsigned int naddrs = 0;
	struct in_addr *addrs = NULL;


	switch (c) {
	case '1':
		check_inverse(optarg, &invert, &optind, 0);

		parse_states(argv[optind-1], sinfo);
		if (invert) {
			sinfo->invflags |= IPT_CONNTRACK_STATE;
		}
		sinfo->flags |= IPT_CONNTRACK_STATE;
		break;

	case '2':
		check_inverse(optarg, &invert, &optind, 0);

		if(invert)
			sinfo->invflags |= IPT_CONNTRACK_PROTO;

		/* Canonicalize into lower case */
		for (protocol = argv[optind-1]; *protocol; protocol++)
			*protocol = tolower(*protocol);

		protocol = argv[optind-1];
		sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum = parse_protocol(protocol);

		if (sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum == 0
		    && (sinfo->invflags & IPT_INV_PROTO))
			exit_error(PARAMETER_PROBLEM,
				   "rule would never match protocol");

		sinfo->flags |= IPT_CONNTRACK_PROTO;
		break;

	case '3':
		check_inverse(optarg, &invert, &optind, 0);

		if (invert)
			sinfo->invflags |= IPT_CONNTRACK_ORIGSRC;

		parse_hostnetworkmask(argv[optind-1], &addrs,
					&sinfo->sipmsk[IP_CT_DIR_ORIGINAL],
					&naddrs);
		if(naddrs > 1)
			exit_error(PARAMETER_PROBLEM,
				"multiple IP addresses not allowed");

		if(naddrs == 1) {
			sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip = addrs[0].s_addr;
		}

		sinfo->flags |= IPT_CONNTRACK_ORIGSRC;
		break;

	case '4':
		check_inverse(optarg, &invert, &optind, 0);

		if (invert)
			sinfo->invflags |= IPT_CONNTRACK_ORIGDST;

		parse_hostnetworkmask(argv[optind-1], &addrs,
					&sinfo->dipmsk[IP_CT_DIR_ORIGINAL],
					&naddrs);
		if(naddrs > 1)
			exit_error(PARAMETER_PROBLEM,
				"multiple IP addresses not allowed");

		if(naddrs == 1) {
			sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip = addrs[0].s_addr;
		}

		sinfo->flags |= IPT_CONNTRACK_ORIGDST;
		break;

	case '5':
		check_inverse(optarg, &invert, &optind, 0);

		if (invert)
			sinfo->invflags |= IPT_CONNTRACK_REPLSRC;

		parse_hostnetworkmask(argv[optind-1], &addrs,
					&sinfo->sipmsk[IP_CT_DIR_REPLY],
					&naddrs);
		if(naddrs > 1)
			exit_error(PARAMETER_PROBLEM,
				"multiple IP addresses not allowed");

		if(naddrs == 1) {
			sinfo->tuple[IP_CT_DIR_REPLY].src.ip = addrs[0].s_addr;
		}

		sinfo->flags |= IPT_CONNTRACK_REPLSRC;
		break;

	case '6':
		check_inverse(optarg, &invert, &optind, 0);

		if (invert)
			sinfo->invflags |= IPT_CONNTRACK_REPLDST;

		parse_hostnetworkmask(argv[optind-1], &addrs,
					&sinfo->dipmsk[IP_CT_DIR_REPLY],
					&naddrs);
		if(naddrs > 1)
			exit_error(PARAMETER_PROBLEM,
				"multiple IP addresses not allowed");

		if(naddrs == 1) {
			sinfo->tuple[IP_CT_DIR_REPLY].dst.ip = addrs[0].s_addr;
		}

		sinfo->flags |= IPT_CONNTRACK_REPLDST;
		break;

	case '7':
		check_inverse(optarg, &invert, &optind, 0);

		parse_statuses(argv[optind-1], sinfo);
		if (invert) {
			sinfo->invflags |= IPT_CONNTRACK_STATUS;
		}
		sinfo->flags |= IPT_CONNTRACK_STATUS;
		break;

	case '8':
		check_inverse(optarg, &invert, &optind, 0);

		parse_expires(argv[optind-1], sinfo);
		if (invert) {
			sinfo->invflags |= IPT_CONNTRACK_EXPIRES;
		}
		sinfo->flags |= IPT_CONNTRACK_EXPIRES;
		break;

	default:
		return 0;
	}

	*flags = sinfo->flags;
	return 1;
}
static int
parse(int c, char **argv, int invert, unsigned int *flags,
      const struct ipt_entry *entry,
      unsigned int *nfcache,
      struct ipt_entry_match **match)
{
	struct ipt_owner_info *ownerinfo = (struct ipt_owner_info *)(*match)->data;

	switch (c) {
		char *end;
		struct passwd *pwd;
		struct group *grp;
	case '1':
		check_inverse(optarg, &invert, &optind, 0);
		if ((pwd = getpwnam(optarg)))
			ownerinfo->uid = pwd->pw_uid;
		else {
			ownerinfo->uid = strtoul(optarg, &end, 0);
			if (*end != '\0' || end == optarg)
				exit_error(PARAMETER_PROBLEM, "Bad OWNER UID value `%s'", optarg);
		}
		if (invert)
			ownerinfo->invert |= IPT_OWNER_UID;
		ownerinfo->match |= IPT_OWNER_UID;
		*flags = 1;
		break;

	case '2':
		check_inverse(optarg, &invert, &optind, 0);
		if ((grp = getgrnam(optarg)))
			ownerinfo->gid = grp->gr_gid;
		else {
			ownerinfo->gid = strtoul(optarg, &end, 0);
			if (*end != '\0' || end == optarg)
				exit_error(PARAMETER_PROBLEM, "Bad OWNER GID value `%s'", optarg);
		}
		if (invert)
			ownerinfo->invert |= IPT_OWNER_GID;
		ownerinfo->match |= IPT_OWNER_GID;
		*flags = 1;
		break;

	case '3':
		check_inverse(optarg, &invert, &optind, 0);
		ownerinfo->pid = strtoul(optarg, &end, 0);
		if (*end != '\0' || end == optarg)
			exit_error(PARAMETER_PROBLEM, "Bad OWNER PID value `%s'", optarg);
		if (invert)
			ownerinfo->invert |= IPT_OWNER_PID;
		ownerinfo->match |= IPT_OWNER_PID;
		*flags = 1;
		break;

	case '4':
		check_inverse(optarg, &invert, &optind, 0);
		ownerinfo->sid = strtoul(optarg, &end, 0);
		if (*end != '\0' || end == optarg)
			exit_error(PARAMETER_PROBLEM, "Bad OWNER SID value `%s'", optarg);
		if (invert)
			ownerinfo->invert |= IPT_OWNER_SID;
		ownerinfo->match |= IPT_OWNER_SID;
		*flags = 1;
		break;

#ifdef IPT_OWNER_COMM
	case '5':
		check_inverse(optarg, &invert, &optind, 0);
		if(strlen(optarg) > sizeof(ownerinfo->comm))
			exit_error(PARAMETER_PROBLEM, "OWNER CMD `%s' too long, max %u characters", optarg, (unsigned int)sizeof(ownerinfo->comm));

		strncpy(ownerinfo->comm, optarg, sizeof(ownerinfo->comm));
		ownerinfo->comm[sizeof(ownerinfo->comm)-1] = '\0';

		if (invert)
			ownerinfo->invert |= IPT_OWNER_COMM;
		ownerinfo->match |= IPT_OWNER_COMM;
		*flags = 1;
		break;
#endif

	default:
		return 0;
	}
	return 1;
}
Example #3
0
/* Function which parses command options; returns true if it
   ate an option */
static int
parse(int c, char **argv, int invert, unsigned int *flags,
      const struct ip6t_entry *entry,
      unsigned int *nfcache,
      struct ip6t_entry_match **match)
{
	struct ip6t_frag *fraginfo = (struct ip6t_frag *)(*match)->data;

	switch (c) {
	case '1':
		if (*flags & IP6T_FRAG_IDS)
			exit_error(PARAMETER_PROBLEM,
				   "Only one `--fragid' allowed");
		check_inverse(optarg, &invert, &optind, 0);
		parse_frag_ids(argv[optind-1], fraginfo->ids);
		if (invert)
			fraginfo->invflags |= IP6T_FRAG_INV_IDS;
		fraginfo->flags |= IP6T_FRAG_IDS;
		*flags |= IP6T_FRAG_IDS;
		break;
	case '2':
		if (*flags & IP6T_FRAG_LEN)
			exit_error(PARAMETER_PROBLEM,
				   "Only one `--fraglen' allowed");
		check_inverse(optarg, &invert, &optind, 0);
		fraginfo->hdrlen = parse_frag_id(argv[optind-1], "length");
		if (invert)
			fraginfo->invflags |= IP6T_FRAG_INV_LEN;
		fraginfo->flags |= IP6T_FRAG_LEN;
		*flags |= IP6T_FRAG_LEN;
		break;
	case '3':
		if (*flags & IP6T_FRAG_RES)
			exit_error(PARAMETER_PROBLEM,
				   "Only one `--fragres' allowed");
		fraginfo->flags |= IP6T_FRAG_RES;
		*flags |= IP6T_FRAG_RES;
		break;
	case '4':
		if (*flags & IP6T_FRAG_FST)
			exit_error(PARAMETER_PROBLEM,
				   "Only one `--fragfirst' allowed");
		fraginfo->flags |= IP6T_FRAG_FST;
		*flags |= IP6T_FRAG_FST;
		break;
	case '5':
		if (*flags & (IP6T_FRAG_MF|IP6T_FRAG_NMF)) 
			exit_error(PARAMETER_PROBLEM,
			   "Only one `--fragmore' or `--fraglast' allowed");
		fraginfo->flags |= IP6T_FRAG_MF;
		*flags |= IP6T_FRAG_MF;
		break;
	case '6':
		if (*flags & (IP6T_FRAG_MF|IP6T_FRAG_NMF)) 
			exit_error(PARAMETER_PROBLEM,
			   "Only one `--fragmore' or `--fraglast' allowed");
		fraginfo->flags |= IP6T_FRAG_NMF;
		*flags |= IP6T_FRAG_NMF;
		break;
	default:
		return 0;
	}

	return 1;
}
/* Function which parses command options; returns true if it
   ate an option */
static int
parse(int c, char **argv, int invert, unsigned int *flags,
      const struct ipt_entry *entry,
      struct ipt_entry_target **target)
{
	struct ipt_trigger_info *info = (struct ipt_trigger_info *)(*target)->data;

	switch (c) {
	case '1':
		if (!strcasecmp(optarg, "dnat"))
			info->type = IPT_TRIGGER_DNAT;
		else if (!strcasecmp(optarg, "in"))
			info->type = IPT_TRIGGER_IN;
		else if (!strcasecmp(optarg, "out"))
			info->type = IPT_TRIGGER_OUT;
		else
			exit_error(PARAMETER_PROBLEM,
				   "triggering type can only be one of `%s', '%s' '%s'", "dnat", "in", "out");
		return 1;

	case '2':
		if (!strcasecmp(optarg, "tcp"))
			info->proto = IPPROTO_TCP;
		else if (!strcasecmp(optarg, "udp"))
			info->proto = IPPROTO_UDP;
		else if (!strcasecmp(optarg, "all"))
			info->proto = 0;
		else
			exit_error(PARAMETER_PROBLEM,
				   "triggering protocol can only be one of `%s', '%s', '%s'", "tcp", "udp", "all");
		return 1;

	case '3':
		if (check_inverse(optarg, &invert, &optind, 0))
			exit_error(PARAMETER_PROBLEM,
				   "Unexpected `!' after --triggering-port");

		parse_ports(optarg, info->ports.mport);
		return 1;

#ifdef ATP_SUPPORT_PRTT_RPROTOCOL

case '4':
    if (!strcasecmp(optarg, "tcp"))
        info->rproto = IPPROTO_TCP;
    else if (!strcasecmp(optarg, "udp"))
        info->rproto = IPPROTO_UDP;
    else if (!strcasecmp(optarg, "all"))
        info->rproto = 0;
    else
        exit_error(PARAMETER_PROBLEM,
               "open protocol can only be one of '%s', '%s', '%s'", "tcp", "udp", "all");
    return 1;

case '5':
    if (check_inverse(optarg, &invert, &optind, 0))
        exit_error(PARAMETER_PROBLEM,
               "Unexpected `!' after --open-port");

    //parse_ports(optarg, info->ports.rport);
    parse_Openports(optarg, &(info->ports));
    *flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
    return 1;
    
#else

#if 0
	case '4':
		if (check_inverse(optarg, &invert, &optind, 0))
            exit_error(PARAMETER_PROBLEM,
                   "Unexpected `!' after --open-port");

		parse_ports(optarg, info->ports.rport);
		*flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
		return 1;
#endif
#endif

	default:
		return 0;
	}
}
Example #5
0
static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
   unsigned int *flags, struct ebt_entry_match **match)
{
	struct ebt_ip_info *ipinfo = (struct ebt_ip_info *)(*match)->data;
	char *end;
	long int i;

	switch (c) {
	case IP_SOURCE:
		check_option(flags, OPT_SOURCE);
		ipinfo->bitmask |= EBT_IP_SOURCE;

	case IP_DEST:
		if (c == IP_DEST) {
			check_option(flags, OPT_DEST);
			ipinfo->bitmask |= EBT_IP_DEST;
		}
		if (check_inverse(optarg)) {
			if (c == IP_SOURCE)
				ipinfo->invflags |= EBT_IP_SOURCE;
			else
				ipinfo->invflags |= EBT_IP_DEST;
		}

		if (optind > argc)
			print_error("Missing IP address argument");
		if (c == IP_SOURCE)
			parse_ip_address(argv[optind - 1], &ipinfo->saddr,
			   &ipinfo->smsk);
		else
			parse_ip_address(argv[optind - 1], &ipinfo->daddr,
			   &ipinfo->dmsk);
		break;

	case IP_SPORT:
	case IP_DPORT:
		if (c == IP_SPORT) {
			check_option(flags, OPT_SPORT);
			ipinfo->bitmask |= EBT_IP_SPORT;
			if (check_inverse(optarg))
				ipinfo->invflags |= EBT_IP_SPORT;
		} else {
			check_option(flags, OPT_DPORT);
			ipinfo->bitmask |= EBT_IP_DPORT;
			if (check_inverse(optarg))
				ipinfo->invflags |= EBT_IP_DPORT;
		}
		if (optind > argc)
			print_error("Missing port argument");
		if (c == IP_SPORT)
			parse_port_range(NULL, argv[optind - 1], ipinfo->sport);
		else
			parse_port_range(NULL, argv[optind - 1], ipinfo->dport);
		break;

	case IP_myTOS:
		check_option(flags, OPT_TOS);
		if (check_inverse(optarg))
			ipinfo->invflags |= EBT_IP_TOS;

		if (optind > argc)
			print_error("Missing IP tos argument");
		i = strtol(argv[optind - 1], &end, 16);
		if (i < 0 || i > 255 || *end != '\0')
			print_error("Problem with specified IP tos");
		ipinfo->tos = i;
		ipinfo->bitmask |= EBT_IP_TOS;
		break;

	case IP_myDSCP:   /* brcm */
		check_option(flags, OPT_DSCP);
		if (check_inverse(optarg))
			ipinfo->invflags |= EBT_IP_DSCP;

		if (optind > argc)
			print_error("Missing IP dscp argument");
		i = strtol(argv[optind - 1], &end, 16);
		if (i < 0 || i > 255 || (i & 0x3) || *end != '\0')
			print_error("Problem with specified IP dscp");
		ipinfo->dscp = i;
		ipinfo->bitmask |= EBT_IP_DSCP;
		break;

	case IP_PROTO:
		check_option(flags, OPT_PROTO);
		if (check_inverse(optarg))
			ipinfo->invflags |= EBT_IP_PROTO;
		if (optind > argc)
			print_error("Missing IP protocol argument");
		i = strtoul(argv[optind - 1], &end, 10);
		if (*end != '\0') {
			struct protoent *pe;

			pe = getprotobyname(argv[optind - 1]);
			if (pe == NULL)
				print_error
				    ("Unknown specified IP protocol - %s",
				     argv[optind - 1]);
			ipinfo->protocol = pe->p_proto;
		} else {
			ipinfo->protocol = (unsigned char) i;
		}
		ipinfo->bitmask |= EBT_IP_PROTO;
		break;
	default:
		return 0;
	}
	return 1;
}
Example #6
0
/* Function which parses command options; returns true if it
   ate an option */
static int
hashlimit_parse(int c, char **argv, int invert, unsigned int *flags,
                const void *entry, struct xt_entry_match **match)
{
	struct xt_hashlimit_info *r = 
			(struct xt_hashlimit_info *)(*match)->data;
	unsigned int num;

	switch(c) {
	case '%':
		param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit",
		          *flags & PARAM_LIMIT);
		if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
		if (!parse_rate(optarg, &r->cfg.avg))
			exit_error(PARAMETER_PROBLEM,
				   "bad rate `%s'", optarg);
		*flags |= PARAM_LIMIT;
		break;

	case '$':
		param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-burst",
		          *flags & PARAM_BURST);
		if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
		if (string_to_number(optarg, 0, 10000, &num) == -1)
			exit_error(PARAMETER_PROBLEM,
				   "bad --hashlimit-burst `%s'", optarg);
		r->cfg.burst = num;
		*flags |= PARAM_BURST;
		break;
	case '&':
		param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-htable-size",
		          *flags & PARAM_SIZE);
		if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
		if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
			exit_error(PARAMETER_PROBLEM,
				"bad --hashlimit-htable-size: `%s'", optarg);
		r->cfg.size = num;
		*flags |= PARAM_SIZE;
		break;
	case '*':
		param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-htable-max",
		          *flags & PARAM_MAX);
		if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
		if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
			exit_error(PARAMETER_PROBLEM,
				"bad --hashlimit-htable-max: `%s'", optarg);
		r->cfg.max = num;
		*flags |= PARAM_MAX;
		break;
	case '(':
		param_act(P_ONLY_ONCE, "hashlimit",
		          "--hashlimit-htable-gcinterval",
		          *flags & PARAM_GCINTERVAL);
		if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
		if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
			exit_error(PARAMETER_PROBLEM,
				"bad --hashlimit-htable-gcinterval: `%s'", 
				optarg);
		/* FIXME: not HZ dependent!! */
		r->cfg.gc_interval = num;
		*flags |= PARAM_GCINTERVAL;
		break;
	case ')':
		param_act(P_ONLY_ONCE, "hashlimit",
		          "--hashlimit-htable-expire", *flags & PARAM_EXPIRE);
		if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
		if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
			exit_error(PARAMETER_PROBLEM,
				"bad --hashlimit-htable-expire: `%s'", optarg);
		/* FIXME: not HZ dependent */
		r->cfg.expire = num;
		*flags |= PARAM_EXPIRE;
		break;
	case '_':
		param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-mode",
		          *flags & PARAM_MODE);
		if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
		if (parse_mode(&r->cfg.mode, optarg) < 0)
			exit_error(PARAMETER_PROBLEM, 
				   "bad --hashlimit-mode: `%s'\n", optarg);
		*flags |= PARAM_MODE;
		break;
	case '"':
		param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-name",
		          *flags & PARAM_NAME);
		if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
		if (strlen(optarg) == 0)
			exit_error(PARAMETER_PROBLEM, "Zero-length name?");
		strncpy(r->name, optarg, sizeof(r->name));
		*flags |= PARAM_NAME;
		break;
	default:
		return 0;
	}

	if (invert)
		exit_error(PARAMETER_PROBLEM,
			   "hashlimit does not support invert");

	return 1;
}
Example #7
0
/* Function which parses command options; returns true if it
   ate an option */
static int
parse(int c, char **argv, int invert, unsigned int *flags,
      const struct ip6t_entry *entry,
      struct ip6t_entry_target **target)
{
	struct ip6t_log_info *loginfo = (struct ip6t_log_info *)(*target)->data;

	switch (c) {
	case '!':
		if (*flags & IP6T_LOG_OPT_LEVEL)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify --log-level twice");

		if (check_inverse(optarg, &invert, NULL, 0))
			exit_error(PARAMETER_PROBLEM,
				   "Unexpected `!' after --log-level");

		loginfo->level = parse_level(optarg);
		*flags |= IP6T_LOG_OPT_LEVEL;
		break;

	case '#':
		if (*flags & IP6T_LOG_OPT_PREFIX)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify --log-prefix twice");

		if (check_inverse(optarg, &invert, NULL, 0))
			exit_error(PARAMETER_PROBLEM,
				   "Unexpected `!' after --log-prefix");

		if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
			exit_error(PARAMETER_PROBLEM,
				   "Maximum prefix length %u for --log-prefix",
				   sizeof(loginfo->prefix) - 1);

		strcpy(loginfo->prefix, optarg);
		*flags |= IP6T_LOG_OPT_PREFIX;
		break;

	case '1':
		if (*flags & IP6T_LOG_OPT_TCPSEQ)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify --log-tcp-sequence "
				   "twice");

		loginfo->logflags |= IP6T_LOG_TCPSEQ;
		*flags |= IP6T_LOG_OPT_TCPSEQ;
		break;

	case '2':
		if (*flags & IP6T_LOG_OPT_TCPOPT)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify --log-tcp-options twice");

		loginfo->logflags |= IP6T_LOG_TCPOPT;
		*flags |= IP6T_LOG_OPT_TCPOPT;
		break;

	case '3':
		if (*flags & IP6T_LOG_OPT_IPOPT)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify --log-ip-options twice");

		loginfo->logflags |= IP6T_LOG_IPOPT;
		*flags |= IP6T_LOG_OPT_IPOPT;
		break;

	default:
		return 0;
	}

	return 1;
}
Example #8
0
/* Function which parses command options; returns true if it
   ate an option */
static int
parse(int c, char **argv, int invert, unsigned int *flags,
      const struct ip6t_entry *entry,
      unsigned int *nfcache,
      struct ip6t_entry_match **match)
{
	struct ip6t_owner_info *ownerinfo = (struct ip6t_owner_info *)(*match)->data;

	switch (c) {
		char *end;
		struct passwd *pwd;
		struct group *grp;
	case '1':
		check_inverse(optarg, &invert, &optind, 0);

		if ((pwd = getpwnam(optarg)))
			ownerinfo->uid = pwd->pw_uid;
		else {
			ownerinfo->uid = strtoul(optarg, &end, 0);
			if (*end != '\0' || end == optarg)
				exit_error(PARAMETER_PROBLEM, "Bad OWNER UID value `%s'", optarg);
		}
		if (invert)
			ownerinfo->invert |= IP6T_OWNER_UID;
		ownerinfo->match |= IP6T_OWNER_UID;
		*flags = 1;
		break;

	case '2':
		check_inverse(optarg, &invert, &optind, 0);
		if ((grp = getgrnam(optarg)))
			ownerinfo->gid = grp->gr_gid;
		else {
			ownerinfo->gid = strtoul(optarg, &end, 0);
			if (*end != '\0' || end == optarg)
				exit_error(PARAMETER_PROBLEM, "Bad OWNER GID value `%s'", optarg);
		}
		if (invert)
			ownerinfo->invert |= IP6T_OWNER_GID;
		ownerinfo->match |= IP6T_OWNER_GID;
		*flags = 1;
		break;

	case '3':
		check_inverse(optarg, &invert, &optind, 0);
		ownerinfo->pid = strtoul(optarg, &end, 0);
		if (*end != '\0' || end == optarg)
			exit_error(PARAMETER_PROBLEM, "Bad OWNER PID value `%s'", optarg);
		if (invert)
			ownerinfo->invert |= IP6T_OWNER_PID;
		ownerinfo->match |= IP6T_OWNER_PID;
		*flags = 1;
		break;

	case '4':
		check_inverse(optarg, &invert, &optind, 0);
		ownerinfo->sid = strtoul(optarg, &end, 0);
		if (*end != '\0' || end == optarg)
			exit_error(PARAMETER_PROBLEM, "Bad OWNER SID value `%s'", optarg);
		if (invert)
			ownerinfo->invert |= IP6T_OWNER_SID;
		ownerinfo->match |= IP6T_OWNER_SID;
		*flags = 1;
		break;

	default:
		return 0;
	}
	return 1;
}
static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
   unsigned int *flags, struct ebt_entry_match **match)
{
	struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)(*match)->data;
	long int i;
	char *end;
	uint32_t *addr;
	uint32_t *mask;
	char *maddr;
	char *mmask;

	switch (c) {
	case ARP_OPCODE:
		check_option(flags, OPT_OPCODE);
		if (check_inverse(optarg))
			arpinfo->invflags |= EBT_ARP_OPCODE;

		if (optind > argc)
			print_error("Missing ARP opcode argument");
		i = strtol(argv[optind - 1], &end, 10);
		if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
			for (i = 0; i < NUMOPCODES; i++)
				if (!strcasecmp(opcodes[i], optarg))
					break;
			if (i == NUMOPCODES)
				print_error("Problem with specified "
				            "ARP opcode");
			i++;
		}
		arpinfo->opcode = htons(i);
		arpinfo->bitmask |= EBT_ARP_OPCODE;
		break;

	case ARP_HTYPE:
		check_option(flags, OPT_HTYPE);
		if (check_inverse(optarg))
			arpinfo->invflags |= EBT_ARP_HTYPE;

		if (optind > argc)
			print_error("Missing ARP hardware type argument");
		i = strtol(argv[optind - 1], &end, 10);
		if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
			if (!strcasecmp("Ethernet", argv[optind - 1]))
				i = 1;
			else
				print_error("Problem with specified ARP "
				            "hardware type");
		}
		arpinfo->htype = htons(i);
		arpinfo->bitmask |= EBT_ARP_HTYPE;
		break;

	case ARP_PTYPE:
	{
		uint16_t proto;

		check_option(flags, OPT_PTYPE);
		if (check_inverse(optarg))
			arpinfo->invflags |= EBT_ARP_PTYPE;

		if (optind > argc)
			print_error("Missing ARP protocol type argument");
		i = strtol(argv[optind - 1], &end, 16);
		if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
			struct ethertypeent *ent;

			ent = getethertypebyname(argv[optind - 1]);
			if (!ent)
				print_error("Problem with specified ARP "
				            "protocol type");
			proto = ent->e_ethertype;

		} else
			proto = i;
		arpinfo->ptype = htons(proto);
		arpinfo->bitmask |= EBT_ARP_PTYPE;
		break;
	}

	case ARP_IP_S:
	case ARP_IP_D:
		if (c == ARP_IP_S) {
			check_option(flags, OPT_IP_S);
			addr = &arpinfo->saddr;
			mask = &arpinfo->smsk;
			arpinfo->bitmask |= EBT_ARP_SRC_IP;
		} else {
			check_option(flags, OPT_IP_D);
			addr = &arpinfo->daddr;
			mask = &arpinfo->dmsk;
			arpinfo->bitmask |= EBT_ARP_DST_IP;
		}
		if (check_inverse(optarg)) {
			if (c == ARP_IP_S)
				arpinfo->invflags |= EBT_ARP_SRC_IP;
			else
				arpinfo->invflags |= EBT_ARP_DST_IP;
		}
		if (optind > argc)
			print_error("Missing ARP IP address argument");
		parse_ip_address(argv[optind - 1], addr, mask);
		break;

	case ARP_MAC_S:
	case ARP_MAC_D:
		if (c == ARP_MAC_S) {
			check_option(flags, OPT_MAC_S);
			maddr = arpinfo->smaddr;
			mmask = arpinfo->smmsk;
			arpinfo->bitmask |= EBT_ARP_SRC_MAC;
		} else {
			check_option(flags, OPT_MAC_D);
			maddr = arpinfo->dmaddr;
			mmask = arpinfo->dmmsk;
			arpinfo->bitmask |= EBT_ARP_DST_MAC;
		}
		if (check_inverse(optarg)) {
			if (c == ARP_MAC_S)
				arpinfo->invflags |= EBT_ARP_SRC_MAC;
			else
				arpinfo->invflags |= EBT_ARP_DST_MAC;
		}
		if (optind > argc)
			print_error("Missing ARP MAC address argument");
		if (get_mac_and_mask(argv[optind - 1], maddr, mmask))
			print_error("Problem with ARP MAC address argument");
		break;

	default:
		return 0;
	}
	return 1;
}
Example #10
0
/* Function which parses command options; returns true if it
   ate an option */
static int parse(int c, char **argv, int invert, unsigned int *flags,
		 const struct ipt_entry *entry,
		 struct ipt_entry_target **target)
{
	struct ipt_ulog_info *loginfo =
	    (struct ipt_ulog_info *) (*target)->data;
	int group_d;

	switch (c) {
	case '!':
		if (*flags & IPT_LOG_OPT_NLGROUP)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify --ulog-nlgroup twice");

		if (check_inverse(optarg, &invert, NULL, 0))
			exit_error(PARAMETER_PROBLEM,
				   "Unexpected `!' after --ulog-nlgroup");
		group_d = atoi(optarg);
		if (group_d > 32 || group_d < 1)
			exit_error(PARAMETER_PROBLEM,
				   "--ulog-nlgroup has to be between 1 and 32");

		loginfo->nl_group = (1 << (group_d - 1));

		*flags |= IPT_LOG_OPT_NLGROUP;
		break;

	case '#':
		if (*flags & IPT_LOG_OPT_PREFIX)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify --ulog-prefix twice");

		if (check_inverse(optarg, &invert, NULL, 0))
			exit_error(PARAMETER_PROBLEM,
				   "Unexpected `!' after --ulog-prefix");

		if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
			exit_error(PARAMETER_PROBLEM,
				   "Maximum prefix length %u for --ulog-prefix",
				   (unsigned int)(sizeof(loginfo->prefix) - 1));

		strcpy(loginfo->prefix, optarg);
		*flags |= IPT_LOG_OPT_PREFIX;
		break;
	case 'A':
		if (*flags & IPT_LOG_OPT_CPRANGE)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify --ulog-cprange twice");
		if (atoi(optarg) < 0)
			exit_error(PARAMETER_PROBLEM,
				   "Negative copy range?");
		loginfo->copy_range = atoi(optarg);
		*flags |= IPT_LOG_OPT_CPRANGE;
		break;
	case 'B':
		if (*flags & IPT_LOG_OPT_QTHRESHOLD)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify --ulog-qthreshold twice");
		if (atoi(optarg) < 1)
			exit_error(PARAMETER_PROBLEM,
				   "Negative or zero queue threshold ?");
		if (atoi(optarg) > ULOG_MAX_QLEN)
			exit_error(PARAMETER_PROBLEM,
				   "Maximum queue length exceeded");
		loginfo->qthreshold = atoi(optarg);
		*flags |= IPT_LOG_OPT_QTHRESHOLD;
		break;
	}
	return 1;
}
/* Function which parses command options; returns true if it
   ate an option */
static int
parse(int c, char **argv, int invert, unsigned int *flags,
      const struct ipt_entry *entry,
      struct ipt_entry_target **target)
{
	int portok;
	struct ipt_porttrigger_info *info = (struct ipt_porttrigger_info *)(*target)->data;

	switch (c) {
	
		case '1':
			if (check_inverse(optarg, &invert, &optind, 0))
				exit_error(PARAMETER_PROBLEM, "Unexpected `!' ");
			if (!strcasecmp(optarg, "dnat"))
				info->mode= MODE_DNAT;
			else if (!strcasecmp(optarg, "forward_in"))
				info->mode= MODE_FORWARD_IN;
			else if (!strcasecmp(optarg, "forward_out"))
				info->mode= MODE_FORWARD_OUT;
			return 1;
			
		case '2':
			if (check_inverse(optarg, &invert, &optind, 0))
				exit_error(PARAMETER_PROBLEM, "Unexpected `!' ");
			if (!strcasecmp(optarg, "tcp"))
				info->trigger_proto= IPPROTO_TCP;
			else if (!strcasecmp(optarg, "udp"))
				info->trigger_proto = IPPROTO_UDP;
			else if (!strcasecmp(optarg, "all") || !strcasecmp(optarg, "any"))
				info->trigger_proto = 0;
			return 1;

		case '3':
			if (check_inverse(optarg, &invert, &optind, 0))
				exit_error(PARAMETER_PROBLEM, "Unexpected `!' ");
			if (!strcasecmp(optarg, "tcp"))
				info->forward_proto= IPPROTO_TCP;
			else if (!strcasecmp(optarg, "udp"))
				info->forward_proto = IPPROTO_UDP;
			else if (!strcasecmp(optarg, "all") || !strcasecmp(optarg, "any"))
				info->forward_proto = 0;
			return 1;

		case '4':
			if (check_inverse(optarg, &invert, &optind, 0))
				exit_error(PARAMETER_PROBLEM, "Unexpected `!' ");
			parse_multi_ports(optarg, &info->trigger_ports);
			return 1;

		case '5':
			if (check_inverse(optarg, &invert, &optind, 0))
				exit_error(PARAMETER_PROBLEM, "Unexpected `!' ");
			parse_multi_ports(optarg, &info->forward_ports);
			return 1;
				
		case '6':
			if (check_inverse(optarg, &invert, &optind, 0))
				exit_error(PARAMETER_PROBLEM, "Unexpected `!' ");
			info->timer = atoi(optarg);
			return 1;
				
		default:
			return 0;
	}
}
Example #12
0
/* Function which parses command options; returns true if it
   ate an option */
static int
parse(int c, char **argv, int invert, unsigned int *flags,
      const struct ip6t_entry *entry,
      unsigned int *nfcache,
      struct ip6t_entry_match **match)
{
	struct ip6t_rt *rtinfo = (struct ip6t_rt *)(*match)->data;

	switch (c) {
	case '1':
		if (*flags & IP6T_RT_TYP)
			exit_error(PARAMETER_PROBLEM,
				   "Only one `--rt-type' allowed");
		check_inverse(optarg, &invert, &optind, 0);
		rtinfo->rt_type = parse_rt_num(argv[optind-1], "type");
		if (invert)
			rtinfo->invflags |= IP6T_RT_INV_TYP;
		rtinfo->flags |= IP6T_RT_TYP;
		*flags |= IP6T_RT_TYP;
		break;
	case '2':
		if (*flags & IP6T_RT_SGS)
			exit_error(PARAMETER_PROBLEM,
				   "Only one `--rt-segsleft' allowed");
		check_inverse(optarg, &invert, &optind, 0);
		parse_rt_segsleft(argv[optind-1], rtinfo->segsleft);
		if (invert)
			rtinfo->invflags |= IP6T_RT_INV_SGS;
		rtinfo->flags |= IP6T_RT_SGS;
		*flags |= IP6T_RT_SGS;
		break;
	case '3':
		if (*flags & IP6T_RT_LEN)
			exit_error(PARAMETER_PROBLEM,
				   "Only one `--rt-len' allowed");
		check_inverse(optarg, &invert, &optind, 0);
		rtinfo->hdrlen = parse_rt_num(argv[optind-1], "length");
		if (invert)
			rtinfo->invflags |= IP6T_RT_INV_LEN;
		rtinfo->flags |= IP6T_RT_LEN;
		*flags |= IP6T_RT_LEN;
		break;
	case '4':
		if (*flags & IP6T_RT_RES)
			exit_error(PARAMETER_PROBLEM,
				   "Only one `--rt-0-res' allowed");
		if ( !(*flags & IP6T_RT_TYP) || (rtinfo->rt_type != 0) || (rtinfo->invflags & IP6T_RT_INV_TYP) )
			exit_error(PARAMETER_PROBLEM,
				   "`--rt-type 0' required before `--rt-0-res'");
		rtinfo->flags |= IP6T_RT_RES;
		*flags |= IP6T_RT_RES;
		break;
	case '5':
		if (*flags & IP6T_RT_FST)
			exit_error(PARAMETER_PROBLEM,
				   "Only one `--rt-0-addrs' allowed");
		if ( !(*flags & IP6T_RT_TYP) || (rtinfo->rt_type != 0) || (rtinfo->invflags & IP6T_RT_INV_TYP) )
			exit_error(PARAMETER_PROBLEM,
				   "`--rt-type 0' required before `--rt-0-addrs'");
		check_inverse(optarg, &invert, &optind, 0);
		if (invert)
			exit_error(PARAMETER_PROBLEM,
				   " '!' not allowed with `--rt-0-addrs'");
		rtinfo->addrnr = parse_addresses(argv[optind-1], rtinfo->addrs);
		rtinfo->flags |= IP6T_RT_FST;
		*flags |= IP6T_RT_FST;
		break;
	case '6':
		if (*flags & IP6T_RT_FST_NSTRICT)
			exit_error(PARAMETER_PROBLEM,
				   "Only one `--rt-0-not-strict' allowed");
		if ( !(*flags & IP6T_RT_FST) )
			exit_error(PARAMETER_PROBLEM,
				   "`--rt-0-addr ...' required before `--rt-0-not-strict'");
		rtinfo->flags |= IP6T_RT_FST_NSTRICT;
		*flags |= IP6T_RT_FST_NSTRICT;
		break;
	default:
		return 0;
	}

	return 1;
}
Example #13
0
/* Function which parses command options; returns true if it
   ate an option. */
static int
tcp_parse(int c, char **argv, int invert, unsigned int *flags,
          const void *entry, struct xt_entry_match **match)
{
	struct xt_tcp *tcpinfo = (struct xt_tcp *)(*match)->data;

	switch (c) {
	case '1':
		if (*flags & TCP_SRC_PORTS)
			exit_error(PARAMETER_PROBLEM,
				   "Only one `--source-port' allowed");
		check_inverse(optarg, &invert, &optind, 0);
		parse_tcp_ports(argv[optind-1], tcpinfo->spts);
		if (invert)
			tcpinfo->invflags |= XT_TCP_INV_SRCPT;
		*flags |= TCP_SRC_PORTS;
		break;

	case '2':
		if (*flags & TCP_DST_PORTS)
			exit_error(PARAMETER_PROBLEM,
				   "Only one `--destination-port' allowed");
		check_inverse(optarg, &invert, &optind, 0);
		parse_tcp_ports(argv[optind-1], tcpinfo->dpts);
		if (invert)
			tcpinfo->invflags |= XT_TCP_INV_DSTPT;
		*flags |= TCP_DST_PORTS;
		break;

	case '3':
		if (*flags & TCP_FLAGS)
			exit_error(PARAMETER_PROBLEM,
				   "Only one of `--syn' or `--tcp-flags' "
				   " allowed");
		parse_tcp_flags(tcpinfo, "SYN,RST,ACK,FIN", "SYN", invert);
		*flags |= TCP_FLAGS;
		break;

	case '4':
		if (*flags & TCP_FLAGS)
			exit_error(PARAMETER_PROBLEM,
				   "Only one of `--syn' or `--tcp-flags' "
				   " allowed");
		check_inverse(optarg, &invert, &optind, 0);

		if (!argv[optind]
		    || argv[optind][0] == '-' || argv[optind][0] == '!')
			exit_error(PARAMETER_PROBLEM,
				   "--tcp-flags requires two args.");

		parse_tcp_flags(tcpinfo, argv[optind-1], argv[optind],
				invert);
		optind++;
		*flags |= TCP_FLAGS;
		break;

	case '5':
		if (*flags & TCP_OPTION)
			exit_error(PARAMETER_PROBLEM,
				   "Only one `--tcp-option' allowed");
		check_inverse(optarg, &invert, &optind, 0);
		parse_tcp_option(argv[optind-1], &tcpinfo->option);
		if (invert)
			tcpinfo->invflags |= XT_TCP_INV_OPTION;
		*flags |= TCP_OPTION;
		break;

	default:
		return 0;
	}

	return 1;
}
static int parse(int c, char **argv, int invert, unsigned int *flags,
				 const struct ipt_entry *entry, unsigned int *nfcache,
				 struct ipt_entry_match **match)
{
	const char *s;
	char *e, *p;
	int n;
	struct ipt_web_info *info;

	if ((c < '1') || (c > '6')) return 0;

	if (*flags) exit_error(PARAMETER_PROBLEM, "Multiple modes are not supported");
	*flags = 1;

	info = (struct ipt_web_info *)(*match)->data;
	switch (c) {
	case '2':
		info->mode = IPT_WEB_HOST;
		break;
	case '3':
		info->mode = IPT_WEB_RURI;
		break;
	case '4':
		info->mode = IPT_WEB_PATH;
		break;
	case '5':
		info->mode = IPT_WEB_QUERY;
		break;
	case '6':
		info->mode = IPT_WEB_HORE;
		break;
	default:	// IPT_WEB_HTTP
		return 1;
	}

	if (entry->ip.proto != IPPROTO_TCP) {
		exit_error(PARAMETER_PROBLEM, "web match requires -p tcp");
	}

	check_inverse(optarg, &invert, &optind, 0);
	if (invert) info->invert = 1;

	// convert arg to text\0text\0\0
	s = argv[optind - 1];

	if ((p = malloc(strlen(s) + 2)) == NULL) {
		exit_error(PARAMETER_PROBLEM, "Not enough memory");
	}

	e = p;
	while (*s) {
		while ((*s == ' ') || (*s == '\n') || (*s == '\t')) ++s;
		if (*s == 0) break;
		while ((*s != 0) && (*s != ' ') && (*s != '\n') && (*s != '\t')) {
			*e++ = *s++;
		}
		*e++ = 0;
	}
	n = (e - p);

#if 0
	*e = 0;
	e = p;
	while (*e) {
		printf("[%s]\n", e);
		e += strlen(e) + 1;
	}
#endif

	if (n <= 1) {
		exit_error(PARAMETER_PROBLEM, "Text is too short");
	}
	if (n >= IPT_WEB_MAXTEXT) {
		exit_error(PARAMETER_PROBLEM, "Text is too long");
	}
	memcpy(info->text, p, n);
	memset(info->text + n, 0, IPT_WEB_MAXTEXT - n);		// term, need to clear rest for ipt rule cmp
	free(p);
	return 1;
}
static int parse(int c, char **argv, int invert, unsigned int *flags,
                 const struct ipt_entry *entry,
                 unsigned int *nfcache,
                 struct ipt_entry_match **match)
{
	struct ipt_policy_info *info = (void *)(*match)->data;
	struct ipt_policy_elem *e = &info->pol[info->len];
	struct in_addr *addr = NULL, mask;
	unsigned int naddr = 0;
	int mode;

	check_inverse(optarg, &invert, &optind, 0);

	switch (c) {
	case '1':
		if (info->flags & (IPT_POLICY_MATCH_IN|IPT_POLICY_MATCH_OUT))
			exit_error(PARAMETER_PROBLEM,
			           "policy match: double --dir option");
		if (invert)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: can't invert --dir option");

		info->flags |= parse_direction(argv[optind-1]);
		break;
	case '2':
		if (invert)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: can't invert --policy option");

		info->flags |= parse_policy(argv[optind-1]);
		break;
	case '3':
		if (info->flags & IPT_POLICY_MATCH_STRICT)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: double --strict option");

		if (invert)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: can't invert --strict option");

		info->flags |= IPT_POLICY_MATCH_STRICT;
		break;
	case '4':
		if (e->match.reqid)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: double --reqid option");

		e->match.reqid = 1;
		e->invert.reqid = invert;
		e->reqid = strtol(argv[optind-1], NULL, 10);
		break;
	case '5':
		if (e->match.spi)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: double --spi option");

		e->match.spi = 1;
		e->invert.spi = invert;
		e->spi = strtol(argv[optind-1], NULL, 0x10);
		break;
	case '6':
		if (e->match.saddr)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: double --tunnel-src option");

		parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
		if (naddr > 1)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: name resolves to multiple IPs");

		e->match.saddr = 1;
		e->invert.saddr = invert;
		e->saddr.a4 = addr[0];
		e->smask.a4 = mask;
                break;
	case '7':
		if (e->match.daddr)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: double --tunnel-dst option");

		parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
		if (naddr > 1)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: name resolves to multiple IPs");

		e->match.daddr = 1;
		e->invert.daddr = invert;
		e->daddr.a4 = addr[0];
		e->dmask.a4 = mask;
		break;
	case '8':
		if (e->match.proto)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: double --proto option");

		e->proto = parse_protocol(argv[optind-1]);
		if (e->proto != IPPROTO_AH && e->proto != IPPROTO_ESP &&
		    e->proto != IPPROTO_COMP)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: protocol must ah/esp/ipcomp");
		e->match.proto = 1;
		e->invert.proto = invert;
		break;
	case '9':
		if (e->match.mode)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: double --mode option");

		mode = parse_mode(argv[optind-1]);
		e->match.mode = 1;
		e->invert.mode = invert;
		e->mode = mode;
		break;
	case 'a':
		if (invert)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: can't invert --next option");

		if (++info->len == IPT_POLICY_MAX_ELEM)
			exit_error(PARAMETER_PROBLEM,
			           "policy match: maximum policy depth reached");
		break;
	default:
		return 0;
	}

	policy_info = info;
	return 1;
}
static int
parse(int c, char **argv, int invert, unsigned int *flags,
      const struct ip6t_entry *entry,
      unsigned int *nfcache,
      struct ip6t_entry_match **match)
{
	struct ip6t_physdev_info *info =
		(struct ip6t_physdev_info*)(*match)->data;

	switch (c) {
	case '1':
		if (*flags & IP6T_PHYSDEV_OP_IN)
			goto multiple_use;
		check_inverse(optarg, &invert, &optind, 0);
		parse_interface(argv[optind-1], info->physindev,
				(unsigned char *)info->in_mask);
		if (invert)
			info->invert |= IP6T_PHYSDEV_OP_IN;
		info->bitmask |= IP6T_PHYSDEV_OP_IN;
		*flags |= IP6T_PHYSDEV_OP_IN;
		break;

	case '2':
		if (*flags & IP6T_PHYSDEV_OP_OUT)
			goto multiple_use;
		check_inverse(optarg, &invert, &optind, 0);
		parse_interface(argv[optind-1], info->physoutdev,
				(unsigned char *)info->out_mask);
		if (invert)
			info->invert |= IP6T_PHYSDEV_OP_OUT;
		info->bitmask |= IP6T_PHYSDEV_OP_OUT;
		*flags |= IP6T_PHYSDEV_OP_OUT;
		break;

	case '3':
		if (*flags & IP6T_PHYSDEV_OP_ISIN)
			goto multiple_use;
		check_inverse(optarg, &invert, &optind, 0);
		info->bitmask |= IP6T_PHYSDEV_OP_ISIN;
		if (invert)
			info->invert |= IP6T_PHYSDEV_OP_ISIN;
		*flags |= IP6T_PHYSDEV_OP_ISIN;
		break;

	case '4':
		if (*flags & IP6T_PHYSDEV_OP_ISOUT)
			goto multiple_use;
		check_inverse(optarg, &invert, &optind, 0);
		info->bitmask |= IP6T_PHYSDEV_OP_ISOUT;
		if (invert)
			info->invert |= IP6T_PHYSDEV_OP_ISOUT;
		*flags |= IP6T_PHYSDEV_OP_ISOUT;
		break;

	case '5':
		if (*flags & IP6T_PHYSDEV_OP_BRIDGED)
			goto multiple_use;
		check_inverse(optarg, &invert, &optind, 0);
		if (invert)
			info->invert |= IP6T_PHYSDEV_OP_BRIDGED;
		*flags |= IP6T_PHYSDEV_OP_BRIDGED;
		info->bitmask |= IP6T_PHYSDEV_OP_BRIDGED;
		break;

	default:
		return 0;
	}

	return 1;
multiple_use:
	exit_error(PARAMETER_PROBLEM,
	   "multiple use of the same physdev option is not allowed");

}
Example #17
0
/* Function which parses command options; returns true if it
   ate an option */
static int
parse(int c, char **argv, int invert, unsigned int *flags,
      const struct ip6t_entry *entry,
      struct ip6t_entry_target **target)
{
	struct ip6t_route_target_info *route_info = 
		(struct ip6t_route_target_info*)(*target)->data;

	switch (c) {
	case '1':
		if (*flags & IP6T_ROUTE_OPT_OIF)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify --oif twice");

		if (check_inverse(optarg, &invert, NULL, 0))
			exit_error(PARAMETER_PROBLEM,
				   "Unexpected `!' after --oif");

		if (strlen(optarg) > sizeof(route_info->oif) - 1)
			exit_error(PARAMETER_PROBLEM,
				   "Maximum interface name length %u",
				   sizeof(route_info->oif) - 1);

		strcpy(route_info->oif, optarg);
		*flags |= IP6T_ROUTE_OPT_OIF;
		break;

	case '2':
		exit_error(PARAMETER_PROBLEM,
			   "--iif option not implemented");
		break;

	case '3':
		if (*flags & IP6T_ROUTE_OPT_GW)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify --gw twice");

		if (check_inverse(optarg, &invert, NULL, 0))
			exit_error(PARAMETER_PROBLEM,
				   "Unexpected `!' after --gw");

		if (!inet_pton(AF_INET6, optarg, (struct in6_addr*)&route_info->gw)) {
			exit_error(PARAMETER_PROBLEM,
				   "Invalid IPv6 address %s",
				   optarg);
		}

		*flags |= IP6T_ROUTE_OPT_GW;
		break;

	case '4':
		if (*flags & IP6T_ROUTE_OPT_CONTINUE)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify --continue twice");
		if (*flags & IP6T_ROUTE_OPT_TEE)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify --continue AND --tee");

		route_info->flags |= IP6T_ROUTE_CONTINUE;
		*flags |= IP6T_ROUTE_OPT_CONTINUE;

		break;

	case '5':
		if (*flags & IP6T_ROUTE_OPT_TEE)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify --tee twice");
		if (*flags & IP6T_ROUTE_OPT_CONTINUE)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify --tee AND --continue");

		route_info->flags |= IP6T_ROUTE_TEE;
		*flags |= IP6T_ROUTE_OPT_TEE;

		break;

	default:
		return 0;
	}

	return 1;
}
Example #18
0
static int
parse(int c, char **argv, int invert, unsigned int *flags,
      const struct ipt_entry *entry,
      unsigned int *nfcache,
      struct ipt_entry_match **match)
{
	struct ipt_dccp_info *einfo
		= (struct ipt_dccp_info *)(*match)->data;

	switch (c) {
	case '1':
		if (*flags & IPT_DCCP_SRC_PORTS)
			exit_error(PARAMETER_PROBLEM,
			           "Only one `--source-port' allowed");
		einfo->flags |= IPT_DCCP_SRC_PORTS;
		check_inverse(optarg, &invert, &optind, 0);
		parse_dccp_ports(argv[optind-1], einfo->spts);
		if (invert)
			einfo->invflags |= IPT_DCCP_SRC_PORTS;
		*flags |= IPT_DCCP_SRC_PORTS;
		break;

	case '2':
		if (*flags & IPT_DCCP_DEST_PORTS)
			exit_error(PARAMETER_PROBLEM,
				   "Only one `--destination-port' allowed");
		einfo->flags |= IPT_DCCP_DEST_PORTS;
		check_inverse(optarg, &invert, &optind, 0);
		parse_dccp_ports(argv[optind-1], einfo->dpts);
		if (invert)
			einfo->invflags |= IPT_DCCP_DEST_PORTS;
		*flags |= IPT_DCCP_DEST_PORTS;
		break;

	case '3':
		if (*flags & IPT_DCCP_TYPE)
			exit_error(PARAMETER_PROBLEM,
				   "Only one `--dccp-types' allowed");
		einfo->flags |= IPT_DCCP_TYPE;
		check_inverse(optarg, &invert, &optind, 0);
		einfo->typemask = parse_dccp_types(argv[optind-1]);
		if (invert)
			einfo->invflags |= IPT_DCCP_TYPE;
		*flags |= IPT_DCCP_TYPE;
		break;

	case '4':
		if (*flags & IPT_DCCP_OPTION)
			exit_error(PARAMETER_PROBLEM,
				   "Only one `--dccp-option' allowed");
		einfo->flags |= IPT_DCCP_OPTION;
		check_inverse(optarg, &invert, &optind, 0);
		einfo->option = parse_dccp_option(argv[optind-1]);
		if (invert)
			einfo->invflags |= IPT_DCCP_OPTION;
		*flags |= IPT_DCCP_OPTION;
		break;
	default:
		return 0;
	}
	return 1;
}
Example #19
0
/* Function which parses command options; returns true if it
   ate an option */
static int
parse(int c, char **argv, int invert, unsigned int *flags,
      const struct ipt_entry *entry,
      unsigned int *nfcache,
      struct ipt_entry_match **match)
{
	struct ipt_recent_info *info = (struct ipt_recent_info *)(*match)->data;
	switch (c) {
		case 201:
			if (*flags) exit_error(PARAMETER_PROBLEM,
					"recent: only one of `--set', `--rcheck' "
					"`--update' or `--remove' may be set");
			check_inverse(optarg, &invert, &optind, 0);
			info->check_set |= IPT_RECENT_SET;
			if (invert) info->invert = 1;
			*flags = 1;
			break;
			
		case 202:
			if (*flags) exit_error(PARAMETER_PROBLEM,
					"recent: only one of `--set', `--rcheck' "
					"`--update' or `--remove' may be set");
			check_inverse(optarg, &invert, &optind, 0);
			info->check_set |= IPT_RECENT_CHECK;
			if(invert) info->invert = 1;
			*flags = 1;
			break;

		case 203:
			if (*flags) exit_error(PARAMETER_PROBLEM,
					"recent: only one of `--set', `--rcheck' "
					"`--update' or `--remove' may be set");
			check_inverse(optarg, &invert, &optind, 0);
			info->check_set |= IPT_RECENT_UPDATE;
			if (invert) info->invert = 1;
			*flags = 1;
			break;

		case 206:
			if (*flags) exit_error(PARAMETER_PROBLEM,
					"recent: only one of `--set', `--rcheck' "
					"`--update' or `--remove' may be set");
			check_inverse(optarg, &invert, &optind, 0);
			info->check_set |= IPT_RECENT_REMOVE;
			if (invert) info->invert = 1;
			*flags = 1;
			break;

		case 204:
			info->seconds = atoi(optarg);
			break;

		case 205:
			info->hit_count = atoi(optarg);
			break;

		case 207:
			info->check_set |= IPT_RECENT_TTL;
			break;

		case 208:
			strncpy(info->name,optarg,IPT_RECENT_NAME_LEN);
			info->name[IPT_RECENT_NAME_LEN-1] = '\0';
			break;

		case 209:
			info->side = IPT_RECENT_SOURCE;
			break;

		case 210:
			info->side = IPT_RECENT_DEST;
			break;

		default:
			return 0;
	}

	return 1;
}
static int parse(int c, char **argv, int invert, unsigned int *flags,
		 const struct ipt_entry *entry,
		 struct xt_entry_target **target)
{
	struct xt_nflog_info *info = (struct xt_nflog_info *)(*target)->data;
	int n;

	switch (c) {
	case NFLOG_GROUP:
		if (*flags & NFLOG_GROUP)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify --nflog-group twice");
		if (check_inverse(optarg, &invert, NULL, 0))
			exit_error(PARAMETER_PROBLEM,
				   "Unexpected `!' after --nflog-group");

		n = atoi(optarg);
		if (n < 1 || n > 32)
			exit_error(PARAMETER_PROBLEM,
				   "--nflog-group has to be between 1 and 32");
		info->group = 1 << (n - 1);
		break;
	case NFLOG_PREFIX:
		if (*flags & NFLOG_PREFIX)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify --nflog-prefix twice");
		if (check_inverse(optarg, &invert, NULL, 0))
			exit_error(PARAMETER_PROBLEM,
				   "Unexpected `!' after --nflog-prefix");

		n = strlen(optarg);
		if (n == 0)
			exit_error(PARAMETER_PROBLEM,
				   "No prefix specified for --nflog-prefix");
		if (n >= sizeof(info->prefix))
			exit_error(PARAMETER_PROBLEM,
				   "--nflog-prefix too long, max %Zu characters",
				   sizeof(info->prefix) - 1);
		if (n != strlen(strtok(optarg, "\n")))
			exit_error(PARAMETER_PROBLEM,
				   "Newlines are not allowed in --nflog-prefix");
		strcpy(info->prefix, optarg);
		break;
	case NFLOG_RANGE:
		if (*flags & NFLOG_RANGE)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify --nflog-range twice");
		n = atoi(optarg);
		if (n < 0)
			exit_error(PARAMETER_PROBLEM,
				   "Invalid --nflog-range, must be >= 0");
		info->len = n;
		break;
	case NFLOG_THRESHOLD:
		if (*flags & NFLOG_THRESHOLD)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify --nflog-threshold twice");
		n = atoi(optarg);
		if (n < 1)
			exit_error(PARAMETER_PROBLEM,
				   "Invalid --nflog-threshold, must be >= 1");
		info->threshold = n;
		break;
	default:
		return 0;
	}
	*flags |= c;
	return 1;
}
/* Function which parses command options; returns true if it
   ate an option */
static int
parse(int c, char **argv, int invert, unsigned int *flags,
      const struct ipt_entry *entry,
      unsigned int *nfcache,
      struct ipt_entry_match **match)
{
	struct ipt_string_info *stringinfo = (struct ipt_string_info *)(*match)->data;

	switch (c) {
	case '1':
		if (*flags & FROM)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify multiple --from");
		stringinfo->from_offset = atoi(optarg);
		*flags |= FROM;
		stringinfo->type = 0;
		break;
	case '2':
		if (*flags & TO)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify multiple --to");
		stringinfo->to_offset = atoi(optarg);
		*flags |= TO;
		stringinfo->type = 0;
		break;
	case '3':
		if (*flags & ALGO)
			exit_error(PARAMETER_PROBLEM,
				   "Can't specify multiple --algo");
		parse_algo(optarg, stringinfo);
		*flags |= ALGO;
		stringinfo->type = 0;
		break;
	case '4':
		check_inverse(optarg, &invert, &optind, 0);
		parse_string(argv[optind-1], stringinfo);
		if (invert)
			stringinfo->invert = 1;
		stringinfo->patlen=strlen((char *)&stringinfo->pattern);
		stringinfo->type = IPT_WEBSTR_URL;
		break;

	case '5':
		check_inverse(optarg, &invert, &optind, 0);
		parse_string(argv[optind-1], stringinfo);
		if (invert)
			stringinfo->invert = 1;
		stringinfo->patlen=strlen((char *)&stringinfo->pattern);
		stringinfo->type = IPT_WEBSTR_HOST;
		break;
        case '6':
               check_inverse(optarg, &invert, &optind, 0);
               parse_string(argv[optind-1], stringinfo);
                if (invert)
                        stringinfo->invert = 1;
	                stringinfo->patlen=strlen((char *)&stringinfo->pattern);
                stringinfo->type = IPT_WEBSTR_CONTENT;
                break;
	default:
		return 0;
	}
	*flags = 1;
	return 1;
}
Example #22
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;
}