mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Use pcap_sendpacket to send packets if this mode is enabled.
This commit is contained in:
@@ -81,6 +81,12 @@ IF(LIBTINS_ENABLE_DOT11)
|
||||
ENDIF(LIBTINS_ENABLE_WPA2)
|
||||
ENDIF(LIBTINS_ENABLE_DOT11)
|
||||
|
||||
OPTION(LIBTINS_USE_PCAP_SENDPACKET "Use pcap_sendpacket to send l2 packets" OFF)
|
||||
IF(LIBTINS_USE_PCAP_SENDPACKET)
|
||||
SET(HAVE_PACKET_SENDER_PCAP_SENDPACKET ON)
|
||||
MESSAGE(STATUS "Using pcap_sendpacket to send l2 packets.")
|
||||
ENDIF(LIBTINS_USE_PCAP_SENDPACKET)
|
||||
|
||||
# Add a target to generate API documentation using Doxygen
|
||||
FIND_PACKAGE(Doxygen QUIET)
|
||||
IF(DOXYGEN_FOUND)
|
||||
|
||||
@@ -10,4 +10,7 @@
|
||||
/* Have WPA2 decryption library */
|
||||
#cmakedefine HAVE_WPA2_DECRYPTION
|
||||
|
||||
/* Use pcap_sendpacket to send l2 packets */
|
||||
#cmakedefine HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
|
||||
#endif // TINS_CONFIG_H
|
||||
|
||||
@@ -145,13 +145,10 @@ namespace Tins {
|
||||
*/
|
||||
uint32_t trailer_size() const;
|
||||
|
||||
// Windows does not support sending L2 PDUs.
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender &sender, const NetworkInterface &iface);
|
||||
#endif // WIN32
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
|
||||
@@ -36,6 +36,10 @@
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include <map>
|
||||
#include "config.h"
|
||||
#ifdef HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
#include <pcap.h>
|
||||
#endif // HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
#include "network_interface.h"
|
||||
#include "macros.h"
|
||||
#include "cxxstd.h"
|
||||
@@ -378,6 +382,9 @@ namespace Tins {
|
||||
void send(PDU &pdu, const NetworkInterface &iface) {
|
||||
static_cast<T&>(pdu).send(*this, iface);
|
||||
}
|
||||
#ifdef HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
pcap_t* make_pcap_handle(const NetworkInterface& iface) const;
|
||||
#endif // HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
|
||||
PDU *recv_match_loop(const std::vector<int>& sockets, PDU &pdu, struct sockaddr* link_addr,
|
||||
uint32_t addrlen);
|
||||
@@ -397,7 +404,11 @@ namespace Tins {
|
||||
// In BSD we need to store the buffer size, retrieved using BIOCGBLEN
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
int buffer_size;
|
||||
#endif
|
||||
#endif // BSD
|
||||
#ifdef HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
typedef std::map<NetworkInterface, pcap_t*> PcapHandleMap;
|
||||
PcapHandleMap pcap_handles;
|
||||
#endif // HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <net/ethernet.h>
|
||||
#endif
|
||||
#include "config.h"
|
||||
#include "ethernetII.h"
|
||||
#include "packet_sender.h"
|
||||
#include "rawpdu.h"
|
||||
@@ -111,12 +112,17 @@ uint32_t EthernetII::trailer_size() const {
|
||||
return padding;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
void EthernetII::send(PacketSender &sender, const NetworkInterface &iface) {
|
||||
if(!iface)
|
||||
throw invalid_interface();
|
||||
|
||||
#if !defined(BSD) && !defined(__FreeBSD_kernel__)
|
||||
#if defined(HAVE_PACKET_SENDER_PCAP_SENDPACKET) || defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
// Sending using pcap_sendpacket/BSD bpf packet mode is the same here
|
||||
sender.send_l2(*this, 0, 0, iface);
|
||||
#elif defined(WIN32)
|
||||
// On Windows we can only send l2 PDUs using pcap_sendpacket
|
||||
throw std::runtime_error("LIBTINS_USE_PCAP_SENDPACKET is not enabled");
|
||||
#else
|
||||
// Default GNU/Linux behaviour
|
||||
struct sockaddr_ll addr;
|
||||
|
||||
memset(&addr, 0, sizeof(struct sockaddr_ll));
|
||||
@@ -128,11 +134,8 @@ void EthernetII::send(PacketSender &sender, const NetworkInterface &iface) {
|
||||
memcpy(&(addr.sll_addr), _eth.dst_mac, address_type::address_size);
|
||||
|
||||
sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr));
|
||||
#else
|
||||
sender.send_l2(*this, 0, 0, iface);
|
||||
#endif
|
||||
}
|
||||
#endif // WIN32
|
||||
|
||||
bool EthernetII::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
if(total_sz < sizeof(ethhdr))
|
||||
|
||||
@@ -66,6 +66,8 @@
|
||||
#include "ieee802_3.h"
|
||||
#include "internals.h"
|
||||
|
||||
using std::string;
|
||||
using std::runtime_error;
|
||||
|
||||
namespace Tins {
|
||||
const int PacketSender::INVALID_RAW_SOCKET = -1;
|
||||
@@ -107,12 +109,19 @@ PacketSender::~PacketSender() {
|
||||
#endif
|
||||
}
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
for(BSDEtherSockets::iterator it = _ether_socket.begin(); it != _ether_socket.end(); ++it)
|
||||
::close(it->second);
|
||||
for(BSDEtherSockets::iterator it = _ether_socket.begin(); it != _ether_socket.end(); ++it)
|
||||
::close(it->second);
|
||||
#elif !defined(WIN32)
|
||||
if(_ether_socket != INVALID_RAW_SOCKET)
|
||||
::close(_ether_socket);
|
||||
if(_ether_socket != INVALID_RAW_SOCKET)
|
||||
::close(_ether_socket);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
for (PcapHandleMap::iterator it = pcap_handles.begin(); it != pcap_handles.end(); ++it) {
|
||||
pcap_close(it->second);
|
||||
}
|
||||
pcap_handles.clear();
|
||||
#endif // HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
}
|
||||
|
||||
void PacketSender::default_interface(const NetworkInterface &iface) {
|
||||
@@ -142,8 +151,37 @@ int PacketSender::get_ether_socket(const NetworkInterface& iface) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
|
||||
pcap_t* PacketSender::make_pcap_handle(const NetworkInterface& iface) const {
|
||||
#ifdef WIN32
|
||||
#define TINS_PREFIX_INTERFACE(x) ("\\Device\\NPF_" + x)
|
||||
#else // WIN32
|
||||
#define TINS_PREFIX_INTERFACE(x) (x)
|
||||
#endif // WIN32
|
||||
|
||||
char error[PCAP_ERRBUF_SIZE];
|
||||
pcap_t* handle = pcap_create(TINS_PREFIX_INTERFACE(iface.name()).c_str(), error);
|
||||
if (!handle) {
|
||||
throw runtime_error("Error opening pcap handle: " + string(error));
|
||||
}
|
||||
if (pcap_set_promisc(handle, 1) < 0) {
|
||||
throw runtime_error("Failed to set pcap handle promisc mode: " + string(pcap_geterr(handle)));
|
||||
}
|
||||
if (pcap_activate(handle) < 0) {
|
||||
throw runtime_error("Failed to activate pcap handle: " + string(pcap_geterr(handle)));
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
#endif // HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
|
||||
void PacketSender::open_l2_socket(const NetworkInterface& iface) {
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
#ifdef HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
if (pcap_handles.count(iface) == 0) {
|
||||
pcap_handles.insert(std::make_pair(iface, make_pcap_handle(iface)));
|
||||
}
|
||||
#elif defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
int sock = -1;
|
||||
// At some point, there should be an available device
|
||||
for (int i = 0; sock == -1;i++) {
|
||||
@@ -258,7 +296,7 @@ PDU *PacketSender::send_recv(PDU &pdu, const NetworkInterface &iface) {
|
||||
try {
|
||||
pdu.send(*this, iface);
|
||||
}
|
||||
catch(std::runtime_error&) {
|
||||
catch(runtime_error&) {
|
||||
return 0;
|
||||
}
|
||||
return pdu.recv_response(*this, iface);
|
||||
@@ -268,16 +306,25 @@ PDU *PacketSender::send_recv(PDU &pdu, const NetworkInterface &iface) {
|
||||
void PacketSender::send_l2(PDU &pdu, struct sockaddr* link_addr,
|
||||
uint32_t len_addr, const NetworkInterface &iface)
|
||||
{
|
||||
int sock = get_ether_socket(iface);
|
||||
PDU::serialization_type buffer = pdu.serialize();
|
||||
if(!buffer.empty()) {
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
if(::write(sock, &buffer[0], buffer.size()) == -1)
|
||||
#else
|
||||
if(::sendto(sock, &buffer[0], buffer.size(), 0, link_addr, len_addr) == -1)
|
||||
#endif
|
||||
throw socket_write_error(make_error_string());
|
||||
}
|
||||
|
||||
#ifdef HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
open_l2_socket(iface);
|
||||
pcap_t* handle = pcap_handles[iface];
|
||||
if (pcap_sendpacket(handle, (u_char*)&buffer[0], buffer.size()) != 0) {
|
||||
throw runtime_error("Failed to send packet: " + string(pcap_geterr(handle)));
|
||||
}
|
||||
#else // HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
int sock = get_ether_socket(iface);
|
||||
if(!buffer.empty()) {
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
if(::write(sock, &buffer[0], buffer.size()) == -1)
|
||||
#else
|
||||
if(::sendto(sock, &buffer[0], buffer.size(), 0, link_addr, len_addr) == -1)
|
||||
#endif
|
||||
throw socket_write_error(make_error_string());
|
||||
}
|
||||
#endif // HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
}
|
||||
|
||||
PDU *PacketSender::recv_l2(PDU &pdu, struct sockaddr *link_addr,
|
||||
@@ -294,7 +341,7 @@ PDU *PacketSender::recv_l3(PDU &pdu, struct sockaddr* link_addr, uint32_t len_ad
|
||||
std::vector<int> sockets(1, _sockets[type]);
|
||||
if(type == IP_TCP_SOCKET || type == IP_UDP_SOCKET) {
|
||||
#ifdef BSD
|
||||
throw std::runtime_error("Receiving L3 packets not supported on this platform");
|
||||
throw runtime_error("Receiving L3 packets not supported on this platform");
|
||||
#endif
|
||||
open_l3_socket(ICMP_SOCKET);
|
||||
sockets.push_back(_sockets[ICMP_SOCKET]);
|
||||
|
||||
Reference in New Issue
Block a user