Commit 598cebd1 authored by Maria Matejka's avatar Maria Matejka
Browse files

Filters: Also sender protocol and channel name available

Introducing the object member dereference framework.
parent 064b59d1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
src := filter.c data.c f-util.c tree.c trie.c inst-gen.c
src := filter.c data.c deref.c f-util.c tree.c trie.c inst-gen.c
obj := $(src-o-files)
$(all-daemon)
$(cf-local)
+20 −13
Original line number Diff line number Diff line
@@ -431,7 +431,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
	SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
	IF, THEN, ELSE, CASE,
	TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
	FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX,
	FROM, GW, NET, MASK, PROTO, AUTHOR, SENDER, SOURCE, SCOPE, DEST, IFNAME, IFINDEX,
	PREFERENCE,
	ROA_CHECK, ASN, SRC, DST,
	IS_V4, IS_V6,
@@ -902,6 +902,8 @@ static_attr:
 | GW      { $$ = f_new_static_attr(T_IP,         SA_GW,	0); }
 | NET     { $$ = f_new_static_attr(T_NET,	  SA_NET,	1); }
 | PROTO   { $$ = f_new_static_attr(T_STRING,     SA_PROTO,	1); }
 | SENDER  { $$ = f_new_static_attr(T_CHANNEL,	  SA_SENDER,	1); }
 | AUTHOR  { $$ = f_new_static_attr(T_PROTO,	  SA_AUTHOR,	1); }
 | SOURCE  { $$ = f_new_static_attr(T_ENUM_RTS,   SA_SOURCE,	1); }
 | SCOPE   { $$ = f_new_static_attr(T_ENUM_SCOPE, SA_SCOPE,	0); }
 | DEST    { $$ = f_new_static_attr(T_ENUM_RTD,   SA_DEST,	0); }
@@ -938,19 +940,24 @@ term:

 | dynamic_attr { $$ = f_new_inst(FI_EA_GET, $1); }

 | term '.' IS_V4 { $$ = f_new_inst(FI_IS_V4, $1); }
 | term '.' TYPE { $$ = f_new_inst(FI_TYPE, $1); }
 | term '.' IP { $$ = f_new_inst(FI_IP, $1); }
 | term '.' RD { $$ = f_new_inst(FI_ROUTE_DISTINGUISHER, $1); }
 | term '.' LEN { $$ = f_new_inst(FI_LENGTH, $1); }
 | term '.' MAXLEN { $$ = f_new_inst(FI_ROA_MAXLEN, $1); }
 | term '.' ASN { $$ = f_new_inst(FI_ROA_ASN, $1); }
 | term '.' SRC { $$ = f_new_inst(FI_NET_SRC, $1); }
 | term '.' DST { $$ = f_new_inst(FI_NET_DST, $1); }
 | term '.' MASK '(' term ')' { $$ = f_new_inst(FI_IP_MASK, $1, $5); }
 | term '.' FIRST { $$ = f_new_inst(FI_AS_PATH_FIRST, $1); }
 | term '.' LAST  { $$ = f_new_inst(FI_AS_PATH_LAST, $1); }
 | term '.' LAST_NONAGGREGATED  { $$ = f_new_inst(FI_AS_PATH_LAST_NAG, $1); }
 | term '.' token {
    switch ($3.value) {
      case IS_V4: $$ = f_new_inst(FI_IS_V4, $1); break;
      case TYPE: $$ = f_new_inst(FI_TYPE, $1); break;
      case IP: $$ = f_new_inst(FI_IP, $1); break;
      case RD: $$ = f_new_inst(FI_ROUTE_DISTINGUISHER, $1); break;
      case LEN: $$ = f_new_inst(FI_LENGTH, $1); break;
      case MAXLEN: $$ = f_new_inst(FI_ROA_MAXLEN, $1); break;
      case ASN: $$ = f_new_inst(FI_ROA_ASN, $1); break;
      case SRC: $$ = f_new_inst(FI_NET_SRC, $1); break;
      case DST: $$ = f_new_inst(FI_NET_DST, $1); break;
      case FIRST: $$ = f_new_inst(FI_AS_PATH_FIRST, $1); break;
      case LAST: $$ = f_new_inst(FI_AS_PATH_LAST, $1); break;
      case LAST_NONAGGREGATED: $$ = f_new_inst(FI_AS_PATH_LAST_NAG, $1); break;
      default: $$ = f_new_inst(FI_DEREF, $1, f_get_deref($1->type, &$3)); break;
    }
 }

