udp_sock_create creates a UDP socket and binds it according to udp_port_cfg. Add a freebind option to udp_port_cfg that allows a socket to be bound as though IP_FREEBIND is set. This change is required for binding vxlan sockets to their local address when the outgoing interface is down. Signed-off-by: Richard Gobert --- include/net/udp_tunnel.h | 3 ++- net/ipv4/udp_tunnel_core.c | 1 + net/ipv6/ip6_udp_tunnel.c | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h index 9acef2fbd2fd..6c1362aa3576 100644 --- a/include/net/udp_tunnel.h +++ b/include/net/udp_tunnel.h @@ -34,7 +34,8 @@ struct udp_port_cfg { unsigned int use_udp_checksums:1, use_udp6_tx_checksums:1, use_udp6_rx_checksums:1, - ipv6_v6only:1; + ipv6_v6only:1, + freebind:1; }; int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg, diff --git a/net/ipv4/udp_tunnel_core.c b/net/ipv4/udp_tunnel_core.c index fce945f23069..147fd8ff4f49 100644 --- a/net/ipv4/udp_tunnel_core.c +++ b/net/ipv4/udp_tunnel_core.c @@ -28,6 +28,7 @@ int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg, udp_addr.sin_family = AF_INET; udp_addr.sin_addr = cfg->local_ip; udp_addr.sin_port = cfg->local_udp_port; + inet_assign_bit(FREEBIND, sock->sk, cfg->freebind); err = kernel_bind(sock, (struct sockaddr *)&udp_addr, sizeof(udp_addr)); if (err < 0) diff --git a/net/ipv6/ip6_udp_tunnel.c b/net/ipv6/ip6_udp_tunnel.c index 0ff547a4bff7..65ff44c274b8 100644 --- a/net/ipv6/ip6_udp_tunnel.c +++ b/net/ipv6/ip6_udp_tunnel.c @@ -40,6 +40,7 @@ int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg, memcpy(&udp6_addr.sin6_addr, &cfg->local_ip6, sizeof(udp6_addr.sin6_addr)); udp6_addr.sin6_port = cfg->local_udp_port; + inet_assign_bit(FREEBIND, sock->sk, cfg->freebind); err = kernel_bind(sock, (struct sockaddr *)&udp6_addr, sizeof(udp6_addr)); if (err < 0) -- 2.36.1