Hi tech, in OSPFs external LSAs the type is encoded in the metric field. ospfd and ospf6d overwrite the type information when "depend on" is used and the specified interface is down (or in backup state). Below diff fixes this.
The problem was reported on misc by Ior Podlesny: https://marc.info/?l=openbsd-misc&m=154704895731641&w=2 OK? Remi Index: ospfd/ospfd.c =================================================================== RCS file: /cvs/src/usr.sbin/ospfd/ospfd.c,v retrieving revision 1.103 diff -u -p -r1.103 ospfd.c --- ospfd/ospfd.c 2 Jan 2019 18:47:59 -0000 1.103 +++ ospfd/ospfd.c 10 Jan 2019 21:08:23 -0000 @@ -564,7 +564,8 @@ ospf_redistribute(struct kroute *kr, u_i switch (r->type & ~REDIST_NO) { case REDIST_LABEL: if (kr->rtlabel == r->label) { - *metric = depend_ok ? r->metric : MAX_METRIC; + *metric = depend_ok ? r->metric : + r->metric | MAX_METRIC; return (r->type & REDIST_NO ? 0 : 1); } break; @@ -579,7 +580,8 @@ ospf_redistribute(struct kroute *kr, u_i if (kr->flags & F_DYNAMIC) continue; if (kr->flags & F_STATIC) { - *metric = depend_ok ? r->metric : MAX_METRIC; + *metric = depend_ok ? r->metric : + r->metric | MAX_METRIC; return (r->type & REDIST_NO ? 0 : 1); } break; @@ -589,7 +591,8 @@ ospf_redistribute(struct kroute *kr, u_i if (kr->flags & F_DYNAMIC) continue; if (kr->flags & F_CONNECTED) { - *metric = depend_ok ? r->metric : MAX_METRIC; + *metric = depend_ok ? r->metric : + r->metric | MAX_METRIC; return (r->type & REDIST_NO ? 0 : 1); } break; @@ -601,7 +604,7 @@ ospf_redistribute(struct kroute *kr, u_i r->mask.s_addr == INADDR_ANY) { if (is_default) { *metric = depend_ok ? r->metric : - MAX_METRIC; + r->metric | MAX_METRIC; return (r->type & REDIST_NO ? 0 : 1); } else return (0); @@ -610,13 +613,15 @@ ospf_redistribute(struct kroute *kr, u_i 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 = depend_ok ? r->metric : MAX_METRIC; + *metric = depend_ok ? r->metric : + r->metric | MAX_METRIC; return (r->type & REDIST_NO ? 0 : 1); } break; case REDIST_DEFAULT: if (is_default) { - *metric = depend_ok ? r->metric : MAX_METRIC; + *metric = depend_ok ? r->metric : + r->metric | MAX_METRIC; return (r->type & REDIST_NO ? 0 : 1); } break; Index: ospf6d/ospf6d.c =================================================================== RCS file: /cvs/src/usr.sbin/ospf6d/ospf6d.c,v retrieving revision 1.41 diff -u -p -r1.41 ospf6d.c --- ospf6d/ospf6d.c 29 Dec 2018 16:04:31 -0000 1.41 +++ ospf6d/ospf6d.c 10 Jan 2019 21:53:10 -0000 @@ -534,7 +534,8 @@ ospf_redistribute(struct kroute *kr, u_i switch (r->type & ~REDIST_NO) { case REDIST_LABEL: if (kr->rtlabel == r->label) { - *metric = depend_ok ? r->metric : MAX_METRIC; + *metric = depend_ok ? r->metric : + r->metric | MAX_METRIC; return (r->type & REDIST_NO ? 0 : 1); } break; @@ -549,7 +550,8 @@ ospf_redistribute(struct kroute *kr, u_i if (kr->flags & F_DYNAMIC) continue; if (kr->flags & F_STATIC) { - *metric = depend_ok ? r->metric : MAX_METRIC; + *metric = depend_ok ? r->metric : + r->metric | MAX_METRIC; return (r->type & REDIST_NO ? 0 : 1); } break; @@ -559,7 +561,8 @@ ospf_redistribute(struct kroute *kr, u_i if (kr->flags & F_DYNAMIC) continue; if (kr->flags & F_CONNECTED) { - *metric = depend_ok ? r->metric : MAX_METRIC; + *metric = depend_ok ? r->metric : + r->metric | MAX_METRIC; return (r->type & REDIST_NO ? 0 : 1); } break; @@ -571,7 +574,7 @@ ospf_redistribute(struct kroute *kr, u_i r->prefixlen == 0) { if (is_default) { *metric = depend_ok ? r->metric : - MAX_METRIC; + r->metric | MAX_METRIC; return (r->type & REDIST_NO ? 0 : 1); } else return (0); @@ -581,13 +584,15 @@ ospf_redistribute(struct kroute *kr, u_i inet6applymask(&inb, &r->addr, r->prefixlen); if (IN6_ARE_ADDR_EQUAL(&ina, &inb) && kr->prefixlen >= r->prefixlen) { - *metric = depend_ok ? r->metric : MAX_METRIC; + *metric = depend_ok ? r->metric : + r->metric | MAX_METRIC; return (r->type & REDIST_NO ? 0 : 1); } break; case REDIST_DEFAULT: if (is_default) { - *metric = depend_ok ? r->metric : MAX_METRIC; + *metric = depend_ok ? r->metric : + r->metric | MAX_METRIC; return (r->type & REDIST_NO ? 0 : 1); } break;
