diff --git a/fea/data_plane/io/io_tcpudp_dummy.cc b/fea/data_plane/io/io_tcpudp_dummy.cc index 3c9d700..4de88f0 100644 --- a/fea/data_plane/io/io_tcpudp_dummy.cc +++ b/fea/data_plane/io/io_tcpudp_dummy.cc @@ -108,12 +108,14 @@ IoTcpUdpDummy::tcp_open_and_bind(const IPvX& local_addr, uint16_t local_port, } int -IoTcpUdpDummy::udp_open_and_bind(const IPvX& local_addr, uint16_t local_port, - string& error_msg) +IoTcpUdpDummy::udp_open_and_bind(const IPvX& local_addr, uint16_t local_port, const string& local_dev, + int reuse, string& error_msg) { XLOG_ASSERT(family() == local_addr.af()); UNUSED(local_addr); + UNUSED(local_dev); + UNUSED(reuse); UNUSED(local_port); UNUSED(error_msg); diff --git a/fea/data_plane/io/io_tcpudp_dummy.hh b/fea/data_plane/io/io_tcpudp_dummy.hh index c151e87..8f65ede 100644 --- a/fea/data_plane/io/io_tcpudp_dummy.hh +++ b/fea/data_plane/io/io_tcpudp_dummy.hh @@ -105,8 +105,8 @@ public: * @param error_msg the error message (if error). * @return XORP_OK on success, otherwise XORP_ERROR. */ - int udp_open_and_bind(const IPvX& local_addr, uint16_t local_port, - string& error_msg); + int udp_open_and_bind(const IPvX& local_addr, uint16_t local_port, const string& local_dev, + int reuse, string& error_msg); /** * Create a bound UDP multicast socket. diff --git a/fea/data_plane/io/io_tcpudp_socket.cc b/fea/data_plane/io/io_tcpudp_socket.cc index ae3d42a..a188bc7 100644 --- a/fea/data_plane/io/io_tcpudp_socket.cc +++ b/fea/data_plane/io/io_tcpudp_socket.cc @@ -348,8 +348,8 @@ IoTcpUdpSocket::tcp_open_and_bind(const IPvX& local_addr, uint16_t local_port, } int -IoTcpUdpSocket::udp_open_and_bind(const IPvX& local_addr, uint16_t local_port, - string& error_msg) +IoTcpUdpSocket::udp_open_and_bind(const IPvX& local_addr, uint16_t local_port, const string& local_dev, + int reuse_addr, string& error_msg) { XLOG_ASSERT(family() == local_addr.af()); @@ -365,7 +365,20 @@ IoTcpUdpSocket::udp_open_and_bind(const IPvX& local_addr, uint16_t local_port, local_addr.copy_out(local_in_addr); _socket_fd = comm_bind_udp4(&local_in_addr, htons(local_port), - COMM_SOCK_NONBLOCKING); + COMM_SOCK_NONBLOCKING, reuse_addr); +#ifdef SO_BINDTODEVICE + if (local_dev.size()) { + if (setsockopt(_socket_fd, SOL_SOCKET, SO_BINDTODEVICE, + local_dev.c_str(), local_dev.size() + 1)) { + XLOG_WARNING("ERROR: IoTcpUdpSocket::udp_open_and_bind, setsockopt (BINDTODEVICE): failed: %s", + strerror(errno)); + } + else { + XLOG_INFO("NOTE: Successfully bound socket: %i to vif: %s\n", + (int)(_socket_fd), local_dev.c_str()); + } + } +#endif break; } #ifdef HAVE_IPV6 @@ -1248,6 +1261,7 @@ IoTcpUdpSocket::send_from_multicast_if(const IPvX& group_addr, struct in_addr ifaddr_in_addr; ifaddr.copy_out(ifaddr_in_addr); + // TODO: Not needed if we are binding to specific ports. ret_value = comm_set_iface4(_socket_fd, &ifaddr_in_addr); break; } diff --git a/fea/data_plane/io/io_tcpudp_socket.hh b/fea/data_plane/io/io_tcpudp_socket.hh index 5831908..69b4ac3 100644 --- a/fea/data_plane/io/io_tcpudp_socket.hh +++ b/fea/data_plane/io/io_tcpudp_socket.hh @@ -111,8 +111,8 @@ public: * @param error_msg the error message (if error). * @return XORP_OK on success, otherwise XORP_ERROR. */ - int udp_open_and_bind(const IPvX& local_addr, uint16_t local_port, - string& error_msg); + int udp_open_and_bind(const IPvX& local_addr, uint16_t local_port, const string& local_dev, + int reuse, string& error_msg); /** * Create a bound UDP multicast socket. diff --git a/fea/io_tcpudp.hh b/fea/io_tcpudp.hh index 446275b..0a59dc5 100644 --- a/fea/io_tcpudp.hh +++ b/fea/io_tcpudp.hh @@ -183,8 +183,8 @@ public: * @param error_msg the error message (if error). * @return XORP_OK on success, otherwise XORP_ERROR. */ - virtual int udp_open_and_bind(const IPvX& local_addr, uint16_t local_port, - string& error_msg) = 0; + virtual int udp_open_and_bind(const IPvX& local_addr, uint16_t local_port, const string& local_dev, + int reuse, string& error_msg) = 0; /** * Create a bound UDP multicast socket. diff --git a/fea/io_tcpudp_manager.cc b/fea/io_tcpudp_manager.cc index 9f1d611..bac0a6c 100644 --- a/fea/io_tcpudp_manager.cc +++ b/fea/io_tcpudp_manager.cc @@ -171,6 +171,7 @@ IoTcpUdpComm::tcp_open_and_bind(const IPvX& local_addr, uint16_t local_port, int IoTcpUdpComm::udp_open_and_bind(const IPvX& local_addr, uint16_t local_port, + const string& local_dev, int reuse, string& sockid, string& error_msg) { int ret_value = XORP_OK; @@ -188,7 +189,7 @@ IoTcpUdpComm::udp_open_and_bind(const IPvX& local_addr, uint16_t local_port, iter != _io_tcpudp_plugins.end(); ++iter) { IoTcpUdp* io_tcpudp = iter->second; - if (io_tcpudp->udp_open_and_bind(local_addr, local_port, error_msg2) + if (io_tcpudp->udp_open_and_bind(local_addr, local_port, local_dev, reuse, error_msg2) != XORP_OK) { ret_value = XORP_ERROR; if (! error_msg.empty()) @@ -1261,6 +1262,7 @@ IoTcpUdpManager::tcp_open_and_bind(int family, const string& creator, int IoTcpUdpManager::udp_open_and_bind(int family, const string& creator, const IPvX& local_addr, uint16_t local_port, + const string& local_dev, int reuse, string& sockid, string& error_msg) { IoTcpUdpComm* io_tcpudp_comm; @@ -1280,7 +1282,7 @@ IoTcpUdpManager::udp_open_and_bind(int family, const string& creator, io_tcpudp_comm = open_io_tcpudp_comm(family, false, creator); XLOG_ASSERT(io_tcpudp_comm != NULL); - if (io_tcpudp_comm->udp_open_and_bind(local_addr, local_port, sockid, + if (io_tcpudp_comm->udp_open_and_bind(local_addr, local_port, local_dev, reuse, sockid, error_msg) != XORP_OK) { delete_io_tcpudp_comm(family, io_tcpudp_comm->sockid()); diff --git a/fea/io_tcpudp_manager.hh b/fea/io_tcpudp_manager.hh index 19ce7d5..bf80985 100644 --- a/fea/io_tcpudp_manager.hh +++ b/fea/io_tcpudp_manager.hh @@ -231,7 +231,7 @@ public: * @return XORP_OK on success, otherwise XORP_ERROR. */ int udp_open_and_bind(const IPvX& local_addr, uint16_t local_port, - string& sockid, string& error_msg); + const string& local_dev, int reuse, string& sockid, string& error_msg); /** * Create a bound UDP multicast socket. @@ -738,6 +738,7 @@ public: */ int udp_open_and_bind(int family, const string& creator, const IPvX& local_addr, uint16_t local_port, + const string& local_dev, int reuse, string& sockid, string& error_msg); /** diff --git a/fea/xorp_fea.cc b/fea/xorp_fea.cc index 4bf1d06..0ea8109 100644 --- a/fea/xorp_fea.cc +++ b/fea/xorp_fea.cc @@ -131,6 +131,7 @@ main(int argc, char *argv[]) xlog_set_verbose(XLOG_VERBOSE_LOW); // Least verbose messages // XXX: verbosity of the error messages temporary increased xlog_level_set_verbose(XLOG_LEVEL_ERROR, XLOG_VERBOSE_HIGH); + //xlog_enable(XLOG_LEVEL_INFO); Doesn't work? --Ben xlog_add_default_output(); xlog_start(); diff --git a/fea/xrl_fea_target.cc b/fea/xrl_fea_target.cc index cb08c6a..4bd3f15 100644 --- a/fea/xrl_fea_target.cc +++ b/fea/xrl_fea_target.cc @@ -3820,6 +3820,8 @@ XrlFeaTarget::socket4_0_1_udp_open_and_bind( const string& creator, const IPv4& local_addr, const uint32_t& local_port, + const string& local_dev, + const uint32_t& reuse, // Output values, string& sockid) { @@ -3832,6 +3834,7 @@ XrlFeaTarget::socket4_0_1_udp_open_and_bind( if (_io_tcpudp_manager.udp_open_and_bind(IPv4::af(), creator, IPvX(local_addr), local_port, + local_dev, reuse, sockid, error_msg) != XORP_OK) { return XrlCmdError::COMMAND_FAILED(error_msg); @@ -4258,6 +4261,8 @@ XrlFeaTarget::socket6_0_1_udp_open_and_bind( const string& creator, const IPv6& local_addr, const uint32_t& local_port, + const string& local_dev, + const uint32_t& reuse, // Output values, string& sockid) { @@ -4270,6 +4275,7 @@ XrlFeaTarget::socket6_0_1_udp_open_and_bind( if (_io_tcpudp_manager.udp_open_and_bind(IPv6::af(), creator, IPvX(local_addr), local_port, + local_dev, reuse, sockid, error_msg) != XORP_OK) { return XrlCmdError::COMMAND_FAILED(error_msg); diff --git a/fea/xrl_fea_target.hh b/fea/xrl_fea_target.hh index c4f77da..5dda687 100644 --- a/fea/xrl_fea_target.hh +++ b/fea/xrl_fea_target.hh @@ -2047,6 +2047,8 @@ public: const string& creator, const IPv4& local_addr, const uint32_t& local_port, + const string& local_dev, + const uint32_t& reuse, // Output values, string& sockid); @@ -2424,6 +2426,8 @@ public: const string& creator, const IPv6& local_addr, const uint32_t& local_port, + const string& local_dev, + const uint32_t& reuse, // Output values, string& sockid); diff --git a/libcomm/comm_api.h b/libcomm/comm_api.h index e43b289..cfa7c4f 100644 --- a/libcomm/comm_api.h +++ b/libcomm/comm_api.h @@ -270,7 +270,8 @@ extern xsock_t comm_bind_tcp(const struct sockaddr *sin, int is_blocking); * @return the new socket on success, otherwise XORP_BAD_SOCKET. */ extern xsock_t comm_bind_udp4(const struct in_addr *my_addr, - unsigned short my_port, int is_blocking); + unsigned short my_port, int is_blocking, + int reuse_flag); /** * Open an IPv6 UDP socket and bind it to a local address and a port. diff --git a/libcomm/comm_user.c b/libcomm/comm_user.c index a67703f..2118ce6 100644 --- a/libcomm/comm_user.c +++ b/libcomm/comm_user.c @@ -310,7 +310,7 @@ comm_bind_tcp(const struct sockaddr *sock, int is_blocking) xsock_t comm_bind_udp4(const struct in_addr *my_addr, unsigned short my_port, - int is_blocking) + int is_blocking, int reuse_flag) { xsock_t sock; @@ -318,6 +318,21 @@ comm_bind_udp4(const struct in_addr *my_addr, unsigned short my_port, sock = comm_sock_open(AF_INET, SOCK_DGRAM, 0, is_blocking); if (sock == XORP_BAD_SOCKET) return (XORP_BAD_SOCKET); + + /* For multicast, you need to set reuse before you bind, if you want + * more than one socket to be able to bind to a particular IP (like, 0.0.0.0) + */ + if (reuse_flag) { + if (comm_set_reuseaddr(sock, 1) != XORP_OK) { + comm_sock_close(sock); + return (XORP_BAD_SOCKET); + } + if (comm_set_reuseport(sock, 1) != XORP_OK) { + comm_sock_close(sock); + return (XORP_BAD_SOCKET); + } + } + if (comm_sock_bind4(sock, my_addr, my_port) != XORP_OK) { comm_sock_close(sock); return (XORP_BAD_SOCKET); diff --git a/libxipc/xrl_pf_sudp.cc b/libxipc/xrl_pf_sudp.cc index c09e981..b0ff96c 100644 --- a/libxipc/xrl_pf_sudp.cc +++ b/libxipc/xrl_pf_sudp.cc @@ -467,7 +467,7 @@ XrlPFSUDPListener::XrlPFSUDPListener(EventLoop& e, XrlDispatcher* xr) in_addr myaddr = get_preferred_ipv4_addr(); - _sock = comm_bind_udp4(&myaddr, 0, COMM_SOCK_NONBLOCKING); + _sock = comm_bind_udp4(&myaddr, 0, COMM_SOCK_NONBLOCKING, false); if (!_sock.is_valid()) { xorp_throw(XrlPFConstructorError, c_format("Could not allocate listening IP socket: %s.", diff --git a/rip/xrl_port_io.cc b/rip/xrl_port_io.cc index d082f4f..6ad0c54 100644 --- a/rip/xrl_port_io.cc +++ b/rip/xrl_port_io.cc @@ -85,10 +85,10 @@ XrlPortIO::request_open_bind_socket() { XrlSocket4V0p1Client cl(&_xr); return cl.send_udp_open_and_bind( - _ss.c_str(), _xr.instance_name(), IPv4::ANY(), - RIP_AF_CONSTANTS::IP_PORT, - callback(this, &XrlPortIO::open_bind_socket_cb) - ); + _ss.c_str(), _xr.instance_name(), IPv4::ANY(), + RIP_AF_CONSTANTS::IP_PORT, vifname(), 1, + callback(this, &XrlPortIO::open_bind_socket_cb) + ); } template <> @@ -188,10 +188,10 @@ XrlPortIO::request_open_bind_socket() { XrlSocket6V0p1Client cl(&_xr); return cl.send_udp_open_and_bind( - _ss.c_str(), _xr.instance_name(), IPv6::ANY(), - RIP_AF_CONSTANTS::IP_PORT, - callback(this, &XrlPortIO::open_bind_socket_cb) - ); + _ss.c_str(), _xr.instance_name(), IPv6::ANY(), + RIP_AF_CONSTANTS::IP_PORT, vifname(), 1, + callback(this, &XrlPortIO::open_bind_socket_cb) + ); } template <> @@ -342,8 +342,7 @@ XrlPortIO::startup_socket() { _ss = xrl_fea_name(); - _sid = socket_manager.sockid(_ss); - if (_sid == SocketManager::no_entry) { + if (_sid.size() == 0) { // Nobody has created the RIP socket yet do it! // If we succeed here the path is: // request_open_bind_socket() diff --git a/xrl/interfaces/socket4.xif b/xrl/interfaces/socket4.xif index 4191c70..2248015 100644 --- a/xrl/interfaces/socket4.xif +++ b/xrl/interfaces/socket4.xif @@ -73,6 +73,8 @@ interface socket4/0.1 { udp_open_and_bind ? creator:txt \ & local_addr:ipv4 \ & local_port:u32 \ + & local_dev:txt \ + & reuse:u32 \ -> sockid:txt /** diff --git a/xrl/interfaces/socket4_xif.cc b/xrl/interfaces/socket4_xif.cc index 968dbfe..688208a 100644 --- a/xrl/interfaces/socket4_xif.cc +++ b/xrl/interfaces/socket4_xif.cc @@ -171,6 +171,8 @@ XrlSocket4V0p1Client::send_udp_open_and_bind( const string& creator, const IPv4& local_addr, const uint32_t& local_port, + const string& local_dev, + const uint32_t& reuse, const UdpOpenAndBindCB& cb ) { @@ -181,6 +183,8 @@ XrlSocket4V0p1Client::send_udp_open_and_bind( x->args().add(XrlAtom(creator)); x->args().add(XrlAtom(local_addr)); x->args().add(XrlAtom(local_port)); + x->args().add(XrlAtom(local_dev)); + x->args().add(XrlAtom(reuse)); } x->set_target(dst_xrl_target_name); @@ -188,6 +192,8 @@ XrlSocket4V0p1Client::send_udp_open_and_bind( x->args().set_arg(0, creator); x->args().set_arg(1, local_addr); x->args().set_arg(2, local_port); + x->args().set_arg(3, local_dev); + x->args().set_arg(4, reuse); return _sender->send(*x, callback(this, &XrlSocket4V0p1Client::unmarshall_udp_open_and_bind, cb)); } diff --git a/xrl/interfaces/socket4_xif.hh b/xrl/interfaces/socket4_xif.hh index d3c9d47..1f1e03f 100644 --- a/xrl/interfaces/socket4_xif.hh +++ b/xrl/interfaces/socket4_xif.hh @@ -106,6 +106,8 @@ public: const string& creator, const IPv4& local_addr, const uint32_t& local_port, + const string& local_dev, + const uint32_t& reuse, const UdpOpenAndBindCB& cb ); diff --git a/xrl/interfaces/socket6.xif b/xrl/interfaces/socket6.xif index 396b3e6..cb310dd 100644 --- a/xrl/interfaces/socket6.xif +++ b/xrl/interfaces/socket6.xif @@ -73,6 +73,8 @@ interface socket6/0.1 { udp_open_and_bind ? creator:txt \ & local_addr:ipv6 \ & local_port:u32 \ + & local_dev:txt \ + & reuse:u32 \ -> sockid:txt /** diff --git a/xrl/interfaces/socket6_xif.cc b/xrl/interfaces/socket6_xif.cc index 89e825f..aa05c89 100644 --- a/xrl/interfaces/socket6_xif.cc +++ b/xrl/interfaces/socket6_xif.cc @@ -171,6 +171,8 @@ XrlSocket6V0p1Client::send_udp_open_and_bind( const string& creator, const IPv6& local_addr, const uint32_t& local_port, + const string& local_dev, + const uint32_t& reuse, const UdpOpenAndBindCB& cb ) { @@ -181,6 +183,8 @@ XrlSocket6V0p1Client::send_udp_open_and_bind( x->args().add(XrlAtom(creator)); x->args().add(XrlAtom(local_addr)); x->args().add(XrlAtom(local_port)); + x->args().add(XrlAtom(local_dev)); + x->args().add(XrlAtom(reuse)); } x->set_target(dst_xrl_target_name); @@ -188,6 +192,8 @@ XrlSocket6V0p1Client::send_udp_open_and_bind( x->args().set_arg(0, creator); x->args().set_arg(1, local_addr); x->args().set_arg(2, local_port); + x->args().set_arg(3, local_dev); + x->args().set_arg(4, reuse); return _sender->send(*x, callback(this, &XrlSocket6V0p1Client::unmarshall_udp_open_and_bind, cb)); } diff --git a/xrl/interfaces/socket6_xif.hh b/xrl/interfaces/socket6_xif.hh index 52baf66..c476ff6 100644 --- a/xrl/interfaces/socket6_xif.hh +++ b/xrl/interfaces/socket6_xif.hh @@ -106,6 +106,8 @@ public: const string& creator, const IPv6& local_addr, const uint32_t& local_port, + const string& local_dev, + const uint32_t& reuse, const UdpOpenAndBindCB& cb ); diff --git a/xrl/targets/fea.xrls b/xrl/targets/fea.xrls index 299e3b5..c75ae48 100644 --- a/xrl/targets/fea.xrls +++ b/xrl/targets/fea.xrls @@ -1327,7 +1327,7 @@ finder://fea/socket4/0.1/tcp_open_and_bind?creator:txt&local_addr:ipv4&local_por * @param sockid return parameter that contains unique socket ID when socket * instantiation is successful. */ -finder://fea/socket4/0.1/udp_open_and_bind?creator:txt&local_addr:ipv4&local_port:u32->sockid:txt +finder://fea/socket4/0.1/udp_open_and_bind?creator:txt&local_addr:ipv4&local_port:u32&local_dev:txt&reuse:u32->sockid:txt /** * Create a bound UDP multicast socket. @@ -1598,7 +1598,7 @@ finder://fea/socket6/0.1/tcp_open_and_bind?creator:txt&local_addr:ipv6&local_por * @param sockid return parameter that contains unique socket ID when socket * instantiation is successful. */ -finder://fea/socket6/0.1/udp_open_and_bind?creator:txt&local_addr:ipv6&local_port:u32->sockid:txt +finder://fea/socket6/0.1/udp_open_and_bind?creator:txt&local_addr:ipv6&local_port:u32&local_dev:txt&reuse:u32->sockid:txt /** * Create a bound UDP multicast socket. diff --git a/xrl/targets/fea_base.cc b/xrl/targets/fea_base.cc index 4265ec9..a59d423 100644 --- a/xrl/targets/fea_base.cc +++ b/xrl/targets/fea_base.cc @@ -4846,9 +4846,9 @@ XrlFeaTargetBase::handle_socket4_0_1_tcp_open_and_bind(const XrlArgs& xa_inputs, const XrlCmdError XrlFeaTargetBase::handle_socket4_0_1_udp_open_and_bind(const XrlArgs& xa_inputs, XrlArgs* pxa_outputs) { - if (xa_inputs.size() != 3) { + if (xa_inputs.size() != 5) { XLOG_ERROR("Wrong number of arguments (%u != %u) handling %s", - XORP_UINT_CAST(3), XORP_UINT_CAST(xa_inputs.size()), "socket4/0.1/udp_open_and_bind"); + XORP_UINT_CAST(5), XORP_UINT_CAST(xa_inputs.size()), "socket4/0.1/udp_open_and_bind"); return XrlCmdError::BAD_ARGS(); } @@ -4864,6 +4864,8 @@ XrlFeaTargetBase::handle_socket4_0_1_udp_open_and_bind(const XrlArgs& xa_inputs, xa_inputs.get(0, "creator").text(), xa_inputs.get(1, "local_addr").ipv4(), xa_inputs.get(2, "local_port").uint32(), + xa_inputs.get(3, "local_dev").text(), + xa_inputs.get(4, "reuse").uint32(), sockid); if (e != XrlCmdError::OKAY()) { XLOG_WARNING("Handling method for %s failed: %s", @@ -5476,9 +5478,9 @@ XrlFeaTargetBase::handle_socket6_0_1_tcp_open_and_bind(const XrlArgs& xa_inputs, const XrlCmdError XrlFeaTargetBase::handle_socket6_0_1_udp_open_and_bind(const XrlArgs& xa_inputs, XrlArgs* pxa_outputs) { - if (xa_inputs.size() != 3) { + if (xa_inputs.size() != 5) { XLOG_ERROR("Wrong number of arguments (%u != %u) handling %s", - XORP_UINT_CAST(3), XORP_UINT_CAST(xa_inputs.size()), "socket6/0.1/udp_open_and_bind"); + XORP_UINT_CAST(5), XORP_UINT_CAST(xa_inputs.size()), "socket6/0.1/udp_open_and_bind"); return XrlCmdError::BAD_ARGS(); } @@ -5494,6 +5496,8 @@ XrlFeaTargetBase::handle_socket6_0_1_udp_open_and_bind(const XrlArgs& xa_inputs, xa_inputs.get(0, "creator").text(), xa_inputs.get(1, "local_addr").ipv6(), xa_inputs.get(2, "local_port").uint32(), + xa_inputs.get(3, "local_dev").text(), + xa_inputs.get(4, "reuse").uint32(), sockid); if (e != XrlCmdError::OKAY()) { XLOG_WARNING("Handling method for %s failed: %s", diff --git a/xrl/targets/fea_base.hh b/xrl/targets/fea_base.hh index 61c48b4..41d4d06 100644 --- a/xrl/targets/fea_base.hh +++ b/xrl/targets/fea_base.hh @@ -2297,6 +2297,8 @@ protected: const string& creator, const IPv4& local_addr, const uint32_t& local_port, + const string& local_dev, + const uint32_t& reuse, // Output values, string& sockid) = 0; @@ -2704,6 +2706,8 @@ protected: const string& creator, const IPv6& local_addr, const uint32_t& local_port, + const string& local_dev, + const uint32_t& reuse, // Output values, string& sockid) = 0;