, , - ethernet basic_raw_socket.
(htons (ETH_P_ALL)) (PF_PACKET), , /.
class ll_protocol
{
public:
int type() const
{
return SOCK_RAW;
}
int protocol() const
{
return protocol_;
}
int family() const
{
return family_;
}
explicit ll_protocol(int protocol, int family) :
protocol_(protocol), family_(family)
{
}
explicit ll_protocol() :
protocol_(htons(ETH_P_ALL)), family_(PF_PACKET)
{
}
typedef boost::asio::basic_raw_socket<ll_protocol> socket;
typedef ll_endpoint<ll_protocol> endpoint;
private:
int protocol_;
int family_;
};
, . sockaddr_ll, / .
#include <net/ethernet.h>
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <cstddef>
template <typename Protocol>
class ll_endpoint
{
private:
sockaddr_ll sockaddr;
public:
typedef Protocol protocol_type;
typedef boost::asio::detail::socket_addr_type data_type;
ll_endpoint(const char* ifname)
{
sockaddr.sll_family = PF_PACKET;
sockaddr.sll_protocol = htons(ETH_P_ALL);
sockaddr.sll_ifindex = if_nametoindex(ifname);
sockaddr.sll_hatype = 1;
}
ll_endpoint& operator=(const ll_endpoint& other)
{
sockaddr = other.sockaddr;
return *this;
}
protocol_type protocol() const
{
return protocol_type();
}
data_type* data()
{
return &sockaddr;
}
const data_type* data() const
{
return (struct sockaddr*)&sockaddr;
}
std::size_t size() const
{
return sizeof(sockaddr);
}
void resize(std::size_t size)
{
}
std::size_t capacity() const
{
return sizeof(sockaddr);
}
friend bool operator==(const ll_endpoint<Protocol>& e1,
const ll_endpoint<Protocol>& e2)
{
return e1.sockaddr == e2.sockaddr;
}
friend bool operator!=(const ll_endpoint<Protocol>& e1,
const ll_endpoint<Protocol>& e2)
{
return !(e1.sockaddr == e2.sockaddr);
}
friend bool operator<(const ll_endpoint<Protocol>& e1,
const ll_endpoint<Protocol>& e2)
{
return e1.sockaddr < e2.sockaddr;
}
friend bool operator>(const ll_endpoint<Protocol>& e1,
const ll_endpoint<Protocol>& e2)
{
return e2.sockaddr < e1.sockaddr;
}
friend bool operator<=(const ll_endpoint<Protocol>& e1,
const ll_endpoint<Protocol>& e2)
{
return !(e2 < e1);
}
friend bool operator>=(const ll_endpoint<Protocol>& e1,
const ll_endpoint<Protocol>& e2)
{
return !(e1 < e2);
}
};
, :
string ifname("eth1");
ll_protocol::socket socket;
socket.open(ll_protocol());
socket.bind(ll_endpoint<ll_protocol>((const char*)ifname.c_str()));