diff --git a/repos/os/include/net/dhcp.h b/repos/os/include/net/dhcp.h index 457df3f0cd..2ab35b9db5 100644 --- a/repos/os/include/net/dhcp.h +++ b/repos/os/include/net/dhcp.h @@ -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 ** diff --git a/repos/os/include/net/ethernet.h b/repos/os/include/net/ethernet.h index 69ecf960f0..d2283bebff 100644 --- a/repos/os/include/net/ethernet.h +++ b/repos/os/include/net/ethernet.h @@ -17,7 +17,7 @@ /* Genode includes */ #include #include - +#include #include #include @@ -72,20 +72,27 @@ class Net::Ethernet_frame struct Bad_data_type : Genode::Exception { }; - template T const *data(Genode::size_t data_size) const + template 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 T *data(Genode::size_t data_size) + template T &data(Genode::size_t data_size) { if (data_size < sizeof(T)) { throw Bad_data_type(); } - return (T *)(_data); + return *(T *)(_data); + } + + template + T &construct_at_data(SIZE_GUARD &size_guard) + { + size_guard.add(sizeof(T)); + return *Genode::construct_at(_data); } diff --git a/repos/os/include/net/ipv4.h b/repos/os/include/net/ipv4.h index e623a35fd1..a00bc928d5 100644 --- a/repos/os/include/net/ipv4.h +++ b/repos/os/include/net/ipv4.h @@ -18,7 +18,7 @@ #include #include #include - +#include #include #include @@ -124,20 +124,29 @@ class Net::Ipv4_packet struct Bad_data_type : Genode::Exception { }; - template T const *data(Genode::size_t data_size) const + template + 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 T *data(Genode::size_t data_size) + template + T &data(Genode::size_t data_size) { if (data_size < sizeof(T)) { throw Bad_data_type(); } - return (T *)(_data); + return *(T *)(_data); + } + + template + T &construct_at_data(SIZE_GUARD &size_guard) + { + size_guard.add(sizeof(T)); + return *Genode::construct_at(_data); } diff --git a/repos/os/include/net/udp.h b/repos/os/include/net/udp.h index e384434646..b7f92dbf84 100644 --- a/repos/os/include/net/udp.h +++ b/repos/os/include/net/udp.h @@ -53,20 +53,27 @@ class Net::Udp_packet struct Bad_data_type : Genode::Exception { }; - template T const *data(Genode::size_t data_size) const + template 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 T *data(Genode::size_t data_size) + template T &data(Genode::size_t data_size) { if (data_size < sizeof(T)) { throw Bad_data_type(); } - return (T *)(_data); + return *(T *)(_data); + } + + template + T &construct_at_data(SIZE_GUARD &size_guard) + { + size_guard.add(sizeof(T)); + return *Genode::construct_at(_data); } diff --git a/repos/os/src/app/ping/main.cc b/repos/os/src/app/ping/main.cc index ffe6f219fb..7f2ddc734d 100644 --- a/repos/os/src/app/ping/main.cc +++ b/repos/os/src/app/ping/main.cc @@ -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(ip_size); + Ipv4_packet &ip = eth.data(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(embed_icmp_sz); + Icmp_packet &embed_icmp = embed_ip.data(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_sz); + Icmp_packet &icmp = ip.data(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(eth_size - sizeof(Ethernet_frame)); + Arp_packet &arp = eth.data(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(pkt_base); + Size_guard size(buf_sz); + size.add(sizeof(Ethernet_frame)); + Ethernet_frame ð = *construct_at(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(PKT_SIZE - sizeof(Ethernet_frame)); + Arp_packet &arp = eth.construct_at_data(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(pkt_base); + Size_guard size(buf_sz); + size.add(sizeof(Ethernet_frame)); + Ethernet_frame ð = *construct_at(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(PKT_SIZE - sizeof(Ethernet_frame)); + Arp_packet &arp = eth.construct_at_data(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 size(buf_sz); size.add(sizeof(Ethernet_frame)); - Ethernet_frame ð = *reinterpret_cast(pkt_base); + Ethernet_frame ð = *construct_at(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(size.left()); - size.add(sizeof(Ipv4_packet)); + Ipv4_packet &ip = eth.construct_at_data(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(size.left()); - size.add(sizeof(Icmp_packet) + _icmp_data_sz); + Icmp_packet &icmp = ip.construct_at_data(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(_icmp_data_sz); char chr = 'a'; diff --git a/repos/os/src/server/nic_bridge/component.cc b/repos/os/src/server/nic_bridge/component.cc index 86dbbf7afd..f637d030f4 100644 --- a/repos/os/src/server/nic_bridge/component.cc +++ b/repos/os/src/server/nic_bridge/component.cc @@ -22,9 +22,9 @@ using namespace Net; bool Session_component::handle_arp(Ethernet_frame *eth, Genode::size_t size) { - Arp_packet *arp = eth->data(size - sizeof(Ethernet_frame)); - if (arp->ethernet_ipv4() && - arp->opcode() == Arp_packet::REQUEST) { + Arp_packet &arp = eth->data(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(size - sizeof(Ethernet_frame)); + Ipv4_packet &ip = eth->data(size - sizeof(Ethernet_frame)); - if (ip->protocol() == Ipv4_packet::Protocol::UDP) + if (ip.protocol() == Ipv4_packet::Protocol::UDP) { - Udp_packet *udp = ip->data(size - sizeof(Ethernet_frame) - - sizeof(Ipv4_packet)); - if (Dhcp_packet::is_dhcp(udp)) { - Dhcp_packet *dhcp = udp->data(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(size - sizeof(Ethernet_frame) + - sizeof(Ipv4_packet)); + if (Dhcp_packet::is_dhcp(&udp)) { + Dhcp_packet &dhcp = udp.data(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()); } } } diff --git a/repos/os/src/server/nic_bridge/nic.cc b/repos/os/src/server/nic_bridge/nic.cc index 8626d1ec4a..d5e8528a3c 100644 --- a/repos/os/src/server/nic_bridge/nic.cc +++ b/repos/os/src/server/nic_bridge/nic.cc @@ -24,37 +24,37 @@ using namespace Net; bool Net::Nic::handle_arp(Ethernet_frame *eth, Genode::size_t size) { - Arp_packet *arp = eth->data(size - sizeof(Ethernet_frame)); + Arp_packet &arp = eth->data(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(size - sizeof(Ethernet_frame)); + Ipv4_packet &ip = eth->data(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(size - sizeof(Ethernet_frame) - - sizeof(Ipv4_packet)); + Udp_packet &udp = ip.data(size - sizeof(Ethernet_frame) + - sizeof(Ipv4_packet)); /* is it a DHCP packet ? */ - if (Dhcp_packet::is_dhcp(udp)) { - Dhcp_packet *dhcp = udp->data(size - sizeof(Ethernet_frame) - - sizeof(Ipv4_packet) - - sizeof(Udp_packet)); + if (Dhcp_packet::is_dhcp(&udp)) { + Dhcp_packet &dhcp = udp.data(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().value(); + dhcp.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); diff --git a/repos/os/src/server/nic_dump/packet_log.cc b/repos/os/src/server/nic_dump/packet_log.cc index 394ff89643..a10c0ada09 100644 --- a/repos/os/src/server/nic_dump/packet_log.cc +++ b/repos/os/src/server/nic_dump/packet_log.cc @@ -157,12 +157,12 @@ void Packet_log::print(Output &output) const switch (_pkt.type()) { case Ethernet_frame::Type::ARP: - print(output, " ", packet_log(*_pkt.data(~0UL), _cfg)); + print(output, " ", packet_log(_pkt.data(~0UL), _cfg)); break; case Ethernet_frame::Type::IPV4: - print(output, " ", packet_log(*_pkt.data(~0UL), _cfg)); + print(output, " ", packet_log(_pkt.data(~0UL), _cfg)); break; default: ; @@ -212,17 +212,17 @@ void Packet_log::print(Output &output) const switch (_pkt.protocol()) { case Ipv4_packet::Protocol::TCP: - print(output, " ", packet_log(*_pkt.data(~0UL), _cfg)); + print(output, " ", packet_log(_pkt.data(~0UL), _cfg)); break; case Ipv4_packet::Protocol::UDP: - print(output, " ", packet_log(*_pkt.data(~0UL), _cfg)); + print(output, " ", packet_log(_pkt.data(~0UL), _cfg)); break; case Ipv4_packet::Protocol::ICMP: - print(output, " ", packet_log(*_pkt.data(~0UL), _cfg)); + print(output, " ", packet_log(_pkt.data(~0UL), _cfg)); break; default: ; } @@ -297,7 +297,7 @@ void Packet_log::print(Output &output) const } /* print encapsulated packet */ if (Dhcp_packet::is_dhcp(&_pkt)) { - print(output, " ", packet_log(*_pkt.data(~0UL), _cfg)); + print(output, " ", packet_log(_pkt.data(~0UL), _cfg)); } } diff --git a/repos/os/src/server/nic_router/dhcp_client.cc b/repos/os/src/server/nic_router/dhcp_client.cc index 8a6c020365..33ec8c3434 100644 --- a/repos/os/src/server/nic_router/dhcp_client.cc +++ b/repos/os/src/server/nic_router/dhcp_client.cc @@ -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(eth_size - sizeof(Ethernet_frame)); + Ipv4_packet &ip = eth.data(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(eth_size - sizeof(Ethernet_frame) - - sizeof(Ipv4_packet)); + Udp_packet &udp = ip.data(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(eth_size - sizeof(Ethernet_frame) - - sizeof(Ipv4_packet) - - sizeof(Udp_packet)); + Dhcp_packet &dhcp = udp.data(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(pkt_base); + Ethernet_frame ð = *construct_at(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(size.left()); - size.add(sizeof(Ipv4_packet)); + Ipv4_packet &ip = eth.construct_at_data(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(size.left()); - size.add(sizeof(Udp_packet)); + Udp_packet &udp = ip.construct_at_data(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(size.left()); - size.add(sizeof(Dhcp_packet)); + Dhcp_packet &dhcp = udp.construct_at_data(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 */ diff --git a/repos/os/src/server/nic_router/interface.cc b/repos/os/src/server/nic_router/interface.cc index 3bdb6470fe..c53a07a076 100644 --- a/repos/os/src/server/nic_router/interface.cc +++ b/repos/os/src/server/nic_router/interface.cc @@ -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(prot_size); - case L3_protocol::UDP: return ip.data(prot_size); - case L3_protocol::ICMP: return ip.data(prot_size); + case L3_protocol::TCP: return &ip.data(prot_size); + case L3_protocol::UDP: return &ip.data(prot_size); + case L3_protocol::ICMP: return &ip.data(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(pkt_base); + Ethernet_frame ð = *construct_at(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(size.left()); - size.add(sizeof(Ipv4_packet)); + Ipv4_packet &ip = eth.construct_at_data(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(size.left()); - size.add(sizeof(Udp_packet)); + Udp_packet &udp = ip.construct_at_data(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(size.left()); - size.add(sizeof(Dhcp_packet)); + Dhcp_packet &dhcp = udp.construct_at_data(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(pkt_base); + Ethernet_frame ð = *construct_at(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(size.left()); - size.add(sizeof(Ipv4_packet)); + Ipv4_packet &ip = eth.construct_at_data(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(size.left()); - size.add(sizeof(Icmp_packet)); + Icmp_packet &icmp = ip.construct_at_data(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(~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_sz); + Icmp_packet &icmp = ip.data(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(eth_size - sizeof(Ethernet_frame)); + Ipv4_packet &ip = eth.data(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(eth_size - sizeof(Ipv4_packet)); + Udp_packet &udp = ip.data(eth_size - sizeof(Ipv4_packet)); if (Dhcp_packet::is_dhcp(&udp)) { /* get DHCP packet */ - Dhcp_packet &dhcp = *udp.data(eth_size - sizeof(Ipv4_packet) - - sizeof(Udp_packet)); + Dhcp_packet &dhcp = udp.data(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; send(PKT_SIZE, [&] (void *pkt_base) { /* write Ethernet header */ - Ethernet_frame ð = *reinterpret_cast(pkt_base); + Size_guard size; + size.add(sizeof(Ethernet_frame)); + Ethernet_frame ð = *construct_at(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(PKT_SIZE - sizeof(Ethernet_frame)); + Arp_packet &arp = eth.construct_at_data(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(eth_size - sizeof(Ethernet_frame)); + Arp_packet &arp = eth.data(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::Invalid) { if (_config().verbose_packets()) { - Ethernet_frame *const eth = reinterpret_cast(eth_base); - log("[?] rcv ", *eth); + log("[?] rcv ", *reinterpret_cast(eth_base)); } if (_config().verbose()) { log("[?] drop packet: no domain"); }