/*
* \brief Address resolution protocol
* \author Stefan Kalkowski
* \date 2010-08-24
*
* ARP is used to determine a network host's link layer or
* hardware address when only its Network Layer address is known.
*/
/*
* Copyright (C) 2010-2017 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__ARP_H_
#define _NET__ARP_H_
/* Genode */
#include
#include
#include
#include
#include
namespace Net { class Arp_packet; }
/**
* Data layout of this class conforms to an ARP-packet (RFC 826)
*
* It's reduced to Internet protocol (IPv4) over Ethernet.
*
* ARP-packet-format:
*
* --------------------------------------------------------------------
* | Bit 0-7 | Bit 8-15 | Bit 16-23 | Bit 24-31 |
* --------------------------------------------------------------------
* | hw.addr.type | prot.addr.type |
* --------------------------------------------------------------------
* | hw.addr.size | prot.addr.size | operation |
* --------------------------------------------------------------------
* | source-mac-address |
* --------------------------------------------------------------------
* | source-mac-address | source-ip-address |
* --------------------------------------------------------------------
* | source-ip-address | dest.-mac-address |
* --------------------------------------------------------------------
* | dest.-mac-address |
* --------------------------------------------------------------------
* | dest.-ip-address |
* --------------------------------------------------------------------
*/
class Net::Arp_packet
{
private:
Genode::uint16_t _hardware_address_type;
Genode::uint16_t _protocol_address_type;
Genode::uint8_t _hardware_address_size;
Genode::uint8_t _protocol_address_size;
Genode::uint16_t _opcode;
Genode::uint8_t _src_mac[Ethernet_frame::ADDR_LEN];
Genode::uint8_t _src_ip[Ipv4_packet::ADDR_LEN];
Genode::uint8_t _dst_mac[Ethernet_frame::ADDR_LEN];
Genode::uint8_t _dst_ip[Ipv4_packet::ADDR_LEN];
public:
/********************
** ARP parameters **
********************/
enum Protocol_address_type { IPV4 = 0x0800 };
enum Hardware_type {
ETHERNET = 0x0001,
EXP_ETHERNET = 0x0002,
AX_25 = 0x0003,
TOKEN_RING = 0x0004,
CHAOS = 0x0005,
IEEE802_NET = 0x0006,
ARCNET = 0x0007,
HYPERCHANNEL = 0x0008,
LANSTAR = 0x0009,
AUTONET = 0x000A,
LOCALTALK = 0x000B,
LOCALNET = 0x000C,
ULTRA_LINK = 0x000D,
SMDS = 0x000E,
FRAME_RELAY = 0x000F,
ATM_1 = 0x0010,
HDLC = 0x0011,
FIBRE_CHANNEL = 0x0012,
ATM_2 = 0x0013,
SERIAL_LINE = 0x0014,
ATM_3 = 0x0015,
MIL_STD_188_220 = 0x0016,
METRICOM = 0x0017,
IEEE1394 = 0x0018,
MAPOS = 0x0019,
TWINAXIAL = 0x001A,
EUI_64 = 0x001B,
HIPARP = 0x001C,
IP_AND_ARP_OVER_ISO7816 = 0x001D,
ARPSEC = 0x001E,
IPSEC_TUNNEL = 0x001F,
INFINIBAND = 0x0020,
TIA_102 = 0x0021,
WIEGAND_INTERFACE = 0x0022,
Pure_IP = 0x0023,
HW_EXP1 = 0x0024,
HFI = 0x0025,
HW_EXP2 = 0x0100,
};
enum Opcode {
REQUEST = 0x0001,
REPLY = 0x0002,
REQUEST_REVERSE = 0x0003,
REPLY_REVERSE = 0x0004,
DRARP_REQUEST = 0x0005,
DRARP_REPLY = 0x0006,
DRARP_ERROR = 0x0007,
INARP_REQUEST = 0x0008,
INARP_REPLY = 0x0009,
ARP_NAK = 0x000A,
MARS_REQUEST = 0x000B,
MARS_MULTI = 0x000C,
MARS_MSERV = 0x000D,
MARS_JOIN = 0x000E,
MARS_LEAVE = 0x000F,
MARS_NAK = 0x0010,
MARS_UNSERV = 0x0011,
MARS_SJOIN = 0x0012,
MARS_SLEAVE = 0x0013,
MARS_GROUPLIST_REQUEST = 0x0014,
MARS_GROUPLIST_REPLY = 0x0015,
MARS_REDIRECT_MAP = 0x0016,
MAPOS_UNARP = 0x0017,
OP_EXP1 = 0x0018,
OP_EXP2 = 0x0019
};
/**
* Exception used to indicate protocol violation.
*/
class No_arp_packet : Genode::Exception {};
/*****************
** Constructor **
*****************/
Arp_packet(Genode::size_t size) {
/* arp packet needs to fit in */
if (size < sizeof(Arp_packet))
throw No_arp_packet();
}
/***************
** Accessors **
***************/
Genode::uint16_t hardware_address_type() const { return host_to_big_endian(_hardware_address_type); }
Genode::uint16_t protocol_address_type() const { return host_to_big_endian(_protocol_address_type); }
Genode::uint8_t hardware_address_size() const { return _hardware_address_size; }
Genode::uint8_t protocol_address_size() const { return _protocol_address_size; }
Genode::uint16_t opcode() const { return host_to_big_endian(_opcode); }
Mac_address src_mac() const { return Mac_address((void *)&_src_mac); }
Ipv4_address src_ip() const { return Ipv4_address((void *)&_src_ip); }
Mac_address dst_mac() const { return Mac_address((void *)&_dst_mac); }
Ipv4_address dst_ip() const { return Ipv4_address((void *)&_dst_ip); }
void hardware_address_type(Genode::uint16_t v) { _hardware_address_type = host_to_big_endian(v); }
void protocol_address_type(Genode::uint16_t v) { _protocol_address_type = host_to_big_endian(v); }
void hardware_address_size(Genode::uint8_t v) { _hardware_address_size = v; }
void protocol_address_size(Genode::uint8_t v) { _protocol_address_size = v; }
void opcode(Genode::uint16_t v) { _opcode = host_to_big_endian(v); }
void src_mac(Mac_address v) { v.copy(&_src_mac); }
void src_ip(Ipv4_address v) { v.copy(&_src_ip); }
void dst_mac(Mac_address v) { v.copy(&_dst_mac); }
void dst_ip(Ipv4_address v) { v.copy(&_dst_ip); }
/***************************
** Convenience functions **
***************************/
/**
* \return true when ARP packet really targets ethernet
* address resolution with respect to IPv4 addresses.
*/
bool ethernet_ipv4() const {
return ( host_to_big_endian(_hardware_address_type) == ETHERNET
&& host_to_big_endian(_protocol_address_type) == (Genode::uint16_t)Ethernet_frame::Type::IPV4
&& _hardware_address_size == Ethernet_frame::ADDR_LEN
&& _protocol_address_size == Ipv4_packet::ADDR_LEN);
}
/***************
** Operators **
***************/
/**
* Placement new
*/
void * operator new(__SIZE_TYPE__ size, void* addr) { return addr; }
/*********
** Log **
*********/
void print(Genode::Output &output) const;
} __attribute__((packed));
#endif /* _NET__ARP_H_ */