Commit 85a291ff authored by Martin Mareš's avatar Martin Mareš

IPv6 address classification fixes.

parent d1a74339
...@@ -67,12 +67,11 @@ ipv6_classify(ip_addr *a) ...@@ -67,12 +67,11 @@ ipv6_classify(ip_addr *a)
{ {
u32 x = a->addr[0]; u32 x = a->addr[0];
/* FIXME: Relax these requirements? */
if ((x & 0xe0000000) == 0x20000000) /* Aggregatable Global Unicast Address */ if ((x & 0xe0000000) == 0x20000000) /* Aggregatable Global Unicast Address */
return IADDR_HOST | SCOPE_UNIVERSE; return IADDR_HOST | SCOPE_UNIVERSE;
if ((x & 0xfc000000) == 0xe8000000) /* Link-Local Address */ if ((x & 0xffc00000) == 0xfe800000) /* Link-Local Address */
return IADDR_HOST | SCOPE_LINK; return IADDR_HOST | SCOPE_LINK;
if ((x & 0xfc000000) == 0xec000000) /* Site-Local Address */ if ((x & 0xffc00000) == 0xfec00000) /* Site-Local Address */
return IADDR_HOST | SCOPE_SITE; return IADDR_HOST | SCOPE_SITE;
if ((x & 0xff000000) == 0xff000000) /* Multicast Address */ if ((x & 0xff000000) == 0xff000000) /* Multicast Address */
{ {
...@@ -86,8 +85,21 @@ ipv6_classify(ip_addr *a) ...@@ -86,8 +85,21 @@ ipv6_classify(ip_addr *a)
case 14: return IADDR_MULTICAST | SCOPE_UNIVERSE; case 14: return IADDR_MULTICAST | SCOPE_UNIVERSE;
} }
} }
if (!x && !a->addr[1] && !a->addr[2] && a->addr[3] == 1) if (!x && !a->addr[1] && !a->addr[2])
return IADDR_HOST | SCOPE_HOST; /* Loopback address */ {
u32 y = a->addr[3];
if (y == 1)
return IADDR_HOST | SCOPE_HOST; /* Loopback address */
/* IPv4 compatible addresses */
if (y >= 0x7f000000 && y < 0x80000000)
return IADDR_HOST | SCOPE_HOST;
if ((y & 0xff000000) == 0x0a000000 ||
(y & 0xffff0000) == 0xc0a80000 ||
(y & 0xfff00000) == 0xac100000)
return IADDR_HOST | SCOPE_SITE;
if (y >= 0x01000000 && y < 0xe0000000)
return IADDR_HOST | SCOPE_UNIVERSE;
}
return IADDR_INVALID; return IADDR_INVALID;
} }
......
...@@ -371,8 +371,10 @@ ifa_update(struct ifa *a) ...@@ -371,8 +371,10 @@ ifa_update(struct ifa *a)
if (!(i->flags & IF_MULTIACCESS) && a->pxlen < BITS_PER_IP_ADDRESS - 2) if (!(i->flags & IF_MULTIACCESS) && a->pxlen < BITS_PER_IP_ADDRESS - 2)
log(L_WARN "Strange prefix length %d for point-to-point interface %s", a->pxlen, i->name); log(L_WARN "Strange prefix length %d for point-to-point interface %s", a->pxlen, i->name);
#ifndef IPV6
if ((i->flags & IF_BROADCAST) && !ipa_nonzero(a->brd)) if ((i->flags & IF_BROADCAST) && !ipa_nonzero(a->brd))
log(L_ERR "Missing broadcast address for interface %s", i->name); log(L_ERR "Missing broadcast address for interface %s", i->name);
#endif
b = mb_alloc(if_pool, sizeof(struct ifa)); b = mb_alloc(if_pool, sizeof(struct ifa));
memcpy(b, a, sizeof(struct ifa)); memcpy(b, a, sizeof(struct ifa));
......
...@@ -232,10 +232,18 @@ rte_validate(rte *e) ...@@ -232,10 +232,18 @@ rte_validate(rte *e)
c = ipa_classify(n->n.prefix); c = ipa_classify(n->n.prefix);
if (c < 0 || !(c & IADDR_HOST)) if (c < 0 || !(c & IADDR_HOST))
{ {
if (!ipa_nonzero(n->n.prefix) && n->n.pxlen <= 1) if (!ipa_nonzero(n->n.prefix))
return 1; /* Default route and half-default route is OK */ {
log(L_WARN "Ignoring bogus route %I/%d received from %I via %s", /* Various default routes */
n->n.prefix, n->n.pxlen, e->attrs->from, e->attrs->proto->name); #ifdef IPV6
if (n->n.pxlen == 96)
#else
if (n->n.pxlen <= 1)
#endif
return 1;
}
log(L_WARN "Ignoring bogus route %I/%d received via %s",
n->n.prefix, n->n.pxlen, e->attrs->proto->name);
return 0; return 0;
} }
if ((c & IADDR_SCOPE_MASK) < e->attrs->proto->min_scope) if ((c & IADDR_SCOPE_MASK) < e->attrs->proto->min_scope)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment