1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-27 04:11:35 +01:00

Fixed merge conflics

This commit is contained in:
Santiago Alessandri
2011-08-19 09:43:49 -03:00
25 changed files with 960 additions and 122 deletions

View File

@@ -31,73 +31,31 @@
using namespace std;
Tins::PDU* Tins::ARP::make_arp_request(const std::string& iface,
const std::string& target,
const std::string& sender,
const uint8_t* hw_snd) {
uint32_t target_ip = Tins::Utils::resolve_ip(target);
uint32_t sender_ip = Tins::Utils::resolve_ip(sender);
return make_arp_request(iface, target_ip, sender_ip, hw_snd);
Tins::ARP::ARP(uint32_t target_ip, uint32_t sender_ip, const uint8_t *target_hw, const uint8_t *sender_hw) : PDU(0x0608) {
memset(&_arp, 0, sizeof(arphdr));
hw_addr_format(1);
prot_addr_format(0x0800);
hw_addr_length(6);
prot_addr_length(4);
sender_ip_addr(sender_ip);
target_ip_addr(target_ip);
if(sender_hw)
sender_hw_addr(sender_hw);
if(target_hw)
target_hw_addr(target_hw);
}
Tins::PDU* Tins::ARP::make_arp_request(const std::string& iface,
uint32_t target,
uint32_t sender,
const uint8_t* hw_snd) {
/* Create ARP packet and set its attributes */
ARP* arp = new ARP();
arp->target_ip_addr(target);
arp->sender_ip_addr(sender);
if (hw_snd) {
arp->sender_hw_addr(hw_snd);
}
arp->opcode(REQUEST);
/* Create the EthernetII PDU with the ARP PDU as its inner PDU */
EthernetII* eth = new EthernetII(iface, Tins::EthernetII::BROADCAST, hw_snd, arp);
return eth;
Tins::ARP::ARP(const uint8_t *buffer, uint32_t total_sz) : PDU(0x0608) {
if(total_sz < sizeof(arphdr))
throw std::runtime_error("Not enought size for an ARP header in the buffer.");
memcpy(&_arp, buffer, sizeof(arphdr));
total_sz -= sizeof(arphdr);
if(total_sz)
inner_pdu(new RawPDU(buffer + sizeof(arphdr), total_sz));
}
Tins::PDU* Tins::ARP::make_arp_reply(const string& iface,
const string& target,
const string& sender,
const uint8_t* hw_tgt,
const uint8_t* hw_snd) {
uint32_t target_ip = Tins::Utils::resolve_ip(target);
uint32_t sender_ip = Tins::Utils::resolve_ip(sender);
return make_arp_reply(iface, target_ip, sender_ip, hw_tgt, hw_snd);
}
Tins::PDU* Tins::ARP::make_arp_reply(const string& iface,
uint32_t target,
uint32_t sender,
const uint8_t* hw_tgt,
const uint8_t* hw_snd) {
/* Create ARP packet and set its attributes */
ARP* arp = new ARP();
arp->target_ip_addr(target);
arp->sender_ip_addr(sender);
arp->target_hw_addr(hw_tgt);
arp->sender_hw_addr(hw_snd);
arp->opcode(REPLY);
/* Create the EthernetII PDU with the ARP PDU as its inner PDU */
EthernetII* eth = new EthernetII(iface, hw_tgt, hw_snd, arp);
return eth;
}
Tins::ARP::ARP() : PDU(0x0608) {
std::memset(&_arp, 0, sizeof(arphdr));
this->hw_addr_format(1);
this->prot_addr_format(0x0800);
this->hw_addr_length(6);
this->prot_addr_length(4);
}
Tins::ARP::ARP(arphdr *arp_ptr) : PDU(Utils::net_to_host_s(0x0806)) {
Tins::ARP::ARP(const arphdr *arp_ptr) : PDU(Utils::net_to_host_s(0x0806)) {
memcpy(&_arp, arp_ptr, sizeof(arphdr));
}
@@ -182,10 +140,10 @@ bool Tins::ARP::matches_response(uint8_t *ptr, uint32_t total_sz) {
return arp_ptr->ar_sip == _arp.ar_tip && arp_ptr->ar_tip == _arp.ar_sip;
}
Tins::PDU *Tins::ARP::clone_packet(uint8_t *ptr, uint32_t total_sz) {
Tins::PDU *Tins::ARP::clone_packet(const uint8_t *ptr, uint32_t total_sz) {
if(total_sz < sizeof(arphdr))
return 0;
arphdr *arp_ptr = (arphdr*)ptr;
const arphdr *arp_ptr = (arphdr*)ptr;
PDU *child = 0, *cloned;
if(total_sz > sizeof(arphdr)) {
if((child = PDU::clone_inner_pdu(ptr + sizeof(arphdr), total_sz - sizeof(arphdr))) == 0)
@@ -195,3 +153,61 @@ Tins::PDU *Tins::ARP::clone_packet(uint8_t *ptr, uint32_t total_sz) {
cloned->inner_pdu(child);
return cloned;
}
Tins::PDU* Tins::ARP::make_arp_request(const string& iface,
const string& target,
const string& sender,
const uint8_t* hw_snd) {
uint32_t target_ip = Tins::Utils::resolve_ip(target);
uint32_t sender_ip = Tins::Utils::resolve_ip(sender);
return make_arp_request(iface, target_ip, sender_ip, hw_snd);
}
Tins::PDU* Tins::ARP::make_arp_request(const std::string& iface,
uint32_t target,
uint32_t sender,
const uint8_t* hw_snd) {
/* Create ARP packet and set its attributes */
ARP* arp = new ARP();
arp->target_ip_addr(target);
arp->sender_ip_addr(sender);
if (hw_snd) {
arp->sender_hw_addr(hw_snd);
}
arp->opcode(REQUEST);
/* Create the EthernetII PDU with the ARP PDU as its inner PDU */
EthernetII* eth = new EthernetII(iface, Tins::EthernetII::BROADCAST, hw_snd, arp);
return eth;
}
Tins::PDU* Tins::ARP::make_arp_reply(const string& iface,
const string& target,
const string& sender,
const uint8_t* hw_tgt,
const uint8_t* hw_snd) {
uint32_t target_ip = Tins::Utils::resolve_ip(target);
uint32_t sender_ip = Tins::Utils::resolve_ip(sender);
return make_arp_reply(iface, target_ip, sender_ip, hw_tgt, hw_snd);
}
Tins::PDU* Tins::ARP::make_arp_reply(const string& iface,
uint32_t target,
uint32_t sender,
const uint8_t* hw_tgt,
const uint8_t* hw_snd) {
/* Create ARP packet and set its attributes */
ARP* arp = new ARP();
arp->target_ip_addr(target);
arp->sender_ip_addr(sender);
arp->target_hw_addr(hw_tgt);
arp->sender_hw_addr(hw_snd);
arp->opcode(REPLY);
/* Create the EthernetII PDU with the ARP PDU as its inner PDU */
EthernetII* eth = new EthernetII(iface, hw_tgt, hw_snd, arp);
return eth;
}

View File

@@ -21,12 +21,13 @@
#include <cstring>
#include <cassert>
#include <iostream> //borrame
#include "utils.h"
#include "dhcp.h"
const uint32_t Tins::DHCP::MAX_DHCP_SIZE = 312;
using namespace std;
/* Magic cookie: uint32_t.
* end of options: 1 byte. */
Tins::DHCP::DHCP() : _size(sizeof(uint32_t) + 1) {
@@ -35,12 +36,19 @@ Tins::DHCP::DHCP() : _size(sizeof(uint32_t) + 1) {
hlen(6);
}
Tins::DHCP::DHCPOption::DHCPOption(uint8_t opt, uint8_t len, uint8_t *val) : option(opt), length(len) {
Tins::DHCP::~DHCP() {
while(_options.size()) {
delete[] _options.front().value;
_options.pop_front();
}
}
Tins::DHCP::DHCPOption::DHCPOption(uint8_t opt, uint8_t len, const 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) {
bool Tins::DHCP::add_option(Options opt, uint8_t len, const uint8_t *val) {
uint32_t opt_size = len + (sizeof(uint8_t) << 1);
if(_size + opt_size > MAX_DHCP_SIZE)
return false;
@@ -50,16 +58,53 @@ bool Tins::DHCP::add_option(Options opt, uint8_t len, uint8_t *val) {
}
bool Tins::DHCP::add_type_option(Flags type) {
return add_option(DHCP_MESSAGE_TYPE, 1, (uint8_t*)&type);
return add_option(DHCP_MESSAGE_TYPE, 1, (const uint8_t*)&type);
}
bool Tins::DHCP::add_server_identifier(uint32_t ip) {
return add_option(DHCP_SERVER_IDENTIFIER, 4, (uint8_t*)&ip);
return add_option(DHCP_SERVER_IDENTIFIER, 4, (const uint8_t*)&ip);
}
bool Tins::DHCP::add_lease_time(uint32_t time) {
time = Utils::net_to_host_l(time);
return add_option(DHCP_LEASE_TIME, 4, (uint8_t*)&time);
return add_option(DHCP_LEASE_TIME, 4, (const uint8_t*)&time);
}
bool Tins::DHCP::add_subnet_mask(uint32_t mask) {
return add_option(SUBNET_MASK, 4, (const uint8_t*)&mask);
}
bool Tins::DHCP::add_routers_option(const list<uint32_t> &routers) {
uint32_t size;
uint8_t *buffer = serialize_list(routers, size);
bool ret = add_option(ROUTERS, size, buffer);
delete[] buffer;
return ret;
}
bool Tins::DHCP::add_dns_options(const list<uint32_t> &dns) {
uint32_t size;
uint8_t *buffer = serialize_list(dns, size);
bool ret = add_option(DOMAIN_NAME_SERVERS, size, buffer);
delete[] buffer;
return ret;
}
bool Tins::DHCP::add_broadcast_option(uint32_t addr) {
return add_option(BROADCAST_ADDRESS, 4, (uint8_t*)&addr);
}
bool Tins::DHCP::add_domain_name(const string &name) {
return add_option(DOMAIN_NAME, name.size(), (const uint8_t*)name.c_str());
}
uint8_t *Tins::DHCP::serialize_list(const list<uint32_t> &int_list, uint32_t &sz) {
uint8_t *buffer = new uint8_t[int_list.size() * sizeof(uint32_t)];
uint32_t *ptr = (uint32_t*)buffer;
for(list<uint32_t>::const_iterator it = int_list.begin(); it != int_list.end(); ++it)
*(ptr++) = *it;
sz = sizeof(uint32_t) * int_list.size();
return buffer;
}
uint32_t Tins::DHCP::header_size() const {
@@ -69,6 +114,7 @@ uint32_t Tins::DHCP::header_size() const {
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);
// Magic cookie
*((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;
@@ -76,6 +122,7 @@ void Tins::DHCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const P
std::memcpy(ptr, it->value, it->length);
ptr += it->length;
}
// End of options
result[_size-1] = END;
vend(result, _size);
BootP::write_serialization(buffer, total_sz, parent);

View File

@@ -21,7 +21,7 @@
#include <cassert>
#include <cstring>
#include <stdexcept>
#ifndef WIN32
#include <net/ethernet.h>
#include <netpacket/packet.h>
@@ -29,6 +29,8 @@
#endif
#include "ethernetII.h"
#include "rawpdu.h"
#include "ip.h"
#include "arp.h"
#include "utils.h"
const uint8_t* Tins::EthernetII::BROADCAST = (const uint8_t*)"\xff\xff\xff\xff\xff\xff";
@@ -54,10 +56,31 @@ Tins::EthernetII::EthernetII(uint32_t iface_index, const uint8_t* dst_hw_addr, c
this->_eth.payload_type = 0;
}
Tins::EthernetII::EthernetII(const uint8_t *buffer, uint32_t total_sz) : PDU(ETHERTYPE_IP) {
if(total_sz < sizeof(ethhdr))
throw std::runtime_error("Not enought size for an ethernetII header in the buffer.");
memcpy(&_eth, buffer, sizeof(ethhdr));
PDU *next = 0;
switch(payload_type()) {
case ETHERTYPE_IP:
next = new Tins::IP(buffer + sizeof(ethhdr), total_sz - sizeof(ethhdr));
break;
case ETHERTYPE_ARP:
next = new Tins::ARP(buffer + sizeof(ethhdr), total_sz - sizeof(ethhdr));
break;
// Other protos plz
}
inner_pdu(next);
}
Tins::EthernetII::EthernetII(ethhdr *eth_ptr) : PDU(ETHERTYPE_IP) {
memcpy(&_eth, eth_ptr, sizeof(ethhdr));
}
uint16_t Tins::EthernetII::payload_type() const {
return Utils::net_to_host_s(_eth.payload_type);
}
void Tins::EthernetII::dst_hw_addr(const uint8_t* new_dst_mac) {
memcpy(this->_eth.dst_mac, new_dst_mac, 6);
}

View File

@@ -19,12 +19,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdexcept>
#include <cstring>
#include <cassert>
#ifndef WIN32
#include <netinet/in.h>
#endif
#include <cstring>
#include <cassert>
#include "icmp.h"
#include "rawpdu.h"
#include "utils.h"
@@ -48,7 +48,16 @@ Tins::ICMP::ICMP(Flags flag) : PDU(IPPROTO_ICMP) {
};
}
Tins::ICMP::ICMP(icmphdr *ptr) : PDU(IPPROTO_ICMP) {
Tins::ICMP::ICMP(const uint8_t *buffer, uint32_t total_sz) : PDU(IPPROTO_ICMP) {
if(total_sz < sizeof(icmphdr))
throw std::runtime_error("Not enought size for an ICMP header in the buffer.");
std::memcpy(&_icmp, buffer, sizeof(icmphdr));
total_sz -= sizeof(icmphdr);
if(total_sz)
inner_pdu(new RawPDU(buffer + sizeof(icmphdr), total_sz));
}
Tins::ICMP::ICMP(const icmphdr *ptr) : PDU(IPPROTO_ICMP) {
std::memcpy(&_icmp, ptr, sizeof(icmphdr));
}
@@ -177,10 +186,10 @@ bool Tins::ICMP::matches_response(uint8_t *ptr, uint32_t total_sz) {
return false;
}
Tins::PDU *Tins::ICMP::clone_packet(uint8_t *ptr, uint32_t total_sz) {
Tins::PDU *Tins::ICMP::clone_packet(const uint8_t *ptr, uint32_t total_sz) {
if(total_sz < sizeof(icmphdr))
return 0;
icmphdr *icmp_ptr = (icmphdr*)ptr;
const icmphdr *icmp_ptr = (icmphdr*)ptr;
PDU *child = 0, *cloned;
if(total_sz > sizeof(icmphdr)) {
if((child = PDU::clone_inner_pdu(ptr + sizeof(icmphdr), total_sz - sizeof(icmphdr))) == 0)

View File

@@ -19,12 +19,16 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdexcept>
#include <cstring>
#include <cassert>
#ifndef WIN32
#include <netinet/in.h>
#endif
#include "ip.h"
#include "tcp.h"
#include "udp.h"
#include "icmp.h"
#include "rawpdu.h"
#include "utils.h"
@@ -42,6 +46,29 @@ Tins::IP::IP(const string &ip_dst, const string &ip_src, PDU *child) : PDU(IPPRO
}
Tins::IP::IP(const uint8_t *buffer, uint32_t total_sz) : PDU(IPPROTO_IP) {
if(total_sz < sizeof(iphdr))
throw std::runtime_error("Not enought size for an IP header in the buffer.");
std::memcpy(&_ip, buffer, sizeof(iphdr));
/* Options... */
buffer += head_len() * sizeof(uint32_t);
total_sz -= head_len() * sizeof(uint32_t);
switch(_ip.protocol) {
case IPPROTO_TCP:
inner_pdu(new Tins::TCP(buffer, total_sz));
break;
case IPPROTO_UDP:
inner_pdu(new Tins::UDP(buffer, total_sz));
break;
case IPPROTO_ICMP:
inner_pdu(new Tins::ICMP(buffer, total_sz));
break;
default:
inner_pdu(new Tins::RawPDU(buffer, total_sz));
break;
}
}
Tins::IP::IP(const iphdr *ptr) : PDU(IPPROTO_IP) {
std::memcpy(&_ip, ptr, sizeof(iphdr));
/* Options... */
@@ -241,10 +268,10 @@ bool Tins::IP::matches_response(uint8_t *ptr, uint32_t total_sz) {
return false;
}
Tins::PDU *Tins::IP::clone_packet(uint8_t *ptr, uint32_t total_sz) {
Tins::PDU *Tins::IP::clone_packet(const uint8_t *ptr, uint32_t total_sz) {
if(total_sz < sizeof(iphdr))
return 0;
iphdr *ip_ptr = (iphdr*)ptr;
const iphdr *ip_ptr = (iphdr*)ptr;
uint32_t sz = ip_ptr->ihl * sizeof(uint32_t);
if(total_sz < sz)
return 0;

View File

@@ -20,7 +20,6 @@
*/
#include <cassert>
#include <iostream> //borrame
#include "utils.h"
#include "pdu.h"
#include "rawpdu.h"
@@ -69,7 +68,7 @@ void Tins::PDU::serialize(uint8_t *buffer, uint32_t total_sz, const PDU *parent)
write_serialization(buffer, total_sz, parent);
}
Tins::PDU *Tins::PDU::clone_inner_pdu(uint8_t *ptr, uint32_t total_sz) {
Tins::PDU *Tins::PDU::clone_inner_pdu(const uint8_t *ptr, uint32_t total_sz) {
PDU *child = 0;
if(inner_pdu()) {
child = inner_pdu()->clone_packet(ptr, total_sz);
@@ -77,7 +76,7 @@ Tins::PDU *Tins::PDU::clone_inner_pdu(uint8_t *ptr, uint32_t total_sz) {
return 0;
}
else
child = new RawPDU(ptr, total_sz, true);
child = new RawPDU(ptr, total_sz);
return child;
}

View File

@@ -24,11 +24,13 @@
#include "rawpdu.h"
Tins::RawPDU::RawPDU(uint8_t *pload, uint32_t size, bool copy) : PDU(255), _payload(pload), _payload_size(size), _owns_payload(copy) {
if(copy) {
_payload = new uint8_t[size];
std::memcpy(_payload, pload, size);
}
Tins::RawPDU::RawPDU(const uint8_t *pload, uint32_t size) : PDU(255), _payload_size(size), _owns_payload(true) {
_payload = new uint8_t[size];
std::memcpy(_payload, pload, size);
}
Tins::RawPDU::RawPDU(uint8_t *pload, uint32_t size) : PDU(255), _payload(pload), _payload_size(size), _owns_payload(false) {
}
Tins::RawPDU::~RawPDU() {

106
src/sniffer.cpp Normal file
View File

@@ -0,0 +1,106 @@
/*
* 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
*/
#include <stdexcept>
#include "sniffer.h"
#include "ethernetII.h"
using namespace std;
/** \cond */
struct LoopData {
pcap_t *handle;
Tins::AbstractSnifferHandler *c_handler;
LoopData(pcap_t *_handle, Tins::AbstractSnifferHandler *_handler) : handle(_handle), c_handler(_handler) { }
};
/** \endcond */
Tins::Sniffer::Sniffer(const string &device, unsigned max_packet_size) {
char error[PCAP_ERRBUF_SIZE];
if (pcap_lookupnet(device.c_str(), &ip, &mask, error) == -1)
throw runtime_error(error);
handle = pcap_open_live(device.c_str(), max_packet_size, 0, 0, error);
if(!handle)
throw runtime_error(error);
}
Tins::Sniffer::~Sniffer() {
if(handle)
pcap_close(handle);
}
bool Tins::Sniffer::compile_set_filter(const string &filter, bpf_program &prog) {
return (pcap_compile(handle, &prog, filter.c_str(), 0, ip) != -1 && pcap_setfilter(handle, &prog) != -1);
}
Tins::PDU *Tins::Sniffer::next_pdu(const string &filter) {
bpf_program prog;
if(!compile_set_filter(filter, prog))
return 0;
pcap_pkthdr header;
PDU *ret = 0;
while(!ret) {
const u_char *content = pcap_next(handle, &header);
try {
ret = new EthernetII((const uint8_t*)content, header.caplen);
}
catch(...) {
ret = 0;
}
}
pcap_freecode(&prog);
return ret;
}
void Tins::Sniffer::stop_sniff() {
pcap_breakloop(handle);
}
void Tins::Sniffer::sniff_loop(const std::string &filter, AbstractSnifferHandler *cback_handler, uint32_t max_packets) {
bpf_program prog;
if(compile_set_filter(filter, prog)) {
LoopData data(handle, cback_handler);
pcap_loop(handle, max_packets, Sniffer::callback_handler, (u_char*)&data);
pcap_freecode(&prog);
}
}
// Static
void Tins::Sniffer::callback_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {
try {
PDU *pdu = new EthernetII((const uint8_t*)packet, header->caplen);
LoopData *data = reinterpret_cast<LoopData*>(args);
bool ret_val = data->c_handler->handle(pdu);
delete pdu;
if(!ret_val)
pcap_breakloop(data->handle);
}
catch(...) {
}
}

View File

@@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdexcept>
#include <cstring>
#include <cassert>
#ifndef WIN32
@@ -41,6 +42,18 @@ Tins::TCP::TCP(uint16_t dport, uint16_t sport) : PDU(IPPROTO_TCP), _options_size
this->check(0);
}
Tins::TCP::TCP(const uint8_t *buffer, uint32_t total_sz) : PDU(IPPROTO_TCP) {
if(total_sz < sizeof(tcphdr))
throw std::runtime_error("Not enought size for an TCP header in the buffer.");
std::memcpy(&_tcp, buffer, sizeof(tcphdr));
/* Options... */
total_sz -= sizeof(tcphdr);
if(total_sz)
inner_pdu(new RawPDU(buffer + sizeof(tcphdr), total_sz));
}
Tins::TCP::~TCP() {
for(unsigned i(0); i < _options.size(); ++i)
delete[] _options[i].data;
@@ -92,6 +105,38 @@ void Tins::TCP::set_timestamp(uint32_t value, uint32_t reply) {
add_option(TSOPT, 8, (uint8_t*)&buffer);
}
uint8_t Tins::TCP::get_flag(Flags tcp_flag) {
switch(tcp_flag) {
case FIN:
return _tcp.fin;
break;
case SYN:
return _tcp.syn;
break;
case RST:
return _tcp.rst;
break;
case PSH:
return _tcp.psh;
break;
case ACK:
return _tcp.ack;
break;
case URG:
return _tcp.urg;
break;
case ECE:
return _tcp.ece;
break;
case CWR:
return _tcp.cwr;
break;
default:
return 0;
break;
};
}
void Tins::TCP::set_flag(Flags tcp_flag, uint8_t value) {
switch(tcp_flag) {
case FIN:

View File

@@ -19,11 +19,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdexcept>
#include <cassert>
#include <cstring>
#ifndef WIN32
#include <netinet/in.h>
#endif
#include <cassert>
#include <cstring>
#include "utils.h"
#include "udp.h"
#include "ip.h"
@@ -36,6 +37,15 @@ Tins::UDP::UDP(uint16_t dport, uint16_t sport, PDU *child) : PDU(IPPROTO_UDP, ch
_udp.len = 0;
}
Tins::UDP::UDP(const uint8_t *buffer, uint32_t total_sz) : PDU(IPPROTO_UDP) {
if(total_sz < sizeof(udphdr))
throw std::runtime_error("Not enought size for an UDP header in the buffer.");
std::memcpy(&_udp, buffer, sizeof(udphdr));
total_sz -= sizeof(udphdr);
if(total_sz)
inner_pdu(new RawPDU(buffer + sizeof(udphdr), total_sz));
}
void Tins::UDP::payload(uint8_t *new_payload, uint32_t new_payload_size) {
inner_pdu(new RawPDU(new_payload, new_payload_size));
}
@@ -61,14 +71,14 @@ void Tins::UDP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PD
const Tins::IP *ip_packet = dynamic_cast<const Tins::IP*>(parent);
if(inner_pdu())
length(sizeof(udphdr) + inner_pdu()->size());
std::memcpy(buffer, &_udp, sizeof(udphdr));
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));
PDU::do_checksum(buffer, buffer + total_sz);
while (checksum >> 16)
checksum = (checksum & 0xffff)+(checksum >> 16);
_udp.check = Utils::net_to_host_s(~checksum);
((udphdr*)buffer)->check = Utils::net_to_host_s(~checksum);
}
std::memcpy(buffer, &_udp, sizeof(udphdr));
_udp.check = 0;
}

View File

@@ -21,6 +21,7 @@
#include <stdexcept>
#include <sstream>
#include <fstream>
#include <stdexcept>
#include <cassert>
#include <cstring>
@@ -76,6 +77,29 @@ struct HWAddressCollector {
}
};
bool from_hex(const string &str, uint32_t &result) {
unsigned i(0);
result = 0;
while(i < str.size()) {
uint8_t tmp;
if(str[i] >= 'A' && str[i] <= 'F')
tmp = (str[i] - 'A' + 10);
else if(str[i] >= '0' && str[i] <= '9')
tmp = (str[i] - '0');
else
return false;
result = (result << 4) | tmp;
i++;
}
return true;
}
void skip_line(istream &input) {
int c = 0;
while(c != '\n' && input)
c = input.get();
}
/** \endcond */
uint32_t Tins::Utils::ip_to_int(const string &ip) {
@@ -179,6 +203,26 @@ bool Tins::Utils::resolve_hwaddr(const string &iface, uint32_t ip, uint8_t *buff
return false;
}
string Tins::Utils::interface_from_ip(uint32_t ip) {
ifstream input("/proc/net/route");
bool match(false);
string iface;
string destination, mask;
uint32_t destination_int, mask_int;
skip_line(input);
while(!match) {
input >> iface >> destination;
for(unsigned i(0); i < 6; ++i)
input >> mask;
from_hex(destination, destination_int);
from_hex(mask, mask_int);
if((ip & mask_int) == destination_int)
return iface;
skip_line(input);
}
return "";
}
set<string> Tins::Utils::network_interfaces() {
InterfaceCollector collector;
generic_iface_loop(collector);