]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
VPN4 and VPN6 literals
authorJan Moskyto Matejka <mq@ucw.cz>
Tue, 9 Feb 2016 13:53:29 +0000 (14:53 +0100)
committerJan Moskyto Matejka <mq@ucw.cz>
Thu, 22 Dec 2016 20:38:33 +0000 (21:38 +0100)
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).

conf/cf-lex.l
conf/confbase.Y
lib/net.c

index bd6dfff206de593dfe84097b2b031c89ee7c5ccd..8e1f60a60cebf873678175fc698e8a6b3b376fd9 100644 (file)
@@ -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);
index 00e782327bcec48fa6c08247fec7d1544d556f13..a5b8b692b0a48f3177f53d7f2a7cd7d7ea141b8d 100644 (file)
@@ -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 {
index 5a7e6fecad28102d76e91061e919dc3b5821bbe5..e46be8b2c054ce3a64b190d98d19f8d07222f07a 100644 (file)
--- a/lib/net.c
+++ b/lib/net.c
@@ -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