summaryrefslogtreecommitdiff
path: root/usr.sbin/ospfd/ospfd.c
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 /usr.sbin/ospfd/ospfd.c
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@
Diffstat (limited to 'usr.sbin/ospfd/ospfd.c')
-rw-r--r--usr.sbin/ospfd/ospfd.c45
1 files changed, 37 insertions, 8 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);
+}