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

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
......@@ -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);
......
......@@ -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 {
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment