+struct frag_handling {
+ const char *name;
+ uint8_t mask;
+ uint8_t value;
+};
+
+static const struct frag_handling all_frags[] = {
+#define A FLOW_FRAG_ANY
+#define L FLOW_FRAG_LATER
+ /* name mask value */
+
+ { "no", A|L, 0 },
+ { "first", A|L, A },
+ { "later", A|L, A|L },
+
+ { "no", A, 0 },
+ { "yes", A, A },
+
+ { "not_later", L, 0 },
+ { "later", L, L },
+#undef A
+#undef L
+};
+
+static char *
+mf_from_frag_string(const char *s, uint8_t *valuep, uint8_t *maskp)
+{
+ const struct frag_handling *h;
+
+ for (h = all_frags; h < &all_frags[ARRAY_SIZE(all_frags)]; h++) {
+ if (!strcasecmp(s, h->name)) {
+ /* We force the upper bits of the mask on to make mf_parse_value()
+ * happy (otherwise it will never think it's an exact match.) */
+ *maskp = h->mask | ~FLOW_FRAG_MASK;
+ *valuep = h->value;
+ return NULL;
+ }
+ }
+
+ return xasprintf("%s: unknown fragment type (valid types are \"no\", "
+ "\"yes\", \"first\", \"later\", \"not_first\"", s);
+}
+