Skip to content

Commit

Permalink
socktap: bind UDP multicasts to network device
Browse files Browse the repository at this point in the history
  • Loading branch information
riebl committed Oct 9, 2024
1 parent 8c75abd commit 1901661
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 39 deletions.
42 changes: 15 additions & 27 deletions tools/socktap/ethernet_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,19 @@ static void initialize(ifreq& request, const char* interface_name)
}

EthernetDevice::EthernetDevice(const char* devname) :
local_socket_(::socket(AF_LOCAL, SOCK_DGRAM, 0)),
inet_socket_(::socket(AF_INET, SOCK_DGRAM, 0)),
interface_name_(devname)
{
if (!local_socket_) {
if (!inet_socket_) {
throw std::system_error(errno, std::system_category());
}
}

EthernetDevice::~EthernetDevice()
{
if (local_socket_ >= 0)
::close(local_socket_);
if (inet_socket_ >= 0)
::close(inet_socket_);

}

EthernetDevice::protocol::endpoint EthernetDevice::endpoint(int family) const
Expand All @@ -43,42 +44,29 @@ int EthernetDevice::index() const
{
ifreq data;
initialize(data, interface_name_.c_str());
::ioctl(local_socket_, SIOCGIFINDEX, &data);
::ioctl(inet_socket_, SIOCGIFINDEX, &data);
return data.ifr_ifindex;
}

vanetza::MacAddress EthernetDevice::address() const
{
ifreq data;
initialize(data, interface_name_.c_str());
::ioctl(local_socket_, SIOCGIFHWADDR, &data);
::ioctl(inet_socket_, SIOCGIFHWADDR, &data);

vanetza::MacAddress addr;
std::copy_n(data.ifr_hwaddr.sa_data, addr.octets.size(), addr.octets.data());
return addr;
}

std::string EthernetDevice::ip() const
boost::asio::ip::address_v4 EthernetDevice::ip() const
{
//@todo maybe there's a better way to obtain IP from device name...
std::string ip;
char host[NI_MAXHOST];
struct ifaddrs *interfaces = nullptr;
// get all network interfaces
if(getifaddrs(&interfaces) == 0){
// search for local interface and copy IP
for(struct ifaddrs *ifa = interfaces; ifa != NULL; ifa = ifa->ifa_next) {
if(ifa->ifa_addr == NULL)
continue;
ifreq data;
initialize(data, interface_name_.c_str());
::ioctl(inet_socket_, SIOCGIFADDR, &data);

if(ifa->ifa_addr->sa_family == AF_INET && std::string(ifa->ifa_name) == interface_name_){
if(getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == 0) {
ip = std::string(host);
break;
}
}
}
freeifaddrs(interfaces);
}
return ip;
char host[NI_MAXHOST] = { 0 };
::getnameinfo(&data.ifr_addr, sizeof(sockaddr), host, NI_MAXHOST, nullptr, 0, NI_NUMERICHOST);

return boost::asio::ip::address_v4::from_string(host);
}
5 changes: 3 additions & 2 deletions tools/socktap/ethernet_device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <vanetza/net/mac_address.hpp>
#include <boost/asio/generic/raw_protocol.hpp>
#include <boost/asio/ip/address_v4.hpp>
#include <string>

class EthernetDevice
Expand All @@ -17,12 +18,12 @@ class EthernetDevice

protocol::endpoint endpoint(int family) const;
vanetza::MacAddress address() const;
std::string ip() const;
boost::asio::ip::address_v4 ip() const;

private:
int index() const;

int local_socket_;
int inet_socket_;
std::string interface_name_;
};

Expand Down
2 changes: 1 addition & 1 deletion tools/socktap/link_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ create_link_layer(boost::asio::io_service& io_service, const EthernetDevice& dev
} else if (name == "udp") {
namespace ip = boost::asio::ip;
ip::udp::endpoint multicast(ip::address::from_string("239.118.122.97"), 8947);
link_layer.reset(new UdpLink { io_service, multicast, device.ip() });
link_layer.reset(new UdpLink { io_service, multicast, device });
} else if (name == "tcp") {
namespace ip = boost::asio::ip;

Expand Down
16 changes: 8 additions & 8 deletions tools/socktap/udp_link.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,26 @@
namespace ip = boost::asio::ip;
using namespace vanetza;

UdpLink::UdpLink(boost::asio::io_service& io_service, const ip::udp::endpoint& endpoint, const std::string& ip) :
UdpLink::UdpLink(boost::asio::io_service& io_service, const ip::udp::endpoint& endpoint, const EthernetDevice& device) :
multicast_endpoint_(endpoint),
tx_socket_(io_service), rx_socket_(io_service),
rx_buffer_(2560, 0x00)
{
tx_socket_.open(multicast_endpoint_.protocol());
auto ip = device.ip();

if(ip.size() != 0){
boost::asio::ip::multicast::outbound_interface option(boost::asio::ip::address_v4::from_string(ip));
tx_socket_.open(multicast_endpoint_.protocol());
if (!ip.is_unspecified()) {
boost::asio::ip::multicast::outbound_interface option(ip);
tx_socket_.set_option(option);
}

rx_socket_.open(multicast_endpoint_.protocol());
rx_socket_.set_option(ip::udp::socket::reuse_address(true));
rx_socket_.bind(multicast_endpoint_);
rx_socket_.set_option(ip::multicast::enable_loopback(false));

if(ip.size() != 0){
rx_socket_.set_option(ip::multicast::join_group(multicast_endpoint_.address().to_v4(), boost::asio::ip::address_v4::from_string(ip)));
}else{
if(!ip.is_unspecified() && multicast_endpoint_.address().is_v4()) {
rx_socket_.set_option(ip::multicast::join_group(multicast_endpoint_.address().to_v4(), ip));
} else {
rx_socket_.set_option(ip::multicast::join_group(multicast_endpoint_.address()));
}

Expand Down
5 changes: 4 additions & 1 deletion tools/socktap/udp_link.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
#include <boost/asio/ip/udp.hpp>
#include <array>

// forward declaration
class EthernetDevice;

class UdpLink : public LinkLayer
{
public:
UdpLink(boost::asio::io_service&, const boost::asio::ip::udp::endpoint&, const std::string&);
UdpLink(boost::asio::io_service&, const boost::asio::ip::udp::endpoint&, const EthernetDevice&);

void indicate(IndicationCallback) override;
void request(const vanetza::access::DataRequest&, std::unique_ptr<vanetza::ChunkPacket>) override;
Expand Down

0 comments on commit 1901661

Please sign in to comment.