From bd263b3b4e3c85baeca136ab3fd5a23f44b4deda Mon Sep 17 00:00:00 2001 From: Calle Wilund Date: Wed, 5 Nov 2014 12:34:35 +0100 Subject: [PATCH] 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 --- net/ip.cc | 41 ++++++++++++++++++++++++++++++++++++++++- net/ip.hh | 20 ++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/net/ip.cc b/net/ip.cc index 75b9511147..a66e2f4406 100644 --- a/net/ip.cc +++ b/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(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; } diff --git a/net/ip.hh b/net/ip.hh index 73b8334adb..7ca2e7d4d0 100644 --- a/net/ip.hh +++ b/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 _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& get_tcp() { return *_tcp._tcp; } void register_l4(proto_type id, ip_protocol* handler); net::hw_features hw_features() { return _netif->hw_features(); }