diff options
-rw-r--r-- | aclocal.m4 | 30 | ||||
-rw-r--r-- | configure.in | 12 | ||||
-rw-r--r-- | doc/bird.sgml | 23 | ||||
-rw-r--r-- | nest/iface.c | 6 | ||||
-rw-r--r-- | proto/bgp/attrs.c | 8 | ||||
-rw-r--r-- | proto/bgp/bgp.h | 1 | ||||
-rw-r--r-- | proto/bgp/config.Y | 3 | ||||
-rw-r--r-- | proto/bgp/packets.c | 2 | ||||
-rw-r--r-- | proto/ospf/config.Y | 32 | ||||
-rw-r--r-- | proto/ospf/hello.c | 3 | ||||
-rw-r--r-- | proto/ospf/iface.c | 27 | ||||
-rw-r--r-- | proto/ospf/ospf.h | 2 |
12 files changed, 103 insertions, 46 deletions
@@ -133,19 +133,23 @@ if test "$bird_cv_struct_ip_mreqn" = yes ; then fi ]) -AC_DEFUN(BIRD_CHECK_GCC_OPTIONS, -[AC_CACHE_VAL(bird_cv_c_option_no_pointer_sign, [ -cat >conftest.c <<EOF -int main(void) -{ return 0; } -EOF -if $CC -Wall -Wno-pointer-sign conftest.c >&AS_MESSAGE_LOG_FD 2>&1 ; then - bird_cv_c_option_no_pointer_sign=yes -else - bird_cv_c_option_no_pointer_sign=no -fi -rm -rf conftest* a.out -])]) +AC_DEFUN(BIRD_CHECK_GCC_OPTION, +[ + bird_tmp_cflags="$CFLAGS" + + CFLAGS="$3 $2" + AC_CACHE_CHECK([whether CC supports $2], $1, + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], [$1=yes], [$1=no])]) + + CFLAGS="$bird_tmp_cflags" +]) + +AC_DEFUN(BIRD_ADD_GCC_OPTION, +[ + if test "$$1" = yes ; then + CFLAGS="$CFLAGS $2" + fi +]) # BIRD_CHECK_PROG_FLAVOR_GNU(PROGRAM-PATH, IF-SUCCESS, [IF-FAILURE]) # copied autoconf internal _AC_PATH_PROG_FLAVOR_GNU diff --git a/configure.in b/configure.in index 534baf21..96f2a50e 100644 --- a/configure.in +++ b/configure.in @@ -87,15 +87,17 @@ if test -z "$GCC" ; then AC_MSG_ERROR([This program requires the GNU C Compiler.]) fi -AC_MSG_CHECKING([what CFLAGS should we use]) if test "$bird_cflags_default" = yes ; then - BIRD_CHECK_GCC_OPTIONS + BIRD_CHECK_GCC_OPTION(bird_cv_c_option_wno_pointer_sign, -Wno-pointer-sign, -Wall) + BIRD_CHECK_GCC_OPTION(bird_cv_c_option_fno_strict_aliasing, -fno-strict-aliasing) + BIRD_CHECK_GCC_OPTION(bird_cv_c_option_fno_strict_overflow, -fno-strict-overflow) CFLAGS="$CFLAGS -Wall -Wstrict-prototypes -Wno-parentheses" - if test "$bird_cv_c_option_no_pointer_sign" = yes ; then - CFLAGS="$CFLAGS -Wno-pointer-sign" - fi + BIRD_ADD_GCC_OPTION(bird_cv_c_option_wno_pointer_sign, -Wno-pointer-sign) + BIRD_ADD_GCC_OPTION(bird_cv_c_option_fno_strict_aliasing, -fno-strict-aliasing) + BIRD_ADD_GCC_OPTION(bird_cv_c_option_fno_strict_overflow, -fno-strict-overflow) fi +AC_MSG_CHECKING([CFLAGS]) AC_MSG_RESULT($CFLAGS) diff --git a/doc/bird.sgml b/doc/bird.sgml index 88d35e49..18f3601b 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1335,6 +1335,11 @@ for each neighbor using the following configuration parameters: circumvent misconfigurations of other routers. Default: disabled. + <tag>next hop keep</tag> Forward the received Next Hop + attribute even in situations where the local address should be + used instead, like when the route is sent to an interface with + a different subnet. Default: disabled. + <tag>missing lladdr self|drop|ignore</tag>Next Hop attribute in BGP-IPv6 sometimes contains just the global IPv6 address, but sometimes it has to contain both global and link-local @@ -1941,6 +1946,7 @@ protocol ospf <name> { nonbroadcast|nbma|pointomultipoint|ptmp]; strict nonbroadcast <switch>; real broadcast <switch>; + ptp netmask <switch>; check link <switch>; ecmp weight <num>; authentication [none|simple|cryptographic]; @@ -2184,6 +2190,18 @@ protocol ospf <name> { probably is not interoperable with other OSPF implementations. Default value is no. + <tag>ptp netmask <m/switch/</tag> + In <cf/type ptp/ network configurations, OSPFv2 + implementations should ignore received netmask field in hello + packets and should send hello packets with zero netmask field + on unnumbered PtP links. But some OSPFv2 implementations + perform netmask checking even for PtP links. This option + specifies whether real netmask will be used in hello packets + on <cf/type ptp/ interfaces. You should ignore this option + unless you meet some compatibility problems related to this + issue. Default value is no for unnumbered PtP links, yes + otherwise. + <tag>check link <M>switch</M></tag> If set, a hardware link state (reported by OS) is taken into consideration. When a link disappears (e.g. an ethernet cable is @@ -2218,7 +2236,10 @@ protocol ospf <name> { <tag>neighbors { <m/set/ } </tag> A set of neighbors to which Hello messages on NBMA or PtMP networks are to be sent. For NBMA networks, some of them - could be marked as eligible. + could be marked as eligible. In OSPFv3, link-local addresses + should be used, using global ones is possible, but it is + nonstandard and might be problematic. And definitely, + link-local and global addresses should not be mixed. </descrip> diff --git a/nest/iface.c b/nest/iface.c index da79b21f..b4ab70c3 100644 --- a/nest/iface.c +++ b/nest/iface.c @@ -589,7 +589,7 @@ if_choose_router_id(struct iface_patt *mask, u32 old_id) WALK_LIST(i, iface_list) { if (!(i->flags & IF_ADMIN_UP) || - (i->flags & (IF_IGNORE | IF_SHUTDOWN))) + (i->flags & IF_SHUTDOWN)) continue; WALK_LIST(a, i->addrs) @@ -612,6 +612,10 @@ if_choose_router_id(struct iface_patt *mask, u32 old_id) if (mask && !iface_patt_match(mask, i, a)) continue; + /* FIXME: This should go away too */ + if ((i->flags & IF_IGNORE) && !mask) + continue; + /* No pattern or pattern matched */ if (!b || ipa_to_u32(a->ip) < ipa_to_u32(b->ip)) b = a; diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 98b2f2c2..c27a4988 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -935,7 +935,8 @@ bgp_create_attrs(struct bgp_proto *p, rte *e, ea_list **attrs, struct linpool *p rta->dest != RTD_ROUTER || ipa_equal(rta->gw, IPA_NONE) || ipa_has_link_scope(rta->gw) || - (!p->is_internal && (!p->neigh || (rta->iface != p->neigh->iface)))) + (!p->is_internal && !p->cf->next_hop_keep && + (!p->neigh || (rta->iface != p->neigh->iface)))) set_next_hop(z, p->source_addr); else set_next_hop(z, rta->gw); @@ -1003,10 +1004,13 @@ bgp_update_attrs(struct bgp_proto *p, rte *e, ea_list **attrs, struct linpool *p /* iBGP -> keep next_hop, eBGP multi-hop -> use source_addr, * eBGP single-hop -> keep next_hop if on the same iface. * If the next_hop is zero (i.e. link-local), keep only if on the same iface. + * + * Note that same-iface-check uses iface from route, which is based on gw. */ a = ea_find(e->attrs->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP)); if (a && !p->cf->next_hop_self && - ((p->is_internal && ipa_nonzero(*((ip_addr *) a->u.ptr->data))) || + (p->cf->next_hop_keep || + (p->is_internal && ipa_nonzero(*((ip_addr *) a->u.ptr->data))) || (p->neigh && (e->attrs->iface == p->neigh->iface)))) { /* Leave the original next hop attribute, will check later where does it point */ diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index c3adf254..13c7fd80 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -24,6 +24,7 @@ struct bgp_config { int multihop; /* Number of hops if multihop */ int ttl_security; /* Enable TTL security [RFC5082] */ int next_hop_self; /* Always set next hop to local IP address */ + int next_hop_keep; /* Do not touch next hop attribute */ int missing_lladdr; /* What we will do when we don' know link-local addr, see MLL_* */ int gw_mode; /* How we compute route gateway from next_hop attr, see GW_* */ int compare_path_lengths; /* Use path lengths when selecting best route */ diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y index 8b80d7fd..d5e5aaca 100644 --- a/proto/bgp/config.Y +++ b/proto/bgp/config.Y @@ -76,7 +76,8 @@ bgp_proto: | bgp_proto KEEPALIVE TIME expr ';' { BGP_CFG->keepalive_time = $4; } | bgp_proto MULTIHOP ';' { BGP_CFG->multihop = 64; } | bgp_proto MULTIHOP expr ';' { BGP_CFG->multihop = $3; if (($3<1) || ($3>255)) cf_error("Multihop must be in range 1-255"); } - | bgp_proto NEXT HOP SELF ';' { BGP_CFG->next_hop_self = 1; } + | bgp_proto NEXT HOP SELF ';' { BGP_CFG->next_hop_self = 1; BGP_CFG->next_hop_keep = 0; } + | bgp_proto NEXT HOP KEEP ';' { BGP_CFG->next_hop_keep = 1; BGP_CFG->next_hop_self = 0; } | bgp_proto MISSING LLADDR SELF ';' { BGP_CFG->missing_lladdr = MLL_SELF; } | bgp_proto MISSING LLADDR DROP ';' { BGP_CFG->missing_lladdr = MLL_DROP; } | bgp_proto MISSING LLADDR IGNORE ';' { BGP_CFG->missing_lladdr = MLL_IGNORE; } diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index cfa37fb5..f2e03f87 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -820,7 +820,7 @@ bgp_set_next_hop(struct bgp_proto *p, rta *a) ip_addr *nexthop = (ip_addr *) nh->u.ptr->data; #ifdef IPV6 - int second = (nh->u.ptr->length == NEXT_HOP_LENGTH); + int second = (nh->u.ptr->length == NEXT_HOP_LENGTH) && ipa_nonzero(nexthop[1]); /* First address should not be link-local, but may be zero in direct mode */ if (ipa_has_link_scope(*nexthop)) diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y index 3f09afba..2cc0b963 100644 --- a/proto/ospf/config.Y +++ b/proto/ospf/config.Y @@ -131,10 +131,11 @@ CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC) CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK) CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY, TAG, EXTERNAL) CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY) -CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL) +CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL, NETMASK) %type <t> opttext %type <ld> lsadb_args +%type <i> nbma_eligible CF_GRAMMAR @@ -289,13 +290,14 @@ ospf_iface_item: | TYPE POINTOMULTIPOINT { OSPF_PATT->type = OSPF_IT_PTMP ; } | TYPE PTMP { OSPF_PATT->type = OSPF_IT_PTMP ; } | REAL BROADCAST bool { OSPF_PATT->real_bcast = $3; if (OSPF_VERSION != 2) cf_error("Real broadcast option requires OSPFv2"); } + | PTP NETMASK bool { OSPF_PATT->ptp_netmask = $3; if (OSPF_VERSION != 2) cf_error("Real netmask option requires OSPFv2"); } | TRANSMIT DELAY expr { OSPF_PATT->inftransdelay = $3 ; if (($3<=0) || ($3>65535)) cf_error("Transmit delay must be in range 1-65535"); } | PRIORITY expr { OSPF_PATT->priority = $2 ; if (($2<0) || ($2>255)) cf_error("Priority must be in range 0-255"); } | STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; } | STUB bool { OSPF_PATT->stub = $2 ; } | CHECK LINK bool { OSPF_PATT->check_link = $3; } | ECMP WEIGHT expr { OSPF_PATT->ecmp_weight = $3 - 1; if (($3<1) || ($3>256)) cf_error("ECMP weight must be in range 1-256"); } - | NEIGHBORS '{' ipa_list '}' + | NEIGHBORS '{' nbma_list '}' | AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE ; } | AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE ; } | AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT ; } @@ -327,33 +329,24 @@ pref_opt: | TAG expr { this_pref->tag = $2; } ; -ipa_list: +nbma_list: /* empty */ - | ipa_list ipa_item + | nbma_list nbma_item ; -ipa_item: - ipa_el - | ipa_ne; +nbma_eligible: + /* empty */ { $$ = 0; } + | ELIGIBLE { $$ = 1; } + ; -ipa_el: IPA ';' +nbma_item: IPA nbma_eligible ';' { this_nbma = cfg_allocz(sizeof(struct nbma_node)); add_tail(&OSPF_PATT->nbma_list, NODE this_nbma); this_nbma->ip=$1; - this_nbma->eligible=0; + this_nbma->eligible=$2; } ; - -ipa_ne: IPA ELIGIBLE ';' - { - this_nbma = cfg_allocz(sizeof(struct nbma_node)); - add_tail(&OSPF_PATT->nbma_list, NODE this_nbma); - this_nbma->ip=$1; - this_nbma->eligible=1; - } -; - ospf_iface_start: { @@ -372,6 +365,7 @@ ospf_iface_start: OSPF_PATT->type = OSPF_IT_UNDEF; init_list(&OSPF_PATT->nbma_list); OSPF_PATT->autype = OSPF_AUTH_NONE; + OSPF_PATT->ptp_netmask = 2; /* not specified */ reset_passwords(); } ; diff --git a/proto/ospf/hello.c b/proto/ospf/hello.c index 6ec5c511..d5aa1b95 100644 --- a/proto/ospf/hello.c +++ b/proto/ospf/hello.c @@ -253,7 +253,8 @@ ospf_hello_send(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn) #ifdef OSPFv2 pkt->netmask = ipa_mkmask(ifa->addr->pxlen); ipa_hton(pkt->netmask); - if ((ifa->type == OSPF_IT_VLINK) || (ifa->type == OSPF_IT_PTP)) + if ((ifa->type == OSPF_IT_VLINK) || + ((ifa->type == OSPF_IT_PTP) && !ifa->ptp_netmask)) pkt->netmask = IPA_NONE; #endif diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c index 290a8634..9050f7b1 100644 --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@ -537,6 +537,9 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i #ifdef OSPFv2 ifa->autype = ip->autype; ifa->passwords = ip->passwords; + ifa->ptp_netmask = !(addr->flags & IA_PEER); + if (ip->ptp_netmask < 2) + ifa->ptp_netmask = ip->ptp_netmask; #endif #ifdef OSPFv3 @@ -574,8 +577,22 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i init_list(&ifa->nbma_list); WALK_LIST(nb, ip->nbma_list) - if (ipa_in_net(nb->ip, addr->prefix, addr->pxlen)) - add_nbma_node(ifa, nb, 0); + { + /* In OSPFv3, addr is link-local while configured neighbors could + have global IP (although RFC 5340 C.5 says link-local addresses + should be used). Because OSPFv3 iface is not subnet-specific, + there is no need for ipa_in_net() check */ + +#ifdef OSPFv2 + if (!ipa_in_net(nb->ip, addr->prefix, addr->pxlen)) + continue; +#else + if (!ipa_has_link_scope(nb->ip)) + log(L_WARN "In OSPFv3, configured neighbor address (%I) should be link-local", nb->ip); +#endif + + add_nbma_node(ifa, nb, 0); + } ifa->state = OSPF_IS_DOWN; add_tail(&oa->po->iface_list, NODE ifa); @@ -771,8 +788,14 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) /* NBMA LIST - add new */ WALK_LIST(nb, new->nbma_list) { + /* See related note in ospf_iface_new() */ +#ifdef OSPFv2 if (!ipa_in_net(nb->ip, ifa->addr->prefix, ifa->addr->pxlen)) continue; +#else + if (!ipa_has_link_scope(nb->ip)) + log(L_WARN "In OSPFv3, configured neighbor address (%I) should be link-local", nb->ip); +#endif if (! find_nbma_node(ifa, nb->ip)) { diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index 7111a13d..d924e657 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -273,6 +273,7 @@ struct ospf_iface u16 rxbuf; /* Buffer size */ u8 check_link; /* Whether iface link change is used */ u8 ecmp_weight; /* Weight used for ECMP */ + u8 ptp_netmask; /* Send real netmask for P2P */ }; struct ospf_md5 @@ -810,6 +811,7 @@ struct ospf_iface_patt u8 check_link; u8 ecmp_weight; u8 real_bcast; /* Not really used in OSPFv3 */ + u8 ptp_netmask; /* bool but 2 for unspecified */ #ifdef OSPFv2 list *passwords; |