static void parse_target(char **argv, int invert, unsigned int *flags, struct ipt_set_info *info, const char *what) { if (info->flags[0]) xtables_error(PARAMETER_PROBLEM, "--%s can be specified only once", what); if (xtables_check_inverse(optarg, &invert, NULL, 0)) xtables_error(PARAMETER_PROBLEM, "Unexpected `!' after --%s", what); if (!argv[optind] || argv[optind][0] == '-' || argv[optind][0] == '!') xtables_error(PARAMETER_PROBLEM, "--%s requires two args.", what); if (strlen(argv[optind-1]) > IP_SET_MAXNAMELEN - 1) xtables_error(PARAMETER_PROBLEM, "setname `%s' too long, max %d characters.", argv[optind-1], IP_SET_MAXNAMELEN - 1); get_set_byname(argv[optind - 1], info); parse_bindings(argv[optind], info); optind++; *flags = 1; }
static int set_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { struct ipt_set_info_match *myinfo = (struct ipt_set_info_match *) (*match)->data; struct ipt_set_info *info = &myinfo->match_set; switch (c) { case '2': #if 0 fprintf(stderr, "--set option deprecated, please use --match-set\n"); #endif case '1': /* --match-set <set> <flag>[,<flag> */ if (info->flags[0]) xtables_error(PARAMETER_PROBLEM, "--match-set can be specified only once"); xtables_check_inverse(optarg, &invert, &optind, 0, argv); if (invert) info->flags[0] |= IPSET_MATCH_INV; if (!argv[optind] || argv[optind][0] == '-' || argv[optind][0] == '!') xtables_error(PARAMETER_PROBLEM, "--match-set requires two args."); if (strlen(optarg) > IP_SET_MAXNAMELEN - 1) xtables_error(PARAMETER_PROBLEM, "setname `%s' too long, max %d characters.", optarg, IP_SET_MAXNAMELEN - 1); get_set_byname(optarg, info); parse_bindings(argv[optind], info); DEBUGP("parse: set index %u\n", info->index); optind++; *flags = 1; 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, unsigned int *nfcache, struct ipt_entry_match **match) { struct ipt_set_info_match *myinfo = (struct ipt_set_info_match *) (*match)->data; struct ipt_set_info *info = &myinfo->match_set; switch (c) { case '1': /* --set <set> <flag>[,<flag> */ if (info->flags[0]) exit_error(PARAMETER_PROBLEM, "--set can be specified only once"); check_inverse(optarg, &invert, &optind, 0); if (invert) info->flags[0] |= IPSET_MATCH_INV; if (!argv[optind] || argv[optind][0] == '-' || argv[optind][0] == '!') exit_error(PARAMETER_PROBLEM, "--set requires two args."); if (strlen(argv[optind-1]) > IP_SET_MAXNAMELEN - 1) exit_error(PARAMETER_PROBLEM, "setname `%s' too long, max %d characters.", argv[optind-1], IP_SET_MAXNAMELEN - 1); get_set_byname(argv[optind - 1], info); parse_bindings(argv[optind], info); DEBUGP("parse: set index %u\n", info->index); optind++; *flags = 1; break; default: return 0; } return 1; }
static int set_parse_v2(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { struct xt_set_info_match_v1 *myinfo = (struct xt_set_info_match_v1 *) (*match)->data; struct xt_set_info *info = &myinfo->match_set; switch (c) { case '3': info->flags |= IPSET_RETURN_NOMATCH; break; case '2': fprintf(stderr, "--set option deprecated, please use --match-set\n"); case '1': /* --match-set <set> <flag>[,<flag> */ if (info->dim) xtables_error(PARAMETER_PROBLEM, "--match-set can be specified only once"); if (invert) info->flags |= IPSET_INV_MATCH; if (!argv[optind] || argv[optind][0] == '-' || argv[optind][0] == '!') xtables_error(PARAMETER_PROBLEM, "--match-set requires two args."); if (strlen(optarg) > IPSET_MAXNAMELEN - 1) xtables_error(PARAMETER_PROBLEM, "setname `%s' too long, max %d characters.", optarg, IPSET_MAXNAMELEN - 1); get_set_byname(optarg, info); parse_dirs(argv[optind], info); DEBUGP("parse: set index %u\n", info->index); optind++; *flags = 1; break; } return 1; }
static int ipset_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr, struct bstr *args) { struct xt_set_info set_info = {}; int ret; #define PARSE_ERR(CARG, FMT, ARGS...) \ em_parse_error(EINVAL, args, CARG, &ipset_ematch_util, FMT, ##ARGS) if (args == NULL) return PARSE_ERR(args, "ipset: missing set name"); if (args->len >= IPSET_MAXNAMELEN) return PARSE_ERR(args, "ipset: set name too long (max %u)", IPSET_MAXNAMELEN - 1); ret = get_set_byname(args->data, &set_info); if (ret < 0) return PARSE_ERR(args, "ipset: unknown set name '%s'", args->data); if (args->next == NULL) return PARSE_ERR(args, "ipset: missing set flags"); args = bstr_next(args); if (parse_dirs(args->data, &set_info)) return PARSE_ERR(args, "ipset: error parsing set flags"); if (args->next) { args = bstr_next(args); return PARSE_ERR(args, "ipset: unknown parameter"); } addraw_l(n, MAX_MSG, hdr, sizeof(*hdr)); addraw_l(n, MAX_MSG, &set_info, sizeof(set_info)); #undef PARSE_ERR return 0; }
/* Revision 4 */ static int set_parse_v4(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { struct xt_set_info_match_v4 *info = (struct xt_set_info_match_v4 *) (*match)->data; switch (c) { case 'a': if (invert) info->flags |= IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE; break; case '0': if (info->bytes.op != IPSET_COUNTER_NONE) xtables_error(PARAMETER_PROBLEM, "only one of the --bytes-[eq|lt|gt]" " is allowed\n"); if (invert) xtables_error(PARAMETER_PROBLEM, "--bytes-gt option cannot be inverted\n"); info->bytes.op = IPSET_COUNTER_GT; info->bytes.value = parse_counter(optarg); break; case '9': if (info->bytes.op != IPSET_COUNTER_NONE) xtables_error(PARAMETER_PROBLEM, "only one of the --bytes-[eq|lt|gt]" " is allowed\n"); if (invert) xtables_error(PARAMETER_PROBLEM, "--bytes-lt option cannot be inverted\n"); info->bytes.op = IPSET_COUNTER_LT; info->bytes.value = parse_counter(optarg); break; case '8': if (info->bytes.op != IPSET_COUNTER_NONE) xtables_error(PARAMETER_PROBLEM, "only one of the --bytes-[eq|lt|gt]" " is allowed\n"); info->bytes.op = invert ? IPSET_COUNTER_NE : IPSET_COUNTER_EQ; info->bytes.value = parse_counter(optarg); break; case '7': if (info->packets.op != IPSET_COUNTER_NONE) xtables_error(PARAMETER_PROBLEM, "only one of the --packets-[eq|lt|gt]" " is allowed\n"); if (invert) xtables_error(PARAMETER_PROBLEM, "--packets-gt option cannot be inverted\n"); info->packets.op = IPSET_COUNTER_GT; info->packets.value = parse_counter(optarg); break; case '6': if (info->packets.op != IPSET_COUNTER_NONE) xtables_error(PARAMETER_PROBLEM, "only one of the --packets-[eq|lt|gt]" " is allowed\n"); if (invert) xtables_error(PARAMETER_PROBLEM, "--packets-lt option cannot be inverted\n"); info->packets.op = IPSET_COUNTER_LT; info->packets.value = parse_counter(optarg); break; case '5': if (info->packets.op != IPSET_COUNTER_NONE) xtables_error(PARAMETER_PROBLEM, "only one of the --packets-[eq|lt|gt]" " is allowed\n"); info->packets.op = invert ? IPSET_COUNTER_NE : IPSET_COUNTER_EQ; info->packets.value = parse_counter(optarg); break; case '4': if (invert) info->flags |= IPSET_FLAG_SKIP_COUNTER_UPDATE; break; case '3': if (invert) xtables_error(PARAMETER_PROBLEM, "--return-nomatch flag cannot be inverted\n"); info->flags |= IPSET_FLAG_RETURN_NOMATCH; break; case '2': fprintf(stderr, "--set option deprecated, please use --match-set\n"); case '1': /* --match-set <set> <flag>[,<flag> */ if (info->match_set.dim) xtables_error(PARAMETER_PROBLEM, "--match-set can be specified only once"); if (invert) info->match_set.flags |= IPSET_INV_MATCH; if (!argv[optind] || argv[optind][0] == '-' || argv[optind][0] == '!') xtables_error(PARAMETER_PROBLEM, "--match-set requires two args."); if (strlen(optarg) > IPSET_MAXNAMELEN - 1) xtables_error(PARAMETER_PROBLEM, "setname `%s' too long, max %d characters.", optarg, IPSET_MAXNAMELEN - 1); get_set_byname(optarg, &info->match_set); parse_dirs(argv[optind], &info->match_set); DEBUGP("parse: set index %u\n", info->match_set.index); optind++; *flags = 1; break; } return 1; }
int ip6tables_add_rules(struct ip6tc_handle* handle, const char* chain_name, int rulenum, int dim, int src_dst, const char* target_name, const char* set_name, uint16_t protocol, int param, int cmd, bool ignore_errors) { size_t size; struct ip6t_entry *fw; struct xt_entry_target *target; struct xt_entry_match *match; #ifdef HAVE_XT_SET_INFO_MATCH_V1 struct xt_set_info_match_v1 *setinfo; #else struct xt_set_info_match *setinfo; #endif ip6t_chainlabel chain; int res; int sav_errno; /* Add an entry */ memset(chain, 0, sizeof(chain)); size = XT_ALIGN(sizeof (struct ip6t_entry)) + XT_ALIGN(sizeof(struct xt_entry_match)) + XT_ALIGN(sizeof(struct xt_entry_target) + 1) + XT_ALIGN(sizeof(*setinfo)); if (protocol == IPPROTO_ICMPV6) size += XT_ALIGN(sizeof(struct xt_entry_match)) + XT_ALIGN(sizeof(struct ip6t_icmp)); fw = (struct ip6t_entry*)MALLOC(size); fw->target_offset = XT_ALIGN(sizeof(struct ip6t_entry)); // set match = (struct xt_entry_match*)((char*)fw + fw->target_offset); match->u.match_size = XT_ALIGN(sizeof(struct xt_entry_match)) + XT_ALIGN(sizeof(*setinfo)); #ifdef HAVE_XT_SET_INFO_MATCH_V1 match->u.user.revision = 1; #else match->u.user.revision = 0; #endif fw->target_offset += match->u.match_size; strcpy(match->u.user.name, "set"); #ifdef HAVE_XT_SET_INFO_MATCH_V1 setinfo = (struct xt_set_info_match_v1 *)match->data; #else setinfo = (struct xt_set_info_match *)match->data; #endif get_set_byname (set_name, &setinfo->match_set, NFPROTO_IPV6, ignore_errors); if (setinfo->match_set.index == IPSET_INVALID_ID) { FREE(fw); return -1; } setinfo->match_set.dim = dim; setinfo->match_set.flags = src_dst; if (protocol != IPPROTO_NONE) { fw->ipv6.proto = protocol; fw->ipv6.flags |= IP6T_F_PROTO ; // IPv6 only if (protocol == IPPROTO_ICMPV6) { match = (struct xt_entry_match*)((char*)fw + fw->target_offset); match->u.match_size = XT_ALIGN(sizeof(struct xt_entry_match)) + XT_ALIGN(sizeof(struct ip6t_icmp)); match->u.user.revision = 0; fw->target_offset += match->u.match_size; strcpy(match->u.user.name, "icmp6"); struct ip6t_icmp *icmpinfo = (struct ip6t_icmp *)match->data; icmpinfo->type = param; // type to match icmpinfo->code[0] = 0; // code lower icmpinfo->code[1] = 0xff; // code upper icmpinfo->invflags = 0; // don't invert } } // target is XTC_LABEL_DROP/XTC_LABEL_ACCEPT fw->next_offset = size; target = ip6t_get_target(fw); target->u.user.target_size = XT_ALIGN(sizeof(struct xt_entry_target) + 1); strcpy(target->u.user.name, target_name); // fw->ip.flags |= IP6T_F_GOTO; strcpy(chain, chain_name); // Use iptc_append_entry to add to the chain if (cmd == IPADDRESS_DEL) { unsigned char matchmask[fw->next_offset]; memset(matchmask, 0xff, fw->next_offset); res = ip6tc_delete_entry(chain, fw, matchmask, handle); } else if (rulenum == -1) res = ip6tc_append_entry(chain, fw, handle) ; else res = ip6tc_insert_entry(chain, fw, rulenum, handle) ; sav_errno = errno; FREE(fw); if (res!= 1) { if (!ignore_errors) log_message(LOG_INFO, "ip6tc_insert_entry for chain %s returned %d: %s", chain, res, ip6tc_strerror(sav_errno)) ; return sav_errno; } return 0; }