Commit b0a01afc authored by Dan Melnic's avatar Dan Melnic Committed by Facebook GitHub Bot

Add support for AsyncUDPSocket SO_BINDTODEVICE

Summary: Add support for AsyncUDPSocket SO_BINDTODEVICE

Reviewed By: danobi

Differential Revision: D28100917

fbshipit-source-id: bcc66d943342cbd40b634ef095eccf3e599fcb65
parent 4e7efffd
...@@ -116,7 +116,8 @@ class AsyncUDPServerSocket : private AsyncUDPSocket::ReadCallback, ...@@ -116,7 +116,8 @@ class AsyncUDPServerSocket : private AsyncUDPSocket::ReadCallback,
void bind( void bind(
const folly::SocketAddress& addy, const folly::SocketAddress& addy,
const SocketOptionMap& options = emptySocketOptionMap) { const SocketOptionMap& options = emptySocketOptionMap,
const std::string& ifName = "") {
CHECK(!socket_); CHECK(!socket_);
socket_ = std::make_shared<AsyncUDPSocket>(evb_); socket_ = std::make_shared<AsyncUDPSocket>(evb_);
...@@ -126,7 +127,14 @@ class AsyncUDPServerSocket : private AsyncUDPSocket::ReadCallback, ...@@ -126,7 +127,14 @@ class AsyncUDPServerSocket : private AsyncUDPSocket::ReadCallback,
validateSocketOptions( validateSocketOptions(
options, addy.getFamily(), SocketOptionKey::ApplyPos::PRE_BIND), options, addy.getFamily(), SocketOptionKey::ApplyPos::PRE_BIND),
SocketOptionKey::ApplyPos::PRE_BIND); SocketOptionKey::ApplyPos::PRE_BIND);
#ifdef FOLLY_HAVE_BIND_OPTIONS_IFNAME
AsyncUDPSocket::BindOptions bindOptions;
bindOptions.ifName = ifName;
socket_->bind(addy, bindOptions);
#else
(void)ifName;
socket_->bind(addy); socket_->bind(addy);
#endif
socket_->applyOptions( socket_->applyOptions(
validateSocketOptions( validateSocketOptions(
options, addy.getFamily(), SocketOptionKey::ApplyPos::POST_BIND), options, addy.getFamily(), SocketOptionKey::ApplyPos::POST_BIND),
......
...@@ -207,6 +207,23 @@ void AsyncUDPSocket::bind( ...@@ -207,6 +207,23 @@ void AsyncUDPSocket::bind(
const folly::SocketAddress& address, BindOptions bindOptions) { const folly::SocketAddress& address, BindOptions bindOptions) {
init(address.getFamily(), bindOptions); init(address.getFamily(), bindOptions);
// bind the socket to the interface
#ifdef FOLLY_HAVE_BIND_OPTIONS_IFNAME
if (!bindOptions.ifName.empty() &&
netops::setsockopt(
fd_,
SOL_SOCKET,
SO_BINDTODEVICE,
bindOptions.ifName.c_str(),
bindOptions.ifName.length())) {
auto errnoCopy = errno;
throw AsyncSocketException(
AsyncSocketException::NOT_OPEN,
"failed to bind to device: " + bindOptions.ifName,
errnoCopy);
}
#endif
// bind to the address // bind to the address
sockaddr_storage addrStorage; sockaddr_storage addrStorage;
address.getAddress(&addrStorage); address.getAddress(&addrStorage);
......
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
#include <folly/net/NetOps.h> #include <folly/net/NetOps.h>
#include <folly/net/NetworkSocket.h> #include <folly/net/NetworkSocket.h>
#if defined(__linux__) && !FOLLY_MOBILE
#define FOLLY_HAVE_BIND_OPTIONS_IFNAME
#endif
namespace folly { namespace folly {
/** /**
...@@ -170,9 +174,12 @@ class AsyncUDPSocket : public EventHandler { ...@@ -170,9 +174,12 @@ class AsyncUDPSocket : public EventHandler {
* Contains options to pass to bind. * Contains options to pass to bind.
*/ */
struct BindOptions { struct BindOptions {
constexpr BindOptions() noexcept {} BindOptions() noexcept {}
// Whether IPV6_ONLY should be set on the socket. // Whether IPV6_ONLY should be set on the socket.
bool bindV6Only{true}; bool bindV6Only{true};
#ifdef FOLLY_HAVE_BIND_OPTIONS_IFNAME
std::string ifName;
#endif
}; };
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment