]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
BGP: Add option 'free bind'
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Sun, 9 Jan 2022 01:40:58 +0000 (02:40 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Sun, 9 Jan 2022 01:44:32 +0000 (02:44 +0100)
The BGP 'free bind' option applies the IP_FREEBIND/IPV6_FREEBIND
socket option for the BGP listening socket.

Thanks to Alexander Zubkov for the idea.

doc/bird.sgml
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/bgp/config.Y

index a63493da1d8d5a5f48180b435bc8231dcf349632..0112622e8bc1f5a0d90503f352750c19f344bcda 100644 (file)
@@ -2412,6 +2412,12 @@ using the following configuration parameters:
        same address family and using the same local port) should have set
        <cf/strict bind/, or none of them. Default: disabled.
 
+       <tag><label id="bgp-free-bind">free bind <m/switch/</tag>
+       Use IP_FREEBIND socket option for the listening socket, which allows
+       binding to an IP address not (yet) assigned to an interface. Note that
+       all BGP instances that share a listening socket should have the same
+       value of the <cf/freebind/ option. Default: disabled.
+
        <tag><label id="bgp-check-link">check link <M>switch</M></tag>
        BGP could use hardware link state into consideration.  If enabled,
        BIRD tracks the link state of the associated interface and when link
index e4d754b1af5e7228f2275da3bf19b5ec6e442473..b6f21bc66ba4d8bbe26f2dca556873c10f7ce3fb 100644 (file)
@@ -157,6 +157,8 @@ bgp_open(struct bgp_proto *p)
   ip_addr addr = p->cf->strict_bind ? p->cf->local_ip :
     (p->ipv4 ? IPA_NONE4 : IPA_NONE6);
   uint port = p->cf->local_port;
+  uint flags = p->cf->free_bind ? SKF_FREEBIND : 0;
+  uint flag_mask = SKF_FREEBIND;
 
   /* FIXME: Add some global init? */
   if (!bgp_linpool)
@@ -165,8 +167,11 @@ bgp_open(struct bgp_proto *p)
   /* We assume that cf->iface is defined iff cf->local_ip is link-local */
 
   WALK_LIST(bs, bgp_sockets)
-    if (ipa_equal(bs->sk->saddr, addr) && (bs->sk->sport == port) &&
-       (bs->sk->iface == ifa) && (bs->sk->vrf == p->p.vrf))
+    if (ipa_equal(bs->sk->saddr, addr) &&
+       (bs->sk->sport == port) &&
+       (bs->sk->iface == ifa) &&
+       (bs->sk->vrf == p->p.vrf) &&
+       ((bs->sk->flags & flag_mask) == flags))
     {
       bs->uc++;
       p->sock = bs;
@@ -180,7 +185,7 @@ bgp_open(struct bgp_proto *p)
   sk->sport = port;
   sk->iface = ifa;
   sk->vrf = p->p.vrf;
-  sk->flags = 0;
+  sk->flags = flags;
   sk->tos = IP_PREC_INTERNET_CONTROL;
   sk->rbsize = BGP_RX_BUFFER_SIZE;
   sk->tbsize = BGP_TX_BUFFER_SIZE;
index cca4b4482dc04627e097f82dfbd9200ad3e9ff7b..5e025ccd2594bc2044ea725f4f134b92ce38cdc3 100644 (file)
@@ -86,6 +86,7 @@ struct bgp_config {
   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 free_bind;                       /* Bind listening socket with SKF_FREEBIND */
   int ttl_security;                    /* Enable TTL security [RFC 5082] */
   int compare_path_lengths;            /* Use path lengths when selecting best route */
   int med_metric;                      /* Compare MULTI_EXIT_DISC even between routes from differen ASes */
index 2dfbdca9bc92f5d63114bd8762c1a1ef540bfe59..7cbc9985fdc00e4464935563bc80e0f34cb60876 100644 (file)
@@ -31,7 +31,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE,
        STRICT, BIND, CONFEDERATION, MEMBER, MULTICAST, FLOW4, FLOW6, LONG,
        LIVED, STALE, IMPORT, IBGP, EBGP, MANDATORY, INTERNAL, EXTERNAL, SETS,
        DYNAMIC, RANGE, NAME, DIGITS, BGP_AIGP, AIGP, ORIGINATE, COST, ENFORCE,
-       FIRST)
+       FIRST, FREE)
 
 %type <i> bgp_nh
 %type <i32> bgp_afi
@@ -155,6 +155,7 @@ bgp_proto:
    }
  | bgp_proto DYNAMIC NAME DIGITS expr ';' { BGP_CFG->dynamic_name_digits = $5; if ($5>10) cf_error("Dynamic name digits must be at most 10"); }
  | bgp_proto STRICT BIND bool ';' { BGP_CFG->strict_bind = $4; }
+ | bgp_proto FREE BIND bool ';' { BGP_CFG->free_bind = $4; }
  | bgp_proto PATH METRIC bool ';' { BGP_CFG->compare_path_lengths = $4; }
  | bgp_proto MED METRIC bool ';' { BGP_CFG->med_metric = $4; }
  | bgp_proto IGP METRIC bool ';' { BGP_CFG->igp_metric = $4; }