summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2011-05-24 20:21:52 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2011-05-24 20:21:52 +0000
commit84cded86709d8bc018a9101ce6a067d69b5aa936 (patch)
tree7f341f48d263ab93ea44ae81b63d6930f8ab3da4
parent4665eb962644a8b44bfd4fa96783da6a7f001eff (diff)
Fix nexthop calculation for directly connected P2P links. connected
may only be set on directly connected networks but not on router nodes which are used by the P2P links. Fix for PR 6597. OK sthen@
-rw-r--r--usr.sbin/ospfd/rde_spf.c54
1 files changed, 29 insertions, 25 deletions
diff --git a/usr.sbin/ospfd/rde_spf.c b/usr.sbin/ospfd/rde_spf.c
index 996e9fcaf26..aea7d4de426 100644
--- a/usr.sbin/ospfd/rde_spf.c
+++ b/usr.sbin/ospfd/rde_spf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_spf.c,v 1.72 2011/05/09 12:24:41 claudio Exp $ */
+/* $OpenBSD: rde_spf.c,v 1.73 2011/05/24 20:21:51 claudio Exp $ */
/*
* Copyright (c) 2005 Esben Norby <norby@openbsd.org>
@@ -38,9 +38,9 @@ struct vertex *spf_root = NULL;
void calc_nexthop(struct vertex *, struct vertex *,
struct area *, struct lsa_rtr_link *);
void rt_nexthop_clear(struct rt_node *);
-void rt_nexthop_add(struct rt_node *, struct v_nexthead *,
+void rt_nexthop_add(struct rt_node *, struct v_nexthead *, u_int8_t,
struct in_addr);
-void rt_update(struct in_addr, u_int8_t, struct v_nexthead *,
+void rt_update(struct in_addr, u_int8_t, struct v_nexthead *, u_int8_t,
u_int32_t, u_int32_t, struct in_addr, struct in_addr,
enum path_type, enum dst_type, u_int8_t, u_int32_t);
void rt_invalidate(struct area *);
@@ -194,7 +194,8 @@ rt_calc(struct vertex *v, struct area *area, struct ospfd_conf *conf)
adv_rtr.s_addr = htonl(v->adv_rtr);
rt_update(addr, mask2prefixlen(rtr_link->data),
- &v->nexthop, v->cost + ntohs(rtr_link->metric), 0,
+ &v->nexthop, v->type,
+ v->cost + ntohs(rtr_link->metric), 0,
area->id, adv_rtr, PT_INTRA_AREA, DT_NET,
v->lsa->data.rtr.flags, 0);
}
@@ -206,7 +207,7 @@ rt_calc(struct vertex *v, struct area *area, struct ospfd_conf *conf)
addr.s_addr = htonl(v->ls_id);
adv_rtr.s_addr = htonl(v->adv_rtr);
- rt_update(addr, 32, &v->nexthop, v->cost, 0, area->id,
+ rt_update(addr, 32, &v->nexthop, v->type, v->cost, 0, area->id,
adv_rtr, PT_INTRA_AREA, DT_RTR, v->lsa->data.rtr.flags, 0);
break;
case LSA_TYPE_NETWORK:
@@ -216,8 +217,8 @@ rt_calc(struct vertex *v, struct area *area, struct ospfd_conf *conf)
addr.s_addr = htonl(v->ls_id) & v->lsa->data.net.mask;
adv_rtr.s_addr = htonl(v->adv_rtr);
rt_update(addr, mask2prefixlen(v->lsa->data.net.mask),
- &v->nexthop, v->cost, 0, area->id, adv_rtr, PT_INTRA_AREA,
- DT_NET, 0, 0);
+ &v->nexthop, v->type, v->cost, 0, area->id, adv_rtr,
+ PT_INTRA_AREA, DT_NET, 0, 0);
break;
case LSA_TYPE_SUM_NETWORK:
case LSA_TYPE_SUM_ROUTER:
@@ -251,12 +252,12 @@ rt_calc(struct vertex *v, struct area *area, struct ospfd_conf *conf)
if (v->type == LSA_TYPE_SUM_NETWORK) {
addr.s_addr = htonl(v->ls_id) & v->lsa->data.sum.mask;
rt_update(addr, mask2prefixlen(v->lsa->data.sum.mask),
- &v->nexthop, v->cost, 0, area->id, adv_rtr,
+ &v->nexthop, v->type, v->cost, 0, area->id, adv_rtr,
PT_INTER_AREA, DT_NET, 0, 0);
} else {
addr.s_addr = htonl(v->ls_id);
- rt_update(addr, 32, &v->nexthop, v->cost, 0, area->id,
- adv_rtr, PT_INTER_AREA, DT_RTR,
+ rt_update(addr, 32, &v->nexthop, v->type, v->cost, 0,
+ area->id, adv_rtr, PT_INTER_AREA, DT_RTR,
v->lsa->data.rtr.flags, 0);
}
@@ -322,19 +323,20 @@ asext_calc(struct vertex *v)
if (rn->invalid)
continue;
- if (rn->connected && r->d_type == DT_NET) {
- if (v->lsa->data.asext.fw_addr != 0)
- vertex_nexthop_add(v, NULL,
- v->lsa->data.asext.fw_addr);
- else
- vertex_nexthop_add(v, NULL,
- htonl(v->adv_rtr));
- } else
+ /*
+ * if a fw_addr is specified and the nexthop
+ * is directly connected then it is possible to
+ * send traffic directly to fw_addr.
+ */
+ if (v->lsa->data.asext.fw_addr != 0 && rn->connected)
+ vertex_nexthop_add(v, NULL,
+ v->lsa->data.asext.fw_addr);
+ else
vertex_nexthop_add(v, NULL, rn->nexthop.s_addr);
}
rt_update(addr, mask2prefixlen(v->lsa->data.asext.mask),
- &v->nexthop, v->cost, cost2, a, adv_rtr, type,
+ &v->nexthop, v->type, v->cost, cost2, a, adv_rtr, type,
DT_NET, 0, ntohl(v->lsa->data.asext.ext_tag));
break;
default:
@@ -729,7 +731,7 @@ rt_nexthop_clear(struct rt_node *r)
}
void
-rt_nexthop_add(struct rt_node *r, struct v_nexthead *vnh,
+rt_nexthop_add(struct rt_node *r, struct v_nexthead *vnh, u_int8_t type,
struct in_addr adv_rtr)
{
struct v_nexthop *vn;
@@ -742,7 +744,8 @@ rt_nexthop_add(struct rt_node *r, struct v_nexthead *vnh,
continue;
rn->adv_rtr.s_addr = adv_rtr.s_addr;
- rn->connected = vn->prev == spf_root;
+ rn->connected = (type == LSA_TYPE_NETWORK &&
+ vn->prev == spf_root);
rn->invalid = 0;
r->invalid = 0;
@@ -758,7 +761,8 @@ rt_nexthop_add(struct rt_node *r, struct v_nexthead *vnh,
rn->nexthop.s_addr = vn->nexthop.s_addr;
rn->adv_rtr.s_addr = adv_rtr.s_addr;
rn->uptime = now.tv_sec;
- rn->connected = vn->prev == spf_root;
+ rn->connected = (type == LSA_TYPE_NETWORK &&
+ vn->prev == spf_root);
rn->invalid = 0;
r->invalid = 0;
@@ -837,7 +841,7 @@ rt_dump(struct in_addr area, pid_t pid, u_int8_t r_type)
void
rt_update(struct in_addr prefix, u_int8_t prefixlen, struct v_nexthead *vnh,
- u_int32_t cost, u_int32_t cost2, struct in_addr area,
+ u_int8_t v_type, u_int32_t cost, u_int32_t cost2, struct in_addr area,
struct in_addr adv_rtr, enum path_type p_type, enum dst_type d_type,
u_int8_t flags, u_int32_t tag)
{
@@ -863,7 +867,7 @@ rt_update(struct in_addr prefix, u_int8_t prefixlen, struct v_nexthead *vnh,
rte->flags = flags;
rte->ext_tag = tag;
- rt_nexthop_add(rte, vnh, adv_rtr);
+ rt_nexthop_add(rte, vnh, v_type, adv_rtr);
rt_insert(rte);
} else {
@@ -923,7 +927,7 @@ rt_update(struct in_addr prefix, u_int8_t prefixlen, struct v_nexthead *vnh,
}
if (equal || better)
- rt_nexthop_add(rte, vnh, adv_rtr);
+ rt_nexthop_add(rte, vnh, v_type, adv_rtr);
}
}