summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorremi <remi@cvs.openbsd.org>2018-02-05 12:11:29 +0000
committerremi <remi@cvs.openbsd.org>2018-02-05 12:11:29 +0000
commitd42b3d1b4aef8e6c5d75a18bb6c4ee79476ad019 (patch)
tree0ef89e91143034e35f52f5d27215d7b3b58c9ec0
parent95c71a012cf89c5f801281d5f82e4e8fdc3db0ec (diff)
Introduce "depend on". This allows ospfd to set the metric dependent
on the status of another interface. in collaboration with benno@ jca@ OK benno@ jca@
-rw-r--r--usr.sbin/ospfd/ospfd.c45
-rw-r--r--usr.sbin/ospfd/ospfd.conf.524
-rw-r--r--usr.sbin/ospfd/ospfd.h7
-rw-r--r--usr.sbin/ospfd/ospfe.c36
-rw-r--r--usr.sbin/ospfd/parse.y82
-rw-r--r--usr.sbin/ospfd/printconf.c11
-rw-r--r--usr.sbin/ospfd/rde.c8
7 files changed, 176 insertions, 37 deletions
diff --git a/usr.sbin/ospfd/ospfd.c b/usr.sbin/ospfd/ospfd.c
index 6e907d4b328..381b35fc600 100644
--- a/usr.sbin/ospfd/ospfd.c
+++ b/usr.sbin/ospfd/ospfd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ospfd.c,v 1.94 2017/01/24 04:24:25 benno Exp $ */
+/* $OpenBSD: ospfd.c,v 1.95 2018/02/05 12:11:28 remi Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -29,6 +29,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <net/if_types.h>
#include <event.h>
#include <err.h>
@@ -512,18 +513,30 @@ imsg_compose_event(struct imsgev *iev, u_int16_t type, u_int32_t peerid,
int
ospf_redistribute(struct kroute *kr, u_int32_t *metric)
{
+ struct in_addr addr;
+ struct kif *kif;
struct redistribute *r;
- u_int8_t is_default = 0;
+ int is_default = 0, depend_ok = 1;
+
+ bzero(&addr, sizeof(addr));
/* only allow 0.0.0.0/0 via REDIST_DEFAULT */
if (kr->prefix.s_addr == INADDR_ANY && kr->prefixlen == 0)
is_default = 1;
SIMPLEQ_FOREACH(r, &ospfd_conf->redist_list, entry) {
+ if (r->dependon[0] != '\0') {
+ if ((kif = kif_findname(r->dependon, addr, NULL)))
+ depend_ok = ifstate_is_up(kif);
+ else
+ depend_ok = 0;
+ } else
+ depend_ok = 1;
+
switch (r->type & ~REDIST_NO) {
case REDIST_LABEL:
if (kr->rtlabel == r->label) {
- *metric = r->metric;
+ *metric = depend_ok ? r->metric : MAX_METRIC;
return (r->type & REDIST_NO ? 0 : 1);
}
break;
@@ -538,7 +551,7 @@ ospf_redistribute(struct kroute *kr, u_int32_t *metric)
if (kr->flags & F_DYNAMIC)
continue;
if (kr->flags & F_STATIC) {
- *metric = r->metric;
+ *metric = depend_ok ? r->metric : MAX_METRIC;
return (r->type & REDIST_NO ? 0 : 1);
}
break;
@@ -548,7 +561,7 @@ ospf_redistribute(struct kroute *kr, u_int32_t *metric)
if (kr->flags & F_DYNAMIC)
continue;
if (kr->flags & F_CONNECTED) {
- *metric = r->metric;
+ *metric = depend_ok ? r->metric : MAX_METRIC;
return (r->type & REDIST_NO ? 0 : 1);
}
break;
@@ -559,7 +572,8 @@ ospf_redistribute(struct kroute *kr, u_int32_t *metric)
if (r->addr.s_addr == INADDR_ANY &&
r->mask.s_addr == INADDR_ANY) {
if (is_default) {
- *metric = r->metric;
+ *metric = depend_ok ? r->metric :
+ MAX_METRIC;
return (r->type & REDIST_NO ? 0 : 1);
} else
return (0);
@@ -568,13 +582,13 @@ ospf_redistribute(struct kroute *kr, u_int32_t *metric)
if ((kr->prefix.s_addr & r->mask.s_addr) ==
(r->addr.s_addr & r->mask.s_addr) &&
kr->prefixlen >= mask2prefixlen(r->mask.s_addr)) {
- *metric = r->metric;
+ *metric = depend_ok ? r->metric : MAX_METRIC;
return (r->type & REDIST_NO ? 0 : 1);
}
break;
case REDIST_DEFAULT:
if (is_default) {
- *metric = r->metric;
+ *metric = depend_ok ? r->metric : MAX_METRIC;
return (r->type & REDIST_NO ? 0 : 1);
}
break;
@@ -841,6 +855,10 @@ merge_interfaces(struct area *a, struct area *xa)
if (ospfd_process == PROC_OSPF_ENGINE)
if_fsm(i, IF_EVT_UP);
}
+
+ strlcpy(i->dependon, xi->dependon,
+ sizeof(i->dependon));
+ i->depend_ok = xi->depend_ok;
}
return (dirty);
}
@@ -857,3 +875,14 @@ iface_lookup(struct area *area, struct iface *iface)
return (i);
return (NULL);
}
+
+int
+ifstate_is_up(struct kif *kif)
+{
+ if (!(kif->flags & IFF_UP))
+ return (0);
+ if (kif->if_type == IFT_CARP &&
+ kif->link_state == LINK_STATE_UNKNOWN)
+ return (0);
+ return LINK_STATE_IS_UP(kif->link_state);
+}
diff --git a/usr.sbin/ospfd/ospfd.conf.5 b/usr.sbin/ospfd/ospfd.conf.5
index 0564ccdbbf9..ec5f1984a69 100644
--- a/usr.sbin/ospfd/ospfd.conf.5
+++ b/usr.sbin/ospfd/ospfd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ospfd.conf.5,v 1.49 2017/11/07 06:32:02 remi Exp $
+.\" $OpenBSD: ospfd.conf.5,v 1.50 2018/02/05 12:11:28 remi Exp $
.\"
.\" Copyright (c) 2005 Esben Norby <norby@openbsd.org>
.\" Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -17,7 +17,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: November 7 2017 $
+.Dd $Mdocdate: February 5 2018 $
.Dt OSPFD.CONF 5
.Os
.Sh NAME
@@ -115,14 +115,19 @@ Table 0 is the default table.
.Ic default Pc
.Sm on
.Op Ic set ...
+.Op Ic depend on Ar interface
.Xc
.It Xo
.Op Ic no
-.Ic redistribute Ar prefix Op Ic set ...
+.Ic redistribute Ar prefix
+.Op Ic set ...
+.Op Ic depend on Ar interface
.Xc
.It Xo
.Op Ic no
-.Ic redistribute rtlabel Ar label Op Ic set ...
+.Ic redistribute rtlabel Ar label
+.Op Ic set ...
+.Op Ic depend on Ar interface
.Xc
If set to
.Ic connected ,
@@ -154,6 +159,14 @@ which will be set no matter what, and additionally
.Ic no
cannot be used together with it.
.Pp
+With the
+.Ic depend on
+option, redistributed routes will have a metric of 65535 if the specified
+.Ar interface
+is down or in state backup.
+This is especially useful on a carp cluster to ensure all traffic goes to
+the carp master.
+.Pp
It is possible to set the route
.Ic metric
and
@@ -344,6 +357,9 @@ demotion counter by 1 on the given interface group, usually
when the interface state is going down.
The demotion counter will be decreased when the interface
state is active again.
+.It Ic depend Ic on Ar interface
+A metric of 65535 is used if the specified interface is down or in status
+backup.
.It Ic fast-hello-interval Ic msec Ar milliseconds
If the interface is configured to use
.Ic router-dead-time minimal ,
diff --git a/usr.sbin/ospfd/ospfd.h b/usr.sbin/ospfd/ospfd.h
index bbf3ce01197..ba3ffbc56cb 100644
--- a/usr.sbin/ospfd/ospfd.h
+++ b/usr.sbin/ospfd/ospfd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ospfd.h,v 1.97 2017/01/24 04:24:25 benno Exp $ */
+/* $OpenBSD: ospfd.h,v 1.98 2018/02/05 12:11:28 remi Exp $ */
/*
* Copyright (c) 2004 Esben Norby <norby@openbsd.org>
@@ -149,6 +149,7 @@ struct redistribute {
u_int32_t metric;
u_int16_t label;
u_int16_t type;
+ char dependon[IFNAMSIZ];
};
SIMPLEQ_HEAD(redist_list, redistribute);
@@ -325,6 +326,7 @@ struct iface {
char name[IF_NAMESIZE];
char demote_group[IFNAMSIZ];
+ char dependon[IFNAMSIZ];
char auth_key[MAX_SIMPLE_AUTH_LEN];
struct in_addr addr;
struct in_addr dst;
@@ -346,6 +348,7 @@ struct iface {
int fd;
int state;
int mtu;
+ int depend_ok;
u_int16_t flags;
u_int16_t transmit_delay;
u_int16_t hello_interval;
@@ -553,6 +556,7 @@ int carp_demote_set(char *, int);
/* parse.y */
struct ospfd_conf *parse_config(char *, int);
int cmdline_symset(char *);
+void conf_clear_redist_list(struct redist_list *);
/* in_cksum.c */
u_int16_t in_cksum(void *, size_t);
@@ -603,6 +607,7 @@ void merge_config(struct ospfd_conf *, struct ospfd_conf *);
void imsg_event_add(struct imsgev *);
int imsg_compose_event(struct imsgev *, u_int16_t, u_int32_t,
pid_t, int, void *, u_int16_t);
+int ifstate_is_up(struct kif *kif);
/* printconf.c */
void print_config(struct ospfd_conf *);
diff --git a/usr.sbin/ospfd/ospfe.c b/usr.sbin/ospfd/ospfe.c
index 86f7e796c40..693e3a6d5a9 100644
--- a/usr.sbin/ospfd/ospfe.c
+++ b/usr.sbin/ospfd/ospfe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ospfe.c,v 1.99 2017/01/24 04:24:25 benno Exp $ */
+/* $OpenBSD: ospfe.c,v 1.100 2018/02/05 12:11:28 remi Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -181,10 +181,7 @@ ospfe(struct ospfd_conf *xconf, int pipe_parent2ospfe[2], int pipe_ospfe2rde[2],
event_add(&oeconf->ev, NULL);
/* remove unneeded config stuff */
- while ((r = SIMPLEQ_FIRST(&oeconf->redist_list)) != NULL) {
- SIMPLEQ_REMOVE_HEAD(&oeconf->redist_list, entry);
- free(r);
- }
+ conf_clear_redist_list(&oeconf->redist_list);
LIST_FOREACH(area, &oeconf->area_list, entry) {
while ((r = SIMPLEQ_FIRST(&area->redist_list)) != NULL) {
SIMPLEQ_REMOVE_HEAD(&area->redist_list, entry);
@@ -346,6 +343,21 @@ ospfe_dispatch_main(int fd, short event, void *bula)
iface->name);
}
}
+ if (strcmp(kif->ifname,
+ iface->dependon) == 0) {
+ log_warnx("interface %s"
+ " changed state, %s"
+ " depends on it",
+ kif->ifname,
+ iface->name);
+ iface->depend_ok =
+ ifstate_is_up(kif);
+
+ if ((iface->flags &
+ IFF_UP) &&
+ LINK_STATE_IS_UP(iface->linkstate))
+ orig_rtr_lsa(iface->area);
+ }
}
}
break;
@@ -847,6 +859,9 @@ orig_rtr_lsa(struct area *area)
if (oeconf->flags & OSPFD_FLAG_STUB_ROUTER ||
oe_nofib)
rtr_link.metric = MAX_METRIC;
+ else if (iface->dependon[0] != '\0' &&
+ iface->depend_ok == 0)
+ rtr_link.metric = MAX_METRIC;
else
rtr_link.metric = htons(iface->metric);
num_links++;
@@ -916,12 +931,16 @@ orig_rtr_lsa(struct area *area)
rtr_link.num_tos = 0;
/*
- * backup carp interfaces are anounced with high metric
- * for faster failover.
+ * backup carp interfaces and interfaces that depend
+ * on an interface that is down are announced with
+ * high metric for faster failover.
*/
if (iface->if_type == IFT_CARP &&
iface->linkstate == LINK_STATE_DOWN)
rtr_link.metric = MAX_METRIC;
+ else if (iface->dependon[0] != '\0' &&
+ iface->depend_ok == 0)
+ rtr_link.metric = MAX_METRIC;
else
rtr_link.metric = htons(iface->metric);
num_links++;
@@ -978,6 +997,9 @@ orig_rtr_lsa(struct area *area)
if (oe_nofib || oeconf->flags &
OSPFD_FLAG_STUB_ROUTER)
rtr_link.metric = MAX_METRIC;
+ else if (iface->dependon[0] != '\0' &&
+ iface->depend_ok == 0)
+ rtr_link.metric = MAX_METRIC;
else
rtr_link.metric =
htons(iface->metric);
diff --git a/usr.sbin/ospfd/parse.y b/usr.sbin/ospfd/parse.y
index 78d5e969f50..03d9ca912ab 100644
--- a/usr.sbin/ospfd/parse.y
+++ b/usr.sbin/ospfd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.83 2017/01/05 13:53:09 krw Exp $ */
+/* $OpenBSD: parse.y,v 1.84 2018/02/05 12:11:28 remi Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -132,11 +132,12 @@ typedef struct {
%token DEMOTE
%token INCLUDE
%token ERROR
+%token DEPEND ON
%token <v.string> STRING
%token <v.number> NUMBER
%type <v.number> yesno no optlist optlist_l option demotecount msec
%type <v.number> deadtime
-%type <v.string> string
+%type <v.string> string dependon
%type <v.redist> redistribute
%%
@@ -278,7 +279,7 @@ conf_main : ROUTERID STRING {
;
-redistribute : no REDISTRIBUTE NUMBER '/' NUMBER optlist {
+redistribute : no REDISTRIBUTE NUMBER '/' NUMBER optlist dependon {
struct redistribute *r;
if ((r = calloc(1, sizeof(*r))) == NULL)
@@ -295,9 +296,14 @@ redistribute : no REDISTRIBUTE NUMBER '/' NUMBER optlist {
if ($1)
r->type |= REDIST_NO;
r->metric = $6;
+ if ($7) {
+ strlcpy(r->dependon, $7, sizeof(r->dependon));
+ } else
+ r->dependon[0] = '\0';
+ free($7);
$$ = r;
}
- | no REDISTRIBUTE STRING optlist {
+ | no REDISTRIBUTE STRING optlist dependon {
struct redistribute *r;
if ((r = calloc(1, sizeof(*r))) == NULL)
@@ -320,10 +326,15 @@ redistribute : no REDISTRIBUTE NUMBER '/' NUMBER optlist {
if ($1)
r->type |= REDIST_NO;
r->metric = $4;
+ if ($5) {
+ strlcpy(r->dependon, $5, sizeof(r->dependon));
+ } else
+ r->dependon[0] = '\0';
free($3);
+ free($5);
$$ = r;
}
- | no REDISTRIBUTE RTLABEL STRING optlist {
+ | no REDISTRIBUTE RTLABEL STRING optlist dependon {
struct redistribute *r;
if ((r = calloc(1, sizeof(*r))) == NULL)
@@ -333,19 +344,23 @@ redistribute : no REDISTRIBUTE NUMBER '/' NUMBER optlist {
if ($1)
r->type |= REDIST_NO;
r->metric = $5;
+ if ($6)
+ strlcpy(r->dependon, $6, sizeof(r->dependon));
+ else
+ r->dependon[0] = '\0';
free($4);
-
+ free($6);
$$ = r;
}
;
optlist : /* empty */ { $$ = DEFAULT_REDIST_METRIC; }
- | SET option {
+ | SET option {
$$ = $2;
if (($$ & LSA_METRIC_MASK) == 0)
$$ |= DEFAULT_REDIST_METRIC;
}
- | SET optnl '{' optnl optlist_l optnl '}' {
+ | SET optnl '{' optnl optlist_l optnl '}' {
$$ = $5;
if (($$ & LSA_METRIC_MASK) == 0)
$$ |= DEFAULT_REDIST_METRIC;
@@ -388,6 +403,26 @@ option : METRIC NUMBER {
}
;
+dependon : /* empty */ { $$ = NULL; }
+ | DEPEND ON STRING {
+ struct in_addr addr;
+ struct kif *kif;
+
+ if (strlen($3) >= IFNAMSIZ) {
+ yyerror("interface name %s too long", $3);
+ free($3);
+ YYERROR;
+ }
+ bzero(&addr, sizeof(addr));
+ if ((kif = kif_findname($3, addr, NULL)) == NULL) {
+ yyerror("unknown interface %s", $3);
+ free($3);
+ YYERROR;
+ }
+ $$ = $3;
+ }
+ ;
+
authmd : AUTHMD NUMBER STRING {
if ($2 < MIN_MD_ID || $2 > MAX_MD_ID) {
yyerror("auth-md key-id out of range "
@@ -693,6 +728,23 @@ interfaceoptsl : PASSIVE { iface->passive = 1; }
YYERROR;
}
}
+ | dependon {
+ struct in_addr addr;
+ struct kif *kif;
+
+ if ($1) {
+ strlcpy(iface->dependon, $1,
+ sizeof(iface->dependon));
+ bzero(&addr, sizeof(addr));
+ kif = kif_findname($1, addr, NULL);
+ iface->depend_ok = ifstate_is_up(kif);
+ } else {
+ iface->dependon[0] = '\0';
+ iface->depend_ok = 1;
+ }
+
+ free($1);
+ }
| defaults
;
@@ -736,6 +788,7 @@ lookup(char *s)
{"auth-md-keyid", AUTHMDKEYID},
{"auth-type", AUTHTYPE},
{"demote", DEMOTE},
+ {"depend", DEPEND},
{"external-tag", EXTTAG},
{"fast-hello-interval", FASTHELLOINTERVAL},
{"fib-update", FIBUPDATE},
@@ -746,6 +799,7 @@ lookup(char *s)
{"minimal", MINIMAL},
{"msec", MSEC},
{"no", NO},
+ {"on", ON},
{"passive", PASSIVE},
{"rdomain", RDOMAIN},
{"redistribute", REDISTRIBUTE},
@@ -1288,6 +1342,16 @@ conf_check_rdomain(unsigned int rdomain)
}
void
+conf_clear_redist_list(struct redist_list *rl)
+{
+ struct redistribute *r;
+ while ((r = SIMPLEQ_FIRST(rl)) != NULL) {
+ SIMPLEQ_REMOVE_HEAD(rl, entry);
+ free(r);
+ }
+}
+
+void
clear_config(struct ospfd_conf *xconf)
{
struct area *a;
@@ -1297,6 +1361,8 @@ clear_config(struct ospfd_conf *xconf)
area_del(a);
}
+ conf_clear_redist_list(&xconf->redist_list);
+
free(xconf);
}
diff --git a/usr.sbin/ospfd/printconf.c b/usr.sbin/ospfd/printconf.c
index fa5536c1f99..5fd501b07f8 100644
--- a/usr.sbin/ospfd/printconf.c
+++ b/usr.sbin/ospfd/printconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.17 2016/11/19 12:46:46 sthen Exp $ */
+/* $OpenBSD: printconf.c,v 1.18 2018/02/05 12:11:28 remi Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -94,9 +94,12 @@ print_redistribute(struct redist_list *rlh)
printf("%sredistribute default ", print_no(r->type));
break;
}
- printf("set { metric %d type %d }\n",
+ printf("set { metric %d type %d }",
(r->metric & LSA_METRIC_MASK),
((r->metric & LSA_ASEXT_E_FLAG) == 0 ? 1 : 2));
+ if (r->dependon[0])
+ printf(" depend on %s", r->dependon);
+ printf("\n");
}
}
@@ -120,8 +123,10 @@ print_iface(struct iface *iface)
printf("\t\tmetric %d\n", iface->metric);
- if (*iface->demote_group)
+ if (iface->demote_group[0] != '\0')
printf("\t\tdemote %s\n", iface->demote_group);
+ if (iface->dependon[0] != '\0')
+ printf("\t\tdepend on %s\n", iface->dependon);
if (iface->passive)
printf("\t\tpassive\n");
else {
diff --git a/usr.sbin/ospfd/rde.c b/usr.sbin/ospfd/rde.c
index 941a25d67f2..6ff3edc9183 100644
--- a/usr.sbin/ospfd/rde.c
+++ b/usr.sbin/ospfd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.108 2017/01/24 04:24:25 benno Exp $ */
+/* $OpenBSD: rde.c,v 1.109 2018/02/05 12:11:28 remi Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -98,7 +98,6 @@ rde(struct ospfd_conf *xconf, int pipe_parent2rde[2], int pipe_ospfe2rde[2],
struct area *area;
struct iface *iface;
struct passwd *pw;
- struct redistribute *r;
pid_t pid;
switch (pid = fork()) {
@@ -188,10 +187,7 @@ rde(struct ospfd_conf *xconf, int pipe_parent2rde[2], int pipe_ospfe2rde[2],
LIST_FOREACH(iface, &area->iface_list, entry)
md_list_clr(&iface->auth_md_list);
- while ((r = SIMPLEQ_FIRST(&rdeconf->redist_list)) != NULL) {
- SIMPLEQ_REMOVE_HEAD(&rdeconf->redist_list, entry);
- free(r);
- }
+ conf_clear_redist_list(&rdeconf->redist_list);
gettimeofday(&now, NULL);
rdeconf->uptime = now.tv_sec;