Fixes a nasty bug in OSPF.
Sending malformed network prefixes in LSAs causes OSPF to crash just after the LSA is propagated to the other routers.
This commit is contained in:
parent
52a43ae3b7
commit
ab16497189
4 changed files with 45 additions and 17 deletions
|
@ -374,7 +374,7 @@ rte_validate(rte *e)
|
||||||
|
|
||||||
if ((n->n.pxlen > BITS_PER_IP_ADDRESS) || !ip_is_prefix(n->n.prefix,n->n.pxlen))
|
if ((n->n.pxlen > BITS_PER_IP_ADDRESS) || !ip_is_prefix(n->n.prefix,n->n.pxlen))
|
||||||
{
|
{
|
||||||
log(L_BUG "Ignoring bogus prefix %I/%d received via %s",
|
log(L_WARN "Ignoring bogus prefix %I/%d received via %s",
|
||||||
n->n.prefix, n->n.pxlen, e->sender->name);
|
n->n.prefix, n->n.pxlen, e->sender->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -587,6 +587,10 @@ lsa_get_ipv6_prefix(u32 *buf, ip_addr *addr, int *pxlen, u8 *pxopts, u16 *rest)
|
||||||
if (pxl > 96)
|
if (pxl > 96)
|
||||||
_I3(*addr) = *buf++;
|
_I3(*addr) = *buf++;
|
||||||
|
|
||||||
|
/* Clean up remaining bits */
|
||||||
|
if (pxl < 128)
|
||||||
|
addr->addr[pxl / 32] &= u32_mkmask(pxl % 32);
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -269,9 +269,10 @@ ospf_rx_hook(sock *sk, int size)
|
||||||
struct proto_ospf *po = ifa->oa->po;
|
struct proto_ospf *po = ifa->oa->po;
|
||||||
// struct proto *p = &po->proto;
|
// struct proto *p = &po->proto;
|
||||||
|
|
||||||
int src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen);
|
int src_local, dst_local UNUSED, dst_mcast;
|
||||||
int dst_local = ipa_equal(sk->laddr, ifa->addr->ip);
|
src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen);
|
||||||
int dst_mcast = ipa_equal(sk->laddr, AllSPFRouters) || ipa_equal(sk->laddr, AllDRouters);
|
dst_local = ipa_equal(sk->laddr, ifa->addr->ip);
|
||||||
|
dst_mcast = ipa_equal(sk->laddr, AllSPFRouters) || ipa_equal(sk->laddr, AllDRouters);
|
||||||
|
|
||||||
#ifdef OSPFv2
|
#ifdef OSPFv2
|
||||||
/* First, we eliminate packets with strange address combinations.
|
/* First, we eliminate packets with strange address combinations.
|
||||||
|
|
|
@ -245,6 +245,13 @@ add_network(struct ospf_area *oa, ip_addr px, int pxlen, int metric, struct top_
|
||||||
.nhs = en->nhs
|
.nhs = en->nhs
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH)
|
||||||
|
{
|
||||||
|
log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
|
||||||
|
oa->po->proto.name, en->lsa.type, en->lsa.id, en->lsa.rt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (en == oa->rt)
|
if (en == oa->rt)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -336,7 +343,8 @@ ospf_rt_spfa_rtlinks(struct ospf_area *oa, struct top_hash_entry *act, struct to
|
||||||
{
|
{
|
||||||
// struct proto *p = &oa->po->proto;
|
// struct proto *p = &oa->po->proto;
|
||||||
struct proto_ospf *po = oa->po;
|
struct proto_ospf *po = oa->po;
|
||||||
int i;
|
ip_addr prefix UNUSED;
|
||||||
|
int pxlen UNUSED, i;
|
||||||
|
|
||||||
struct ospf_lsa_rt *rt = en->lsa_body;
|
struct ospf_lsa_rt *rt = en->lsa_body;
|
||||||
struct ospf_lsa_rt_link *rr = (struct ospf_lsa_rt_link *) (rt + 1);
|
struct ospf_lsa_rt_link *rr = (struct ospf_lsa_rt_link *) (rt + 1);
|
||||||
|
@ -357,9 +365,9 @@ ospf_rt_spfa_rtlinks(struct ospf_area *oa, struct top_hash_entry *act, struct to
|
||||||
* the same result by handing them here because add_network()
|
* the same result by handing them here because add_network()
|
||||||
* will keep the best (not the first) found route.
|
* will keep the best (not the first) found route.
|
||||||
*/
|
*/
|
||||||
add_network(oa, ipa_from_u32(rtl->id),
|
prefix = ipa_from_u32(rtl->id & rtl->data);
|
||||||
ipa_mklen(ipa_from_u32(rtl->data)),
|
pxlen = ipa_mklen(ipa_from_u32(rtl->data));
|
||||||
act->dist + rtl->metric, act, i);
|
add_network(oa, prefix, pxlen, act->dist + rtl->metric, act, i);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -398,6 +406,8 @@ ospf_rt_spfa(struct ospf_area *oa)
|
||||||
struct ospf_lsa_rt *rt;
|
struct ospf_lsa_rt *rt;
|
||||||
struct ospf_lsa_net *ln;
|
struct ospf_lsa_net *ln;
|
||||||
struct top_hash_entry *act, *tmp;
|
struct top_hash_entry *act, *tmp;
|
||||||
|
ip_addr prefix UNUSED;
|
||||||
|
int pxlen UNUSED;
|
||||||
u32 i, *rts;
|
u32 i, *rts;
|
||||||
node *n;
|
node *n;
|
||||||
|
|
||||||
|
@ -470,8 +480,9 @@ ospf_rt_spfa(struct ospf_area *oa)
|
||||||
ln = act->lsa_body;
|
ln = act->lsa_body;
|
||||||
|
|
||||||
#ifdef OSPFv2
|
#ifdef OSPFv2
|
||||||
add_network(oa, ipa_and(ipa_from_u32(act->lsa.id), ln->netmask),
|
prefix = ipa_and(ipa_from_u32(act->lsa.id), ln->netmask);
|
||||||
ipa_mklen(ln->netmask), act->dist, act, -1);
|
pxlen = ipa_mklen(ln->netmask);
|
||||||
|
add_network(oa, prefix, pxlen, act->dist, act, -1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rts = (u32 *) (ln + 1);
|
rts = (u32 *) (ln + 1);
|
||||||
|
@ -618,8 +629,8 @@ ospf_rt_sum(struct ospf_area *oa)
|
||||||
{
|
{
|
||||||
#ifdef OSPFv2
|
#ifdef OSPFv2
|
||||||
struct ospf_lsa_sum *ls = en->lsa_body;
|
struct ospf_lsa_sum *ls = en->lsa_body;
|
||||||
pxlen = ipa_mklen(ls->netmask);
|
|
||||||
ip = ipa_and(ipa_from_u32(en->lsa.id), ls->netmask);
|
ip = ipa_and(ipa_from_u32(en->lsa.id), ls->netmask);
|
||||||
|
pxlen = ipa_mklen(ls->netmask);
|
||||||
#else /* OSPFv3 */
|
#else /* OSPFv3 */
|
||||||
u8 pxopts;
|
u8 pxopts;
|
||||||
u16 rest;
|
u16 rest;
|
||||||
|
@ -630,6 +641,13 @@ ospf_rt_sum(struct ospf_area *oa)
|
||||||
continue;
|
continue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH)
|
||||||
|
{
|
||||||
|
log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
|
||||||
|
p->name, en->lsa.type, en->lsa.id, en->lsa.rt);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
metric = ls->metric & METRIC_MASK;
|
metric = ls->metric & METRIC_MASK;
|
||||||
options = 0;
|
options = 0;
|
||||||
type = ORT_NET;
|
type = ORT_NET;
|
||||||
|
@ -695,7 +713,7 @@ ospf_rt_sum(struct ospf_area *oa)
|
||||||
static void
|
static void
|
||||||
ospf_rt_sum_tr(struct ospf_area *oa)
|
ospf_rt_sum_tr(struct ospf_area *oa)
|
||||||
{
|
{
|
||||||
// struct proto *p = &oa->po->proto;
|
struct proto *p = &oa->po->proto;
|
||||||
struct proto_ospf *po = oa->po;
|
struct proto_ospf *po = oa->po;
|
||||||
struct ospf_area *bb = po->backbone;
|
struct ospf_area *bb = po->backbone;
|
||||||
ip_addr abrip;
|
ip_addr abrip;
|
||||||
|
@ -728,8 +746,8 @@ ospf_rt_sum_tr(struct ospf_area *oa)
|
||||||
int pxlen;
|
int pxlen;
|
||||||
#ifdef OSPFv2
|
#ifdef OSPFv2
|
||||||
struct ospf_lsa_sum *ls = en->lsa_body;
|
struct ospf_lsa_sum *ls = en->lsa_body;
|
||||||
pxlen = ipa_mklen(ls->netmask);
|
|
||||||
ip = ipa_and(ipa_from_u32(en->lsa.id), ls->netmask);
|
ip = ipa_and(ipa_from_u32(en->lsa.id), ls->netmask);
|
||||||
|
pxlen = ipa_mklen(ls->netmask);
|
||||||
#else /* OSPFv3 */
|
#else /* OSPFv3 */
|
||||||
u8 pxopts;
|
u8 pxopts;
|
||||||
u16 rest;
|
u16 rest;
|
||||||
|
@ -740,6 +758,13 @@ ospf_rt_sum_tr(struct ospf_area *oa)
|
||||||
continue;
|
continue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH)
|
||||||
|
{
|
||||||
|
log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
|
||||||
|
p->name, en->lsa.type, en->lsa.id, en->lsa.rt);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
metric = ls->metric & METRIC_MASK;
|
metric = ls->metric & METRIC_MASK;
|
||||||
re = fib_find(&po->rtf, &ip, pxlen);
|
re = fib_find(&po->rtf, &ip, pxlen);
|
||||||
}
|
}
|
||||||
|
@ -1139,9 +1164,9 @@ ospf_ext_spf(struct proto_ospf *po)
|
||||||
rt_tag = 0;
|
rt_tag = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (pxlen < 0)
|
if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH)
|
||||||
{
|
{
|
||||||
log(L_WARN "%s: Invalid mask in LSA (Type: %04x, Id: %R, Rt: %R)",
|
log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
|
||||||
p->name, en->lsa.type, en->lsa.id, en->lsa.rt);
|
p->name, en->lsa.type, en->lsa.id, en->lsa.rt);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1703,8 +1728,6 @@ again1:
|
||||||
e->net = ne;
|
e->net = ne;
|
||||||
e->pref = p->preference;
|
e->pref = p->preference;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DBG("Mod rte type %d - %I/%d via %I on iface %s, met %d\n",
|
DBG("Mod rte type %d - %I/%d via %I on iface %s, met %d\n",
|
||||||
a0.source, nf->fn.prefix, nf->fn.pxlen, a0.gw, a0.iface ? a0.iface->name : "(none)", nf->n.metric1);
|
a0.source, nf->fn.prefix, nf->fn.pxlen, a0.gw, a0.iface ? a0.iface->name : "(none)", nf->n.metric1);
|
||||||
rte_update(p->table, ne, p, p, e);
|
rte_update(p->table, ne, p, p, e);
|
||||||
|
|
Loading…
Reference in a new issue