summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--aclocal.m430
-rw-r--r--configure.in12
-rw-r--r--doc/bird.sgml23
-rw-r--r--nest/iface.c6
-rw-r--r--proto/bgp/attrs.c8
-rw-r--r--proto/bgp/bgp.h1
-rw-r--r--proto/bgp/config.Y3
-rw-r--r--proto/bgp/packets.c2
-rw-r--r--proto/ospf/config.Y32
-rw-r--r--proto/ospf/hello.c3
-rw-r--r--proto/ospf/iface.c27
-rw-r--r--proto/ospf/ospf.h2
12 files changed, 103 insertions, 46 deletions
diff --git a/aclocal.m4 b/aclocal.m4
index 75b3f92a..3ceb6eb6 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -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 &lt;name&gt; {
nonbroadcast|nbma|pointomultipoint|ptmp];
strict nonbroadcast &lt;switch&gt;;
real broadcast &lt;switch&gt;;
+ ptp netmask &lt;switch&gt;;
check link &lt;switch&gt;;
ecmp weight &lt;num&gt;;
authentication [none|simple|cryptographic];
@@ -2184,6 +2190,18 @@ protocol ospf &lt;name&gt; {
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 &lt;name&gt; {
<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;