Commit e4df8a3e authored by Eugene Bogomazov's avatar Eugene Bogomazov Committed by Ondrej Zajicek (work)
Browse files

Add ASPA functionality to BIRD

ASPA [1] is a new IETF draft for BGP that adds new RPKI objects and
create an AS_PATH validation mechanism [2] based on this objects.

[1] https://datatracker.ietf.org/doc/draft-ietf-sidrops-aspa-profile/
[2] https://datatracker.ietf.org/doc/draft-ietf-sidrops-aspa-verification/

(Minor changes done by commiter)
parent 0edf0c8c
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -31,6 +31,8 @@ class BIRDFValPrinter(BIRDPrinter):
            "T_ENUM_NETTYPE": "i",
            "T_ENUM_NETTYPE": "i",
            "T_ENUM_RA_PREFERENCE": "i",
            "T_ENUM_RA_PREFERENCE": "i",
            "T_ENUM_AF": "i",
            "T_ENUM_AF": "i",
            "T_ENUM_ASPA": "i",
            "T_ENUM_BGP_DIR": "i",
            "T_IP": "ip",
            "T_IP": "ip",
            "T_NET": "net",
            "T_NET": "net",
            "T_STRING": "s",
            "T_STRING": "s",
+16 −2
Original line number Original line Diff line number Diff line
@@ -107,7 +107,7 @@ CF_DECLS
%type <time> expr_us time
%type <time> expr_us time
%type <a> ipa
%type <a> ipa
%type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
%type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
%type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ net_ip6_sadr_ net_mpls_
%type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ net_ip6_sadr_ net_mpls_ net_aspa4_ net_aspa6_ net_aspa_
%type <mls> label_stack_start label_stack
%type <mls> label_stack_start label_stack


%type <t> text opttext
%type <t> text opttext
@@ -123,7 +123,7 @@ CF_DECLS


%start config
%start config


CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN, MPLS, FROM)
CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN, MPLS, ASPA4, ASPA6, FROM)


CF_GRAMMAR
CF_GRAMMAR


@@ -283,9 +283,22 @@ net_mpls_: MPLS NUM
  net_fill_mpls($$, $2);
  net_fill_mpls($$, $2);
}
}


net_aspa4_: ASPA4 NUM NUM
{
  $$ = cfg_alloc(sizeof(net_addr_aspa));
  net_fill_aspa($$, $2, $3, AFI_IPV4);
};

net_aspa6_: ASPA6 NUM NUM
{
  $$ = cfg_alloc(sizeof(net_addr_aspa));
  net_fill_aspa($$, $2, $3, AFI_IPV6);
};

net_ip_: net_ip4_ | net_ip6_ ;
net_ip_: net_ip4_ | net_ip6_ ;
net_vpn_: net_vpn4_ | net_vpn6_ ;
net_vpn_: net_vpn4_ | net_vpn6_ ;
net_roa_: net_roa4_ | net_roa6_ ;
net_roa_: net_roa4_ | net_roa6_ ;
net_aspa_: net_aspa4_ | net_aspa6_ ;


net_:
net_:
   net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); }
   net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); }
@@ -294,6 +307,7 @@ net_:
 | net_flow_
 | net_flow_
 | net_ip6_sadr_
 | net_ip6_sadr_
 | net_mpls_
 | net_mpls_
 | net_aspa_
 ;
 ;




+4 −0
Original line number Original line Diff line number Diff line
@@ -434,6 +434,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
	FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX,
	FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX,
	PREFERENCE,
	PREFERENCE,
	ROA_CHECK, ASN, SRC,
	ROA_CHECK, ASN, SRC,
	ASPA_CHECK,
	IS_V4, IS_V6,
	IS_V4, IS_V6,
	LEN, MAXLEN,
	LEN, MAXLEN,
	DEFINED,
	DEFINED,
