<cf/local 10.0.0.1; local as 65000;/ are valid). This parameter is
mandatory.
- <tag><label id="bgp-neighbor">neighbor [<m/ip/] [port <m/number/] [as <m/number/]</tag>
+ <tag><label id="bgp-neighbor">neighbor [<m/ip/] [port <m/number/] [as <m/number/] [internal|external]</tag>
Define neighboring router this instance will be talking to and what AS
it is located in. In case the neighbor is in the same AS as we are, we
- automatically switch to iBGP. Optionally, the remote port may also be
- specified. Like <cf/local/ parameter, this parameter may also be used
- multiple times with different sub-options. This parameter is mandatory.
+ automatically switch to IBGP. Alternatively, it is possible to specify
+ just <cf/internal/ or </cf/external/ instead of AS number, in that case
+ either local AS number, or any external AS number is accepted.
+ Optionally, the remote port may also be specified. Like <cf/local/
+ parameter, this parameter may also be used multiple times with different
+ sub-options. This parameter is mandatory.
<tag><label id="bgp-iface">interface <m/string/</tag>
Define interface we should use for link-local BGP IPv6 sessions.
if (ipa_zero(p->local_ip))
p->local_ip = conn->sk->saddr;
+ /* For promiscuous sessions */
+ if (!p->remote_as)
+ p->remote_as = conn->received_as;
+
/* In case of LLv6 is not valid during BGP start */
if (ipa_zero(p->link_addr) && p->neigh && p->neigh->iface && p->neigh->iface->llv6)
p->link_addr = p->neigh->iface->llv6->ip;
bgp_postconfig(struct proto_config *CF)
{
struct bgp_config *cf = (void *) CF;
- int internal = (cf->local_as == cf->remote_as);
- int interior = internal || cf->confederation_member;
/* Do not check templates at all */
if (cf->c.class == SYM_TEMPLATE)
return;
+ /* Handle undefined remote_as, zero should mean unspecified external */
+ if (!cf->remote_as && (cf->peer_type == BGP_PT_INTERNAL))
+ cf->remote_as = cf->local_as;
+
+ int internal = (cf->local_as == cf->remote_as);
+ int interior = internal || cf->confederation_member;
+
/* EBGP direct by default, IBGP multihop by default */
if (cf->multihop < 0)
cf->multihop = internal ? 64 : 0;
if (ipa_zero(cf->remote_ip))
cf_error("Neighbor must be configured");
- if (!cf->remote_as)
- cf_error("Remote AS number must be set");
+ if (!cf->remote_as && !cf->peer_type)
+ cf_error("Remote AS number (or peer type) must be set");
+
+ if ((cf->peer_type == BGP_PT_INTERNAL) && !internal)
+ cf_error("IBGP cannot have different ASNs");
+
+ if ((cf->peer_type == BGP_PT_EXTERNAL) && internal)
+ cf_error("EBGP cannot have the same ASNs");
if (!cf->iface && (ipa_is_link_local(cf->local_ip) ||
ipa_is_link_local(cf->remote_ip)))
cli_msg(-1006, " BGP state: %s", bgp_state_dsc(p));
cli_msg(-1006, " Neighbor address: %I%J", p->cf->remote_ip, p->cf->iface);
- cli_msg(-1006, " Neighbor AS: %u", p->cf->remote_as);
+ cli_msg(-1006, " Neighbor AS: %u", p->cf->remote_as ?: p->remote_as);
if (p->gr_active_num)
cli_msg(-1006, " Neighbor graceful restart active");
struct iface *iface; /* Interface for link-local addresses */
u16 local_port; /* Local listening port */
u16 remote_port; /* Neighbor destination port */
+ int peer_type; /* Internal or external BGP (BGP_PT_*, optional) */
int multihop; /* Number of hops if multihop */
int strict_bind; /* Bind listening socket to local address */
int ttl_security; /* Enable TTL security [RFC 5082] */
struct rtable_config *igp_table_ip6; /* Table for recursive IPv6 next hop lookups */
};
+#define BGP_PT_INTERNAL 1
+#define BGP_PT_EXTERNAL 2
+
#define NH_NO 0
#define NH_ALL 1
#define NH_IBGP 2
u8 state; /* State of connection state machine */
u8 as4_session; /* Session uses 4B AS numbers in AS_PATH (both sides support it) */
u8 ext_messages; /* Session uses extended message length */
+ u32 received_as; /* ASN received in OPEN message */
struct bgp_caps *local_caps;
struct bgp_caps *remote_caps;
SECURITY, DETERMINISTIC, SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX,
GRACEFUL, RESTART, AWARE, CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY,
STRICT, BIND, CONFEDERATION, MEMBER, MULTICAST, FLOW4, FLOW6, LONG,
- LIVED, STALE, IMPORT, IBGP, EBGP, MANDATORY)
+ LIVED, STALE, IMPORT, IBGP, EBGP, MANDATORY, INTERNAL, EXTERNAL)
%type <i> bgp_nh
%type <i32> bgp_afi
/* empty */
| bgp_nbr_opts PORT expr { BGP_CFG->remote_port = $3; if (($3<1) || ($3>65535)) cf_error("Invalid port number"); }
| bgp_nbr_opts AS expr { BGP_CFG->remote_as = $3; }
+ | bgp_nbr_opts INTERNAL { BGP_CFG->peer_type = BGP_PT_INTERNAL; }
+ | bgp_nbr_opts EXTERNAL { BGP_CFG->peer_type = BGP_PT_EXTERNAL; }
;
bgp_cease_mask:
if ((as4 != asn) && (asn != AS_TRANS))
log(L_WARN "%s: Peer advertised inconsistent AS numbers", p->p.name);
- if (as4 != p->remote_as)
+ /* When remote ASN is unspecified, it must be external one */
+ if (p->remote_as ? (as4 != p->remote_as) : (as4 == p->local_as))
{ as4 = htonl(as4); bgp_error(conn, 2, 2, (byte *) &as4, 4); return; }
+
+ conn->received_as = as4;
}
else
{
- if (asn != p->remote_as)
+ if (p->remote_as ? (asn != p->remote_as) : (asn == p->local_as))
{ bgp_error(conn, 2, 2, pkt+20, 2); return; }
+
+ conn->received_as = asn;
}
/* Check the other connection */