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:
Calle Wilund
2014-11-05 12:34:35 +01:00
committed by Avi Kivity
parent 534d4017a1
commit bd263b3b4e
2 changed files with 60 additions and 1 deletions

View File

@@ -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;
}

View File

@@ -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(); }