diff options
author | remi <remi@cvs.openbsd.org> | 2018-02-05 12:11:29 +0000 |
---|---|---|
committer | remi <remi@cvs.openbsd.org> | 2018-02-05 12:11:29 +0000 |
commit | d42b3d1b4aef8e6c5d75a18bb6c4ee79476ad019 (patch) | |
tree | 0ef89e91143034e35f52f5d27215d7b3b58c9ec0 /usr.sbin/ospfd/ospfd.c | |
parent | 95c71a012cf89c5f801281d5f82e4e8fdc3db0ec (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.c | 45 |
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); +} |