/* Communities */
/* This causes one shift/reduce conflict
+17 −0
Original line number Diff line number Diff line
@@ -61,6 +61,9 @@ enum f_type {

  T_SET = 0x80,
  T_PREFIX_SET = 0x81,

  T_PROTO = 0xa0,	/* Protocol instance */
  T_CHANNEL = 0xa1,	/* Channel */
} PACKED;

/* Filter value; size of this affects filter memory consumption */
@@ -78,6 +81,8 @@ struct f_val {
    const struct adata *ad;
    const struct f_path_mask *path_mask;
    struct f_path_mask_item pmi;
    struct proto *proto;
    struct channel *channel;
  } val;
};

@@ -94,6 +99,8 @@ enum f_sa_code {
  SA_GW,
  SA_NET,
  SA_PROTO,
  SA_SENDER,
  SA_AUTHOR,
  SA_SOURCE,
  SA_SCOPE,
  SA_DEST,
@@ -126,6 +133,16 @@ struct f_lval {
  };
};

/* Member dereference (in filter/deref.c) */
struct f_deref {
  struct f_val (*deref)(struct f_val *);
  const char *name;
  enum f_type source_type, result_type;
};

struct keyword;
const struct f_deref *f_get_deref(enum f_type, const struct keyword *);

/* IP prefix range structure */
struct f_prefix {
  net_addr net;		/* The matching prefix must match this net */
+1 −1
Original line number Diff line number Diff line
@@ -90,7 +90,7 @@ FID_DUMP_BODY()m4_dnl
debug("%s" $4 "\n", INDENT, $5);
]])
FID_INTERPRET_EXEC()m4_dnl
const $1 $2 = whati->$2
$1 const $2 = whati->$2
FID_INTERPRET_BODY')

#	Instruction arguments are needed only until linearization is done.

filter/deref.c

0 → 100644
+68 −0
Original line number Diff line number Diff line
/*
 *	Filters: dereferencing metaobjects
 *
 *	(c) 2020 Maria Matejka <mq@jmq.cz>
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 *
 */

#define PARSER 1

#include "nest/bird.h"
#include "nest/route.h"
#include "nest/protocol.h"
#include "filter/filter.h"
#include "filter/f-inst.h"
#include "filter/data.h"
#include "conf/conf.h"
#include "conf/cf-parse.tab.h"

static struct f_val deref_proto__name__deref(struct f_val *val)
{ return (struct f_val) { .type = T_STRING, .val.s = val->val.proto->name }; }

static const struct f_deref deref_proto__name = {
  .deref = deref_proto__name__deref,
  .name = "name",
  .source_type = T_PROTO,
  .result_type = T_STRING,
};

static struct f_val deref_channel__name__deref(struct f_val *val)
{ return (struct f_val) { .type = T_STRING, .val.s = val->val.channel->name }; }

static const struct f_deref deref_channel__name = {
  .deref = deref_channel__name__deref,
  .name = "name",
  .source_type = T_CHANNEL,
  .result_type = T_STRING,
};

static struct f_val deref_channel__proto__deref(struct f_val *val)
{ return (struct f_val) { .type = T_PROTO, .val.proto = val->val.channel->proto }; }

static const struct f_deref deref_channel__proto = {
  .deref = deref_channel__proto__deref,
  .name = "proto",
  .source_type = T_CHANNEL,
  .result_type = T_PROTO,
};

const struct f_deref *f_get_deref(enum f_type type, const struct keyword *kw)
{
  if (!type)
    cf_error("Can't dereference an object with unsure type");

#define CX(t, v)  ((u64) (t) | ((v) << (8 * sizeof (enum f_type))))
  switch (CX(type, kw->value))
  {
    case CX(T_PROTO, NAME):
      return &deref_proto__name;
    case CX(T_CHANNEL, NAME):
      return &deref_channel__name;
    case CX(T_CHANNEL, PROTO):
      return &deref_channel__proto;
  }

  cf_error("Can't call (%s).%s: Undefined operation", f_type_name(type), kw->name);
}
Loading