/* * \brief DHCP related definitions * \author Stefan Kalkowski * \date 2010-08-19 */ /* * 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 _DHCP_H_ #define _DHCP_H_ /* Genode */ #include #include #include #include #include #include namespace Net { /** * The data-layout of this class conforms to an DHCP packet (RFC 2131). * * DHCP packet layout: * * =================================== * | 1 byte | 1 byte | 1 byte | 1 byte | * =================================== * | op | htype | hlen | hops | * ----------------------------------- * | connection-id (xid) | * ----------------------------------- * | seconds | flags | * ----------------------------------- * | client-ip-address | * ----------------------------------- * | your-ip-address | * ----------------------------------- * | server-ip-address | * ----------------------------------- * | relay-agent-ip-address | * ----------------------------------- * | client-hw-address | * | (16 bytes) | * ----------------------------------- * | sname | * | (64 bytes) | * ----------------------------------- * | file | * | (128 bytes) | * ----------------------------------- * | options | * | (312 bytes, optional) | * ----------------------------------- */ class Dhcp_packet { public: class No_dhcp_packet : Genode::Exception {}; class Client_hw_address { public: Genode::uint8_t addr[16]; }; private: /************************ ** DHCP packet fields ** ************************/ Genode::uint8_t _op; Genode::uint8_t _htype; Genode::uint8_t _hlen; Genode::uint8_t _hops; Genode::uint32_t _xid; Genode::uint16_t _secs; Genode::uint16_t _flags; Genode::uint8_t _ciaddr[Ipv4_packet::ADDR_LEN]; Genode::uint8_t _yiaddr[Ipv4_packet::ADDR_LEN]; Genode::uint8_t _siaddr[Ipv4_packet::ADDR_LEN]; Genode::uint8_t _giaddr[Ipv4_packet::ADDR_LEN]; Client_hw_address _chaddr; Genode::uint8_t _sname[64]; Genode::uint8_t _file[128]; Genode::uint32_t _magic_cookie; Genode::uint8_t _opts[0]; enum Flag { BROADCAST = 0x80 }; public: /** * This class represents the data layout of an DHCP option. */ class Option { private: Genode::uint8_t _code; Genode::uint8_t _len; Genode::uint8_t _value[0]; public: Option() {} Genode::uint8_t code() { return _code; } Genode::size_t length() { return _len; } void* value() { return _value; } /** * Placement new. */ void * operator new(Genode::size_t size, void* addr) { return addr; } } __attribute__((packed)); enum Opcode { REQUEST = 1, REPLY = 2, INVALID }; enum Udp_port { BOOTPS = 67, BOOTPC = 68 }; enum Option_type { REQ_IP_ADDR = 50, IP_LEASE_TIME = 51, OPT_OVERLOAD = 52, MSG_TYPE = 53, SRV_ID = 54, REQ_PARAMETER = 55, MESSAGE = 56, MAX_MSG_SZ = 57, RENEWAL = 58, REBINDING = 59, VENDOR = 60, CLI_ID = 61, TFTP_SRV_NAME = 66, BOOT_FILE = 67, END = 255 }; enum Message_type { DHCP_DISCOVER = 1, DHCP_OFFER = 2, DHCP_REQUEST = 3, DHCP_DECLINE = 4, DHCP_ACK = 5, DHCP_NAK = 6, DHCP_RELEASE = 7, DHCP_INFORM = 8 }; /***************** ** Constructor ** *****************/ Dhcp_packet(Genode::size_t size) { /* dhcp packet needs to fit in */ if (size < sizeof(Dhcp_packet)) throw No_dhcp_packet(); } /******************************* ** DHCP field read-accessors ** *******************************/ Genode::uint8_t op() { return _op; } Genode::uint8_t htype() { return _htype; } Genode::uint8_t hlen() { return _hlen; } Genode::uint8_t hops() { return _hops; } Genode::uint32_t xid() { return bswap(_xid); } Genode::uint16_t secs() { return bswap(_secs); } bool broadcast() { return _flags & BROADCAST; } Ipv4_packet::Ipv4_address ciaddr() { return Ipv4_packet::Ipv4_address(&_ciaddr); } Ipv4_packet::Ipv4_address yiaddr() { return Ipv4_packet::Ipv4_address(&_yiaddr); } Ipv4_packet::Ipv4_address siaddr() { return Ipv4_packet::Ipv4_address(&_siaddr); } Ipv4_packet::Ipv4_address giaddr() { return Ipv4_packet::Ipv4_address(&_giaddr); } Ethernet_frame::Mac_address client_mac() { return Ethernet_frame::Mac_address(&_chaddr); } const char* server_name() { return (const char*) &_sname; } const char* file() { return (const char*) &_file; } Option *option(Option_type op) { void *ptr = &_opts; while (true) { Option *ext = new (ptr) Option(); if (ext->code() == op) return ext; if (ext->code() == END || ext->code() == 0) break; ptr = ext + ext->length(); } return 0; } /******************************* ** DHCP field write-accessors ** *******************************/ void op(Genode::uint8_t op) { _op = op; } void htype(Genode::uint8_t htype) { _htype = htype; } void hlen(Genode::uint8_t hlen) { _hlen = hlen; } void hops(Genode::uint8_t hops) { _hops = hops; } void xid(Genode::uint32_t xid) { _xid = bswap(_xid); } void secs(Genode::uint16_t secs) { _secs = bswap(_secs); } void broadcast(bool broadcast) { _flags = broadcast ? BROADCAST : 0; } void ciaddr(Ipv4_packet::Ipv4_address ciaddr) { ciaddr.copy(&_ciaddr); } void yiaddr(Ipv4_packet::Ipv4_address yiaddr) { yiaddr.copy(&_yiaddr); } void siaddr(Ipv4_packet::Ipv4_address siaddr) { siaddr.copy(&_siaddr); } void giaddr(Ipv4_packet::Ipv4_address giaddr) { giaddr.copy(&_giaddr); } void client_mac(Ethernet_frame::Mac_address mac) { mac.copy(&_chaddr); } /*************************** ** Convenience functions ** ***************************/ static bool is_dhcp(Udp_packet *udp) { return ((udp->src_port() == Dhcp_packet::BOOTPC || udp->src_port() == Dhcp_packet::BOOTPS) && (udp->dst_port() == Dhcp_packet::BOOTPC || udp->dst_port() == Dhcp_packet::BOOTPS)); } /*************** ** Operators ** ***************/ /** * Placement new. */ void * operator new(Genode::size_t size, void* addr) { return addr; } } __attribute__((packed)); } #endif /* _DHCP_H_ */