summaryrefslogtreecommitdiff
path: root/usr.sbin/ospf6d
diff options
context:
space:
mode:
authorremi <remi@cvs.openbsd.org>2018-07-12 12:19:06 +0000
committerremi <remi@cvs.openbsd.org>2018-07-12 12:19:06 +0000
commit04465519fe8d7c9cb8403aac6a5463372cf75b1f (patch)
tree7c36d39b746dadf291c04a9c35f83aa4b7ccdb5c /usr.sbin/ospf6d
parent08186ef8d9cc113c0d4b4d2bb691992f694cd26d (diff)
With the "depend on" option routes are sent out with a metric of 65535 if
the referenced interface is down or in state backup. This is especially useful on a carp cluster to ensure all traffic goes to the carp master. ok friehm@ jca@
Diffstat (limited to 'usr.sbin/ospf6d')
-rw-r--r--usr.sbin/ospf6d/kroute.c12
-rw-r--r--usr.sbin/ospf6d/ospf6d.c37
-rw-r--r--usr.sbin/ospf6d/ospf6d.conf.519
-rw-r--r--usr.sbin/ospf6d/ospf6d.h6
-rw-r--r--usr.sbin/ospf6d/ospfe.c40
-rw-r--r--usr.sbin/ospf6d/parse.y50
-rw-r--r--usr.sbin/ospf6d/printconf.c9
-rw-r--r--usr.sbin/ospf6d/rde.c29
8 files changed, 168 insertions, 34 deletions
diff --git a/usr.sbin/ospf6d/kroute.c b/usr.sbin/ospf6d/kroute.c
index 5e485ff83f6..7d798cd038a 100644
--- a/usr.sbin/ospf6d/kroute.c
+++ b/usr.sbin/ospf6d/kroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kroute.c,v 1.56 2018/07/10 12:17:38 friehm Exp $ */
+/* $OpenBSD: kroute.c,v 1.57 2018/07/12 12:19:05 remi Exp $ */
/*
* Copyright (c) 2004 Esben Norby <norby@openbsd.org>
@@ -810,13 +810,9 @@ if_change(u_short ifindex, int flags, struct if_data *ifd)
return;
}
- /* inform engine and rde about state change if interface is used */
- if (iface->cflags & F_IFACE_CONFIGURED) {
- main_imsg_compose_ospfe(IMSG_IFINFO, 0, iface,
- sizeof(struct iface));
- main_imsg_compose_rde(IMSG_IFINFO, 0, iface,
- sizeof(struct iface));
- }
+ /* inform engine and rde about state change */
+ main_imsg_compose_rde(IMSG_IFINFO, 0, iface, sizeof(struct iface));
+ main_imsg_compose_ospfe(IMSG_IFINFO, 0, iface, sizeof(struct iface));
isvalid = (iface->flags & IFF_UP) &&
LINK_STATE_IS_UP(iface->linkstate);
diff --git a/usr.sbin/ospf6d/ospf6d.c b/usr.sbin/ospf6d/ospf6d.c
index 0e40111b526..dcea8c7a86b 100644
--- a/usr.sbin/ospf6d/ospf6d.c
+++ b/usr.sbin/ospf6d/ospf6d.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ospf6d.c,v 1.36 2018/07/09 13:19:46 remi Exp $ */
+/* $OpenBSD: ospf6d.c,v 1.37 2018/07/12 12:19:05 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>
@@ -485,17 +486,27 @@ ospf_redistribute(struct kroute *kr, u_int32_t *metric)
{
struct redistribute *r;
struct in6_addr ina, inb;
+ struct iface *iface;
u_int8_t is_default = 0;
+ int depend_ok;
/* only allow ::/0 via REDIST_DEFAULT */
if (IN6_IS_ADDR_UNSPECIFIED(&kr->prefix) && kr->prefixlen == 0)
is_default = 1;
SIMPLEQ_FOREACH(r, &ospfd_conf->redist_list, entry) {
+ if (r->dependon[0] != '\0') {
+ if ((iface = if_findname(r->dependon)))
+ depend_ok = ifstate_is_up(iface);
+ 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;
@@ -510,7 +521,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;
@@ -520,7 +531,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;
@@ -531,7 +542,8 @@ ospf_redistribute(struct kroute *kr, u_int32_t *metric)
if (IN6_IS_ADDR_UNSPECIFIED(&r->addr) &&
r->prefixlen == 0) {
if (is_default) {
- *metric = r->metric;
+ *metric = depend_ok ? r->metric :
+ MAX_METRIC;
return (r->type & REDIST_NO ? 0 : 1);
} else
return (0);
@@ -541,13 +553,13 @@ ospf_redistribute(struct kroute *kr, u_int32_t *metric)
inet6applymask(&inb, &r->addr, r->prefixlen);
if (IN6_ARE_ADDR_EQUAL(&ina, &inb) &&
kr->prefixlen >= r->prefixlen) {
- *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;
@@ -774,3 +786,14 @@ iface_lookup(struct area *area, struct iface *iface)
return (i);
return (NULL);
}
+
+int
+ifstate_is_up(struct iface *iface)
+{
+ if (!(iface->flags & IFF_UP))
+ return (0);
+ if (iface->if_type == IFT_CARP &&
+ iface->linkstate == LINK_STATE_UNKNOWN)
+ return (0);
+ return LINK_STATE_IS_UP(iface->linkstate);
+}
diff --git a/usr.sbin/ospf6d/ospf6d.conf.5 b/usr.sbin/ospf6d/ospf6d.conf.5
index ddcb1be1851..ac0c51a6535 100644
--- a/usr.sbin/ospf6d/ospf6d.conf.5
+++ b/usr.sbin/ospf6d/ospf6d.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ospf6d.conf.5,v 1.14 2018/06/18 06:04:25 jmc Exp $
+.\" $OpenBSD: ospf6d.conf.5,v 1.15 2018/07/12 12:19:05 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: June 18 2018 $
+.Dd $Mdocdate: July 12 2018 $
.Dt OSPF6D.CONF 5
.Os
.Sh NAME
@@ -109,14 +109,18 @@ option to ensure that no traffic tries to transit via this router.
.Ic default Pc
.Sm on
.Op Ic set ...\&
+.Bk -words
+.Op Ic depend on Ar interface
.Xc
.It Xo
.Op Ic no
.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 ...\&
+.Op Ic depend on Ar interface
.Xc
If set to
.Ic connected ,
@@ -148,6 +152,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
@@ -267,6 +279,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 on Ar interface
+A metric of 65535 is used if the specified interface is down or in status
+backup.
.It Ic hello-interval Ar seconds
Set the hello interval.
The default value is 10; valid range is 1\-65535 seconds.
diff --git a/usr.sbin/ospf6d/ospf6d.h b/usr.sbin/ospf6d/ospf6d.h
index 0b6d8835a99..38314e2992c 100644
--- a/usr.sbin/ospf6d/ospf6d.h
+++ b/usr.sbin/ospf6d/ospf6d.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ospf6d.h,v 1.35 2018/02/08 00:18:20 claudio Exp $ */
+/* $OpenBSD: ospf6d.h,v 1.36 2018/07/12 12:19:05 remi Exp $ */
/*
* Copyright (c) 2004, 2007 Esben Norby <norby@openbsd.org>
@@ -299,6 +299,7 @@ struct iface {
char name[IF_NAMESIZE];
char demote_group[IFNAMSIZ];
+ char dependon[IFNAMSIZ];
struct in6_addr addr;
struct in6_addr dst;
struct in_addr abr_id;
@@ -314,6 +315,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;
@@ -358,6 +360,7 @@ struct redistribute {
u_int16_t label;
u_int16_t type;
u_int8_t prefixlen;
+ char dependon[IFNAMSIZ];
};
struct ospfd_conf {
@@ -578,6 +581,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 iface *iface);
/* printconf.c */
void print_config(struct ospfd_conf *);
diff --git a/usr.sbin/ospf6d/ospfe.c b/usr.sbin/ospf6d/ospfe.c
index 98e42409a07..7ce0392aec5 100644
--- a/usr.sbin/ospf6d/ospfe.c
+++ b/usr.sbin/ospf6d/ospfe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ospfe.c,v 1.52 2018/07/10 21:21:56 friehm Exp $ */
+/* $OpenBSD: ospfe.c,v 1.53 2018/07/12 12:19:05 remi Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -263,7 +263,7 @@ ospfe_dispatch_main(int fd, short event, void *bula)
{
static struct area *narea;
struct area *area;
- struct iface *iface, *ifp;
+ struct iface *iface, *ifp, *i;
struct ifaddrchange *ifc;
struct iface_addr *ia, *nia;
struct imsg imsg;
@@ -298,6 +298,24 @@ ospfe_dispatch_main(int fd, short event, void *bula)
fatalx("IFINFO imsg with wrong len");
ifp = imsg.data;
+ LIST_FOREACH(area, &oeconf->area_list, entry) {
+ LIST_FOREACH(i, &area->iface_list, entry) {
+ if (strcmp(i->dependon,
+ ifp->name) == 0) {
+ log_warnx("interface %s"
+ " changed state, %s"
+ " depends on it",
+ ifp->name, i->name);
+ i->depend_ok =
+ ifstate_is_up(ifp);
+ if (ifstate_is_up(i))
+ orig_rtr_lsa(i);
+ }
+ }
+ }
+
+ if (!(ifp->cflags & F_IFACE_CONFIGURED))
+ break;
iface = if_find(ifp->ifindex);
if (iface == NULL)
fatalx("interface lost in ospfe");
@@ -837,7 +855,11 @@ orig_rtr_lsa_area(struct area *area)
log_debug("orig_rtr_lsa: point-to-point, "
"interface %s", iface->name);
rtr_link.type = LINK_TYPE_POINTTOPOINT;
- rtr_link.metric = htons(iface->metric);
+ if (iface->dependon[0] != '\0' &&
+ iface->depend_ok == 0)
+ rtr_link.metric = MAX_METRIC;
+ else
+ rtr_link.metric = htons(iface->metric);
rtr_link.iface_id = htonl(iface->ifindex);
rtr_link.nbr_iface_id = htonl(nbr->iface_id);
rtr_link.nbr_rtr_id = nbr->id.s_addr;
@@ -862,7 +884,12 @@ orig_rtr_lsa_area(struct area *area)
"interface %s", iface->name);
rtr_link.type = LINK_TYPE_TRANSIT_NET;
- rtr_link.metric = htons(iface->metric);
+ if (iface->dependon[0] != '\0' &&
+ iface->depend_ok == 0)
+ rtr_link.metric = MAX_METRIC;
+ else
+ rtr_link.metric =
+ htons(iface->metric);
rtr_link.iface_id = htonl(iface->ifindex);
rtr_link.nbr_iface_id = htonl(iface->dr->iface_id);
rtr_link.nbr_rtr_id = iface->dr->id.s_addr;
@@ -922,7 +949,10 @@ orig_rtr_lsa_area(struct area *area)
/* RFC 3137: stub router support */
if (oe_nofib || oeconf->flags &
OSPFD_FLAG_STUB_ROUTER)
- rtr_link.metric = 0xffff;
+ rtr_link.metric = MAX_METRIC;
+ else if (iface->dependon[0] != '\0' &&
+ iface->dependon_ok == 0)
+ rtr_link.metric = MAX_METRIC;
else
rtr_link.metric =
htons(iface->metric);
diff --git a/usr.sbin/ospf6d/parse.y b/usr.sbin/ospf6d/parse.y
index ca95db4bc60..75ffb782d7b 100644
--- a/usr.sbin/ospf6d/parse.y
+++ b/usr.sbin/ospf6d/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.36 2018/07/11 10:23:47 remi Exp $ */
+/* $OpenBSD: parse.y,v 1.37 2018/07/12 12:19:05 remi Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -131,10 +131,11 @@ 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
-%type <v.string> string
+%type <v.string> string dependon
%type <v.redist> redistribute
%%
@@ -259,7 +260,7 @@ conf_main : ROUTERID STRING {
| defaults
;
-redistribute : no REDISTRIBUTE STRING optlist {
+redistribute : no REDISTRIBUTE STRING optlist dependon {
struct redistribute *r;
if ((r = calloc(1, sizeof(*r))) == NULL)
@@ -282,10 +283,15 @@ redistribute : no REDISTRIBUTE STRING 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)
@@ -295,7 +301,12 @@ redistribute : no REDISTRIBUTE STRING 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;
}
;
@@ -349,6 +360,22 @@ option : METRIC NUMBER {
}
;
+dependon : /* empty */ { $$ = NULL; }
+ | DEPEND ON STRING {
+ if (strlen($3) >= IFNAMSIZ) {
+ yyerror("interface name %s too long", $3);
+ free($3);
+ YYERROR;
+ }
+ if ((if_findname($3)) == NULL) {
+ yyerror("unknown interface %s", $3);
+ free($3);
+ YYERROR;
+ }
+ $$ = $3;
+ }
+ ;
+
defaults : METRIC NUMBER {
if ($2 < MIN_METRIC || $2 > MAX_METRIC) {
yyerror("metric out of range (%d-%d)",
@@ -524,6 +551,19 @@ interfaceoptsl : PASSIVE { iface->cflags |= F_IFACE_PASSIVE; }
YYERROR;
}
}
+ | dependon {
+ struct iface *depend_if = NULL;
+
+ if ($1) {
+ strlcpy(iface->dependon, $1,
+ sizeof(iface->dependon));
+ depend_if = if_findname($1);
+ iface->depend_ok = ifstate_is_up(depend_if);
+ } else {
+ iface->dependon[0] = '\0';
+ iface->depend_ok = 1;
+ }
+ }
| defaults
;
@@ -563,6 +603,7 @@ lookup(char *s)
static const struct keywords keywords[] = {
{"area", AREA},
{"demote", DEMOTE},
+ {"depend", DEPEND},
{"external-tag", EXTTAG},
{"fib-update", FIBUPDATE},
{"hello-interval", HELLOINTERVAL},
@@ -570,6 +611,7 @@ lookup(char *s)
{"interface", INTERFACE},
{"metric", METRIC},
{"no", NO},
+ {"on", ON},
{"passive", PASSIVE},
{"redistribute", REDISTRIBUTE},
{"retransmit-interval", RETRANSMITINTERVAL},
diff --git a/usr.sbin/ospf6d/printconf.c b/usr.sbin/ospf6d/printconf.c
index 17a0ac11dbc..a8e77ac962d 100644
--- a/usr.sbin/ospf6d/printconf.c
+++ b/usr.sbin/ospf6d/printconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.5 2016/12/24 14:58:55 jca Exp $ */
+/* $OpenBSD: printconf.c,v 1.6 2018/07/12 12:19:05 remi Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -90,9 +90,12 @@ print_redistribute(struct ospfd_conf *conf)
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");
}
}
@@ -119,6 +122,8 @@ print_iface(struct iface *iface)
printf("\t\tpassive\n");
if (*iface->demote_group)
printf("\t\tdemote %s\n", iface->demote_group);
+ if (iface->dependon[0] != '\0')
+ printf("\t\tdepend on %s\n", iface->dependon);
printf("\t\tretransmit-interval %d\n", iface->rxmt_interval);
printf("\t\trouter-dead-time %d\n", iface->dead_interval);
diff --git a/usr.sbin/ospf6d/rde.c b/usr.sbin/ospf6d/rde.c
index 7e630e6ed4e..eaeccace4f0 100644
--- a/usr.sbin/ospf6d/rde.c
+++ b/usr.sbin/ospf6d/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.77 2018/07/10 21:21:56 friehm Exp $ */
+/* $OpenBSD: rde.c,v 1.78 2018/07/12 12:19:05 remi Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -633,7 +633,7 @@ rde_dispatch_parent(int fd, short event, void *bula)
{
static struct area *narea;
struct area *area;
- struct iface *iface, *ifp;
+ struct iface *iface, *ifp, *i;
struct ifaddrchange *ifc;
struct iface_addr *ia, *nia;
struct imsg imsg;
@@ -643,7 +643,7 @@ rde_dispatch_parent(int fd, short event, void *bula)
struct lsa *lsa;
struct vertex *v;
ssize_t n;
- int shut = 0, link_ok, prev_link_ok;
+ int shut = 0, link_ok, prev_link_ok, orig_lsa;
unsigned int ifindex;
if (event & EV_READ) {
@@ -709,6 +709,24 @@ rde_dispatch_parent(int fd, short event, void *bula)
fatalx("IFINFO imsg with wrong len");
ifp = imsg.data;
+
+ LIST_FOREACH(area, &rdeconf->area_list, entry) {
+ orig_lsa = 0;
+ LIST_FOREACH(i, &area->iface_list, entry) {
+ if (strcmp(i->dependon,
+ ifp->name) == 0) {
+ i->depend_ok =
+ ifstate_is_up(ifp);
+ if (ifstate_is_up(i))
+ orig_lsa = 1;
+ }
+ }
+ if (orig_lsa)
+ orig_intra_area_prefix_lsas(area);
+ }
+
+ if (!(ifp->cflags & F_IFACE_CONFIGURED))
+ break;
iface = if_find(ifp->ifindex);
if (iface == NULL)
fatalx("interface lost in rde");
@@ -1532,8 +1550,9 @@ orig_intra_lsa_rtr(struct area *area, struct vertex *old)
iface->state & IF_STA_LOOPBACK) {
lsa_prefix->prefixlen = 128;
lsa_prefix->metric = 0;
- } else if (iface->if_type == IFT_CARP &&
- iface->linkstate == LINK_STATE_DOWN) {
+ } else if ((iface->if_type == IFT_CARP &&
+ iface->linkstate == LINK_STATE_DOWN) ||
+ !(iface->depend_ok)) {
/* carp interfaces in state backup are
* announced with high metric for faster
* failover. */