-/* $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>
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);
-/* $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>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <net/if_types.h>
#include <event.h>
#include <err.h>
{
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;
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;
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;
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);
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;
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);
+}
-.\" $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>
.\" 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
.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 ,
.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
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.
-/* $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>
char name[IF_NAMESIZE];
char demote_group[IFNAMSIZ];
+ char dependon[IFNAMSIZ];
struct in6_addr addr;
struct in6_addr dst;
struct in_addr abr_id;
int fd;
int state;
int mtu;
+ int depend_ok;
u_int16_t flags;
u_int16_t transmit_delay;
u_int16_t hello_interval;
u_int16_t label;
u_int16_t type;
u_int8_t prefixlen;
+ char dependon[IFNAMSIZ];
};
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 *);
-/* $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>
{
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;
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");
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;
"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;
/* 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);
-/* $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>
%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
%%
| defaults
;
-redistribute : no REDISTRIBUTE STRING optlist {
+redistribute : no REDISTRIBUTE STRING optlist dependon {
struct redistribute *r;
if ((r = calloc(1, sizeof(*r))) == NULL)
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)
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;
}
;
}
;
+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)",
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
;
static const struct keywords keywords[] = {
{"area", AREA},
{"demote", DEMOTE},
+ {"depend", DEPEND},
{"external-tag", EXTTAG},
{"fib-update", FIBUPDATE},
{"hello-interval", HELLOINTERVAL},
{"interface", INTERFACE},
{"metric", METRIC},
{"no", NO},
+ {"on", ON},
{"passive", PASSIVE},
{"redistribute", REDISTRIBUTE},
{"retransmit-interval", RETRANSMITINTERVAL},
-/* $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>
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");
}
}
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);
-/* $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>
{
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;
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) {
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");
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. */