/* Parses ports */ static void parse_ports(const char *arg, struct nf_nat_multi_range *mr) { char *end; unsigned int port, maxport; mr->range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED; if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX)) xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg); switch (*end) { case '\0': mr->range[0].min.tcp.port = mr->range[0].max.tcp.port = htons(port); return; case '-': if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX)) break; if (maxport < port) break; mr->range[0].min.tcp.port = htons(port); mr->range[0].max.tcp.port = htons(maxport); return; default: break; } xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg); }
static int mark_mt_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { struct xt_mark_mtinfo1 *info = (void *)(*match)->data; unsigned int mark, mask = UINT32_MAX; char *end; switch (c) { case '1': /* --mark */ xtables_param_act(XTF_ONLY_ONCE, "mark", "--mark", *flags & F_MARK); if (!xtables_strtoui(optarg, &end, &mark, 0, UINT32_MAX)) xtables_param_act(XTF_BAD_VALUE, "mark", "--mark", optarg); if (*end == '/') if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) xtables_param_act(XTF_BAD_VALUE, "mark", "--mark", optarg); if (*end != '\0') xtables_param_act(XTF_BAD_VALUE, "mark", "--mark", optarg); if (invert) info->invert = true; info->mark = mark; info->mask = mask; *flags |= F_MARK; return true; } return false; }
/* Parses ports */ static void parse_ports(const char *arg, struct nf_nat_range *range) { char *end = ""; unsigned int port, maxport; range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED; if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX) && (port = xtables_service_to_port(arg, NULL)) == (unsigned)-1) xtables_param_act(XTF_BAD_VALUE, "REDIRECT", "--to-ports", arg); switch (*end) { case '\0': range->min_proto.tcp.port = range->max_proto.tcp.port = htons(port); return; case '-': if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX) && (maxport = xtables_service_to_port(end + 1, NULL)) == (unsigned)-1) break; if (maxport < port) break; range->min_proto.tcp.port = htons(port); range->max_proto.tcp.port = htons(maxport); return; default: break; } xtables_param_act(XTF_BAD_VALUE, "REDIRECT", "--to-ports", arg); }
static int mark_tg_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_target **target) { struct xt_mark_tginfo2 *info = (void *)(*target)->data; unsigned int value, mask = UINT32_MAX; char *end; switch (c) { case 'X': /* --set-xmark */ case '=': /* --set-mark */ xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK); xtables_param_act(XTF_NO_INVERT, "MARK", "--set-xmark/--set-mark", invert); if (!xtables_strtoui(optarg, &end, &value, 0, UINT32_MAX)) xtables_param_act(XTF_BAD_VALUE, "MARK", "--set-xmark/--set-mark", optarg); if (*end == '/') if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) xtables_param_act(XTF_BAD_VALUE, "MARK", "--set-xmark/--set-mark", optarg); if (*end != '\0') xtables_param_act(XTF_BAD_VALUE, "MARK", "--set-xmark/--set-mark", optarg); info->mark = value; info->mask = mask; if (c == '=') info->mask = value | mask; break; case '&': /* --and-mark */ xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK); xtables_param_act(XTF_NO_INVERT, "MARK", "--and-mark", invert); if (!xtables_strtoui(optarg, NULL, &mask, 0, UINT32_MAX)) xtables_param_act(XTF_BAD_VALUE, "MARK", "--and-mark", optarg); info->mark = 0; info->mask = ~mask; break; case '|': /* --or-mark */ xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK); xtables_param_act(XTF_NO_INVERT, "MARK", "--or-mark", invert); if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX)) xtables_param_act(XTF_BAD_VALUE, "MARK", "--or-mark", optarg); info->mark = value; info->mask = value; break; case '^': /* --xor-mark */ xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK); xtables_param_act(XTF_NO_INVERT, "MARK", "--xor-mark", invert); if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX)) xtables_param_act(XTF_BAD_VALUE, "MARK", "--xor-mark", optarg); info->mark = value; info->mask = 0; break; default: return false; } *flags |= F_MARK; return true; }
static int statistic_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { struct xt_statistic_info *info = (void *)(*match)->data; unsigned int val; double prob; if (invert) info->flags |= XT_STATISTIC_INVERT; switch (c) { case '1': if (*flags & 0x1) xtables_error(PARAMETER_PROBLEM, "double --mode"); if (!strcmp(optarg, "random")) info->mode = XT_STATISTIC_MODE_RANDOM; else if (!strcmp(optarg, "nth")) info->mode = XT_STATISTIC_MODE_NTH; else xtables_error(PARAMETER_PROBLEM, "Bad mode \"%s\"", optarg); *flags |= 0x1; break; case '2': if (*flags & 0x2) xtables_error(PARAMETER_PROBLEM, "double --probability"); prob = atof(optarg); if (prob < 0 || prob > 1) xtables_error(PARAMETER_PROBLEM, "--probability must be between 0 and 1"); info->u.random.probability = 0x80000000 * prob; *flags |= 0x2; break; case '3': if (*flags & 0x4) xtables_error(PARAMETER_PROBLEM, "double --every"); if (!xtables_strtoui(optarg, NULL, &val, 0, UINT32_MAX)) xtables_error(PARAMETER_PROBLEM, "cannot parse --every `%s'", optarg); info->u.nth.every = val; if (info->u.nth.every == 0) xtables_error(PARAMETER_PROBLEM, "--every cannot be 0"); info->u.nth.every--; *flags |= 0x4; break; case '4': if (*flags & 0x8) xtables_error(PARAMETER_PROBLEM, "double --packet"); if (!xtables_strtoui(optarg, NULL, &val, 0, UINT32_MAX)) xtables_error(PARAMETER_PROBLEM, "cannot parse --packet `%s'", optarg); info->u.nth.packet = val; *flags |= 0x8; break; default: return 0; } return 1; }
static int ttl_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { struct ipt_ttl_info *info = (struct ipt_ttl_info *) (*match)->data; unsigned int value; xtables_check_inverse(optarg, &invert, &optind, 0); switch (c) { case '2': if (!xtables_strtoui(optarg, NULL, &value, 0, UINT8_MAX)) xtables_error(PARAMETER_PROBLEM, "ttl: Expected value between 0 and 255"); if (invert) info->mode = IPT_TTL_NE; else info->mode = IPT_TTL_EQ; /* is 0 allowed? */ info->ttl = value; break; case '3': if (!xtables_strtoui(optarg, NULL, &value, 0, UINT8_MAX)) xtables_error(PARAMETER_PROBLEM, "ttl: Expected value between 0 and 255"); if (invert) xtables_error(PARAMETER_PROBLEM, "ttl: unexpected `!'"); info->mode = IPT_TTL_LT; info->ttl = value; break; case '4': if (!xtables_strtoui(optarg, NULL, &value, 0, UINT8_MAX)) xtables_error(PARAMETER_PROBLEM, "ttl: Expected value between 0 and 255"); if (invert) xtables_error(PARAMETER_PROBLEM, "ttl: unexpected `!'"); info->mode = IPT_TTL_GT; info->ttl = value; break; default: return 0; } if (*flags) xtables_error(PARAMETER_PROBLEM, "Can't specify TTL option twice"); *flags = 1; return 1; }
static int ipmark_tg_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_target **target) { struct xt_ipmark_tginfo *info = (void *)(*target)->data; unsigned int n; switch (c) { case '1': xtables_param_act(XTF_ONLY_ONCE, "IPMARK", "addr", *flags & FL_ADDR_USED); xtables_param_act(XTF_NO_INVERT, "IPMARK", "addr", invert); if (strcmp(optarg, "src") == 0) info->selector = XT_IPMARK_SRC; else if (strcmp(optarg, "dst") == 0) info->selector = XT_IPMARK_DST; else xtables_error(PARAMETER_PROBLEM, "Bad addr value `%s' - should be `src' or `dst'", optarg); *flags |= FL_ADDR_USED; return true; case '2': xtables_param_act(XTF_ONLY_ONCE, "IPMARK", "and-mask", *flags & FL_AND_MASK_USED); xtables_param_act(XTF_NO_INVERT, "IPMARK", "and-mask", invert); if (!xtables_strtoui(optarg, NULL, &n, 0, ~0U)) xtables_param_act(XTF_BAD_VALUE, "IPMARK", "and-mask", optarg); info->andmask = n; *flags |= FL_AND_MASK_USED; return true; case '3': xtables_param_act(XTF_ONLY_ONCE, "IPMARK", "or-mask", *flags & FL_OR_MASK_USED); xtables_param_act(XTF_NO_INVERT, "IPMARK", "or-mask", invert); if (!xtables_strtoui(optarg, NULL, &n, 0, ~0U)) xtables_param_act(XTF_BAD_VALUE, "IPMARK", "or-mask", optarg); info->ormask = n; *flags |= FL_OR_MASK_USED; return true; case '4': xtables_param_act(XTF_ONLY_ONCE, "IPMARK", "--shift", *flags & FL_SHIFT); xtables_param_act(XTF_NO_INVERT, "IPMARK", "--shift", invert); /* * Anything >31 does not make sense for IPv4, but it still * does the right thing. */ if (!xtables_strtoui(optarg, NULL, &n, 0, 128)) xtables_param_act(XTF_BAD_VALUE, "IPMARK", "--shift", optarg); info->shift = n; *flags |= FL_SHIFT; return true; } return false; }
static int length_mt_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { struct xt_length_mtinfo2 *info = (void *)(*match)->data; unsigned int from, to; char *end; switch (c) { case '3': /* --layer3 */ xtables_param_act(XTF_ONLY_ONCE, "length", "--layer*", *flags & F_LAYER); info->flags &= ~XT_LENGTH_LAYER_MASK; info->flags |= XT_LENGTH_LAYER3; *flags |= F_LAYER; return true; case '4': /* --layer4 */ xtables_param_act(XTF_ONLY_ONCE, "length", "--layer*", *flags & F_LAYER); info->flags &= ~XT_LENGTH_LAYER_MASK; info->flags |= XT_LENGTH_LAYER4; *flags |= F_LAYER; return true; case '5': /* --layer5 */ xtables_param_act(XTF_ONLY_ONCE, "length", "--layer*", *flags & F_LAYER); info->flags &= ~XT_LENGTH_LAYER_MASK; info->flags |= XT_LENGTH_LAYER5; *flags |= F_LAYER; return true; case '7': /* --layer7 */ xtables_param_act(XTF_ONLY_ONCE, "length", "--layer*", *flags & F_LAYER); info->flags &= ~XT_LENGTH_LAYER_MASK; info->flags |= XT_LENGTH_LAYER7; *flags |= F_LAYER; return true; case '=': /* --length */ xtables_param_act(XTF_ONLY_ONCE, "length", "--length", *flags & F_LENGTH); if (invert) info->flags |= XT_LENGTH_INVERT; if (!xtables_strtoui(optarg, &end, &from, 0, ~0U)) xtables_param_act(XTF_BAD_VALUE, "length", "--length", optarg); to = from; if (*end == ':') if (!xtables_strtoui(end + 1, &end, &to, 0, ~0U)) xtables_param_act(XTF_BAD_VALUE, "length", "--length", optarg); if (*end != '\0') xtables_param_act(XTF_BAD_VALUE, "length", "--length", optarg); info->min = from; info->max = to; *flags |= F_LENGTH; return true; } return false; }
static void parse_icmp(const char *icmptype, uint8_t *type, uint8_t code[]) { static const unsigned int limit = ARRAY_SIZE(icmp_codes); unsigned int match = limit; unsigned int i; for (i = 0; i < limit; i++) { if (strncasecmp(icmp_codes[i].name, icmptype, strlen(icmptype)) == 0) { if (match != limit) xtables_error(PARAMETER_PROBLEM, "Ambiguous ICMP type `%s':" " `%s' or `%s'?", icmptype, icmp_codes[match].name, icmp_codes[i].name); match = i; } } if (match != limit) { *type = icmp_codes[match].type; code[0] = icmp_codes[match].code_min; code[1] = icmp_codes[match].code_max; } else { char *slash; char buffer[strlen(icmptype) + 1]; unsigned int number; strcpy(buffer, icmptype); slash = strchr(buffer, '/'); if (slash) *slash = '\0'; if (!xtables_strtoui(buffer, NULL, &number, 0, UINT8_MAX)) xtables_error(PARAMETER_PROBLEM, "Invalid ICMP type `%s'\n", buffer); *type = number; if (slash) { if (!xtables_strtoui(slash+1, NULL, &number, 0, UINT8_MAX)) xtables_error(PARAMETER_PROBLEM, "Invalid ICMP code `%s'\n", slash+1); code[0] = code[1] = number; } else { code[0] = 0; code[1] = 0xFF; } } }
static int tos_tg_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_target **target) { struct xt_tos_target_info *info = (void *)(*target)->data; struct tos_value_mask tvm; unsigned int bits; switch (c) { case '=': /* --set-tos */ xtables_param_act(XTF_ONLY_ONCE, "TOS", "--set-tos", *flags & FLAG_TOS); xtables_param_act(XTF_NO_INVERT, "TOS", "--set-tos", invert); if (!tos_parse_symbolic(optarg, &tvm, 0x3F)) xtables_param_act(XTF_BAD_VALUE, "TOS", "--set-tos", optarg); info->tos_value = tvm.value; info->tos_mask = tvm.mask; break; case '&': /* --and-tos */ xtables_param_act(XTF_ONLY_ONCE, "TOS", "--and-tos", *flags & FLAG_TOS); xtables_param_act(XTF_NO_INVERT, "TOS", "--and-tos", invert); if (!xtables_strtoui(optarg, NULL, &bits, 0, UINT8_MAX)) xtables_param_act(XTF_BAD_VALUE, "TOS", "--and-tos", optarg); info->tos_value = 0; info->tos_mask = ~bits; break; case '|': /* --or-tos */ xtables_param_act(XTF_ONLY_ONCE, "TOS", "--or-tos", *flags & FLAG_TOS); xtables_param_act(XTF_NO_INVERT, "TOS", "--or-tos", invert); if (!xtables_strtoui(optarg, NULL, &bits, 0, UINT8_MAX)) xtables_param_act(XTF_BAD_VALUE, "TOS", "--or-tos", optarg); info->tos_value = bits; info->tos_mask = bits; break; case '^': /* --xor-tos */ xtables_param_act(XTF_ONLY_ONCE, "TOS", "--xor-tos", *flags & FLAG_TOS); xtables_param_act(XTF_NO_INVERT, "TOS", "--xor-tos", invert); if (!xtables_strtoui(optarg, NULL, &bits, 0, UINT8_MAX)) xtables_param_act(XTF_BAD_VALUE, "TOS", "--xor-tos", optarg); info->tos_value = bits; info->tos_mask = 0; break; default: return false; } *flags |= FLAG_TOS; return true; }
static int psd_mt_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { struct xt_psd_info *psdinfo = (struct xt_psd_info *)(*match)->data; unsigned int num; switch (c) { /* PSD-weight-threshold */ case '1': if (*flags & XT_PSD_OPT_CTRESH) xtables_error(PARAMETER_PROBLEM,"Can't specify --psd-weight-threshold twice"); if (!xtables_strtoui(optarg, NULL, &num, 0, PSD_MAX_RATE)) xtables_error(PARAMETER_PROBLEM, "bad --psd-weight-threshold '%s'", optarg); psdinfo->weight_threshold = num; *flags |= XT_PSD_OPT_CTRESH; return true; /* PSD-delay-threshold */ case '2': if (*flags & XT_PSD_OPT_DTRESH) xtables_error(PARAMETER_PROBLEM, "Can't specify --psd-delay-threshold twice"); if (!xtables_strtoui(optarg, NULL, &num, 0, PSD_MAX_RATE)) xtables_error(PARAMETER_PROBLEM, "bad --psd-delay-threshold '%s'", optarg); psdinfo->delay_threshold = num; *flags |= XT_PSD_OPT_DTRESH; return true; /* PSD-lo-ports-weight */ case '3': if (*flags & XT_PSD_OPT_LPWEIGHT) xtables_error(PARAMETER_PROBLEM, "Can't specify --psd-lo-ports-weight twice"); if (!xtables_strtoui(optarg, NULL, &num, 0, PSD_MAX_RATE)) xtables_error(PARAMETER_PROBLEM, "bad --psd-lo-ports-weight '%s'", optarg); psdinfo->lo_ports_weight = num; *flags |= XT_PSD_OPT_LPWEIGHT; return true; /* PSD-hi-ports-weight */ case '4': if (*flags & XT_PSD_OPT_HPWEIGHT) xtables_error(PARAMETER_PROBLEM, "Can't specify --psd-hi-ports-weight twice"); if (!xtables_strtoui(optarg, NULL, &num, 0, PSD_MAX_RATE)) xtables_error(PARAMETER_PROBLEM, "bad --psd-hi-ports-weight '%s'", optarg); psdinfo->hi_ports_weight = num; *flags |= XT_PSD_OPT_HPWEIGHT; return true; } return false; }
static void owner_parse_range(const char *s, unsigned int *from, unsigned int *to, const char *opt) { char *end; /* -1 is reversed, so the max is one less than that. */ if (!xtables_strtoui(s, &end, from, 0, UINT32_MAX - 1)) xtables_param_act(XTF_BAD_VALUE, "owner", opt, s); *to = *from; if (*end == '-' || *end == ':') if (!xtables_strtoui(end + 1, &end, to, 0, UINT32_MAX - 1)) xtables_param_act(XTF_BAD_VALUE, "owner", opt, s); if (*end != '\0') xtables_param_act(XTF_BAD_VALUE, "owner", opt, s); }
static void parse_tproxy_mark(char *s, uint32_t *markp, uint32_t *maskp) { unsigned int value, mask = UINT32_MAX; char *end; if (!xtables_strtoui(s, &end, &value, 0, UINT32_MAX)) xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s); if (*end == '/') if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s); if (*end != '\0') xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s); *markp = value; *maskp = mask; }
uint16_t xtables_parse_protocol(const char *s) { const struct protoent *pent; unsigned int proto, i; if (xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX)) return proto; /* first deal with the special case of 'all' to prevent * people from being able to redefine 'all' in nsswitch * and/or provoke expensive [not working] ldap/nis/... * lookups */ if (strcmp(s, "all") == 0) return 0; pent = getprotobyname(s); if (pent != NULL) return pent->p_proto; for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) { if (xtables_chain_protos[i].name == NULL) continue; if (strcmp(s, xtables_chain_protos[i].name) == 0) return xtables_chain_protos[i].num; } xt_params->exit_err(PARAMETER_PROBLEM, "unknown protocol \"%s\" specified", s); return -1; }
static int limit_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { struct xt_rateinfo *r = (struct xt_rateinfo *)(*match)->data; unsigned int num; switch(c) { case '%': if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break; if (!parse_rate(optarg, &r->avg)) xtables_error(PARAMETER_PROBLEM, "bad rate `%s'", optarg); break; case '$': if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break; if (!xtables_strtoui(optarg, NULL, &num, 0, 10000)) xtables_error(PARAMETER_PROBLEM, "bad --limit-burst `%s'", optarg); r->burst = num; break; default: return 0; } if (invert) xtables_error(PARAMETER_PROBLEM, "limit does not support invert"); return 1; }
static void parse_tproxy_mark(char *s, struct xt_tproxy_target_info *info) { unsigned int value, mask = UINT32_MAX; char *end; if (!xtables_strtoui(s, &end, &value, 0, UINT32_MAX)) xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s); if (*end == '/') if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s); if (*end != '\0') xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s); info->mark_mask = mask; info->mark_value = value; }
static u_int32_t parse_led(const char *name) { unsigned int led = -1; unsigned int set = 0; if (!xtables_strtoui(name, NULL, &led, 0, 7)) { unsigned int i = 0; for (i = 0; ipt_led_names[i].name; i++) { if (strcasecmp(name, ipt_led_names[i].name) == 0) { set++; led = ipt_led_names[i].led; break; } if (strncasecmp(name, ipt_led_names[i].name, strlen(name)) == 0) { if (set++) xtables_error(PARAMETER_PROBLEM, "led `%s' ambiguous", name); led = ipt_led_names[i].led; } } if (!set) xtables_error(PARAMETER_PROBLEM, "led `%s' unknown", name); } return led; }
static unsigned int name_to_type(const char *name) { int namelen = strlen(name); static const unsigned int limit = ARRAY_SIZE(mh_names); unsigned int match = limit; unsigned int i; for (i = 0; i < limit; i++) { if (strncasecmp(mh_names[i].name, name, namelen) == 0) { int len = strlen(mh_names[i].name); if (match == limit || len == namelen) match = i; } } if (match != limit) { return mh_names[match].type; } else { unsigned int number; if (!xtables_strtoui(name, NULL, &number, 0, UINT8_MAX)) xtables_error(PARAMETER_PROBLEM, "Invalid MH type `%s'\n", name); return number; } }
static struct in6_addr *parse_ip6mask(char *mask) { static struct in6_addr maskaddr; struct in6_addr *addrp; unsigned int bits; if (mask == NULL) { /* no mask at all defaults to 128 bits */ memset(&maskaddr, 0xff, sizeof maskaddr); return &maskaddr; } if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL) return addrp; if (!xtables_strtoui(mask, NULL, &bits, 0, 128)) xt_params->exit_err(PARAMETER_PROBLEM, "invalid mask `%s' specified", mask); if (bits != 0) { char *p = (void *)&maskaddr; memset(p, 0xff, bits / 8); memset(p + (bits / 8) + 1, 0, (128 - bits) / 8); p[bits/8] = 0xff << (8 - (bits & 7)); return &maskaddr; } memset(&maskaddr, 0, sizeof(maskaddr)); return &maskaddr; }
static int MARK_parse_v1(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_target **target) { struct xt_mark_target_info_v1 *markinfo = (struct xt_mark_target_info_v1 *)(*target)->data; unsigned int mark = 0; switch (c) { case '1': markinfo->mode = XT_MARK_SET; break; case '2': markinfo->mode = XT_MARK_AND; break; case '3': markinfo->mode = XT_MARK_OR; break; default: return 0; } if (!xtables_strtoui(optarg, NULL, &mark, 0, UINT32_MAX)) xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg); markinfo->mark = mark; if (*flags) xtables_error(PARAMETER_PROBLEM, "MARK target: Can't specify --set-mark twice"); *flags = 1; return 1; }
static struct in_addr *parse_ipmask(const char *mask) { static struct in_addr maskaddr; struct in_addr *addrp; unsigned int bits; if (mask == NULL) { /* no mask at all defaults to 32 bits */ maskaddr.s_addr = 0xFFFFFFFF; return &maskaddr; } if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL) /* dotted_to_addr already returns a network byte order addr */ return addrp; if (!xtables_strtoui(mask, NULL, &bits, 0, 32)) xt_params->exit_err(PARAMETER_PROBLEM, "invalid mask `%s' specified", mask); if (bits != 0) { maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits)); return &maskaddr; } maskaddr.s_addr = 0U; return &maskaddr; }
static void owner_mt_parse_v0(struct xt_option_call *cb) { struct ipt_owner_info *info = cb->data; struct passwd *pwd; struct group *grp; unsigned int id; xtables_option_parse(cb); switch (cb->entry->id) { case O_USER: if ((pwd = getpwnam(cb->arg)) != NULL) id = pwd->pw_uid; else if (!xtables_strtoui(cb->arg, NULL, &id, 0, UINT32_MAX - 1)) xtables_param_act(XTF_BAD_VALUE, "owner", "--uid-owner", cb->arg); if (cb->invert) info->invert |= IPT_OWNER_UID; info->match |= IPT_OWNER_UID; info->uid = id; break; case O_GROUP: if ((grp = getgrnam(cb->arg)) != NULL) id = grp->gr_gid; else if (!xtables_strtoui(cb->arg, NULL, &id, 0, UINT32_MAX - 1)) xtables_param_act(XTF_BAD_VALUE, "owner", "--gid-owner", cb->arg); if (cb->invert) info->invert |= IPT_OWNER_GID; info->match |= IPT_OWNER_GID; info->gid = id; break; case O_PROCESS: if (cb->invert) info->invert |= IPT_OWNER_PID; info->match |= IPT_OWNER_PID; break; case O_SESSION: if (cb->invert) info->invert |= IPT_OWNER_SID; info->match |= IPT_OWNER_SID; break; case O_COMM: if (cb->invert) info->invert |= IPT_OWNER_COMM; info->match |= IPT_OWNER_COMM; break; } }
static struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask) { static struct in_addr addr; unsigned char *addrp; unsigned int onebyte; char buf[20], *p, *q; int i; /* copy dotted string, because we need to modify it */ strncpy(buf, dotted, sizeof(buf) - 1); buf[sizeof(buf) - 1] = '\0'; addrp = (void *)&addr.s_addr; p = buf; for (i = 0; i < 3; ++i) { if ((q = strchr(p, '.')) == NULL) { if (is_mask) return NULL; /* autocomplete, this is a network address */ if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) return NULL; addrp[i] = onebyte; while (i < 3) addrp[++i] = 0; return &addr; } *q = '\0'; if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) return NULL; addrp[i] = onebyte; p = q + 1; } /* we have checked 3 bytes, now we check the last one */ if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) return NULL; addrp[3] = onebyte; return &addr; }
static void parse_tproxy_lport(const char *s, struct xt_tproxy_target_info *info) { unsigned int lport; if (xtables_strtoui(s, NULL, &lport, 0, UINT16_MAX)) info->lport = htons(lport); else xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--on-port", s); }
static int TTL_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_target **target) { struct ipt_TTL_info *info = (struct ipt_TTL_info *) (*target)->data; unsigned int value; if (*flags & IPT_TTL_USED) { xtables_error(PARAMETER_PROBLEM, "Can't specify TTL option twice"); } if (!optarg) xtables_error(PARAMETER_PROBLEM, "TTL: You must specify a value"); if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) xtables_error(PARAMETER_PROBLEM, "TTL: unexpected `!'"); if (!xtables_strtoui(optarg, NULL, &value, 0, UINT8_MAX)) xtables_error(PARAMETER_PROBLEM, "TTL: Expected value between 0 and 255"); switch (c) { case '1': info->mode = IPT_TTL_SET; break; case '2': if (value == 0) { xtables_error(PARAMETER_PROBLEM, "TTL: decreasing by 0?"); } info->mode = IPT_TTL_DEC; break; case '3': if (value == 0) { xtables_error(PARAMETER_PROBLEM, "TTL: increasing by 0?"); } info->mode = IPT_TTL_INC; break; default: return 0; } info->ttl = value; *flags |= IPT_TTL_USED; return 1; }
static void parse_tproxy_lport(const char *s, uint16_t *portp) { unsigned int lport; if (xtables_strtoui(s, NULL, &lport, 0, UINT16_MAX)) *portp = htons(lport); else xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--on-port", s); }
static int NFQUEUE_parse_v1(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_target **target) { struct xt_NFQ_info_v1 *info = (void *)(*target)->data; char *colon; unsigned int firstqueue, lastqueue; switch (c) { case 'F': /* fallthrough */ case 'B': if (*flags) xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: " "Only use --queue-num ONCE!"); if (!xtables_strtoui(optarg, &colon, &firstqueue, 0, UINT16_MAX)) exit_badqueue(optarg); info->queuenum = firstqueue; if (c == 'F') { if (*colon) exit_badqueue(optarg); break; } if (*colon != ':') xtables_error(PARAMETER_PROBLEM, "Bad range \"%s\"", optarg); if (!xtables_strtoui(colon + 1, NULL, &lastqueue, 1, UINT16_MAX)) exit_badqueue(optarg); if (firstqueue >= lastqueue) xtables_error(PARAMETER_PROBLEM, "%u should be less than %u", firstqueue, lastqueue); info->queues_total = lastqueue - firstqueue + 1; break; default: return 0; } return 1; }
static u_int16_t parse_length(const char *s) { unsigned int len; if (!xtables_strtoui(s, NULL, &len, 0, UINT32_MAX)) xtables_error(PARAMETER_PROBLEM, "length invalid: \"%s\"\n", s); else return len; }
static void parse_num(const char *s, struct xt_NFQ_info *tinfo) { unsigned int num; if (!xtables_strtoui(s, NULL, &num, 0, UINT16_MAX)) exit_badqueue(s); tinfo->queuenum = num; }
static void parse_tcp_option(const char *option, u_int8_t *result) { unsigned int ret; if (!xtables_strtoui(option, NULL, &ret, 1, UINT8_MAX)) xtables_error(PARAMETER_PROBLEM, "Bad TCP option \"%s\"", option); *result = ret; }