bird6 has a rather limited list of IPv6 address classifications, unfortunately 
limiting the routes that it will accept.

ipv6_classify(ip_addr *a) in lib/ipv6.c:

    if ((x & 0xe0000000) == 0x20000000)           /* 2000::/3  Aggregatable 
Global Unicast Address */
    if ((x & 0xffc00000) == 0xfe800000)           /* fe80::/10 Link-Local 
Address */
    if ((x & 0xffc00000) == 0xfec00000)           /* fec0::/10 Site-Local 
Address */
    if ((x & 0xfe000000) == 0xfc000000)           /* fc00::/7  Unique Local 
Unicast Address (RFC 4193) */
    if ((x & 0xff000000) == 0xff000000)           /* ff00::/8  Multicast 
Address */

Unfortunately there is a bad side-effect when a BGP peer sends a route for an 
address that does not fit any of these classifications; bird6 claims that they 
are "bogus routes", and then seems to drop any routes that have already been 
received by that peer.

This problem can be very easily reproduced in bird6-1.3.1 by receiving a route 
outside of these ranges. The validation code appears below, and the problem can 
be very easily corrected by commenting it out:

rte_validate(rte *e) in nest/rt-table.c:

    c = ipa_classify_net(n->n.prefix);
    if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
      {
        log(L_WARN "Ignoring bogus route %I/%d received via %s",
            n->n.prefix, n->n.pxlen, e->sender->name);
        return 0;
      }

I am interested to hear whether the strictness of the ipv6_classify(ip_addr *a) 
function would be considered a "bug" or a "feature", but from what I can tell, 
quagga and openbgpd do not classify addresses in such a strict fashion, and 
this can produce problems in mixed environments where quagga/openbgpd peers may 
try and send such routes to bird6.

Perhaps any address that is not link-scoped should be implicitly classified as 
global? At the very least, receiving a "bogus route" should not result in all 
existing routes from that peer being dropped.

Reply via email to