@@ -966,6 +967,9 @@ term:
 | ROA_CHECK '(' rtable ')' { $$ = f_new_inst(FI_ROA_CHECK_IMPLICIT, $3); }
 | ROA_CHECK '(' rtable ')' { $$ = f_new_inst(FI_ROA_CHECK_IMPLICIT, $3); }
 | ROA_CHECK '(' rtable ',' term ',' term ')' { $$ = f_new_inst(FI_ROA_CHECK_EXPLICIT, $5, $7, $3); }
 | ROA_CHECK '(' rtable ',' term ',' term ')' { $$ = f_new_inst(FI_ROA_CHECK_EXPLICIT, $5, $7, $3); }


 | ASPA_CHECK '(' rtable ',' term ')' { $$ = f_new_inst(FI_ASPA_CHECK_IMPLICIT, $5, $3); }
 | ASPA_CHECK '(' rtable ',' term ',' term ',' term ')' { $$ = f_new_inst(FI_ASPA_CHECK_EXPLICIT, $5, $7, $9, $3); }

 | FORMAT '(' term ')' {  $$ = f_new_inst(FI_FORMAT, $3); }
 | FORMAT '(' term ')' {  $$ = f_new_inst(FI_FORMAT, $3); }


/* | term '.' LEN { $$->code = P('P','l'); } */
/* | term '.' LEN { $$->code = P('P','l'); } */
+2 −0
Original line number Original line Diff line number Diff line
@@ -39,6 +39,8 @@ enum f_type {
  T_ENUM_NETTYPE = 0x36,
  T_ENUM_NETTYPE = 0x36,
  T_ENUM_RA_PREFERENCE = 0x37,
  T_ENUM_RA_PREFERENCE = 0x37,
  T_ENUM_AF = 0x38,
  T_ENUM_AF = 0x38,
  T_ENUM_ASPA = 0x39,
  T_ENUM_BGP_DIR = 0x3a,


/* new enums go here */
/* new enums go here */
  T_ENUM_EMPTY = 0x3f,	/* Special hack for atomic_aggr */
  T_ENUM_EMPTY = 0x3f,	/* Special hack for atomic_aggr */
+52 −0
Original line number Original line Diff line number Diff line
@@ -1170,6 +1170,58 @@


  }
  }


  INST(FI_ASPA_CHECK_IMPLICIT, 1, 1) {	/* ASPA Check */
    NEVER_CONSTANT;
    ARG(1, T_ENUM_BGP_DIR);
    RTC(2);
    struct rtable *table = rtc->table;
    ACCESS_RTE;
    ACCESS_EATTRS;
    const net_addr *net = (*fs->rte)->net->n.addr;

    if (!table)
      runtime("Missing ASPA table");

    if (table->addr_type != NET_ASPA)
      runtime("Table type must be ASPA");

    /* We ignore temporary attributes, probably not a problem here */
    /* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */
    eattr *e = ea_find(*fs->eattrs, EA_CODE(PROTOCOL_BGP, 0x02));

    if (!e || ((e->type & EAF_TYPE_MASK) != EAF_TYPE_AS_PATH))
      runtime("Missing AS_PATH attribute");

    uint dir = v1.val.i;

    if (!net_is_ip(net))
      runtime("Network type must be IPv4 or IPv6");

    uint afi = (net->type == NET_IP4) ? AFI_IPV4 : AFI_IPV6;

    RESULT(T_ENUM_ASPA, i, [[ net_aspa_check(fpool, table, e->u.ptr, dir, afi) ]]);
  }

  INST(FI_ASPA_CHECK_EXPLICIT, 3, 1) {	/* ASPA Check */
    NEVER_CONSTANT;
    ARG(1, T_PATH);
    ARG(2, T_ENUM_BGP_DIR);
    ARG(3, T_ENUM_AF);
    RTC(4);
    struct rtable *table = rtc->table;

    if (!table)
      runtime("Missing ASPA table");

    if (table->addr_type != NET_ASPA)
      runtime("Table type must be ASPA");

    if ((v3.val.i != AFI_IPV4) && (v3.val.i != AFI_IPV6))
      runtime("Address family must be AF_IPV4 or AF_IPV6");

    RESULT(T_ENUM_ASPA, i, [[ net_aspa_check(fpool, table, v1.val.ad, v2.val.i, v3.val.i) ]]);
  }

  INST(FI_FORMAT, 1, 0) {	/* Format */
  INST(FI_FORMAT, 1, 0) {	/* Format */
    ARG_ANY(1);
    ARG_ANY(1);
    RESULT(T_STRING, s, val_format_str(fpool, &v1));
    RESULT(T_STRING, s, val_format_str(fpool, &v1));
Loading