Commit b655596d authored by Ondrej Zajicek's avatar Ondrej Zajicek
Browse files

Simplifies val_in_range().

Also fixes missing type check for element ~ set.
parent ec57bbf6
Loading
Loading
Loading
Loading
+36 −59
Original line number Diff line number Diff line
@@ -220,39 +220,6 @@ fprefix_get_bounds(struct f_prefix *px, int *l, int *h)
    }
}

/*
 * val_simple_in_range - check if @v1 ~ @v2 for everything except sets
 */ 
static int
val_simple_in_range(struct f_val v1, struct f_val v2)
{
  if ((v1.type == T_PATH) && (v2.type == T_PATH_MASK))
    return as_path_match(v1.val.ad, v2.val.path_mask);
  if ((v1.type == T_INT) && (v2.type == T_PATH))
    return as_path_is_member(v2.val.ad, v1.val.i);

  if (((v1.type == T_PAIR) || (v1.type == T_QUAD)) && (v2.type == T_CLIST))
    return int_set_contains(v2.val.ad, v1.val.i);
#ifndef IPV6
  /* IP->Quad implicit conversion */
  if ((v1.type == T_IP) && (v2.type == T_CLIST))
    return int_set_contains(v2.val.ad, ipa_to_u32(v1.val.px.ip));
#endif
  if ((v1.type == T_EC) && (v2.type == T_ECLIST))
    return ec_set_contains(v2.val.ad, v1.val.ec);

  if ((v1.type == T_STRING) && (v2.type == T_STRING))
    return patmatch(v2.val.s, v1.val.s);

  if ((v1.type == T_IP) && (v2.type == T_PREFIX))
    return ipa_in_net(v1.val.px.ip, v2.val.px.ip, v2.val.px.len);

  if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX))
    return net_in_net(v1.val.px.ip, v1.val.px.len, v2.val.px.ip, v2.val.px.len);

  return CMP_ERROR;
}

static int
clist_set_type(struct f_tree *set, struct f_val *v)
{
@@ -396,47 +363,57 @@ eclist_filter(struct linpool *pool, struct adata *list, struct f_val set, int po
 * @v1: element
 * @v2: set
 *
 * Checks if @v1 is element (|~| operator) of @v2. Sets are internally represented as balanced trees, see
 * |tree.c| module (this is not limited to sets, but for non-set cases, val_simple_in_range() is called early).
 * Checks if @v1 is element (|~| operator) of @v2.
 */
static int
val_in_range(struct f_val v1, struct f_val v2)
{
  int res;
  if ((v1.type == T_PATH) && (v2.type == T_PATH_MASK))
    return as_path_match(v1.val.ad, v2.val.path_mask);

  if ((v1.type == T_INT) && (v2.type == T_PATH))
    return as_path_is_member(v2.val.ad, v1.val.i);

  res = val_simple_in_range(v1, v2);
  if (((v1.type == T_PAIR) || (v1.type == T_QUAD)) && (v2.type == T_CLIST))
    return int_set_contains(v2.val.ad, v1.val.i);
#ifndef IPV6
  /* IP->Quad implicit conversion */
  if ((v1.type == T_IP) && (v2.type == T_CLIST))
    return int_set_contains(v2.val.ad, ipa_to_u32(v1.val.px.ip));
#endif

  if (res != CMP_ERROR)
    return res;
  if ((v1.type == T_EC) && (v2.type == T_ECLIST))
    return ec_set_contains(v2.val.ad, v1.val.ec);

  if ((v1.type == T_STRING) && (v2.type == T_STRING))
    return patmatch(v2.val.s, v1.val.s);

  if ((v1.type == T_IP) && (v2.type == T_PREFIX))
    return ipa_in_net(v1.val.px.ip, v2.val.px.ip, v2.val.px.len);

  if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX))
    return net_in_net(v1.val.px.ip, v1.val.px.len, v2.val.px.ip, v2.val.px.len);

  if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX_SET))
    return trie_match_fprefix(v2.val.ti, &v1.val.px);

  if ((v1.type == T_CLIST) && (v2.type == T_SET))
  if (v2.type != T_SET)
    return CMP_ERROR;

  /* With integrated Quad<->IP implicit conversion */
  if ((v1.type == v2.val.t->from.type) ||
      ((IP_VERSION == 4) && (v1.type == T_QUAD) && (v2.val.t->from.type == T_IP)))
    return !!find_tree(v2.val.t, v1);

  if (v1.type == T_CLIST)
    return clist_match_set(v1.val.ad, v2.val.t);

  if ((v1.type == T_ECLIST) && (v2.type == T_SET))
  if (v1.type == T_ECLIST)
    return eclist_match_set(v1.val.ad, v2.val.t);

  if ((v1.type == T_PATH) && (v2.type == T_SET))
  if (v1.type == T_PATH)
    return as_path_match_set(v1.val.ad, v2.val.t);

  if (v2.type == T_SET)
    switch (v1.type) {
    case T_ENUM:
    case T_INT:
    case T_PAIR:
    case T_QUAD:
    case T_IP:
    case T_EC:
      {
	struct f_tree *n;
	n = find_tree(v2.val.t, v1);
	if (!n)
	  return 0;
	return !! (val_simple_in_range(v1, n->from));	/* We turn CMP_ERROR into compared ok, and that's fine */
      }
    }
  return CMP_ERROR;
}

+6 −0
Original line number Diff line number Diff line
@@ -34,6 +34,12 @@
#define NULL ((void *) 0)
#endif

#ifndef IPV6
#define IP_VERSION 4
#else
#define IP_VERSION 6
#endif

/* Macros for gcc attributes */

#define NORET __attribute__((noreturn))