From 87a02489f3880689a4e2ad72b0b981649dad2154 Mon Sep 17 00:00:00 2001 From: Alexander Zubkov Date: Sat, 8 Jan 2022 18:31:56 +0100 Subject: [PATCH 1/8] IO: Support nonlocal bind in socket interface Add option to socket interface for nonlocal binding, i.e. binding to an IP address that is not present on interfaces. This behaviour is enabled when SKF_FREEBIND socket flag is set. For Linux systems, it is implemented by IP_FREEBIND socket flag. Minor changes done by commiter. --- lib/socket.h | 1 + sysdep/bsd/sysio.h | 6 ++++++ sysdep/linux/sysio.h | 19 +++++++++++++++++++ sysdep/unix/io.c | 4 ++++ 4 files changed, 30 insertions(+) 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..f1887fb4 100644 --- a/sysdep/bsd/sysio.h +++ b/sysdep/bsd/sysio.h @@ -271,3 +271,9 @@ sk_set_priority(sock *s, int prio UNUSED) { ERR_MSG("Socket priority not supported"); } + +static inline int +sk_set_freebind(sock *s) +{ + ERR_MSG("Freebind is not supported"); +} diff --git a/sysdep/linux/sysio.h b/sysdep/linux/sysio.h index e21ff487..f13eda7c 100644 --- a/sysdep/linux/sysio.h +++ b/sysdep/linux/sysio.h @@ -10,6 +10,10 @@ #define IPV6_MINHOPCOUNT 73 #endif +#ifndef IPV6_FREEBIND +#define IPV6_FREEBIND 78 +#endif + #ifndef TCP_MD5SIG_EXT #define TCP_MD5SIG_EXT 32 #endif @@ -266,3 +270,18 @@ sk_set_priority(sock *s, int prio) return 0; } +static inline int +sk_set_freebind(sock *s) +{ + int y = 1; + + if (sk_is_ipv4(s)) + if (setsockopt(s->fd, SOL_IP, IP_FREEBIND, &y, sizeof(y)) < 0) + ERR("IP_FREEBIND"); + + if (sk_is_ipv6(s)) + if (setsockopt(s->fd, SOL_IPV6, IPV6_FREEBIND, &y, sizeof(y)) < 0) + ERR("IPV6_FREEBIND"); + + 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"); From 60e9def9ef7b5d16f868b0fb4ab1192d59fd7541 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Sun, 9 Jan 2022 02:40:58 +0100 Subject: [PATCH 2/8] BGP: Add option 'free bind' 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 | 6 ++++++ proto/bgp/bgp.c | 11 ++++++++--- proto/bgp/bgp.h | 1 + proto/bgp/config.Y | 3 ++- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/doc/bird.sgml b/doc/bird.sgml index a63493da..0112622e 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -2412,6 +2412,12 @@ using the following configuration parameters: same address family and using the same local port) should have set