1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-23 02:35:57 +01:00

Added DHCP class. It's now working yet.

This commit is contained in:
Matias Fontanini
2011-08-17 12:16:48 -03:00
parent bdadcbb47d
commit c49806603b
8 changed files with 269 additions and 17 deletions

View File

@@ -133,14 +133,14 @@ namespace Tins {
/** \brief Getter for the vend field.
* \return The vend field for this BootP PDU.
*/
uint8_t *vend() { return _bootp.vend; }
uint8_t *vend() { return _vend; }
/** \brief Getter for the vend field.
*/
uint32_t vend_size() const { return _vend_size; }
/** \brief Getter for the header size.
* \return Returns the ARP header size.
* \return Returns the BOOTP header size.
* \sa PDU::header_size
*/
uint32_t header_size() const;
@@ -221,6 +221,8 @@ namespace Tins {
* \param size The size of the new vend field.
*/
void vend(uint8_t *new_vend, uint32_t size);
protected:
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
private:
/**
* Struct that represents the Bootp datagram.
@@ -242,7 +244,6 @@ namespace Tins {
uint8_t file[128];
} __attribute__((__packed__));
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
bootphdr _bootp;
uint8_t *_vend;

184
include/dhcp.h Normal file
View File

@@ -0,0 +1,184 @@
/*
* libtins is a net packet wrapper library for crafting and
* interpreting sniffed packets.
*
* Copyright (C) 2011 Nasel
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __DHCP_H
#define __DHCP_H
#include <list>
#include "bootp.h"
namespace Tins {
/** \brief Class that represents the DHCP PDU.
*
* The end option is added automatically at the end of the option list.
*/
class DHCP : public BootP {
public:
/** \brief DHCP flags.
*/
enum Flags {
DHCPDISCOVER = 1,
DHCPOFFER = 2,
DHCPREQUEST = 3,
DHCPDECLINE = 4,
DHCPACK = 5,
DHCPNAK = 6,
DHCPRELEASE = 7,
DHCPINFORM = 8
};
/** \brief DHCP options enum.
*/
enum Options {
PAD,
SUBNET_MASK,
TIME_OFFSET,
ROUTERS,
TIME_SERVERS,
NAME_SERVERS,
DOMAIN_NAME_SERVERS,
LOG_SERVERS,
COOKIE_SERVERS,
LPR_SERVERS,
IMPRESS_SERVERS,
RESOURCE_LOCATION_SERVERS,
HOST_NAME,
BOOT_SIZE,
MERIT_DUMP,
DOMAIN_NAME,
SWAP_SERVER,
ROOT_PATH,
EXTENSIONS_PATH,
IP_FORWARDING,
NON_LOCAL_SOURCE_ROUTING,
POLICY_FILTER,
MAX_DGRAM_REASSEMBLY,
DEFAULT_IP_TTL,
PATH_MTU_AGING_TIMEOUT,
PATH_MTU_PLATEAU_TABLE,
INTERFACE_MTU,
ALL_SUBNETS_LOCAL,
BROADCAST_ADDRESS,
PERFORM_MASK_DISCOVERY,
MASK_SUPPLIER,
ROUTER_DISCOVERY,
ROUTER_SOLICITATION_ADDRESS,
STATIC_ROUTES,
TRAILER_ENCAPSULATION,
ARP_CACHE_TIMEOUT,
IEEE802_3_ENCAPSULATION,
DEFAULT_TCP_TTL,
TCP_KEEPALIVE_INTERVAL,
TCP_KEEPALIVE_GARBAGE,
NIS_DOMAIN,
NIS_SERVERS,
NTP_SERVERS,
VENDOR_ENCAPSULATED_OPTIONS,
NETBIOS_NAME_SERVERS,
NETBIOS_DD_SERVER,
NETBIOS_NODE_TYPE,
NETBIOS_SCOPE,
FONT_SERVERS,
X_DISPLAY_MANAGER,
DHCP_REQUESTED_ADDRESS,
DHCP_LEASE_TIME,
DHCP_OPTION_OVERLOAD,
DHCP_MESSAGE_TYPE,
DHCP_SERVER_IDENTIFIER,
DHCP_PARAMETER_REQUEST_LIST,
DHCP_MESSAGE,
DHCP_MAX_MESSAGE_SIZE,
DHCP_RENEWAL_TIME,
DHCP_REBINDING_TIME,
VENDOR_CLASS_IDENTIFIER,
DHCP_CLIENT_IDENTIFIER,
NWIP_DOMAIN_NAME,
NWIP_SUBOPTIONS,
USER_CLASS = 77,
FQDN = 81,
DHCP_AGENT_OPTIONS = 82,
SUBNET_SELECTION = 118,
AUTHENTICATE = 210,
END = 255
};
/** \brief DHCP options struct.
*/
struct DHCPOption {
uint8_t option, length;
uint8_t *value;
DHCPOption(uint8_t opt, uint8_t len, uint8_t *val);
};
/** \brief Creates an instance of DHCP.
*
* This sets the hwtype and hlen fields to match the ethernet
* type and length.
*/
DHCP();
/** \brief Adds a new option to this DHCP PDU.
*
* This copies the value buffer. Adding options may fail if
* there's not enough size to hold a new option.
* \param opt The option identifier.
* \param len The length of the value field.
* \param val The value of this option.
* \return True if the option was added successfully.
*/
bool add_option(Options opt, uint8_t len, uint8_t *val);
/** \brief Adds a type option the the option list.
* \param type The type of this DHCP PDU.
*/
void add_type_option(Flags type);
/** \brief Getter for the options list.
* \return The option list.
*/
const std::list<DHCPOption> options() const { return _options; }
/**
* \brief Getter for the PDU's type.
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::UDP; }
/** \brief Getter for the header size.
* \return Returns the BOOTP header size.
* \sa PDU::header_size
*/
uint32_t header_size() const;
private:
static const uint32_t MAX_DHCP_SIZE;
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
std::list<DHCPOption> _options;
uint32_t _size;
};
};
#endif

View File

@@ -56,7 +56,8 @@ namespace Tins {
ARP,
TCP,
UDP,
ICMP
ICMP,
DHCP
};
/** \brief PDU constructor

View File

@@ -41,7 +41,7 @@ namespace Tins {
* \param dport Destination port.
* \param sport Source port.
* */
UDP(uint16_t sport = 0, uint16_t dport = 0);
UDP(uint16_t dport = 0, uint16_t sport = 0, PDU *child = 0);
/** \brief Returns the destination port
@@ -63,6 +63,12 @@ namespace Tins {
* \param new_sport The new source port.
*/
void sport(uint16_t new_sport);
/** \brief Getter for the length field.
* \param new_len The new length field.
* \return The length field.
*/
void length(uint16_t new_len);
/** \brief Set the payload.
*
@@ -88,7 +94,6 @@ namespace Tins {
* \sa PDU::pdu_type
*/
PDUType pdu_type() const { return PDU::UDP; }
private:
struct udphdr {
uint16_t sport;

View File

@@ -4,16 +4,18 @@
#include "utils.h"
Tins::BootP::BootP() : PDU(255) {
Tins::BootP::BootP() : PDU(255), _vend_size(64) {
_vend = new uint8_t[64];
std::memset(&_bootp, 0, sizeof(bootphdr));
std::memset(_vend, 0, 64);
}
Tins::BootP::~BootP() {
delete[] vend;
delete[] _vend;
}
uint32_t Tins::BootP::header_size() const {
return sizeof(bootphdr);
return sizeof(bootphdr) + _vend_size;
}
void Tins::BootP::opcode(uint8_t new_opcode) {
@@ -61,7 +63,7 @@ void Tins::BootP::giaddr(uint32_t new_giaddr) {
}
void Tins::BootP::chaddr(uint8_t *new_chaddr) {
std::memcpy(_bootp.chaddr, new_chaddr, sizeof(_bootp.chaddr));
std::memcpy(_bootp.chaddr, new_chaddr, _bootp.hlen);
}
void Tins::BootP::sname(uint8_t *new_sname) {
@@ -80,6 +82,7 @@ void Tins::BootP::vend(uint8_t *new_vend, uint32_t size) {
}
void Tins::BootP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
assert(total_sz >= sizeof(bootphdr));
assert(total_sz >= sizeof(bootphdr) + _vend_size);
std::memcpy(buffer, &_bootp, sizeof(bootphdr));
std::memcpy(buffer + sizeof(bootphdr), _vend, _vend_size);
}

52
src/dhcp.cpp Normal file
View File

@@ -0,0 +1,52 @@
#include <cstring>
#include <cassert>
#include <iostream> //borrame
#include "utils.h"
#include "dhcp.h"
const uint32_t Tins::DHCP::MAX_DHCP_SIZE = 312;
/* Magic cookie: uint32_t.
* end of options: 1 byte. */
Tins::DHCP::DHCP() : _size(sizeof(uint32_t) + 1) {
opcode(BOOTREQUEST);
htype(1); //ethernet
hlen(6);
}
Tins::DHCP::DHCPOption::DHCPOption(uint8_t opt, uint8_t len, uint8_t *val) : option(opt), length(len) {
value = new uint8_t[len];
std::memcpy(value, val, len);
}
bool Tins::DHCP::add_option(Options opt, uint8_t len, uint8_t *val) {
uint32_t opt_size = len + (sizeof(uint8_t) << 1);
if(_size + opt_size > MAX_DHCP_SIZE)
return false;
_options.push_back(DHCPOption((uint8_t)opt, len, val));
_size += opt_size;
return true;
}
void Tins::DHCP::add_type_option(Flags type) {
add_option(DHCP_MESSAGE_TYPE, 1, (uint8_t*)&type);
}
uint32_t Tins::DHCP::header_size() const {
return BootP::header_size() - vend_size() + _size;
}
void Tins::DHCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
assert(total_sz >= header_size());
uint8_t *result = new uint8_t[_size], *ptr = result + sizeof(uint32_t);
*((uint32_t*)result) = Utils::net_to_host_l(0x63825363);
for(std::list<DHCPOption>::const_iterator it = _options.begin(); it != _options.end(); ++it) {
*(ptr++) = it->option;
*(ptr++) = it->length;
std::memcpy(ptr++, it->value, it->length);
}
result[_size-1] = END;
vend(result, _size);
BootP::write_serialization(buffer, total_sz, parent);
}

View File

@@ -20,6 +20,7 @@
*/
#include <cassert>
#include <iostream> //borrame
#include "utils.h"
#include "pdu.h"
#include "rawpdu.h"

View File

@@ -29,24 +29,27 @@
#include "ip.h"
#include "rawpdu.h"
Tins::UDP::UDP(uint16_t sport, uint16_t dport) : PDU(IPPROTO_UDP) {
_udp.sport = sport;
_udp.dport = dport;
Tins::UDP::UDP(uint16_t dport, uint16_t sport, PDU *child) : PDU(IPPROTO_UDP, child) {
this->dport(dport);
this->sport(sport);
_udp.check = 0;
_udp.len = 0;
}
void Tins::UDP::payload(uint8_t *new_payload, uint32_t new_payload_size) {
inner_pdu(new RawPDU(new_payload, new_payload_size));
_udp.len = Utils::net_to_host_s(sizeof(udphdr) + new_payload_size);
}
void Tins::UDP::dport(uint16_t new_dport) {
_udp.dport = new_dport;
_udp.dport = Utils::net_to_host_s(new_dport);
}
void Tins::UDP::sport(uint16_t new_sport) {
_udp.sport = new_sport;
_udp.sport = Utils::net_to_host_s(new_sport);
}
void Tins::UDP::length(uint16_t new_len) {
_udp.len = Utils::net_to_host_s(new_len);
}
uint32_t Tins::UDP::header_size() const {
@@ -56,6 +59,8 @@ uint32_t Tins::UDP::header_size() const {
void Tins::UDP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
assert(total_sz >= sizeof(udphdr));
const Tins::IP *ip_packet = dynamic_cast<const Tins::IP*>(parent);
if(inner_pdu())
length(sizeof(udphdr) + inner_pdu()->size());
if(!_udp.check && ip_packet) {
uint32_t checksum = PDU::pseudoheader_checksum(ip_packet->source_address(), ip_packet->dest_address(), size(), IPPROTO_UDP) +
PDU::do_checksum(buffer + sizeof(udphdr), buffer + total_sz) + PDU::do_checksum((uint8_t*)&_udp, ((uint8_t*)&_udp) + sizeof(udphdr));