+bool
+fw3_parse_mark(void *ptr, const char *val, bool is_list)
+{
+ uint32_t n;
+ char *s, *e;
+ struct fw3_mark *m = ptr;
+
+ if (*val == '!')
+ {
+ m->invert = true;
+ while (isspace(*++val));
+ }
+
+ if ((s = strchr(val, '/')) != NULL)
+ *s++ = 0;
+
+ n = strtoul(val, &e, 0);
+
+ if (e == val || *e)
+ return false;
+
+ m->mark = n;
+ m->mask = 0xFFFFFFFF;
+
+ if (s)
+ {
+ n = strtoul(s, &e, 0);
+
+ if (e == s || *e)
+ return false;
+
+ m->mask = n;
+ }
+
+ m->set = true;
+ return true;
+}
+
+bool
+fw3_parse_dscp(void *ptr, const char *val, bool is_list)
+{
+ uint32_t n;
+ char *e;
+ struct fw3_dscp *d = ptr;
+
+ if (*val == '!')
+ {
+ d->invert = true;
+ while (isspace(*++val));
+ }
+
+ for (n = 0; n < sizeof(dscp_classes) / sizeof(dscp_classes[0]); n++)
+ {
+ if (strcmp(dscp_classes[n].name, val))
+ continue;
+
+ d->set = true;
+ d->dscp = dscp_classes[n].dscp;
+ return true;
+ }
+
+ n = strtoul(val, &e, 0);
+
+ if (e == val || *e || n > 0x3F)
+ return false;
+
+ d->set = true;
+ d->dscp = n;
+ return true;
+}
+
+bool
+fw3_parse_setmatch(void *ptr, const char *val, bool is_list)
+{
+ struct fw3_setmatch *m = ptr;
+ char *p, *s;
+ int i;
+
+ if (*val == '!')
+ {
+ m->invert = true;
+ while (isspace(*++val));
+ }
+
+ if (!(s = strdup(val)))
+ return false;
+
+ if (!(p = strtok(s, " \t")))
+ {
+ free(s);
+ return false;
+ }
+
+ snprintf(m->name, sizeof(m->name), "%s", p);
+
+ for (i = 0, p = strtok(NULL, " \t,");
+ i < 3 && p != NULL;
+ i++, p = strtok(NULL, " \t,"))
+ {
+ if (!strncmp(p, "dest", 4) || !strncmp(p, "dst", 3))
+ m->dir[i] = "dst";
+ else if (!strncmp(p, "src", 3))
+ m->dir[i] = "src";
+ }
+
+ free(s);
+
+ m->set = true;
+ return true;
+}
+
+bool
+fw3_parse_direction(void *ptr, const char *val, bool is_list)
+{
+ bool *is_out = ptr;
+ bool valid = true;
+
+ if (!strcmp(val, "in") || !strcmp(val, "ingress"))
+ *is_out = false;
+ else if (!strcmp(val, "out") || !strcmp(val, "egress"))
+ *is_out = true;
+ else
+ valid = false;
+
+ return valid;
+}
+
+bool
+fw3_parse_cthelper(void *ptr, const char *val, bool is_list)
+{
+ struct fw3_cthelpermatch m = { };
+
+ if (*val == '!')
+ {
+ m.invert = true;
+ while (isspace(*++val));
+ }
+
+ if (*val)
+ {
+ m.set = true;
+ snprintf(m.name, sizeof(m.name), "%s", val);
+ put_value(ptr, &m, sizeof(m), is_list);
+ return true;
+ }
+
+ return false;
+}
+
+bool
+fw3_parse_setentry(void *ptr, const char *val, bool is_list)
+{
+ struct fw3_setentry e = { };
+
+ e.value = val;
+ put_value(ptr, &e, sizeof(e), is_list);
+
+ return true;
+}
+