summaryrefslogtreecommitdiff
path: root/usr.sbin/ldpd/parse.y
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/ldpd/parse.y')
-rw-r--r--usr.sbin/ldpd/parse.y300
1 files changed, 227 insertions, 73 deletions
diff --git a/usr.sbin/ldpd/parse.y b/usr.sbin/ldpd/parse.y
index 193b1cb1f79..174bdd303fe 100644
--- a/usr.sbin/ldpd/parse.y
+++ b/usr.sbin/ldpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.49 2016/05/23 18:55:21 renato Exp $ */
+/* $OpenBSD: parse.y,v 1.50 2016/05/23 18:58:48 renato Exp $ */
/*
* Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org>
@@ -81,33 +81,41 @@ char *symget(const char *);
void clear_config(struct ldpd_conf *xconf);
uint32_t get_rtr_id(void);
-int host(const char *, struct in_addr *, struct in_addr *);
+int get_address(const char *, union ldpd_addr *);
+int get_af_address(const char *, int *, union ldpd_addr *);
static struct ldpd_conf *conf;
static int errors = 0;
+int af = AF_UNSPEC;
+struct ldpd_af_conf *af_conf = NULL;
struct iface *iface = NULL;
+struct iface_af *ia = NULL;
struct tnbr *tnbr = NULL;
struct nbr_params *nbrp = NULL;
struct l2vpn *l2vpn = NULL;
struct l2vpn_pw *pw = NULL;
struct config_defaults {
+ uint16_t keepalive;
uint16_t lhello_holdtime;
uint16_t lhello_interval;
uint16_t thello_holdtime;
uint16_t thello_interval;
+ union ldpd_addr trans_addr;
+ int afflags;
uint8_t pwflags;
};
struct config_defaults globaldefs;
+struct config_defaults afdefs;
struct config_defaults ifacedefs;
struct config_defaults tnbrdefs;
struct config_defaults pwdefs;
struct config_defaults *defs;
struct iface *conf_get_if(struct kif *);
-struct tnbr *conf_get_tnbr(struct in_addr);
+struct tnbr *conf_get_tnbr(union ldpd_addr *);
struct nbr_params *conf_get_nbrp(struct in_addr);
struct l2vpn *conf_get_l2vpn(char *);
struct l2vpn_if *conf_get_l2vpn_if(struct l2vpn *, struct kif *);
@@ -126,19 +134,19 @@ typedef struct {
%token INTERFACE TNEIGHBOR ROUTERID FIBUPDATE EXPNULL
%token LHELLOHOLDTIME LHELLOINTERVAL
%token THELLOHOLDTIME THELLOINTERVAL
-%token THELLOACCEPT
-%token KEEPALIVE TRANSADDRESS
+%token THELLOACCEPT AF IPV4 IPV6
+%token KEEPALIVE TRANSADDRESS TRANSPREFERENCE DSCISCOINTEROP
%token NEIGHBOR PASSWORD
%token L2VPN TYPE VPLS PWTYPE MTU BRIDGE
%token ETHERNET ETHERNETTAGGED STATUSTLV CONTROLWORD
-%token PSEUDOWIRE NEIGHBOR PWID
+%token PSEUDOWIRE NEIGHBORID NEIGHBORADDR PWID
%token EXTTAG
%token YES NO
%token INCLUDE
%token ERROR
%token <v.string> STRING
%token <v.number> NUMBER
-%type <v.number> yesno l2vpn_type pw_type
+%type <v.number> yesno ldp_af l2vpn_type pw_type
%type <v.string> string
%%
@@ -148,8 +156,7 @@ grammar : /* empty */
| grammar '\n'
| grammar conf_main '\n'
| grammar varset '\n'
- | grammar interface '\n'
- | grammar tneighbor '\n'
+ | grammar af '\n'
| grammar neighbor '\n'
| grammar l2vpn '\n'
| grammar error '\n' { file->errors++; }
@@ -187,6 +194,10 @@ yesno : YES { $$ = 1; }
| NO { $$ = 0; }
;
+ldp_af : IPV4 { $$ = AF_INET; }
+ | IPV6 { $$ = AF_INET6; }
+ ;
+
l2vpn_type : VPLS { $$ = L2VPN_TYPE_VPLS; }
;
@@ -211,7 +222,7 @@ conf_main : ROUTERID STRING {
YYERROR;
}
free($2);
- if (bad_ip_addr(conf->rtr_id)) {
+ if (bad_addr_v4(conf->rtr_id)) {
yyerror("invalid router-id");
YYERROR;
}
@@ -222,40 +233,114 @@ conf_main : ROUTERID STRING {
else
conf->flags &= ~F_LDPD_NO_FIB_UPDATE;
}
- | THELLOACCEPT yesno {
- if ($2 == 0)
- conf->flags &= ~F_LDPD_TH_ACCEPT;
- else
- conf->flags |= F_LDPD_TH_ACCEPT;
+ | TRANSPREFERENCE ldp_af {
+ conf->trans_pref = $2;
+
+ switch (conf->trans_pref) {
+ case AF_INET:
+ conf->trans_pref = DUAL_STACK_LDPOV4;
+ break;
+ case AF_INET6:
+ conf->trans_pref = DUAL_STACK_LDPOV6;
+ break;
+ default:
+ yyerror("invalid address-family");
+ YYERROR;
+ }
}
- | EXPNULL yesno {
- if ($2 == 0)
- conf->flags &= ~F_LDPD_EXPNULL;
+ | DSCISCOINTEROP yesno {
+ if ($2 == 1)
+ conf->flags |= F_LDPD_DS_CISCO_INTEROP;
else
- conf->flags |= F_LDPD_EXPNULL;
+ conf->flags &= ~F_LDPD_DS_CISCO_INTEROP;
}
- | KEEPALIVE NUMBER {
- if ($2 < MIN_KEEPALIVE || $2 > MAX_KEEPALIVE) {
- yyerror("keepalive out of range (%d-%d)",
- MIN_KEEPALIVE, MAX_KEEPALIVE);
+ | af_defaults
+ | iface_defaults
+ | tnbr_defaults
+ ;
+
+af : AF ldp_af {
+ af = $2;
+ switch (af) {
+ case AF_INET:
+ af_conf = &conf->ipv4;
+ break;
+ case AF_INET6:
+ af_conf = &conf->ipv6;
+ break;
+ default:
+ yyerror("invalid address-family");
YYERROR;
}
- conf->keepalive = $2;
+
+ afdefs = *defs;
+ defs = &afdefs;
+ } af_block {
+ af_conf->keepalive = defs->keepalive;
+ af_conf->thello_holdtime = defs->thello_holdtime;
+ af_conf->thello_interval = defs->thello_interval;
+ af_conf->flags = defs->afflags;
+ af_conf->flags |= F_LDPD_AF_ENABLED;
+ af_conf = NULL;
+ af = AF_UNSPEC;
+ defs = &globaldefs;
}
- | TRANSADDRESS STRING {
- if (!inet_aton($2, &conf->trans_addr)) {
+ ;
+
+af_block : '{' optnl afopts_l '}'
+ | '{' optnl '}'
+ |
+ ;
+
+afopts_l : afopts_l afoptsl nl
+ | afoptsl optnl
+ ;
+
+afoptsl : TRANSADDRESS STRING {
+ if (get_address($2, &af_conf->trans_addr) == -1) {
yyerror("error parsing transport-address");
free($2);
YYERROR;
}
free($2);
- if (bad_ip_addr(conf->trans_addr)) {
+ if (bad_addr(af, &af_conf->trans_addr)) {
yyerror("invalid transport-address");
YYERROR;
}
+ if (af == AF_INET6 &&
+ IN6_IS_SCOPE_EMBED(&af_conf->trans_addr.v6)) {
+ yyerror("ipv6 transport-address can not be "
+ "link-local");
+ YYERROR;
+ }
}
+ | af_defaults
| iface_defaults
| tnbr_defaults
+ | interface
+ | tneighbor
+ ;
+
+af_defaults : THELLOACCEPT yesno {
+ if ($2 == 0)
+ defs->afflags &= ~F_LDPD_AF_THELLO_ACCEPT;
+ else
+ defs->afflags |= F_LDPD_AF_THELLO_ACCEPT;
+ }
+ | EXPNULL yesno {
+ if ($2 == 0)
+ defs->afflags &= ~F_LDPD_AF_EXPNULL;
+ else
+ defs->afflags |= F_LDPD_AF_EXPNULL;
+ }
+ | KEEPALIVE NUMBER {
+ if ($2 < MIN_KEEPALIVE || $2 > MAX_KEEPALIVE) {
+ yyerror("keepalive out of range (%d-%d)",
+ MIN_KEEPALIVE, MAX_KEEPALIVE);
+ YYERROR;
+ }
+ defs->keepalive = $2;
+ }
;
iface_defaults : LHELLOHOLDTIME NUMBER {
@@ -344,22 +429,46 @@ pwopts : PWID NUMBER {
pw->pwid = $2;
}
- | NEIGHBOR STRING {
+ | NEIGHBORID STRING {
struct in_addr addr;
- if (inet_aton($2, &addr) == 0) {
- yyerror("error parsing neighbor address");
+ if (!inet_aton($2, &addr)) {
+ yyerror("error parsing neighbor-id");
free($2);
YYERROR;
}
free($2);
- if (bad_ip_addr(addr)) {
+ if (bad_addr_v4(addr)) {
yyerror("invalid neighbor-id");
YYERROR;
}
pw->lsr_id = addr;
}
+ | NEIGHBORADDR STRING {
+ int family;
+ union ldpd_addr addr;
+
+ if (get_af_address($2, &family, &addr) == -1) {
+ yyerror("error parsing neighbor address");
+ free($2);
+ YYERROR;
+ }
+ free($2);
+ if (bad_addr(family, &addr)) {
+ yyerror("invalid neighbor address");
+ YYERROR;
+ }
+ if (family == AF_INET6 &&
+ IN6_IS_SCOPE_EMBED(&addr.v6)) {
+ yyerror("neighbor address can not be "
+ "link-local");
+ YYERROR;
+ }
+
+ pw->af = family;
+ pw->addr = addr;
+ }
| pw_defaults
;
@@ -395,14 +504,16 @@ pseudowire : PSEUDOWIRE STRING {
YYERROR;
}
if (pw->lsr_id.s_addr == INADDR_ANY) {
- yyerror("missing pseudowire neighbor");
+ yyerror("missing pseudowire neighbor-id");
YYERROR;
}
LIST_FOREACH(l, &conf->l2vpn_list, entry) {
LIST_FOREACH(p, &l->pw_list, entry) {
if (pw != p &&
pw->pwid == p->pwid &&
- pw->lsr_id.s_addr == p->lsr_id.s_addr) {
+ pw->af == p->af &&
+ pw->lsr_id.s_addr ==
+ p->lsr_id.s_addr) {
yyerror("pseudowire already "
"configured");
YYERROR;
@@ -410,6 +521,15 @@ pseudowire : PSEUDOWIRE STRING {
}
}
+ /*
+ * If the neighbor address is not specified, use the
+ * neighbor id.
+ */
+ if (pw->af == AF_UNSPEC) {
+ pw->af = AF_INET;
+ pw->addr.v4 = pw->lsr_id;
+ }
+
pw->flags = defs->pwflags;
pw = NULL;
defs = &globaldefs;
@@ -521,13 +641,22 @@ interface : INTERFACE STRING {
if (iface == NULL)
YYERROR;
+ ia = iface_af_get(iface, af);
+ if (ia->enabled) {
+ yyerror("interface %s already configured for "
+ "address-family %s", kif->ifname,
+ af_name(af));
+ YYERROR;
+ }
+ ia->enabled = 1;
+
ifacedefs = *defs;
defs = &ifacedefs;
} interface_block {
- iface->hello_holdtime = defs->lhello_holdtime;
- iface->hello_interval = defs->lhello_interval;
+ ia->hello_holdtime = defs->lhello_holdtime;
+ ia->hello_interval = defs->lhello_interval;
iface = NULL;
- defs = &globaldefs;
+ defs = &afdefs;
}
;
@@ -541,21 +670,27 @@ interfaceopts_l : interfaceopts_l iface_defaults nl
;
tneighbor : TNEIGHBOR STRING {
- struct in_addr addr;
+ union ldpd_addr addr;
- if (inet_aton($2, &addr) == 0) {
+ if (get_address($2, &addr) == -1) {
yyerror("error parsing targeted-neighbor "
"address");
free($2);
YYERROR;
}
free($2);
- if (bad_ip_addr(addr)) {
+ if (bad_addr(af, &addr)) {
yyerror("invalid targeted-neighbor address");
YYERROR;
}
+ if (af == AF_INET6 &&
+ IN6_IS_SCOPE_EMBED(&addr.v6)) {
+ yyerror("targeted-neighbor address can not be "
+ "link-local");
+ YYERROR;
+ }
- tnbr = conf_get_tnbr(addr);
+ tnbr = conf_get_tnbr(&addr);
if (tnbr == NULL)
YYERROR;
@@ -565,7 +700,7 @@ tneighbor : TNEIGHBOR STRING {
tnbr->hello_holdtime = defs->thello_holdtime;
tnbr->hello_interval = defs->thello_interval;
tnbr = NULL;
- defs = &globaldefs;
+ defs = &afdefs;
}
;
@@ -582,13 +717,13 @@ neighbor : NEIGHBOR STRING {
struct in_addr addr;
if (inet_aton($2, &addr) == 0) {
- yyerror("error parsing neighbor address");
+ yyerror("error parsing neighbor-id");
free($2);
YYERROR;
}
free($2);
- if (bad_ip_addr(addr)) {
- yyerror("invalid neighbor address");
+ if (bad_addr_v4(addr)) {
+ yyerror("invalid neighbor-id");
YYERROR;
}
@@ -662,20 +797,26 @@ lookup(char *s)
{
/* this has to be sorted always */
static const struct keywords keywords[] = {
+ {"address-family", AF},
{"bridge", BRIDGE},
{"control-word", CONTROLWORD},
+ {"ds-cisco-interop", DSCISCOINTEROP},
{"ethernet", ETHERNET},
{"ethernet-tagged", ETHERNETTAGGED},
{"explicit-null", EXPNULL},
{"fib-update", FIBUPDATE},
{"include", INCLUDE},
{"interface", INTERFACE},
+ {"ipv4", IPV4},
+ {"ipv6", IPV6},
{"keepalive", KEEPALIVE},
{"l2vpn", L2VPN},
{"link-hello-holdtime", LHELLOHOLDTIME},
{"link-hello-interval", LHELLOINTERVAL},
{"mtu", MTU},
{"neighbor", NEIGHBOR},
+ {"neighbor-addr", NEIGHBORADDR},
+ {"neighbor-id", NEIGHBORID},
{"no", NO},
{"password", PASSWORD},
{"pseudowire", PSEUDOWIRE},
@@ -688,6 +829,7 @@ lookup(char *s)
{"targeted-hello-interval", THELLOINTERVAL},
{"targeted-neighbor", TNEIGHBOR},
{"transport-address", TRANSADDRESS},
+ {"transport-preference", TRANSPREFERENCE},
{"type", TYPE},
{"vpls", VPLS},
{"yes", YES}
@@ -1020,15 +1162,14 @@ parse_config(char *filename)
if ((conf = calloc(1, sizeof(struct ldpd_conf))) == NULL)
fatal(__func__);
- conf->keepalive = DEFAULT_KEEPALIVE;
+ conf->trans_pref = DUAL_STACK_LDPOV6;
defs = &globaldefs;
+ defs->keepalive = DEFAULT_KEEPALIVE;
defs->lhello_holdtime = LINK_DFLT_HOLDTIME;
defs->lhello_interval = DEFAULT_HELLO_INTERVAL;
defs->thello_holdtime = TARGETED_DFLT_HOLDTIME;
defs->thello_interval = DEFAULT_HELLO_INTERVAL;
- conf->thello_holdtime = TARGETED_DFLT_HOLDTIME;
- conf->thello_interval = DEFAULT_HELLO_INTERVAL;
defs->pwflags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF;
if ((file = pushfile(filename,
@@ -1069,8 +1210,11 @@ parse_config(char *filename)
if (conf->rtr_id.s_addr == INADDR_ANY)
conf->rtr_id.s_addr = get_rtr_id();
- if (conf->trans_addr.s_addr == 0)
- conf->trans_addr = conf->rtr_id;
+
+ /* if the ipv4 transport-address is not set, use the router-id */
+ if ((conf->ipv4.flags & F_LDPD_AF_ENABLED) &&
+ conf->ipv4.trans_addr.v4.s_addr == INADDR_ANY)
+ conf->ipv4.trans_addr.v4 = conf->rtr_id;
return (conf);
}
@@ -1154,13 +1298,9 @@ conf_get_if(struct kif *kif)
{
struct iface *i;
- LIST_FOREACH(i, &conf->iface_list, entry) {
- if (i->ifindex == kif->ifindex) {
- yyerror("interface %s already configured",
- kif->ifname);
- return (NULL);
- }
- }
+ LIST_FOREACH(i, &conf->iface_list, entry)
+ if (i->ifindex == kif->ifindex)
+ return (i);
if (kif->if_type == IFT_LOOP ||
kif->if_type == IFT_CARP ||
@@ -1176,18 +1316,18 @@ conf_get_if(struct kif *kif)
}
struct tnbr *
-conf_get_tnbr(struct in_addr addr)
+conf_get_tnbr(union ldpd_addr *addr)
{
struct tnbr *t;
- t = tnbr_find(conf, addr);
+ t = tnbr_find(conf, af, addr);
if (t) {
yyerror("targeted neighbor %s already configured",
- inet_ntoa(addr));
+ log_addr(af, addr));
return (NULL);
}
- t = tnbr_new(conf, addr);
+ t = tnbr_new(conf, af, addr);
t->flags |= F_TNBR_CONFIGURED;
LIST_INSERT_HEAD(&conf->tnbr_list, t, entry);
return (t);
@@ -1343,22 +1483,36 @@ get_rtr_id(void)
}
int
-host(const char *s, struct in_addr *addr, struct in_addr *mask)
+get_address(const char *s, union ldpd_addr *addr)
{
- struct in_addr ina;
- int bits = 32;
+ switch (af) {
+ case AF_INET:
+ if (inet_pton(AF_INET, s, &addr->v4) != 1)
+ return (-1);
+ break;
+ case AF_INET6:
+ if (inet_pton(AF_INET6, s, &addr->v6) != 1)
+ return (-1);
+ break;
+ default:
+ return (-1);
+ }
- memset(&ina, 0, sizeof(struct in_addr));
- if (strrchr(s, '/') != NULL) {
- if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1)
- return (0);
- } else {
- if (inet_pton(AF_INET, s, &ina) != 1)
- return (0);
+ return (0);
+}
+
+int
+get_af_address(const char *s, int *family, union ldpd_addr *addr)
+{
+ if (inet_pton(AF_INET, s, &addr->v4) == 1) {
+ *family = AF_INET;
+ return (0);
}
- *addr = ina;
- mask->s_addr = prefixlen2mask(bits);
+ if (inet_pton(AF_INET6, s, &addr->v6) == 1) {
+ *family = AF_INET6;
+ return (0);
+ }
- return (1);
+ return (-1);
}