net: ICMP protocol

Packet format and common utilities for the Internet Control Message
Protocol.

Issue #2732
This commit is contained in:
Martin Stein 2018-03-23 17:33:31 +01:00 committed by Christian Helmuth
parent 8ba26c612a
commit 365bd347a6
5 changed files with 158 additions and 3 deletions

View File

@ -0,0 +1,95 @@
/*
* \brief Internet Control Message Protocol
* \author Martin Stein
* \date 2018-03-23
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _NET__ICMP_H_
#define _NET__ICMP_H_
/* Genode includes */
#include <util/endian.h>
#include <base/exception.h>
namespace Genode { class Output; }
namespace Net { class Icmp_packet; }
class Net::Icmp_packet
{
private:
Genode::uint8_t _type;
Genode::uint8_t _code;
Genode::uint16_t _checksum;
union {
Genode::uint32_t _rest_of_header_u32[1];
Genode::uint16_t _rest_of_header_u16[2];
Genode::uint8_t _rest_of_header_u8[4];
};
Genode::uint8_t _data[0];
public:
struct Bad_data_type : Genode::Exception { };
enum class Type
{
ECHO_REPLY = 0,
DST_UNREACHABLE = 3,
ECHO_REQUEST = 8,
};
enum class Code
{
DST_NET_UNREACHABLE = 0,
ECHO_REQUEST = 0,
ECHO_REPLY = 0,
};
Genode::uint16_t calc_checksum(Genode::size_t data_sz) const;
/***************
** Accessors **
***************/
Type type() const { return (Type)_type; }
Code code() const { return (Code)_code; }
Genode::uint16_t checksum() const { return host_to_big_endian(_checksum); }
Genode::uint16_t query_id() const { return host_to_big_endian(_rest_of_header_u16[0]); }
Genode::uint16_t query_seq() const { return host_to_big_endian(_rest_of_header_u16[1]); }
Genode::uint32_t rest_of_header() const { return host_to_big_endian(_rest_of_header_u32[0]); }
template <typename T> T &data(Genode::size_t data_size)
{
if (data_size < sizeof(T)) {
throw Bad_data_type();
}
return *(T *)(_data);
}
void type(Type v) { _type = (Genode::uint8_t)v; }
void code(Code v) { _code = (Genode::uint8_t)v; }
void checksum(Genode::uint16_t v) { _checksum = host_to_big_endian(v); }
void rest_of_header(Genode::uint32_t v) { _rest_of_header_u32[0] = host_to_big_endian(v); }
void query_id(Genode::uint16_t v) { _rest_of_header_u16[0] = host_to_big_endian(v); }
void query_seq(Genode::uint16_t v) { _rest_of_header_u16[1] = host_to_big_endian(v); }
/*********
** log **
*********/
void print(Genode::Output &output) const;
};
#endif /* _NET__ICMP_H_ */

View File

@ -117,8 +117,9 @@ class Net::Ipv4_packet
enum class Protocol : Genode::uint8_t
{
TCP = 6,
UDP = 17,
ICMP = 1,
TCP = 6,
UDP = 17,
};
struct Bad_data_type : Genode::Exception { };

View File

@ -1,3 +1,4 @@
SRC_CC = ethernet.cc ipv4.cc dhcp.cc arp.cc udp.cc tcp.cc mac_address.cc
SRC_CC += ethernet.cc ipv4.cc dhcp.cc arp.cc udp.cc tcp.cc mac_address.cc
SRC_CC += icmp.cc
vpath %.cc $(REP_DIR)/src/lib/net

View File

@ -0,0 +1,54 @@
/*
* \brief Internet Control Message Protocol
* \author Martin Stein
* \date 2018-03-23
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Genode includes */
#include <net/icmp.h>
#include <base/output.h>
using namespace Net;
using namespace Genode;
void Net::Icmp_packet::print(Output &output) const
{
Genode::print(output, "\033[32mICMP\033[0m ", (unsigned)type(), " ",
(unsigned)code());
}
uint16_t Icmp_packet::calc_checksum(size_t data_sz) const
{
/* do not sum-up checksum itself */
register long sum = _type + _code;
addr_t addr = (addr_t)&_rest_of_header_u32;
size_t count = sizeof(Icmp_packet) + data_sz - sizeof(_type) -
sizeof(_code) - sizeof(_checksum);
/* sum-up rest of header and data */
while (count > 1) {
sum += *(uint16_t *)addr;
addr += sizeof(uint16_t);
count -= sizeof(uint16_t);
}
/* add left-over byte, if any */
if (count) {
sum += *(uint8_t *)addr;
}
/* fold 32-bit sum to 16 bits */
while (sum >> 16) {
sum = (sum & 0xffff) + (sum >> 16);
}
/* write to header */
uint16_t sum16 = ~sum;
return host_to_big_endian(sum16);
}

View File

@ -16,6 +16,7 @@
#include <net/udp.h>
#include <net/tcp.h>
#include <net/icmp.h>
#include <net/ipv4.h>
using namespace Genode;
@ -32,6 +33,9 @@ void Net::Ipv4_packet::print(Genode::Output &output) const
case Protocol::UDP:
Genode::print(output, *reinterpret_cast<Udp_packet const *>(_data));
break;
case Protocol::ICMP:
Genode::print(output, *reinterpret_cast<Icmp_packet const *>(_data));
break;
default: ; }
}