/* * \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-2013 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ #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: /*********************** ** ARP header fields ** ***********************/ Genode::uint16_t _hw_addr_type; Genode::uint16_t _prot_addr_type; Genode::uint8_t _hw_addr_sz; Genode::uint8_t _prot_addr_sz; Genode::uint16_t _opcode; Genode::uint8_t _src_mac_addr[Ethernet_frame::ADDR_LEN]; Genode::uint8_t _src_ip_addr[Ipv4_packet::ADDR_LEN]; Genode::uint8_t _dst_mac_addr[Ethernet_frame::ADDR_LEN]; Genode::uint8_t _dst_ip_addr[Ipv4_packet::ADDR_LEN]; public: /******************** ** ARP parameters ** ********************/ 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(); } /****************************** ** ARP field read-accessors ** ******************************/ /** * \return link layer type (Arp_packet::Hardware_type). */ Genode::uint16_t hardware_address_type() { return host_to_big_endian(_hw_addr_type); } /** * \return network/internet layer type (Ether_frame::EtherType). */ Genode::uint16_t protocol_address_type() { return host_to_big_endian(_prot_addr_type); } /** * \return size in bytes of hardware address. */ Genode::uint8_t hardware_address_size() { return _hw_addr_sz; } /** * \return size in bytes of protocol address. */ Genode::uint8_t protocol_address_size() { return _prot_addr_sz; } /** * \return operation code (Arp_packet::Opcode). */ Genode::uint16_t opcode() { return host_to_big_endian(_opcode); } /** * \return source MAC address. */ Ethernet_frame::Mac_address src_mac() { return Ethernet_frame::Mac_address(&_src_mac_addr); } /** * \return source IP address. */ Ipv4_packet::Ipv4_address src_ip() { return Ipv4_packet::Ipv4_address(&_src_ip_addr); } /** * \return destination MAC address. */ Ethernet_frame::Mac_address dst_mac() { return Ethernet_frame::Mac_address(&_dst_mac_addr); } /** * \return destination IP address. */ Ipv4_packet::Ipv4_address dst_ip() { return Ipv4_packet::Ipv4_address(&_dst_ip_addr); } /****************************** ** ARP field write-accessors ** ******************************/ /** * Set Operation code. * * \param opcode Arp_packet::Opcode to set. */ void opcode(Genode::uint16_t opcode) { _opcode = host_to_big_endian(opcode); } /** * Set source MAC address. * * \param src_mac_addr MAC address to set. */ void src_mac(Ethernet_frame::Mac_address src_mac_addr) { src_mac_addr.copy(&_src_mac_addr); } /** * Set source IP address. * * \param src_ip_addr IP address to set. */ void src_ip(Ipv4_packet::Ipv4_address src_ip_addr) { src_ip_addr.copy(&_src_ip_addr); } /** * Set destination MAC address. * * \param src_mac_addr MAC address to set. */ void dst_mac(Ethernet_frame::Mac_address dst_mac_addr) { dst_mac_addr.copy(&_dst_mac_addr); } /** * Set destination IP address. * * \param src_ip_addr IP address to set. */ void dst_ip(Ipv4_packet::Ipv4_address dst_ip_addr) { dst_ip_addr.copy(&_dst_ip_addr); } /*************************** ** Convenience functions ** ***************************/ /** * \return true when ARP packet really targets ethernet * address resolution with respect to IPv4 addresses. */ bool ethernet_ipv4() { return ( host_to_big_endian(_hw_addr_type) == ETHERNET && host_to_big_endian(_prot_addr_type) == Ethernet_frame::IPV4 && _hw_addr_sz == Ethernet_frame::ADDR_LEN && _prot_addr_sz == Ipv4_packet::ADDR_LEN); } /*************** ** Operators ** ***************/ /** * Placement new */ void * operator new(Genode::size_t size, void* addr) { return addr; } } __attribute__((packed)); #endif /* _NET__ARP_H_ */