I'm developing a C++ program listening to multiple UDP ports and need to retrieve the TTL of received packets. Boost ASIO does not provide access to that.
I added raw sockets to the program with boost raw sockets instead of udp sockets. After some struggle, I'm able to send and receive UDP packets setting myself the IP and UDP headers.
The issue is that the program receives on each socket as many duplicate packets as the number of created sockets. If I open 3 sockets, I receive 3 packets on each, open 4 receive 4... Wireshark shows me that everything is fine on the network.
Here is how I initiate the sockets :
sockstr_.sin_family = AF_INET;
sockstr_.sin_port = htons(localendpoint.port());
sockstr_.sin_addr.s_addr = inet_addr(localendpoint.address().to_string().c_str());
socklen_t socklen = (socklen_t) sizeof(sockstr_);
if ((raw_socket_ = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1) {
throw std::runtime_error("Failed to open socket! ");
}
int on = 1;
setsockopt(raw_socket_, IPPROTO_IP, IP_HDRINCL , &on, sizeof(on));
if (bind(raw_socket_, (struct sockaddr*) &sockstr_, socklen) == -1) {
close(raw_socket_);
throw std::runtime_error("Failed to bind socket! ");
}
// udp_socket_ defined in header file
// boost::asio::ip::raw_udp::socket udp_socket_;
udp_socket_.assign(boost::asio::ip::raw_udp::v4(), raw_socket_);
// Then I simply use boost functions
udp_socket_.async_send_to(boost::asio::buffer(ST), ref_endpoint_ ...
udp_socket_.async_receive_from(boost::asio::buffer(RT), ref_endpoint_ ...
In the log, I saw that all the raw sockets share the same port number 17, but my program sends and receives on the ports I choose and wireshark shows me that. Si I guess that's the source of the problem. Any idea how to change the raw socket port ? or another solution to fix the issue :
[10:06:09.966254][0014][debug]: Socket : 11
[10:06:09.966301][0015][debug]: UDP Source endpoint: 10.20.100.121:17
[10:06:09.966347][0016][debug]: Client [0] starting test session [0] with endless duration !
[10:06:09.966652][0017][debug]: Socket : 12
[10:06:09.966696][0018][debug]: UDP Source endpoint: 10.20.100.121:17
[10:06:09.966731][0019][debug]: Client [0] starting test session [1] with endless duration !
[10:06:09.967040][001a][debug]: Socket : 13
[10:06:09.967078][001b][debug]: UDP Source endpoint: 10.20.100.121:17
[10:06:09.967112][001c][debug]: Client [0] starting test session [2] with endless duration !
Here is the raw_udp code:
namespace boost {
namespace asio {
namespace ip {
class raw_udp
{
public:
typedef basic_endpoint<raw_udp> endpoint;
static raw_udp v4()
{
return raw_udp(IPPROTO_UDP, AF_INET);
}
static raw_udp v6()
{
return raw_udp(IPPROTO_UDP, AF_INET);
}
int type() const
{
return SOCK_RAW;
}
int protocol() const
{
return protocol_;
}
int family() const
{
return family_;
}
typedef basic_raw_socket<raw_udp> socket;
typedef basic_resolver<raw_udp> resolver;
friend bool operator==(const raw_udp& p1, const raw_udp& p2)
{
return p1.protocol_ == p2.protocol_ && p1.family_ == p2.family_;
}
friend bool operator!=(const raw_udp& p1, const raw_udp& p2)
{
return p1.protocol_ != p2.protocol_ || p1.family_ != p2.family_;
}
private:
explicit raw_udp(int protocol_id, int protocol_family)
: protocol_(protocol_id),
family_(protocol_family)
{
}
int protocol_;
int family_;
};
} // namespace ip
} // namespace asio
} // namespace boost