Hi,

I want to bring this question up again. In our company we use it in
production with patches, but I think it would be useful in upstream
version too.
Short version of the story: bird can try to bind socket when
IP-address is absent in the system, it will result in a error and the
protocol will remain in down state after that. Suggested change is to
allow it to bind non-local addresses.
First, lets start with just the flag in the socket interface. I
adapted the patch, now system-dependend code is in a separate function
sk_set_freebind(), which is defined in sysdep/X/sysio.h, as it was
suggested.
If this variant is OK, than the next step is to choose wether it would
be some configuration option or maybe a compile-time flag.

On Thu, Jan 23, 2020 at 11:05 PM Alexander Zubkov <gr...@qrator.net> wrote:
>
> On Thu, Jan 23, 2020 at 5:21 PM Ondrej Zajicek <santi...@crfreenet.org> wrote:
> >
> > On Wed, Jan 15, 2020 at 01:57:19AM +0100, Alexander Zubkov wrote:
> > > Hi,
> > >
> > > Check the attached patches. The first adds option to sockets to use
> > > nonlocal bind (IP_FREEBIND in Linux) and the second adds bgp option to
> > > use such sockets ("nonlocal bind yes|no"). Some additional thoughts:
> > > - probably the option could be implemented for any protocol, not only for 
> > > bgp
> > > ...
> > > - it can be also considered to enable nonlocal bind for all bgp
> > > unconditionally, at least I see no obvious problems yet
> >
> > Hi
> >
> > Is there a reason for such option? Is there a downside of using it always?
>
> If I remember right, when address is not available during bind, in
> strict bind mode bird logs en error and puts protocol down. It is
> inconvenient when one uses VRRP, for example, with migrating address.
> Or there could be some problems during applying some configuration
> changes to the interfaces in the system. We use this socket option
> with VRRP and also we have interfaces without ip addresses configured
> yet for some reason.
> I do not know if using it always-on is a good idea or not. We made it
> always-on in our setup and are just happy with it. But I'm not sure if
> it does not break something somewhere. It will make at least bird's
> behaviour different on different systems with the same config and that
> may be confusing. On the other hand, the extra option to put in config
> may be unreasonable payment.
> I also not tested how it will behave if ip address migrates from one
> interface to the other in the system. If it ties to the interfaces
> somehow and because of this option does not mention the change, that
> could be a problem.
>
> >
> > One minor nitpick is that sysdep/unix/io.c should not use non-portable
> > syscalls/sockopts directly, they should be defined as functions in
> > sysdep/X/sysio.h (with implementations for Linux and BSD) and such
> > function called from sysdep/unix/io.c code.
>
> Probably you are right, it might be somewhere there if it would end
> into the vanilla bird.
>
> >
> > --
> > Elen sila lumenn' omentielvo
> >
> > Ondrej 'Santiago' Zajicek (email: santi...@crfreenet.org)
> > OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net)
> > "To err is human -- to blame it on a computer is even more so."
commit 3ed4532cf7b652adb14336ca4a611a49cfe3b262
Author: Alexander Zubkov <gr...@qrator.net>
Date:   Tue Dec 28 18:16:33 2021 +0100

    IO: Support nonlocal bind in socket interface
    
    Add option to socket interface for nonlocal binding, i.e. binding an IP
    address, that is not present on the interfaces. This behaviour is
    enabled when SKF_FREEBIND socket flag is set.
    It is now implemented for Linux system only with IP_FREEBIND socket flag.

diff --git a/lib/socket.h b/lib/socket.h
index 96fedeeb..0b6ac589 100644
--- a/lib/socket.h
+++ b/lib/socket.h
@@ -123,6 +123,7 @@ extern int sk_priority_control;		/* Suggested priority for control traffic, shou
 #define SKF_TTL_RX	0x08	/* Report TTL / Hop Limit for RX packets */
 #define SKF_BIND	0x10	/* Bind datagram socket to given source address */
 #define SKF_HIGH_PORT	0x20	/* Choose port from high range if possible */
+#define SKF_FREEBIND	0x40	/* Allow socket to bind to a nonlocal address */
 
 #define SKF_THREAD	0x100	/* Socked used in thread, Do not add to main loop */
 #define SKF_TRUNCATED	0x200	/* Received packet was truncated, set by IO layer */
diff --git a/sysdep/bsd/sysio.h b/sysdep/bsd/sysio.h
index c757960a..2ae03aae 100644
--- a/sysdep/bsd/sysio.h
+++ b/sysdep/bsd/sysio.h
@@ -271,3 +271,11 @@ sk_set_priority(sock *s, int prio UNUSED)
 {
   ERR_MSG("Socket priority not supported");
 }
+
+static inline int
+sk_set_freebind(sock *s)
+{
+  ERR("IP free bind is not implemented");
+
+  return 0;
+}
diff --git a/sysdep/linux/sysio.h b/sysdep/linux/sysio.h
index e21ff487..a55b5c2a 100644
--- a/sysdep/linux/sysio.h
+++ b/sysdep/linux/sysio.h
@@ -266,3 +266,16 @@ sk_set_priority(sock *s, int prio)
   return 0;
 }
 
+static inline int
+sk_set_freebind(sock *s)
+{
+#ifdef IP_FREEBIND
+  int y = 1;
+  if (setsockopt(s->fd, SOL_IP, IP_FREEBIND, &y, sizeof(y)) < 0)
+    ERR("IP_FREEBIND");
+#else
+  ERR("IP_FREEBIND is not supported");
+#endif
+
+  return 0;
+}
diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c
index 3d67d0a7..4fd77453 100644
--- a/sysdep/unix/io.c
+++ b/sysdep/unix/io.c
@@ -1436,6 +1436,10 @@ sk_open(sock *s)
 	if (sk_set_high_port(s) < 0)
 	  log(L_WARN "Socket error: %s%#m", s->err);
 
+    if (s->flags & SKF_FREEBIND)
+      if (sk_set_freebind(s) < 0)
+        log(L_WARN "Socket error: %s%#m", s->err);
+
     sockaddr_fill(&sa, s->af, bind_addr, s->iface, bind_port);
     if (bind(fd, &sa.sa, SA_LEN(sa)) < 0)
       ERR2("bind");

Reply via email to