Commit d311368b authored by Jan Moskyto Matejka's avatar Jan Moskyto Matejka
Browse files

VPN4 and VPN6 literals

From now on, protocol static accepts VPN4 and VPN6 addressess.
With some concerns about VPN6 Route Distinguishers, I finally chose
to have the same format as for VPN4 (where it is defined by RFC 4364).
parent d47c3d64
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -123,6 +123,43 @@ include ^{WHITE}*include{WHITE}*\".*\"{WHITE}*;
  cf_include(start, end-start);
}

[02]:{DIGIT}+:{DIGIT}+ {
  char *e;
  unsigned long int l;

  if (yytext[0] == '0')
    cf_lval.i64 = 0;
  else
    cf_lval.i64 = 0x2000000000000ULL;

  errno = 0;
  l = strtoul(yytext+2, &e, 10);
  if (e && (*e != ':') || errno == ERANGE || (yytext[0] == '0') && (l >= (1<<16)))
    cf_error("ASN out of range");
  cf_lval.i64 |= (((u64) l) << 32);
  errno = 0;
  l = strtoul(e+1, &e, 10);
  if (e && *e || errno == ERANGE || (yytext[0] == '2') && (l >= (1<<16)))
    cf_error("Assigned number out of range");
  cf_lval.i64 |= l;
  return VPN_RD;
}

1:{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+:{DIGIT}+ {
  unsigned long int l;
  char *e = strchr(yytext+2, ':');
  *e++ = '\0';
  ip4_addr ip4;
  if (!ip4_pton(yytext+2, &ip4))
    cf_error("Invalid IPv4 address %s in Route Distinguisher", yytext+2);
  errno = 0;
  l = strtoul(e, &e, 10);
  if (e && *e || errno == ERANGE || (l >= (1<<16)))
    cf_error("Assigned number out of range");
  cf_lval.i64 = (1ULL<<48) | (((u64)ip4_to_u32(ip4)) << 16) | ((u64)l);
  return VPN_RD;
}

{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ {
  if (!ip4_pton(yytext, &cf_lval.ip4))
    cf_error("Invalid IPv4 address %s", yytext);
+20 −2
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ CF_DECLS
%union {
  int i;
  u32 i32;
  u64 i64;
  ip_addr a;
  ip4_addr ip4;
  ip6_addr ip6;
@@ -73,6 +74,7 @@ CF_DECLS
%token <i> NUM ENUM
%token <ip4> IP4
%token <ip6> IP6
%token <i64> VPN_RD
%token <s> SYM
%token <t> TEXT
%type <iface> ipa_scope
@@ -82,7 +84,7 @@ CF_DECLS
%type <time> datetime
%type <a> ipa
%type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
%type <net_ptr> net_ net_any net_roa4_ net_roa6_ net_roa_
%type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_
%type <lbl> label_stack_start label_stack

%type <t> text opttext
@@ -95,7 +97,7 @@ CF_DECLS
%left '!'
%nonassoc '.'

CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT)
CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN)

CF_GRAMMAR

@@ -198,6 +200,18 @@ net_ip6_: IP6 '/' NUM
    cf_error("Invalid IPv6 prefix");
};

net_vpn4_: VPN_RD net_ip4_
{
  $$ = cfg_alloc(sizeof(net_addr_vpn4));
  net_fill_vpn4($$, ((net_addr_ip4 *)&$2)->prefix, $2.pxlen, $1);
}

net_vpn6_: VPN_RD net_ip6_
{
  $$ = cfg_alloc(sizeof(net_addr_vpn6));
  net_fill_vpn6($$, ((net_addr_ip6 *)&$2)->prefix, $2.pxlen, $1);
}

net_roa4_: net_ip4_ MAX NUM AS NUM
{
  $$ = cfg_alloc(sizeof(net_addr_roa4));
@@ -216,9 +230,11 @@ net_roa6_: net_ip6_ MAX NUM AS NUM

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

net_:
   net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); }
 | net_vpn_
 | net_roa_
 | net_flow_
 ;
@@ -256,6 +272,8 @@ net_any:
net_or_ipa:
   net_ip4_
 | net_ip6_
 | net_vpn4_ { $$ = *$1; }
 | net_vpn6_ { $$ = *$1; }
 | IP4 { net_fill_ip4(&($$), $1, IP4_MAX_PREFIX_LENGTH); }
 | IP6 { net_fill_ip6(&($$), $1, IP6_MAX_PREFIX_LENGTH); }
 | SYM {
+18 −3
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ int
net_format(const net_addr *N, char *buf, int buflen)
{
  net_addr_union *n = (void *) N;
  buf[0] = 0;

  switch (n->n.type)
  {
@@ -66,9 +67,23 @@ net_format(const net_addr *N, char *buf, int buflen)
  case NET_IP6:
    return bsnprintf(buf, buflen, "%I6/%d", n->ip6.prefix, n->ip6.pxlen);
  case NET_VPN4:
    return bsnprintf(buf, buflen, "%u:%u %I4/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen);
    switch (n->vpn4.rd >> 48)
    {
      case 0: return bsnprintf(buf, buflen, "0:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen);
      case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I4/%d", ip4_from_u32(n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen);
      case 2: return bsnprintf(buf, buflen, "2:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen);
    }
    return bsnprintf(buf, buflen, "X: %016x %I4/%d", (n->vpn4.rd), n->vpn4.prefix, n->vpn4.pxlen);

    /* XXX: RD format is specified for VPN4; not found any for VPN6, reusing the same as for VPN4. */
  case NET_VPN6:
    return bsnprintf(buf, buflen, "%u:%u %I6/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen);
    switch (n->vpn6.rd >> 48)
    {
      case 0: return bsnprintf(buf, buflen, "0:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen);
      case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I6/%d", ip4_from_u32(n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen);
      case 2: return bsnprintf(buf, buflen, "2:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen);
    }
    return bsnprintf(buf, buflen, "X: %016x %I6/%d", (n->vpn6.rd), n->vpn6.prefix, n->vpn6.pxlen);
  case NET_ROA4:
    return bsnprintf(buf, buflen, "%I4/%u-%u AS%u",  n->roa4.prefix, n->roa4.pxlen, n->roa4.max_pxlen, n->roa4.asn);
  case NET_ROA6:
@@ -81,7 +96,7 @@ net_format(const net_addr *N, char *buf, int buflen)
    return bsnprintf(buf, buflen, "%u", n->mpls.label);
  }

  return 0;
  bug("unknown network type");
}

ip_addr