mirror of
https://github.com/scylladb/scylladb.git
synced 2026-06-02 13:06:57 +00:00
net: Add "packet filter" functionality + accessors + "raw" packet send function
Perhaps not the best way to enable "hijacking" the ip stack (for DHCP querying), but considering the options seems the least intrusive. Signed-off-by: Calle Wilund <calle@cloudius-systems.com>
This commit is contained in:
41
net/ip.cc
41
net/ip.cc
@@ -34,6 +34,15 @@ ipv4::ipv4(interface* netif)
|
||||
unsigned ipv4::handle_on_cpu(packet& p, size_t off)
|
||||
{
|
||||
auto iph = p.get_header<ip_hdr>(off);
|
||||
|
||||
if (_packet_filter) {
|
||||
bool h = false;
|
||||
auto r = _packet_filter->forward(p, off + sizeof(ip_hdr), iph->src_ip, iph->dst_ip, h);
|
||||
if (h) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
auto l4 = _l4[iph->ip_proto];
|
||||
if (!l4) {
|
||||
return engine.cpu_id();
|
||||
@@ -65,6 +74,15 @@ ipv4::handle_received_packet(packet p, ethernet_address from) {
|
||||
// FIXME: defragment
|
||||
return make_ready_future<>();
|
||||
}
|
||||
|
||||
if (_packet_filter) {
|
||||
bool h = false;
|
||||
auto r = _packet_filter->handle(p, from, h);
|
||||
if (h) {
|
||||
return std::move(r);
|
||||
}
|
||||
}
|
||||
|
||||
if (iph->dst_ip != _host_address) {
|
||||
// FIXME: forward
|
||||
return make_ready_future<>();
|
||||
@@ -115,10 +133,15 @@ future<> ipv4::send(ipv4_address to, ip_protocol_num proto_num, packet p) {
|
||||
}
|
||||
|
||||
return _arp.lookup(dst).then([this, p = std::move(p)] (ethernet_address e_dst) mutable {
|
||||
return _l3.send(e_dst, std::move(p));
|
||||
return send_raw(e_dst, std::move(p));
|
||||
});
|
||||
}
|
||||
|
||||
future<> ipv4::send_raw(ethernet_address dst, packet p) {
|
||||
return _l3.send(dst, std::move(p));
|
||||
}
|
||||
|
||||
|
||||
void ipv4::set_host_address(ipv4_address ip) {
|
||||
_host_address = ip;
|
||||
_arp.set_self_addr(ip);
|
||||
@@ -132,10 +155,26 @@ void ipv4::set_gw_address(ipv4_address ip) {
|
||||
_gw_address = ip;
|
||||
}
|
||||
|
||||
ipv4_address ipv4::gw_address() const {
|
||||
return _gw_address;
|
||||
}
|
||||
|
||||
void ipv4::set_netmask_address(ipv4_address ip) {
|
||||
_netmask = ip;
|
||||
}
|
||||
|
||||
ipv4_address ipv4::netmask_address() const {
|
||||
return _netmask;
|
||||
}
|
||||
|
||||
void ipv4::set_packet_filter(ip_packet_filter * f) {
|
||||
_packet_filter = f;
|
||||
}
|
||||
|
||||
ip_packet_filter * ipv4::packet_filter() const {
|
||||
return _packet_filter;
|
||||
}
|
||||
|
||||
void ipv4::register_l4(ipv4::proto_type id, ip_protocol *protocol) {
|
||||
_l4.at(id) = protocol;
|
||||
}
|
||||
|
||||
20
net/ip.hh
20
net/ip.hh
@@ -141,6 +141,14 @@ public:
|
||||
friend class ipv4;
|
||||
};
|
||||
|
||||
struct ip_packet_filter {
|
||||
virtual ~ip_packet_filter() {};
|
||||
virtual future<> handle(packet& p, ethernet_address from, bool & handled) = 0;
|
||||
virtual unsigned forward(packet& p, size_t off, ipv4_address from, ipv4_address to, bool & handled) {
|
||||
return engine.cpu_id();
|
||||
}
|
||||
};
|
||||
|
||||
class ipv4 {
|
||||
public:
|
||||
using address_type = ipv4_address;
|
||||
@@ -159,6 +167,7 @@ private:
|
||||
ipv4_tcp _tcp;
|
||||
ipv4_icmp _icmp;
|
||||
array_map<ip_protocol*, 256> _l4;
|
||||
ip_packet_filter * _packet_filter = nullptr;
|
||||
private:
|
||||
future<> handle_received_packet(packet p, ethernet_address from);
|
||||
unsigned handle_on_cpu(packet& p, size_t off);
|
||||
@@ -168,8 +177,19 @@ public:
|
||||
void set_host_address(ipv4_address ip);
|
||||
ipv4_address host_address();
|
||||
void set_gw_address(ipv4_address ip);
|
||||
ipv4_address gw_address() const;
|
||||
void set_netmask_address(ipv4_address ip);
|
||||
ipv4_address netmask_address() const;
|
||||
interface * netif() const {
|
||||
return _netif;
|
||||
}
|
||||
// TODO or something. Should perhaps truly be a list
|
||||
// of filters. With ordering. And blackjack. Etc.
|
||||
// But for now, a simple single raw pointer suffices
|
||||
void set_packet_filter(ip_packet_filter *);
|
||||
ip_packet_filter * packet_filter() const;
|
||||
future<> send(ipv4_address to, ip_protocol_num proto_num, packet p);
|
||||
future<> send_raw(ethernet_address, packet);
|
||||
tcp<ipv4_traits>& get_tcp() { return *_tcp._tcp; }
|
||||
void register_l4(proto_type id, ip_protocol* handler);
|
||||
net::hw_features hw_features() { return _netif->hw_features(); }
|
||||
|
||||
Reference in New Issue
Block a user