mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-20 14:13:09 +00:00
e370e08e01
Fixes #2105
279 lines
6.6 KiB
C++
279 lines
6.6 KiB
C++
/*
|
|
* \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 <base/exception.h>
|
|
#include <base/stdint.h>
|
|
|
|
#include <util/endian.h>
|
|
#include <net/ethernet.h>
|
|
#include <net/ipv4.h>
|
|
#include <net/udp.h>
|
|
|
|
namespace Net { class Dhcp_packet; }
|
|
|
|
|
|
/**
|
|
* 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 Net::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(__SIZE_TYPE__, 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 host_to_big_endian(_xid); }
|
|
Genode::uint16_t secs() { return host_to_big_endian(_secs); }
|
|
|
|
bool broadcast() { return _flags & BROADCAST; }
|
|
|
|
Ipv4_address ciaddr() {
|
|
return Ipv4_address(&_ciaddr); }
|
|
Ipv4_address yiaddr() {
|
|
return Ipv4_address(&_yiaddr); }
|
|
Ipv4_address siaddr() {
|
|
return Ipv4_address(&_siaddr); }
|
|
Ipv4_address giaddr() {
|
|
return Ipv4_address(&_giaddr); }
|
|
|
|
Mac_address client_mac() {
|
|
return 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 = host_to_big_endian(_xid); }
|
|
void secs(Genode::uint16_t secs) { _secs = host_to_big_endian(_secs); }
|
|
|
|
void broadcast(bool broadcast) {
|
|
_flags = broadcast ? BROADCAST : 0; }
|
|
|
|
void ciaddr(Ipv4_address ciaddr) {
|
|
ciaddr.copy(&_ciaddr); }
|
|
void yiaddr(Ipv4_address yiaddr) {
|
|
yiaddr.copy(&_yiaddr); }
|
|
void siaddr(Ipv4_address siaddr) {
|
|
siaddr.copy(&_siaddr); }
|
|
void giaddr(Ipv4_address giaddr) {
|
|
giaddr.copy(&_giaddr); }
|
|
|
|
void client_mac(Mac_address mac) {
|
|
mac.copy(&_chaddr); }
|
|
|
|
|
|
/*************************
|
|
** Convenience methods **
|
|
*************************/
|
|
|
|
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(__SIZE_TYPE__ size, void* addr) { return addr; }
|
|
|
|
} __attribute__((packed));
|
|
|
|
#endif /* _DHCP_H_ */
|