mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-07 19:34:56 +00:00
net: safer access to packet data
Replace packet method 'T *data' by the new methods 'T &reinterpret_data' for parsing or modifying existing sub-protocol packets and 'T &construct_at_data' for composing a new sub-protocol packet. This has the advantage that, when composing a new packet, the default constructor that zero-fills the packet is always called first. Fixes #2751
This commit is contained in:
parent
58fcf577ea
commit
373134c4e7
@ -104,10 +104,6 @@ class Net::Dhcp_packet
|
||||
_magic_cookie = host_to_big_endian(0x63825363);
|
||||
}
|
||||
|
||||
void zero_fill_sname() { Genode::memset(_sname, 0, sizeof(_sname)); }
|
||||
|
||||
void zero_fill_file() { Genode::memset(_file, 0, sizeof(_file)); }
|
||||
|
||||
|
||||
/*******************************
|
||||
** Utilities for the options **
|
||||
|
@ -17,7 +17,7 @@
|
||||
/* Genode includes */
|
||||
#include <base/exception.h>
|
||||
#include <util/string.h>
|
||||
|
||||
#include <util/construct_at.h>
|
||||
#include <util/endian.h>
|
||||
#include <net/mac_address.h>
|
||||
|
||||
@ -72,20 +72,27 @@ class Net::Ethernet_frame
|
||||
|
||||
struct Bad_data_type : Genode::Exception { };
|
||||
|
||||
template <typename T> T const *data(Genode::size_t data_size) const
|
||||
template <typename T> T const &data(Genode::size_t data_size) const
|
||||
{
|
||||
if (data_size < sizeof(T)) {
|
||||
throw Bad_data_type();
|
||||
}
|
||||
return (T const *)(_data);
|
||||
return *(T const *)(_data);
|
||||
}
|
||||
|
||||
template <typename T> T *data(Genode::size_t data_size)
|
||||
template <typename T> T &data(Genode::size_t data_size)
|
||||
{
|
||||
if (data_size < sizeof(T)) {
|
||||
throw Bad_data_type();
|
||||
}
|
||||
return (T *)(_data);
|
||||
return *(T *)(_data);
|
||||
}
|
||||
|
||||
template <typename T, typename SIZE_GUARD>
|
||||
T &construct_at_data(SIZE_GUARD &size_guard)
|
||||
{
|
||||
size_guard.add(sizeof(T));
|
||||
return *Genode::construct_at<T>(_data);
|
||||
}
|
||||
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <base/exception.h>
|
||||
#include <util/string.h>
|
||||
#include <util/token.h>
|
||||
|
||||
#include <util/construct_at.h>
|
||||
#include <util/endian.h>
|
||||
#include <net/netaddress.h>
|
||||
|
||||
@ -124,20 +124,29 @@ class Net::Ipv4_packet
|
||||
|
||||
struct Bad_data_type : Genode::Exception { };
|
||||
|
||||
template <typename T> T const *data(Genode::size_t data_size) const
|
||||
template <typename T>
|
||||
T const &data(Genode::size_t data_size) const
|
||||
{
|
||||
if (data_size < sizeof(T)) {
|
||||
throw Bad_data_type();
|
||||
}
|
||||
return (T const *)(_data);
|
||||
return *(T const *)(_data);
|
||||
}
|
||||
|
||||
template <typename T> T *data(Genode::size_t data_size)
|
||||
template <typename T>
|
||||
T &data(Genode::size_t data_size)
|
||||
{
|
||||
if (data_size < sizeof(T)) {
|
||||
throw Bad_data_type();
|
||||
}
|
||||
return (T *)(_data);
|
||||
return *(T *)(_data);
|
||||
}
|
||||
|
||||
template <typename T, typename SIZE_GUARD>
|
||||
T &construct_at_data(SIZE_GUARD &size_guard)
|
||||
{
|
||||
size_guard.add(sizeof(T));
|
||||
return *Genode::construct_at<T>(_data);
|
||||
}
|
||||
|
||||
|
||||
|
@ -53,20 +53,27 @@ class Net::Udp_packet
|
||||
|
||||
struct Bad_data_type : Genode::Exception { };
|
||||
|
||||
template <typename T> T const *data(Genode::size_t data_size) const
|
||||
template <typename T> T const &data(Genode::size_t data_size) const
|
||||
{
|
||||
if (data_size < sizeof(T)) {
|
||||
throw Bad_data_type();
|
||||
}
|
||||
return (T const *)(_data);
|
||||
return *(T const *)(_data);
|
||||
}
|
||||
|
||||
template <typename T> T *data(Genode::size_t data_size)
|
||||
template <typename T> T &data(Genode::size_t data_size)
|
||||
{
|
||||
if (data_size < sizeof(T)) {
|
||||
throw Bad_data_type();
|
||||
}
|
||||
return (T *)(_data);
|
||||
return *(T *)(_data);
|
||||
}
|
||||
|
||||
template <typename T, typename SIZE_GUARD>
|
||||
T &construct_at_data(SIZE_GUARD &size_guard)
|
||||
{
|
||||
size_guard.add(sizeof(T));
|
||||
return *Genode::construct_at<T>(_data);
|
||||
}
|
||||
|
||||
|
||||
|
@ -200,7 +200,7 @@ void Main::_handle_ip(Ethernet_frame ð,
|
||||
{
|
||||
/* drop packet if IP does not target us */
|
||||
size_t const ip_size = eth_size - sizeof(Ethernet_frame);
|
||||
Ipv4_packet &ip = *eth.data<Ipv4_packet>(ip_size);
|
||||
Ipv4_packet &ip = eth.data<Ipv4_packet>(ip_size);
|
||||
if (ip.dst() != _src_ip &&
|
||||
ip.dst() != Ipv4_packet::broadcast())
|
||||
{
|
||||
@ -306,7 +306,7 @@ void Main::_handle_icmp_dst_unreachbl(Ipv4_packet &ip,
|
||||
}
|
||||
/* drop packet if embedded ICMP identifier is invalid */
|
||||
size_t const embed_icmp_sz = embed_ip.total_length() - sizeof(Ipv4_packet);
|
||||
Icmp_packet &embed_icmp = *embed_ip.data<Icmp_packet>(embed_icmp_sz);
|
||||
Icmp_packet &embed_icmp = embed_ip.data<Icmp_packet>(embed_icmp_sz);
|
||||
if (embed_icmp.query_id() != ICMP_ID) {
|
||||
if (_verbose) {
|
||||
log("bad ICMP identifier in payload of ICMP error"); }
|
||||
@ -328,7 +328,7 @@ void Main::_handle_icmp(Ipv4_packet &ip,
|
||||
{
|
||||
/* drop packet if ICMP checksum is invalid */
|
||||
size_t const icmp_sz = ip_size - sizeof(Ipv4_packet);
|
||||
Icmp_packet &icmp = *ip.data<Icmp_packet>(icmp_sz);
|
||||
Icmp_packet &icmp = ip.data<Icmp_packet>(icmp_sz);
|
||||
size_t const icmp_data_sz = icmp_sz - sizeof(Icmp_packet);
|
||||
if (icmp.calc_checksum(icmp_data_sz) != icmp.checksum()) {
|
||||
if (_verbose) {
|
||||
@ -351,7 +351,7 @@ void Main::_handle_arp(Ethernet_frame ð,
|
||||
size_t const eth_size)
|
||||
{
|
||||
/* check ARP protocol- and hardware address type */
|
||||
Arp_packet &arp = *eth.data<Arp_packet>(eth_size - sizeof(Ethernet_frame));
|
||||
Arp_packet &arp = eth.data<Arp_packet>(eth_size - sizeof(Ethernet_frame));
|
||||
if (!arp.ethernet_ipv4()) {
|
||||
error("ARP for unknown protocol"); }
|
||||
|
||||
@ -409,24 +409,19 @@ void Main::_ready_to_ack()
|
||||
void Main::_send_arp_reply(Ethernet_frame &req_eth,
|
||||
Arp_packet &req_arp)
|
||||
{
|
||||
enum {
|
||||
ETH_HDR_SZ = sizeof(Ethernet_frame),
|
||||
ETH_DAT_SZ = sizeof(Arp_packet) + ETH_HDR_SZ >= Ethernet_frame::MIN_SIZE ?
|
||||
sizeof(Arp_packet) :
|
||||
Ethernet_frame::MIN_SIZE - ETH_HDR_SZ,
|
||||
ETH_CRC_SZ = sizeof(uint32_t),
|
||||
PKT_SIZE = ETH_HDR_SZ + ETH_DAT_SZ + ETH_CRC_SZ,
|
||||
};
|
||||
_send(PKT_SIZE, [&] (void *pkt_base) {
|
||||
size_t const buf_sz = sizeof(Ethernet_frame) + sizeof(Arp_packet);
|
||||
_send(buf_sz, [&] (void *pkt_base) {
|
||||
|
||||
/* write Ethernet header */
|
||||
Ethernet_frame ð = *reinterpret_cast<Ethernet_frame *>(pkt_base);
|
||||
Size_guard<Send_buffer_too_small> size(buf_sz);
|
||||
size.add(sizeof(Ethernet_frame));
|
||||
Ethernet_frame ð = *construct_at<Ethernet_frame>(pkt_base);
|
||||
eth.dst(req_eth.src());
|
||||
eth.src(_src_mac);
|
||||
eth.type(Ethernet_frame::Type::ARP);
|
||||
|
||||
/* write ARP header */
|
||||
Arp_packet &arp = *eth.data<Arp_packet>(PKT_SIZE - sizeof(Ethernet_frame));
|
||||
Arp_packet &arp = eth.construct_at_data<Arp_packet>(size);
|
||||
arp.hardware_address_type(Arp_packet::ETHERNET);
|
||||
arp.protocol_address_type(Arp_packet::IPV4);
|
||||
arp.hardware_address_size(sizeof(Mac_address));
|
||||
@ -442,24 +437,19 @@ void Main::_send_arp_reply(Ethernet_frame &req_eth,
|
||||
|
||||
void Main::_broadcast_arp_request()
|
||||
{
|
||||
enum {
|
||||
ETH_HDR_SZ = sizeof(Ethernet_frame),
|
||||
ETH_DAT_SZ = sizeof(Arp_packet) + ETH_HDR_SZ >= Ethernet_frame::MIN_SIZE ?
|
||||
sizeof(Arp_packet) :
|
||||
Ethernet_frame::MIN_SIZE - ETH_HDR_SZ,
|
||||
ETH_CRC_SZ = sizeof(uint32_t),
|
||||
PKT_SIZE = ETH_HDR_SZ + ETH_DAT_SZ + ETH_CRC_SZ,
|
||||
};
|
||||
_send(PKT_SIZE, [&] (void *pkt_base) {
|
||||
size_t const buf_sz = sizeof(Ethernet_frame) + sizeof(Arp_packet);
|
||||
_send(buf_sz, [&] (void *pkt_base) {
|
||||
|
||||
/* write Ethernet header */
|
||||
Ethernet_frame ð = *reinterpret_cast<Ethernet_frame *>(pkt_base);
|
||||
Size_guard<Send_buffer_too_small> size(buf_sz);
|
||||
size.add(sizeof(Ethernet_frame));
|
||||
Ethernet_frame ð = *construct_at<Ethernet_frame>(pkt_base);
|
||||
eth.dst(Mac_address(0xff));
|
||||
eth.src(_src_mac);
|
||||
eth.type(Ethernet_frame::Type::ARP);
|
||||
|
||||
/* write ARP header */
|
||||
Arp_packet &arp = *eth.data<Arp_packet>(PKT_SIZE - sizeof(Ethernet_frame));
|
||||
Arp_packet &arp = eth.construct_at_data<Arp_packet>(size);
|
||||
arp.hardware_address_type(Arp_packet::ETHERNET);
|
||||
arp.protocol_address_type(Arp_packet::IPV4);
|
||||
arp.hardware_address_size(sizeof(Mac_address));
|
||||
@ -487,36 +477,30 @@ void Main::_send_ping(Duration)
|
||||
/* create ETH header */
|
||||
Size_guard<Send_buffer_too_small> size(buf_sz);
|
||||
size.add(sizeof(Ethernet_frame));
|
||||
Ethernet_frame ð = *reinterpret_cast<Ethernet_frame *>(pkt_base);
|
||||
Ethernet_frame ð = *construct_at<Ethernet_frame>(pkt_base);
|
||||
eth.dst(_dst_mac);
|
||||
eth.src(_src_mac);
|
||||
eth.type(Ethernet_frame::Type::IPV4);
|
||||
|
||||
/* create IP header */
|
||||
size_t const ip_off = size.curr();
|
||||
Ipv4_packet &ip = *eth.data<Ipv4_packet>(size.left());
|
||||
size.add(sizeof(Ipv4_packet));
|
||||
Ipv4_packet &ip = eth.construct_at_data<Ipv4_packet>(size);
|
||||
ip.header_length(sizeof(Ipv4_packet) / 4);
|
||||
ip.version(4);
|
||||
ip.diff_service(0);
|
||||
ip.ecn(0);
|
||||
ip.identification(0);
|
||||
ip.flags(0);
|
||||
ip.fragment_offset(0);
|
||||
ip.time_to_live(IPV4_TIME_TO_LIVE);
|
||||
ip.protocol(Ipv4_packet::Protocol::ICMP);
|
||||
ip.src(_src_ip);
|
||||
ip.dst(_dst_ip);
|
||||
|
||||
/* create ICMP header */
|
||||
Icmp_packet &icmp = *ip.data<Icmp_packet>(size.left());
|
||||
size.add(sizeof(Icmp_packet) + _icmp_data_sz);
|
||||
Icmp_packet &icmp = ip.construct_at_data<Icmp_packet>(size);
|
||||
icmp.type(Icmp_packet::Type::ECHO_REQUEST);
|
||||
icmp.code(Icmp_packet::Code::ECHO_REQUEST);
|
||||
icmp.query_id(ICMP_ID);
|
||||
icmp.query_seq(_icmp_seq);
|
||||
|
||||
/* fill ICMP data with characters from 'a' to 'w' */
|
||||
/* fill ICMP data with characters from 'a' to 'z' */
|
||||
size.add(_icmp_data_sz);
|
||||
struct Data { char chr[0]; };
|
||||
Data &data = icmp.data<Data>(_icmp_data_sz);
|
||||
char chr = 'a';
|
||||
|
@ -22,9 +22,9 @@ using namespace Net;
|
||||
|
||||
bool Session_component::handle_arp(Ethernet_frame *eth, Genode::size_t size)
|
||||
{
|
||||
Arp_packet *arp = eth->data<Arp_packet>(size - sizeof(Ethernet_frame));
|
||||
if (arp->ethernet_ipv4() &&
|
||||
arp->opcode() == Arp_packet::REQUEST) {
|
||||
Arp_packet &arp = eth->data<Arp_packet>(size - sizeof(Ethernet_frame));
|
||||
if (arp.ethernet_ipv4() &&
|
||||
arp.opcode() == Arp_packet::REQUEST) {
|
||||
|
||||
/*
|
||||
* 'Gratuitous ARP' broadcast messages are used to announce newly created
|
||||
@ -34,14 +34,14 @@ bool Session_component::handle_arp(Ethernet_frame *eth, Genode::size_t size)
|
||||
* The simplest solution to this problem is to just drop those messages,
|
||||
* since they are not really necessary.
|
||||
*/
|
||||
if (arp->src_ip() == arp->dst_ip())
|
||||
if (arp.src_ip() == arp.dst_ip())
|
||||
return false;
|
||||
|
||||
Ipv4_address_node *node = vlan().ip_tree.first();
|
||||
if (node)
|
||||
node = node->find_by_address(arp->dst_ip());
|
||||
node = node->find_by_address(arp.dst_ip());
|
||||
if (!node) {
|
||||
arp->src_mac(_nic.mac());
|
||||
arp.src_mac(_nic.mac());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -50,19 +50,19 @@ bool Session_component::handle_arp(Ethernet_frame *eth, Genode::size_t size)
|
||||
|
||||
bool Session_component::handle_ip(Ethernet_frame *eth, Genode::size_t size)
|
||||
{
|
||||
Ipv4_packet *ip = eth->data<Ipv4_packet>(size - sizeof(Ethernet_frame));
|
||||
Ipv4_packet &ip = eth->data<Ipv4_packet>(size - sizeof(Ethernet_frame));
|
||||
|
||||
if (ip->protocol() == Ipv4_packet::Protocol::UDP)
|
||||
if (ip.protocol() == Ipv4_packet::Protocol::UDP)
|
||||
{
|
||||
Udp_packet *udp = ip->data<Udp_packet>(size - sizeof(Ethernet_frame)
|
||||
- sizeof(Ipv4_packet));
|
||||
if (Dhcp_packet::is_dhcp(udp)) {
|
||||
Dhcp_packet *dhcp = udp->data<Dhcp_packet>(size - sizeof(Ethernet_frame)
|
||||
- sizeof(Ipv4_packet)
|
||||
- sizeof(Udp_packet));
|
||||
if (dhcp->op() == Dhcp_packet::REQUEST) {
|
||||
dhcp->broadcast(true);
|
||||
udp->update_checksum(ip->src(), ip->dst());
|
||||
Udp_packet &udp = ip.data<Udp_packet>(size - sizeof(Ethernet_frame)
|
||||
- sizeof(Ipv4_packet));
|
||||
if (Dhcp_packet::is_dhcp(&udp)) {
|
||||
Dhcp_packet &dhcp = udp.data<Dhcp_packet>(size - sizeof(Ethernet_frame)
|
||||
- sizeof(Ipv4_packet)
|
||||
- sizeof(Udp_packet));
|
||||
if (dhcp.op() == Dhcp_packet::REQUEST) {
|
||||
dhcp.broadcast(true);
|
||||
udp.update_checksum(ip.src(), ip.dst());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,37 +24,37 @@ using namespace Net;
|
||||
|
||||
|
||||
bool Net::Nic::handle_arp(Ethernet_frame *eth, Genode::size_t size) {
|
||||
Arp_packet *arp = eth->data<Arp_packet>(size - sizeof(Ethernet_frame));
|
||||
Arp_packet &arp = eth->data<Arp_packet>(size - sizeof(Ethernet_frame));
|
||||
|
||||
/* ignore broken packets */
|
||||
if (!arp->ethernet_ipv4())
|
||||
if (!arp.ethernet_ipv4())
|
||||
return true;
|
||||
|
||||
/* look whether the IP address is one of our client's */
|
||||
Ipv4_address_node *node = vlan().ip_tree.first();
|
||||
if (node)
|
||||
node = node->find_by_address(arp->dst_ip());
|
||||
node = node->find_by_address(arp.dst_ip());
|
||||
if (node) {
|
||||
if (arp->opcode() == Arp_packet::REQUEST) {
|
||||
if (arp.opcode() == Arp_packet::REQUEST) {
|
||||
/*
|
||||
* The ARP packet gets re-written, we interchange source
|
||||
* and destination MAC and IP addresses, and set the opcode
|
||||
* to reply, and then push the packet back to the NIC driver.
|
||||
*/
|
||||
Ipv4_address old_src_ip = arp->src_ip();
|
||||
arp->opcode(Arp_packet::REPLY);
|
||||
arp->dst_mac(arp->src_mac());
|
||||
arp->src_mac(mac());
|
||||
arp->src_ip(arp->dst_ip());
|
||||
arp->dst_ip(old_src_ip);
|
||||
eth->dst(arp->dst_mac());
|
||||
Ipv4_address old_src_ip = arp.src_ip();
|
||||
arp.opcode(Arp_packet::REPLY);
|
||||
arp.dst_mac(arp.src_mac());
|
||||
arp.src_mac(mac());
|
||||
arp.src_ip(arp.dst_ip());
|
||||
arp.dst_ip(old_src_ip);
|
||||
eth->dst(arp.dst_mac());
|
||||
|
||||
/* set our MAC as sender */
|
||||
eth->src(mac());
|
||||
send(eth, size);
|
||||
} else {
|
||||
/* overwrite destination MAC */
|
||||
arp->dst_mac(node->component().mac_address().addr);
|
||||
arp.dst_mac(node->component().mac_address().addr);
|
||||
eth->dst(node->component().mac_address().addr);
|
||||
node->component().send(eth, size);
|
||||
}
|
||||
@ -65,26 +65,26 @@ bool Net::Nic::handle_arp(Ethernet_frame *eth, Genode::size_t size) {
|
||||
|
||||
|
||||
bool Net::Nic::handle_ip(Ethernet_frame *eth, Genode::size_t size) {
|
||||
Ipv4_packet *ip = eth->data<Ipv4_packet>(size - sizeof(Ethernet_frame));
|
||||
Ipv4_packet &ip = eth->data<Ipv4_packet>(size - sizeof(Ethernet_frame));
|
||||
|
||||
/* is it an UDP packet ? */
|
||||
if (ip->protocol() == Ipv4_packet::Protocol::UDP)
|
||||
if (ip.protocol() == Ipv4_packet::Protocol::UDP)
|
||||
{
|
||||
Udp_packet *udp = ip->data<Udp_packet>(size - sizeof(Ethernet_frame)
|
||||
- sizeof(Ipv4_packet));
|
||||
Udp_packet &udp = ip.data<Udp_packet>(size - sizeof(Ethernet_frame)
|
||||
- sizeof(Ipv4_packet));
|
||||
|
||||
/* is it a DHCP packet ? */
|
||||
if (Dhcp_packet::is_dhcp(udp)) {
|
||||
Dhcp_packet *dhcp = udp->data<Dhcp_packet>(size - sizeof(Ethernet_frame)
|
||||
- sizeof(Ipv4_packet)
|
||||
- sizeof(Udp_packet));
|
||||
if (Dhcp_packet::is_dhcp(&udp)) {
|
||||
Dhcp_packet &dhcp = udp.data<Dhcp_packet>(size - sizeof(Ethernet_frame)
|
||||
- sizeof(Ipv4_packet)
|
||||
- sizeof(Udp_packet));
|
||||
|
||||
/* check for DHCP ACKs containing new client ips */
|
||||
if (dhcp->op() == Dhcp_packet::REPLY) {
|
||||
if (dhcp.op() == Dhcp_packet::REPLY) {
|
||||
|
||||
try {
|
||||
Dhcp_packet::Message_type const msg_type =
|
||||
dhcp->option<Dhcp_packet::Message_type_option>().value();
|
||||
dhcp.option<Dhcp_packet::Message_type_option>().value();
|
||||
|
||||
/*
|
||||
* Extract the IP address and set it in the client's
|
||||
@ -94,9 +94,9 @@ bool Net::Nic::handle_ip(Ethernet_frame *eth, Genode::size_t size) {
|
||||
Mac_address_node *node =
|
||||
vlan().mac_tree.first();
|
||||
if (node)
|
||||
node = node->find_by_address(dhcp->client_mac());
|
||||
node = node->find_by_address(dhcp.client_mac());
|
||||
if (node)
|
||||
node->component().set_ipv4_address(dhcp->yiaddr());
|
||||
node->component().set_ipv4_address(dhcp.yiaddr());
|
||||
}
|
||||
}
|
||||
catch (Dhcp_packet::Option_not_found) { }
|
||||
@ -108,7 +108,7 @@ bool Net::Nic::handle_ip(Ethernet_frame *eth, Genode::size_t size) {
|
||||
if (eth->dst() == mac()) {
|
||||
Ipv4_address_node *node = vlan().ip_tree.first();
|
||||
if (node) {
|
||||
node = node->find_by_address(ip->dst());
|
||||
node = node->find_by_address(ip.dst());
|
||||
if (node) {
|
||||
/* overwrite destination MAC */
|
||||
eth->dst(node->component().mac_address().addr);
|
||||
|
@ -157,12 +157,12 @@ void Packet_log<Ethernet_frame>::print(Output &output) const
|
||||
switch (_pkt.type()) {
|
||||
case Ethernet_frame::Type::ARP:
|
||||
|
||||
print(output, " ", packet_log(*_pkt.data<Arp_packet const>(~0UL), _cfg));
|
||||
print(output, " ", packet_log(_pkt.data<Arp_packet const>(~0UL), _cfg));
|
||||
break;
|
||||
|
||||
case Ethernet_frame::Type::IPV4:
|
||||
|
||||
print(output, " ", packet_log(*_pkt.data<Ipv4_packet const>(~0UL), _cfg));
|
||||
print(output, " ", packet_log(_pkt.data<Ipv4_packet const>(~0UL), _cfg));
|
||||
break;
|
||||
|
||||
default: ;
|
||||
@ -212,17 +212,17 @@ void Packet_log<Ipv4_packet>::print(Output &output) const
|
||||
switch (_pkt.protocol()) {
|
||||
case Ipv4_packet::Protocol::TCP:
|
||||
|
||||
print(output, " ", packet_log(*_pkt.data<Tcp_packet const>(~0UL), _cfg));
|
||||
print(output, " ", packet_log(_pkt.data<Tcp_packet const>(~0UL), _cfg));
|
||||
break;
|
||||
|
||||
case Ipv4_packet::Protocol::UDP:
|
||||
|
||||
print(output, " ", packet_log(*_pkt.data<Udp_packet const>(~0UL), _cfg));
|
||||
print(output, " ", packet_log(_pkt.data<Udp_packet const>(~0UL), _cfg));
|
||||
break;
|
||||
|
||||
case Ipv4_packet::Protocol::ICMP:
|
||||
|
||||
print(output, " ", packet_log(*_pkt.data<Icmp_packet const>(~0UL), _cfg));
|
||||
print(output, " ", packet_log(_pkt.data<Icmp_packet const>(~0UL), _cfg));
|
||||
break;
|
||||
|
||||
default: ; }
|
||||
@ -297,7 +297,7 @@ void Packet_log<Udp_packet>::print(Output &output) const
|
||||
}
|
||||
/* print encapsulated packet */
|
||||
if (Dhcp_packet::is_dhcp(&_pkt)) {
|
||||
print(output, " ", packet_log(*_pkt.data<Dhcp_packet const>(~0UL), _cfg));
|
||||
print(output, " ", packet_log(_pkt.data<Dhcp_packet const>(~0UL), _cfg));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,20 +119,20 @@ void Dhcp_client::handle_ip(Ethernet_frame ð, size_t eth_size)
|
||||
{
|
||||
throw Drop_packet_inform("DHCP client expects Ethernet targeting the router");
|
||||
}
|
||||
Ipv4_packet &ip = *eth.data<Ipv4_packet>(eth_size - sizeof(Ethernet_frame));
|
||||
Ipv4_packet &ip = eth.data<Ipv4_packet>(eth_size - sizeof(Ethernet_frame));
|
||||
|
||||
if (ip.protocol() != Ipv4_packet::Protocol::UDP) {
|
||||
throw Drop_packet_inform("DHCP client expects UDP packet");
|
||||
}
|
||||
Udp_packet &udp = *ip.data<Udp_packet>(eth_size - sizeof(Ethernet_frame)
|
||||
- sizeof(Ipv4_packet));
|
||||
Udp_packet &udp = ip.data<Udp_packet>(eth_size - sizeof(Ethernet_frame)
|
||||
- sizeof(Ipv4_packet));
|
||||
|
||||
if (!Dhcp_packet::is_dhcp(&udp)) {
|
||||
throw Drop_packet_inform("DHCP client expects DHCP packet");
|
||||
}
|
||||
Dhcp_packet &dhcp = *udp.data<Dhcp_packet>(eth_size - sizeof(Ethernet_frame)
|
||||
- sizeof(Ipv4_packet)
|
||||
- sizeof(Udp_packet));
|
||||
Dhcp_packet &dhcp = udp.data<Dhcp_packet>(eth_size - sizeof(Ethernet_frame)
|
||||
- sizeof(Ipv4_packet)
|
||||
- sizeof(Udp_packet));
|
||||
|
||||
if (dhcp.op() != Dhcp_packet::REPLY) {
|
||||
throw Drop_packet_inform("DHCP client expects DHCP reply");
|
||||
@ -206,7 +206,7 @@ void Dhcp_client::_send(Message_type msg_type,
|
||||
/* create ETH header of the request */
|
||||
Size_guard size;
|
||||
size.add(sizeof(Ethernet_frame));
|
||||
Ethernet_frame ð = *reinterpret_cast<Ethernet_frame *>(pkt_base);
|
||||
Ethernet_frame ð = *construct_at<Ethernet_frame>(pkt_base);
|
||||
eth.dst(Mac_address(0xff));
|
||||
eth.src(client_mac);
|
||||
eth.type(Ethernet_frame::Type::IPV4);
|
||||
@ -214,15 +214,9 @@ void Dhcp_client::_send(Message_type msg_type,
|
||||
/* create IP header of the request */
|
||||
enum { IPV4_TIME_TO_LIVE = 64 };
|
||||
size_t const ip_off = size.curr();
|
||||
Ipv4_packet &ip = *eth.data<Ipv4_packet>(size.left());
|
||||
size.add(sizeof(Ipv4_packet));
|
||||
Ipv4_packet &ip = eth.construct_at_data<Ipv4_packet>(size);
|
||||
ip.header_length(sizeof(Ipv4_packet) / 4);
|
||||
ip.version(4);
|
||||
ip.diff_service(0);
|
||||
ip.ecn(0);
|
||||
ip.identification(0);
|
||||
ip.flags(0);
|
||||
ip.fragment_offset(0);
|
||||
ip.time_to_live(IPV4_TIME_TO_LIVE);
|
||||
ip.protocol(Ipv4_packet::Protocol::UDP);
|
||||
ip.src(client_ip);
|
||||
@ -230,29 +224,18 @@ void Dhcp_client::_send(Message_type msg_type,
|
||||
|
||||
/* create UDP header of the request */
|
||||
size_t const udp_off = size.curr();
|
||||
Udp_packet &udp = *ip.data<Udp_packet>(size.left());
|
||||
size.add(sizeof(Udp_packet));
|
||||
Udp_packet &udp = ip.construct_at_data<Udp_packet>(size);
|
||||
udp.src_port(Port(Dhcp_packet::BOOTPC));
|
||||
udp.dst_port(Port(Dhcp_packet::BOOTPS));
|
||||
|
||||
/* create mandatory DHCP fields of the request */
|
||||
size_t const dhcp_off = size.curr();
|
||||
Dhcp_packet &dhcp = *udp.data<Dhcp_packet>(size.left());
|
||||
size.add(sizeof(Dhcp_packet));
|
||||
Dhcp_packet &dhcp = udp.construct_at_data<Dhcp_packet>(size);
|
||||
dhcp.op(Dhcp_packet::REQUEST);
|
||||
dhcp.htype(Dhcp_packet::Htype::ETH);
|
||||
dhcp.hlen(sizeof(Mac_address));
|
||||
dhcp.hops(0);
|
||||
dhcp.xid(0x12345678);
|
||||
dhcp.secs(0);
|
||||
dhcp.flags(0);
|
||||
dhcp.ciaddr(client_ip);
|
||||
dhcp.yiaddr(Ipv4_address());
|
||||
dhcp.siaddr(Ipv4_address());
|
||||
dhcp.giaddr(Ipv4_address());
|
||||
dhcp.client_mac(client_mac);
|
||||
dhcp.zero_fill_sname();
|
||||
dhcp.zero_fill_file();
|
||||
dhcp.default_magic_cookie();
|
||||
|
||||
/* append DHCP option fields to the request */
|
||||
|
@ -30,6 +30,7 @@ using Genode::uint32_t;
|
||||
using Genode::log;
|
||||
using Genode::error;
|
||||
using Genode::warning;
|
||||
using Genode::construct_at;
|
||||
using Genode::Signal_context_capability;
|
||||
using Genode::Signal_transmitter;
|
||||
|
||||
@ -169,9 +170,9 @@ static void *_prot_base(L3_protocol const prot,
|
||||
Ipv4_packet &ip)
|
||||
{
|
||||
switch (prot) {
|
||||
case L3_protocol::TCP: return ip.data<Tcp_packet>(prot_size);
|
||||
case L3_protocol::UDP: return ip.data<Udp_packet>(prot_size);
|
||||
case L3_protocol::ICMP: return ip.data<Icmp_packet>(prot_size);
|
||||
case L3_protocol::TCP: return &ip.data<Tcp_packet>(prot_size);
|
||||
case L3_protocol::UDP: return &ip.data<Udp_packet>(prot_size);
|
||||
case L3_protocol::ICMP: return &ip.data<Icmp_packet>(prot_size);
|
||||
default: throw Interface::Bad_transport_protocol(); }
|
||||
}
|
||||
|
||||
@ -464,22 +465,16 @@ void Interface::_send_dhcp_reply(Dhcp_server const &dhcp_srv,
|
||||
/* create ETH header of the reply */
|
||||
Size_guard size;
|
||||
size.add(sizeof(Ethernet_frame));
|
||||
Ethernet_frame ð = *reinterpret_cast<Ethernet_frame *>(pkt_base);
|
||||
Ethernet_frame ð = *construct_at<Ethernet_frame>(pkt_base);
|
||||
eth.dst(client_mac);
|
||||
eth.src(_router_mac);
|
||||
eth.type(Ethernet_frame::Type::IPV4);
|
||||
|
||||
/* create IP header of the reply */
|
||||
size_t const ip_off = size.curr();
|
||||
Ipv4_packet &ip = *eth.data<Ipv4_packet>(size.left());
|
||||
size.add(sizeof(Ipv4_packet));
|
||||
Ipv4_packet &ip = eth.construct_at_data<Ipv4_packet>(size);
|
||||
ip.header_length(sizeof(Ipv4_packet) / 4);
|
||||
ip.version(4);
|
||||
ip.diff_service(0);
|
||||
ip.ecn(0);
|
||||
ip.identification(0);
|
||||
ip.flags(0);
|
||||
ip.fragment_offset(0);
|
||||
ip.time_to_live(IPV4_TIME_TO_LIVE);
|
||||
ip.protocol(Ipv4_packet::Protocol::UDP);
|
||||
ip.src(local_intf.address);
|
||||
@ -487,28 +482,22 @@ void Interface::_send_dhcp_reply(Dhcp_server const &dhcp_srv,
|
||||
|
||||
/* create UDP header of the reply */
|
||||
size_t const udp_off = size.curr();
|
||||
Udp_packet &udp = *ip.data<Udp_packet>(size.left());
|
||||
size.add(sizeof(Udp_packet));
|
||||
Udp_packet &udp = ip.construct_at_data<Udp_packet>(size);
|
||||
udp.src_port(Port(Dhcp_packet::BOOTPS));
|
||||
udp.dst_port(Port(Dhcp_packet::BOOTPC));
|
||||
|
||||
/* create mandatory DHCP fields of the reply */
|
||||
Dhcp_packet &dhcp = *udp.data<Dhcp_packet>(size.left());
|
||||
size.add(sizeof(Dhcp_packet));
|
||||
Dhcp_packet &dhcp = udp.construct_at_data<Dhcp_packet>(size);
|
||||
dhcp.op(Dhcp_packet::REPLY);
|
||||
dhcp.htype(Dhcp_packet::Htype::ETH);
|
||||
dhcp.hlen(sizeof(Mac_address));
|
||||
dhcp.hops(0);
|
||||
dhcp.xid(xid);
|
||||
dhcp.secs(0);
|
||||
dhcp.flags(0);
|
||||
dhcp.ciaddr(msg_type == Dhcp_packet::Message_type::INFORM ? client_ip : Ipv4_address());
|
||||
dhcp.yiaddr(msg_type == Dhcp_packet::Message_type::INFORM ? Ipv4_address() : client_ip);
|
||||
if (msg_type == Dhcp_packet::Message_type::INFORM) {
|
||||
dhcp.ciaddr(client_ip); }
|
||||
else {
|
||||
dhcp.yiaddr(client_ip); }
|
||||
dhcp.siaddr(local_intf.address);
|
||||
dhcp.giaddr(Ipv4_address());
|
||||
dhcp.client_mac(client_mac);
|
||||
dhcp.zero_fill_sname();
|
||||
dhcp.zero_fill_file();
|
||||
dhcp.default_magic_cookie();
|
||||
|
||||
/* append DHCP option fields to the reply */
|
||||
@ -716,37 +705,30 @@ void Interface::_send_icmp_dst_unreachable(Ipv4_address_prefix const &local_intf
|
||||
/* create ETH header */
|
||||
Size_guard size;
|
||||
size.add(sizeof(Ethernet_frame));
|
||||
Ethernet_frame ð = *reinterpret_cast<Ethernet_frame *>(pkt_base);
|
||||
Ethernet_frame ð = *construct_at<Ethernet_frame>(pkt_base);
|
||||
eth.dst(req_eth.src());
|
||||
eth.src(_router_mac);
|
||||
eth.type(Ethernet_frame::Type::IPV4);
|
||||
|
||||
/* create IP header */
|
||||
size_t const ip_off = size.curr();
|
||||
Ipv4_packet &ip = *eth.data<Ipv4_packet>(size.left());
|
||||
size.add(sizeof(Ipv4_packet));
|
||||
Ipv4_packet &ip = eth.construct_at_data<Ipv4_packet>(size);
|
||||
ip.header_length(sizeof(Ipv4_packet) / 4);
|
||||
ip.version(4);
|
||||
ip.diff_service(0);
|
||||
ip.ecn(0);
|
||||
ip.identification(0);
|
||||
ip.flags(0);
|
||||
ip.fragment_offset(0);
|
||||
ip.time_to_live(IPV4_TIME_TO_LIVE);
|
||||
ip.protocol(Ipv4_packet::Protocol::ICMP);
|
||||
ip.src(local_intf.address);
|
||||
ip.dst(req_ip.src());
|
||||
|
||||
/* create ICMP header */
|
||||
Icmp_packet &icmp = *ip.data<Icmp_packet>(size.left());
|
||||
size.add(sizeof(Icmp_packet));
|
||||
Icmp_packet &icmp = ip.construct_at_data<Icmp_packet>(size);
|
||||
icmp.type(Icmp_packet::Type::DST_UNREACHABLE);
|
||||
icmp.code(code);
|
||||
icmp.rest_of_header(0);
|
||||
size_t icmp_data_size = req_ip.total_length();
|
||||
if (icmp_data_size > ICMP_MAX_DATA_SIZE) {
|
||||
icmp_data_size = ICMP_MAX_DATA_SIZE;
|
||||
}
|
||||
/* create ICMP data */
|
||||
size.add(icmp_data_size);
|
||||
Genode::memcpy(&icmp.data<char>(~0), &req_ip, icmp_data_size);
|
||||
|
||||
@ -890,7 +872,7 @@ void Interface::_handle_icmp(Ethernet_frame ð,
|
||||
{
|
||||
/* drop packet if ICMP checksum is invalid */
|
||||
size_t const icmp_sz = ip.total_length() - sizeof(Ipv4_packet);
|
||||
Icmp_packet &icmp = *ip.data<Icmp_packet>(icmp_sz);
|
||||
Icmp_packet &icmp = ip.data<Icmp_packet>(icmp_sz);
|
||||
size_t const icmp_data_sz = icmp_sz - sizeof(Icmp_packet);
|
||||
if (icmp.calc_checksum(icmp_data_sz) != icmp.checksum()) {
|
||||
throw Drop_packet_inform("bad ICMP checksum");
|
||||
@ -910,7 +892,7 @@ void Interface::_handle_ip(Ethernet_frame ð,
|
||||
Domain &local_domain)
|
||||
{
|
||||
/* read packet information */
|
||||
Ipv4_packet &ip = *eth.data<Ipv4_packet>(eth_size - sizeof(Ethernet_frame));
|
||||
Ipv4_packet &ip = eth.data<Ipv4_packet>(eth_size - sizeof(Ethernet_frame));
|
||||
Ipv4_address_prefix const &local_intf = local_domain.ip_config().interface;
|
||||
|
||||
/* try handling subnet-local IP packets */
|
||||
@ -933,13 +915,13 @@ void Interface::_handle_ip(Ethernet_frame ð,
|
||||
|
||||
/* try handling DHCP requests before trying any routing */
|
||||
if (prot == L3_protocol::UDP) {
|
||||
Udp_packet &udp = *ip.data<Udp_packet>(eth_size - sizeof(Ipv4_packet));
|
||||
Udp_packet &udp = ip.data<Udp_packet>(eth_size - sizeof(Ipv4_packet));
|
||||
|
||||
if (Dhcp_packet::is_dhcp(&udp)) {
|
||||
|
||||
/* get DHCP packet */
|
||||
Dhcp_packet &dhcp = *udp.data<Dhcp_packet>(eth_size - sizeof(Ipv4_packet)
|
||||
- sizeof(Udp_packet));
|
||||
Dhcp_packet &dhcp = udp.data<Dhcp_packet>(eth_size - sizeof(Ipv4_packet)
|
||||
- sizeof(Udp_packet));
|
||||
|
||||
if (dhcp.op() == Dhcp_packet::REQUEST) {
|
||||
try {
|
||||
@ -1063,16 +1045,19 @@ void Interface::_broadcast_arp_request(Ipv4_address const &src_ip,
|
||||
ETH_CRC_SZ = sizeof(Genode::uint32_t),
|
||||
PKT_SIZE = ETH_HDR_SZ + ETH_DAT_SZ + ETH_CRC_SZ,
|
||||
};
|
||||
using Size_guard = Genode::Size_guard_tpl<PKT_SIZE, Send_buffer_too_small>;
|
||||
send(PKT_SIZE, [&] (void *pkt_base) {
|
||||
|
||||
/* write Ethernet header */
|
||||
Ethernet_frame ð = *reinterpret_cast<Ethernet_frame *>(pkt_base);
|
||||
Size_guard size;
|
||||
size.add(sizeof(Ethernet_frame));
|
||||
Ethernet_frame ð = *construct_at<Ethernet_frame>(pkt_base);
|
||||
eth.dst(Mac_address(0xff));
|
||||
eth.src(_router_mac);
|
||||
eth.type(Ethernet_frame::Type::ARP);
|
||||
|
||||
/* write ARP header */
|
||||
Arp_packet &arp = *eth.data<Arp_packet>(PKT_SIZE - sizeof(Ethernet_frame));
|
||||
Arp_packet &arp = eth.construct_at_data<Arp_packet>(size);
|
||||
arp.hardware_address_type(Arp_packet::ETHERNET);
|
||||
arp.protocol_address_type(Arp_packet::IPV4);
|
||||
arp.hardware_address_size(sizeof(Mac_address));
|
||||
@ -1194,7 +1179,7 @@ void Interface::_handle_arp(Ethernet_frame ð,
|
||||
Domain &local_domain)
|
||||
{
|
||||
/* ignore ARP regarding protocols other than IPv4 via ethernet */
|
||||
Arp_packet &arp = *eth.data<Arp_packet>(eth_size - sizeof(Ethernet_frame));
|
||||
Arp_packet &arp = eth.data<Arp_packet>(eth_size - sizeof(Ethernet_frame));
|
||||
if (!arp.ethernet_ipv4()) {
|
||||
error("ARP for unknown protocol"); }
|
||||
|
||||
@ -1306,8 +1291,7 @@ void Interface::_handle_eth(void *const eth_base,
|
||||
}
|
||||
catch (Pointer<Domain>::Invalid) {
|
||||
if (_config().verbose_packets()) {
|
||||
Ethernet_frame *const eth = reinterpret_cast<Ethernet_frame *>(eth_base);
|
||||
log("[?] rcv ", *eth);
|
||||
log("[?] rcv ", *reinterpret_cast<Ethernet_frame *>(eth_base));
|
||||
}
|
||||
if (_config().verbose()) {
|
||||
log("[?] drop packet: no domain"); }
|
||||
|
Loading…
x
Reference in New Issue
Block a user